From c34b17963d21665e2944225ffbf507d338749273 Mon Sep 17 00:00:00 2001 From: Angus Lees Date: Thu, 16 Apr 2015 20:08:53 +1000 Subject: [PATCH] Imported Upstream version 1.0.0~beta --- AUTHORS.txt | 2 +- CONTRIBUTING.md | 2 +- Makefile.in | 7 +- README.md | 79 +- RELEASES.md | 101 +- configure | 57 +- man/rustc.1 | 289 +- man/rustdoc.1 | 102 +- mk/cfg/x86_64-unknown-bitrig.mk | 26 + mk/cfg/x86_64-unknown-linux-gnu.mk | 1 - mk/crates.mk | 46 +- mk/debuggers.mk | 18 +- mk/dist.mk | 1 + mk/docs.mk | 7 +- mk/llvm.mk | 9 +- mk/main.mk | 9 +- mk/platform.mk | 26 +- mk/prepare.mk | 2 - mk/target.mk | 10 +- mk/tests.mk | 46 +- mk/util.mk | 1 - src/compiletest/common.rs | 17 +- src/compiletest/compiletest.rs | 62 +- src/compiletest/errors.rs | 19 +- src/compiletest/header.rs | 73 +- src/compiletest/procsrv.rs | 36 +- src/compiletest/runtest.rs | 395 +-- src/compiletest/util.rs | 61 +- src/doc/complement-design-faq.md | 7 + src/doc/grammar.md | 100 +- src/doc/guide-tasks.md | 2 +- src/doc/index.md | 2 +- src/doc/intro.md | 87 +- src/doc/not_found.md | 1 - src/doc/reference.md | 388 +-- src/doc/rust.css | 1 + src/doc/style/errors/ergonomics.md | 12 +- src/doc/trpl/README.md | 14 +- src/doc/trpl/SUMMARY.md | 19 +- src/doc/trpl/advanced-macros.md | 56 +- src/doc/trpl/arrays-vectors-and-slices.md | 13 +- src/doc/trpl/associated-types.md | 202 ++ src/doc/trpl/basic.md | 3 +- src/doc/trpl/benchmark-tests.md | 152 + src/doc/trpl/box-syntax-and-patterns.md | 100 + src/doc/trpl/closures.md | 538 +++- src/doc/trpl/comments.md | 2 +- src/doc/trpl/compound-data-types.md | 74 +- src/doc/trpl/concurrency.md | 43 +- src/doc/trpl/crates-and-modules.md | 114 +- src/doc/trpl/documentation.md | 679 ++-- src/doc/trpl/error-handling.md | 85 +- src/doc/trpl/ffi.md | 40 +- src/doc/trpl/functions.md | 2 +- src/doc/trpl/glossary.md | 23 + src/doc/trpl/guessing-game.md | 893 ------ src/doc/trpl/hello-cargo.md | 74 +- src/doc/trpl/if.md | 14 + src/doc/trpl/inline-assembly.md | 141 + src/doc/trpl/installing-rust.md | 13 +- src/doc/trpl/intrinsics.md | 25 + src/doc/trpl/iterators.md | 37 +- src/doc/trpl/lang-items.md | 79 + src/doc/trpl/link-args.md | 25 + src/doc/trpl/looping.md | 2 +- src/doc/trpl/macros.md | 93 +- src/doc/trpl/method-syntax.md | 70 +- src/doc/trpl/more-strings.md | 62 +- src/doc/trpl/no-stdlib.md | 168 + src/doc/trpl/ownership.md | 17 +- src/doc/trpl/patterns.md | 1 + src/doc/trpl/plugins.md | 52 +- src/doc/trpl/pointers.md | 143 +- src/doc/trpl/standard-input.md | 159 - src/doc/trpl/static-and-dynamic-dispatch.md | 144 +- src/doc/trpl/strings.md | 6 +- src/doc/trpl/testing.md | 168 +- src/doc/trpl/tracing-macros.md | 91 + src/doc/trpl/traits.md | 72 + src/doc/trpl/unsafe.md | 534 ---- src/doc/trpl/unstable.md | 1 + src/driver/driver.rs | 4 +- src/etc/check-sanitycheck.py | 54 + src/etc/featureck.py | 1 - src/etc/gdb_rust_pretty_printing.py | 89 +- src/etc/htmldocck.py | 15 + src/etc/libc.c | 10 + src/etc/lldb_rust_formatters.py | 98 +- src/etc/local_stage0.sh | 2 +- src/etc/mingw-fix-include/README.txt | 2 +- src/etc/mklldeps.py | 11 +- src/etc/rustup.sh | 31 +- src/etc/snapshot.py | 4 +- src/etc/snapshot.pyc | Bin 10047 -> 10095 bytes src/etc/third-party/COPYING.RUNTIME | 1 - src/etc/tidy.py | 80 +- src/etc/unicode.py | 82 +- src/jemalloc/VERSION | 2 +- src/jemalloc/configure | 6 + src/jemalloc/configure.ac | 5 + src/liballoc/arc.rs | 226 +- src/liballoc/boxed.rs | 147 +- src/liballoc/boxed_test.rs | 13 +- src/liballoc/heap.rs | 14 +- src/liballoc/lib.rs | 16 +- src/liballoc/rc.rs | 135 +- src/libarena/lib.rs | 36 +- src/libbacktrace/Makefile.am | 4 +- src/libbacktrace/Makefile.in | 18 +- src/libbacktrace/alloc.c | 6 +- src/libbacktrace/atomic.c | 6 +- src/libbacktrace/backtrace-supported.h.in | 6 +- src/libbacktrace/backtrace.c | 6 +- src/libbacktrace/backtrace.h | 6 +- src/libbacktrace/btest.c | 8 +- src/libbacktrace/configure | 5 +- src/libbacktrace/configure.ac | 6 +- src/libbacktrace/dwarf.c | 12 +- src/libbacktrace/elf.c | 6 +- src/libbacktrace/fileline.c | 6 +- src/libbacktrace/hashtab.h | 4 +- src/libbacktrace/internal.h | 6 +- src/libbacktrace/ltmain.sh | 3 +- src/libbacktrace/mmap.c | 6 +- src/libbacktrace/mmapio.c | 6 +- src/libbacktrace/nounwind.c | 6 +- src/libbacktrace/posix.c | 6 +- src/libbacktrace/print.c | 6 +- src/libbacktrace/read.c | 6 +- src/libbacktrace/simple.c | 6 +- src/libbacktrace/state.c | 6 +- src/libbacktrace/unknown.c | 6 +- src/libcollections/binary_heap.rs | 234 +- src/libcollections/bit.rs | 1340 +------- src/libcollections/borrow.rs | 103 +- src/libcollections/borrow_stage0.rs | 313 -- src/libcollections/btree/map.rs | 434 +-- src/libcollections/btree/node.rs | 96 +- src/libcollections/btree/set.rs | 247 +- src/libcollections/enum_set.rs | 258 +- src/libcollections/fmt.rs | 108 +- src/libcollections/lib.rs | 91 +- src/libcollections/linked_list.rs | 446 +-- src/libcollections/macros.rs | 23 +- src/libcollections/slice.rs | 2495 +++------------ src/libcollections/str.rs | 2807 ++++------------- src/libcollections/string.rs | 666 +--- src/libcollections/vec.rs | 1387 ++------ src/libcollections/vec_deque.rs | 1087 +------ src/libcollections/vec_map.rs | 637 +--- .../bench.rs | 12 +- src/libcollectionstest/binary_heap.rs | 219 ++ .../bit/mod.rs} | 7 +- src/libcollectionstest/bit/set.rs | 440 +++ src/libcollectionstest/bit/vec.rs | 729 +++++ src/libcollectionstest/btree/map.rs | 299 ++ .../btree/mod.rs} | 3 +- src/libcollectionstest/btree/set.rs | 186 ++ src/libcollectionstest/enum_set.rs | 244 ++ src/libcollectionstest/fmt.rs | 17 + src/libcollectionstest/lib.rs | 45 + src/libcollectionstest/linked_list.rs | 397 +++ src/libcollectionstest/slice.rs | 1572 +++++++++ src/libcollectionstest/str.rs | 1696 ++++++++++ src/libcollectionstest/string.rs | 453 +++ src/libcollectionstest/vec.rs | 994 ++++++ src/libcollectionstest/vec_deque.rs | 887 ++++++ src/libcollectionstest/vec_map.rs | 510 +++ src/libcore/any.rs | 62 +- src/libcore/array.rs | 103 +- src/libcore/atomic.rs | 157 +- src/libcore/cell.rs | 67 +- src/libcore/char.rs | 280 +- src/libcore/clone.rs | 8 + src/libcore/cmp.rs | 22 +- src/libcore/cmp_macros.rs | 47 + src/libcore/convert.rs | 135 + src/libcore/default.rs | 1 - src/libcore/error.rs | 112 - src/libcore/finally.rs | 110 - src/libcore/fmt/builders.rs | 333 ++ src/libcore/fmt/float.rs | 44 +- src/libcore/fmt/mod.rs | 270 +- src/libcore/fmt/num.rs | 31 +- src/libcore/fmt/rt/v1.rs | 12 +- src/libcore/hash/mod.rs | 225 +- src/libcore/hash/sip.rs | 43 +- src/libcore/intrinsics.rs | 102 +- src/libcore/iter.rs | 1029 +++--- src/libcore/lib.rs | 24 +- src/libcore/macros.rs | 62 +- src/libcore/marker.rs | 198 +- src/libcore/mem.rs | 82 +- src/libcore/num/f32.rs | 79 +- src/libcore/num/f64.rs | 86 +- src/libcore/num/float_macros.rs | 1 - src/libcore/num/int.rs | 21 - src/libcore/num/int_macros.rs | 4 +- src/libcore/num/mod.rs | 1559 ++++++++- src/libcore/num/uint_macros.rs | 6 +- src/libcore/num/wrapping.rs | 488 +++ src/libcore/ops.rs | 211 +- src/libcore/option.rs | 115 +- src/libcore/panicking.rs | 22 +- src/libcore/prelude.rs | 14 +- src/libcore/ptr.rs | 276 +- src/libcore/raw.rs | 18 +- src/libcore/result.rs | 162 +- src/libcore/simd.rs | 22 +- src/libcore/slice.rs | 253 +- src/libcore/str/mod.rs | 833 +++-- src/libcore/str/pattern.rs | 571 ++++ src/libcore/tuple.rs | 174 +- src/libcoretest/any.rs | 26 +- src/libcoretest/cell.rs | 23 +- src/libcoretest/char.rs | 66 +- src/libcoretest/cmp.rs | 2 +- src/libcoretest/finally.rs | 62 - src/libcoretest/fmt/builders.rs | 498 +++ src/libcoretest/fmt/mod.rs | 1 + src/libcoretest/fmt/num.rs | 46 +- src/libcoretest/hash/mod.rs | 7 +- src/libcoretest/hash/sip.rs | 8 +- src/libcoretest/intrinsics.rs | 1 - src/libcoretest/iter.rs | 154 +- src/libcoretest/lib.rs | 16 +- src/libcoretest/mem.rs | 30 +- src/libcoretest/nonzero.rs | 4 +- src/libcoretest/num/int_macros.rs | 25 +- src/libcoretest/num/mod.rs | 23 +- src/libcoretest/num/uint_macros.rs | 12 +- src/libcoretest/ops.rs | 2 +- src/libcoretest/option.rs | 59 +- src/libcoretest/ptr.rs | 57 +- src/libcoretest/result.rs | 64 +- src/libcoretest/slice.rs | 6 +- src/libcoretest/str.rs | 304 +- src/libflate/lib.rs | 79 +- src/libfmt_macros/lib.rs | 43 +- src/libgetopts/lib.rs | 49 +- src/libgraphviz/lib.rs | 114 +- src/liblibc/lib.rs | 1517 ++++++--- src/liblog/lib.rs | 81 +- src/liblog/macros.rs | 17 +- src/librand/chacha.rs | 27 +- src/librand/distributions/exponential.rs | 13 +- src/librand/distributions/gamma.rs | 22 +- src/librand/distributions/mod.rs | 39 +- src/librand/distributions/normal.rs | 20 +- src/librand/distributions/range.rs | 30 +- src/librand/isaac.rs | 192 +- src/librand/lib.rs | 91 +- src/librand/rand_impls.rs | 27 +- src/librand/reseeding.rs | 25 +- src/librbml/io.rs | 241 -- src/librbml/lib.rs | 987 +++--- src/librustc/README.md | 128 + src/librustc/README.txt | 124 - src/librustc/diagnostics.rs | 6 +- src/librustc/lib.rs | 18 +- src/librustc/lint/builtin.rs | 2048 +----------- src/librustc/lint/context.rs | 141 +- src/librustc/lint/mod.rs | 17 +- src/librustc/metadata/common.rs | 292 +- src/librustc/metadata/creader.rs | 187 +- src/librustc/metadata/csearch.rs | 40 +- src/librustc/metadata/cstore.rs | 29 +- src/librustc/metadata/decoder.rs | 189 +- src/librustc/metadata/encoder.rs | 678 ++-- src/librustc/metadata/filesearch.rs | 94 +- src/librustc/metadata/loader.rs | 109 +- src/librustc/metadata/macro_import.rs | 14 +- src/librustc/metadata/tydecode.rs | 88 +- src/librustc/metadata/tyencode.rs | 94 +- src/librustc/middle/astconv_util.rs | 99 +- src/librustc/middle/astencode.rs | 382 +-- src/librustc/middle/cfg/construct.rs | 285 +- src/librustc/middle/cfg/graphviz.rs | 11 +- src/librustc/middle/cfg/mod.rs | 24 +- src/librustc/middle/check_const.rs | 20 +- src/librustc/middle/check_loop.rs | 2 +- src/librustc/middle/check_match.rs | 102 +- src/librustc/middle/check_static_recursion.rs | 8 +- src/librustc/middle/const_eval.rs | 754 +++-- src/librustc/middle/dataflow.rs | 182 +- src/librustc/middle/dead.rs | 78 +- src/librustc/middle/def.rs | 110 +- src/librustc/middle/dependency_format.rs | 8 +- src/librustc/middle/effect.rs | 13 +- src/librustc/middle/expr_use_visitor.rs | 82 +- src/librustc/middle/fast_reject.rs | 9 +- src/librustc/middle/graph.rs | 24 +- src/librustc/middle/infer/bivariate.rs | 111 +- src/librustc/middle/infer/combine.rs | 728 +---- src/librustc/middle/infer/equate.rs | 113 +- src/librustc/middle/infer/error_reporting.rs | 165 +- src/librustc/middle/infer/freshen.rs | 32 +- src/librustc/middle/infer/glb.rs | 130 +- .../middle/infer/higher_ranked/mod.rs | 198 +- src/librustc/middle/infer/lattice.rs | 48 +- src/librustc/middle/infer/lub.rs | 128 +- src/librustc/middle/infer/mod.rs | 282 +- .../middle/infer/region_inference/README.md | 163 +- .../middle/infer/region_inference/graphviz.rs | 25 +- .../middle/infer/region_inference/mod.rs | 169 +- src/librustc/middle/infer/resolve.rs | 3 +- src/librustc/middle/infer/sub.rs | 137 +- src/librustc/middle/infer/type_variable.rs | 16 +- src/librustc/middle/infer/unify.rs | 248 +- src/librustc/middle/intrinsicck.rs | 4 +- src/librustc/middle/lang_items.rs | 39 +- src/librustc/middle/liveness.rs | 90 +- src/librustc/middle/mem_categorization.rs | 217 +- src/librustc/middle/pat_util.rs | 47 +- src/librustc/middle/privacy.rs | 11 +- src/librustc/middle/reachable.rs | 76 +- src/librustc/middle/region.rs | 236 +- src/librustc/middle/resolve_lifetime.rs | 37 +- src/librustc/middle/stability.rs | 195 +- src/librustc/middle/subst.rs | 42 +- src/librustc/middle/traits/coherence.rs | 229 +- src/librustc/middle/traits/error_reporting.rs | 56 +- src/librustc/middle/traits/fulfill.rs | 15 +- src/librustc/middle/traits/mod.rs | 187 +- src/librustc/middle/traits/object_safety.rs | 95 +- src/librustc/middle/traits/project.rs | 37 +- src/librustc/middle/traits/select.rs | 1064 +++++-- src/librustc/middle/traits/util.rs | 251 +- src/librustc/middle/ty.rs | 1381 ++++---- src/librustc/middle/ty_fold.rs | 41 +- src/librustc/middle/ty_match.rs | 95 + src/librustc/middle/ty_relate/mod.rs | 655 ++++ src/librustc/middle/ty_walk.rs | 125 +- src/librustc/plugin/load.rs | 10 +- src/librustc/plugin/mod.rs | 2 +- src/librustc/plugin/registry.rs | 13 +- src/librustc/session/config.rs | 154 +- src/librustc/session/mod.rs | 47 +- src/librustc/session/search_paths.rs | 11 +- src/librustc/util/common.rs | 127 +- src/librustc/util/lev_distance.rs | 4 +- src/librustc/util/nodemap.rs | 35 +- src/librustc/util/ppaux.rs | 79 +- src/librustc/util/snapshot_vec.rs | 14 +- src/librustc_back/abi.rs | 8 +- src/librustc_back/archive.rs | 88 +- src/librustc_back/arm.rs | 2 +- src/librustc_back/fs.rs | 27 +- src/librustc_back/lib.rs | 12 +- src/librustc_back/mips.rs | 2 +- src/librustc_back/mipsel.rs | 2 +- src/librustc_back/rpath.rs | 173 +- src/librustc_back/sha2.rs | 102 +- src/librustc_back/svh.rs | 29 +- src/librustc_back/target/apple_ios_base.rs | 19 +- .../target/bitrig_base.rs} | 23 +- src/librustc_back/target/dragonfly_base.rs | 1 - src/librustc_back/target/freebsd_base.rs | 1 - src/librustc_back/target/mod.rs | 38 +- src/librustc_back/target/openbsd_base.rs | 6 +- .../target/x86_64_unknown_bitrig.rs | 28 + src/librustc_back/tempdir.rs | 120 + src/librustc_back/x86.rs | 8 +- src/librustc_back/x86_64.rs | 12 +- src/librustc_bitflags/lib.rs | 18 +- src/librustc_borrowck/borrowck/README.md | 201 +- src/librustc_borrowck/borrowck/check_loans.rs | 57 +- src/librustc_borrowck/borrowck/fragments.rs | 32 +- .../borrowck/gather_loans/lifetime.rs | 2 - .../borrowck/gather_loans/mod.rs | 43 +- .../borrowck/gather_loans/move_error.rs | 12 +- src/librustc_borrowck/borrowck/mod.rs | 115 +- src/librustc_borrowck/borrowck/move_data.rs | 36 +- src/librustc_borrowck/graphviz.rs | 10 +- src/librustc_borrowck/lib.rs | 7 +- src/librustc_driver/driver.rs | 113 +- src/librustc_driver/lib.rs | 209 +- src/librustc_driver/pretty.rs | 109 +- src/librustc_driver/test.rs | 164 +- src/librustc_lint/builtin.rs | 2109 +++++++++++++ src/librustc_lint/lib.rs | 136 + src/librustc_llvm/archive_ro.rs | 25 +- src/librustc_llvm/diagnostic.rs | 9 +- src/librustc_llvm/lib.rs | 67 +- src/librustc_privacy/lib.rs | 330 +- src/librustc_resolve/build_reduced_graph.rs | 447 +-- src/librustc_resolve/check_unused.rs | 28 +- src/librustc_resolve/diagnostics.rs | 4 +- src/librustc_resolve/lib.rs | 2754 +++++----------- src/librustc_resolve/record_exports.rs | 13 +- src/librustc_resolve/resolve_imports.rs | 1018 ++++++ src/librustc_trans/README.txt | 2 +- src/librustc_trans/back/link.rs | 270 +- src/librustc_trans/back/lto.rs | 41 +- src/librustc_trans/back/write.rs | 85 +- src/librustc_trans/lib.rs | 14 +- src/librustc_trans/save/mod.rs | 398 ++- src/librustc_trans/save/recorder.rs | 12 +- src/librustc_trans/save/span_utils.rs | 26 +- src/librustc_trans/trans/_match.rs | 160 +- src/librustc_trans/trans/adt.rs | 159 +- src/librustc_trans/trans/asm.rs | 72 +- src/librustc_trans/trans/base.rs | 561 ++-- src/librustc_trans/trans/basic_block.rs | 4 +- src/librustc_trans/trans/build.rs | 16 +- src/librustc_trans/trans/builder.rs | 18 +- src/librustc_trans/trans/cabi.rs | 4 +- src/librustc_trans/trans/cabi_aarch64.rs | 14 +- src/librustc_trans/trans/cabi_arm.rs | 18 +- src/librustc_trans/trans/cabi_mips.rs | 18 +- src/librustc_trans/trans/cabi_powerpc.rs | 18 +- src/librustc_trans/trans/cabi_x86_64.rs | 22 +- src/librustc_trans/trans/callee.rs | 106 +- src/librustc_trans/trans/cleanup.rs | 58 +- src/librustc_trans/trans/closure.rs | 207 +- src/librustc_trans/trans/common.rs | 223 +- src/librustc_trans/trans/consts.rs | 259 +- src/librustc_trans/trans/context.rs | 96 +- src/librustc_trans/trans/controlflow.rs | 75 +- src/librustc_trans/trans/datum.rs | 56 +- src/librustc_trans/trans/debuginfo.rs | 228 +- src/librustc_trans/trans/expr.rs | 655 ++-- src/librustc_trans/trans/foreign.rs | 28 +- src/librustc_trans/trans/glue.rs | 351 +-- src/librustc_trans/trans/inline.rs | 86 +- src/librustc_trans/trans/intrinsic.rs | 80 +- src/librustc_trans/trans/llrepr.rs | 2 - src/librustc_trans/trans/machine.rs | 16 +- src/librustc_trans/trans/meth.rs | 316 +- src/librustc_trans/trans/mod.rs | 2 +- src/librustc_trans/trans/monomorphize.rs | 41 +- src/librustc_trans/trans/tvec.rs | 177 +- src/librustc_trans/trans/type_.rs | 59 +- src/librustc_trans/trans/type_of.rs | 167 +- src/librustc_trans/trans/value.rs | 6 +- src/librustc_typeck/astconv.rs | 1157 ++++--- src/librustc_typeck/check/_match.rs | 62 +- src/librustc_typeck/check/callee.rs | 44 +- src/librustc_typeck/check/closure.rs | 78 +- src/librustc_typeck/check/coercion.rs | 331 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/demand.rs | 8 +- src/librustc_typeck/check/dropck.rs | 392 ++- src/librustc_typeck/check/implicator.rs | 53 +- src/librustc_typeck/check/method/confirm.rs | 54 +- src/librustc_typeck/check/method/mod.rs | 47 +- src/librustc_typeck/check/method/probe.rs | 238 +- src/librustc_typeck/check/method/suggest.rs | 84 +- src/librustc_typeck/check/mod.rs | 1256 +++----- src/librustc_typeck/check/op.rs | 481 +++ src/librustc_typeck/check/regionck.rs | 213 +- src/librustc_typeck/check/upvar.rs | 8 +- src/librustc_typeck/check/vtable.rs | 98 +- src/librustc_typeck/check/wf.rs | 115 +- src/librustc_typeck/check/writeback.rs | 34 +- src/librustc_typeck/coherence/impls.rs | 47 - src/librustc_typeck/coherence/mod.rs | 91 +- src/librustc_typeck/coherence/orphan.rs | 293 +- src/librustc_typeck/coherence/overlap.rs | 66 +- src/librustc_typeck/coherence/unsafety.rs | 93 +- src/librustc_typeck/collect.rs | 1792 ++++++----- src/librustc_typeck/diagnostics.rs | 15 +- src/librustc_typeck/lib.rs | 31 +- src/librustc_typeck/rscope.rs | 34 +- src/librustc_typeck/variance.rs | 134 +- src/librustdoc/clean/inline.rs | 68 +- src/librustdoc/clean/mod.rs | 332 +- src/librustdoc/core.rs | 2 + src/librustdoc/doctree.rs | 14 +- src/librustdoc/externalfiles.rs | 19 +- src/librustdoc/flock.rs | 40 +- src/librustdoc/fold.rs | 28 +- src/librustdoc/html/format.rs | 46 +- src/librustdoc/html/highlight.rs | 7 +- src/librustdoc/html/item_type.rs | 2 +- src/librustdoc/html/layout.rs | 9 +- src/librustdoc/html/markdown.rs | 36 +- src/librustdoc/html/render.rs | 457 ++- .../html/static/Heuristica-LICENSE.txt | 4 +- .../html/static/SourceCodePro-LICENSE.txt | 2 +- .../html/static/SourceSerifPro-LICENSE.txt | 2 +- src/librustdoc/html/static/main.css | 27 +- src/librustdoc/html/static/main.js | 140 +- src/librustdoc/html/static/playpen.js | 3 +- src/librustdoc/html/toc.rs | 2 +- src/librustdoc/lib.rs | 77 +- src/librustdoc/markdown.rs | 23 +- src/librustdoc/passes.rs | 2 +- src/librustdoc/plugins.rs | 7 +- src/librustdoc/stability_summary.rs | 38 +- src/librustdoc/test.rs | 191 +- src/librustdoc/visit_ast.rs | 16 +- src/libserialize/collection_impls.rs | 78 - src/libserialize/hex.rs | 28 +- src/libserialize/json.rs | 267 +- src/libserialize/lib.rs | 7 +- src/libserialize/serialize.rs | 107 +- src/libstd/array.rs | 13 + src/libstd/ascii.rs | 119 +- src/libstd/bool.rs | 1 - src/libstd/collections/hash/bench.rs | 2 +- src/libstd/collections/hash/map.rs | 181 +- src/libstd/collections/hash/map_stage0.rs | 2330 -------------- src/libstd/collections/hash/mod.rs | 8 - src/libstd/collections/hash/set.rs | 117 +- src/libstd/collections/hash/set_stage0.rs | 1252 -------- src/libstd/collections/hash/state.rs | 1 + src/libstd/collections/hash/table.rs | 102 +- src/libstd/collections/mod.rs | 33 +- src/libstd/dynamic_lib.rs | 65 +- src/libstd/env.rs | 400 ++- src/libstd/error.rs | 152 + src/libstd/ffi/c_str.rs | 168 +- src/libstd/ffi/mod.rs | 16 +- src/libstd/ffi/os_str.rs | 217 +- src/libstd/fs.rs | 379 ++- src/libstd/io/buffered.rs | 263 +- src/libstd/io/cursor.rs | 202 +- src/libstd/io/error.rs | 164 +- src/libstd/io/impls.rs | 192 +- src/libstd/io/lazy.rs | 67 + src/libstd/io/mod.rs | 380 ++- src/libstd/io/prelude.rs | 9 +- src/libstd/io/stdio.rs | 432 +++ src/libstd/io/util.rs | 41 +- src/libstd/lib.rs | 89 +- src/libstd/macros.rs | 83 +- src/libstd/net/addr.rs | 446 ++- src/libstd/net/ip.rs | 104 +- src/libstd/net/mod.rs | 43 +- src/libstd/net/parser.rs | 55 +- src/libstd/net/tcp.rs | 88 +- src/libstd/net/test.rs | 19 +- src/libstd/net/udp.rs | 36 +- src/libstd/num/f32.rs | 2040 +++++++++--- src/libstd/num/f64.rs | 1991 +++++++++--- src/libstd/num/float_macros.rs | 1 - src/libstd/num/int.rs | 22 - src/libstd/num/mod.rs | 339 +- src/libstd/num/strconv.rs | 94 +- src/libstd/num/uint.rs | 22 - src/libstd/num/uint_macros.rs | 62 - src/libstd/old_io/buffered.rs | 119 +- src/libstd/old_io/comm_adapters.rs | 36 +- src/libstd/old_io/extensions.rs | 68 +- src/libstd/old_io/fs.rs | 187 +- src/libstd/old_io/mem.rs | 101 +- src/libstd/old_io/mod.rs | 210 +- src/libstd/old_io/net/addrinfo.rs | 22 +- src/libstd/old_io/net/ip.rs | 50 +- src/libstd/old_io/net/mod.rs | 4 + src/libstd/old_io/net/pipe.rs | 28 +- src/libstd/old_io/net/tcp.rs | 66 +- src/libstd/old_io/net/udp.rs | 9 +- src/libstd/old_io/pipe.rs | 16 +- src/libstd/old_io/process.rs | 127 +- src/libstd/old_io/result.rs | 13 +- src/libstd/old_io/stdio.rs | 93 +- src/libstd/old_io/tempfile.rs | 17 +- src/libstd/old_io/test.rs | 20 +- src/libstd/old_io/timer.rs | 29 +- src/libstd/old_io/util.rs | 115 +- src/libstd/old_path/mod.rs | 146 +- src/libstd/old_path/posix.rs | 233 +- src/libstd/old_path/windows.rs | 134 +- src/libstd/os.rs | 1739 +--------- src/libstd/panicking.rs | 17 +- src/libstd/path.rs | 1103 +++++-- src/libstd/prelude/v1.rs | 23 +- src/libstd/process.rs | 192 +- src/libstd/rand/mod.rs | 80 +- src/libstd/rand/os.rs | 68 +- src/libstd/rand/reader.rs | 32 +- src/libstd/rt/args.rs | 23 +- src/libstd/rt/at_exit_imp.rs | 63 +- src/libstd/rt/libunwind.rs | 20 +- src/libstd/rt/mod.rs | 72 +- src/libstd/rt/unwind.rs | 49 +- src/libstd/rt/util.rs | 95 +- src/libstd/rtdeps.rs | 4 +- src/libstd/sync/barrier.rs | 12 +- src/libstd/sync/condvar.rs | 67 +- src/libstd/sync/future.rs | 10 +- src/libstd/sync/mod.rs | 2 - src/libstd/sync/mpsc/blocking.rs | 8 +- src/libstd/sync/mpsc/mod.rs | 303 +- src/libstd/sync/mpsc/mpsc_queue.rs | 18 +- src/libstd/sync/mpsc/oneshot.rs | 34 +- src/libstd/sync/mpsc/select.rs | 72 +- src/libstd/sync/mpsc/shared.rs | 14 +- src/libstd/sync/mpsc/spsc_queue.rs | 26 +- src/libstd/sync/mpsc/stream.rs | 14 +- src/libstd/sync/mpsc/sync.rs | 30 +- src/libstd/sync/mutex.rs | 54 +- src/libstd/sync/once.rs | 11 +- src/libstd/sync/poison.rs | 26 +- src/libstd/sync/rwlock.rs | 32 +- src/libstd/sync/semaphore.rs | 7 +- src/libstd/sync/task_pool.rs | 214 -- src/libstd/sys/common/backtrace.rs | 49 +- src/libstd/sys/common/helper_thread.rs | 40 +- src/libstd/sys/common/mod.rs | 26 +- src/libstd/sys/common/net.rs | 92 +- src/libstd/sys/common/net2.rs | 74 +- src/libstd/sys/common/rwlock.rs | 8 +- src/libstd/sys/common/stack.rs | 90 +- src/libstd/sys/common/thread.rs | 16 +- src/libstd/sys/common/thread_info.rs | 18 +- src/libstd/sys/common/thread_local.rs | 31 +- src/libstd/sys/common/wtf8.rs | 121 +- src/libstd/sys/unix/backtrace.rs | 148 +- src/libstd/sys/unix/c.rs | 62 +- src/libstd/sys/unix/condvar.rs | 6 +- src/libstd/sys/unix/ext.rs | 425 ++- src/libstd/sys/unix/fd.rs | 1 - src/libstd/sys/unix/fs.rs | 48 +- src/libstd/sys/unix/fs2.rs | 61 +- src/libstd/sys/unix/helper_signal.rs | 10 +- src/libstd/sys/unix/mod.rs | 47 +- src/libstd/sys/unix/mutex.rs | 6 +- src/libstd/sys/unix/net.rs | 17 +- src/libstd/sys/unix/os.rs | 143 +- src/libstd/sys/unix/os_str.rs | 12 +- src/libstd/sys/unix/pipe.rs | 16 +- src/libstd/sys/unix/process.rs | 308 +- src/libstd/sys/unix/process2.rs | 29 +- src/libstd/sys/unix/rwlock.rs | 11 +- src/libstd/sys/unix/stack_overflow.rs | 27 +- src/libstd/sys/unix/stdio.rs | 62 + src/libstd/sys/unix/sync.rs | 25 +- src/libstd/sys/unix/tcp.rs | 14 +- src/libstd/sys/unix/thread.rs | 357 +-- src/libstd/sys/unix/thread_local.rs | 2 + src/libstd/sys/unix/time.rs | 13 +- src/libstd/sys/unix/timer.rs | 32 +- src/libstd/sys/unix/tty.rs | 26 +- src/libstd/sys/windows/backtrace.rs | 21 +- src/libstd/sys/windows/c.rs | 10 +- src/libstd/sys/windows/condvar.rs | 9 +- src/libstd/sys/windows/ext.rs | 378 ++- src/libstd/sys/windows/fs.rs | 31 +- src/libstd/sys/windows/fs2.rs | 56 +- src/libstd/sys/windows/handle.rs | 11 +- src/libstd/sys/windows/mod.rs | 70 +- src/libstd/sys/windows/mutex.rs | 17 +- src/libstd/sys/windows/net.rs | 32 +- src/libstd/sys/windows/os.rs | 75 +- src/libstd/sys/windows/os_str.rs | 9 +- src/libstd/sys/windows/pipe.rs | 24 +- src/libstd/sys/windows/process.rs | 230 +- src/libstd/sys/windows/process2.rs | 24 +- src/libstd/sys/windows/rwlock.rs | 5 + src/libstd/sys/windows/stack_overflow.rs | 6 +- src/libstd/sys/windows/stdio.rs | 164 + src/libstd/sys/windows/tcp.rs | 14 +- src/libstd/sys/windows/thread.rs | 65 +- src/libstd/sys/windows/thread_local.rs | 24 +- src/libstd/sys/windows/time.rs | 27 +- src/libstd/sys/windows/timer.rs | 17 +- src/libstd/sys/windows/tty.rs | 20 +- .../{thread_local/mod.rs => thread/local.rs} | 168 +- src/libstd/{thread.rs => thread/mod.rs} | 434 +-- src/libstd/{thread_local => thread}/scoped.rs | 54 +- src/libstd/thunk.rs | 45 +- src/libstd/time/duration.rs | 3 +- src/libstd/tuple.rs | 2 +- src/libsyntax/abi.rs | 14 +- src/libsyntax/ast.rs | 392 ++- src/libsyntax/ast_map/blocks.rs | 38 +- src/libsyntax/ast_map/mod.rs | 320 +- src/libsyntax/ast_util.rs | 204 +- src/libsyntax/attr.rs | 47 +- src/libsyntax/codemap.rs | 398 ++- src/libsyntax/config.rs | 23 +- src/libsyntax/diagnostic.rs | 84 +- src/libsyntax/diagnostics/macros.rs | 7 + src/libsyntax/diagnostics/plugin.rs | 11 +- src/libsyntax/ext/asm.rs | 7 +- src/libsyntax/ext/base.rs | 222 +- src/libsyntax/ext/build.rs | 62 +- src/libsyntax/ext/cfg.rs | 2 +- src/libsyntax/ext/concat.rs | 8 +- src/libsyntax/ext/concat_idents.rs | 6 +- src/libsyntax/ext/deriving/bounds.rs | 45 +- src/libsyntax/ext/deriving/clone.rs | 10 +- src/libsyntax/ext/deriving/cmp/eq.rs | 10 +- src/libsyntax/ext/deriving/cmp/ord.rs | 20 +- src/libsyntax/ext/deriving/cmp/totaleq.rs | 7 +- src/libsyntax/ext/deriving/cmp/totalord.rs | 8 +- src/libsyntax/ext/deriving/decodable.rs | 6 +- src/libsyntax/ext/deriving/default.rs | 4 +- src/libsyntax/ext/deriving/encodable.rs | 51 +- src/libsyntax/ext/deriving/generic/mod.rs | 189 +- src/libsyntax/ext/deriving/hash.rs | 4 +- src/libsyntax/ext/deriving/mod.rs | 214 +- src/libsyntax/ext/deriving/primitive.rs | 12 +- src/libsyntax/ext/deriving/rand.rs | 6 +- src/libsyntax/ext/deriving/show.rs | 106 +- src/libsyntax/ext/env.rs | 6 +- src/libsyntax/ext/expand.rs | 327 +- src/libsyntax/ext/format.rs | 28 +- src/libsyntax/ext/mtwt.rs | 36 +- src/libsyntax/ext/quote.rs | 211 +- src/libsyntax/ext/source_util.rs | 46 +- src/libsyntax/ext/tt/macro_parser.rs | 20 +- src/libsyntax/ext/tt/macro_rules.rs | 57 +- src/libsyntax/feature_gate.rs | 295 +- src/libsyntax/fold.rs | 231 +- src/libsyntax/lib.rs | 12 +- src/libsyntax/owned_slice.rs | 2 +- src/libsyntax/parse/attr.rs | 62 +- src/libsyntax/parse/lexer/comments.rs | 23 +- src/libsyntax/parse/lexer/mod.rs | 165 +- src/libsyntax/parse/mod.rs | 264 +- src/libsyntax/parse/obsolete.rs | 47 +- src/libsyntax/parse/parser.rs | 1462 +++------ src/libsyntax/parse/token.rs | 34 +- src/libsyntax/print/pp.rs | 56 +- src/libsyntax/print/pprust.rs | 612 ++-- src/libsyntax/ptr.rs | 11 +- src/libsyntax/std_inject.rs | 14 +- src/libsyntax/test.rs | 62 +- src/libsyntax/util/interner.rs | 77 +- src/libsyntax/util/parser_testing.rs | 8 +- src/libsyntax/util/small_vector.rs | 10 +- src/libsyntax/visit.rs | 155 +- src/libterm/lib.rs | 89 +- src/libterm/terminfo/mod.rs | 62 +- src/libterm/terminfo/parm.rs | 58 +- src/libterm/terminfo/parser/compiled.rs | 70 +- src/libterm/terminfo/searcher.rs | 38 +- src/libterm/win.rs | 32 +- src/libtest/lib.rs | 299 +- src/libtest/stats.rs | 45 +- src/libunicode/{u_char.rs => char.rs} | 440 ++- src/libunicode/lib.rs | 35 +- src/libunicode/tables.rs | 1112 ++++--- src/libunicode/u_str.rs | 37 +- src/llvm/autoconf/config.sub | 2 +- src/llvm/autoconf/configure.ac | 7 + src/llvm/configure | 7 + src/llvm/docs/ReleaseNotes.rst | 42 +- src/llvm/docs/index.rst | 5 - .../Kaleidoscope/Chapter4/CMakeLists.txt | 1 + .../include/llvm/CodeGen/MachineModuleInfo.h | 6 - src/llvm/include/llvm/CodeGen/SelectionDAG.h | 6 +- .../include/llvm/CodeGen/SelectionDAGNodes.h | 31 +- src/llvm/include/llvm/Config/config.h.cmake | 3 - .../include/llvm/Config/llvm-config.h.cmake | 7 +- src/llvm/include/llvm/Config/llvm-config.h.in | 3 + src/llvm/include/llvm/IR/Constants.h | 6 + .../include/llvm/Target/TargetLibraryInfo.h | 5 + src/llvm/lib/Analysis/IPA/InlineCost.cpp | 12 +- src/llvm/lib/Analysis/MemoryBuiltins.cpp | 5 +- src/llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 18 +- src/llvm/lib/Bitcode/Reader/BitcodeReader.h | 2 + .../lib/CodeGen/AsmPrinter/EHStreamer.cpp | 15 +- src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h | 17 +- .../lib/CodeGen/AsmPrinter/Win64Exception.cpp | 149 +- .../lib/CodeGen/AsmPrinter/Win64Exception.h | 4 - src/llvm/lib/CodeGen/MachineModuleInfo.cpp | 8 - src/llvm/lib/CodeGen/Passes.cpp | 2 +- .../lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 38 +- .../SelectionDAG/LegalizeIntegerTypes.cpp | 25 +- .../lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 + .../SelectionDAG/LegalizeVectorOps.cpp | 8 +- .../SelectionDAG/LegalizeVectorTypes.cpp | 62 +- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 13 +- .../SelectionDAG/SelectionDAGBuilder.cpp | 39 +- .../SelectionDAG/SelectionDAGBuilder.h | 2 - .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 64 +- src/llvm/lib/ExecutionEngine/CMakeLists.txt | 1 - src/llvm/lib/ExecutionEngine/LLVMBuild.txt | 2 +- .../RuntimeDyld/CMakeLists.txt | 1 + .../{ => RuntimeDyld}/RTDyldMemoryManager.cpp | 0 src/llvm/lib/IR/Constants.cpp | 23 +- src/llvm/lib/IR/DebugInfo.cpp | 3 + src/llvm/lib/IR/Type.cpp | 7 +- src/llvm/lib/MC/WinCOFFObjectWriter.cpp | 17 +- src/llvm/lib/Target/TargetLibraryInfo.cpp | 2 + src/llvm/lib/Target/X86/X86ISelLowering.cpp | 166 + .../InstCombineLoadStoreAlloca.cpp | 11 +- .../Instrumentation/InstrProfiling.cpp | 41 + src/llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 3 + .../Scalar/MergedLoadStoreMotion.cpp | 10 +- .../Transforms/Utils/LoopUnrollRuntime.cpp | 62 +- .../Transforms/Vectorize/LoopVectorize.cpp | 2 + .../Transforms/Vectorize/SLPVectorizer.cpp | 20 +- src/llvm/tools/gold/gold-plugin.cpp | 19 +- src/llvm/tools/lli/CMakeLists.txt | 1 + .../unittests/ExecutionEngine/CMakeLists.txt | 1 + .../ExecutionEngine/MCJIT/CMakeLists.txt | 1 + .../utils/llvm-build/llvmbuild/__init__.pyc | Bin 261 -> 261 bytes .../llvm-build/llvmbuild/componentinfo.pyc | Bin 20261 -> 20261 bytes .../utils/llvm-build/llvmbuild/configutil.pyc | Bin 2075 -> 2075 bytes src/llvm/utils/llvm-build/llvmbuild/main.pyc | Bin 31108 -> 31108 bytes src/llvm/utils/llvm-build/llvmbuild/util.pyc | Bin 1644 -> 1644 bytes src/rt/arch/x86_64/morestack.S | 4 +- src/rt/msvc/typeof.h | 1 - src/rt/rust_builtin.c | 282 +- src/rt/valgrind/memcheck.h | 2 - src/rust-installer/.gitmodules | 2 +- src/rust-installer/combine-installers.sh | 0 src/rust-installer/gen-install-script.sh | 22 +- src/rust-installer/gen-installer.sh | 8 +- src/rust-installer/install-template.sh | 17 +- src/rust-installer/test.sh | 42 +- src/rustbook/book.rs | 42 +- src/rustbook/build.rs | 81 +- src/rustbook/error.rs | 69 +- src/rustbook/help.rs | 2 +- src/rustbook/main.rs | 32 +- src/rustbook/serve.rs | 2 +- src/rustbook/subcommand.rs | 10 +- src/rustbook/term.rs | 9 +- src/rustbook/test.rs | 30 +- src/rustllvm/PassWrapper.cpp | 8 +- src/rustllvm/RustWrapper.cpp | 120 +- src/rustllvm/llvm-auto-clean-trigger | 2 +- src/snapshots.txt | 59 + src/test/auxiliary/ambig_impl_2_lib.rs | 4 +- .../anon-extern-mod-cross-crate-1.rs | 1 + .../auxiliary/anon_trait_static_method_lib.rs | 2 +- src/test/auxiliary/associated-types-cc-lib.rs | 6 +- src/test/auxiliary/cci_borrow_lib.rs | 2 +- src/test/auxiliary/cci_class.rs | 6 +- src/test/auxiliary/cci_class_2.rs | 6 +- src/test/auxiliary/cci_class_3.rs | 10 +- src/test/auxiliary/cci_class_4.rs | 10 +- src/test/auxiliary/cci_class_5.rs | 6 +- src/test/auxiliary/cci_class_6.rs | 8 +- src/test/auxiliary/cci_class_cast.rs | 12 +- src/test/auxiliary/cci_const.rs | 4 +- src/test/auxiliary/cci_const_block.rs | 4 +- src/test/auxiliary/cci_impl_lib.rs | 8 +- src/test/auxiliary/cci_intrinsic.rs | 2 +- src/test/auxiliary/cci_iter_lib.rs | 4 +- src/test/auxiliary/cci_nested_lib.rs | 8 +- src/test/auxiliary/cci_no_inline_lib.rs | 6 +- src/test/auxiliary/cfg_inner_static.rs | 2 +- src/test/auxiliary/changing-crates-a2.rs | 1 - src/test/auxiliary/changing-crates-b.rs | 2 +- .../check_static_recursion_foreign_helper.rs | 2 + .../coherence_copy_like_lib.rs} | 20 +- .../{coherence-lib.rs => coherence_lib.rs} | 0 ...-orphan-lib.rs => coherence_orphan_lib.rs} | 1 - .../auxiliary/crate_with_invalid_spans.rs | 30 + .../crate_with_invalid_spans_macros.rs | 17 + src/test/auxiliary/crateresolve1-1.rs | 2 +- src/test/auxiliary/crateresolve1-2.rs | 2 +- src/test/auxiliary/crateresolve1-3.rs | 2 +- src/test/auxiliary/crateresolve3-1.rs | 2 +- src/test/auxiliary/crateresolve3-2.rs | 2 +- src/test/auxiliary/crateresolve4a-1.rs | 2 +- src/test/auxiliary/crateresolve4a-2.rs | 2 +- src/test/auxiliary/crateresolve4b-1.rs | 2 +- src/test/auxiliary/crateresolve4b-2.rs | 2 +- src/test/auxiliary/crateresolve5-1.rs | 4 +- src/test/auxiliary/crateresolve5-2.rs | 4 +- src/test/auxiliary/crateresolve7x.rs | 4 +- src/test/auxiliary/crateresolve8-1.rs | 2 +- src/test/auxiliary/crateresolve_calories-1.rs | 2 +- src/test/auxiliary/crateresolve_calories-2.rs | 2 +- .../auxiliary/cross_crate_spans.rs} | 24 +- src/test/auxiliary/custom_derive_plugin.rs | 74 + src/test/auxiliary/default_type_params_xc.rs | 1 - .../auxiliary/extern-crosscrate-source.rs | 1 + .../auxiliary/extern_calling_convention.rs | 4 +- src/test/auxiliary/foreign_lib.rs | 1 + src/test/auxiliary/go_trait.rs | 16 +- src/test/auxiliary/impl_privacy_xc_1.rs | 2 +- src/test/auxiliary/impl_privacy_xc_2.rs | 2 +- src/test/auxiliary/inherit_struct_lib.rs | 4 +- src/test/auxiliary/inherited_stability.rs | 2 +- src/test/auxiliary/inner_static.rs | 26 +- src/test/auxiliary/internal_unstable.rs | 60 + src/test/auxiliary/iss.rs | 1 - src/test/auxiliary/issue-11224.rs | 4 +- src/test/auxiliary/issue-11225-1.rs | 2 +- src/test/auxiliary/issue-11225-2.rs | 2 +- src/test/auxiliary/issue-11529.rs | 2 +- src/test/auxiliary/issue-12133-dylib2.rs | 5 +- src/test/auxiliary/issue-13560-3.rs | 5 +- src/test/auxiliary/issue-13620-2.rs | 2 +- src/test/auxiliary/issue-13872-2.rs | 2 +- src/test/auxiliary/issue-13872-3.rs | 2 +- src/test/auxiliary/issue-14422.rs | 2 +- src/test/auxiliary/issue-17718.rs | 8 +- src/test/auxiliary/issue-2414-a.rs | 2 +- src/test/auxiliary/issue-2526.rs | 8 +- src/test/auxiliary/issue-2631-a.rs | 2 +- src/test/auxiliary/issue-3012-1.rs | 1 + src/test/auxiliary/issue-5521.rs | 3 +- src/test/auxiliary/issue-8044.rs | 2 +- src/test/auxiliary/issue-9906.rs | 4 +- src/test/auxiliary/issue13213aux.rs | 5 +- src/test/auxiliary/issue13507.rs | 18 +- .../{issue-11680.rs => issue_11680.rs} | 4 +- .../{issue-12612-1.rs => issue_12612_1.rs} | 0 .../{issue-12612-2.rs => issue_12612_2.rs} | 0 .../issue_16723_multiple_items_syntax_ext.rs | 9 +- .../{issue-16725.rs => issue_16725.rs} | 1 - ...rivacy.rs => issue_17718_const_privacy.rs} | 6 +- src/test/auxiliary/issue_19293.rs | 2 +- .../{issue-21202.rs => issue_21202.rs} | 0 src/test/auxiliary/issue_2723_a.rs | 2 +- src/test/auxiliary/issue_3907.rs | 3 +- src/test/auxiliary/issue_3979_traits.rs | 6 +- src/test/auxiliary/issue_5844_aux.rs | 3 +- src/test/auxiliary/issue_8401.rs | 1 - src/test/auxiliary/issue_9123.rs | 1 - src/test/auxiliary/issue_9188.rs | 11 +- src/test/auxiliary/kinds_in_metadata.rs | 1 - src/test/auxiliary/lang-item-public.rs | 19 +- src/test/auxiliary/linkage-visibility.rs | 11 +- src/test/auxiliary/linkage1.rs | 2 +- src/test/auxiliary/lint_for_crate.rs | 43 + src/test/auxiliary/lint_group_plugin_test.rs | 2 +- src/test/auxiliary/lint_output_format.rs | 6 +- src/test/auxiliary/lint_plugin_test.rs | 2 +- src/test/auxiliary/lint_stability.rs | 24 +- src/test/auxiliary/lint_stability_fields.rs | 60 + ...n-crate.rs => lint_unused_extern_crate.rs} | 0 src/test/auxiliary/logging_right_crate.rs | 4 +- .../auxiliary/macro_crate_MacroRulesTT.rs | 2 +- src/test/auxiliary/macro_crate_nonterminal.rs | 2 +- src/test/auxiliary/macro_crate_test.rs | 38 +- src/test/auxiliary/macro_reexport_1.rs | 2 +- src/test/auxiliary/method_self_arg1.rs | 2 +- src/test/auxiliary/method_self_arg2.rs | 2 +- src/test/auxiliary/moves_based_on_type_lib.rs | 2 +- .../auxiliary/namespaced_enum_emulate_flat.rs | 8 +- src/test/auxiliary/namespaced_enums.rs | 5 +- src/test/auxiliary/nested_item.rs | 8 +- src/test/auxiliary/newtype_struct_xc.rs | 2 +- src/test/auxiliary/noexporttypelib.rs | 2 +- src/test/auxiliary/plugin_args.rs | 9 +- .../plugin_crate_outlive_expansion_phase.rs | 5 +- src/test/auxiliary/plugin_with_plugin_lib.rs | 2 +- src/test/auxiliary/priv-impl-prim-ty.rs | 2 +- src/test/auxiliary/privacy_reexport.rs | 2 +- ...uple-struct.rs => privacy_tuple_struct.rs} | 6 +- src/test/auxiliary/private_trait_xc.rs | 2 + src/test/auxiliary/procedural_mbe_matching.rs | 69 + .../pub_static_array.rs} | 4 +- src/test/auxiliary/pub_use_xcrate1.rs | 2 +- .../auxiliary/reexported_static_methods.rs | 10 +- ...method_type_parameters_cross_crate_lib.rs} | 6 +- src/test/auxiliary/rlib_crate_test.rs | 2 +- src/test/auxiliary/roman_numerals.rs | 11 +- src/test/auxiliary/sepcomp-extern-lib.rs | 2 +- src/test/auxiliary/sepcomp_cci_lib.rs | 4 +- src/test/auxiliary/sepcomp_lib.rs | 6 +- .../auxiliary/static-function-pointer-aux.rs | 7 +- src/test/auxiliary/static-methods-crate.rs | 6 +- src/test/auxiliary/static_fn_inline_xc_aux.rs | 4 +- src/test/auxiliary/static_fn_trait_xc_aux.rs | 4 +- src/test/auxiliary/static_mut_xc.rs | 2 +- src/test/auxiliary/static_priv_by_default.rs | 20 +- .../struct_destructuring_cross_crate.rs | 4 +- ...eld-privacy.rs => struct_field_privacy.rs} | 8 +- src/test/auxiliary/struct_variant_privacy.rs | 3 +- src/test/auxiliary/struct_variant_xc_aux.rs | 1 + src/test/auxiliary/svh-a-base.rs | 7 +- src/test/auxiliary/svh-a-change-lit.rs | 7 +- .../auxiliary/svh-a-change-significant-cfg.rs | 7 +- .../auxiliary/svh-a-change-trait-bound.rs | 7 +- src/test/auxiliary/svh-a-change-type-arg.rs | 7 +- src/test/auxiliary/svh-a-change-type-ret.rs | 5 +- .../auxiliary/svh-a-change-type-static.rs | 5 +- src/test/auxiliary/svh-a-comment.rs | 7 +- src/test/auxiliary/svh-a-doc.rs | 7 +- src/test/auxiliary/svh-a-macro.rs | 7 +- src/test/auxiliary/svh-a-no-change.rs | 7 +- src/test/auxiliary/svh-a-redundant-cfg.rs | 7 +- src/test/auxiliary/svh-a-whitespace.rs | 7 +- src/test/auxiliary/svh-uta-base.rs | 6 +- .../auxiliary/svh-uta-change-use-trait.rs | 6 +- .../syntax_extension_with_dll_deps_1.rs | 2 +- .../syntax_extension_with_dll_deps_2.rs | 6 +- .../trait_bounds_on_structs_and_enums_xc.rs | 5 +- .../auxiliary/trait_default_method_xc_aux.rs | 24 +- .../trait_default_method_xc_aux_2.rs | 6 +- src/test/auxiliary/trait_impl_conflict.rs | 4 +- .../trait_inheritance_auto_xc_2_aux.rs | 14 +- .../trait_inheritance_auto_xc_aux.rs | 6 +- ...ait_inheritance_cross_trait_call_xc_aux.rs | 6 +- .../trait_inheritance_overloading_xc.rs | 4 +- ...rait-safety-lib.rs => trait_safety_lib.rs} | 6 +- ...lt_trait_impl_cross_crate_coherence_lib.rs | 19 + src/test/auxiliary/typeid-intrinsic.rs | 14 +- src/test/auxiliary/typeid-intrinsic2.rs | 14 +- .../auxiliary/unboxed-closures-cross-crate.rs | 6 +- ...able-variant.rs => unreachable_variant.rs} | 0 src/test/auxiliary/weak-lang-items.rs | 3 +- src/test/auxiliary/where_clauses_xc.rs | 1 - src/test/auxiliary/xc_private_method_lib.rs | 10 +- .../auxiliary/xcrate_address_insignificant.rs | 8 +- src/test/auxiliary/xcrate_static_addresses.rs | 18 +- src/test/auxiliary/xcrate_struct_aliases.rs | 5 +- src/test/auxiliary/xcrate_unit_struct.rs | 17 +- src/test/bench/core-map.rs | 2 +- src/test/bench/core-set.rs | 2 +- src/test/bench/core-std.rs | 5 +- src/test/bench/msgsend-pipes-shared.rs | 10 +- src/test/bench/msgsend-pipes.rs | 12 +- src/test/bench/msgsend-ring-mutex-arcs.rs | 14 +- src/test/bench/noise.rs | 18 +- src/test/bench/shootout-binarytrees.rs | 7 +- src/test/bench/shootout-chameneos-redux.rs | 16 +- src/test/bench/shootout-fannkuch-redux.rs | 30 +- src/test/bench/shootout-fasta-redux.rs | 13 +- src/test/bench/shootout-fasta.rs | 7 +- src/test/bench/shootout-k-nucleotide-pipes.rs | 22 +- src/test/bench/shootout-k-nucleotide.rs | 52 +- src/test/bench/shootout-mandelbrot.rs | 3 +- src/test/bench/shootout-meteor.rs | 6 +- src/test/bench/shootout-nbody.rs | 8 +- src/test/bench/shootout-pfib.rs | 4 +- src/test/bench/shootout-reverse-complement.rs | 26 +- src/test/bench/shootout-spectralnorm.rs | 16 +- src/test/bench/std-smallintmap.rs | 2 + src/test/bench/sudoku.rs | 162 +- src/test/bench/task-perf-alloc-unwind.rs | 16 +- .../bench/task-perf-jargon-metal-smoke.rs | 2 +- src/test/codegen/iterate-over-array.rs | 2 +- src/test/codegen/scalar-function-call.rs | 2 +- src/test/codegen/single-return-value.rs | 2 +- src/test/codegen/small-dense-int-switch.rs | 2 +- src/test/codegen/static-method-call-multi.rs | 6 +- src/test/codegen/static-method-call.rs | 6 +- .../virtual-method-call-struct-return.rs | 4 +- src/test/codegen/virtual-method-call.rs | 4 +- .../gated-macro-reexports.rs | 22 + src/test/compile-fail-fulldeps/gated-quote.rs | 50 + .../compile-fail-fulldeps/issue-15778-fail.rs | 18 + src/test/compile-fail-fulldeps/issue-18986.rs | 2 +- src/test/compile-fail/array-not-vector.rs | 6 +- src/test/compile-fail/asm-in-bad-modifier.rs | 4 +- src/test/compile-fail/asm-misplaced-option.rs | 9 +- src/test/compile-fail/asm-out-assign-imm.rs | 2 +- src/test/compile-fail/asm-out-no-modifier.rs | 2 +- src/test/compile-fail/assign-to-method.rs | 4 +- .../assignment-operator-unimplemented.rs | 2 +- ...on-ambig-between-bound-and-where-clause.rs | 52 + ...ed-types-ICE-when-projecting-out-of-err.rs | 3 +- .../associated-types-coherence-failure.rs | 1 - .../associated-types-eq-expr-path.rs | 2 +- .../associated-types-in-ambiguous-context.rs | 3 + .../associated-types-issue-17359.rs | 1 - src/test/compile-fail/bad-bang-ann-3.rs | 2 +- src/test/compile-fail/bad-bang-ann.rs | 2 +- src/test/compile-fail/bad-const-type.rs | 6 +- .../compile-fail/bad-method-typaram-kind.rs | 2 +- .../compile-fail/bad-mid-path-type-params.rs | 2 +- src/test/compile-fail/binop-logic-float.rs | 5 +- src/test/compile-fail/binop-logic-int.rs | 6 +- .../borrow-immutable-upvar-mutation.rs | 12 +- src/test/compile-fail/borrow-tuple-fields.rs | 2 +- .../borrowck-bad-nested-calls-free.rs | 4 +- .../borrowck-bad-nested-calls-move.rs | 4 +- .../borrowck-borrow-from-owned-ptr.rs | 4 +- .../borrowck-borrow-from-stack-variable.rs | 4 +- ...rrowck-borrow-immut-deref-of-box-as-mut.rs | 2 +- ...ck-borrow-mut-base-ptr-in-aliasable-loc.rs | 2 +- .../borrowck-borrowed-uniq-rvalue.rs | 5 +- .../borrowck-box-insensitivity.rs | 33 +- .../borrowck-call-is-borrow-issue-12224.rs | 13 +- .../borrowck-closures-mut-and-imm.rs | 6 +- .../compile-fail/borrowck-closures-two-mut.rs | 2 +- .../borrowck-closures-unique-imm.rs | 1 - .../borrowck-closures-use-after-free.rs | 2 +- .../borrowck-consume-unsize-vec.rs | 22 + .../borrowck-consume-upcast-box.rs | 24 + .../borrowck-field-sensitivity.rs | 1 - ...ssue-5543.rs => borrowck-fn-in-const-a.rs} | 14 +- .../compile-fail/borrowck-fn-in-const-b.rs | 24 + .../compile-fail/borrowck-fn-in-const-c.rs | 33 + ...rrowck-for-loop-correct-cmt-for-pattern.rs | 3 +- .../borrowck-for-loop-head-linkage.rs | 1 - src/test/compile-fail/borrowck-issue-14498.rs | 67 +- .../compile-fail/borrowck-issue-2657-1.rs | 2 +- .../compile-fail/borrowck-issue-2657-2.rs | 2 +- .../compile-fail/borrowck-lend-flow-if.rs | 4 +- .../compile-fail/borrowck-lend-flow-loop.rs | 24 +- src/test/compile-fail/borrowck-lend-flow.rs | 4 +- .../compile-fail/borrowck-let-suggestion.rs | 1 - .../borrowck-loan-blocks-move-cc.rs | 4 +- .../borrowck-loan-blocks-mut-uniq.rs | 2 +- .../borrowck-loan-rcvr-overloaded-op.rs | 2 +- .../borrowck-match-binding-is-assignment.rs | 2 + .../compile-fail/borrowck-move-by-capture.rs | 2 +- .../borrowck-move-error-with-note.rs | 2 +- ...owck-move-from-subpath-of-borrowed-path.rs | 2 +- .../borrowck-move-moved-value-into-closure.rs | 2 +- .../borrowck-move-mut-base-ptr.rs | 2 +- .../borrowck-move-out-of-vec-tail.rs | 2 + .../borrowck-multiple-captures.rs | 13 +- .../borrowck-mut-borrow-of-mut-base-ptr.rs | 2 +- .../compile-fail/borrowck-mutate-in-guard.rs | 1 - .../borrowck-no-cycle-in-exchange-heap.rs | 2 +- .../compile-fail/borrowck-object-lifetime.rs | 1 - .../borrowck-object-mutability.rs | 1 - .../compile-fail/borrowck-overloaded-call.rs | 19 +- ...k-overloaded-index-and-overloaded-deref.rs | 3 +- .../borrowck-overloaded-index-autoderef.rs | 36 +- ...orrowck-overloaded-index-move-from-vec.rs} | 4 +- .../borrowck-overloaded-index-move-index.rs | 74 + ...=> borrowck-overloaded-index-ref-index.rs} | 14 +- .../compile-fail/borrowck-partial-reinit-2.rs | 1 - .../borrowck-report-with-custom-diagnostic.rs | 6 +- .../borrowck-swap-mut-base-ptr.rs | 2 +- .../compile-fail/borrowck-unboxed-closures.rs | 1 - .../compile-fail/borrowck-uniq-via-lend.rs | 14 +- .../compile-fail/borrowck-use-mut-borrow.rs | 3 +- .../borrowck-vec-pattern-element-loan.rs | 1 + .../borrowck-vec-pattern-loan-from-mut.rs | 2 + .../borrowck-vec-pattern-move-tail.rs | 2 + .../borrowck-vec-pattern-nesting.rs | 1 + .../borrowck-vec-pattern-tail-element-loan.rs | 2 + .../cannot-mutate-captured-non-mut-var.rs | 6 +- ...-attr-unknown-attribute-macro-expansion.rs | 20 + src/test/compile-fail/class-method-missing.rs | 2 +- src/test/compile-fail/class-missing-self.rs | 2 +- src/test/compile-fail/closure-reform-bad.rs | 1 - .../compile-fail/coerce-unsafe-to-closure.rs | 3 +- src/test/compile-fail/coercion-slice.rs | 4 +- src/test/compile-fail/coherence-all-remote.rs | 4 +- .../compile-fail/coherence-bigint-param.rs | 4 +- ...nket-conflicts-with-blanket-implemented.rs | 2 +- ...et-conflicts-with-blanket-unimplemented.rs | 2 +- ...ket-conflicts-with-specific-cross-crate.rs | 2 +- ...t-conflicts-with-specific-multidispatch.rs | 2 +- ...herence-blanket-conflicts-with-specific.rs | 2 +- src/test/compile-fail/coherence-cow-1.rs | 28 + src/test/compile-fail/coherence-cow-2.rs | 27 + .../compile-fail/coherence-cow-no-cover.rs | 8 +- .../coherence-default-trait-impl.rs | 34 + src/test/compile-fail/coherence-impls-copy.rs | 53 + ...pls-builtin.rs => coherence-impls-send.rs} | 14 +- .../compile-fail/coherence-impls-sized.rs | 38 + .../coherence-lone-type-parameter.rs | 4 +- src/test/compile-fail/coherence-orphan.rs | 12 +- .../coherence-overlap-issue-23516.rs | 19 + .../coherence-overlapping-pairs.rs | 4 +- .../coherence-pair-covered-uncovered-1.rs | 4 +- .../coherence-pair-covered-uncovered.rs | 4 +- .../compile-fail/coherence-tuple-conflict.rs | 2 +- .../compile-fail/coherence-vec-local-2.rs | 25 + src/test/compile-fail/coherence-vec-local.rs | 25 + ...erence_copy_like_err_fundamental_struct.rs | 36 + ...ce_copy_like_err_fundamental_struct_ref.rs | 36 + ..._copy_like_err_fundamental_struct_tuple.rs | 32 + .../coherence_copy_like_err_struct.rs | 33 + .../coherence_copy_like_err_tuple.rs | 32 + src/test/compile-fail/coherence_local.rs | 33 + .../coherence_local_err_struct.rs | 29 + .../compile-fail/coherence_local_err_tuple.rs | 29 + src/test/compile-fail/coherence_local_ref.rs | 27 + src/test/compile-fail/const-array-oob.rs | 16 + .../const-block-non-item-statement.rs | 4 +- .../compile-fail/const-eval-overflow-2.rs | 30 + .../compile-fail/const-eval-overflow-3.rs | 39 + .../compile-fail/const-eval-overflow-3b.rs | 43 + .../compile-fail/const-eval-overflow-4.rs | 36 + .../compile-fail/const-eval-overflow-4b.rs | 36 + src/test/compile-fail/const-eval-overflow.rs | 132 + .../const-len-underflow-separate-spans.rs | 23 + .../const-len-underflow-subspans.rs | 20 + src/test/compile-fail/cross-borrow-trait.rs | 6 +- src/test/compile-fail/custom_attribute.rs | 2 +- .../cycle-projection-based-on-where-clause.rs | 34 + .../cycle-trait-default-type-trait.rs | 18 + .../cycle-trait-supertrait-direct.rs} | 13 +- .../cycle-trait-supertrait-indirect.rs | 25 + .../derive-assoc-type-not-impl.rs | 29 + .../derive-no-std-not-supported.rs | 2 +- src/test/compile-fail/deriving-bounds.rs | 6 +- .../deriving-meta-unknown-trait.rs | 3 +- src/test/compile-fail/deriving-non-type.rs | 4 +- .../compile-fail/destructor-restrictions.rs | 4 +- src/test/compile-fail/discrim-ill-typed.rs | 118 + src/test/compile-fail/discrim-overflow-2.rs | 94 + src/test/compile-fail/discrim-overflow.rs | 108 + .../drop-with-active-borrows-1.rs | 1 - .../compile-fail/dropck_arr_cycle_checked.rs | 4 +- .../dropck_no_diverge_on_nonregular_1.rs | 37 + .../dropck_no_diverge_on_nonregular_2.rs | 36 + .../dropck_no_diverge_on_nonregular_3.rs | 46 + .../dropck_tarena_cycle_checked.rs | 4 +- .../compile-fail/dropck_vec_cycle_checked.rs | 4 +- src/test/compile-fail/dst-bad-assign-2.rs | 5 +- src/test/compile-fail/dst-bad-assign.rs | 5 +- src/test/compile-fail/dst-bad-coerce1.rs | 4 - src/test/compile-fail/dst-index.rs | 8 +- src/test/compile-fail/duplicate-parameter.rs | 1 - .../compile-fail/duplicate-type-parameter.rs | 1 - src/test/compile-fail/empty-extern-arg.rs | 2 +- .../compile-fail/enum-discrim-too-small.rs | 2 + src/test/compile-fail/estr-subtyping.rs | 2 +- src/test/compile-fail/eval-enum.rs | 4 +- .../compile-fail/exclusive-drop-and-copy.rs | 4 +- .../explicit-self-lifetime-mismatch.rs | 1 - .../compile-fail/extern-with-type-bounds.rs | 3 +- .../compile-fail/extern-wrong-value-type.rs | 2 +- .../feature-gate-advanced-slice-features.rs | 3 +- ...te-allow-internal-unstable-nested-macro.rs | 23 + ...> feature-gate-allow-internal-unstable.rs} | 7 +- .../compile-fail/feature-gate-box-expr.rs | 1 - .../compile-fail/feature-gate-int-uint.rs | 37 - ...ng-items.rs => feature-gate-intrinsics.rs} | 4 - .../feature-gate-lang-items.rs} | 5 +- ...tor-owned.rs => feature-gate-rust-call.rs} | 20 +- .../compile-fail/feature-gate-simd-ffi.rs | 2 +- src/test/compile-fail/feature-gate-start.rs | 1 - ...e-id2.rs => feature-gate-static-assert.rs} | 6 +- ...ture-gate-unboxed-closures-manual-impls.rs | 21 +- .../feature-gated-feature-in-macro-arg.rs | 2 +- src/test/compile-fail/fn-compare-mismatch.rs | 1 + src/test/compile-fail/fn-trait-formatting.rs | 7 +- src/test/compile-fail/fn-variance-1.rs | 8 +- ...cessary-casts.rs => gated-box-patterns.rs} | 22 +- src/test/compile-fail/gated-box-syntax.rs | 17 + src/test/compile-fail/gated-link-args.rs | 19 + .../gated-link-llvm-intrinsics.rs | 19 + .../compile-fail/gated-plugin_registrar.rs | 8 +- src/test/compile-fail/gated-simd-ffi.rs | 27 + src/test/compile-fail/gated-thread-local.rs | 25 + .../compile-fail/gated-unsafe-destructor.rs | 27 + .../generic-impl-less-params-with-defaults.rs | 2 +- .../generic-impl-more-params-with-defaults.rs | 2 +- src/test/compile-fail/generic-no-mangle.rs | 1 - src/test/compile-fail/glob-resolve1.rs | 3 - .../hrtb-precedence-of-plus-error-message.rs | 36 - src/test/compile-fail/huge-array-simple.rs | 10 +- src/test/compile-fail/if-loop.rs | 20 + .../compile-fail/impl-duplicate-methods.rs | 2 +- src/test/compile-fail/import-glob-circular.rs | 4 +- src/test/compile-fail/index-bot.rs | 2 +- .../compile-fail/indexing-requires-a-uint.rs | 1 - .../compile-fail/infinite-instantiation.rs | 26 +- .../compile-fail/infinite-macro-expansion.rs | 1 - .../infinite-vec-type-recursion.rs | 4 +- .../inner-static-type-parameter.rs | 3 +- src/test/compile-fail/integral-indexing.rs | 8 +- .../compile-fail/internal-unstable-noallow.rs | 27 + ...h.rs => internal-unstable-thread-local.rs} | 14 +- src/test/compile-fail/internal-unstable.rs | 50 + .../compile-fail/intrinsic-return-address.rs | 2 - src/test/compile-fail/invalid-inline.rs | 24 + src/test/compile-fail/issue-10291.rs | 7 +- src/test/compile-fail/issue-10398.rs | 2 +- src/test/compile-fail/issue-10536.rs | 1 - src/test/compile-fail/issue-11192.rs | 3 +- src/test/compile-fail/issue-11374.rs | 10 +- src/test/compile-fail/issue-11515.rs | 3 +- src/test/compile-fail/issue-11593.rs | 1 - src/test/compile-fail/issue-11680.rs | 4 +- src/test/compile-fail/issue-11714.rs | 2 +- src/test/compile-fail/issue-11771.rs | 14 +- src/test/compile-fail/issue-11844.rs | 1 - src/test/compile-fail/issue-11925.rs | 2 +- src/test/compile-fail/issue-12041.rs | 1 - src/test/compile-fail/issue-12127.rs | 2 +- src/test/compile-fail/issue-12369.rs | 2 + src/test/compile-fail/issue-12567.rs | 2 + src/test/compile-fail/issue-12612.rs | 5 +- src/test/compile-fail/issue-13058.rs | 10 +- .../{run-pass => compile-fail}/issue-13352.rs | 6 + src/test/compile-fail/issue-13407.rs | 19 + src/test/compile-fail/issue-13446.rs | 1 - src/test/compile-fail/issue-13466.rs | 6 +- src/test/compile-fail/issue-13482-2.rs | 2 + src/test/compile-fail/issue-13482.rs | 2 + src/test/compile-fail/issue-13641.rs | 4 +- src/test/compile-fail/issue-13853-3.rs | 36 - src/test/compile-fail/issue-14092.rs | 1 - src/test/compile-fail/issue-14254.rs | 10 +- src/test/compile-fail/issue-14845.rs | 2 +- src/test/compile-fail/issue-15094.rs | 7 +- src/test/compile-fail/issue-15381.rs | 2 + src/test/compile-fail/issue-16149.rs | 1 - src/test/compile-fail/issue-16338.rs | 1 - src/test/compile-fail/issue-16538.rs | 3 +- src/test/compile-fail/issue-16725.rs | 5 +- src/test/compile-fail/issue-16747.rs | 5 +- src/test/compile-fail/issue-16922.rs | 20 + src/test/compile-fail/issue-17263.rs | 4 +- src/test/compile-fail/issue-17283.rs | 2 +- src/test/compile-fail/issue-17441.rs | 16 +- src/test/compile-fail/issue-17651.rs | 8 +- .../issue-17718-const-bad-values.rs | 1 - .../compile-fail/issue-17718-const-privacy.rs | 4 +- src/test/compile-fail/issue-17718-patterns.rs | 2 +- src/test/compile-fail/issue-17913.rs | 4 +- src/test/compile-fail/issue-17933.rs | 4 +- src/test/compile-fail/issue-18107.rs | 2 +- src/test/compile-fail/issue-18252.rs | 2 +- src/test/compile-fail/issue-18389.rs | 8 +- src/test/compile-fail/issue-18400.rs | 3 - src/test/compile-fail/issue-18566.rs | 2 +- src/test/compile-fail/issue-18783.rs | 16 +- src/test/compile-fail/issue-18919.rs | 17 + src/test/compile-fail/issue-18959.rs | 6 +- src/test/compile-fail/issue-19244-1.rs | 4 +- src/test/compile-fail/issue-19244-2.rs | 4 +- src/test/compile-fail/issue-19660.rs | 2 +- src/test/compile-fail/issue-19883.rs | 13 +- src/test/compile-fail/issue-19982.rs | 17 + src/test/compile-fail/issue-19991.rs | 6 +- src/test/compile-fail/issue-20225.rs | 32 + src/test/compile-fail/issue-20261.rs | 17 + src/test/compile-fail/issue-20714.rs | 15 + src/test/compile-fail/issue-20801.rs | 4 +- src/test/compile-fail/issue-21202.rs | 6 +- src/test/compile-fail/issue-2149.rs | 3 +- src/test/compile-fail/issue-2150.rs | 2 +- src/test/compile-fail/issue-22426-1.rs | 17 + src/test/compile-fail/issue-22426-2.rs | 12 + src/test/compile-fail/issue-22426-3.rs | 22 + src/test/compile-fail/issue-22912.rs | 41 + src/test/compile-fail/issue-23080-2.rs | 29 + src/test/compile-fail/issue-23080.rs | 31 + src/test/compile-fail/issue-2356.rs | 14 +- src/test/compile-fail/issue-3008-2.rs | 1 - src/test/compile-fail/issue-3521-2.rs | 4 +- src/test/compile-fail/issue-3521.rs | 4 +- src/test/compile-fail/issue-3668-2.rs | 4 +- src/test/compile-fail/issue-3668.rs | 1 + src/test/compile-fail/issue-3763.rs | 11 +- src/test/compile-fail/issue-3907.rs | 1 - src/test/compile-fail/issue-3953.rs | 34 - src/test/compile-fail/issue-3973.rs | 2 - src/test/compile-fail/issue-4265.rs | 2 +- src/test/compile-fail/issue-4335.rs | 6 +- src/test/compile-fail/issue-4517.rs | 2 +- src/test/compile-fail/issue-5239-1.rs | 2 +- src/test/compile-fail/issue-5844.rs | 1 - src/test/compile-fail/issue-6804.rs | 9 +- src/test/compile-fail/issue-7575.rs | 6 +- src/test/compile-fail/issue-7607-1.rs | 5 +- src/test/compile-fail/issue-7867.rs | 6 +- src/test/compile-fail/issue-7950.rs | 17 + src/test/compile-fail/issue-8460-const.rs | 6 +- src/test/compile-fail/issue-8767.rs | 3 +- src/test/compile-fail/issue-9814.rs | 2 +- src/test/compile-fail/kindck-copy.rs | 3 +- .../compile-fail/kindck-impl-type-params-2.rs | 2 +- .../compile-fail/kindck-impl-type-params.rs | 1 + .../kindck-inherited-copy-bound.rs | 8 +- src/test/compile-fail/kindck-nonsendable-1.rs | 3 +- ...-return-type-requires-explicit-lifetime.rs | 1 - ...me-inference-give-expl-lifetime-param-2.rs | 6 +- src/test/compile-fail/linkage1.rs | 1 - src/test/compile-fail/linkage3.rs | 1 - src/test/compile-fail/lint-dead-code-3.rs | 4 +- src/test/compile-fail/lint-dead-code-4.rs | 4 +- .../compile-fail/lint-exceeding-bitshifts.rs | 4 +- src/test/compile-fail/lint-missing-doc.rs | 43 +- .../compile-fail/lint-non-camel-case-types.rs | 3 + src/test/compile-fail/lint-output-format.rs | 4 +- .../compile-fail/lint-stability-fields.rs | 346 ++ src/test/compile-fail/lint-stability.rs | 235 +- src/test/compile-fail/lint-stability3.rs | 1 - src/test/compile-fail/lint-type-limits.rs | 6 +- src/test/compile-fail/lint-unsafe-code.rs | 102 + .../compile-fail/lint-unused-extern-crate.rs | 6 +- .../compile-fail/lint-uppercase-variables.rs | 1 - src/test/compile-fail/liveness-issue-2163.rs | 2 +- .../liveness-return-last-stmt-semi.rs | 2 +- src/test/compile-fail/liveness-unused.rs | 2 +- .../compile-fail/liveness-use-after-move.rs | 2 +- .../compile-fail/loop-labeled-break-value.rs | 21 + .../compile-fail/macro-inner-attributes.rs | 1 - .../macro-no-implicit-reexport.rs | 2 +- .../compile-fail/macro-outer-attributes.rs | 1 - .../macro-reexport-not-locally-visible.rs | 2 +- .../compile-fail/malformed-derive-entry.rs | 25 + src/test/compile-fail/malformed-plugin-1.rs | 1 + src/test/compile-fail/malformed-plugin-2.rs | 1 + src/test/compile-fail/malformed-plugin-3.rs | 1 + src/test/compile-fail/manual-link-bad-form.rs | 4 +- src/test/compile-fail/manual-link-bad-kind.rs | 3 +- .../manual-link-bad-search-path.rs | 15 + .../compile-fail/manual-link-framework.rs | 2 +- src/test/compile-fail/map-types.rs | 3 +- ...{lint-unsafe-block.rs => match-ref-ice.rs} | 26 +- ...-impl-2.rs => match-ref-mut-invariance.rs} | 18 +- .../match-ref-mut-let-invariance.rs | 25 + src/test/compile-fail/match-vec-fixed.rs | 2 + src/test/compile-fail/match-vec-mismatch-2.rs | 2 + src/test/compile-fail/match-vec-mismatch.rs | 2 + .../compile-fail/match-vec-unreachable.rs | 1 + .../method-ambig-two-traits-cross-crate.rs | 1 - .../compile-fail/method-macro-backtrace.rs | 2 +- src/test/compile-fail/method-missing-call.rs | 1 - src/test/compile-fail/method-self-arg-1.rs | 6 +- .../method-suggestion-no-duplication.rs | 2 - src/test/compile-fail/move-in-guard-1.rs | 25 + src/test/compile-fail/move-in-guard-2.rs | 25 + .../compile-fail/move-out-of-tuple-field.rs | 2 +- ...ased-on-type-no-recursive-stack-closure.rs | 4 +- src/test/compile-fail/mut-cross-borrowing.rs | 3 +- .../compile-fail/mut-pattern-mismatched.rs | 8 +- .../compile-fail/mutable-class-fields-2.rs | 2 +- src/test/compile-fail/mutable-class-fields.rs | 2 +- .../no-implicit-prelude-nested.rs | 30 +- src/test/compile-fail/no-implicit-prelude.rs | 10 +- .../non-constant-enum-for-vec-repeat.rs | 5 +- .../non-constant-expr-for-fixed-len-vec.rs | 3 +- .../non-constant-expr-for-vec-repeat.rs | 3 +- .../non-exhaustive-match-nested.rs | 2 + src/test/compile-fail/non-exhaustive-match.rs | 2 + .../non-exhaustive-pattern-witness.rs | 3 +- .../compile-fail/nonbool_static_assert.rs | 17 + .../object-lifetime-default-elision.rs | 4 +- .../object-lifetime-default-from-box-error.rs | 4 +- .../object-safety-by-value-self-use.rs} | 19 +- .../object-safety-by-value-self.rs | 39 +- .../compile-fail/object-safety-generics.rs | 16 +- .../object-safety-mentions-Self.rs | 15 +- src/test/compile-fail/opt-in-copy.rs | 3 +- src/test/compile-fail/or-patter-mismatch.rs | 2 +- src/test/compile-fail/overloaded-calls-bad.rs | 9 +- .../compile-fail/overloaded-calls-nontuple.rs | 7 +- .../compile-fail/pattern-bindings-after-at.rs | 1 - .../pattern-ident-path-generics.rs | 1 - src/test/compile-fail/phantom-oibit.rs | 41 + .../compile-fail/priv_in_pub_sig_priv_mod.rs | 28 + src/test/compile-fail/privacy1.rs | 16 +- src/test/compile-fail/privacy5.rs | 23 +- src/test/compile-fail/private-method.rs | 2 +- .../private-struct-field-cross-crate.rs | 4 +- src/test/compile-fail/pub-method-macro.rs | 2 +- src/test/compile-fail/range-1.rs | 9 +- src/test/compile-fail/recursion.rs | 14 +- src/test/compile-fail/recursion_limit.rs | 6 +- src/test/compile-fail/reflect-assoc.rs | 35 + src/test/compile-fail/reflect-object-param.rs | 47 + src/test/compile-fail/reflect.rs | 39 + .../region-bound-on-closure-outlives-call.rs | 1 - .../compile-fail/region-object-lifetime-1.rs | 1 - .../compile-fail/region-object-lifetime-2.rs | 1 - .../compile-fail/region-object-lifetime-3.rs | 1 - .../compile-fail/region-object-lifetime-4.rs | 1 - .../compile-fail/region-object-lifetime-5.rs | 1 - .../region-object-lifetime-in-coercion.rs | 18 +- .../regionck-unboxed-closure-lifetimes.rs | 1 - src/test/compile-fail/regions-addr-of-self.rs | 6 +- .../regions-addr-of-upvar-self.rs | 2 +- ...nded-method-type-parameters-cross-crate.rs | 4 +- ...gions-close-associated-type-into-object.rs | 23 +- .../regions-close-object-into-object-1.rs | 1 - .../regions-close-object-into-object-3.rs | 1 - .../regions-close-object-into-object-4.rs | 1 - .../regions-close-object-into-object-5.rs | 2 +- .../regions-close-over-type-parameter-1.rs | 2 + ...ions-close-over-type-parameter-multiple.rs | 2 +- .../regions-close-param-into-object.rs | 11 +- .../compile-fail/regions-creating-enums.rs | 4 +- src/test/compile-fail/regions-nested-fns.rs | 10 +- .../regions-pattern-typing-issue-19552.rs | 2 + .../regions-pattern-typing-issue-19997.rs | 4 +- .../regions-proc-bound-capture.rs | 6 +- ...regions-return-ref-to-upvar-issue-17403.rs | 2 +- .../compile-fail/regions-steal-closure.rs | 6 +- src/test/compile-fail/regions-trait-1.rs | 4 +- .../regions-trait-object-subtyping.rs | 35 + .../reject-specialized-drops-8142.rs | 79 + src/test/compile-fail/repeat_count.rs | 2 +- .../compile-fail/reserved-attr-on-macro.rs | 18 + ...e-conflict-extern-crate-vs-extern-crate.rs | 1 - ...resolve-conflict-import-vs-extern-crate.rs | 1 - .../resolve-conflict-import-vs-import.rs | 1 - .../resolve-conflict-item-vs-extern-crate.rs | 1 - .../resolve-conflict-item-vs-import.rs | 1 - .../compile-fail/resolve-unknown-trait.rs | 7 +- src/test/compile-fail/retslot-cast.rs | 31 + .../send-is-not-static-ensures-scoping.rs | 5 +- .../send-is-not-static-std-sync-2.rs | 46 + .../send-is-not-static-std-sync.rs | 56 + .../shadowing-in-the-same-pattern.rs | 1 - .../compile-fail/shift-various-bad-types.rs | 14 +- src/test/compile-fail/simd-binop.rs | 1 + src/test/compile-fail/single-derive-attr.rs | 15 + .../single-primitive-inherent-impl.rs | 24 + .../compile-fail/static-array-across-crate.rs | 20 + src/test/compile-fail/static-assert.rs | 1 + src/test/compile-fail/static-assert2.rs | 1 + src/test/compile-fail/static-region-bound.rs | 2 +- src/test/compile-fail/struct-field-privacy.rs | 8 +- .../compile-fail/struct-variant-privacy-xc.rs | 1 - .../structure-constructor-type-mismatch.rs | 29 +- .../compile-fail/suggest-private-fields.rs | 36 + .../syntaxt-default-trait-impls.rs | 18 + src/test/compile-fail/tail-typeck.rs | 2 +- .../trait-as-struct-constructor.rs | 1 - .../trait-bounds-impl-comparison-2.rs | 1 - .../trait-bounds-not-on-bare-trait.rs | 2 +- ...rait-bounds-on-structs-and-enums-locals.rs | 1 - ...rait-bounds-on-structs-and-enums-static.rs | 1 - .../trait-bounds-on-structs-and-enums-xc.rs | 1 - .../trait-bounds-on-structs-and-enums-xc1.rs | 1 - .../trait-bounds-on-structs-and-enums.rs | 1 - .../trait-coercion-generic-bad.rs | 5 +- .../trait-coercion-generic-regions.rs | 6 +- .../compile-fail/trait-impl-for-module.rs | 2 +- .../compile-fail/trait-or-new-type-instead.rs | 5 +- .../trait-safety-trait-impl-cc.rs | 4 +- src/test/compile-fail/trait-test-2.rs | 1 + .../traits-assoc-type-in-supertrait-bad.rs | 26 + .../traits-issue-23003-overflow.rs | 38 + ...traits-multidispatch-convert-ambig-dest.rs | 2 +- .../traits-repeated-supertrait-ambig.rs | 53 + .../compile-fail/transmute-different-sizes.rs | 2 - src/test/compile-fail/trivial_casts.rs | 94 + .../compile-fail/tuple-index-out-of-bounds.rs | 6 +- .../compile-fail/type-mismatch-multiple.rs | 6 +- ...rameter-defaults-referencing-Self-ppaux.rs | 2 +- .../type-params-in-different-spaces-1.rs | 2 +- .../type-params-in-different-spaces-2.rs | 1 - .../type-params-in-different-spaces-3.rs | 1 - .../typeck-builtin-bound-type-parameters.rs | 28 + .../typeck-default-trait-impl-assoc-type.rs | 25 + ...-default-trait-impl-constituent-types-2.rs | 32 + ...ck-default-trait-impl-constituent-types.rs | 35 + ...efault-trait-impl-cross-crate-coherence.rs | 34 + ...typeck-default-trait-impl-negation-send.rs | 31 + ...typeck-default-trait-impl-negation-sync.rs | 50 + .../typeck-default-trait-impl-negation.rs | 44 + ...ypeck-default-trait-impl-outside-crate.rs} | 9 +- .../typeck-default-trait-impl-precedence.rs | 33 + .../typeck-default-trait-impl-send-param.rs} | 10 +- .../typeck-default-trait-impl-superregion.rs | 29 + .../typeck-default-trait-impl-supertrait.rs | 31 + ...k-default-trait-impl-trait-where-clause.rs | 47 + .../typeck-negative-impls-builtin.rs | 2 +- .../typeck_type_placeholder_item.rs | 4 +- .../compile-fail/ufcs-explicit-self-bad.rs | 1 - .../compile-fail/ufcs-qpath-missing-params.rs | 2 +- .../compile-fail/ufcs-qpath-self-mismatch.rs | 1 - .../unboxed-closure-illegal-move.rs | 15 +- .../unboxed-closure-immutable-capture.rs | 2 +- .../compile-fail/unboxed-closure-region.rs | 4 +- ...unboxed-closure-sugar-nonexistent-trait.rs | 3 +- .../unboxed-closure-sugar-not-used-on-fn.rs | 1 - .../unboxed-closure-sugar-used-on-struct-1.rs | 1 - .../unboxed-closure-sugar-used-on-struct.rs | 1 - .../unboxed-closure-sugar-wrong-trait.rs | 1 - .../unboxed-closures-borrow-conflict.rs | 2 +- .../unboxed-closures-fnmut-as-fn.rs | 10 +- ...-closures-infer-explicit-call-too-early.rs | 1 - ...osures-infer-fnmut-calling-fnmut-no-mut.rs | 1 - .../unboxed-closures-mutate-upvar.rs | 12 +- ...-closures-mutated-upvar-from-fn-closure.rs | 2 +- ...oxed-closures-recursive-fn-using-fn-mut.rs | 9 +- ...nboxed-closures-static-call-wrong-trait.rs | 1 - .../unboxed-closures-unsafe-extern-fn.rs | 8 +- .../unboxed-closures-vtable-mismatch.rs | 1 - .../unboxed-closures-wrong-abi.rs | 9 +- ...boxed-closures-wrong-arg-type-extern-fn.rs | 8 +- src/test/compile-fail/unique-pinned-nocopy.rs | 5 +- src/test/compile-fail/unique-unique-kind.rs | 5 +- src/test/compile-fail/unique-vec-res.rs | 7 +- src/test/compile-fail/unnecessary-private.rs | 4 +- src/test/compile-fail/unreachable-arm.rs | 2 +- src/test/compile-fail/unreachable-variant.rs | 4 +- .../unsafe-fn-assign-deref-ptr.rs | 2 +- src/test/compile-fail/unsafe-subtyping.rs | 21 + src/test/compile-fail/unsafe-trait-impl.rs | 22 + .../compile-fail/unsafe_no_drop_flag-gate.rs | 23 + src/test/compile-fail/unsendable-class.rs | 35 - src/test/compile-fail/unsized4.rs | 19 - .../unused-macro-with-bad-frag-spec.rs | 17 + .../unused-macro-with-follow-violation.rs | 15 + ...use-after-move-implicity-coerced-object.rs | 6 +- src/test/compile-fail/use-from-trait.rs | 2 +- src/test/compile-fail/use-meta-mismatch.rs | 2 +- src/test/compile-fail/useless-priv.rs | 5 +- src/test/compile-fail/useless-priv2.rs | 18 - src/test/compile-fail/variadic-ffi.rs | 4 +- .../variance-deprecated-markers.rs | 35 - src/test/compile-fail/variance-issue-20533.rs | 7 +- .../variance-region-bounds.rs} | 18 +- .../compile-fail/variance-trait-matching.rs | 1 - .../vec-must-not-hide-type-from-dropck.rs | 4 +- .../vec_refs_data_with_early_death.rs | 2 +- .../compile-fail/vector-cast-weirdness.rs | 7 +- .../compile-fail/vtable-res-trait-param.rs | 2 +- .../compile-fail/walk-struct-literal-with.rs | 1 - src/test/compile-fail/weak-lang-item.rs | 2 +- .../compile-fail/where-clauses-unsatisfied.rs | 1 - src/test/debuginfo/associated-types.rs | 14 +- .../debuginfo/basic-types-globals-metadata.rs | 32 +- src/test/debuginfo/basic-types-globals.rs | 32 +- src/test/debuginfo/basic-types-mut-globals.rs | 60 +- src/test/debuginfo/basic-types.rs | 6 +- src/test/debuginfo/borrowed-basic.rs | 8 +- src/test/debuginfo/borrowed-struct.rs | 8 +- src/test/debuginfo/borrowed-unique-basic.rs | 8 +- src/test/debuginfo/boxed-struct.rs | 4 +- .../by-value-non-immediate-argument.rs | 6 +- .../by-value-self-argument-in-trait-impl.rs | 14 +- src/test/debuginfo/c-style-enum.rs | 29 +- .../debuginfo/closure-in-generic-function.rs | 2 +- src/test/debuginfo/constant-debug-locs.rs | 68 + src/test/debuginfo/cross-crate-spans.rs | 74 + .../debuginfo/destructured-fn-argument.rs | 26 +- src/test/debuginfo/destructured-local.rs | 8 +- src/test/debuginfo/extern-c-fn.rs | 68 + .../debuginfo/function-arg-initialization.rs | 7 +- src/test/debuginfo/function-arguments.rs | 2 +- ...nction-prologue-stepping-no-stack-check.rs | 4 +- .../function-prologue-stepping-regular.rs | 3 +- src/test/debuginfo/gdb-pretty-std.rs | 60 + ...gdb-pretty-struct-and-enums-pre-gdb-7-7.rs | 2 +- .../debuginfo/gdb-pretty-struct-and-enums.rs | 6 +- src/test/debuginfo/generic-function.rs | 2 +- .../generic-method-on-generic-struct.rs | 11 +- ...eneric-static-method-on-struct-and-enum.rs | 10 +- .../debuginfo/generic-struct-style-enum.rs | 2 +- src/test/debuginfo/generic-struct.rs | 2 +- ...ric-trait-generic-static-default-method.rs | 9 +- .../debuginfo/generic-tuple-style-enum.rs | 2 +- src/test/debuginfo/issue12886.rs | 5 +- src/test/debuginfo/issue13213.rs | 3 + src/test/debuginfo/issue22656.rs | 57 + src/test/debuginfo/lexical-scope-in-match.rs | 4 +- .../lexical-scope-in-parameterless-closure.rs | 1 - .../lexical-scope-in-stack-closure.rs | 2 +- .../lexical-scope-in-unique-closure.rs | 2 +- .../lexical-scopes-in-block-expression.rs | 28 +- src/test/debuginfo/limited-debuginfo.rs | 5 +- src/test/debuginfo/method-on-enum.rs | 11 +- .../debuginfo/method-on-generic-struct.rs | 11 +- src/test/debuginfo/method-on-struct.rs | 13 +- src/test/debuginfo/method-on-trait.rs | 19 +- src/test/debuginfo/method-on-tuple-struct.rs | 13 +- src/test/debuginfo/no-debug-attribute.rs | 1 - src/test/debuginfo/recursive-struct.rs | 7 +- src/test/debuginfo/self-in-default-method.rs | 13 +- .../self-in-generic-default-method.rs | 13 +- src/test/debuginfo/simd.rs | 21 +- src/test/debuginfo/simple-struct.rs | 24 +- src/test/debuginfo/simple-tuple.rs | 28 +- .../static-method-on-struct-and-enum.rs | 10 +- src/test/debuginfo/struct-in-enum.rs | 2 +- src/test/debuginfo/struct-style-enum.rs | 2 +- .../trait-generic-static-default-method.rs | 6 +- src/test/debuginfo/trait-pointers.rs | 4 +- src/test/debuginfo/tuple-style-enum.rs | 2 +- src/test/debuginfo/type-names.rs | 60 +- src/test/debuginfo/unique-enum.rs | 8 +- src/test/debuginfo/unreachable-locals.rs | 85 +- .../var-captured-in-nested-closure.rs | 6 +- .../var-captured-in-sendable-closure.rs | 8 +- .../var-captured-in-stack-closure.rs | 6 +- src/test/debuginfo/vec-slices.rs | 4 +- .../parse-fail/ascii-only-character-escape.rs | 1 - src/test/parse-fail/bad-lit-suffixes.rs | 4 - src/test/parse-fail/byte-literals.rs | 2 - src/test/parse-fail/byte-string-literals.rs | 2 - src/test/parse-fail/circular_modules_main.rs | 4 +- .../parse-fail/class-implements-bad-trait.rs | 2 +- .../closure-return-syntax.rs} | 10 +- src/test/parse-fail/column-offset-1-based.rs | 2 +- src/test/parse-fail/empty-impl-semicolon.rs | 2 +- .../extern-crate-as-no-string-help.rs | 15 - src/test/parse-fail/extern-foreign-crate.rs | 2 +- src/test/parse-fail/issue-10392-2.rs | 1 - src/test/parse-fail/issue-1655.rs | 2 +- src/test/parse-fail/issue-17718-const-mut.rs | 1 - src/test/parse-fail/issue-1802-1.rs | 2 +- src/test/parse-fail/issue-20711-2.rs | 1 - src/test/parse-fail/issue-21153.rs | 2 +- src/test/parse-fail/issue-22647.rs | 25 + src/test/parse-fail/issue-22712.rs | 19 + src/test/parse-fail/issue-2354-1.rs | 1 - .../parse-fail/issue-23620-invalid-escapes.rs | 45 + src/test/parse-fail/issue-5544-b.rs | 2 +- src/test/parse-fail/issue-5806.rs | 12 +- .../keywords-followed-by-double-colon.rs | 1 - src/test/parse-fail/lex-bad-binary-literal.rs | 21 + src/test/parse-fail/lex-bad-char-literals.rs | 22 - .../parse-fail/lex-bad-numeric-literals.rs | 2 +- src/test/parse-fail/lex-bad-octal-literal.rs | 14 + src/test/parse-fail/macro-attribute.rs | 1 - src/test/parse-fail/macros-no-semicolon.rs | 1 - src/test/parse-fail/multitrait.rs | 2 +- src/test/parse-fail/new-unicode-escapes-4.rs | 5 +- src/test/parse-fail/obsolete-closure-kind.rs | 18 + src/test/parse-fail/obsolete-proc.rs | 4 +- src/test/parse-fail/raw-byte-string-eof.rs | 2 - .../parse-fail/raw-byte-string-literals.rs | 2 - src/test/parse-fail/regions-trait-2.rs | 2 +- src/test/parse-fail/struct-literal-in-for.rs | 1 - src/test/parse-fail/struct-literal-in-if.rs | 1 - .../struct-literal-in-match-discriminant.rs | 1 - .../parse-fail/struct-literal-in-while.rs | 1 - .../parse-fail/trailing-plus-in-bounds.rs | 5 +- .../parse-fail/trait-bounds-not-on-impl.rs | 4 +- src/test/parse-fail/trait-pub-assoc-ty.rs | 15 + src/test/parse-fail/trait-pub-method.rs | 15 + .../type-parameters-in-field-exprs.rs | 1 - .../unboxed-closure-sugar-used-on-struct-3.rs | 1 - src/test/parse-fail/use-mod-4.rs | 1 - .../where-clauses-no-bounds-or-predicates.rs | 1 - src/test/pretty/asm-clobbers.rs | 1 - src/test/pretty/blank-lines.rs | 2 +- src/test/pretty/block-comment-wchar.pp | 9 +- src/test/pretty/block-comment-wchar.rs | 9 +- src/test/pretty/block-disambig.rs | 18 +- src/test/pretty/closure-reform-pretty.rs | 7 +- .../default-trait-impl.rs} | 13 +- src/test/pretty/disamb-stmt-expr.rs | 4 +- src/test/pretty/do1.rs | 2 +- src/test/pretty/empty-impl.rs | 4 +- src/test/pretty/empty-lines.rs | 4 +- src/test/pretty/for-comment.rs | 2 +- src/test/pretty/issue-4264.pp | 6 +- src/test/pretty/issue-4264.rs | 4 +- src/test/pretty/path-type-bounds.rs | 5 +- src/test/pretty/raw-str-nonexpr.rs | 2 +- src/test/pretty/record-trailing-comma.rs | 4 +- src/test/pretty/struct-tuple.rs | 4 +- src/test/pretty/trait-safety.rs | 2 +- src/test/pretty/unary-op-disambig.rs | 12 +- src/test/pretty/where-clauses.rs | 3 +- src/test/run-fail/args-panic.rs | 2 +- src/test/run-fail/assert-eq-macro-panic.rs | 2 +- .../binop-fail-3.rs | 5 +- src/test/run-fail/bounds-check-no-overflow.rs | 6 +- .../bug-2470-bounds-check-overflow-2.rs | 4 +- .../bug-2470-bounds-check-overflow-3.rs | 4 +- .../bug-2470-bounds-check-overflow.rs | 10 +- src/test/run-fail/bug-811.rs | 6 +- src/test/run-fail/die-macro-expr.rs | 2 +- src/test/run-fail/expr-if-panic-fn.rs | 2 +- src/test/run-fail/expr-match-panic-fn.rs | 2 +- src/test/run-fail/extern-panic.rs | 11 +- .../run-fail/hashmap-capacity-overflow.rs | 4 +- src/test/run-fail/if-check-panic.rs | 10 +- src/test/run-fail/issue-2061.rs | 2 +- src/test/run-fail/issue-23354-2.rs | 17 + src/test/run-fail/issue-23354.rs | 16 + src/test/run-fail/issue-2444.rs | 2 +- src/test/run-fail/issue-948.rs | 2 +- src/test/run-fail/match-bot-panic.rs | 2 +- src/test/run-fail/match-disc-bot.rs | 2 +- src/test/run-fail/match-wildcards.rs | 2 +- src/test/run-fail/overflowing-add.rs | 19 + src/test/run-fail/overflowing-lsh-1.rs | 19 + src/test/run-fail/overflowing-lsh-2.rs | 19 + src/test/run-fail/overflowing-lsh-3.rs | 19 + src/test/run-fail/overflowing-lsh-4.rs | 34 + src/test/run-fail/overflowing-mul.rs | 19 + src/test/run-fail/overflowing-rsh-1.rs | 19 + src/test/run-fail/overflowing-rsh-2.rs | 19 + src/test/run-fail/overflowing-rsh-3.rs | 19 + src/test/run-fail/overflowing-rsh-4.rs | 34 + src/test/run-fail/overflowing-sub.rs | 19 + src/test/run-fail/panic-arg.rs | 2 +- src/test/run-fail/panic-macro-any-wrapped.rs | 5 +- src/test/run-fail/result-get-panic.rs | 2 +- src/test/run-fail/rt-set-exit-status-panic.rs | 6 +- .../run-fail/rt-set-exit-status-panic2.rs | 12 +- src/test/run-fail/rt-set-exit-status.rs | 6 +- .../run-fail/test-should-fail-bad-message.rs | 2 +- src/test/run-fail/test-tasks-invalid-value.rs | 4 +- src/test/run-fail/unique-panic.rs | 5 +- src/test/run-fail/unwind-rec.rs | 4 +- src/test/run-fail/unwind-rec2.rs | 6 +- src/test/run-fail/unwind-unique.rs | 5 +- src/test/run-fail/vec-overrun.rs | 4 +- src/test/run-fail/while-body-panics.rs | 2 +- .../allow-non-lint-warnings-cmdline/Makefile | 1 - .../allow-non-lint-warnings-cmdline/foo.rs | 2 +- .../allow-warnings-cmdline-stability/Makefile | 4 - .../allow-warnings-cmdline-stability/foo.rs | 2 + src/test/run-make/bare-outfile/Makefile | 4 + src/test/run-make/bare-outfile/foo.rs | 12 + .../create_and_compile.rs | 18 +- src/test/run-make/compiler-lookup-paths/c.rs | 1 - src/test/run-make/crate-name-priority/foo1.rs | 1 - src/test/run-make/debug-assertions/Makefile | 21 + src/test/run-make/debug-assertions/debug.rs | 42 + .../extern-flag-disambiguates/Makefile | 1 - src/test/run-make/extern-flag-fun/bar.rs | 1 - src/test/run-make/extern-fn-reachable/main.rs | 13 +- .../extern-fn-with-packed-struct/test.rs | 2 +- .../extern-overrides-distribution/main.rs | 1 - .../graphviz-flowgraph/f07.dot-expected.dot | 6 +- src/test/run-make/graphviz-flowgraph/f07.rs | 2 + .../graphviz-flowgraph/f13.dot-expected.dot | 12 +- .../graphviz-flowgraph/f20.dot-expected.dot | 18 +- src/test/run-make/graphviz-flowgraph/f20.rs | 4 +- .../interdependent-c-libraries/Makefile | 1 - .../interdependent-c-libraries/bar.rs | 1 - .../intrinsic-unreachable/exit-ret.rs | 2 +- .../intrinsic-unreachable/exit-unreachable.rs | 4 +- src/test/run-make/issue-14500/Makefile | 1 - src/test/run-make/issue-19371/foo.rs | 14 +- src/test/run-make/issue-7349/foo.rs | 8 +- src/test/run-make/libs-and-bins/Makefile | 1 - src/test/run-make/link-path-order/Makefile | 1 - src/test/run-make/link-path-order/main.rs | 4 +- .../run-make/linkage-attr-on-static/Makefile | 1 - .../run-make/lto-syntax-extension/main.rs | 2 + src/test/run-make/manual-link/Makefile | 1 - .../many-crates-but-no-match/Makefile | 2 +- .../metadata-flag-frobs-symbols/foo.rs | 4 +- .../mismatching-target-triples/bar.rs | 0 .../mismatching-target-triples/foo.rs | 0 .../missing-crate-dependency/Makefile | 2 +- src/test/run-make/mixing-deps/both.rs | 2 +- src/test/run-make/mixing-deps/dylib.rs | 2 +- src/test/run-make/mixing-deps/prog.rs | 2 +- src/test/run-make/mixing-formats/baz2.rs | 1 - src/test/run-make/no-duplicate-libs/bar.rs | 2 +- src/test/run-make/no-duplicate-libs/foo.rs | 2 +- .../run-make/obey-crate-type-flag/test.rs | 1 - .../run-make/output-with-hyphens/Makefile | 6 + .../output-with-hyphens/foo-bar.rs} | 5 +- .../pretty-expanded-hygiene/input.pp.rs | 0 .../run-make/pretty-expanded-hygiene/input.rs | 0 src/test/run-make/pretty-expanded/input.rs | 6 +- .../pretty-print-path-suffix/foo_method.pp | 2 +- .../pretty-print-path-suffix/input.rs | 2 +- .../run-make/rustdoc-default-impl/Makefile | 5 + .../rustdoc-default-impl/bar.rs} | 9 +- src/test/run-make/rustdoc-default-impl/foo.rs | 36 + .../rustdoc-extern-default-method/Makefile | 6 + .../rustdoc-extern-default-method/ext.rs | 21 + .../rustdoc-extern-default-method/lib.rs | 14 + .../run-make/rustdoc-extern-method/Makefile | 1 - .../run-make/rustdoc-extern-method/bar.rs | 2 + .../run-make/rustdoc-extern-method/foo.rs | 1 + .../run-make/rustdoc-negative-impl/Makefile | 1 - src/test/run-make/rustdoc-recursion/Makefile | 1 - src/test/run-make/rustdoc-recursion/foo.rs | 1 - src/test/run-make/rustdoc-smoke/foo.rs | 4 +- src/test/run-make/rustdoc-src-links/Makefile | 5 + src/test/run-make/rustdoc-src-links/foo.rs | 43 + .../run-make/rustdoc-src-links/qux/mod.rs | 39 + .../run-make/rustdoc-viewpath-self/Makefile | 1 - src/test/run-make/rustdoc-where/Makefile | 1 - src/test/run-make/save-analysis/foo.rs | 23 +- .../run-make/sepcomp-cci-copies/cci_lib.rs | 2 +- src/test/run-make/sepcomp-cci-copies/foo.rs | 8 +- src/test/run-make/sepcomp-separate/foo.rs | 6 +- src/test/run-make/simd-ffi/simd.rs | 0 .../run-make/symbols-are-reasonable/lib.rs | 4 +- src/test/run-make/target-cpu-native/Makefile | 5 + .../run-make/target-cpu-native/foo.rs} | 3 +- src/test/run-make/target-specs/foo.rs | 2 +- src/test/run-make/tools.mk | 1 - .../run-make/unicode-input/multiple_files.rs | 18 +- .../run-make/unicode-input/span_length.rs | 22 +- src/test/run-make/volatile-intrinsics/main.rs | 4 +- .../run-make/weird-output-filenames/Makefile | 3 + src/test/run-pass-fulldeps/compiler-calls.rs | 19 +- .../run-pass-fulldeps/create-dir-all-bare.rs | 25 + src/test/run-pass-fulldeps/derive-totalsum.rs | 59 + src/test/run-pass-fulldeps/issue-13560.rs | 4 +- .../run-pass-fulldeps/issue-15778-pass.rs | 19 + src/test/run-pass-fulldeps/issue-16822.rs | 4 +- src/test/run-pass-fulldeps/issue-16992.rs | 2 +- src/test/run-pass-fulldeps/issue-18502.rs | 2 +- .../issue-18763-quote-token-tree.rs | 6 +- src/test/run-pass-fulldeps/macro-crate.rs | 2 +- .../mbe_matching_test_macro.rs | 25 + src/test/run-pass-fulldeps/qquote.rs | 13 +- src/test/run-pass-fulldeps/quote-tokens.rs | 14 +- .../quote-unused-sp-no-warning.rs | 2 +- .../run-pass-fulldeps/rename-directory.rs | 41 + .../syntax-extension-with-dll-deps.rs | 2 +- .../cleanup-auto-borrow-obj.rs | 1 - src/test/run-pass-valgrind/cleanup-stdin.rs | 3 + src/test/run-pass-valgrind/dst-dtor-1.rs | 5 +- src/test/run-pass-valgrind/dst-dtor-2.rs | 7 +- src/test/run-pass/alias-uninit-value.rs | 6 +- .../run-pass/alloca-from-derived-tydesc.rs | 4 +- .../run-pass/anon-extern-mod-cross-crate-2.rs | 2 + src/test/run-pass/anon-extern-mod.rs | 4 + src/test/run-pass/anon-trait-static-method.rs | 2 +- src/test/run-pass/argument-passing.rs | 8 +- src/test/run-pass/arith-0.rs | 2 +- src/test/run-pass/arith-1.rs | 6 +- src/test/run-pass/arith-2.rs | 4 +- src/test/run-pass/arith-unsigned.rs | 2 + src/test/run-pass/artificial-block.rs | 4 +- src/test/run-pass/as-precedence.rs | 13 +- src/test/run-pass/asm-concat-src.rs | 2 + src/test/run-pass/asm-in-out-operand.rs | 6 +- src/test/run-pass/asm-out-assign.rs | 4 +- src/test/run-pass/assert-eq-macro-success.rs | 7 +- src/test/run-pass/assign-assign.rs | 6 +- src/test/run-pass/assignability-trait.rs | 12 +- src/test/run-pass/associated-types-basic.rs | 8 +- .../associated-types-binding-in-trait.rs | 2 + ...ssociated-types-binding-in-where-clause.rs | 12 +- src/test/run-pass/associated-types-bound.rs | 2 + src/test/run-pass/associated-types-cc.rs | 2 +- .../associated-types-conditional-dispatch.rs | 2 + .../associated-types-constant-type.rs | 22 +- ...ciated-types-doubleendediterator-object.rs | 7 +- ...ted-types-duplicate-binding-in-env-hrtb.rs | 2 + ...sociated-types-duplicate-binding-in-env.rs | 2 + .../associated-types-enum-field-named.rs | 2 + .../associated-types-enum-field-numbered.rs | 2 + src/test/run-pass/associated-types-eq-obj.rs | 4 +- .../associated-types-in-default-method.rs | 8 +- src/test/run-pass/associated-types-in-fn.rs | 8 +- .../associated-types-in-impl-generics.rs | 8 +- .../associated-types-in-inherent-method.rs | 8 +- .../run-pass/associated-types-issue-20220.rs | 2 + .../run-pass/associated-types-issue-20371.rs | 6 +- .../run-pass/associated-types-issue-21212.rs | 2 + .../associated-types-iterator-binding.rs | 4 +- .../associated-types-nested-projections.rs | 4 + ...iated-types-normalize-in-bounds-binding.rs | 3 + ...sociated-types-normalize-in-bounds-ufcs.rs | 2 + .../associated-types-normalize-in-bounds.rs | 2 + ...ociated-types-normalize-unifield-struct.rs | 6 +- ...om-type-param-via-bound-in-where-clause.rs | 111 + ...d-types-projection-bound-in-supertraits.rs | 4 +- ...ypes-projection-from-known-type-in-impl.rs | 2 + ...ociated-types-projection-in-object-type.rs | 2 + ...sociated-types-projection-in-supertrait.rs | 2 + ...ciated-types-projection-in-where-clause.rs | 2 + ...ed-path-with-trait-with-type-parameters.rs | 2 + .../associated-types-ref-from-struct.rs | 2 + .../associated-types-ref-in-struct-literal.rs | 6 +- ...ciated-types-region-erasure-issue-20582.rs | 2 + .../associated-types-resolve-lifetime.rs | 4 +- src/test/run-pass/associated-types-return.rs | 16 +- src/test/run-pass/associated-types-simple.rs | 8 +- src/test/run-pass/associated-types-stream.rs | 2 + .../associated-types-struct-field-named.rs | 6 +- .../associated-types-struct-field-numbered.rs | 6 +- .../run-pass/associated-types-sugar-path.rs | 10 +- .../astconv-cycle-between-trait-and-type.rs | 2 + src/test/run-pass/attr-before-view-item.rs | 4 +- src/test/run-pass/attr-before-view-item2.rs | 4 +- src/test/run-pass/attr-main-2.rs | 2 + src/test/run-pass/attr-main.rs | 2 + src/test/run-pass/attr-mix-new.rs | 2 + src/test/run-pass/attr-no-drop-flag-size.rs | 4 +- src/test/run-pass/attr-start.rs | 4 +- src/test/run-pass/attr.rs | 2 + src/test/run-pass/auto-encode.rs | 22 +- src/test/run-pass/auto-instantiate.rs | 2 +- src/test/run-pass/auto-loop.rs | 2 + .../run-pass/auto-ref-bounded-ty-param.rs | 2 +- src/test/run-pass/auto-ref-sliceable.rs | 4 +- src/test/run-pass/auto-ref.rs | 2 +- src/test/run-pass/autobind.rs | 4 +- .../autoderef-and-borrow-method-receiver.rs | 4 +- .../run-pass/autoderef-method-on-trait.rs | 12 +- .../run-pass/autoderef-method-priority.rs | 16 +- .../autoderef-method-twice-but-not-thrice.rs | 12 +- src/test/run-pass/autoderef-method-twice.rs | 12 +- src/test/run-pass/autoderef-method.rs | 12 +- .../autoref-intermediate-types-issue-3585.rs | 6 +- src/test/run-pass/backtrace-debuginfo-aux.rs | 21 + src/test/run-pass/backtrace-debuginfo.rs | 161 + src/test/run-pass/backtrace.rs | 10 +- .../run-pass/bare-fn-implements-fn-mut.rs | 1 - src/test/run-pass/big-literals.rs | 17 +- .../run-pass/binary-minus-without-space.rs | 2 + src/test/run-pass/bind-by-move.rs | 2 + .../bind-field-short-with-modifiers.rs | 4 +- src/test/run-pass/binops-issue-22743.rs | 32 + src/test/run-pass/binops.rs | 10 +- src/test/run-pass/bitv-perf-test.rs | 9 +- src/test/run-pass/bitwise.rs | 9 +- .../blind-item-mixed-crate-use-item.rs | 6 +- .../run-pass/blind-item-mixed-use-item.rs | 2 + src/test/run-pass/block-arg-call-as.rs | 8 +- src/test/run-pass/block-explicit-types.rs | 2 +- src/test/run-pass/block-expr-precedence.rs | 2 + src/test/run-pass/block-fn-coerce.rs | 6 +- src/test/run-pass/block-iter-1.rs | 4 +- src/test/run-pass/block-iter-2.rs | 2 +- src/test/run-pass/bool-not.rs | 2 + src/test/run-pass/bool.rs | 2 + .../run-pass/borrow-by-val-method-receiver.rs | 4 +- src/test/run-pass/borrow-tuple-fields.rs | 4 +- .../run-pass/borrowck-assign-to-subfield.rs | 6 +- src/test/run-pass/borrowck-binding-mutbl.rs | 6 +- .../borrowck-borrow-from-expr-block.rs | 10 +- .../borrowck-borrow-of-mut-base-ptr-safe.rs | 14 +- .../run-pass/borrowck-closures-two-imm.rs | 8 +- .../run-pass/borrowck-field-sensitivity.rs | 7 +- .../run-pass/borrowck-fixed-length-vecs.rs | 2 + .../run-pass/borrowck-freeze-frozen-mut.rs | 4 +- src/test/run-pass/borrowck-lend-args.rs | 10 +- .../borrowck-macro-interaction-issue-6304.rs | 8 +- .../run-pass/borrowck-move-by-capture-ok.rs | 7 +- src/test/run-pass/borrowck-mut-uniq.rs | 12 +- .../run-pass/borrowck-mut-vec-as-imm-slice.rs | 6 +- src/test/run-pass/borrowck-nested-calls.rs | 6 +- src/test/run-pass/borrowck-pat-enum.rs | 10 +- .../borrowck-pat-reassign-no-binding.rs | 2 + src/test/run-pass/borrowck-rvalues-mutable.rs | 10 +- .../borrowck-scope-of-deref-issue-4666.rs | 8 +- .../run-pass/borrowck-static-item-in-fn.rs | 2 + src/test/run-pass/borrowck-trait-lifetime.rs | 2 + src/test/run-pass/borrowck-uniq-via-ref.rs | 12 +- src/test/run-pass/borrowck-univariant-enum.rs | 6 +- src/test/run-pass/borrowck-use-mut-borrow.rs | 5 +- src/test/run-pass/borrowed-ptr-pattern-2.rs | 2 + src/test/run-pass/borrowed-ptr-pattern-3.rs | 4 +- .../borrowed-ptr-pattern-infallible.rs | 2 + .../run-pass/borrowed-ptr-pattern-option.rs | 4 +- src/test/run-pass/borrowed-ptr-pattern.rs | 2 + src/test/run-pass/box-new.rs | 2 + src/test/run-pass/box-of-array-of-drop-1.rs | 52 + src/test/run-pass/box-of-array-of-drop-2.rs | 52 + src/test/run-pass/break-value.rs | 4 +- src/test/run-pass/break.rs | 2 + src/test/run-pass/bug-7183-generics.rs | 8 +- src/test/run-pass/bug-7295.rs | 2 + ...ltin-superkinds-capabilities-transitive.rs | 2 + .../builtin-superkinds-capabilities-xc.rs | 4 +- .../builtin-superkinds-capabilities.rs | 4 +- .../builtin-superkinds-in-metadata.rs | 6 +- .../builtin-superkinds-phantom-typaram.rs | 2 + .../run-pass/builtin-superkinds-self-type.rs | 2 + .../run-pass/builtin-superkinds-simple.rs | 4 +- .../run-pass/builtin-superkinds-typaram.rs | 2 + .../run-pass/by-value-self-in-mut-slot.rs | 4 +- src/test/run-pass/byte-literals.rs | 15 +- src/test/run-pass/c-stack-as-value.rs | 4 + src/test/run-pass/c-stack-returning-int64.rs | 9 +- .../call-closure-from-overloaded-op.rs | 6 +- src/test/run-pass/can-copy-pod.rs | 4 +- .../cancel-clean-via-immediate-rvalue-ref.rs | 2 + .../capture-clauses-boxed-closures.rs | 3 +- .../capture-clauses-unboxed-closures.rs | 8 +- src/test/run-pass/capturing-logging.rs | 10 +- src/test/run-pass/cast-in-array-size.rs | 12 +- src/test/run-pass/cast-region-to-uint.rs | 4 +- src/test/run-pass/cast.rs | 6 +- src/test/run-pass/cci_borrow.rs | 4 +- src/test/run-pass/cci_capture_clause.rs | 2 + src/test/run-pass/cci_impl_exe.rs | 2 +- src/test/run-pass/cci_iter_exe.rs | 4 +- src/test/run-pass/cci_nested_exe.rs | 2 + src/test/run-pass/cci_no_inline_exe.rs | 2 +- src/test/run-pass/cell-does-not-clone.rs | 4 +- src/test/run-pass/cfg-attr-cfg.rs | 2 + src/test/run-pass/cfg-attr-crate.rs | 2 + src/test/run-pass/cfg-family.rs | 2 + src/test/run-pass/cfg-macros-foo.rs | 2 + src/test/run-pass/cfg-macros-notfoo.rs | 2 + src/test/run-pass/cfg-match-arm.rs | 2 + src/test/run-pass/cfg-target-family.rs | 2 + src/test/run-pass/cfg_inner_static.rs | 2 + src/test/run-pass/cfgs-on-items.rs | 12 +- src/test/run-pass/char.rs | 2 + src/test/run-pass/check-static-mut-slices.rs | 4 +- .../check-static-recursion-foreign.rs | 4 +- src/test/run-pass/check-static-slice.rs | 28 +- src/test/run-pass/child-outlives-parent.rs | 8 +- .../class-cast-to-trait-cross-crate-2.rs | 2 +- .../class-cast-to-trait-multiple-types.rs | 24 +- src/test/run-pass/class-cast-to-trait.rs | 12 +- src/test/run-pass/class-dtor.rs | 10 +- src/test/run-pass/class-exports.rs | 7 +- .../class-impl-very-parameterized-trait.rs | 30 +- .../class-implement-trait-cross-crate.rs | 6 +- src/test/run-pass/class-implement-traits.rs | 6 +- src/test/run-pass/class-method-cross-crate.rs | 6 +- .../run-pass/class-methods-cross-crate.rs | 8 +- src/test/run-pass/class-methods.rs | 18 +- .../class-poly-methods-cross-crate.rs | 2 + src/test/run-pass/class-poly-methods.rs | 18 +- src/test/run-pass/class-separate-impl.rs | 14 +- src/test/run-pass/class-str-field.rs | 2 + src/test/run-pass/class-typarams.rs | 16 +- src/test/run-pass/classes-cross-crate.rs | 2 + src/test/run-pass/classes-self-referential.rs | 2 + .../run-pass/classes-simple-cross-crate.rs | 6 +- src/test/run-pass/classes-simple-method.rs | 12 +- src/test/run-pass/classes-simple.rs | 12 +- src/test/run-pass/classes.rs | 6 +- src/test/run-pass/cleanup-arm-conditional.rs | 11 +- .../cleanup-rvalue-during-if-and-while.rs | 4 +- ...nup-rvalue-temp-during-incomplete-alloc.rs | 10 +- src/test/run-pass/cleanup-shortcircuit.rs | 5 +- src/test/run-pass/clone-with-exterior.rs | 14 +- .../closure-bounds-can-capture-chan.rs | 2 + src/test/run-pass/closure-inference.rs | 2 + src/test/run-pass/closure-inference2.rs | 2 + src/test/run-pass/closure-reform.rs | 3 +- src/test/run-pass/cmp-default.rs | 6 +- src/test/run-pass/coerce-expect-unsized.rs | 41 +- src/test/run-pass/coerce-match-calls.rs | 6 +- src/test/run-pass/coerce-match.rs | 10 +- .../run-pass/coerce-overloaded-autoderef.rs | 2 + .../run-pass/coerce-reborrow-imm-ptr-arg.rs | 8 +- .../run-pass/coerce-reborrow-imm-ptr-rcvr.rs | 8 +- .../run-pass/coerce-reborrow-imm-vec-arg.rs | 8 +- .../run-pass/coerce-reborrow-imm-vec-rcvr.rs | 8 +- .../run-pass/coerce-reborrow-mut-ptr-arg.rs | 4 +- .../run-pass/coerce-reborrow-mut-ptr-rcvr.rs | 4 +- .../run-pass/coerce-reborrow-mut-vec-arg.rs | 8 +- .../run-pass/coerce-reborrow-mut-vec-rcvr.rs | 6 +- src/test/run-pass/coerce-unify-return.rs | 2 + src/test/run-pass/coherence-bigint-int.rs | 6 +- src/test/run-pass/coherence-bigint-vecint.rs | 6 +- src/test/run-pass/coherence-blanket.rs | 6 +- .../coherence-covered-type-parameter.rs | 6 +- src/test/run-pass/coherence-impl-in-fn.rs | 6 +- .../coherence-iterator-vec-any-elem.rs | 6 +- src/test/run-pass/coherence-iterator-vec.rs | 6 +- .../run-pass/coherence-multidispatch-tuple.rs | 12 +- .../run-pass/coherence-negative-impls-safe.rs | 2 + src/test/run-pass/coherence-where-clause.rs | 2 +- src/test/run-pass/coherence_copy_like.rs | 29 + src/test/run-pass/colorful-write-macros.rs | 11 +- src/test/run-pass/comm.rs | 8 +- src/test/run-pass/compare-generic-enums.rs | 6 +- src/test/run-pass/complex.rs | 12 +- src/test/run-pass/concat.rs | 6 +- src/test/run-pass/conditional-compile-arch.rs | 2 + src/test/run-pass/conditional-compile.rs | 19 +- .../run-pass/conditional-debug-macro-off.rs | 6 +- src/test/run-pass/const-autoderef.rs | 2 + src/test/run-pass/const-big-enum.rs | 2 + src/test/run-pass/const-binops.rs | 36 +- .../run-pass/const-block-cross-crate-fn.rs | 2 + .../const-block-item-macro-codegen.rs | 10 +- src/test/run-pass/const-block-item.rs | 18 +- src/test/run-pass/const-block.rs | 6 +- src/test/run-pass/const-bound.rs | 9 +- src/test/run-pass/const-cast-ptr-int.rs | 2 + src/test/run-pass/const-cast.rs | 4 + src/test/run-pass/const-const.rs | 6 +- src/test/run-pass/const-contents.rs | 10 +- src/test/run-pass/const-cross-crate-const.rs | 6 +- src/test/run-pass/const-cross-crate-extern.rs | 2 + src/test/run-pass/const-deref.rs | 6 +- src/test/run-pass/const-enum-byref-self.rs | 4 +- src/test/run-pass/const-enum-byref.rs | 4 +- src/test/run-pass/const-enum-cast.rs | 10 +- src/test/run-pass/const-enum-ptr.rs | 4 +- src/test/run-pass/const-enum-struct.rs | 2 + src/test/run-pass/const-enum-struct2.rs | 2 + src/test/run-pass/const-enum-structlike.rs | 4 +- src/test/run-pass/const-enum-tuple.rs | 2 + src/test/run-pass/const-enum-tuple2.rs | 2 + src/test/run-pass/const-enum-tuplestruct.rs | 2 + src/test/run-pass/const-enum-tuplestruct2.rs | 2 + src/test/run-pass/const-enum-vec-index.rs | 4 +- src/test/run-pass/const-enum-vec-ptr.rs | 4 +- src/test/run-pass/const-enum-vector.rs | 4 +- .../const-expr-in-fixed-length-vec.rs | 6 +- src/test/run-pass/const-expr-in-vec-repeat.rs | 4 +- src/test/run-pass/const-extern-function.rs | 2 + .../run-pass/const-fields-and-indexing.rs | 18 +- src/test/run-pass/const-fn-val.rs | 8 +- src/test/run-pass/const-negative.rs | 4 +- src/test/run-pass/const-nullary-enum.rs | 2 + .../run-pass/const-nullary-univariant-enum.rs | 8 +- .../run-pass/const-region-ptrs-noncopy.rs | 4 +- src/test/run-pass/const-region-ptrs.rs | 4 +- src/test/run-pass/const-str-ptr.rs | 2 + src/test/run-pass/const-struct-offsets.rs | 2 + src/test/run-pass/const-struct.rs | 2 +- src/test/run-pass/const-tuple-struct.rs | 4 +- src/test/run-pass/const-unit-struct.rs | 2 + src/test/run-pass/const-vec-of-fns.rs | 2 + src/test/run-pass/const-vec-syntax.rs | 4 +- src/test/run-pass/const-vecs-and-slices.rs | 8 +- src/test/run-pass/const.rs | 2 +- src/test/run-pass/consts-in-patterns.rs | 8 +- src/test/run-pass/copy-out-of-array-1.rs | 5 +- src/test/run-pass/core-run-destroy.rs | 7 +- src/test/run-pass/crate-leading-sep.rs | 2 + .../crate-method-reexport-grrrrrrr.rs | 4 +- src/test/run-pass/crate-name-attr-used.rs | 6 +- src/test/run-pass/cross-crate-const-pat.rs | 2 + .../cross-crate-newtype-struct-pat.rs | 2 + src/test/run-pass/cycle-generic-bound.rs | 20 + src/test/run-pass/cycle-trait-type-trait.rs | 25 + .../run-pass/dead-code-leading-underscore.rs | 8 +- src/test/run-pass/deep.rs | 6 +- src/test/run-pass/default-method-parsing.rs | 4 +- src/test/run-pass/default-method-simple.rs | 2 +- .../default-method-supertrait-vtable.rs | 12 +- src/test/run-pass/deprecated-derive.rs | 15 + src/test/run-pass/deref-lval.rs | 2 +- src/test/run-pass/deref-mut-on-ref.rs | 6 +- src/test/run-pass/deref-on-ref.rs | 6 +- src/test/run-pass/deref-rc.rs | 2 + src/test/run-pass/deref.rs | 6 +- src/test/run-pass/derive-no-std.rs | 4 +- .../run-pass/deriving-associated-types.rs | 210 ++ src/test/run-pass/deriving-bounds.rs | 4 +- src/test/run-pass/deriving-clone-enum.rs | 2 + .../run-pass/deriving-clone-generic-enum.rs | 4 +- .../run-pass/deriving-clone-generic-struct.rs | 2 + .../deriving-clone-generic-tuple-struct.rs | 2 + src/test/run-pass/deriving-clone-struct.rs | 6 +- .../run-pass/deriving-clone-tuple-struct.rs | 2 + .../run-pass/deriving-cmp-generic-enum.rs | 2 + .../deriving-cmp-generic-struct-enum.rs | 2 + .../run-pass/deriving-cmp-generic-struct.rs | 2 + .../deriving-cmp-generic-tuple-struct.rs | 2 + .../run-pass/deriving-cmp-shortcircuit.rs | 4 +- src/test/run-pass/deriving-default-box.rs | 5 +- .../deriving-encodable-decodable-box.rs | 7 +- ...riving-encodable-decodable-cell-refcell.rs | 6 +- .../run-pass/deriving-encodable-decodable.rs | 14 +- .../run-pass/deriving-enum-single-variant.rs | 4 +- .../run-pass/deriving-eq-ord-boxed-slice.rs | 8 +- src/test/run-pass/deriving-global.rs | 8 +- src/test/run-pass/deriving-hash.rs | 8 +- src/test/run-pass/deriving-in-fn.rs | 2 +- src/test/run-pass/deriving-in-macro.rs | 2 + src/test/run-pass/deriving-meta-multiple.rs | 7 +- src/test/run-pass/deriving-meta.rs | 7 +- src/test/run-pass/deriving-primitive.rs | 8 +- src/test/run-pass/deriving-rand.rs | 8 +- ...deriving-self-lifetime-totalord-totaleq.rs | 2 +- src/test/run-pass/deriving-self-lifetime.rs | 2 +- src/test/run-pass/deriving-show-2.rs | 12 +- src/test/run-pass/deriving-show.rs | 8 +- .../run-pass/deriving-via-extension-enum.rs | 2 +- .../deriving-via-extension-hash-enum.rs | 7 +- .../deriving-via-extension-hash-struct.rs | 9 +- ...-via-extension-struct-like-enum-variant.rs | 2 +- .../deriving-via-extension-struct-tuple.rs | 2 +- .../run-pass/deriving-via-extension-struct.rs | 6 +- .../deriving-via-extension-type-params.rs | 5 +- src/test/run-pass/destructure-array-1.rs | 4 + src/test/run-pass/die-macro.rs | 4 +- src/test/run-pass/discrim-explicit-23030.rs | 156 + src/test/run-pass/div-mod.rs | 6 +- src/test/run-pass/double-ref.rs | 30 +- src/test/run-pass/drop-flag-sanity-check.rs | 69 + .../run-pass/drop-flag-skip-sanity-check.rs | 69 + src/test/run-pass/drop-on-empty-block-exit.rs | 4 +- src/test/run-pass/drop-on-ret.rs | 4 +- src/test/run-pass/drop-struct-as-object.rs | 10 +- src/test/run-pass/drop-trait-enum.rs | 8 +- src/test/run-pass/drop-trait.rs | 2 +- src/test/run-pass/drop-uninhabited-enum.rs | 2 + .../run-pass/drop-with-type-ascription-1.rs | 5 +- .../run-pass/drop-with-type-ascription-2.rs | 7 +- src/test/run-pass/dropck_tarena_sound_drop.rs | 4 +- src/test/run-pass/dst-coercions.rs | 2 + src/test/run-pass/dst-deref-mut.rs | 16 +- src/test/run-pass/dst-deref.rs | 14 +- src/test/run-pass/dst-index.rs | 14 +- src/test/run-pass/dst-raw.rs | 12 +- src/test/run-pass/dst-struct-sole.rs | 16 +- src/test/run-pass/dst-struct.rs | 39 +- src/test/run-pass/dst-trait.rs | 20 +- src/test/run-pass/dupe-first-attr.rc | 5 + src/test/run-pass/duplicated-external-mods.rs | 3 +- src/test/run-pass/early-ret-binop-add.rs | 7 +- src/test/run-pass/early-vtbl-resolution.rs | 6 +- src/test/run-pass/else-if.rs | 2 + .../run-pass/empty-allocation-non-null.rs | 13 +- .../empty-allocation-rvalue-non-null.rs | 5 +- src/test/run-pass/empty-mutable-vec.rs | 4 +- src/test/run-pass/empty-tag.rs | 4 +- src/test/run-pass/enum-alignment.rs | 8 +- src/test/run-pass/enum-clike-ffi-as-int.rs | 6 +- src/test/run-pass/enum-discr.rs | 6 +- src/test/run-pass/enum-discrim-autosizing.rs | 2 + .../run-pass/enum-discrim-manual-sizing.rs | 10 +- .../run-pass/enum-discrim-range-overflow.rs | 2 + src/test/run-pass/enum-discrim-width-stuff.rs | 2 +- src/test/run-pass/enum-disr-val-pretty.rs | 6 +- src/test/run-pass/enum-export-inheritance.rs | 2 + src/test/run-pass/enum-null-pointer-opt.rs | 33 +- .../enum-nullable-const-null-with-fields.rs | 4 +- .../enum-nullable-simplifycfg-misopt.rs | 2 + src/test/run-pass/enum-size-variance.rs | 14 +- src/test/run-pass/enum-variants.rs | 2 + src/test/run-pass/enum-vec-initializer.rs | 10 +- src/test/run-pass/env-home-dir.rs | 13 +- src/test/run-pass/env-vars.rs | 2 + src/test/run-pass/eq-multidispatch.rs | 2 + src/test/run-pass/estr-uniq.rs | 2 + src/test/run-pass/evec-internal.rs | 10 +- src/test/run-pass/evec-slice.rs | 12 +- src/test/run-pass/exec-env.rs | 2 + src/test/run-pass/explicit-i-suffix.rs | 6 +- src/test/run-pass/explicit-self-closures.rs | 6 +- src/test/run-pass/explicit-self-generic.rs | 10 +- .../run-pass/explicit-self-objects-uniq.rs | 4 +- src/test/run-pass/explicit-self.rs | 12 +- src/test/run-pass/explicit_self_xcrate_exe.rs | 2 + src/test/run-pass/exponential-notation.rs | 4 + src/test/run-pass/export-abstract-tag.rs | 2 + .../run-pass/export-glob-imports-target.rs | 4 +- src/test/run-pass/export-multi.rs | 3 +- src/test/run-pass/export-non-interference3.rs | 1 - src/test/run-pass/export-tag-variant.rs | 2 + src/test/run-pass/export-unexported-dep.rs | 31 - src/test/run-pass/expr-block-fn.rs | 4 +- .../run-pass/expr-block-generic-unique2.rs | 6 +- src/test/run-pass/expr-block-generic.rs | 6 +- src/test/run-pass/expr-block-slot.rs | 6 +- src/test/run-pass/expr-block-unique.rs | 4 +- src/test/run-pass/expr-block.rs | 4 +- src/test/run-pass/expr-copy.rs | 6 +- src/test/run-pass/expr-empty-ret.rs | 2 + src/test/run-pass/expr-fn.rs | 16 +- src/test/run-pass/expr-if-generic.rs | 6 +- src/test/run-pass/expr-if-panic-all.rs | 2 + src/test/run-pass/expr-if-panic.rs | 2 + src/test/run-pass/expr-if-struct.rs | 8 +- src/test/run-pass/expr-if-unique.rs | 4 +- src/test/run-pass/expr-if.rs | 2 + .../run-pass/expr-match-generic-unique1.rs | 2 + .../run-pass/expr-match-generic-unique2.rs | 6 +- src/test/run-pass/expr-match-generic.rs | 6 +- src/test/run-pass/expr-match-panic-all.rs | 2 + src/test/run-pass/expr-match-panic.rs | 2 + src/test/run-pass/expr-match-struct.rs | 8 +- src/test/run-pass/expr-match-unique.rs | 4 +- src/test/run-pass/expr-match.rs | 2 + src/test/run-pass/expr-scope.rs | 2 + src/test/run-pass/ext-expand-inner-exprs.rs | 2 + src/test/run-pass/exterior.rs | 6 +- src/test/run-pass/extern-1.rs | 2 + src/test/run-pass/extern-call-deep.rs | 2 + src/test/run-pass/extern-call-deep2.rs | 8 +- src/test/run-pass/extern-call-direct.rs | 4 +- src/test/run-pass/extern-call-indirect.rs | 2 + src/test/run-pass/extern-call-scrub.rs | 6 +- .../extern-calling-convention-test.rs | 2 + .../extern-compare-with-return-type.rs | 15 +- src/test/run-pass/extern-crosscrate.rs | 2 + src/test/run-pass/extern-foreign-crate.rs | 4 +- src/test/run-pass/extern-methods.rs | 42 + src/test/run-pass/extern-mod-abi.rs | 2 + src/test/run-pass/extern-mod-ordering-exe.rs | 2 + src/test/run-pass/extern-mod-syntax.rs | 2 +- src/test/run-pass/extern-pass-TwoU16s.rs | 2 +- src/test/run-pass/extern-pass-TwoU32s.rs | 2 +- src/test/run-pass/extern-pass-TwoU64s.rs | 2 +- src/test/run-pass/extern-pass-TwoU8s.rs | 2 +- src/test/run-pass/extern-pass-char.rs | 4 +- src/test/run-pass/extern-pass-double.rs | 2 + src/test/run-pass/extern-pass-empty.rs | 2 + src/test/run-pass/extern-pass-u32.rs | 4 +- src/test/run-pass/extern-pass-u64.rs | 4 +- src/test/run-pass/extern-pub.rs | 2 + src/test/run-pass/extern-return-TwoU16s.rs | 2 + src/test/run-pass/extern-return-TwoU32s.rs | 2 + src/test/run-pass/extern-return-TwoU64s.rs | 2 + src/test/run-pass/extern-return-TwoU8s.rs | 2 + src/test/run-pass/extern-rust.rs | 2 + src/test/run-pass/extern-stress.rs | 49 - src/test/run-pass/extern-take-value.rs | 2 + src/test/run-pass/extern-yield.rs | 48 - .../run-pass/extoption_env-not-defined.rs | 2 + src/test/run-pass/fact.rs | 4 +- src/test/run-pass/field-destruction-order.rs | 2 + src/test/run-pass/filter-block-view-items.rs | 2 + src/test/run-pass/fixed_length_copy.rs | 2 + src/test/run-pass/fixup-deref-mut.rs | 8 +- src/test/run-pass/float-nan.rs | 4 + src/test/run-pass/float2.rs | 2 + src/test/run-pass/floatlits.rs | 2 + src/test/run-pass/fn-abi.rs | 2 + src/test/run-pass/fn-bare-assign.rs | 6 +- src/test/run-pass/fn-bare-coerce-to-block.rs | 2 + src/test/run-pass/fn-bare-size.rs | 4 +- src/test/run-pass/fn-bare-spawn.rs | 4 +- src/test/run-pass/fn-coerce-field.rs | 2 + src/test/run-pass/fn-item-type-cast.rs | 8 +- src/test/run-pass/fn-item-type-coerce.rs | 8 +- src/test/run-pass/fn-lval.rs | 6 +- .../run-pass/fn-pattern-expected-type-2.rs | 2 +- src/test/run-pass/fn-pattern-expected-type.rs | 4 +- src/test/run-pass/fn-type-infer.rs | 2 + src/test/run-pass/for-destruct.rs | 4 +- src/test/run-pass/for-loop-goofiness.rs | 5 +- src/test/run-pass/for-loop-into-iterator.rs | 2 + src/test/run-pass/for-loop-no-std.rs | 8 +- src/test/run-pass/for-loop-panic.rs | 4 +- .../foreach-external-iterators-break.rs | 2 + ...xternal-iterators-hashmap-break-restart.rs | 4 + .../foreach-external-iterators-hashmap.rs | 4 + .../foreach-external-iterators-loop.rs | 2 + .../foreach-external-iterators-nested.rs | 2 + .../run-pass/foreach-external-iterators.rs | 2 + src/test/run-pass/foreach-nested.rs | 10 +- src/test/run-pass/foreach-put-structured.rs | 10 +- .../run-pass/foreach-simple-outer-slot.rs | 6 +- src/test/run-pass/foreign-call-no-runtime.rs | 5 +- src/test/run-pass/foreign-dupe.rs | 4 + src/test/run-pass/foreign-fn-linkname.rs | 11 +- src/test/run-pass/foreign-fn-with-byval.rs | 4 +- src/test/run-pass/foreign-mod-unused-const.rs | 5 +- src/test/run-pass/foreign-no-abi.rs | 4 + src/test/run-pass/foreign-struct.rs | 2 + src/test/run-pass/foreign2.rs | 5 +- src/test/run-pass/format-nan.rs | 3 +- src/test/run-pass/format-no-std.rs | 8 +- src/test/run-pass/format-ref-cell.rs | 2 + src/test/run-pass/fsu-moves-and-copies.rs | 20 +- src/test/run-pass/fun-call-variants.rs | 10 +- src/test/run-pass/fun-indirect-call.rs | 8 +- .../run-pass/func-arg-incomplete-pattern.rs | 14 +- src/test/run-pass/func-arg-ref-pattern.rs | 12 +- src/test/run-pass/func-arg-wild-pattern.rs | 4 +- src/test/run-pass/functional-struct-upd.rs | 4 +- src/test/run-pass/generic-alias-unique.rs | 4 +- ...generic-default-type-params-cross-crate.rs | 10 +- .../run-pass/generic-default-type-params.rs | 10 +- src/test/run-pass/generic-derived-type.rs | 2 +- src/test/run-pass/generic-exterior-unique.rs | 6 +- src/test/run-pass/generic-extern-mangle.rs | 12 +- src/test/run-pass/generic-fn-infer.rs | 4 +- src/test/run-pass/generic-fn-twice.rs | 4 +- src/test/run-pass/generic-fn.rs | 6 +- src/test/run-pass/generic-ivec-leak.rs | 2 + src/test/run-pass/generic-newtype-struct.rs | 2 + src/test/run-pass/generic-object.rs | 10 +- src/test/run-pass/generic-recursive-tag.rs | 10 +- src/test/run-pass/generic-static-methods.rs | 4 +- src/test/run-pass/generic-tag-corruption.rs | 2 + src/test/run-pass/generic-tag-local.rs | 2 + src/test/run-pass/generic-tag-match.rs | 2 +- src/test/run-pass/generic-tag-values.rs | 6 +- src/test/run-pass/generic-tag.rs | 6 +- src/test/run-pass/generic-temporary.rs | 10 +- src/test/run-pass/generic-type-synonym.rs | 2 + src/test/run-pass/generic-type.rs | 4 +- src/test/run-pass/generic-unique.rs | 4 +- src/test/run-pass/getopts_ref.rs | 4 + src/test/run-pass/global-scope.rs | 6 +- src/test/run-pass/guards-not-exhaustive.rs | 8 +- src/test/run-pass/guards.rs | 10 +- src/test/run-pass/hashmap-memory.rs | 18 +- .../hrtb-binder-levels-in-object-types.rs | 6 +- .../hrtb-debruijn-object-types-in-closures.rs | 4 +- .../run-pass/hrtb-fn-like-trait-object.rs | 4 +- src/test/run-pass/hrtb-fn-like-trait.rs | 4 +- src/test/run-pass/hrtb-opt-in-copy.rs | 6 +- src/test/run-pass/hrtb-parse.rs | 2 + .../hrtb-precedence-of-plus-where-clause.rs | 10 +- src/test/run-pass/hrtb-precedence-of-plus.rs | 12 +- src/test/run-pass/hrtb-resolve-lifetime.rs | 4 +- .../hrtb-trait-object-paren-notation.rs | 2 + .../hrtb-trait-object-passed-to-closure.rs | 8 +- .../run-pass/hrtb-unboxed-closure-trait.rs | 4 +- src/test/run-pass/huge-largest-array.rs | 2 + src/test/run-pass/hygiene-dodging-1.rs | 4 +- src/test/run-pass/hygienic-labels-in-let.rs | 8 +- src/test/run-pass/hygienic-labels.rs | 2 + src/test/run-pass/i32-sub.rs | 4 +- src/test/run-pass/i8-incr.rs | 10 +- src/test/run-pass/if-bot.rs | 2 +- src/test/run-pass/if-check.rs | 10 +- src/test/run-pass/if-let.rs | 8 +- src/test/run-pass/if-ret.rs | 2 + src/test/run-pass/ifmt.rs | 10 +- src/test/run-pass/ignore-all-the-things.rs | 7 +- src/test/run-pass/impl-implicit-trait.rs | 4 +- .../run-pass/impl-inherent-non-conflict.rs | 33 + .../impl-inherent-prefer-over-trait.rs | 40 + .../run-pass/impl-not-adjacent-to-type.rs | 26 + src/test/run-pass/impl-privacy-xc-1.rs | 2 + .../import-crate-with-invalid-spans.rs | 22 + src/test/run-pass/import-from.rs | 3 +- src/test/run-pass/import-glob-crate.rs | 2 + src/test/run-pass/import-in-block.rs | 2 + src/test/run-pass/import-trailing-comma.rs | 3 +- src/test/run-pass/import.rs | 2 +- src/test/run-pass/import2.rs | 1 - src/test/run-pass/import3.rs | 1 - src/test/run-pass/import4.rs | 1 - src/test/run-pass/import5.rs | 1 - src/test/run-pass/import6.rs | 1 - src/test/run-pass/import7.rs | 1 - src/test/run-pass/import8.rs | 3 +- .../inconsistent-lifetime-mismatch.rs | 2 + .../infer-container-across-object-cast.rs | 59 - src/test/run-pass/infer-fn-tail-expr.rs | 4 +- .../inferred-suffix-in-pattern-range.rs | 2 + src/test/run-pass/infinite-loops.rs | 2 +- .../run-pass/inherent-trait-method-order.rs | 3 +- src/test/run-pass/init-large-type.rs | 8 +- src/test/run-pass/init-res-into-things.rs | 10 +- src/test/run-pass/inner-attrs-on-impl.rs | 2 + src/test/run-pass/inner-static.rs | 2 + src/test/run-pass/instantiable.rs | 4 +- src/test/run-pass/int.rs | 4 +- src/test/run-pass/integer-literal-radix.rs | 2 + .../integer-literal-suffix-inference-2.rs | 3 +- .../integer-literal-suffix-inference-3.rs | 1 - .../integer-literal-suffix-inference.rs | 6 +- .../into-iterator-type-inference-shift.rs | 8 +- src/test/run-pass/intrinsic-alignment.rs | 38 +- src/test/run-pass/intrinsic-assume.rs | 5 +- src/test/run-pass/intrinsic-atomics-cc.rs | 2 + src/test/run-pass/intrinsic-atomics.rs | 4 +- src/test/run-pass/intrinsic-move-val.rs | 13 +- src/test/run-pass/intrinsic-return-address.rs | 9 +- src/test/run-pass/intrinsic-uninit.rs | 4 +- src/test/run-pass/intrinsic-unreachable.rs | 6 +- src/test/run-pass/intrinsics-integer.rs | 159 +- src/test/run-pass/intrinsics-math.rs | 9 +- src/test/run-pass/invoke-external-foreign.rs | 2 + src/test/run-pass/irrefutable-unit.rs | 2 + src/test/run-pass/issue-10025.rs | 2 + src/test/run-pass/issue-10028.rs | 4 +- src/test/run-pass/issue-10031.rs | 2 + src/test/run-pass/issue-10228.rs | 2 + src/test/run-pass/issue-10392.rs | 6 +- src/test/run-pass/issue-10456.rs | 2 + src/test/run-pass/issue-10626.rs | 2 + src/test/run-pass/issue-10638.rs | 2 + src/test/run-pass/issue-10682.rs | 4 +- src/test/run-pass/issue-10683.rs | 2 + src/test/run-pass/issue-10714.rs | 2 + src/test/run-pass/issue-10718.rs | 2 + src/test/run-pass/issue-10734.rs | 4 +- src/test/run-pass/issue-10763.rs | 2 + src/test/run-pass/issue-10764.rs | 2 + src/test/run-pass/issue-10767.rs | 2 + src/test/run-pass/issue-10802.rs | 6 +- src/test/run-pass/issue-10806.rs | 12 +- src/test/run-pass/issue-10853.rs | 2 + src/test/run-pass/issue-10902.rs | 2 + src/test/run-pass/issue-11085.rs | 10 +- src/test/run-pass/issue-1112.rs | 24 +- src/test/run-pass/issue-11205.rs | 24 +- src/test/run-pass/issue-11224.rs | 4 +- src/test/run-pass/issue-11225-1.rs | 4 +- src/test/run-pass/issue-11225-2.rs | 4 +- src/test/run-pass/issue-11267.rs | 6 +- src/test/run-pass/issue-11384.rs | 2 + src/test/run-pass/issue-11508.rs | 2 +- src/test/run-pass/issue-11529.rs | 4 +- src/test/run-pass/issue-11552.rs | 4 +- src/test/run-pass/issue-11577.rs | 6 +- src/test/run-pass/issue-11592.rs | 20 + src/test/run-pass/issue-11612.rs | 2 + src/test/run-pass/issue-11677.rs | 9 +- src/test/run-pass/issue-11709.rs | 4 +- src/test/run-pass/issue-11736.rs | 9 +- src/test/run-pass/issue-11820.rs | 21 + src/test/run-pass/issue-11869.rs | 2 + src/test/run-pass/issue-11881.rs | 17 +- src/test/run-pass/issue-11940.rs | 2 + src/test/run-pass/issue-11958.rs | 7 +- src/test/run-pass/issue-12133-1.rs | 6 +- src/test/run-pass/issue-12133-2.rs | 6 +- src/test/run-pass/issue-12133-3.rs | 4 +- src/test/run-pass/issue-12285.rs | 2 + src/test/run-pass/issue-1251.rs | 4 + src/test/run-pass/issue-1257.rs | 2 + src/test/run-pass/issue-12612.rs | 10 +- src/test/run-pass/issue-12660.rs | 2 + src/test/run-pass/issue-12677.rs | 2 + src/test/run-pass/issue-12684.rs | 4 + src/test/run-pass/issue-12699.rs | 4 + .../{compile-fail => run-pass}/issue-12729.rs | 5 +- src/test/run-pass/issue-12744.rs | 6 +- src/test/run-pass/issue-12860.rs | 11 +- src/test/run-pass/issue-12909.rs | 8 +- src/test/run-pass/issue-13027.rs | 8 +- src/test/run-pass/issue-13105.rs | 4 + src/test/run-pass/issue-13167.rs | 4 +- src/test/run-pass/issue-13204.rs | 4 +- src/test/run-pass/issue-13214.rs | 2 + .../run-pass/issue-13259-windows-tcb-trash.rs | 4 + src/test/run-pass/issue-13264.rs | 8 +- src/test/run-pass/issue-13304.rs | 21 +- src/test/run-pass/issue-13323.rs | 2 + src/test/run-pass/issue-13405.rs | 6 +- src/test/run-pass/issue-13494.rs | 11 +- src/test/run-pass/issue-13507-2.rs | 5 + src/test/run-pass/issue-13620.rs | 4 +- src/test/run-pass/issue-13655.rs | 17 +- src/test/run-pass/issue-13665.rs | 2 + src/test/run-pass/issue-13703.rs | 4 +- src/test/run-pass/issue-13763.rs | 8 +- src/test/run-pass/issue-13775.rs | 4 +- src/test/run-pass/issue-13808.rs | 6 +- src/test/run-pass/issue-13837.rs | 6 +- src/test/run-pass/issue-13867.rs | 4 +- src/test/run-pass/issue-13872.rs | 4 +- src/test/run-pass/issue-14021.rs | 2 +- src/test/run-pass/issue-14082.rs | 2 + src/test/run-pass/issue-14254.rs | 20 +- src/test/run-pass/issue-14308.rs | 4 +- src/test/run-pass/issue-14330.rs | 4 +- src/test/run-pass/issue-14393.rs | 2 + src/test/run-pass/issue-14399.rs | 4 +- src/test/run-pass/issue-14421.rs | 5 +- src/test/run-pass/issue-14422.rs | 4 +- src/test/run-pass/issue-14456.rs | 26 +- src/test/run-pass/issue-1451.rs | 2 + src/test/run-pass/issue-14589.rs | 13 +- src/test/run-pass/issue-1460.rs | 4 +- src/test/run-pass/issue-14837.rs | 4 +- src/test/run-pass/issue-14865.rs | 4 +- src/test/run-pass/issue-14901.rs | 4 + src/test/run-pass/issue-14919.rs | 16 +- src/test/run-pass/issue-14933.rs | 4 +- src/test/run-pass/issue-14936.rs | 6 +- src/test/run-pass/issue-14940.rs | 9 +- src/test/run-pass/issue-14958.rs | 14 +- src/test/run-pass/issue-14959.rs | 18 +- src/test/run-pass/issue-15043.rs | 10 +- src/test/run-pass/issue-15080.rs | 4 + src/test/run-pass/issue-15104.rs | 6 +- src/test/run-pass/issue-15108.rs | 2 + src/test/run-pass/issue-15129.rs | 4 +- src/test/run-pass/issue-15149.rs | 36 +- src/test/run-pass/issue-15155.rs | 2 - src/test/run-pass/issue-15221.rs | 3 +- src/test/run-pass/issue-15261.rs | 6 +- src/test/run-pass/issue-15444.rs | 6 +- src/test/run-pass/issue-15562.rs | 4 +- src/test/run-pass/issue-15571.rs | 6 +- src/test/run-pass/issue-15673.rs | 6 +- src/test/run-pass/issue-15689-1.rs | 4 +- src/test/run-pass/issue-15689-2.rs | 4 +- src/test/run-pass/issue-15730.rs | 2 + src/test/run-pass/issue-15734.rs | 34 +- src/test/run-pass/issue-15763.rs | 34 +- src/test/run-pass/issue-15774.rs | 4 +- src/test/run-pass/issue-15793.rs | 4 +- src/test/run-pass/issue-15858.rs | 4 +- .../issue-15881-model-lexer-dotdotdot.rs | 2 + src/test/run-pass/issue-15924.rs | 6 +- src/test/run-pass/issue-16151.rs | 5 +- src/test/run-pass/issue-16256.rs | 2 + src/test/run-pass/issue-16272.rs | 8 +- src/test/run-pass/issue-16278.rs | 1 - src/test/run-pass/issue-16441.rs | 2 + src/test/run-pass/issue-16452.rs | 5 +- src/test/run-pass/issue-16492.rs | 6 +- src/test/run-pass/issue-16530.rs | 4 + src/test/run-pass/issue-16560.rs | 4 +- src/test/run-pass/issue-16596.rs | 2 + src/test/run-pass/issue-16597.rs | 2 +- src/test/run-pass/issue-1660.rs | 4 +- src/test/run-pass/issue-16643.rs | 6 +- src/test/run-pass/issue-16648.rs | 6 +- src/test/run-pass/issue-16668.rs | 6 +- src/test/run-pass/issue-16671.rs | 10 +- src/test/run-pass/issue-16739.rs | 26 +- src/test/run-pass/issue-16774.rs | 10 +- src/test/run-pass/issue-16783.rs | 2 + src/test/run-pass/issue-16922.rs | 20 + src/test/run-pass/issue-1696.rs | 2 + src/test/run-pass/issue-1701.rs | 2 + src/test/run-pass/issue-17068.rs | 4 +- src/test/run-pass/issue-17074.rs | 10 +- src/test/run-pass/issue-17121.rs | 24 +- src/test/run-pass/issue-17216.rs | 6 +- src/test/run-pass/issue-17233.rs | 27 + src/test/run-pass/issue-17302.rs | 6 +- src/test/run-pass/issue-17322.rs | 12 +- src/test/run-pass/issue-17351.rs | 8 + src/test/run-pass/issue-17361.rs | 2 + src/test/run-pass/issue-17503.rs | 6 +- src/test/run-pass/issue-17662.rs | 8 +- src/test/run-pass/issue-17718-parse-const.rs | 4 +- .../issue-17718-static-unsafe-interior.rs | 18 +- src/test/run-pass/issue-17718.rs | 24 +- src/test/run-pass/issue-17732.rs | 2 + src/test/run-pass/issue-17734.rs | 7 +- src/test/run-pass/issue-17746.rs | 33 + src/test/run-pass/issue-17771.rs | 2 + src/test/run-pass/issue-17816.rs | 4 +- src/test/run-pass/issue-17877.rs | 4 + src/test/run-pass/issue-17897.rs | 8 +- src/test/run-pass/issue-17904.rs | 2 + src/test/run-pass/issue-18110.rs | 2 + src/test/run-pass/issue-18188.rs | 8 +- src/test/run-pass/issue-1821.rs | 2 + src/test/run-pass/issue-18232.rs | 2 + src/test/run-pass/issue-18352.rs | 2 + src/test/run-pass/issue-18353.rs | 2 + src/test/run-pass/issue-18412.rs | 10 +- src/test/run-pass/issue-18425.rs | 5 +- src/test/run-pass/issue-18501.rs | 4 +- src/test/run-pass/issue-18514.rs | 4 +- src/test/run-pass/issue-18539.rs | 6 +- src/test/run-pass/issue-18619.rs | 4 + src/test/run-pass/issue-18652.rs | 2 + src/test/run-pass/issue-1866.rs | 4 +- src/test/run-pass/issue-18661.rs | 4 +- src/test/run-pass/issue-18685.rs | 2 + src/test/run-pass/issue-18711.rs | 4 +- src/test/run-pass/issue-18738.rs | 4 +- src/test/run-pass/issue-18767.rs | 2 + src/test/run-pass/issue-18859.rs | 6 +- src/test/run-pass/issue-18906.rs | 2 + src/test/run-pass/issue-19037.rs | 2 + src/test/run-pass/issue-19098.rs | 4 +- src/test/run-pass/issue-19100.rs | 2 +- src/test/run-pass/issue-19121.rs | 2 + src/test/run-pass/issue-19127.rs | 2 + src/test/run-pass/issue-19129-1.rs | 2 + src/test/run-pass/issue-19129-2.rs | 2 + src/test/run-pass/issue-19244.rs | 31 +- src/test/run-pass/issue-19293.rs | 2 + src/test/run-pass/issue-19340-1.rs | 4 +- src/test/run-pass/issue-19340-2.rs | 2 + src/test/run-pass/issue-19358.rs | 2 +- src/test/run-pass/issue-19398.rs | 2 + src/test/run-pass/issue-19479.rs | 2 + src/test/run-pass/issue-19499.rs | 2 + src/test/run-pass/issue-19631.rs | 2 + src/test/run-pass/issue-19632.rs | 2 + src/test/run-pass/issue-1974.rs | 2 + .../run-pass/issue-19811-escape-unicode.rs | 4 + src/test/run-pass/issue-19850.rs | 4 +- src/test/run-pass/issue-19982.rs | 32 + src/test/run-pass/issue-20009.rs | 2 + src/test/run-pass/issue-20055-box-trait.rs | 8 +- .../run-pass/issue-20055-box-unsized-array.rs | 8 +- src/test/run-pass/issue-20091.rs | 18 +- src/test/run-pass/issue-20313.rs | 2 + src/test/run-pass/issue-20343.rs | 2 + src/test/run-pass/issue-20389.rs | 2 + src/test/run-pass/issue-20396.rs | 25 + src/test/run-pass/issue-20414.rs | 6 +- src/test/run-pass/issue-20454.rs | 8 +- src/test/run-pass/issue-20575.rs | 5 +- src/test/run-pass/issue-20644.rs | 23 +- src/test/run-pass/issue-20676.rs | 4 +- src/test/run-pass/issue-2074.rs | 6 +- src/test/run-pass/issue-20763-1.rs | 2 + src/test/run-pass/issue-20763-2.rs | 2 + src/test/run-pass/issue-20797.rs | 105 +- src/test/run-pass/issue-20823.rs | 2 +- src/test/run-pass/issue-21033.rs | 2 + src/test/run-pass/issue-21058.rs | 15 +- src/test/run-pass/issue-21245.rs | 2 + src/test/run-pass/issue-21296.rs | 6 + src/test/run-pass/issue-21306.rs | 2 + src/test/run-pass/issue-21350.rs | 2 + src/test/run-pass/issue-21361.rs | 2 + src/test/run-pass/issue-21363.rs | 2 + src/test/run-pass/issue-21384.rs | 4 +- src/test/run-pass/issue-21402.rs | 2 + src/test/run-pass/issue-21475.rs | 27 + src/test/run-pass/issue-21520.rs | 3 +- src/test/run-pass/issue-21634.rs | 8 +- src/test/run-pass/issue-21655.rs | 2 + src/test/run-pass/issue-21721.rs | 19 + src/test/run-pass/issue-21726.rs | 2 + src/test/run-pass/issue-2185.rs | 22 +- src/test/run-pass/issue-21891.rs | 8 +- src/test/run-pass/issue-2190-1.rs | 12 +- src/test/run-pass/issue-21909.rs | 2 + src/test/run-pass/issue-22036.rs | 4 +- src/test/run-pass/issue-2214.rs | 13 +- src/test/run-pass/issue-22356.rs | 41 + src/test/run-pass/issue-22426.rs | 18 + .../run-pass/issue-22536-copy-mustnt-zero.rs | 38 + src/test/run-pass/issue-22577.rs | 37 + src/test/run-pass/issue-22629.rs | 22 + src/test/run-pass/issue-22777.rs | 57 + src/test/run-pass/issue-22828.rs | 31 + src/test/run-pass/issue-2284.rs | 2 + src/test/run-pass/issue-2288.rs | 6 +- src/test/run-pass/issue-23037.rs | 19 + src/test/run-pass/issue-2311-2.rs | 2 + src/test/run-pass/issue-2311.rs | 2 + src/test/run-pass/issue-2312.rs | 4 +- src/test/run-pass/issue-2316-c.rs | 2 + src/test/run-pass/issue-23435.rs | 37 + src/test/run-pass/issue-23485.rs | 58 + src/test/run-pass/issue-23550.rs | 39 + src/test/run-pass/issue-23781.rs | 38 + src/test/run-pass/issue-2380-b.rs | 2 + src/test/run-pass/issue-2383.rs | 5 +- src/test/run-pass/issue-2414-c.rs | 2 + src/test/run-pass/issue-2428.rs | 6 +- src/test/run-pass/issue-2445-b.rs | 10 +- src/test/run-pass/issue-2445.rs | 6 +- src/test/run-pass/issue-2463.rs | 4 +- src/test/run-pass/issue-2472.rs | 2 + src/test/run-pass/issue-2487-a.rs | 6 +- src/test/run-pass/issue-2502.rs | 2 + src/test/run-pass/issue-2526-a.rs | 2 + src/test/run-pass/issue-2550.rs | 8 +- src/test/run-pass/issue-2611-3.rs | 4 +- src/test/run-pass/issue-2631-b.rs | 4 +- src/test/run-pass/issue-2633-2.rs | 6 +- src/test/run-pass/issue-2633.rs | 4 +- src/test/run-pass/issue-2642.rs | 4 +- src/test/run-pass/issue-2708.rs | 10 +- src/test/run-pass/issue-2718.rs | 31 +- src/test/run-pass/issue-2723-b.rs | 2 + src/test/run-pass/issue-2734.rs | 2 + src/test/run-pass/issue-2735-2.rs | 2 + src/test/run-pass/issue-2735-3.rs | 2 + src/test/run-pass/issue-2735.rs | 2 + src/test/run-pass/issue-2748-a.rs | 2 + src/test/run-pass/issue-2748-b.rs | 4 +- src/test/run-pass/issue-2804-2.rs | 7 +- src/test/run-pass/issue-2804.rs | 13 +- src/test/run-pass/issue-2895.rs | 14 +- src/test/run-pass/issue-2904.rs | 5 +- src/test/run-pass/issue-2935.rs | 4 +- src/test/run-pass/issue-2936.rs | 12 +- src/test/run-pass/issue-2989.rs | 8 +- src/test/run-pass/issue-3012-2.rs | 6 +- src/test/run-pass/issue-3026.rs | 9 +- src/test/run-pass/issue-3037.rs | 2 + src/test/run-pass/issue-3052.rs | 6 +- src/test/run-pass/issue-3091.rs | 2 + src/test/run-pass/issue-3121.rs | 8 +- src/test/run-pass/issue-3149.rs | 2 + src/test/run-pass/issue-3220.rs | 4 +- src/test/run-pass/issue-3290.rs | 4 +- src/test/run-pass/issue-333.rs | 2 + src/test/run-pass/issue-3424.rs | 10 +- src/test/run-pass/issue-3429.rs | 2 + src/test/run-pass/issue-3500.rs | 2 + src/test/run-pass/issue-3559.rs | 6 +- src/test/run-pass/issue-3563-2.rs | 6 +- src/test/run-pass/issue-3563-3.rs | 34 +- src/test/run-pass/issue-3574.rs | 2 + src/test/run-pass/issue-3609.rs | 13 +- src/test/run-pass/issue-3656.rs | 4 + src/test/run-pass/issue-3683.rs | 8 +- src/test/run-pass/issue-3743.rs | 3 +- src/test/run-pass/issue-3753.rs | 6 +- src/test/run-pass/issue-3794.rs | 2 +- src/test/run-pass/issue-3847.rs | 4 +- src/test/run-pass/issue-3874.rs | 6 +- src/test/run-pass/issue-3878.rs | 4 +- src/test/run-pass/issue-3888-2.rs | 2 + src/test/run-pass/issue-3895.rs | 2 + src/test/run-pass/issue-3935.rs | 2 + src/test/run-pass/issue-3979-2.rs | 2 + src/test/run-pass/issue-3979-generics.rs | 12 +- src/test/run-pass/issue-3979-xcrate.rs | 8 +- src/test/run-pass/issue-3979.rs | 15 +- src/test/run-pass/issue-3991.rs | 4 +- src/test/run-pass/issue-4016.rs | 3 + src/test/run-pass/issue-4036.rs | 6 +- src/test/run-pass/issue-4107.rs | 8 +- src/test/run-pass/issue-4208.rs | 2 + src/test/run-pass/issue-4228.rs | 2 + src/test/run-pass/issue-4241.rs | 20 +- src/test/run-pass/issue-4252.rs | 4 +- src/test/run-pass/issue-4333.rs | 8 +- src/test/run-pass/issue-4387.rs | 2 + src/test/run-pass/issue-4446.rs | 4 + src/test/run-pass/issue-4448.rs | 2 + src/test/run-pass/issue-4464.rs | 4 +- src/test/run-pass/issue-4542.rs | 2 + src/test/run-pass/issue-4545.rs | 6 +- src/test/run-pass/issue-4734.rs | 6 +- src/test/run-pass/issue-4735.rs | 9 +- src/test/run-pass/issue-4759-1.rs | 6 +- src/test/run-pass/issue-4759.rs | 7 +- src/test/run-pass/issue-4830.rs | 4 +- src/test/run-pass/issue-4875.rs | 2 + src/test/run-pass/issue-5060.rs | 1 - src/test/run-pass/issue-5192.rs | 4 +- src/test/run-pass/issue-5239-2.rs | 4 +- src/test/run-pass/issue-5243.rs | 4 +- src/test/run-pass/issue-5315.rs | 2 + .../issue-5321-immediates-with-bare-self.rs | 2 +- src/test/run-pass/issue-5353.rs | 2 + src/test/run-pass/issue-5518.rs | 4 +- src/test/run-pass/issue-5521.rs | 6 +- src/test/run-pass/issue-5530.rs | 10 +- src/test/run-pass/issue-5550.rs | 2 + src/test/run-pass/issue-5554.rs | 4 +- src/test/run-pass/issue-5572.rs | 2 + src/test/run-pass/issue-5666.rs | 1 - src/test/run-pass/issue-5688.rs | 6 +- src/test/run-pass/issue-5708.rs | 4 +- src/test/run-pass/issue-5718.rs | 8 +- src/test/run-pass/issue-5741.rs | 2 + src/test/run-pass/issue-5754.rs | 2 + src/test/run-pass/issue-5791.rs | 4 + src/test/run-pass/issue-5884.rs | 6 +- src/test/run-pass/issue-5900.rs | 4 +- src/test/run-pass/issue-5917.rs | 4 +- src/test/run-pass/issue-5950.rs | 4 +- src/test/run-pass/issue-5988.rs | 4 + src/test/run-pass/issue-5997.rs | 4 +- src/test/run-pass/issue-6117.rs | 5 +- src/test/run-pass/issue-6128.rs | 12 +- src/test/run-pass/issue-6130.rs | 12 +- src/test/run-pass/issue-6153.rs | 4 +- src/test/run-pass/issue-6157.rs | 12 +- src/test/run-pass/issue-6318.rs | 3 +- src/test/run-pass/issue-6334.rs | 16 +- src/test/run-pass/issue-6341.rs | 4 +- src/test/run-pass/issue-6344-let.rs | 2 +- src/test/run-pass/issue-6344-match.rs | 2 +- src/test/run-pass/issue-6449.rs | 4 +- src/test/run-pass/issue-6470.rs | 4 +- src/test/run-pass/issue-6557.rs | 4 +- src/test/run-pass/issue-6892.rs | 14 +- src/test/run-pass/issue-6898.rs | 16 +- src/test/run-pass/issue-6919.rs | 3 +- src/test/run-pass/issue-7012.rs | 6 +- src/test/run-pass/issue-7178.rs | 4 +- src/test/run-pass/issue-7222.rs | 3 +- src/test/run-pass/issue-7268.rs | 2 + src/test/run-pass/issue-7344.rs | 2 + .../run-pass/issue-7519-match-unit-in-arg.rs | 2 + src/test/run-pass/issue-7563.rs | 4 +- src/test/run-pass/issue-7575.rs | 6 +- .../issue-7607-2.rs | 6 +- src/test/run-pass/issue-7660.rs | 12 +- src/test/run-pass/issue-7663.rs | 10 +- ...7673-cast-generically-implemented-trait.rs | 2 + src/test/run-pass/issue-7784.rs | 3 + src/test/run-pass/issue-7899.rs | 4 +- src/test/run-pass/issue-8044.rs | 6 +- ...fault-method-self-inherit-builtin-trait.rs | 2 + src/test/run-pass/issue-8248.rs | 3 +- src/test/run-pass/issue-8249.rs | 3 +- src/test/run-pass/issue-8259.rs | 4 +- src/test/run-pass/issue-8351-1.rs | 4 +- src/test/run-pass/issue-8351-2.rs | 4 +- src/test/run-pass/issue-8391.rs | 2 + src/test/run-pass/issue-8398.rs | 5 +- src/test/run-pass/issue-8401.rs | 2 + src/test/run-pass/issue-8460.rs | 24 +- src/test/run-pass/issue-8498.rs | 9 +- src/test/run-pass/issue-8506.rs | 2 + src/test/run-pass/issue-8578.rs | 2 + src/test/run-pass/issue-868.rs | 2 + src/test/run-pass/issue-8709.rs | 4 +- src/test/run-pass/issue-8783.rs | 6 +- src/test/run-pass/issue-8827.rs | 12 +- src/test/run-pass/issue-8851.rs | 10 +- src/test/run-pass/issue-8860.rs | 10 +- src/test/run-pass/issue-8898.rs | 2 + src/test/run-pass/issue-9047.rs | 2 +- src/test/run-pass/issue-9110.rs | 2 + src/test/run-pass/issue-9123.rs | 2 + src/test/run-pass/issue-9129.rs | 2 +- src/test/run-pass/issue-9188.rs | 5 +- src/test/run-pass/issue-9249.rs | 2 + src/test/run-pass/issue-9259.rs | 2 + src/test/run-pass/issue-9382.rs | 6 +- .../issue-9394-inherited-trait-calls.rs | 2 + src/test/run-pass/issue-9396.rs | 8 +- src/test/run-pass/issue-9719.rs | 14 +- src/test/run-pass/issue-979.rs | 6 +- src/test/run-pass/issue-9906.rs | 4 +- src/test/run-pass/issue-9918.rs | 2 + src/test/run-pass/issue-9942.rs | 4 +- src/test/run-pass/issue-9951.rs | 30 + src/test/run-pass/issue-9968.rs | 4 +- src/test/run-pass/issue2170exe.rs | 4 +- src/test/run-pass/issue22346.rs | 6 +- src/test/run-pass/issue_3136_b.rs | 2 + src/test/run-pass/issue_9155.rs | 2 + src/test/run-pass/istr.rs | 2 + src/test/run-pass/item-attributes.rs | 18 +- src/test/run-pass/item-name-overload.rs | 2 + .../run-pass/iter-cloned-type-inference.rs | 27 + src/test/run-pass/iter-range.rs | 6 +- src/test/run-pass/ivec-pass-by-value.rs | 4 +- src/test/run-pass/ivec-tag.rs | 12 +- .../run-pass/keyword-changes-2012-07-31.rs | 4 +- .../kindck-implicit-close-over-mut-var.rs | 13 +- .../run-pass/kindck-owned-trait-contains-1.rs | 2 + src/test/run-pass/kinds-in-metadata.rs | 5 +- src/test/run-pass/labeled-break.rs | 2 + src/test/run-pass/lambda-infer-unresolved.rs | 4 +- src/test/run-pass/lambda-var-hygiene.rs | 2 +- src/test/run-pass/lang-item-public.rs | 9 +- src/test/run-pass/large-records.rs | 26 +- src/test/run-pass/last-use-in-block.rs | 2 + src/test/run-pass/last-use-in-cap-clause.rs | 13 +- src/test/run-pass/last-use-is-capture.rs | 4 +- src/test/run-pass/lazy-and-or.rs | 4 +- src/test/run-pass/lazy-init.rs | 4 +- src/test/run-pass/leak-unique-as-tydesc.rs | 4 +- src/test/run-pass/let-assignability.rs | 4 +- src/test/run-pass/let-destruct-ref.rs | 2 + src/test/run-pass/let-var-hygiene.rs | 2 + src/test/run-pass/linear-for-loop.rs | 2 +- src/test/run-pass/link-section.rs | 8 +- src/test/run-pass/linkage-visibility.rs | 6 +- src/test/run-pass/linkage1.rs | 6 +- ...ase-types-non-uppercase-statics-unicode.rs | 2 +- ...on-camel-case-with-trailing-underscores.rs | 4 +- ...uppercase-statics-lowercase-mut-statics.rs | 4 +- src/test/run-pass/list.rs | 4 +- .../liveness-assign-imm-local-after-loop.rs | 4 +- .../liveness-assign-imm-local-after-ret.rs | 4 +- src/test/run-pass/liveness-move-in-loop.rs | 4 +- .../log-knows-the-names-of-variants-in-std.rs | 2 +- ...log_syntax-trace_macros-macro-locations.rs | 2 + src/test/run-pass/logging-enabled-debug.rs | 6 +- src/test/run-pass/logging-enabled.rs | 6 +- src/test/run-pass/logging-only-prints-once.rs | 2 +- src/test/run-pass/logging-right-crate.rs | 4 +- src/test/run-pass/logging-separate-lines.rs | 3 + .../run-pass/logging_before_rt_started.rs | 2 + src/test/run-pass/long-while.rs | 4 +- src/test/run-pass/loop-break-cont-1.rs | 2 + src/test/run-pass/loop-diverges.rs | 2 + src/test/run-pass/loop-label-shadowing.rs | 3 +- src/test/run-pass/loop-labeled-break-value.rs | 20 + .../loop-no-reinit-needed-post-bot.rs | 2 + src/test/run-pass/loop-scope.rs | 2 + src/test/run-pass/macro-2.rs | 2 +- src/test/run-pass/macro-attributes.rs | 2 + src/test/run-pass/macro-block-nonterminal.rs | 2 + src/test/run-pass/macro-crate-def-only.rs | 2 + .../macro-crate-nonterminal-renamed.rs | 2 +- src/test/run-pass/macro-crate-use.rs | 4 +- src/test/run-pass/macro-deep_expansion.rs | 2 + .../run-pass/macro-delimiter-significance.rs | 3 +- src/test/run-pass/macro-interpolation.rs | 6 +- ...vocation-in-count-expr-fixed-array-type.rs | 2 + src/test/run-pass/macro-meta-items.rs | 1 - src/test/run-pass/macro-method-issue-4621.rs | 7 +- src/test/run-pass/macro-nt-list.rs | 2 + src/test/run-pass/macro-of-higher-order.rs | 2 + src/test/run-pass/macro-pat.rs | 10 +- src/test/run-pass/macro-path.rs | 4 +- src/test/run-pass/macro-stmt.rs | 2 +- src/test/run-pass/macro-with-attrs1.rs | 2 + src/test/run-pass/macro-with-attrs2.rs | 3 +- .../macro-with-braces-in-expr-position.rs | 6 +- src/test/run-pass/macro_with_super_2.rs | 2 + src/test/run-pass/match-arm-statics.rs | 8 +- src/test/run-pass/match-borrowed_str.rs | 2 + src/test/run-pass/match-bot-2.rs | 4 +- src/test/run-pass/match-bot.rs | 4 +- src/test/run-pass/match-enum-struct-0.rs | 4 +- src/test/run-pass/match-enum-struct-1.rs | 4 +- .../run-pass/match-implicit-copy-unique.rs | 6 +- src/test/run-pass/match-in-macro.rs | 4 +- src/test/run-pass/match-join.rs | 6 +- src/test/run-pass/match-naked-record-expr.rs | 4 +- src/test/run-pass/match-naked-record.rs | 4 +- src/test/run-pass/match-path.rs | 2 + src/test/run-pass/match-pattern-bindings.rs | 2 + src/test/run-pass/match-pattern-lit.rs | 2 +- .../run-pass/match-pattern-no-type-params.rs | 2 +- src/test/run-pass/match-pattern-simple.rs | 4 +- src/test/run-pass/match-phi.rs | 4 +- src/test/run-pass/match-pipe-binding.rs | 2 + src/test/run-pass/match-range-static.rs | 6 +- src/test/run-pass/match-reassign.rs | 30 + .../match-ref-binding-in-guard-3256.rs | 2 + .../run-pass/match-ref-binding-mut-option.rs | 2 + src/test/run-pass/match-ref-binding-mut.rs | 4 +- src/test/run-pass/match-ref-binding.rs | 4 +- .../{lint-cstack.rs => match-ref-unsized.rs} | 20 +- .../run-pass/match-static-const-rename.rs | 6 +- src/test/run-pass/match-str.rs | 2 + src/test/run-pass/match-struct-0.rs | 4 +- src/test/run-pass/match-tag.rs | 12 +- .../match-value-binding-in-guard-3291.rs | 4 +- src/test/run-pass/match-vec-alternatives.rs | 13 +- src/test/run-pass/match-vec-rvalue.rs | 2 + src/test/run-pass/match-with-ret-arm.rs | 6 +- src/test/run-pass/max-min-classes.rs | 12 +- src/test/run-pass/method-attributes.rs | 4 +- .../method-early-bound-lifetimes-on-self.rs | 2 + ...thod-mut-self-modifies-mut-slice-lvalue.rs | 17 +- .../method-normalize-bounds-issue-20604.rs | 5 +- src/test/run-pass/method-projection.rs | 18 +- .../run-pass/method-recursive-blanket-impl.rs | 2 + src/test/run-pass/method-self-arg-aux1.rs | 4 +- src/test/run-pass/method-self-arg-aux2.rs | 4 +- src/test/run-pass/method-self-arg-trait.rs | 6 +- src/test/run-pass/method-self-arg.rs | 8 +- .../method-two-trait-defer-resolution-1.rs | 2 + .../method-two-trait-defer-resolution-2.rs | 43 +- ...o-traits-distinguished-via-where-clause.rs | 8 +- src/test/run-pass/method-where-clause.rs | 2 + src/test/run-pass/mid-path-type-params.rs | 13 +- .../run-pass/minmax-stability-issue-23687.rs | 83 + src/test/run-pass/mod-inside-fn.rs | 6 +- src/test/run-pass/mod-view-items.rs | 5 +- src/test/run-pass/mod_dir_implicit_aux/mod.rs | 2 +- src/test/run-pass/mod_dir_simple/test.rs | 2 +- src/test/run-pass/mod_file_aux.rs | 2 +- .../module-qualified-struct-destructure.rs | 6 +- src/test/run-pass/monad.rs | 16 +- .../run-pass/monomorphize-abi-alignment.rs | 6 +- ...nomorphized-callees-with-ty-params-3314.rs | 8 +- src/test/run-pass/move-1-unique.rs | 12 +- src/test/run-pass/move-2-unique.rs | 6 +- src/test/run-pass/move-2.rs | 6 +- src/test/run-pass/move-3-unique.rs | 12 +- src/test/run-pass/move-4-unique.rs | 4 +- src/test/run-pass/move-4.rs | 4 +- src/test/run-pass/move-arg-2-unique.rs | 4 +- src/test/run-pass/move-arg-2.rs | 4 +- src/test/run-pass/move-arg.rs | 4 +- src/test/run-pass/move-guard-const.rs | 27 + src/test/run-pass/move-nullary-fn.rs | 2 + src/test/run-pass/move-out-of-field.rs | 2 + src/test/run-pass/move-scalar.rs | 6 +- .../moves-based-on-type-capture-clause.rs | 6 +- .../moves-based-on-type-cross-crate.rs | 2 + src/test/run-pass/multi-let.rs | 2 + src/test/run-pass/multidispatch1.rs | 12 +- src/test/run-pass/multidispatch2.rs | 10 +- src/test/run-pass/multiline-comment.rs | 2 + src/test/run-pass/multiple-trait-bounds.rs | 2 + src/test/run-pass/mut-function-arguments.rs | 6 +- src/test/run-pass/mut-in-ident-patterns.rs | 12 +- src/test/run-pass/mut-vstore-expr.rs | 4 +- ...ility-inherits-through-fixed-length-vec.rs | 2 + src/test/run-pass/mutable-alias-vec.rs | 6 +- src/test/run-pass/mutual-recursion-group.rs | 4 +- .../namespaced-enum-emulate-flat-xc.rs | 3 +- .../run-pass/namespaced-enum-emulate-flat.rs | 10 +- .../namespaced-enum-glob-import-xcrate.rs | 2 + .../run-pass/namespaced-enum-glob-import.rs | 6 +- src/test/run-pass/namespaced-enums-xcrate.rs | 3 +- src/test/run-pass/namespaced-enums.rs | 6 +- src/test/run-pass/native-print-no-runtime.rs | 2 +- src/test/run-pass/negative.rs | 2 + src/test/run-pass/nested-block-comment.rs | 2 + src/test/run-pass/nested-class.rs | 10 +- src/test/run-pass/nested-enum-same-names.rs | 2 + src/test/run-pass/nested-exhaustive-match.rs | 4 +- .../nested-function-names-issue-8587.rs | 14 +- src/test/run-pass/nested-matchs.rs | 8 +- src/test/run-pass/nested-pattern.rs | 6 +- src/test/run-pass/nested-vec-1.rs | 16 + src/test/run-pass/nested-vec-2.rs | 23 + src/test/run-pass/nested-vec-3.rs | 60 + src/test/run-pass/nested_item_main.rs | 4 +- src/test/run-pass/new-box-syntax.rs | 14 +- src/test/run-pass/new-box.rs | 5 +- src/test/run-pass/new-impl-syntax.rs | 4 +- src/test/run-pass/new-style-constants.rs | 2 +- .../run-pass/new-style-fixed-length-vec.rs | 2 +- src/test/run-pass/new-unicode-escapes.rs | 4 + src/test/run-pass/new-unsafe-pointers.rs | 6 +- src/test/run-pass/newlambdas-ret-infer.rs | 6 +- src/test/run-pass/newlambdas-ret-infer2.rs | 6 +- src/test/run-pass/newlambdas.rs | 4 +- src/test/run-pass/newtype-polymorphic.rs | 2 + src/test/run-pass/newtype-struct-drop-run.rs | 4 +- src/test/run-pass/newtype-struct-with-dtor.rs | 5 +- src/test/run-pass/newtype-struct-xc-2.rs | 2 + src/test/run-pass/newtype-struct-xc.rs | 2 + src/test/run-pass/newtype-temporary.rs | 2 +- src/test/run-pass/newtype.rs | 10 +- src/test/run-pass/nil-decl-in-foreign.rs | 2 + src/test/run-pass/nil-pattern.rs | 2 + src/test/run-pass/no-landing-pads.rs | 2 + src/test/run-pass/no-std-xcrate2.rs | 2 +- src/test/run-pass/non-built-in-quote.rs | 2 + src/test/run-pass/non-legacy-modes.rs | 6 +- src/test/run-pass/nondrop-cycle.rs | 2 + src/test/run-pass/nul-characters.rs | 14 +- .../run-pass/nullable-pointer-ffi-compat.rs | 8 +- .../nullable-pointer-iotareduction.rs | 16 +- src/test/run-pass/nullable-pointer-size.rs | 10 +- src/test/run-pass/nullary-or-pattern.rs | 4 +- .../run-pass/numeric-method-autoexport.rs | 4 + ...ject-lifetime-default-default-to-static.rs | 2 + ...object-lifetime-default-from-ref-struct.rs | 2 + .../object-lifetime-default-from-rptr-box.rs | 2 + .../object-lifetime-default-from-rptr-mut.rs | 2 + ...bject-lifetime-default-from-rptr-struct.rs | 2 + .../object-lifetime-default-from-rptr.rs | 2 + src/test/run-pass/object-method-numbering.rs | 4 +- .../run-pass/object-one-type-two-traits.rs | 12 +- .../object-safety-sized-self-by-value-self.rs | 48 + ...object-safety-sized-self-generic-method.rs | 48 + .../object-safety-sized-self-return-Self.rs | 49 + .../objects-coerce-freeze-borrored.rs | 18 +- ...owned-object-borrowed-method-headerless.rs | 10 +- .../objects-owned-object-owned-method.rs | 8 +- src/test/run-pass/once-move-out-on-heap.rs | 2 + src/test/run-pass/one-tuple.rs | 2 + src/test/run-pass/opeq.rs | 2 +- src/test/run-pass/operator-associativity.rs | 2 + src/test/run-pass/operator-multidispatch.rs | 8 +- src/test/run-pass/operator-overloading.rs | 16 +- src/test/run-pass/option-ext.rs | 4 +- src/test/run-pass/option-unwrap.rs | 4 +- src/test/run-pass/or-pattern.rs | 8 +- src/test/run-pass/order-drop-with-match.rs | 6 +- src/test/run-pass/osx-frameworks.rs | 4 + .../out-of-stack-new-thread-no-split.rs | 7 +- src/test/run-pass/out-of-stack-no-split.rs | 3 +- src/test/run-pass/out-of-stack.rs | 2 +- src/test/run-pass/out-pointer-aliasing.rs | 8 +- src/test/run-pass/output-slot-variants.rs | 14 +- src/test/run-pass/over-constrained-vregs.rs | 4 +- .../run-pass/overloaded-autoderef-count.rs | 12 +- .../run-pass/overloaded-autoderef-indexing.rs | 2 + .../run-pass/overloaded-autoderef-order.rs | 6 +- .../run-pass/overloaded-autoderef-vtable.rs | 6 +- .../run-pass/overloaded-autoderef-xcrate.rs | 2 + src/test/run-pass/overloaded-autoderef.rs | 11 +- .../overloaded-calls-object-one-arg.rs | 4 +- .../overloaded-calls-object-two-args.rs | 4 +- .../overloaded-calls-object-zero-args.rs | 4 +- .../overloaded-calls-param-vtables.rs | 17 +- src/test/run-pass/overloaded-calls-simple.rs | 23 +- .../run-pass/overloaded-calls-zero-args.rs | 14 +- src/test/run-pass/overloaded-deref-count.rs | 8 +- src/test/run-pass/overloaded-deref.rs | 9 +- .../run-pass/overloaded-index-assoc-list.rs | 14 +- .../run-pass/overloaded-index-autoderef.rs | 34 +- .../run-pass/overloaded-index-in-field.rs | 26 +- src/test/run-pass/overloaded-index.rs | 32 +- src/test/run-pass/owned-implies-static.rs | 5 +- .../run-pass/packed-struct-borrow-element.rs | 4 +- .../run-pass/packed-struct-generic-layout.rs | 2 + .../run-pass/packed-struct-generic-size.rs | 2 + src/test/run-pass/packed-struct-layout.rs | 2 + src/test/run-pass/packed-struct-match.rs | 4 +- src/test/run-pass/packed-struct-size-xc.rs | 2 + src/test/run-pass/packed-struct-size.rs | 2 + src/test/run-pass/packed-struct-vec.rs | 4 +- .../run-pass/packed-tuple-struct-layout.rs | 2 + src/test/run-pass/packed-tuple-struct-size.rs | 2 + .../run-pass/panic-in-dtor-drops-fields.rs | 4 +- .../parameterized-trait-with-bounds.rs | 4 +- src/test/run-pass/parse-assoc-type-lt.rs | 2 + .../run-pass/parse-complex-macro-invoc-op.rs | 2 + src/test/run-pass/path.rs | 6 +- .../run-pass/pattern-bound-var-in-for-each.rs | 4 +- src/test/run-pass/pattern-in-closure.rs | 6 +- src/test/run-pass/placement-new-arena.rs | 3 +- src/test/run-pass/pred-not-bool.rs | 4 +- src/test/run-pass/preempt.rs | 6 +- src/test/run-pass/priv-impl-prim-ty.rs | 4 +- src/test/run-pass/privacy-ns.rs | 2 + src/test/run-pass/privacy-reexport.rs | 2 + src/test/run-pass/privacy1.rs | 2 + src/test/run-pass/private-class-field.rs | 14 +- src/test/run-pass/private-method.rs | 8 +- src/test/run-pass/process-exit.rs | 31 + src/test/run-pass/process-remove-from-env.rs | 4 + .../process-spawn-with-unicode-params.rs | 42 +- src/test/run-pass/ptr-coercion.rs | 24 +- src/test/run-pass/pub-extern-privacy.rs | 2 + src/test/run-pass/pub-item-inside-macro.rs | 2 + src/test/run-pass/pub-method-inside-macro.rs | 2 + src/test/run-pass/pub-use-xcrate.rs | 2 + src/test/run-pass/pub_use_mods_xcrate_exe.rs | 2 + src/test/run-pass/pure-sum.rs | 30 +- src/test/run-pass/range-type-infer.rs | 2 + src/test/run-pass/range.rs | 4 +- src/test/run-pass/ranges-precedence.rs | 9 +- src/test/run-pass/raw-str.rs | Bin 1339 -> 1341 bytes src/test/run-pass/rcvr-borrowed-to-region.rs | 10 +- src/test/run-pass/rcvr-borrowed-to-slice.rs | 8 +- src/test/run-pass/readalias.rs | 4 +- src/test/run-pass/realloc-16687.rs | 48 +- src/test/run-pass/rec-align-u32.rs | 14 +- src/test/run-pass/rec-align-u64.rs | 35 +- src/test/run-pass/rec-extend.rs | 4 +- src/test/run-pass/rec-tup.rs | 10 +- src/test/run-pass/rec.rs | 10 +- src/test/run-pass/record-pat.rs | 16 +- .../run-pass/reexport-should-still-link.rs | 4 +- src/test/run-pass/reexport-star.rs | 2 + .../reexported-static-methods-cross-crate.rs | 6 +- .../regions-addr-of-interior-of-unique-box.rs | 8 +- src/test/run-pass/regions-addr-of-ret.rs | 2 +- .../regions-assoc-type-region-bound.rs | 2 + .../regions-assoc-type-static-bound.rs | 2 + src/test/run-pass/regions-borrow-at.rs | 6 +- .../run-pass/regions-borrow-evec-fixed.rs | 4 +- src/test/run-pass/regions-borrow-evec-uniq.rs | 4 +- src/test/run-pass/regions-borrow-uniq.rs | 8 +- src/test/run-pass/regions-bot.rs | 4 +- ...-close-over-type-parameter-successfully.rs | 10 +- src/test/run-pass/regions-copy-closure.rs | 10 +- src/test/run-pass/regions-creating-enums2.rs | 4 +- src/test/run-pass/regions-creating-enums5.rs | 4 +- .../run-pass/regions-debruijn-of-object.rs | 2 + .../run-pass/regions-dependent-addr-of.rs | 30 +- src/test/run-pass/regions-dependent-autofn.rs | 2 + .../run-pass/regions-dependent-autoslice.rs | 6 +- .../run-pass/regions-dependent-let-ref.rs | 4 +- ...egions-early-bound-lifetime-in-assoc-fn.rs | 4 +- .../regions-early-bound-trait-param.rs | 31 +- ...egions-early-bound-used-in-bound-method.rs | 12 +- .../regions-early-bound-used-in-bound.rs | 7 +- .../regions-early-bound-used-in-type-param.rs | 6 +- .../run-pass/regions-escape-into-other-fn.rs | 8 +- src/test/run-pass/regions-expl-self.rs | 4 +- src/test/run-pass/regions-fn-subtyping-2.rs | 6 +- src/test/run-pass/regions-fn-subtyping.rs | 17 +- .../regions-infer-borrow-scope-addr-of.rs | 2 + .../regions-infer-borrow-scope-view.rs | 2 + ...gions-infer-borrow-scope-within-loop-ok.rs | 4 +- .../run-pass/regions-infer-borrow-scope.rs | 8 +- src/test/run-pass/regions-infer-call-2.rs | 8 +- src/test/run-pass/regions-infer-call.rs | 6 +- ...regions-infer-contravariance-due-to-ret.rs | 8 +- .../regions-infer-reborrow-ref-mut-recurse.rs | 8 +- ...regions-infer-region-in-fn-but-not-type.rs | 6 +- .../regions-infer-static-from-proc.rs | 6 +- src/test/run-pass/regions-issue-21422.rs | 2 + src/test/run-pass/regions-issue-22246.rs | 2 + .../regions-lifetime-nonfree-late-bound.rs | 10 +- ...-lifetime-static-items-enclosing-scopes.rs | 4 +- src/test/run-pass/regions-link-fn-args.rs | 4 +- src/test/run-pass/regions-mock-tcx.rs | 16 +- src/test/run-pass/regions-mock-trans.rs | 6 +- .../regions-no-bound-in-argument-cleanup.rs | 2 + .../regions-no-variance-from-fn-generics.rs | 2 + src/test/run-pass/regions-nullary-variant.rs | 6 +- src/test/run-pass/regions-params.rs | 10 +- .../regions-reassign-let-bound-pointer.rs | 4 +- .../regions-reassign-match-bound-pointer.rs | 4 +- src/test/run-pass/regions-refcell.rs | 14 +- ...ions-on-closures-to-inference-variables.rs | 17 +- .../regions-return-interior-of-option.rs | 2 + .../run-pass/regions-scope-chain-example.rs | 2 + src/test/run-pass/regions-self-impls.rs | 6 +- src/test/run-pass/regions-self-in-enums.rs | 4 +- src/test/run-pass/regions-simple.rs | 4 +- src/test/run-pass/regions-static-closure.rs | 5 +- src/test/run-pass/regions-trait-object-1.rs | 6 +- ...ariance-contravariant-use-contravariant.rs | 6 +- ...egions-variance-covariant-use-covariant.rs | 4 +- src/test/run-pass/rename-directory.rs | 55 - src/test/run-pass/repeat-expr-in-static.rs | 6 +- src/test/run-pass/resolve-issue-2428.rs | 6 +- .../run-pass/resource-assign-is-not-copy.rs | 4 +- src/test/run-pass/resource-destruct.rs | 6 +- src/test/run-pass/resource-in-struct.rs | 2 + src/test/run-pass/ret-bang.rs | 6 +- src/test/run-pass/ret-none.rs | 4 +- src/test/run-pass/return-from-closure.rs | 8 +- src/test/run-pass/return-nil.rs | 2 + src/test/run-pass/running-with-no-runtime.rs | 22 +- src/test/run-pass/rust-log-filter.rs | 10 +- src/test/run-pass/segfault-no-out-of-stack.rs | 6 +- src/test/run-pass/self-impl.rs | 6 +- .../self-in-mut-slot-default-method.rs | 10 +- .../self-in-mut-slot-immediate-value.rs | 6 +- src/test/run-pass/self-re-assign.rs | 4 +- src/test/run-pass/self-shadowing-import.rs | 5 +- src/test/run-pass/self-type-param.rs | 4 +- .../run-pass/send-is-not-static-par-for.rs | 6 +- src/test/run-pass/send-resource.rs | 12 +- src/test/run-pass/send-type-inference.rs | 2 + src/test/run-pass/send_str_hashmap.rs | 6 +- src/test/run-pass/send_str_treemap.rs | 6 +- src/test/run-pass/sendable-class.rs | 6 +- src/test/run-pass/sendfn-is-a-block.rs | 10 +- src/test/run-pass/sendfn-spawn-with-fn-arg.rs | 6 +- src/test/run-pass/sepcomp-cci.rs | 8 +- src/test/run-pass/sepcomp-extern.rs | 12 +- src/test/run-pass/sepcomp-fns-backwards.rs | 11 +- src/test/run-pass/sepcomp-fns.rs | 8 +- src/test/run-pass/sepcomp-lib-lto.rs | 1 + src/test/run-pass/sepcomp-lib.rs | 2 + src/test/run-pass/sepcomp-statics.rs | 15 +- src/test/run-pass/sepcomp-unwind.rs | 4 +- src/test/run-pass/seq-compare.rs | 2 + src/test/run-pass/shadow.rs | 10 +- src/test/run-pass/shift-near-oflo.rs | 100 + src/test/run-pass/shift-various-types.rs | 24 +- src/test/run-pass/shift.rs | 64 +- src/test/run-pass/show-boxed-slice.rs | 6 +- src/test/run-pass/signal-exit-status.rs | 5 +- src/test/run-pass/signed-shift-const-eval.rs | 4 +- .../run-pass/sigpipe-should-be-ignored.rs | 21 +- src/test/run-pass/simd-binop.rs | 5 + src/test/run-pass/simd-generics.rs | 4 +- src/test/run-pass/simd-issue-10604.rs | 2 + src/test/run-pass/simd-size-align.rs | 2 + src/test/run-pass/simd-type.rs | 2 + src/test/run-pass/simple-generic-match.rs | 4 +- src/test/run-pass/simple-generic-tag.rs | 2 + src/test/run-pass/simple-match-generic-tag.rs | 4 +- .../run-pass/single-derive-attr-with-gate.rs | 20 + src/test/run-pass/size-and-align.rs | 6 +- src/test/run-pass/sized-borrowed-pointer.rs | 2 + src/test/run-pass/sized-owned-pointer.rs | 2 + src/test/run-pass/slice-2.rs | 42 +- src/test/run-pass/slice-panic-1.rs | 4 +- src/test/run-pass/slice-panic-2.rs | 6 +- src/test/run-pass/slice.rs | 22 +- src/test/run-pass/small-enum-range-edge.rs | 13 +- src/test/run-pass/small-enums-with-fields.rs | 12 +- src/test/run-pass/smallest-hello-world.rs | 8 +- .../snake-case-no-lowercase-equivalent.rs | 2 + src/test/run-pass/spawn-fn.rs | 14 +- src/test/run-pass/spawn-types.rs | 6 +- src/test/run-pass/spawn.rs | 2 +- src/test/run-pass/spawn2.rs | 4 +- src/test/run-pass/stable-addr-of.rs | 6 +- src/test/run-pass/stat.rs | 32 - src/test/run-pass/static-assert.rs | 4 + src/test/run-pass/static-fn-inline-xc.rs | 4 +- src/test/run-pass/static-fn-trait-xc.rs | 4 +- .../run-pass/static-function-pointer-xc.rs | 6 +- src/test/run-pass/static-function-pointer.rs | 10 +- src/test/run-pass/static-impl.rs | 20 +- ...tic-method-in-trait-with-tps-intracrate.rs | 12 +- src/test/run-pass/static-method-xcrate.rs | 4 +- src/test/run-pass/static-methods-in-traits.rs | 16 +- .../run-pass/static-methods-in-traits2.rs | 2 + src/test/run-pass/static-mut-foreign.rs | 4 + src/test/run-pass/static-mut-xc.rs | 8 +- .../run-pass/std-sync-right-kind-impls.rs | 31 + src/test/run-pass/str-multiline.rs | 2 + src/test/run-pass/string-escapes.rs | 2 + src/test/run-pass/string-self-append.rs | 4 +- src/test/run-pass/struct-aliases-xcrate.rs | 3 +- src/test/run-pass/struct-aliases.rs | 7 +- .../struct-destructuring-cross-crate.rs | 2 + .../run-pass/struct-like-variant-construct.rs | 6 +- .../run-pass/struct-like-variant-match.rs | 6 +- src/test/run-pass/struct-new-as-field-name.rs | 4 +- src/test/run-pass/struct-order-of-eval-1.rs | 7 +- src/test/run-pass/struct-order-of-eval-2.rs | 5 +- src/test/run-pass/struct-order-of-eval-3.rs | 48 + src/test/run-pass/struct-order-of-eval-4.rs | 45 + src/test/run-pass/struct-partial-move-1.rs | 4 +- src/test/run-pass/struct-partial-move-2.rs | 4 +- src/test/run-pass/struct-pattern-matching.rs | 4 +- src/test/run-pass/struct-return.rs | 34 +- .../struct-variant-field-visibility.rs | 4 +- src/test/run-pass/struct_variant_xc.rs | 2 + src/test/run-pass/struct_variant_xc_match.rs | 2 + src/test/run-pass/structured-compare.rs | 4 +- src/test/run-pass/super-fast-paren-parsing.rs | 2 +- src/test/run-pass/super.rs | 2 + .../run-pass/supertrait-default-generics.rs | 2 + src/test/run-pass/supported-cast.rs | 62 +- src/test/run-pass/svh-add-comment.rs | 2 + src/test/run-pass/svh-add-doc.rs | 2 + src/test/run-pass/svh-add-macro.rs | 2 + src/test/run-pass/svh-add-nothing.rs | 2 + src/test/run-pass/svh-add-redundant-cfg.rs | 2 + src/test/run-pass/svh-add-whitespace.rs | 2 + src/test/run-pass/swap-1.rs | 2 + src/test/run-pass/swap-2.rs | 4 +- src/test/run-pass/swap-overlapping.rs | 6 +- .../sync-send-iterators-in-libcollections.rs | 100 + src/test/run-pass/syntax-extension-cfg.rs | 2 + .../includeme.fragment | 2 +- .../run-pass/syntax-extension-source-utils.rs | 14 +- src/test/run-pass/syntax-trait-polarity.rs | 4 +- src/test/run-pass/tag-align-dyn-u64.rs | 14 +- src/test/run-pass/tag-align-dyn-variants.rs | 54 +- src/test/run-pass/tag-align-shape.rs | 2 +- src/test/run-pass/tag-align-u64.rs | 14 +- src/test/run-pass/tag-exports.rs | 2 + src/test/run-pass/tag-in-block.rs | 2 + .../tag-variant-disr-type-mismatch.rs | 2 + src/test/run-pass/tag-variant-disr-val.rs | 10 +- src/test/run-pass/tag.rs | 4 +- src/test/run-pass/tail-call-arg-leak.rs | 2 + src/test/run-pass/tail-cps.rs | 4 +- src/test/run-pass/tail-direct.rs | 6 +- src/test/run-pass/task-comm-0.rs | 10 +- src/test/run-pass/task-comm-1.rs | 6 +- src/test/run-pass/task-comm-10.rs | 8 +- src/test/run-pass/task-comm-11.rs | 10 +- src/test/run-pass/task-comm-12.rs | 12 +- src/test/run-pass/task-comm-13.rs | 10 +- src/test/run-pass/task-comm-14.rs | 10 +- src/test/run-pass/task-comm-15.rs | 10 +- src/test/run-pass/task-comm-16.rs | 18 +- src/test/run-pass/task-comm-17.rs | 8 +- src/test/run-pass/task-comm-3.rs | 16 +- src/test/run-pass/task-comm-4.rs | 4 +- src/test/run-pass/task-comm-5.rs | 10 +- src/test/run-pass/task-comm-6.rs | 10 +- src/test/run-pass/task-comm-7.rs | 27 +- src/test/run-pass/task-comm-9.rs | 18 +- src/test/run-pass/task-comm-chan-nil.rs | 2 + src/test/run-pass/task-life-0.rs | 8 +- src/test/run-pass/task-spawn-move-and-copy.rs | 16 +- src/test/run-pass/task-stderr.rs | 31 +- src/test/run-pass/tcp-accept-stress.rs | 12 +- src/test/run-pass/tcp-connect-timeouts.rs | 7 +- src/test/run-pass/tcp-stress.rs | 15 +- src/test/run-pass/tempfile.rs | 11 +- src/test/run-pass/terminate-in-initializer.rs | 12 +- ...e-verification-for-explicit-return-type.rs | 7 +- .../run-pass/test-should-fail-good-message.rs | 10 +- src/test/run-pass/threads.rs | 8 +- src/test/run-pass/trailing-comma.rs | 13 +- src/test/run-pass/trait-bounds-basic.rs | 3 + ...trait-bounds-impl-comparison-duplicates.rs | 6 +- src/test/run-pass/trait-bounds-in-arc.rs | 31 +- .../trait-bounds-on-structs-and-enums.rs | 4 + src/test/run-pass/trait-bounds-recursion.rs | 4 + src/test/run-pass/trait-bounds.rs | 6 +- src/test/run-pass/trait-cache-issue-18209.rs | 2 + src/test/run-pass/trait-coercion-generic.rs | 13 +- src/test/run-pass/trait-coercion.rs | 23 +- .../run-pass/trait-composition-trivial.rs | 2 + src/test/run-pass/trait-contravariant-self.rs | 2 - .../trait-default-method-bound-subst.rs | 2 + .../trait-default-method-bound-subst2.rs | 4 +- .../trait-default-method-bound-subst3.rs | 4 +- .../trait-default-method-bound-subst4.rs | 12 +- .../run-pass/trait-default-method-bound.rs | 6 +- .../run-pass/trait-default-method-xc-2.rs | 6 +- src/test/run-pass/trait-default-method-xc.rs | 12 +- ...se-ambiguity-where-clause-builtin-bound.rs | 2 + src/test/run-pass/trait-generic.rs | 12 +- .../trait-impl-2.rs} | 19 +- src/test/run-pass/trait-impl.rs | 6 +- .../run-pass/trait-inheritance-auto-xc-2.rs | 4 +- .../run-pass/trait-inheritance-auto-xc.rs | 12 +- src/test/run-pass/trait-inheritance-auto.rs | 16 +- .../trait-inheritance-call-bound-inherited.rs | 14 +- ...trait-inheritance-call-bound-inherited2.rs | 18 +- ...ritance-cast-without-call-to-supertrait.rs | 12 +- src/test/run-pass/trait-inheritance-cast.rs | 12 +- .../trait-inheritance-cross-trait-call-xc.rs | 8 +- .../trait-inheritance-cross-trait-call.rs | 12 +- .../run-pass/trait-inheritance-diamond.rs | 18 +- .../trait-inheritance-multiple-inheritors.rs | 14 +- .../trait-inheritance-multiple-params.rs | 14 +- src/test/run-pass/trait-inheritance-num.rs | 5 +- src/test/run-pass/trait-inheritance-num0.rs | 7 +- src/test/run-pass/trait-inheritance-num1.rs | 4 + src/test/run-pass/trait-inheritance-num2.rs | 19 +- src/test/run-pass/trait-inheritance-num3.rs | 2 + src/test/run-pass/trait-inheritance-num5.rs | 8 +- .../trait-inheritance-overloading-simple.rs | 4 +- .../trait-inheritance-overloading-xc-exe.rs | 4 +- .../run-pass/trait-inheritance-overloading.rs | 4 +- .../trait-inheritance-self-in-supertype.rs | 2 + src/test/run-pass/trait-inheritance-self.rs | 2 +- src/test/run-pass/trait-inheritance-simple.rs | 16 +- src/test/run-pass/trait-inheritance-static.rs | 8 +- .../run-pass/trait-inheritance-static2.rs | 10 +- src/test/run-pass/trait-inheritance-subst.rs | 6 +- src/test/run-pass/trait-inheritance-subst2.rs | 6 +- .../run-pass/trait-inheritance-visibility.rs | 6 +- src/test/run-pass/trait-inheritance2.rs | 16 +- src/test/run-pass/trait-object-generics.rs | 8 +- .../trait-object-with-lifetime-bound.rs | 6 +- .../run-pass/trait-region-pointer-simple.rs | 6 +- src/test/run-pass/trait-safety-ok-cc.rs | 14 +- src/test/run-pass/trait-safety-ok.rs | 12 +- .../trait-static-method-overwriting.rs | 1 - src/test/run-pass/trait-to-str.rs | 2 +- .../run-pass/trait-where-clause-vs-impl.rs | 2 + .../run-pass/trait-with-bounds-default.rs | 4 +- .../traits-assoc-type-in-supertrait.rs | 33 + .../run-pass/traits-conditional-dispatch.rs | 20 +- .../run-pass/traits-conditional-model-fn.rs | 10 +- .../run-pass/traits-default-method-macro.rs | 2 + .../run-pass/traits-default-method-mut.rs | 4 +- .../run-pass/traits-default-method-self.rs | 2 +- .../run-pass/traits-default-method-trivial.rs | 2 +- src/test/run-pass/traits-issue-22019.rs | 2 + src/test/run-pass/traits-issue-22110.rs | 2 + src/test/run-pass/traits-issue-22655.rs | 31 + src/test/run-pass/traits-issue-23003.rs | 41 + ...aits-multidispatch-infer-convert-target.rs | 4 +- .../run-pass/traits-repeated-supertrait.rs | 58 + src/test/run-pass/trans-tag-static-padding.rs | 2 + .../transmute-non-immediate-to-immediate.rs | 4 +- src/test/run-pass/trivial_casts.rs | 71 + src/test/run-pass/tup.rs | 6 +- src/test/run-pass/tuple-index-fat-types.rs | 8 +- src/test/run-pass/tuple-index.rs | 4 +- src/test/run-pass/tuple-struct-construct.rs | 2 +- .../tuple-struct-constructor-pointer.rs | 8 +- .../run-pass/tuple-struct-destructuring.rs | 2 +- src/test/run-pass/tuple-struct-matching.rs | 2 +- src/test/run-pass/tuple-struct-trivial.rs | 4 +- src/test/run-pass/tydesc-name.rs | 9 +- src/test/run-pass/type-id-higher-rank.rs | 36 +- src/test/run-pass/type-in-nested-module.rs | 4 +- src/test/run-pass/type-namespace.rs | 6 +- src/test/run-pass/type-param-constraints.rs | 14 +- src/test/run-pass/type-param.rs | 2 + src/test/run-pass/type-params-in-for-each.rs | 12 +- src/test/run-pass/type-ptr.rs | 6 +- src/test/run-pass/type-sizes.rs | 38 +- src/test/run-pass/type-use-i1-versus-i8.rs | 2 + .../typeck-macro-interaction-issue-8852.rs | 4 +- .../run-pass/typeck_type_placeholder_1.rs | 16 +- src/test/run-pass/typeid-intrinsic.rs | 20 +- src/test/run-pass/typestate-cfg-nesting.rs | 2 + src/test/run-pass/typestate-multi-decl.rs | 2 + src/test/run-pass/u32-decr.rs | 8 +- src/test/run-pass/u8-incr-decr.rs | 10 +- src/test/run-pass/u8-incr.rs | 14 +- src/test/run-pass/ufcs-explicit-self.rs | 25 +- ...hic-paths.rs => ufcs-polymorphic-paths.rs} | 81 +- src/test/run-pass/ufcs-trait-object.rs | 4 +- src/test/run-pass/ufcs-type-params.rs | 2 + src/test/run-pass/uint.rs | 4 +- .../run-pass/unary-minus-suffix-inference.rs | 4 +- .../run-pass/unboxed-closures-all-traits.rs | 17 +- .../unboxed-closures-blanket-fn-mut.rs | 37 + .../run-pass/unboxed-closures-blanket-fn.rs | 37 + src/test/run-pass/unboxed-closures-boxed.rs | 1 - src/test/run-pass/unboxed-closures-by-ref.rs | 2 + .../unboxed-closures-call-fn-autoderef.rs | 8 +- .../unboxed-closures-call-sugar-autoderef.rs | 6 +- ...ed-closures-call-sugar-object-autoderef.rs | 7 +- .../unboxed-closures-call-sugar-object.rs | 7 +- .../unboxed-closures-counter-not-moved.rs | 2 + .../run-pass/unboxed-closures-cross-crate.rs | 4 +- .../unboxed-closures-direct-sugary-call.rs | 3 +- src/test/run-pass/unboxed-closures-drop.rs | 33 +- .../run-pass/unboxed-closures-extern-fn-hr.rs | 15 +- .../run-pass/unboxed-closures-extern-fn.rs | 11 +- ...unboxed-closures-fn-as-fnmut-and-fnonce.rs | 16 +- .../unboxed-closures-fnmut-as-fnonce.rs | 14 +- src/test/run-pass/unboxed-closures-generic.rs | 1 - ...nfer-argument-types-from-expected-bound.rs | 8 +- ...rgument-types-from-expected-object-type.rs | 8 +- ...-with-bound-regions-from-expected-bound.rs | 8 +- ...oxed-closures-infer-fnmut-calling-fnmut.rs | 3 +- .../unboxed-closures-infer-fnmut-move.rs | 2 + .../run-pass/unboxed-closures-infer-fnmut.rs | 2 + .../unboxed-closures-infer-fnonce-move.rs | 2 + .../run-pass/unboxed-closures-infer-fnonce.rs | 2 + .../run-pass/unboxed-closures-infer-kind.rs | 2 + .../unboxed-closures-infer-recursive-fn.rs | 13 +- .../run-pass/unboxed-closures-infer-upvar.rs | 4 +- .../run-pass/unboxed-closures-manual-impl.rs | 14 +- .../unboxed-closures-monomorphization.rs | 7 +- .../run-pass/unboxed-closures-move-mutable.rs | 4 +- ...ures-move-some-upvars-in-by-ref-closure.rs | 2 + src/test/run-pass/unboxed-closures-prelude.rs | 12 +- src/test/run-pass/unboxed-closures-simple.rs | 4 +- .../unboxed-closures-single-word-env.rs | 15 +- .../unboxed-closures-static-call-fn-once.rs | 3 +- .../run-pass/unboxed-closures-sugar-object.rs | 2 + .../unboxed-closures-unique-type-id.rs | 12 +- .../run-pass/unboxed-closures-zero-args.rs | 3 +- src/test/run-pass/unfold-cross-crate.rs | 6 +- src/test/run-pass/unify-return-ty.rs | 4 +- src/test/run-pass/uninit-empty-types.rs | 2 + src/test/run-pass/uniq-self-in-mut-slot.rs | 6 +- src/test/run-pass/unique-assign-copy.rs | 4 +- src/test/run-pass/unique-assign-drop.rs | 6 +- src/test/run-pass/unique-assign-generic.rs | 4 +- src/test/run-pass/unique-assign.rs | 4 +- src/test/run-pass/unique-autoderef-field.rs | 6 +- src/test/run-pass/unique-autoderef-index.rs | 4 +- src/test/run-pass/unique-cmp.rs | 4 +- src/test/run-pass/unique-containing-tag.rs | 6 +- src/test/run-pass/unique-create.rs | 4 +- src/test/run-pass/unique-decl-init-copy.rs | 4 +- src/test/run-pass/unique-decl-init.rs | 4 +- src/test/run-pass/unique-decl-move.rs | 4 +- src/test/run-pass/unique-decl.rs | 6 +- src/test/run-pass/unique-deref.rs | 4 +- src/test/run-pass/unique-destructure.rs | 4 +- src/test/run-pass/unique-drop-complex.rs | 4 +- src/test/run-pass/unique-fn-arg-move.rs | 4 +- src/test/run-pass/unique-fn-arg-mut.rs | 4 +- src/test/run-pass/unique-fn-arg.rs | 4 +- src/test/run-pass/unique-fn-ret.rs | 4 +- src/test/run-pass/unique-generic-assign.rs | 2 + src/test/run-pass/unique-in-tag.rs | 2 +- src/test/run-pass/unique-in-vec-copy.rs | 4 +- src/test/run-pass/unique-in-vec.rs | 4 +- src/test/run-pass/unique-init.rs | 4 +- src/test/run-pass/unique-kinds.rs | 26 +- src/test/run-pass/unique-log.rs | 2 +- src/test/run-pass/unique-match-discrim.rs | 5 +- src/test/run-pass/unique-move-drop.rs | 6 +- src/test/run-pass/unique-move-temp.rs | 4 +- src/test/run-pass/unique-move.rs | 4 +- src/test/run-pass/unique-mutable.rs | 4 +- src/test/run-pass/unique-object-move.rs | 4 +- src/test/run-pass/unique-pat-2.rs | 10 +- src/test/run-pass/unique-pat-3.rs | 2 +- src/test/run-pass/unique-pat.rs | 2 + src/test/run-pass/unique-rec.rs | 6 +- src/test/run-pass/unique-send-2.rs | 16 +- src/test/run-pass/unique-send.rs | 4 +- src/test/run-pass/unique-swap.rs | 6 +- .../run-pass/unit-like-struct-drop-run.rs | 7 +- src/test/run-pass/unit.rs | 2 + src/test/run-pass/unnamed_argument_mode.rs | 8 +- src/test/run-pass/unreachable-code-1.rs | 2 + src/test/run-pass/unreachable-code.rs | 2 + src/test/run-pass/unsafe-coercion.rs | 27 + .../unsafe-fn-called-from-unsafe-blk.rs | 2 + .../unsafe-fn-called-from-unsafe-fn.rs | 2 + .../run-pass/unsafe-pointer-assignability.rs | 4 +- src/test/run-pass/unsized.rs | 4 +- src/test/run-pass/unsized2.rs | 10 +- src/test/run-pass/unsized3.rs | 32 +- src/test/run-pass/unused-move-capture.rs | 4 +- src/test/run-pass/unused-move.rs | 4 +- src/test/run-pass/unwind-resource.rs | 3 +- src/test/run-pass/unwind-unique.rs | 7 +- src/test/run-pass/use-crate-name-alias.rs | 4 +- src/test/run-pass/use-import-export.rs | 6 +- src/test/run-pass/use-mod.rs | 2 + src/test/run-pass/use-trait-before-def.rs | 6 +- src/test/run-pass/use-uninit-match.rs | 4 +- src/test/run-pass/use-uninit-match2.rs | 4 +- src/test/run-pass/use.rs | 7 +- src/test/run-pass/use_inline_dtor.rs | 2 + src/test/run-pass/utf8.rs | 28 +- src/test/run-pass/utf8_chars.rs | 34 +- src/test/run-pass/utf8_idents.rs | 2 +- src/test/run-pass/variadic-ffi.rs | 17 +- ...ariance-intersection-of-ref-and-opt-ref.rs | 3 + src/test/run-pass/variance-trait-matching.rs | 4 +- src/test/run-pass/variance-vec-covariant.rs | 3 + src/test/run-pass/variant-attributes.rs | 2 + src/test/run-pass/variant-structs-trivial.rs | 6 +- src/test/run-pass/vec-concat.rs | 8 +- src/test/run-pass/vec-dst.rs | 10 +- src/test/run-pass/vec-fixed-length.rs | 8 +- src/test/run-pass/vec-growth.rs | 2 + src/test/run-pass/vec-late-init.rs | 2 +- src/test/run-pass/vec-macro-no-std.rs | 8 +- src/test/run-pass/vec-macro-repeat.rs | 2 + src/test/run-pass/vec-macro-rvalue-scope.rs | 2 + src/test/run-pass/vec-macro-with-brackets.rs | 2 + .../run-pass/vec-macro-with-trailing-comma.rs | 2 + src/test/run-pass/vec-matching-autoslice.rs | 4 + src/test/run-pass/vec-matching-fixed.rs | 3 + src/test/run-pass/vec-matching-fold.rs | 3 + .../vec-matching-legal-tail-element-borrow.rs | 4 +- src/test/run-pass/vec-matching.rs | 5 +- src/test/run-pass/vec-push.rs | 2 + src/test/run-pass/vec-repeat-with-cast.rs | 4 +- src/test/run-pass/vec-slice-drop.rs | 6 +- src/test/run-pass/vec-slice.rs | 2 + src/test/run-pass/vec-tail-matching.rs | 4 + src/test/run-pass/vec-to_str.rs | 4 +- src/test/run-pass/vec.rs | 6 +- src/test/run-pass/vector-no-ann-2.rs | 4 +- src/test/run-pass/vector-sort-panic-safe.rs | 6 +- .../visible-private-types-feature-gate.rs | 3 +- .../run-pass/wait-forked-but-failed-child.rs | 4 + src/test/run-pass/warn-ctypes-inhibit.rs | 4 +- src/test/run-pass/weak-lang-item.rs | 4 +- src/test/run-pass/weird-exprs.rs | 6 +- .../wf-bound-region-in-object-type.rs | 8 +- .../where-clause-bounds-inconsistency.rs | 2 + .../where-clause-early-bound-lifetimes.rs | 6 +- .../where-clause-method-substituion.rs | 3 +- .../run-pass/where-clause-region-outlives.rs | 4 +- .../run-pass/where-clauses-cross-crate.rs | 3 +- src/test/run-pass/where-clauses-lifetimes.rs | 4 +- .../where-clauses-unboxed-closures.rs | 3 +- src/test/run-pass/where-clauses.rs | 3 +- src/test/run-pass/where-for-self.rs | 5 +- src/test/run-pass/while-flow-graph.rs | 4 +- src/test/run-pass/while-label.rs | 2 + src/test/run-pass/while-let.rs | 6 +- src/test/run-pass/while-loop-constraints-2.rs | 6 +- src/test/run-pass/while-prelude-drop.rs | 6 +- src/test/run-pass/while-with-break.rs | 4 +- src/test/run-pass/while.rs | 4 +- src/test/run-pass/writealias.rs | 4 +- src/test/run-pass/x86stdcall.rs | 7 +- src/test/run-pass/x86stdcall2.rs | 12 +- .../run-pass/xcrate-address-insignificant.rs | 4 +- src/test/run-pass/xcrate-static-addresses.rs | 2 + .../run-pass/xcrate-trait-lifetime-param.rs | 4 +- src/test/run-pass/xcrate-unit-struct.rs | 2 + src/test/run-pass/yield2.rs | 2 +- .../run-pass/zero-size-type-destructors.rs | 4 +- .../run-pass/zero_sized_subslice_match.rs | 6 +- 3783 files changed, 81650 insertions(+), 61416 deletions(-) create mode 100644 mk/cfg/x86_64-unknown-bitrig.mk create mode 100644 src/doc/trpl/associated-types.md create mode 100644 src/doc/trpl/benchmark-tests.md create mode 100644 src/doc/trpl/box-syntax-and-patterns.md delete mode 100644 src/doc/trpl/guessing-game.md create mode 100644 src/doc/trpl/inline-assembly.md create mode 100644 src/doc/trpl/intrinsics.md create mode 100644 src/doc/trpl/lang-items.md create mode 100644 src/doc/trpl/link-args.md create mode 100644 src/doc/trpl/no-stdlib.md delete mode 100644 src/doc/trpl/standard-input.md create mode 100644 src/doc/trpl/tracing-macros.md create mode 100644 src/doc/trpl/unstable.md create mode 100644 src/etc/check-sanitycheck.py delete mode 100644 src/libcollections/borrow_stage0.rs rename src/{libcollections => libcollectionstest}/bench.rs (92%) create mode 100644 src/libcollectionstest/binary_heap.rs rename src/{test/pretty/issue-929.rs => libcollectionstest/bit/mod.rs} (76%) create mode 100644 src/libcollectionstest/bit/set.rs create mode 100644 src/libcollectionstest/bit/vec.rs create mode 100644 src/libcollectionstest/btree/map.rs rename src/{libcoretest/num/int.rs => libcollectionstest/btree/mod.rs} (95%) create mode 100644 src/libcollectionstest/btree/set.rs create mode 100644 src/libcollectionstest/enum_set.rs create mode 100644 src/libcollectionstest/fmt.rs create mode 100644 src/libcollectionstest/lib.rs create mode 100644 src/libcollectionstest/linked_list.rs create mode 100644 src/libcollectionstest/slice.rs create mode 100644 src/libcollectionstest/str.rs create mode 100644 src/libcollectionstest/string.rs create mode 100644 src/libcollectionstest/vec.rs create mode 100644 src/libcollectionstest/vec_deque.rs create mode 100644 src/libcollectionstest/vec_map.rs create mode 100644 src/libcore/cmp_macros.rs create mode 100644 src/libcore/convert.rs delete mode 100644 src/libcore/error.rs delete mode 100644 src/libcore/finally.rs create mode 100644 src/libcore/fmt/builders.rs delete mode 100644 src/libcore/num/int.rs create mode 100644 src/libcore/num/wrapping.rs create mode 100644 src/libcore/str/pattern.rs delete mode 100644 src/libcoretest/finally.rs create mode 100644 src/libcoretest/fmt/builders.rs delete mode 100644 src/librbml/io.rs create mode 100644 src/librustc/README.md delete mode 100644 src/librustc/README.txt create mode 100644 src/librustc/middle/ty_match.rs create mode 100644 src/librustc/middle/ty_relate/mod.rs rename src/{test/compile-fail/issue-13853-4.rs => librustc_back/target/bitrig_base.rs} (54%) create mode 100644 src/librustc_back/target/x86_64_unknown_bitrig.rs create mode 100644 src/librustc_back/tempdir.rs create mode 100644 src/librustc_lint/builtin.rs create mode 100644 src/librustc_lint/lib.rs create mode 100644 src/librustc_resolve/resolve_imports.rs create mode 100644 src/librustc_typeck/check/op.rs delete mode 100644 src/librustc_typeck/coherence/impls.rs create mode 100644 src/libstd/array.rs delete mode 100644 src/libstd/collections/hash/map_stage0.rs delete mode 100644 src/libstd/collections/hash/set_stage0.rs create mode 100644 src/libstd/error.rs create mode 100644 src/libstd/io/lazy.rs create mode 100644 src/libstd/io/stdio.rs delete mode 100644 src/libstd/num/int.rs delete mode 100644 src/libstd/num/uint.rs mode change 100755 => 100644 src/libstd/path.rs delete mode 100644 src/libstd/sync/task_pool.rs create mode 100644 src/libstd/sys/unix/stdio.rs create mode 100644 src/libstd/sys/windows/stdio.rs rename src/libstd/{thread_local/mod.rs => thread/local.rs} (81%) rename src/libstd/{thread.rs => thread/mod.rs} (71%) rename src/libstd/{thread_local => thread}/scoped.rs (84%) rename src/libunicode/{u_char.rs => char.rs} (51%) rename src/llvm/lib/ExecutionEngine/{ => RuntimeDyld}/RTDyldMemoryManager.cpp (100%) mode change 100644 => 100755 src/rust-installer/combine-installers.sh rename src/test/{compile-fail/issue-16465.rs => auxiliary/coherence_copy_like_lib.rs} (59%) rename src/test/auxiliary/{coherence-lib.rs => coherence_lib.rs} (100%) rename src/test/auxiliary/{coherence-orphan-lib.rs => coherence_orphan_lib.rs} (99%) create mode 100644 src/test/auxiliary/crate_with_invalid_spans.rs create mode 100644 src/test/auxiliary/crate_with_invalid_spans_macros.rs rename src/{libcore/num/uint.rs => test/auxiliary/cross_crate_spans.rs} (50%) create mode 100644 src/test/auxiliary/custom_derive_plugin.rs create mode 100644 src/test/auxiliary/internal_unstable.rs rename src/test/auxiliary/{issue-11680.rs => issue_11680.rs} (93%) rename src/test/auxiliary/{issue-12612-1.rs => issue_12612_1.rs} (100%) rename src/test/auxiliary/{issue-12612-2.rs => issue_12612_2.rs} (100%) rename src/test/auxiliary/{issue-16725.rs => issue_16725.rs} (99%) rename src/test/auxiliary/{issue-17718-const-privacy.rs => issue_17718_const_privacy.rs} (86%) rename src/test/auxiliary/{issue-21202.rs => issue_21202.rs} (100%) create mode 100644 src/test/auxiliary/lint_for_crate.rs mode change 100755 => 100644 src/test/auxiliary/lint_output_format.rs create mode 100644 src/test/auxiliary/lint_stability_fields.rs rename src/test/auxiliary/{lint-unused-extern-crate.rs => lint_unused_extern_crate.rs} (100%) rename src/test/auxiliary/{privacy-tuple-struct.rs => privacy_tuple_struct.rs} (86%) create mode 100644 src/test/auxiliary/procedural_mbe_matching.rs rename src/test/{compile-fail/bad-crate-id.rs => auxiliary/pub_static_array.rs} (85%) rename src/test/auxiliary/{regions-bounded-method-type-parameters-cross-crate-lib.rs => regions_bounded_method_type_parameters_cross_crate_lib.rs} (95%) rename src/test/auxiliary/{struct-field-privacy.rs => struct_field_privacy.rs} (88%) rename src/test/auxiliary/{trait-safety-lib.rs => trait_safety_lib.rs} (85%) create mode 100644 src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs rename src/test/auxiliary/{unreachable-variant.rs => unreachable_variant.rs} (100%) create mode 100644 src/test/compile-fail-fulldeps/gated-macro-reexports.rs create mode 100644 src/test/compile-fail-fulldeps/gated-quote.rs create mode 100644 src/test/compile-fail-fulldeps/issue-15778-fail.rs create mode 100644 src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs create mode 100644 src/test/compile-fail/borrowck-consume-unsize-vec.rs create mode 100644 src/test/compile-fail/borrowck-consume-upcast-box.rs rename src/test/compile-fail/{issue-5543.rs => borrowck-fn-in-const-a.rs} (69%) create mode 100644 src/test/compile-fail/borrowck-fn-in-const-b.rs create mode 100644 src/test/compile-fail/borrowck-fn-in-const-c.rs rename src/test/compile-fail/{borrowck-overloaded-index-2.rs => borrowck-overloaded-index-move-from-vec.rs} (88%) create mode 100644 src/test/compile-fail/borrowck-overloaded-index-move-index.rs rename src/test/compile-fail/{borrowck-overloaded-index.rs => borrowck-overloaded-index-ref-index.rs} (82%) create mode 100644 src/test/compile-fail/cfg-attr-unknown-attribute-macro-expansion.rs create mode 100644 src/test/compile-fail/coherence-cow-1.rs create mode 100644 src/test/compile-fail/coherence-cow-2.rs create mode 100644 src/test/compile-fail/coherence-default-trait-impl.rs create mode 100644 src/test/compile-fail/coherence-impls-copy.rs rename src/test/compile-fail/{coherence-impls-builtin.rs => coherence-impls-send.rs} (69%) create mode 100644 src/test/compile-fail/coherence-impls-sized.rs create mode 100644 src/test/compile-fail/coherence-overlap-issue-23516.rs create mode 100644 src/test/compile-fail/coherence-vec-local-2.rs create mode 100644 src/test/compile-fail/coherence-vec-local.rs create mode 100644 src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs create mode 100644 src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs create mode 100644 src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs create mode 100644 src/test/compile-fail/coherence_copy_like_err_struct.rs create mode 100644 src/test/compile-fail/coherence_copy_like_err_tuple.rs create mode 100644 src/test/compile-fail/coherence_local.rs create mode 100644 src/test/compile-fail/coherence_local_err_struct.rs create mode 100644 src/test/compile-fail/coherence_local_err_tuple.rs create mode 100644 src/test/compile-fail/coherence_local_ref.rs create mode 100644 src/test/compile-fail/const-array-oob.rs create mode 100644 src/test/compile-fail/const-eval-overflow-2.rs create mode 100644 src/test/compile-fail/const-eval-overflow-3.rs create mode 100644 src/test/compile-fail/const-eval-overflow-3b.rs create mode 100644 src/test/compile-fail/const-eval-overflow-4.rs create mode 100644 src/test/compile-fail/const-eval-overflow-4b.rs create mode 100644 src/test/compile-fail/const-eval-overflow.rs create mode 100644 src/test/compile-fail/const-len-underflow-separate-spans.rs create mode 100644 src/test/compile-fail/const-len-underflow-subspans.rs create mode 100644 src/test/compile-fail/cycle-projection-based-on-where-clause.rs create mode 100644 src/test/compile-fail/cycle-trait-default-type-trait.rs rename src/test/{run-pass/coherence-local-1.rs => compile-fail/cycle-trait-supertrait-direct.rs} (67%) create mode 100644 src/test/compile-fail/cycle-trait-supertrait-indirect.rs create mode 100644 src/test/compile-fail/derive-assoc-type-not-impl.rs create mode 100644 src/test/compile-fail/discrim-ill-typed.rs create mode 100644 src/test/compile-fail/discrim-overflow-2.rs create mode 100644 src/test/compile-fail/discrim-overflow.rs create mode 100644 src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs create mode 100644 src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs create mode 100644 src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs create mode 100644 src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs rename src/test/compile-fail/{plugin-extern-crate-attr-deprecated.rs => feature-gate-allow-internal-unstable.rs} (77%) delete mode 100644 src/test/compile-fail/feature-gate-int-uint.rs rename src/test/compile-fail/{feature-gate-intrinsics-and-lang-items.rs => feature-gate-intrinsics.rs} (89%) rename src/test/{run-pass/deprecated-no-split-stack.rs => compile-fail/feature-gate-lang-items.rs} (84%) rename src/test/compile-fail/{kindck-destructor-owned.rs => feature-gate-rust-call.rs} (68%) rename src/test/compile-fail/{bad-crate-id2.rs => feature-gate-static-assert.rs} (72%) rename src/test/compile-fail/{lint-unnecessary-casts.rs => gated-box-patterns.rs} (53%) create mode 100644 src/test/compile-fail/gated-box-syntax.rs create mode 100644 src/test/compile-fail/gated-link-args.rs create mode 100644 src/test/compile-fail/gated-link-llvm-intrinsics.rs create mode 100644 src/test/compile-fail/gated-simd-ffi.rs create mode 100644 src/test/compile-fail/gated-thread-local.rs create mode 100644 src/test/compile-fail/gated-unsafe-destructor.rs delete mode 100644 src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs create mode 100644 src/test/compile-fail/if-loop.rs create mode 100644 src/test/compile-fail/internal-unstable-noallow.rs rename src/test/compile-fail/{unsafe-destructor-check-crash.rs => internal-unstable-thread-local.rs} (62%) create mode 100755 src/test/compile-fail/internal-unstable.rs create mode 100644 src/test/compile-fail/invalid-inline.rs rename src/test/{run-pass => compile-fail}/issue-13352.rs (86%) create mode 100644 src/test/compile-fail/issue-13407.rs delete mode 100644 src/test/compile-fail/issue-13853-3.rs create mode 100644 src/test/compile-fail/issue-16922.rs create mode 100644 src/test/compile-fail/issue-18919.rs create mode 100644 src/test/compile-fail/issue-19982.rs create mode 100644 src/test/compile-fail/issue-20225.rs create mode 100644 src/test/compile-fail/issue-20261.rs create mode 100644 src/test/compile-fail/issue-20714.rs create mode 100644 src/test/compile-fail/issue-22426-1.rs create mode 100644 src/test/compile-fail/issue-22426-2.rs create mode 100644 src/test/compile-fail/issue-22426-3.rs create mode 100644 src/test/compile-fail/issue-22912.rs create mode 100644 src/test/compile-fail/issue-23080-2.rs create mode 100644 src/test/compile-fail/issue-23080.rs delete mode 100644 src/test/compile-fail/issue-3953.rs create mode 100644 src/test/compile-fail/issue-7950.rs create mode 100644 src/test/compile-fail/lint-stability-fields.rs create mode 100644 src/test/compile-fail/lint-unsafe-code.rs create mode 100644 src/test/compile-fail/loop-labeled-break-value.rs create mode 100644 src/test/compile-fail/malformed-derive-entry.rs create mode 100644 src/test/compile-fail/manual-link-bad-search-path.rs rename src/test/compile-fail/{lint-unsafe-block.rs => match-ref-ice.rs} (50%) rename src/test/compile-fail/{trait-impl-2.rs => match-ref-mut-invariance.rs} (53%) create mode 100644 src/test/compile-fail/match-ref-mut-let-invariance.rs create mode 100644 src/test/compile-fail/move-in-guard-1.rs create mode 100644 src/test/compile-fail/move-in-guard-2.rs create mode 100644 src/test/compile-fail/nonbool_static_assert.rs rename src/test/{run-pass/coherence-cow-2.rs => compile-fail/object-safety-by-value-self-use.rs} (62%) create mode 100644 src/test/compile-fail/phantom-oibit.rs create mode 100644 src/test/compile-fail/priv_in_pub_sig_priv_mod.rs create mode 100644 src/test/compile-fail/reflect-assoc.rs create mode 100644 src/test/compile-fail/reflect-object-param.rs create mode 100644 src/test/compile-fail/reflect.rs create mode 100644 src/test/compile-fail/regions-trait-object-subtyping.rs create mode 100644 src/test/compile-fail/reject-specialized-drops-8142.rs create mode 100644 src/test/compile-fail/reserved-attr-on-macro.rs create mode 100644 src/test/compile-fail/retslot-cast.rs mode change 100755 => 100644 src/test/compile-fail/send-is-not-static-ensures-scoping.rs create mode 100644 src/test/compile-fail/send-is-not-static-std-sync-2.rs create mode 100644 src/test/compile-fail/send-is-not-static-std-sync.rs create mode 100644 src/test/compile-fail/single-derive-attr.rs create mode 100644 src/test/compile-fail/single-primitive-inherent-impl.rs create mode 100644 src/test/compile-fail/static-array-across-crate.rs create mode 100644 src/test/compile-fail/suggest-private-fields.rs create mode 100644 src/test/compile-fail/syntaxt-default-trait-impls.rs create mode 100644 src/test/compile-fail/traits-assoc-type-in-supertrait-bad.rs create mode 100644 src/test/compile-fail/traits-issue-23003-overflow.rs create mode 100644 src/test/compile-fail/traits-repeated-supertrait-ambig.rs create mode 100644 src/test/compile-fail/trivial_casts.rs create mode 100644 src/test/compile-fail/typeck-builtin-bound-type-parameters.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-negation-send.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-negation.rs rename src/test/compile-fail/{duplicate-trait-bounds.rs => typeck-default-trait-impl-outside-crate.rs} (72%) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-precedence.rs rename src/test/{parse-fail/obsolete-for-sized.rs => compile-fail/typeck-default-trait-impl-send-param.rs} (70%) create mode 100644 src/test/compile-fail/typeck-default-trait-impl-superregion.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-supertrait.rs create mode 100644 src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs create mode 100644 src/test/compile-fail/unsafe-subtyping.rs create mode 100644 src/test/compile-fail/unsafe-trait-impl.rs create mode 100644 src/test/compile-fail/unsafe_no_drop_flag-gate.rs delete mode 100644 src/test/compile-fail/unsendable-class.rs delete mode 100644 src/test/compile-fail/unsized4.rs create mode 100644 src/test/compile-fail/unused-macro-with-bad-frag-spec.rs create mode 100644 src/test/compile-fail/unused-macro-with-follow-violation.rs delete mode 100644 src/test/compile-fail/useless-priv2.rs delete mode 100644 src/test/compile-fail/variance-deprecated-markers.rs rename src/test/{run-pass/coherence-cow-1.rs => compile-fail/variance-region-bounds.rs} (65%) create mode 100644 src/test/debuginfo/constant-debug-locs.rs create mode 100644 src/test/debuginfo/cross-crate-spans.rs create mode 100644 src/test/debuginfo/extern-c-fn.rs create mode 100644 src/test/debuginfo/gdb-pretty-std.rs create mode 100644 src/test/debuginfo/issue22656.rs rename src/test/{compile-fail/slice-1.rs => parse-fail/closure-return-syntax.rs} (73%) delete mode 100644 src/test/parse-fail/extern-crate-as-no-string-help.rs create mode 100644 src/test/parse-fail/issue-22647.rs create mode 100644 src/test/parse-fail/issue-22712.rs create mode 100644 src/test/parse-fail/issue-23620-invalid-escapes.rs create mode 100644 src/test/parse-fail/lex-bad-binary-literal.rs create mode 100644 src/test/parse-fail/lex-bad-octal-literal.rs create mode 100644 src/test/parse-fail/obsolete-closure-kind.rs create mode 100644 src/test/parse-fail/trait-pub-assoc-ty.rs create mode 100644 src/test/parse-fail/trait-pub-method.rs rename src/test/{run-pass/coherence-local-2.rs => pretty/default-trait-impl.rs} (75%) rename src/test/{compile-fail => run-fail}/binop-fail-3.rs (84%) create mode 100644 src/test/run-fail/issue-23354-2.rs create mode 100644 src/test/run-fail/issue-23354.rs create mode 100644 src/test/run-fail/overflowing-add.rs create mode 100644 src/test/run-fail/overflowing-lsh-1.rs create mode 100644 src/test/run-fail/overflowing-lsh-2.rs create mode 100644 src/test/run-fail/overflowing-lsh-3.rs create mode 100644 src/test/run-fail/overflowing-lsh-4.rs create mode 100644 src/test/run-fail/overflowing-mul.rs create mode 100644 src/test/run-fail/overflowing-rsh-1.rs create mode 100644 src/test/run-fail/overflowing-rsh-2.rs create mode 100644 src/test/run-fail/overflowing-rsh-3.rs create mode 100644 src/test/run-fail/overflowing-rsh-4.rs create mode 100644 src/test/run-fail/overflowing-sub.rs create mode 100644 src/test/run-make/bare-outfile/Makefile create mode 100644 src/test/run-make/bare-outfile/foo.rs create mode 100644 src/test/run-make/debug-assertions/Makefile create mode 100644 src/test/run-make/debug-assertions/debug.rs mode change 100755 => 100644 src/test/run-make/mismatching-target-triples/bar.rs mode change 100755 => 100644 src/test/run-make/mismatching-target-triples/foo.rs create mode 100644 src/test/run-make/output-with-hyphens/Makefile rename src/test/{compile-fail/deriving-is-deprecated.rs => run-make/output-with-hyphens/foo-bar.rs} (85%) mode change 100755 => 100644 src/test/run-make/pretty-expanded-hygiene/input.pp.rs mode change 100755 => 100644 src/test/run-make/pretty-expanded-hygiene/input.rs create mode 100644 src/test/run-make/rustdoc-default-impl/Makefile rename src/test/{compile-fail/deprecated-phase.rs => run-make/rustdoc-default-impl/bar.rs} (77%) create mode 100644 src/test/run-make/rustdoc-default-impl/foo.rs create mode 100644 src/test/run-make/rustdoc-extern-default-method/Makefile create mode 100644 src/test/run-make/rustdoc-extern-default-method/ext.rs create mode 100644 src/test/run-make/rustdoc-extern-default-method/lib.rs create mode 100644 src/test/run-make/rustdoc-src-links/Makefile create mode 100644 src/test/run-make/rustdoc-src-links/foo.rs create mode 100644 src/test/run-make/rustdoc-src-links/qux/mod.rs mode change 100755 => 100644 src/test/run-make/simd-ffi/simd.rs create mode 100644 src/test/run-make/target-cpu-native/Makefile rename src/{libcoretest/num/uint.rs => test/run-make/target-cpu-native/foo.rs} (94%) create mode 100644 src/test/run-pass-fulldeps/create-dir-all-bare.rs create mode 100644 src/test/run-pass-fulldeps/derive-totalsum.rs create mode 100644 src/test/run-pass-fulldeps/issue-15778-pass.rs create mode 100644 src/test/run-pass-fulldeps/mbe_matching_test_macro.rs create mode 100644 src/test/run-pass-fulldeps/rename-directory.rs create mode 100644 src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs create mode 100644 src/test/run-pass/backtrace-debuginfo-aux.rs create mode 100644 src/test/run-pass/backtrace-debuginfo.rs create mode 100644 src/test/run-pass/binops-issue-22743.rs create mode 100644 src/test/run-pass/box-of-array-of-drop-1.rs create mode 100644 src/test/run-pass/box-of-array-of-drop-2.rs create mode 100644 src/test/run-pass/coherence_copy_like.rs create mode 100644 src/test/run-pass/cycle-generic-bound.rs create mode 100644 src/test/run-pass/cycle-trait-type-trait.rs create mode 100644 src/test/run-pass/deprecated-derive.rs create mode 100644 src/test/run-pass/deriving-associated-types.rs create mode 100644 src/test/run-pass/discrim-explicit-23030.rs create mode 100644 src/test/run-pass/drop-flag-sanity-check.rs create mode 100644 src/test/run-pass/drop-flag-skip-sanity-check.rs delete mode 100644 src/test/run-pass/export-unexported-dep.rs create mode 100644 src/test/run-pass/extern-methods.rs delete mode 100644 src/test/run-pass/extern-stress.rs delete mode 100644 src/test/run-pass/extern-yield.rs create mode 100644 src/test/run-pass/impl-inherent-non-conflict.rs create mode 100644 src/test/run-pass/impl-inherent-prefer-over-trait.rs create mode 100644 src/test/run-pass/impl-not-adjacent-to-type.rs create mode 100644 src/test/run-pass/import-crate-with-invalid-spans.rs delete mode 100644 src/test/run-pass/infer-container-across-object-cast.rs create mode 100644 src/test/run-pass/issue-11592.rs create mode 100644 src/test/run-pass/issue-11820.rs rename src/test/{compile-fail => run-pass}/issue-12729.rs (80%) create mode 100644 src/test/run-pass/issue-16922.rs create mode 100644 src/test/run-pass/issue-17233.rs create mode 100644 src/test/run-pass/issue-17746.rs create mode 100644 src/test/run-pass/issue-19982.rs create mode 100644 src/test/run-pass/issue-20396.rs create mode 100644 src/test/run-pass/issue-21475.rs create mode 100644 src/test/run-pass/issue-21721.rs create mode 100644 src/test/run-pass/issue-22356.rs create mode 100644 src/test/run-pass/issue-22426.rs create mode 100644 src/test/run-pass/issue-22536-copy-mustnt-zero.rs create mode 100644 src/test/run-pass/issue-22577.rs create mode 100644 src/test/run-pass/issue-22629.rs create mode 100644 src/test/run-pass/issue-22777.rs create mode 100644 src/test/run-pass/issue-22828.rs create mode 100644 src/test/run-pass/issue-23037.rs create mode 100644 src/test/run-pass/issue-23435.rs create mode 100644 src/test/run-pass/issue-23485.rs create mode 100644 src/test/run-pass/issue-23550.rs create mode 100644 src/test/run-pass/issue-23781.rs rename src/test/{compile-fail => run-pass}/issue-7607-2.rs (81%) create mode 100644 src/test/run-pass/issue-9951.rs create mode 100644 src/test/run-pass/iter-cloned-type-inference.rs create mode 100644 src/test/run-pass/loop-labeled-break-value.rs create mode 100644 src/test/run-pass/match-reassign.rs rename src/test/run-pass/{lint-cstack.rs => match-ref-unsized.rs} (64%) create mode 100644 src/test/run-pass/minmax-stability-issue-23687.rs create mode 100644 src/test/run-pass/move-guard-const.rs create mode 100644 src/test/run-pass/nested-vec-1.rs create mode 100644 src/test/run-pass/nested-vec-2.rs create mode 100644 src/test/run-pass/nested-vec-3.rs create mode 100644 src/test/run-pass/object-safety-sized-self-by-value-self.rs create mode 100644 src/test/run-pass/object-safety-sized-self-generic-method.rs create mode 100644 src/test/run-pass/object-safety-sized-self-return-Self.rs create mode 100644 src/test/run-pass/process-exit.rs delete mode 100644 src/test/run-pass/rename-directory.rs mode change 100755 => 100644 src/test/run-pass/send-is-not-static-par-for.rs create mode 100644 src/test/run-pass/shift-near-oflo.rs create mode 100644 src/test/run-pass/single-derive-attr-with-gate.rs delete mode 100644 src/test/run-pass/stat.rs create mode 100644 src/test/run-pass/std-sync-right-kind-impls.rs create mode 100644 src/test/run-pass/struct-order-of-eval-3.rs create mode 100644 src/test/run-pass/struct-order-of-eval-4.rs create mode 100644 src/test/run-pass/sync-send-iterators-in-libcollections.rs rename src/test/{compile-fail/impl-not-adjacent-to-type.rs => run-pass/trait-impl-2.rs} (64%) create mode 100644 src/test/run-pass/traits-assoc-type-in-supertrait.rs create mode 100644 src/test/run-pass/traits-issue-22655.rs create mode 100644 src/test/run-pass/traits-issue-23003.rs create mode 100644 src/test/run-pass/traits-repeated-supertrait.rs create mode 100644 src/test/run-pass/trivial_casts.rs rename src/test/run-pass/{const-polymorphic-paths.rs => ufcs-polymorphic-paths.rs} (52%) create mode 100644 src/test/run-pass/unboxed-closures-blanket-fn-mut.rs create mode 100644 src/test/run-pass/unboxed-closures-blanket-fn.rs create mode 100644 src/test/run-pass/unsafe-coercion.rs diff --git a/AUTHORS.txt b/AUTHORS.txt index f7934b2fa7..4109797a55 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -606,7 +606,7 @@ Peter Schuller Peter Williams Peter Zotov Petter Remen -Phil Dawes +Phil Dawes Phil Ruffwind Philip Munksgaard Philipp Brüschweiler diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4656dd415..71b20cb094 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ links to the major sections: If you have questions, please make a post on [internals.rust-lang.org][internals] or hop on [#rust-internals][pound-rust-internals]. -As a reminder, all contributors are expected to follow our [Code of Conduct](coc). +As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. [pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals [internals]: http://internals.rust-lang.org diff --git a/Makefile.in b/Makefile.in index a760155bbd..e7ad2aec7b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -97,12 +97,7 @@ # make check-stage1-rpass TESTNAME=my-shiny-new-test # # // Having trouble figuring out which test is failing? Turn off parallel tests -# make check-stage1-std RUST_TEST_TASKS=1 -# -# This is hardly all there is to know of The Rust Build System's -# mysteries. The tale continues on the wiki[1]. -# -# [1]: https://github.com/rust-lang/rust/wiki/Note-testsuite +# make check-stage1-std RUST_TEST_THREADS=1 # # If you really feel like getting your hands dirty, then: # diff --git a/README.md b/README.md index b6a73730d3..f92fc653e0 100644 --- a/README.md +++ b/README.md @@ -15,28 +15,34 @@ Read ["Installing Rust"] from [The Book]. ## Building from Source 1. Make sure you have installed the dependencies: - * `g++` 4.7 or `clang++` 3.x - * `python` 2.6 or later (but not 3.x) - * GNU `make` 3.81 or later - * `curl` - * `git` + + * `g++` 4.7 or `clang++` 3.x + * `python` 2.6 or later (but not 3.x) + * GNU `make` 3.81 or later + * `curl` + * `git` 2. Clone the [source] with `git`: - $ git clone https://github.com/rust-lang/rust.git - $ cd rust + ```sh + $ git clone https://github.com/rust-lang/rust.git + $ cd rust + ``` [source]: https://github.com/rust-lang/rust 3. Build and install: - $ ./configure - $ make && make install + ```sh + $ ./configure + $ make && make install + ``` - > ***Note:*** You may need to use `sudo make install` if you do not normally have - > permission to modify the destination directory. The install locations can - > be adjusted by passing a `--prefix` argument to `configure`. Various other - > options are also supported, pass `--help` for more information on them. + > ***Note:*** You may need to use `sudo make install` if you do not + > normally have permission to modify the destination directory. The + > install locations can be adjusted by passing a `--prefix` argument + > to `configure`. Various other options are also supported – pass + > `--help` for more information on them. When complete, `make install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the @@ -47,27 +53,30 @@ Read ["Installing Rust"] from [The Book]. ### Building on Windows -To easily build on windows we can use [MSYS2](http://msys2.github.io/): +[MSYS2](http://msys2.github.io/) can be used to easily build Rust on Windows: 1. Grab the latest MSYS2 installer and go through the installer. -2. Now from the MSYS2 terminal we want to install the mingw64 toolchain and the other - tools we need. -```bash -# choose one based on platform -$ pacman -S mingw-w64-i686-toolchain -$ pacman -S mingw-w64-x86_64-toolchain +2. From the MSYS2 terminal, install the `mingw64` toolchain and other required + tools. + + ```sh + # Choose one based on platform: + $ pacman -S mingw-w64-i686-toolchain + $ pacman -S mingw-w64-x86_64-toolchain + + $ pacman -S base-devel + ``` -$ pacman -S base-devel -``` +3. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed + MYSY2 (i.e. `C:\msys`), depending on whether you want 32-bit or 64-bit Rust. -3. With that now start `mingw32_shell.bat` or `mingw64_shell.bat` - from where you installed MSYS2 (i.e. `C:\msys`). Which one you - choose depends on if you want 32 or 64 bit Rust. -4. From there just navigate to where you have Rust's source code, configure and build it: +4. Navigate to Rust's source code, configure and build it: - $ ./configure - $ make && make install + ```sh + $ ./configure + $ make && make install + ``` ## Notes @@ -92,26 +101,26 @@ There is more advice about hacking on Rust in [CONTRIBUTING.md]. [CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md -## Getting help +## Getting Help The Rust community congregates in a few places: -* [StackOverflow] - Direct questions about using the language here. -* [users.rust-lang.org] - General discussion, broader questions. +* [Stack Overflow] - Direct questions about using the language. +* [users.rust-lang.org] - General discussion and broader questions. * [/r/rust] - News and general discussion. -[StackOverflow]: http://stackoverflow.com/questions/tagged/rust +[Stack Overflow]: http://stackoverflow.com/questions/tagged/rust [/r/rust]: http://reddit.com/r/rust [users.rust-lang.org]: http://users.rust-lang.org/ ## Contributing -To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md). +To contribute to Rust, please see [CONTRIBUTING](CONTRIBUTING.md). Rust has an [IRC] culture and most real-time collaboration happens in a variety of channels on Mozilla's IRC network, irc.mozilla.org. The most popular channel is [#rust], a venue for general discussion about -Rust, and a good place to ask for help, +Rust, and a good place to ask for help. [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat [#rust]: irc://irc.mozilla.org/rust @@ -122,4 +131,4 @@ Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses. -See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details. +See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and [COPYRIGHT](COPYRIGHT) for details. diff --git a/RELEASES.md b/RELEASES.md index 09929eee92..7da73afb41 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,102 @@ +Version 1.0.0-beta (April 2015) +------------------------------------- + +* ~1100 changes, numerous bugfixes + +* Highlights + + * The big news is that the vast majority of the standard library + is now `#[stable]` -- 75% of the non-deprecated API surface at + last count. Numerous crates are now running on stable + Rust. Starting with this release, it is not possible to use + unstable features on a stable build. + * Arithmetic on basic integer types now + [checks for overflow in debug builds][overflow]. + +* Language + + * [`Send` no longer implies `'static`][send-rfc], which made + possible the [`thread::scoped` API][scoped]. Scoped threads can + borrow data from their parent's stack frame -- safely! + * [UFCS now supports trait-less associated paths][moar-ufcs] like + `MyType::default()`. + * Primitive types [now have inherent methods][prim-inherent], + obviating the need for extension traits like `SliceExt`. + * Methods with `Self: Sized` in their `where` clause are + [considered object-safe][self-sized], allowing many extension + traits like `IteratorExt` to be merged into the traits they + extended. + * You can now [refer to associated types][assoc-where] whose + corresponding trait bounds appear only in a `where` clause. + * The final bits of [OIBIT landed][oibit-final], meaning that + traits like `Send` and `Sync` are now library-defined. + * A [Reflect trait][reflect] was introduced, which means that + downcasting via the `Any` trait is effectively limited to + concrete types. This helps retain the potentially-important + "parametricity" property: generic code cannot behave differently + for different type arguments except in minor ways. + * The `unsafe_destructor` feature is now deprecated in favor of + the [new `dropck`][dropck]. This change is a major reduction in + unsafe code. + * Trait coherence was [revised again][fundamental], this time with + an eye toward API evolution over time. + +* Libraries + + * The new path and IO modules are complete and `#[stable]`. This + was the major library focus for this cycle. + * The path API was [revised][path-normalize] to normalize `.`, + adjusting the tradeoffs in favor of the most common usage. + * A large number of remaining APIs in `std` were also stabilized + during this cycle; about 75% of the non-deprecated API surface + is now stable. + * The new [string pattern API][string-pattern] landed, which makes + the string slice API much more internally consistent and flexible. + * A shiny [framework for Debug implementations][debug-builder] landed. + This makes it possible to opt in to "pretty-printed" debugging output. + * A new set of [generic conversion traits][conversion] replaced + many existing ad hoc traits. + * Generic numeric traits were + [completely removed][num-traits]. This was made possible thanks + to inherent methods for primitive types, and the removal gives + maximal flexibility for designing a numeric hierarchy in the future. + * The `Fn` traits are now related via [inheritance][fn-inherit] + and provide ergonomic [blanket implementations][fn-blanket]. + * The `Index` and `IndexMut` traits were changed to + [take the index by value][index-value], enabling code like + `hash_map["string"]` to work. + * `Copy` now [inherits][copy-clone] from `Clone`, meaning that all + `Copy` data is known to be `Clone` as well. + +* Infrastructure + + * Metadata was tuned, shrinking binaries [by 27%][metadata-shrink]. + * Much headway was made on ecosystem-wide CI, making it possible + to [compare builds for breakage][ci-compare]. + +[send-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0458-send-improvements.md +[scoped]: http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html +[moar-ufcs]: https://github.com/rust-lang/rust/pull/22172 +[prim-inherent]: https://github.com/rust-lang/rust/pull/23104 +[overflow]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md +[metadata-shrink]: https://github.com/rust-lang/rust/pull/22971 +[self-sized]: https://github.com/rust-lang/rust/pull/22301 +[assoc-where]: https://github.com/rust-lang/rust/pull/22512 +[string-pattern]: https://github.com/rust-lang/rust/pull/22466 +[oibit-final]: https://github.com/rust-lang/rust/pull/21689 +[reflect]: https://github.com/rust-lang/rust/pull/23712 +[debug-builder]: https://github.com/rust-lang/rfcs/blob/master/text/0640-debug-improvements.md +[conversion]: https://github.com/rust-lang/rfcs/pull/529 +[num-traits]: https://github.com/rust-lang/rust/pull/23549 +[index-value]: https://github.com/rust-lang/rust/pull/23601 +[dropck]: https://github.com/rust-lang/rfcs/pull/769 +[fundamental]: https://github.com/rust-lang/rfcs/pull/1023 +[ci-compare]: https://gist.github.com/brson/a30a77836fbec057cbee +[fn-inherit]: https://github.com/rust-lang/rust/pull/23282 +[fn-blanket]: https://github.com/rust-lang/rust/pull/23895 +[copy-clone]: https://github.com/rust-lang/rust/pull/23860 +[path-normalize]: https://github.com/rust-lang/rust/pull/23229 + Version 1.0.0-alpha.2 (February 2015) ------------------------------------- @@ -51,7 +150,7 @@ Version 1.0.0-alpha.2 (February 2015) * Abstract [OS-specific string types][osstr], `std::ff::{OsString, OsStr}`, provide strings in platform-specific encodings for easier interop with system APIs. [RFC][osstr-rfc]. - * The `boxed::into_raw` and `Box::frow_raw` functions [convert + * The `boxed::into_raw` and `Box::from_raw` functions [convert between `Box` and `*mut T`][boxraw], a common pattern for creating raw pointers. diff --git a/configure b/configure index d1b27a96f9..ca73c1cf8b 100755 --- a/configure +++ b/configure @@ -374,8 +374,12 @@ case $CFG_OSTYPE in CFG_OSTYPE=unknown-dragonfly ;; + Bitrig) + CFG_OSTYPE=unknown-bitrig + ;; + OpenBSD) - CFG_OSTYPE=unknown-openbsd + CFG_OSTYPE=unknown-openbsd ;; Darwin) @@ -400,7 +404,7 @@ case $CFG_OSTYPE in CFG_OSTYPE=pc-windows-gnu ;; -# Thad's Cygwin identifers below +# Thad's Cygwin identifiers below # Vista 32 bit CYGWIN_NT-6.0) @@ -426,6 +430,10 @@ case $CFG_OSTYPE in CFG_CPUTYPE=x86_64 ;; +# Win 8 # uname -s on 64-bit cygwin does not contain WOW64, so simply use uname -m to detect arch (works in my install) + CYGWIN_NT-6.3) + CFG_OSTYPE=pc-windows-gnu + ;; # We do not detect other OS such as XP/2003 using 64 bit using uname. # If we want to in the future, we will need to use Cygwin - Chuck's csih helper in /usr/lib/csih/winProductName.exe or alternative. *) @@ -453,7 +461,10 @@ case $CFG_CPUTYPE in CFG_CPUTYPE=aarch64 ;; - powerpc) + # At some point, when ppc64[le] support happens, this will need to do + # something clever. For now it's safe to assume that we're only ever + # interested in building 32 bit. + powerpc | ppc | ppc64) CFG_CPUTYPE=powerpc ;; @@ -468,10 +479,19 @@ esac # Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ] then - file -L "$SHELL" | grep -q "x86[_-]64" - if [ $? != 0 ]; then - CFG_CPUTYPE=i686 + # $SHELL does not exist in standard 'sh', so probably only exists + # if configure is running in an interactive bash shell. /usr/bin/env + # exists *everywhere*. + BIN_TO_PROBE="$SHELL" + if [ -z "$BIN_TO_PROBE" -a -e "/usr/bin/env" ]; then + BIN_TO_PROBE="/usr/bin/env" fi + if [ -n "$BIN_TO_PROBE" ]; then + file -L "$BIN_TO_PROBE" | grep -q "x86[_-]64" + if [ $? != 0 ]; then + CFG_CPUTYPE=i686 + fi + fi fi @@ -506,7 +526,8 @@ VAL_OPTIONS="" opt valgrind 0 "run tests with valgrind (memcheck by default)" opt helgrind 0 "run tests with helgrind instead of memcheck" opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind" -opt docs 1 "build documentation" +opt docs 1 "build standard library documentation" +opt compiler-docs 0 "build compiler documentation" opt optimize 1 "build optimized rust code" opt optimize-cxx 1 "build optimized C++ code" opt optimize-llvm 1 "build optimized LLVM" @@ -693,15 +714,17 @@ probe CFG_ADB adb if [ ! -z "$CFG_PANDOC" ] then - PV_MAJOR_MINOR=$(pandoc --version | grep '^pandoc\(.exe\)\? ' | - # extract the first 2 version fields, ignore everything else - sed 's/pandoc\(.exe\)\? \([0-9]*\)\.\([0-9]*\).*/\2 \3/') + # Extract "MAJOR MINOR" from Pandoc's version number + PV_MAJOR_MINOR=$(pandoc --version | grep '^pandoc' | + sed -E 's/pandoc(.exe)? ([0-9]+)\.([0-9]+).*/\2 \3/') MIN_PV_MAJOR="1" MIN_PV_MINOR="9" + # these patterns are shell globs, *not* regexps PV_MAJOR=${PV_MAJOR_MINOR% *} PV_MINOR=${PV_MAJOR_MINOR#* } + if [ "$PV_MAJOR" -lt "$MIN_PV_MAJOR" ] || [ "$PV_MINOR" -lt "$MIN_PV_MINOR" ] then step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. Need at least $MIN_PV_MAJOR.$MIN_PV_MINOR. Disabling" @@ -747,6 +770,14 @@ then CFG_ENABLE_CLANG=1 fi +# Force bitrig to build with clang; gcc doesn't like us there +if [ $CFG_OSTYPE = unknown-bitrig ] +then + step_msg "on Bitrig, forcing use of clang, disabling jemalloc" + CFG_ENABLE_CLANG=1 + CFG_ENABLE_JEMALLOC=0 +fi + if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ] then err "either clang or gcc is required" @@ -805,11 +836,11 @@ then LLVM_VERSION=$($LLVM_CONFIG --version) case $LLVM_VERSION in - (3.[2-6]*) + (3.[5-6]*) msg "found ok version of LLVM: $LLVM_VERSION" ;; (*) - err "bad LLVM version: $LLVM_VERSION, need >=3.0svn" + err "bad LLVM version: $LLVM_VERSION, need >=3.5" ;; esac fi @@ -864,7 +895,7 @@ then | cut -d ' ' -f 2) case $CFG_CLANG_VERSION in - (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 3.4* | 3.5* | 3.6*) + (3.2* | 3.3* | 3.4* | 3.5* | 3.6*) step_msg "found ok version of CLANG: $CFG_CLANG_VERSION" if [ -z "$CC" ] then diff --git a/man/rustc.1 b/man/rustc.1 index 49056afa04..b15829db43 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -7,224 +7,289 @@ rustc \- The Rust compiler .SH DESCRIPTION This program is a compiler for the Rust language, available at -<\fBhttps://www.rust-lang.org\fR>. +.UR https://www.rust\-lang.org +.UE . .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR -Display the help message +Display the help message. .TP -\fB\-\-cfg\fR SPEC -Configure the compilation environment +\fB\-\-cfg\fR \fISPEC\fR +Configure the compilation environment. .TP -\fB\-L\fR [KIND=]PATH -Add a directory to the library search path. The optional KIND can be one of: - dependency = only lookup transitive dependencies here - crate = only lookup local `extern crate` directives here - native = only lookup native libraries here - framework = only look for OSX frameworks here - all = look for anything here (the default) +\fB\-L\fR [\fIKIND\fR=]\fIPATH\fR +Add a directory to the library search path. +The optional \fIKIND\fR can be one of: +.RS .TP -\fB\-l\fR [KIND=]NAME -Link the generated crate(s) to the specified native library NAME. The optional -KIND can be one of, static, dylib, or framework. If omitted, dylib is assumed. +\fBdependency\fR +only lookup transitive dependencies here .TP -\fB\-\-crate-type\fR [bin|lib|rlib|dylib|staticlib] -Comma separated list of types of crates for the compiler to emit +.B crate +only lookup local `extern crate` directives here .TP -\fB\-\-crate-name NAME\fR -Specify the name of the crate being built +.B native +only lookup native libraries here .TP -\fB\-\-emit\fR [asm|llvm-bc|llvm-ir|obj|link|dep-info] -Configure the output that rustc will produce +.B framework +only look for OSX frameworks here .TP -\fB\-\-print\fR [crate-name|file-names|sysroot] -Comma separated list of compiler information to print on stdout +.B all +look for anything here (the default) +.RE +.TP +\fB\-l\fR [\fIKIND\fR=]\fINAME\fR +Link the generated crate(s) to the specified native library \fINAME\fR. +The optional \fIKIND\fR can be one of \fIstatic\fR, \fIdylib\fR, or +\fIframework\fR. +If omitted, \fIdylib\fR is assumed. +.TP +\fB\-\-crate\-type\fR [bin|lib|rlib|dylib|staticlib] +Comma separated list of types of crates for the compiler to emit. +.TP +\fB\-\-crate\-name\fR \fINAME\fR +Specify the name of the crate being built. +.TP +\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info] +Configure the output that \fBrustc\fR will produce. +.TP +\fB\-\-print\fR [crate\-name|file\-names|sysroot] +Comma separated list of compiler information to print on stdout. .TP \fB\-g\fR -Equivalent to \fI\-C\fR debuginfo=2 +Equivalent to \fI\-C\ debuginfo=2\fR. .TP \fB\-O\fR -Equivalent to \fI\-C\fR opt-level=2 +Equivalent to \fI\-C\ opt\-level=2\fR. .TP -\fB\-o\fR FILENAME -Write output to . Ignored if multiple \fI\-\-emit\fR outputs are -specified. +\fB\-o\fR \fIFILENAME\fR +Write output to \fIFILENAME\fR. +Ignored if multiple \fI\-\-emit\fR outputs are specified. .TP -\fB\-\-out\-dir\fR DIR -Write output to compiler-chosen filename in . Ignored if \fI\-o\fR is -specified. Defaults to the current directory. +\fB\-\-out\-dir\fR \fIDIR\fR +Write output to compiler\[hy]chosen filename in \fIDIR\fR. +Ignored if \fI\-o\fR is specified. +Defaults to the current directory. .TP -\fB\-\-explain\fR OPT -Provide a detailed explanation of an error message +\fB\-\-explain\fR \fIOPT\fR +Provide a detailed explanation of an error message. .TP \fB\-\-test\fR -Build a test harness +Build a test harness. .TP -\fB\-\-target\fR TRIPLE -Target triple cpu-manufacturer-kernel[-os] to compile for (see chapter 3.4 of -http://www.sourceware.org/autobook/ for details) +\fB\-\-target\fR \fITRIPLE\fR +Target triple \fIcpu\fR\-\fImanufacturer\fR\-\fIkernel\fR[\-\fIos\fR] +to compile for (see chapter 3.4 of +.UR http://www.sourceware.org/autobook/ +.UE +for details). .TP -\fB\-W\fR help -Print 'lint' options and default settings +\fB\-W help\fR +Print 'lint' options and default settings. .TP -\fB\-W\fR OPT, \fB\-\-warn\fR OPT -Set lint warnings +\fB\-W\fR \fIOPT\fR, \fB\-\-warn\fR \fIOPT\fR +Set lint warnings. .TP -\fB\-A\fR OPT, \fB\-\-allow\fR OPT -Set lint allowed +\fB\-A\fR \fIOPT\fR, \fB\-\-allow\fR \fIOPT\fR +Set lint allowed. .TP -\fB\-D\fR OPT, \fB\-\-deny\fR OPT -Set lint denied +\fB\-D\fR \fIOPT\fR, \fB\-\-deny\fR \fIOPT\fR +Set lint denied. .TP -\fB\-F\fR OPT, \fB\-\-forbid\fR OPT -Set lint forbidden +\fB\-F\fR \fIOPT\fR, \fB\-\-forbid\fR \fIOPT\fR +Set lint forbidden. .TP -\fB\-C\fR FLAG[=VAL], \fB\-\-codegen\fR FLAG[=VAL] -Set a codegen-related flag to the value specified. Use "-C help" to print -available flags. See CODEGEN OPTIONS below +\fB\-C\fR \fIFLAG\fR[=\fIVAL\fR], \fB\-\-codegen\fR \fIFLAG\fR[=\fIVAL\fR] +Set a codegen\[hy]related flag to the value specified. +Use \fI\-C help\fR to print available flags. +See CODEGEN OPTIONS below. .TP \fB\-V\fR, \fB\-\-version\fR -Print version info and exit +Print version info and exit. .TP \fB\-v\fR, \fB\-\-verbose\fR -Use verbose output +Use verbose output. .TP -\fB\-\-extern\fR NAME=PATH -Specify where an external rust library is located +\fB\-\-extern\fR \fINAME\fR=\fIPATH\fR +Specify where an external rust library is located. .TP -\fB\-\-sysroot\fR PATH -Override the system root +\fB\-\-sysroot\fR \fIPATH\fR +Override the system root. .TP -\fB\-Z\fR FLAG -Set internal debugging options. Use "-Z help" to print available options. +\fB\-Z\fR \fIFLAG\fR +Set internal debugging options. +Use \fI\-Z help\fR to print available options. .TP \fB\-\-color\fR auto|always|never Configure coloring of output: - auto = colorize, if output goes to a tty (default); - always = always colorize output; - never = never colorize output +.RS +.TP +.B auto +colorize, if output goes to a tty (default); +.TP +.B always +always colorize output; +.TP +.B never +never colorize output. +.RE .SH CODEGEN OPTIONS .TP -\fBar\fR=/path/to/ar +\fBar\fR=\fI/path/to/ar\fR Path to the archive utility to use when assembling archives. .TP -\fBlinker\fR=/path/to/cc +\fBlinker\fR=\fI/path/to/cc\fR Path to the linker utility to use when linking libraries, executables, and objects. .TP -\fBlink-args\fR='-flag1 -flag2' -A space-separated list of extra arguments to pass to the linker when the linker +\fBlink\-args\fR='\fI\-flag1 \-flag2\fR' +A space\[hy]separated list of extra arguments to pass to the linker when the linker is invoked. .TP \fBlto\fR -Perform LLVM link-time optimizations. +Perform LLVM link\[hy]time optimizations. .TP -\fBtarget-cpu\fR=help -Selects a target processor. If the value is 'help', then a list of available -CPUs is printed. +\fBtarget\-cpu\fR=\fIhelp\fR +Selects a target processor. +If the value is 'help', then a list of available CPUs is printed. .TP -\fBtarget-feature\fR='+feature1,-feature2' -A comma-separated list of features to enable or disable for the target. A -preceding '+' enables a feature while a preceding '-' disables it. Available -features can be discovered through target-cpu=help. +\fBtarget\-feature\fR='\fI+feature1\fR,\fI\-feature2\fR' +A comma\[hy]separated list of features to enable or disable for the target. +A preceding '+' enables a feature while a preceding '\-' disables it. +Available features can be discovered through \fItarget\-cpu=help\fR. .TP -\fBpasses\fR=list -A space-separated list of extra LLVM passes to run. A value of 'list' will -cause rustc to print all known passes and exit. The passes specified are -appended at the end of the normal pass manager. +\fBpasses\fR=\fIval\fR +A space\[hy]separated list of extra LLVM passes to run. +A value of 'list' will cause \fBrustc\fR to print all known passes and +exit. +The passes specified are appended at the end of the normal pass manager. .TP -\fBllvm-args\fR='-arg1 -arg2' -A space-separated list of arguments to pass through to LLVM. +\fBllvm\-args\fR='\fI\-arg1\fR \fI\-arg2\fR' +A space\[hy]separated list of arguments to pass through to LLVM. .TP -\fBsave-temps\fR -If specified, the compiler will save more files (.bc, .o, .no-opt.bc) generated +\fBsave\-temps\fR +If specified, the compiler will save more files (.bc, .o, .no\-opt.bc) generated throughout compilation in the output directory. .TP \fBrpath\fR If specified, then the rpath value for dynamic libraries will be set in either dynamic library or executable outputs. .TP -\fBno-prepopulate-passes\fR -Suppresses pre-population of the LLVM pass manager that is run over the module. +\fBno\-prepopulate\-passes\fR +Suppresses pre\[hy]population of the LLVM pass manager that is run over the module. .TP -\fBno-vectorize-loops\fR +\fBno\-vectorize\-loops\fR Suppresses running the loop vectorization LLVM pass, regardless of optimization level. .TP -\fBno-vectorize-slp\fR +\fBno\-vectorize\-slp\fR Suppresses running the LLVM SLP vectorization pass, regardless of optimization level. .TP -\fBsoft-float\fR +\fBsoft\-float\fR Generates software floating point library calls instead of hardware instructions. .TP -\fBprefer-dynamic\fR +\fBprefer\-dynamic\fR Prefers dynamic linking to static linking. .TP -\fBno-integrated-as\fR +\fBno\-integrated\-as\fR Force usage of an external assembler rather than LLVM's integrated one. .TP -\fBno-redzone\fR +\fBno\-redzone\fR Disable the use of the redzone. .TP -\fBrelocation-model\fR=[pic,static,dynamic-no-pic] -The relocation model to use. (Default: pic) +\fBrelocation\-model\fR=[pic,static,dynamic\-no\-pic] +The relocation model to use. +(Default: \fIpic\fR) .TP -\fBcode-model\fR=[small,kernel,medium,large] +\fBcode\-model\fR=[small,kernel,medium,large] Choose the code model to use. .TP -\fBmetadata\fR=val +\fBmetadata\fR=\fIval\fR Metadata to mangle symbol names with. .TP -\fBextra-filename\fR=val +\fBextra\-filename\fR=\fIval\fR Extra data to put in each output filename. .TP -\fBcodegen-units\fR=val -Divide crate into N units to optimize in parallel. +\fBcodegen\-units\fR=\fIn\fR +Divide crate into \fIn\fR units to optimize in parallel. .TP -\fBremark\fR=val +\fBremark\fR=\fIval\fR Print remarks for these optimization passes (space separated, or "all"). .TP -\fBno-stack-check\fR -Disable checks for stack exhaustion (a memory-safety hazard!). +\fBno\-stack\-check\fR +Disable checks for stack exhaustion (a memory\[hy]safety hazard!). .TP -\fBdebuginfo\fR=val +\fBdebuginfo\fR=\fIval\fR Debug info emission level: - 0 = no debug info; - 1 = line-tables only (for stacktraces and breakpoints); - 2 = full debug info with variable and type information. +.RS +.TP +.B 0 +no debug info; +.TP +.B 1 +line\[hy]tables only (for stacktraces and breakpoints); +.TP +.B 2 +full debug info with variable and type information. +.RE +.TP +\fBopt\-level\fR=\fIVAL\fR +Optimize with possible levels 0\[en]3 + +.SH ENVIRONMENT + +Some of these affect the output of the compiler, while others affect programs +which link to the standard library. + +.TP +\fBRUST_TEST_THREADS\fR +The test framework Rust provides executes tests in parallel. This variable sets +the maximum number of threads used for this purpose. + +.TP +\fBRUST_TEST_NOCAPTURE\fR +A synonym for the --nocapture flag. + +.TP +\fBRUST_MIN_STACK\fR +Sets the minimum stack size for new threads. + .TP -\fBopt-level\fR=val -Optimize with possible levels 0-3 +\fBRUST_BACKTRACE\fR +If set, produces a backtrace in the output of a program which panics. .SH "EXAMPLES" To build an executable from a source file with a main function: - $ rustc -o hello hello.rs + $ rustc \-o hello hello.rs To build a library from a source file: - $ rustc --crate-type=lib hello-lib.rs + $ rustc \-\-crate\-type=lib hello\-lib.rs To build either with a crate (.rs) file: $ rustc hello.rs To build an executable with debug info: - $ rustc -g -o hello hello.rs + $ rustc \-g \-o hello hello.rs .SH "SEE ALSO" -rustdoc +.BR rustdoc (1) .SH "BUGS" -See <\fBhttps://github.com/rust-lang/rust/issues\fR> for issues. +See +.UR https://github.com/rust\-lang/rust/issues +.UE +for issues. .SH "AUTHOR" -See \fBAUTHORS.txt\fR in the Rust source distribution. +See \fIAUTHORS.txt\fR in the Rust source distribution. .SH "COPYRIGHT" -This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR -file in the rust source distribution. +This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms. +See \fICOPYRIGHT\fR file in the rust source distribution. diff --git a/man/rustdoc.1 b/man/rustdoc.1 index 830884b19b..1738354fb4 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -8,76 +8,79 @@ rustdoc \- generate documentation from Rust source code .SH DESCRIPTION This tool generates API reference documentation by extracting comments from source code written in the Rust language, available at -<\fBhttps://www.rust-lang.org\fR>. It accepts several input formats and provides -several output formats for the generated documentation. +.UR https://www.rust\-lang.org +.UE . +It accepts several input formats and provides several output formats +for the generated documentation. .SH OPTIONS .TP --r --input-format +\fB\-r\fR, \fB\-\-input\-format\fR \fIFORMAT\fR html or json (default: inferred) .TP --w --output-format +\fB\-w\fR, \fB\-\-output\-format\fR \fIFORMAT\fR html or json (default: html) .TP --o --output -where to place the output (default: doc/ for html, doc.json for json) +\fB\-o\fR, \fB\-\-output\fR \fIOUTPUT\fR +where to place the output (default: \fIdoc/\fR for html, +\fIdoc.json\fR for json) .TP ---passes -space-separated list of passes to run (default: '') +\fB\-\-passes\fR \fILIST\fR +space\[hy]separated list of passes to run (default: '') .TP ---no-defaults +\fB\-\-no\-defaults\fR don't run the default passes .TP ---plugins +\fB\-\-plugins\fR \fILIST\fR space-separated list of plugins to run (default: '') .TP ---plugin-path -directory to load plugins from (default: /tmp/rustdoc_ng/plugins) +\fB\-\-plugin\-path\fR \fIDIR\fR +directory to load plugins from (default: \fI/tmp/rustdoc_ng/plugins\fR) .TP ---target +\fB\-\-target\fR \fITRIPLE\fR target triple to document .TP ---crate-name +\fB\-\-crate\-name\fR \fINAME\fR specify the name of this crate .TP --L --library-path +\fB\-L\fR, \fB\-\-library\-path\fR \fIDIR\fR directory to add to crate search path .TP ---cfg -pass a --cfg to rustc +\fB\-\-cfg\fR \fISPEC\fR +pass a \fI\-\-cfg\fR to rustc .TP ---extern -pass an --extern to rustc +\fB\-\-extern\fR \fIVAL\fR +pass an \fI\-\-extern\fR to rustc .TP ---test +\fB\-\-test\fR run code examples as tests .TP ---test-args +\fB\-\-test\-args\fR \fIARGS\fR pass arguments to the test runner .TP ---html-in-header +\fB\-\-html\-in\-header\fR \fIFILE\fR file to add to .TP ---html-before-content +\fB\-\-html\-before\-content\fR \fIFILE\fR file to add in , before content .TP ---html-after-content +\fB\-\-html\-after\-content\fR \fIFILE\fR file to add in , after content .TP ---markdown-css +\fB\-\-markdown\-css\fR \fIFILE\fR CSS files to include via in a rendered Markdown file .TP ---markdown-playground-url +\fB\-\-markdown\-playground\-url\fR \fIURL\fR URL to send code snippets to .TP ---markdown-no-toc +\fB\-\-markdown\-no\-toc\fR don't include table of contents .TP --h, --help +\fB\-h\fR, \fB\-\-help\fR Print help .TP --V, --version +\fB\-V\fR, \fB\-\-version\fR Print rustdoc's version .SH "OUTPUT FORMATS" @@ -85,14 +88,15 @@ Print rustdoc's version The rustdoc tool can generate output in either an HTML or JSON format. If using an HTML format, then the specified output destination will be the root -directory of an HTML structure for all the documentation. Pages will be placed -into this directory, and source files will also possibly be rendered into it as -well. +directory of an HTML structure for all the documentation. +Pages will be placed into this directory, and source files will also +possibly be rendered into it as well. If using a JSON format, then the specified output destination will have the -rustdoc output serialized as JSON into it. This output format exists to -pre-compile documentation for crates, and for usage in non-rustdoc tools. The -JSON output is the following hash: +rustdoc output serialized as JSON into it. +This output format exists to pre\[hy]compile documentation for crates, +and for usage in non\[hy]rustdoc tools. +The JSON output is the following hash: { "schema": VERSION, @@ -100,11 +104,12 @@ JSON output is the following hash: "plugins": ..., } -The schema version indicates what the structure of crate/plugins will look -like. Within a schema version the structure will remain the same. The `crate` -field will contain all relevant documentation for the source being documented, -and the `plugins` field will contain the output of the plugins run over the -crate. +The schema version indicates what the structure of crate/plugins will +look like. +Within a schema version the structure will remain the same. +The \fIcrate\fR field will contain all relevant documentation for the +source being documented, and the \fIplugins\fR field will contain the +output of the plugins run over the crate. .SH "EXAMPLES" @@ -112,25 +117,28 @@ To generate documentation for the source in the current directory: $ rustdoc hello.rs List all available passes that rustdoc has, along with default passes: - $ rustdoc --passes list + $ rustdoc \-\-passes list To precompile the documentation for a crate, and then use it to render html at a later date: - $ rustdoc -w json hello.rs + $ rustdoc \-w json hello.rs $ rustdoc doc.json The generated HTML can be viewed with any standard web browser. .SH "SEE ALSO" -rustc +.BR rustc (1) .SH "BUGS" -See <\fBhttps://github.com/rust-lang/rust/issues\fR> for issues. +See +.UR https://github.com/rust\-lang/rust/issues +.UE +for issues. .SH "AUTHOR" -See \fBAUTHORS.txt\fR in the Rust source distribution. +See \fIAUTHORS.txt\fR in the Rust source distribution. .SH "COPYRIGHT" -This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR -file in the rust source distribution. +This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms. +See \fICOPYRIGHT\fR file in the rust source distribution. diff --git a/mk/cfg/x86_64-unknown-bitrig.mk b/mk/cfg/x86_64-unknown-bitrig.mk new file mode 100644 index 0000000000..ad34988cb1 --- /dev/null +++ b/mk/cfg/x86_64-unknown-bitrig.mk @@ -0,0 +1,26 @@ +# x86_64-unknown-bitrig-elf configuration +CC_x86_64-unknown-bitrig=$(CC) +CXX_x86_64-unknown-bitrig=$(CXX) +CPP_x86_64-unknown-bitrig=$(CPP) +AR_x86_64-unknown-bitrig=$(AR) +CFG_LIB_NAME_x86_64-unknown-bitrig=lib$(1).so +CFG_STATIC_LIB_NAME_x86_64-unknown-bitrig=lib$(1).a +CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM +CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS) +CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIC -m64 -I/usr/include $(CFLAGS) +CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS) +CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-pic -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-no-whole-archive +CFG_DEF_SUFFIX_x86_64-unknown-bitrig := .bsd.def +CFG_LLC_FLAGS_x86_64-unknown-bitrig := +CFG_INSTALL_NAME_x86_64-unknown-bitrig = +CFG_EXE_SUFFIX_x86_64-unknown-bitrig := +CFG_WINDOWSY_x86_64-unknown-bitrig := +CFG_UNIXY_x86_64-unknown-bitrig := 1 +CFG_PATH_MUNGE_x86_64-unknown-bitrig := +CFG_LDPATH_x86_64-unknown-bitrig := +CFG_RUN_x86_64-unknown-bitrig=$(2) +CFG_RUN_TARG_x86_64-unknown-bitrig=$(call CFG_RUN_x86_64-unknown-bitrig,,$(2)) +CFG_GNU_TRIPLE_x86_64-unknown-bitrig := x86_64-unknown-bitrig diff --git a/mk/cfg/x86_64-unknown-linux-gnu.mk b/mk/cfg/x86_64-unknown-linux-gnu.mk index 845f9c1c52..e5866094ee 100644 --- a/mk/cfg/x86_64-unknown-linux-gnu.mk +++ b/mk/cfg/x86_64-unknown-linux-gnu.mk @@ -25,4 +25,3 @@ CFG_LDPATH_x86_64-unknown-linux-gnu := CFG_RUN_x86_64-unknown-linux-gnu=$(2) CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2)) CFG_GNU_TRIPLE_x86_64-unknown-linux-gnu := x86_64-unknown-linux-gnu - diff --git a/mk/crates.mk b/mk/crates.mk index be1965b7ed..f594a6a19f 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -54,7 +54,7 @@ TARGET_CRATES := libc std flate arena term \ log graphviz core rbml alloc \ unicode rustc_bitflags RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \ - rustc_trans rustc_back rustc_llvm rustc_privacy + rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros CRATES := $(TARGET_CRATES) $(HOST_CRATES) TOOLS := compiletest rustdoc rustc rustbook @@ -70,7 +70,7 @@ DEPS_graphviz := std DEPS_syntax := std term serialize log fmt_macros arena libc DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \ rustc_typeck rustc_resolve log syntax serialize rustc_llvm \ - rustc_trans rustc_privacy + rustc_trans rustc_privacy rustc_lint DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ log syntax serialize rustc_llvm @@ -78,12 +78,13 @@ DEPS_rustc_typeck := rustc syntax DEPS_rustc_borrowck := rustc log graphviz syntax DEPS_rustc_resolve := rustc log syntax DEPS_rustc_privacy := rustc log syntax +DEPS_rustc_lint := rustc log syntax DEPS_rustc := syntax flate arena serialize getopts rbml \ log graphviz rustc_llvm rustc_back DEPS_rustc_llvm := native:rustllvm libc std DEPS_rustc_back := std syntax rustc_llvm flate log libc DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \ - test + test rustc_lint DEPS_rustc_bitflags := core DEPS_flate := std native:miniz DEPS_arena := std @@ -121,18 +122,37 @@ ONLY_RLIB_rustc_bitflags := 1 # You should not need to edit below this line ################################################################################ +# On channels where the only usable crate is std, only build documentation for +# std. This keeps distributions small and doesn't clutter up the API docs with +# confusing internal details from the crates behind the facade. +# +# (Disabled while cmr figures out how to change rustdoc to make reexports work +# slightly nicer. Otherwise, all cross-crate links to Vec will go to +# libcollections, breaking them, and [src] links for anything reexported will +# not work.) + +#ifeq ($(CFG_RELEASE_CHANNEL),stable) +#DOC_CRATES := std +#else +#ifeq ($(CFG_RELEASE_CHANNEL),beta) +#DOC_CRATES := std +#else DOC_CRATES := $(filter-out rustc, \ - $(filter-out rustc_trans, \ - $(filter-out rustc_typeck, \ - $(filter-out rustc_borrowck, \ - $(filter-out rustc_resolve, \ - $(filter-out rustc_driver, \ - $(filter-out rustc_privacy, \ - $(filter-out log, \ - $(filter-out getopts, \ - $(filter-out syntax, $(CRATES))))))))))) + $(filter-out rustc_trans, \ + $(filter-out rustc_typeck, \ + $(filter-out rustc_borrowck, \ + $(filter-out rustc_resolve, \ + $(filter-out rustc_driver, \ + $(filter-out rustc_privacy, \ + $(filter-out rustc_lint, \ + $(filter-out log, \ + $(filter-out getopts, \ + $(filter-out syntax, $(CRATES)))))))))))) +#endif +#endif COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \ - rustc_typeck rustc_driver syntax rustc_privacy + rustc_typeck rustc_driver syntax rustc_privacy \ + rustc_lint # This macro creates some simple definitions for each crate being built, just # some munging of all of the parameters above. diff --git a/mk/debuggers.mk b/mk/debuggers.mk index 899cc42d06..e6a2174f84 100644 --- a/mk/debuggers.mk +++ b/mk/debuggers.mk @@ -56,29 +56,32 @@ define DEF_INSTALL_DEBUGGER_SCRIPTS_HOST tmp/install-debugger-scripts$(1)_H_$(2)-gdb.done: \ $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \ $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) + $(Q)touch $$@.start_time $(Q)mkdir -p $$(HBIN$(1)_H_$(2)) $(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc $(Q)install $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $$(HBIN$(1)_H_$(2)) $(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc - $(Q)touch $$@ + $(Q)touch -r $$@.start_time $$@ && rm $$@.start_time tmp/install-debugger-scripts$(1)_H_$(2)-lldb.done: \ $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) \ $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) + $(Q)touch $$@.start_time $(Q)mkdir -p $$(HBIN$(1)_H_$(2)) $(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc $(Q)install $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $$(HBIN$(1)_H_$(2)) $(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc - $(Q)touch $$@ + $(Q)touch -r $$@.start_time $$@ && rm $$@.start_time tmp/install-debugger-scripts$(1)_H_$(2)-all.done: \ $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) \ $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) + $(Q)touch $$@.start_time $(Q)mkdir -p $$(HBIN$(1)_H_$(2)) $(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc $(Q)install $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $$(HBIN$(1)_H_$(2)) $(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc - $(Q)touch $$@ + $(Q)touch -r $$@.start_time $$@ && rm $$@.start_time tmp/install-debugger-scripts$(1)_H_$(2)-none.done: $(Q)touch $$@ @@ -98,29 +101,32 @@ define DEF_INSTALL_DEBUGGER_SCRIPTS_TARGET tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-gdb.done: \ $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \ $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) + $(Q)touch $$@.start_time $(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc $(Q)install $(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc - $(Q)touch $$@ + $(Q)touch -r $$@.start_time $$@ && rm $$@.start_time tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-lldb.done: \ $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) \ $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) + $(Q)touch $$@.start_time $(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc $(Q)install $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc - $(Q)touch $$@ + $(Q)touch -r $$@.start_time $$@ && rm $$@.start_time tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-all.done: \ $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) \ $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) + $(Q)touch $$@.start_time $(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc $(Q)install $(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $$(TBIN$(1)_T_$(2)_H_$(3)) $(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc - $(Q)touch $$@ + $(Q)touch -r $$@.start_time $$@ && rm $$@.start_time tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-none.done: $(Q)touch $$@ diff --git a/mk/dist.mk b/mk/dist.mk index 831225556f..57adaee519 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -53,6 +53,7 @@ PKG_FILES := \ driver \ etc \ $(foreach crate,$(CRATES),lib$(crate)) \ + libcollectionstest \ libcoretest \ libbacktrace \ rt \ diff --git a/mk/docs.mk b/mk/docs.mk index 743032f676..d297055ba9 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -259,7 +259,10 @@ doc/$(1)/index.html: $$(LIB_DOC_DEP_$(1)) doc/$(1)/ endef $(foreach crate,$(DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),DOC_TARGETS))) -$(foreach crate,$(COMPILER_DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),COMPILER_DOC_TARGETS))) + +ifdef CFG_COMPILER_DOCS + $(foreach crate,$(COMPILER_DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),COMPILER_DOC_TARGETS))) +endif ifdef CFG_DISABLE_DOCS $(info cfg: disabling doc build (CFG_DISABLE_DOCS)) @@ -273,11 +276,13 @@ compiler-docs: $(COMPILER_DOC_TARGETS) trpl: doc/book/index.html doc/book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) | doc/ + @$(call E, rustbook: $@) $(Q)rm -rf doc/book $(Q)$(RUSTBOOK) build $(S)src/doc/trpl doc/book style: doc/style/index.html doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/ + @$(call E, rustbook: $@) $(Q)rm -rf doc/style $(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style diff --git a/mk/llvm.mk b/mk/llvm.mk index ba2e073803..1861dd313c 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -38,15 +38,16 @@ endif # the stamp in the source dir. $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger @$$(call E, make: cleaning llvm) + $(Q)touch $$@.start_time $(Q)$(MAKE) clean-llvm$(1) @$$(call E, make: done cleaning llvm) - touch $$@ + touch -r $$@.start_time $$@ && rm $$@.start_time ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1) -LLVM_STDCPP_LOCATION_$(1) = $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ - -print-file-name=libstdc++.a) +LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ + -print-file-name=libstdc++.a))" else -LLVM_STDCPP_LOCATION_$(1) = +LLVM_STDCPP_RUSTFLAGS_$(1) = endif diff --git a/mk/main.mk b/mk/main.mk index 9752ee233b..b9f2cf1cce 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.0.0 # An optional number to put after the label, e.g. '.2' -> '-beta.2' # NB Make sure it starts with a dot to conform to semver pre-release # versions (section 9) -CFG_PRERELEASE_VERSION=.2 +CFG_PRERELEASE_VERSION= CFG_FILENAME_EXTRA=4e7c5e5c @@ -30,8 +30,8 @@ CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM) CFG_DISABLE_UNSTABLE_FEATURES=1 endif ifeq ($(CFG_RELEASE_CHANNEL),beta) -CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_PRERELEASE_VERSION) -CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_PRERELEASE_VERSION) +CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION) +CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION) CFG_DISABLE_UNSTABLE_FEATURES=1 endif ifeq ($(CFG_RELEASE_CHANNEL),nightly) @@ -130,7 +130,7 @@ ifdef CFG_DISABLE_DEBUG CFG_RUSTC_FLAGS += --cfg ndebug else $(info cfg: enabling more debugging (CFG_ENABLE_DEBUG)) - CFG_RUSTC_FLAGS += --cfg debug + CFG_RUSTC_FLAGS += --cfg debug -C debug-assertions=on endif ifdef SAVE_TEMPS @@ -290,6 +290,7 @@ LLVM_VERSION_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --version) LLVM_BINDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --bindir) LLVM_INCDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --includedir) LLVM_LIBDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libdir) +LLVM_LIBDIR_RUSTFLAGS_$(1)=-L "$$(LLVM_LIBDIR_$(1))" LLVM_LIBS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libs $$(LLVM_COMPONENTS)) LLVM_LDFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --ldflags) # On FreeBSD, it may search wrong headers (that are for pre-installed LLVM), diff --git a/mk/platform.mk b/mk/platform.mk index 78c1057c2f..cd86b273c6 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -144,14 +144,14 @@ FIND_COMPILER = $(word 1,$(1:ccache=)) define CFG_MAKE_TOOLCHAIN # Prepend the tools with their prefix if cross compiling ifneq ($(CFG_BUILD),$(1)) - CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1)) - CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1)) - CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1)) - AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1)) - RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \ - -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1)) - - RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1)) + CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1)) + CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1)) + CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1)) + AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1)) + RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \ + -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1)) + + RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1)) endif CFG_COMPILE_C_$(1) = $$(CC_$(1)) \ @@ -179,11 +179,19 @@ define CFG_MAKE_TOOLCHAIN ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),) + # On Bitrig, we need the relocation model to be PIC for everything + ifeq (,$(filter $(OSTYPE_$(1)),bitrig)) + LLVM_MC_RELOCATION_MODEL="pic" + else + LLVM_MC_RELOCATION_MODEL="default" + endif + # We're using llvm-mc as our assembler because it supports # .cfi pseudo-ops on mac CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(CFG_DEPEND_FLAGS) $$(2) | \ $$(LLVM_MC_$$(CFG_BUILD)) \ -assemble \ + -relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \ -filetype=obj \ -triple=$(1) \ -o=$$(1) @@ -192,7 +200,7 @@ define CFG_MAKE_TOOLCHAIN # For the ARM, AARCH64, MIPS and POWER crosses, use the toolchain assembler # FIXME: We should be able to use the LLVM assembler CFG_ASSEMBLE_$(1)=$$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \ - $$(CFG_DEPEND_FLAGS) $$(2) -c -o $$(1) + $$(CFG_DEPEND_FLAGS) $$(2) -c -o $$(1) endif diff --git a/mk/prepare.mk b/mk/prepare.mk index f1c4aa65f5..4ded8a7916 100644 --- a/mk/prepare.mk +++ b/mk/prepare.mk @@ -221,5 +221,3 @@ prepare-maybe-clean-$(1): endef - - diff --git a/mk/target.mk b/mk/target.mk index 1f67d9ed8d..8cc74a9cbf 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -72,9 +72,11 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER_HOST_TRIPLE = $(2) $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(CRATEFILE_$(4)) \ $$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4)) \ + $$(LLVM_CONFIG_$(2)) \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, rustc: $$(@D)/lib$(4)) + @touch $$@.start_time $$(call REMOVE_ALL_OLD_GLOB_MATCHES, \ $$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4))) $$(call REMOVE_ALL_OLD_GLOB_MATCHES, \ @@ -83,13 +85,13 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) \ $$(RUST_LIB_FLAGS_ST$(1)) \ -L "$$(RT_OUTPUT_DIR_$(2))" \ - -L "$$(LLVM_LIBDIR_$(2))" \ - -L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \ + $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ + $$(LLVM_STDCPP_RUSTFLAGS_$(2)) \ $$(RUSTFLAGS_$(4)) \ --out-dir $$(@D) \ -C extra-filename=-$$(CFG_FILENAME_EXTRA) \ $$< - @touch $$@ + @touch -r $$@.start_time $$@ && rm $$@.start_time $$(call LIST_ALL_OLD_GLOB_MATCHES, \ $$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4))) $$(call LIST_ALL_OLD_GLOB_MATCHES, \ @@ -130,7 +132,7 @@ endef # on $$(TSREQ$(1)_T_$(2)_H_$(3)), to ensure that no products will be # put into the target area until after the get-snapshot.py script has # had its chance to clean it out; otherwise the other products will be -# inadvertantly included in the clean out. +# inadvertently included in the clean out. SNAPSHOT_RUSTC_POST_CLEANUP=$(HBIN0_H_$(CFG_BUILD))/rustc$(X_$(CFG_BUILD)) define TARGET_HOST_RULES diff --git a/mk/tests.mk b/mk/tests.mk index 692d28bfad..48ebe4e540 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -19,9 +19,12 @@ DEPS_coretest := $(eval $(call RUST_CRATE,coretest)) -TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) coretest +DEPS_collectionstest := +$(eval $(call RUST_CRATE,collectionstest)) + +TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) collectionstest coretest TEST_DOC_CRATES = $(DOC_CRATES) -TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans,\ +TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\ $(HOST_CRATES)) TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) @@ -163,7 +166,7 @@ $(foreach file,$(wildcard $(S)src/doc/trpl/*.md), \ ###################################################################### # The main testing target. Tests lots of stuff. -check: cleantmptestlogs cleantestlibs all check-stage2 tidy +check: check-sanitycheck cleantmptestlogs cleantestlibs all check-stage2 tidy $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log # As above but don't bother running tidy. @@ -190,6 +193,11 @@ check-docs: cleantestlibs cleantmptestlogs check-stage2-docs # Not run as part of the normal test suite, but tested by bors on checkin. check-secondary: check-build-compiletest check-build-lexer-verifier check-lexer check-pretty +.PHONY: check-sanitycheck + +check-sanitycheck: + $(Q)$(CFG_PYTHON) $(S)src/etc/check-sanitycheck.py + # check + check-secondary. # # Issue #17883: build check-secondary first so hidden dependencies in @@ -372,7 +380,7 @@ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): \ $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \ $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) -o $$@ $$< --test \ -L "$$(RT_OUTPUT_DIR_$(2))" \ - -L "$$(LLVM_LIBDIR_$(2))" \ + $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ $$(RUSTFLAGS_$(4)) endef @@ -389,10 +397,11 @@ check-stage$(1)-T-$(2)-H-$(3)-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4 $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)) @$$(call E, run: $$<) + $$(Q)touch $$@.start_time $$(Q)$$(call CFG_RUN_TEST_$(2),$$<,$(1),$(2),$(3)) $$(TESTARGS) \ --logfile $$(call TEST_LOG_FILE,$(1),$(2),$(3),$(4)) \ $$(call CRATE_TEST_EXTRA_ARGS,$(1),$(2),$(3),$(4)) \ - && touch $$@ + && touch -r $$@.start_time $$@ && rm $$@.start_time endef define DEF_TEST_CRATE_RULES_android @@ -401,6 +410,7 @@ check-stage$(1)-T-$(2)-H-$(3)-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4 $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)) @$$(call E, run: $$< via adb) + $$(Q)touch $$@.start_time $$(Q)$(CFG_ADB) push $$< $(CFG_ADB_TEST_DIR) $$(Q)$(CFG_ADB) shell '(cd $(CFG_ADB_TEST_DIR); LD_LIBRARY_PATH=./$(2) \ ./$$(notdir $$<) \ @@ -414,7 +424,7 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ @if grep -q "result: ok" tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).tmp; \ then \ rm tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).tmp; \ - touch $$@; \ + touch -r $$@.start_time $$@ && rm $$@.start_time; \ else \ rm tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).tmp; \ exit 101; \ @@ -564,6 +574,11 @@ ifeq ($(CFG_OSTYPE),apple-darwin) CTEST_DISABLE_debuginfo-gdb = "gdb on darwin needs root" endif +ifeq ($(findstring android, $(CFG_TARGET)), android) +CTEST_DISABLE_debuginfo-gdb = +CTEST_DISABLE_debuginfo-lldb = "lldb tests are disabled on android" +endif + # CTEST_DISABLE_NONSELFHOST_$(TEST_GROUP), if set, will cause that # test group to be disabled *unless* the target is able to build a # compiler (i.e. when the target triple is in the set of of host @@ -588,7 +603,7 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \ # The tests select when to use debug configuration on their own; # remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898). -CTEST_RUSTC_FLAGS := $$(subst --cfg ndebug,,$$(CFG_RUSTC_FLAGS)) +CTEST_RUSTC_FLAGS := $$(subst -C debug-assertions,,$$(subst -C debug-assertions=on,,$$(CFG_RUSTC_FLAGS))) # The tests cannot be optimized while the rest of the compiler is optimized, so # filter out the optimization (if any) from rustc and then figure out if we need @@ -690,10 +705,11 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ $$(CTEST_DEPS_$(4)_$(1)-T-$(2)-H-$(3)) @$$(call E, run $(4) [$(2)]: $$<) + $$(Q)touch $$@.start_time $$(Q)$$(call CFG_RUN_CTEST_$(2),$(1),$$<,$(3)) \ $$(CTEST_ARGS$(1)-T-$(2)-H-$(3)-$(4)) \ --logfile $$(call TEST_LOG_FILE,$(1),$(2),$(3),$(4)) \ - && touch $$@ + && touch -r $$@.start_time $$@ && rm $$@.start_time else @@ -750,10 +766,11 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ $$(PRETTY_DEPS_$(4)) \ $$(PRETTY_DEPS$(1)_H_$(3)_$(4)) @$$(call E, run pretty-rpass [$(2)]: $$<) + $$(Q)touch $$@.start_time $$(Q)$$(call CFG_RUN_CTEST_$(2),$(1),$$<,$(3)) \ $$(PRETTY_ARGS$(1)-T-$(2)-H-$(3)-$(4)) \ --logfile $$(call TEST_LOG_FILE,$(1),$(2),$(3),$(4)) \ - && touch $$@ + && touch -r $$@.start_time $$@ && rm $$@.start_time endef @@ -799,8 +816,10 @@ endif ifeq ($(2),$$(CFG_BUILD)) $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): $$(DOCTESTDEP_$(1)_$(2)_$(3)_$(4)) @$$(call E, run doc-$(4) [$(2)]) + $$(Q)touch $$@.start_time $$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --cfg dox --test $$< \ - --test-args "$$(TESTARGS)" && touch $$@ + --test-args "$$(TESTARGS)" && \ + touch -r $$@.start_time $$@ && rm $$@.start_time else $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): touch $$@ @@ -835,9 +854,11 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-crate-$(4)-exec: \ ifeq ($(2),$$(CFG_BUILD)) $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-crate-$(4)): $$(CRATEDOCTESTDEP_$(1)_$(2)_$(3)_$(4)) @$$(call E, run doc-crate-$(4) [$(2)]) + $$(Q)touch $$@.start_time $$(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(3)) \ $$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test --cfg dox \ - $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && touch $$@ + $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && \ + touch -r $$@.start_time $$@ && rm $$@.start_time else $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-crate-$(4)): touch $$@ @@ -984,6 +1005,7 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ $$(CSREQ$(1)_T_$(2)_H_$(3)) @rm -rf $(3)/test/run-make/$$* @mkdir -p $(3)/test/run-make/$$* + $$(Q)touch $$@.start_time $$(Q)$$(CFG_PYTHON) $(S)src/etc/maketest.py $$(dir $$<) \ $$(MAKE) \ $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ @@ -996,7 +1018,7 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ "$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \ $(1) \ $$(S) - @touch $$@ + @touch -r $$@.start_time $$@ && rm $$@.start_time else # FIXME #11094 - The above rule doesn't work right for multiple targets check-stage$(1)-T-$(2)-H-$(3)-rmake-exec: diff --git a/mk/util.mk b/mk/util.mk index 3bbc8f413a..b419c0bbe8 100644 --- a/mk/util.mk +++ b/mk/util.mk @@ -17,4 +17,3 @@ else endif S := $(CFG_SRC_DIR) - diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 2c046d2527..fe556cecef 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -11,6 +11,7 @@ pub use self::Mode::*; use std::fmt; use std::str::FromStr; +use std::path::PathBuf; #[derive(Clone, Copy, PartialEq, Debug)] pub enum Mode { @@ -68,13 +69,13 @@ pub struct Config { pub run_lib_path: String, // The rustc executable - pub rustc_path: Path, + pub rustc_path: PathBuf, // The clang executable - pub clang_path: Option, + pub clang_path: Option, // The llvm binaries path - pub llvm_bin_path: Option, + pub llvm_bin_path: Option, // The valgrind path pub valgrind_path: Option, @@ -84,13 +85,13 @@ pub struct Config { pub force_valgrind: bool, // The directory containing the tests to run - pub src_base: Path, + pub src_base: PathBuf, // The directory where programs should be built - pub build_base: Path, + pub build_base: PathBuf, // Directory for auxiliary libraries - pub aux_base: Path, + pub aux_base: PathBuf, // The name of the stage being built (stage1, etc) pub stage_id: String, @@ -105,7 +106,7 @@ pub struct Config { pub filter: Option, // Write out a parseable log of tests that were run - pub logfile: Option, + pub logfile: Option, // A command line to prefix program execution with, // for running under valgrind @@ -133,7 +134,7 @@ pub struct Config { pub lldb_version: Option, // Path to the android tools - pub android_cross_path: Path, + pub android_cross_path: PathBuf, // Extra parameter to run adb on arm-linux-androideabi pub adb_path: String, diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 278ce5565d..f00ff9bcbe 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -12,16 +12,13 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(int_uint)] #![feature(old_io)] -#![feature(old_path)] #![feature(rustc_private)] #![feature(unboxed_closures)] #![feature(std_misc)] #![feature(test)] -#![feature(unicode)] -#![feature(env)] -#![feature(core)] +#![feature(path_ext)] +#![feature(str_char)] #![deny(warnings)] @@ -32,9 +29,8 @@ extern crate getopts; extern crate log; use std::env; -use std::old_io; -use std::old_io::fs; -use std::thunk::Thunk; +use std::fs; +use std::path::{Path, PathBuf}; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; @@ -115,9 +111,9 @@ pub fn parse_config(args: Vec ) -> Config { panic!() } - fn opt_path(m: &getopts::Matches, nm: &str) -> Path { + fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf { match m.opt_str(nm) { - Some(s) => Path::new(s), + Some(s) => PathBuf::from(&s), None => panic!("no option (=path) found for {}", nm), } } @@ -132,10 +128,10 @@ pub fn parse_config(args: Vec ) -> Config { compile_lib_path: matches.opt_str("compile-lib-path").unwrap(), run_lib_path: matches.opt_str("run-lib-path").unwrap(), rustc_path: opt_path(matches, "rustc-path"), - clang_path: matches.opt_str("clang-path").map(|s| Path::new(s)), + clang_path: matches.opt_str("clang-path").map(|s| PathBuf::from(&s)), valgrind_path: matches.opt_str("valgrind-path"), force_valgrind: matches.opt_present("force-valgrind"), - llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| Path::new(s)), + llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| PathBuf::from(&s)), src_base: opt_path(matches, "src-base"), build_base: opt_path(matches, "build-base"), aux_base: opt_path(matches, "aux-base"), @@ -143,7 +139,7 @@ pub fn parse_config(args: Vec ) -> Config { mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"), run_ignored: matches.opt_present("ignored"), filter: filter, - logfile: matches.opt_str("logfile").map(|s| Path::new(s)), + logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)), runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), target_rustcflags: matches.opt_str("target-rustcflags"), @@ -226,7 +222,7 @@ pub fn run_tests(config: &Config) { // android debug-info test uses remote debugger // so, we test 1 task at once. // also trying to isolate problems with adb_run_wrapper.sh ilooping - env::set_var("RUST_TEST_TASKS","1"); + env::set_var("RUST_TEST_THREADS","1"); } match config.mode { @@ -234,7 +230,7 @@ pub fn run_tests(config: &Config) { // Some older versions of LLDB seem to have problems with multiple // instances running in parallel, so only run one test task at a // time. - env::set_var("RUST_TEST_TASKS", "1"); + env::set_var("RUST_TEST_THREADS", "1"); } _ => { /* proceed */ } } @@ -244,7 +240,11 @@ pub fn run_tests(config: &Config) { // sadly osx needs some file descriptor limits raised for running tests in // parallel (especially when we have lots and lots of child processes). // For context, see #8904 - old_io::test::raise_fd_limit(); + #[allow(deprecated)] + fn raise_fd_limit() { + std::old_io::test::raise_fd_limit(); + } + raise_fd_limit(); // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary env::set_var("__COMPAT_LAYER", "RunAsInvoker"); @@ -268,7 +268,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { logfile: config.logfile.clone(), run_tests: true, run_benchmarks: true, - nocapture: false, + nocapture: env::var("RUST_TEST_NOCAPTURE").is_ok(), color: test::AutoColor, } } @@ -277,9 +277,9 @@ pub fn make_tests(config: &Config) -> Vec { debug!("making tests from {:?}", config.src_base.display()); let mut tests = Vec::new(); - let dirs = fs::readdir(&config.src_base).unwrap(); - for file in &dirs { - let file = file.clone(); + let dirs = fs::read_dir(&config.src_base).unwrap(); + for file in dirs { + let file = file.unwrap().path(); debug!("inspecting file {:?}", file.display()); if is_test(config, &file) { let t = make_test(config, &file, || { @@ -302,7 +302,7 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool { _ => vec!(".rc".to_string(), ".rs".to_string()) }; let invalid_prefixes = vec!(".".to_string(), "#".to_string(), "~".to_string()); - let name = testfile.filename_str().unwrap(); + let name = testfile.file_name().unwrap().to_str().unwrap(); let mut valid = false; @@ -328,7 +328,7 @@ pub fn make_test(config: &Config, testfile: &Path, f: F) -> test::TestDescAnd desc: test::TestDesc { name: make_test_name(config, testfile), ignore: header::is_test_ignored(config, testfile), - should_fail: test::ShouldFail::No, + should_panic: test::ShouldPanic::No, }, testfn: f(), } @@ -338,9 +338,9 @@ pub fn make_test_name(config: &Config, testfile: &Path) -> test::TestName { // Try to elide redundant long paths fn shorten(path: &Path) -> String { - let filename = path.filename_str(); - let p = path.dir_path(); - let dir = p.filename_str(); + let filename = path.file_name().unwrap().to_str(); + let p = path.parent().unwrap(); + let dir = p.file_name().unwrap().to_str(); format!("{}/{}", dir.unwrap_or(""), filename.unwrap_or("")) } @@ -349,19 +349,17 @@ pub fn make_test_name(config: &Config, testfile: &Path) -> test::TestName { pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn { let config = (*config).clone(); - // FIXME (#9639): This needs to handle non-utf8 paths - let testfile = testfile.as_str().unwrap().to_string(); - test::DynTestFn(Thunk::new(move || { - runtest::run(config, testfile) + let testfile = testfile.to_path_buf(); + test::DynTestFn(Box::new(move || { + runtest::run(config, &testfile) })) } pub fn make_metrics_test_closure(config: &Config, testfile: &Path) -> test::TestFn { let config = (*config).clone(); - // FIXME (#9639): This needs to handle non-utf8 paths - let testfile = testfile.as_str().unwrap().to_string(); + let testfile = testfile.to_path_buf(); test::DynMetricFn(box move |mm: &mut test::MetricMap| { - runtest::run_metrics(config, testfile, mm) + runtest::run_metrics(config, &testfile, mm) }) } diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index d8faa53a2d..4b2a3e0283 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -9,16 +9,19 @@ // except according to those terms. use self::WhichLine::*; -use std::old_io::{BufferedReader, File}; +use std::fs::File; +use std::io::BufReader; +use std::io::prelude::*; +use std::path::Path; pub struct ExpectedError { - pub line: uint, + pub line: usize, pub kind: String, pub msg: String, } #[derive(PartialEq, Debug)] -enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) } +enum WhichLine { ThisLine, FollowPrevious(usize), AdjustBackward(usize) } /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE" /// The former is a "follow" that inherits its target from the preceding line; @@ -29,7 +32,7 @@ enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) } /// //~| ERROR message two for that same line. // Load any test directives embedded in the file pub fn load_errors(testfile: &Path) -> Vec { - let mut rdr = BufferedReader::new(File::open(testfile).unwrap()); + let rdr = BufReader::new(File::open(testfile).unwrap()); // `last_nonfollow_error` tracks the most recently seen // line with an error template that did not use the @@ -55,10 +58,10 @@ pub fn load_errors(testfile: &Path) -> Vec { }).collect() } -fn parse_expected(last_nonfollow_error: Option, - line_num: uint, +fn parse_expected(last_nonfollow_error: Option, + line_num: usize, line: &str) -> Option<(WhichLine, ExpectedError)> { - let start = match line.find_str("//~") { Some(i) => i, None => return None }; + let start = match line.find("//~") { Some(i) => i, None => return None }; let (follow, adjusts) = if line.char_at(start + 3) == '|' { (true, 0) } else { @@ -68,7 +71,7 @@ fn parse_expected(last_nonfollow_error: Option, let letters = line[kind_start..].chars(); let kind = letters.skip_while(|c| c.is_whitespace()) .take_while(|c| !c.is_whitespace()) - .map(|c| c.to_lowercase()) + .flat_map(|c| c.to_lowercase()) .collect::(); let letters = line[kind_start..].chars(); let msg = letters.skip_while(|c| c.is_whitespace()) diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index c253967964..f5505b6e83 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::env; +use std::fs::File; +use std::io::BufReader; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; + use common::Config; use common; use util; @@ -21,7 +27,7 @@ pub struct TestProps { pub run_flags: Option, // If present, the name of a file that this test should match when // pretty-printed - pub pp_exact: Option, + pub pp_exact: Option, // Modules from aux directory that should be compiled pub aux_builds: Vec , // Environment settings to use during execution @@ -34,8 +40,8 @@ pub struct TestProps { pub check_stdout: bool, // Don't force a --crate-type=dylib flag on the command line pub no_prefer_dynamic: bool, - // Don't run --pretty expanded when running pretty printing tests - pub no_pretty_expanded: bool, + // Run --pretty expanded when running pretty printing tests + pub pretty_expanded: bool, // Which pretty mode are we testing with, default to 'normal' pub pretty_mode: String, // Only compare pretty output and don't try compiling @@ -56,11 +62,11 @@ pub fn load_props(testfile: &Path) -> TestProps { let mut force_host = false; let mut check_stdout = false; let mut no_prefer_dynamic = false; - let mut no_pretty_expanded = false; + let mut pretty_expanded = false; let mut pretty_mode = None; let mut pretty_compare_only = false; let mut forbid_output = Vec::new(); - iter_header(testfile, |ln| { + iter_header(testfile, &mut |ln| { match parse_error_pattern(ln) { Some(ep) => error_patterns.push(ep), None => () @@ -90,8 +96,8 @@ pub fn load_props(testfile: &Path) -> TestProps { no_prefer_dynamic = parse_no_prefer_dynamic(ln); } - if !no_pretty_expanded { - no_pretty_expanded = parse_no_pretty_expanded(ln); + if !pretty_expanded { + pretty_expanded = parse_pretty_expanded(ln); } if pretty_mode.is_none() { @@ -125,6 +131,16 @@ pub fn load_props(testfile: &Path) -> TestProps { true }); + for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { + match env::var(key) { + Ok(val) => + if exec_env.iter().find(|&&(ref x, _)| *x == key.to_string()).is_none() { + exec_env.push((key.to_string(), val)) + }, + Err(..) => {} + } + } + TestProps { error_patterns: error_patterns, compile_flags: compile_flags, @@ -136,7 +152,7 @@ pub fn load_props(testfile: &Path) -> TestProps { force_host: force_host, check_stdout: check_stdout, no_prefer_dynamic: no_prefer_dynamic, - no_pretty_expanded: no_pretty_expanded, + pretty_expanded: pretty_expanded, pretty_mode: pretty_mode.unwrap_or("normal".to_string()), pretty_compare_only: pretty_compare_only, forbid_output: forbid_output, @@ -147,6 +163,9 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { fn ignore_target(config: &Config) -> String { format!("ignore-{}", util::get_os(&config.target)) } + fn ignore_architecture(config: &Config) -> String { + format!("ignore-{}", util::get_arch(&config.target)) + } fn ignore_stage(config: &Config) -> String { format!("ignore-{}", config.stage_id.split('-').next().unwrap()) @@ -207,9 +226,10 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { } } - let val = iter_header(testfile, |ln| { + let val = iter_header(testfile, &mut |ln| { !parse_name_directive(ln, "ignore-test") && !parse_name_directive(ln, &ignore_target(config)) && + !parse_name_directive(ln, &ignore_architecture(config)) && !parse_name_directive(ln, &ignore_stage(config)) && !(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) && !(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) && @@ -220,12 +240,8 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { !val } -fn iter_header(testfile: &Path, mut it: F) -> bool where - F: FnMut(&str) -> bool, -{ - use std::old_io::{BufferedReader, File}; - - let mut rdr = BufferedReader::new(File::open(testfile).unwrap()); +fn iter_header(testfile: &Path, it: &mut FnMut(&str) -> bool) -> bool { + let rdr = BufReader::new(File::open(testfile).unwrap()); for ln in rdr.lines() { // Assume that any directives will be found before the first // module or function. This doesn't seem to be an optimization @@ -279,8 +295,8 @@ fn parse_no_prefer_dynamic(line: &str) -> bool { parse_name_directive(line, "no-prefer-dynamic") } -fn parse_no_pretty_expanded(line: &str) -> bool { - parse_name_directive(line, "no-pretty-expanded") +fn parse_pretty_expanded(line: &str) -> bool { + parse_name_directive(line, "pretty-expanded") } fn parse_pretty_mode(line: &str) -> Option { @@ -295,7 +311,7 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> { parse_name_value_directive(line, "exec-env").map(|nv| { // nv is either FOO or FOO=BAR let mut strs: Vec = nv - .splitn(1, '=') + .splitn(2, '=') .map(|s| s.to_string()) .collect(); @@ -310,12 +326,12 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> { }) } -fn parse_pp_exact(line: &str, testfile: &Path) -> Option { +fn parse_pp_exact(line: &str, testfile: &Path) -> Option { match parse_name_value_directive(line, "pp-exact") { - Some(s) => Some(Path::new(s)), + Some(s) => Some(PathBuf::from(&s)), None => { if parse_name_directive(line, "pp-exact") { - testfile.filename().map(|s| Path::new(s)) + testfile.file_name().map(|s| PathBuf::from(s)) } else { None } @@ -324,13 +340,14 @@ fn parse_pp_exact(line: &str, testfile: &Path) -> Option { } fn parse_name_directive(line: &str, directive: &str) -> bool { - line.contains(directive) + // This 'no-' rule is a quick hack to allow pretty-expanded and no-pretty-expanded to coexist + line.contains(directive) && !line.contains(&("no-".to_string() + directive)) } pub fn parse_name_value_directive(line: &str, directive: &str) -> Option { let keycolon = format!("{}:", directive); - match line.find_str(&keycolon) { + match line.find(&keycolon) { Some(colon) => { let value = line[(colon + keycolon.len()) .. line.len()].to_string(); debug!("{}: {}", directive, value); @@ -340,7 +357,7 @@ pub fn parse_name_value_directive(line: &str, directive: &str) } } -pub fn gdb_version_to_int(version_string: &str) -> int { +pub fn gdb_version_to_int(version_string: &str) -> isize { let error_string = format!( "Encountered GDB version string with unexpected format: {}", version_string); @@ -352,17 +369,17 @@ pub fn gdb_version_to_int(version_string: &str) -> int { panic!("{}", error_string); } - let major: int = components[0].parse().ok().expect(&error_string); - let minor: int = components[1].parse().ok().expect(&error_string); + let major: isize = components[0].parse().ok().expect(&error_string); + let minor: isize = components[1].parse().ok().expect(&error_string); return major * 1000 + minor; } -pub fn lldb_version_to_int(version_string: &str) -> int { +pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!( "Encountered LLDB version string with unexpected format: {}", version_string); let error_string = error_string; - let major: int = version_string.parse().ok().expect(&error_string); + let major: isize = version_string.parse().ok().expect(&error_string); return major; } diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index 148a43e6c7..b30efaa6c2 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -8,27 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::process::{ProcessExit, Command, Process, ProcessOutput}; use std::dynamic_lib::DynamicLibrary; +use std::io::prelude::*; +use std::path::PathBuf; +use std::process::{ExitStatus, Command, Child, Output, Stdio}; fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { // Need to be sure to put both the lib_path and the aux path in the dylib // search path for the child. let mut path = DynamicLibrary::search_path(); match aux_path { - Some(p) => path.insert(0, Path::new(p)), + Some(p) => path.insert(0, PathBuf::from(p)), None => {} } - path.insert(0, Path::new(lib_path)); + path.insert(0, PathBuf::from(lib_path)); // Add the new dylib search path var let var = DynamicLibrary::envvar(); let newpath = DynamicLibrary::create_path(&path); - let newpath = String::from_utf8(newpath).unwrap(); - cmd.env(var.to_string(), newpath); + let newpath = newpath.to_str().unwrap().to_string(); + cmd.env(var, &newpath); } -pub struct Result {pub status: ProcessExit, pub out: String, pub err: String} +pub struct Result {pub status: ExitStatus, pub out: String, pub err: String} pub fn run(lib_path: &str, prog: &str, @@ -38,10 +40,13 @@ pub fn run(lib_path: &str, input: Option) -> Option { let mut cmd = Command::new(prog); - cmd.args(args); + cmd.args(args) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); add_target_env(&mut cmd, lib_path, aux_path); for (key, val) in env { - cmd.env(key, val); + cmd.env(&key, &val); } match cmd.spawn() { @@ -49,13 +54,13 @@ pub fn run(lib_path: &str, if let Some(input) = input { process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); } - let ProcessOutput { status, output, error } = + let Output { status, stdout, stderr } = process.wait_with_output().unwrap(); Some(Result { status: status, - out: String::from_utf8(output).unwrap(), - err: String::from_utf8(error).unwrap() + out: String::from_utf8(stdout).unwrap(), + err: String::from_utf8(stderr).unwrap() }) }, Err(..) => None @@ -67,13 +72,16 @@ pub fn run_background(lib_path: &str, aux_path: Option<&str>, args: &[String], env: Vec<(String, String)> , - input: Option) -> Option { + input: Option) -> Option { let mut cmd = Command::new(prog); - cmd.args(args); + cmd.args(args) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); add_target_env(&mut cmd, lib_path, aux_path); for (key, val) in env { - cmd.env(key, val); + cmd.env(&key, &val); } match cmd.spawn() { diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 1cbb8742bb..23267c3e93 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -11,35 +11,28 @@ use self::TargetLocation::*; use common::Config; -use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind, DebugInfoGdb}; -use common::{Codegen, DebugInfoLldb}; +use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; +use common::{Codegen, DebugInfoLldb, DebugInfoGdb}; use errors; use header::TestProps; use header; use procsrv; use util::logv; -#[cfg(target_os = "windows")] -use util; - -#[cfg(target_os = "windows")] -use std::ascii::AsciiExt; -use std::old_io::File; -use std::old_io::fs::PathExtensions; -use std::old_io::fs; -use std::old_io::net::tcp; -use std::old_io::process::ProcessExit; -use std::old_io::process; -use std::old_io::timer; -use std::old_io; + use std::env; +use std::fmt; +use std::fs::{self, File}; +use std::io::BufReader; +use std::io::prelude::*; use std::iter::repeat; +use std::net::TcpStream; +use std::path::{Path, PathBuf}; +use std::process::{Command, Output, ExitStatus}; use std::str; -use std::string::String; -use std::thread; use std::time::Duration; use test::MetricMap; -pub fn run(config: Config, testfile: String) { +pub fn run(config: Config, testfile: &Path) { match &*config.target { "arm-linux-androideabi" | "aarch64-linux-android" => { @@ -55,12 +48,11 @@ pub fn run(config: Config, testfile: String) { run_metrics(config, testfile, &mut _mm); } -pub fn run_metrics(config: Config, testfile: String, mm: &mut MetricMap) { +pub fn run_metrics(config: Config, testfile: &Path, mm: &mut MetricMap) { if config.verbose { // We're going to be dumping a lot of info. Start on a new line. print!("\n\n"); } - let testfile = Path::new(testfile); debug!("running {:?}", testfile.display()); let props = header::load_props(&testfile); debug!("loaded props"); @@ -89,7 +81,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) { let proc_res = compile_test(config, props, testfile); if proc_res.status.success() { - fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[], + fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[..], &proc_res); } @@ -127,8 +119,8 @@ fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) { }; // The value our Makefile configures valgrind to return on failure - static VALGRIND_ERR: int = 100; - if proc_res.status.matches_exit_status(VALGRIND_ERR) { + const VALGRIND_ERR: i32 = 100; + if proc_res.status.code() == Some(VALGRIND_ERR) { fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res); } @@ -139,10 +131,10 @@ fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) { fn check_correct_failure_status(proc_res: &ProcRes) { // The value the rust runtime returns on failure - static RUST_ERR: int = 101; - if !proc_res.status.matches_exit_status(RUST_ERR) { + const RUST_ERR: i32 = 101; + if proc_res.status.code() != Some(RUST_ERR) { fatal_proc_rec( - &format!("failure produced the wrong error: {:?}", + &format!("failure produced the wrong error: {}", proc_res.status), proc_res); } @@ -201,8 +193,8 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { let rounds = match props.pp_exact { Some(_) => 1, None => 2 }; - let src = File::open(testfile).read_to_end().unwrap(); - let src = String::from_utf8(src.clone()).unwrap(); + let mut src = String::new(); + File::open(testfile).unwrap().read_to_string(&mut src).unwrap(); let mut srcs = vec!(src); let mut round = 0; @@ -226,9 +218,10 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { let mut expected = match props.pp_exact { Some(ref file) => { - let filepath = testfile.dir_path().join(file); - let s = File::open(&filepath).read_to_end().unwrap(); - String::from_utf8(s).unwrap() + let filepath = testfile.parent().unwrap().join(file); + let mut s = String::new(); + File::open(&filepath).unwrap().read_to_string(&mut s).unwrap(); + s } None => { srcs[srcs.len() - 2].clone() } }; @@ -252,7 +245,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { if !proc_res.status.success() { fatal_proc_rec("pretty-printed source does not typecheck", &proc_res); } - if props.no_pretty_expanded { return } + if !props.pretty_expanded { return } // additionally, run `--pretty expanded` and try to build it. let proc_res = print_source(config, props, testfile, srcs[round].clone(), "expanded"); @@ -283,7 +276,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { pretty_type.to_string()), props.exec_env.clone(), &config.compile_lib_path, - Some(aux_dir.as_str().unwrap()), + Some(aux_dir.to_str().unwrap()), Some(src)) } @@ -299,11 +292,11 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) { pretty_type, format!("--target={}", config.target), "-L".to_string(), - aux_dir.as_str().unwrap().to_string()); + aux_dir.to_str().unwrap().to_string()); args.extend(split_maybe_args(&config.target_rustcflags).into_iter()); args.extend(split_maybe_args(&props.compile_flags).into_iter()); return ProcArgs { - prog: config.rustc_path.as_str().unwrap().to_string(), + prog: config.rustc_path.to_str().unwrap().to_string(), args: args, }; } @@ -345,14 +338,14 @@ actual:\n\ "--crate-type=lib".to_string(), format!("--target={}", target), "-L".to_string(), - config.build_base.as_str().unwrap().to_string(), + config.build_base.to_str().unwrap().to_string(), "-L".to_string(), - aux_dir.as_str().unwrap().to_string()); + aux_dir.to_str().unwrap().to_string()); args.extend(split_maybe_args(&config.target_rustcflags).into_iter()); args.extend(split_maybe_args(&props.compile_flags).into_iter()); // FIXME (#9639): This needs to handle non-utf8 paths return ProcArgs { - prog: config.rustc_path.as_str().unwrap().to_string(), + prog: config.rustc_path.to_str().unwrap().to_string(), args: args, }; } @@ -390,18 +383,19 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { // write debugger script let mut script_str = String::with_capacity(2048); script_str.push_str("set charset UTF-8\n"); - script_str.push_str(&format!("file {}\n", exe_file.as_str().unwrap())); + script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap())); script_str.push_str("target remote :5039\n"); script_str.push_str(&format!("set solib-search-path \ ./{}/stage2/lib/rustlib/{}/lib/\n", config.host, config.target)); for line in breakpoint_lines.iter() { script_str.push_str(&format!("break {:?}:{}\n", - testfile.filename_display(), - *line)[]); + testfile.file_name().unwrap() + .to_string_lossy(), + *line)[..]); } script_str.push_str(&cmds); - script_str.push_str("quit\n"); + script_str.push_str("\nquit\n"); debug!("script_str = {}", script_str); dump_output_file(config, @@ -415,7 +409,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { None, &[ "push".to_string(), - exe_file.as_str().unwrap().to_string(), + exe_file.to_str().unwrap().to_string(), config.adb_test_dir.clone() ], vec!(("".to_string(), "".to_string())), @@ -440,9 +434,8 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { if config.target.contains("aarch64") {"64"} else {""}, config.adb_test_dir.clone(), - str::from_utf8( - exe_file.filename() - .unwrap()).unwrap()); + exe_file.file_name().unwrap().to_str() + .unwrap()); let mut process = procsrv::run_background("", &config.adb_path @@ -458,17 +451,17 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { .expect(&format!("failed to exec `{:?}`", config.adb_path)); loop { //waiting 1 second for gdbserver start - timer::sleep(Duration::milliseconds(1000)); - let result = thread::spawn(move || { - tcp::TcpStream::connect("127.0.0.1:5039").unwrap(); - }).join(); - if result.is_err() { - continue; + #[allow(deprecated)] + fn sleep() { + ::std::old_io::timer::sleep(Duration::milliseconds(1000)); + } + sleep(); + if TcpStream::connect("127.0.0.1:5039").is_ok() { + break } - break; } - let tool_path = match config.android_cross_path.as_str() { + let tool_path = match config.android_cross_path.to_str() { Some(x) => x.to_string(), None => fatal("cannot find android cross path") }; @@ -479,7 +472,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { vec!("-quiet".to_string(), "-batch".to_string(), "-nx".to_string(), - format!("-command={}", debugger_script.as_str().unwrap())); + format!("-command={}", debugger_script.to_str().unwrap())); let mut gdb_path = tool_path; gdb_path.push_str(&format!("/bin/{}-gdb", config.target)); @@ -503,12 +496,12 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { }; debugger_run_result = ProcRes { - status: status, + status: Status::Normal(status), stdout: out, stderr: err, cmdline: cmdline }; - if process.signal_kill().is_err() { + if process.kill().is_err() { println!("Adb process is already finished."); } } @@ -518,7 +511,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { .expect("Could not find Rust source root"); let rust_pp_module_rel_path = Path::new("./src/etc"); let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) - .as_str() + .to_str() .unwrap() .to_string(); // write debugger script @@ -538,7 +531,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { // GDB's script auto loading safe path script_str.push_str( &format!("add-auto-load-safe-path {}\n", - rust_pp_module_abs_path.replace("\\", "\\\\")) + rust_pp_module_abs_path.replace(r"\", r"\\")) ); } } @@ -553,21 +546,24 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { script_str.push_str("set print pretty off\n"); // Add the pretty printer directory to GDB's source-file search path - script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path)[]); + script_str.push_str(&format!("directory {}\n", + rust_pp_module_abs_path)); // Load the target executable script_str.push_str(&format!("file {}\n", - exe_file.as_str().unwrap().replace("\\", "\\\\"))[]); + exe_file.to_str().unwrap() + .replace(r"\", r"\\"))); // Add line breakpoints for line in &breakpoint_lines { script_str.push_str(&format!("break '{}':{}\n", - testfile.filename_display(), - *line)[]); + testfile.file_name().unwrap() + .to_string_lossy(), + *line)); } script_str.push_str(&cmds); - script_str.push_str("quit\n"); + script_str.push_str("\nquit\n"); debug!("script_str = {}", script_str); dump_output_file(config, @@ -576,13 +572,8 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { "debugger.script"); // run debugger script with gdb - #[cfg(windows)] - fn debugger() -> String { - "gdb.exe".to_string() - } - #[cfg(unix)] - fn debugger() -> String { - "gdb".to_string() + fn debugger() -> &'static str { + if cfg!(windows) {"gdb.exe"} else {"gdb"} } let debugger_script = make_out_name(config, testfile, "debugger.script"); @@ -592,10 +583,10 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { vec!("-quiet".to_string(), "-batch".to_string(), "-nx".to_string(), - format!("-command={}", debugger_script.as_str().unwrap())); + format!("-command={}", debugger_script.to_str().unwrap())); let proc_args = ProcArgs { - prog: debugger(), + prog: debugger().to_string(), args: debugger_opts, }; @@ -618,7 +609,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { check_debugger_output(&debugger_run_result, &check_lines); } -fn find_rust_src_root(config: &Config) -> Option { +fn find_rust_src_root(config: &Config) -> Option { let mut path = config.src_base.clone(); let path_postfix = Path::new("src/etc/lldb_batchmode.py"); @@ -632,8 +623,6 @@ fn find_rust_src_root(config: &Config) -> Option { } fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) { - use std::old_io::process::{Command, ProcessOutput}; - if config.lldb_python_dir.is_none() { fatal("Can't run LLDB test because LLDB's python path is not set."); } @@ -685,11 +674,12 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) .expect("Could not find Rust source root"); let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py"); let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) - .as_str() + .to_str() .unwrap() .to_string(); - script_str.push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[]); + script_str.push_str(&format!("command script import {}\n", + &rust_pp_module_abs_path[..])[..]); script_str.push_str("type summary add --no-value "); script_str.push_str("--python-function lldb_rust_formatters.print_val "); script_str.push_str("-x \".*\" --category Rust\n"); @@ -707,7 +697,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) } // Finally, quit the debugger - script_str.push_str("quit\n"); + script_str.push_str("\nquit\n"); // Write the script into a file debug!("script_str = {}", script_str); @@ -735,22 +725,19 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) rust_src_root: &Path) -> ProcRes { // Prepare the lldb_batchmode which executes the debugger script - let lldb_script_path = rust_src_root.join(Path::new("./src/etc/lldb_batchmode.py")); + let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py"); let mut cmd = Command::new("python"); - cmd.arg(lldb_script_path) + cmd.arg(&lldb_script_path) .arg(test_executable) .arg(debugger_script) - .env_set_all(&[("PYTHONPATH", config.lldb_python_dir.clone().unwrap())]); - - let (status, out, err) = match cmd.spawn() { - Ok(process) => { - let ProcessOutput { status, output, error } = - process.wait_with_output().unwrap(); + .env("PYTHONPATH", config.lldb_python_dir.as_ref().unwrap()); + let (status, out, err) = match cmd.output() { + Ok(Output { status, stdout, stderr }) => { (status, - String::from_utf8(output).unwrap(), - String::from_utf8(error).unwrap()) + String::from_utf8(stdout).unwrap(), + String::from_utf8(stderr).unwrap()) }, Err(e) => { fatal(&format!("Failed to setup Python process for \ @@ -760,7 +747,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) dump_output(config, test_executable, &out, &err); return ProcRes { - status: status, + status: Status::Normal(status), stdout: out, stderr: err, cmdline: format!("{:?}", cmd) @@ -771,13 +758,11 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) struct DebuggerCommands { commands: Vec, check_lines: Vec, - breakpoint_lines: Vec, + breakpoint_lines: Vec, } fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) -> DebuggerCommands { - use std::old_io::{BufferedReader, File}; - let command_directive = format!("{}-command", debugger_prefix); let check_directive = format!("{}-check", debugger_prefix); @@ -785,7 +770,7 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) let mut commands = vec!(); let mut check_lines = vec!(); let mut counter = 1; - let mut reader = BufferedReader::new(File::open(file_path).unwrap()); + let reader = BufReader::new(File::open(file_path).unwrap()); for line in reader.lines() { match line { Ok(line) => { @@ -847,7 +832,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) check_lines.iter().map(|s| { s .trim() - .split_str("[...]") + .split("[...]") .map(|x| x.to_string()) .collect() }).collect(); @@ -866,7 +851,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) None } } else { - rest.find_str(frag) + rest.find(frag) }; match found { None => { @@ -963,16 +948,17 @@ fn check_expected_errors(expected_errors: Vec , let prefixes = expected_errors.iter().map(|ee| { format!("{}:{}:", testfile.display(), ee.line) - }).collect:: >(); - - #[cfg(windows)] - fn prefix_matches( line : &str, prefix : &str ) -> bool { - line.to_ascii_lowercase().starts_with(&prefix.to_ascii_lowercase()) - } - - #[cfg(unix)] - fn prefix_matches( line : &str, prefix : &str ) -> bool { - line.starts_with( prefix ) + }).collect::>(); + + fn prefix_matches(line: &str, prefix: &str) -> bool { + use std::ascii::AsciiExt; + // On windows just translate all '\' path separators to '/' + let line = line.replace(r"\", "/"); + if cfg!(windows) { + line.to_ascii_lowercase().starts_with(&prefix.to_ascii_lowercase()) + } else { + line.starts_with(prefix) + } } // A multi-line error will have followup lines which will always @@ -1050,7 +1036,7 @@ fn is_compiler_error_or_warning(line: &str) -> bool { scan_string(line, "warning", &mut i)); } -fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool { +fn scan_until_char(haystack: &str, needle: char, idx: &mut usize) -> bool { if *idx >= haystack.len() { return false; } @@ -1062,26 +1048,26 @@ fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool { return true; } -fn scan_char(haystack: &str, needle: char, idx: &mut uint) -> bool { +fn scan_char(haystack: &str, needle: char, idx: &mut usize) -> bool { if *idx >= haystack.len() { return false; } - let range = haystack.char_range_at(*idx); - if range.ch != needle { + let ch = haystack.char_at(*idx); + if ch != needle { return false; } - *idx = range.next; + *idx += ch.len_utf8(); return true; } -fn scan_integer(haystack: &str, idx: &mut uint) -> bool { +fn scan_integer(haystack: &str, idx: &mut usize) -> bool { let mut i = *idx; while i < haystack.len() { - let range = haystack.char_range_at(i); - if range.ch < '0' || '9' < range.ch { + let ch = haystack.char_at(i); + if ch < '0' || '9' < ch { break; } - i = range.next; + i += ch.len_utf8(); } if i == *idx { return false; @@ -1090,16 +1076,16 @@ fn scan_integer(haystack: &str, idx: &mut uint) -> bool { return true; } -fn scan_string(haystack: &str, needle: &str, idx: &mut uint) -> bool { +fn scan_string(haystack: &str, needle: &str, idx: &mut usize) -> bool { let mut haystack_i = *idx; let mut needle_i = 0; while needle_i < needle.len() { if haystack_i >= haystack.len() { return false; } - let range = haystack.char_range_at(haystack_i); - haystack_i = range.next; - if !scan_char(needle, range.ch, &mut needle_i) { + let ch = haystack.char_at(haystack_i); + haystack_i += ch.len_utf8(); + if !scan_char(needle, ch, &mut needle_i) { return false; } } @@ -1113,12 +1099,42 @@ struct ProcArgs { } struct ProcRes { - status: ProcessExit, + status: Status, stdout: String, stderr: String, cmdline: String, } +enum Status { + Parsed(i32), + Normal(ExitStatus), +} + +impl Status { + fn code(&self) -> Option { + match *self { + Status::Parsed(i) => Some(i), + Status::Normal(ref e) => e.code(), + } + } + + fn success(&self) -> bool { + match *self { + Status::Parsed(i) => i == 0, + Status::Normal(ref e) => e.success(), + } + } +} + +impl fmt::Display for Status { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Status::Parsed(i) => write!(f, "exit code: {}", i), + Status::Normal(ref e) => e.fmt(f), + } + } +} + fn compile_test(config: &Config, props: &TestProps, testfile: &Path) -> ProcRes { compile_test_(config, props, testfile, &[]) @@ -1133,7 +1149,7 @@ fn compile_test_(config: &Config, props: &TestProps, let aux_dir = aux_output_dir_name(config, testfile); // FIXME (#9639): This needs to handle non-utf8 paths let mut link_args = vec!("-L".to_string(), - aux_dir.as_str().unwrap().to_string()); + aux_dir.to_str().unwrap().to_string()); link_args.extend(extra_args.iter().cloned()); let args = make_compile_args(config, props, @@ -1160,7 +1176,7 @@ fn exec_compiled_test(config: &Config, props: &TestProps, make_run_args(config, props, testfile), env, &config.run_lib_path, - Some(aux_dir.as_str().unwrap()), + Some(aux_dir.to_str().unwrap()), None) } } @@ -1179,7 +1195,7 @@ fn compose_and_run_compiler( let aux_dir = aux_output_dir_name(config, testfile); // FIXME (#9639): This needs to handle non-utf8 paths - let extra_link_args = vec!("-L".to_string(), aux_dir.as_str().unwrap().to_string()); + let extra_link_args = vec!("-L".to_string(), aux_dir.to_str().unwrap().to_string()); for rel_ab in &props.aux_builds { let abs_ab = config.aux_base.join(rel_ab); @@ -1196,7 +1212,8 @@ fn compose_and_run_compiler( crate_type, |a,b| { let f = make_lib_name(a, b, testfile); - TargetLocation::ThisDirectory(f.dir_path()) + let parent = f.parent().unwrap(); + TargetLocation::ThisDirectory(parent.to_path_buf()) }, &abs_ab); let auxres = compose_and_run(config, @@ -1204,7 +1221,7 @@ fn compose_and_run_compiler( aux_args, Vec::new(), &config.compile_lib_path, - Some(aux_dir.as_str().unwrap()), + Some(aux_dir.to_str().unwrap()), None); if !auxres.status.success() { fatal_proc_rec( @@ -1226,13 +1243,13 @@ fn compose_and_run_compiler( args, Vec::new(), &config.compile_lib_path, - Some(aux_dir.as_str().unwrap()), + Some(aux_dir.to_str().unwrap()), input) } fn ensure_dir(path: &Path) { if path.is_dir() { return; } - fs::mkdir(path, old_io::USER_RWX).unwrap(); + fs::create_dir(path).unwrap(); } fn compose_and_run(config: &Config, testfile: &Path, @@ -1246,8 +1263,8 @@ fn compose_and_run(config: &Config, testfile: &Path, } enum TargetLocation { - ThisFile(Path), - ThisDirectory(Path), + ThisFile(PathBuf), + ThisDirectory(PathBuf), } fn make_compile_args(config: &Config, @@ -1265,9 +1282,9 @@ fn make_compile_args(config: &Config, &*config.target }; // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec!(testfile.as_str().unwrap().to_string(), + let mut args = vec!(testfile.to_str().unwrap().to_string(), "-L".to_string(), - config.build_base.as_str().unwrap().to_string(), + config.build_base.to_str().unwrap().to_string(), format!("--target={}", target)); args.push_all(&extras); if !props.no_prefer_dynamic { @@ -1284,7 +1301,7 @@ fn make_compile_args(config: &Config, path } }; - args.push(path.as_str().unwrap().to_string()); + args.push(path.to_str().unwrap().to_string()); if props.force_host { args.extend(split_maybe_args(&config.host_rustcflags).into_iter()); } else { @@ -1292,24 +1309,24 @@ fn make_compile_args(config: &Config, } args.extend(split_maybe_args(&props.compile_flags).into_iter()); return ProcArgs { - prog: config.rustc_path.as_str().unwrap().to_string(), + prog: config.rustc_path.to_str().unwrap().to_string(), args: args, }; } -fn make_lib_name(config: &Config, auxfile: &Path, testfile: &Path) -> Path { +fn make_lib_name(config: &Config, auxfile: &Path, testfile: &Path) -> PathBuf { // what we return here is not particularly important, as it // happens; rustc ignores everything except for the directory. let auxname = output_testname(auxfile); aux_output_dir_name(config, testfile).join(&auxname) } -fn make_exe_name(config: &Config, testfile: &Path) -> Path { +fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf { let mut f = output_base_name(config, testfile); if !env::consts::EXE_SUFFIX.is_empty() { - let mut fname = f.filename().unwrap().to_vec(); - fname.extend(env::consts::EXE_SUFFIX.bytes()); - f.set_filename(fname); + let mut fname = f.file_name().unwrap().to_os_string(); + fname.push(env::consts::EXE_SUFFIX); + f.set_file_name(&fname); } f } @@ -1322,7 +1339,7 @@ fn make_run_args(config: &Config, props: &TestProps, testfile: &Path) -> let exe_file = make_exe_name(config, testfile); // FIXME (#9639): This needs to handle non-utf8 paths - args.push(exe_file.as_str().unwrap().to_string()); + args.push(exe_file.to_str().unwrap().to_string()); // Add the arguments in the run_flags directive args.extend(split_maybe_args(&props.run_flags).into_iter()); @@ -1375,29 +1392,28 @@ fn program_output(config: &Config, testfile: &Path, lib_path: &str, prog: String input).expect(&format!("failed to exec `{}`", prog)); dump_output(config, testfile, &out, &err); return ProcRes { - status: status, + status: Status::Normal(status), stdout: out, stderr: err, cmdline: cmdline, }; } -// Linux and mac don't require adjusting the library search path -#[cfg(unix)] -fn make_cmdline(_libpath: &str, prog: &str, args: &[String]) -> String { - format!("{} {}", prog, args.connect(" ")) -} - -#[cfg(windows)] fn make_cmdline(libpath: &str, prog: &str, args: &[String]) -> String { + use util; - // Build the LD_LIBRARY_PATH variable as it would be seen on the command line - // for diagnostic purposes - fn lib_path_cmd_prefix(path: &str) -> String { - format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) - } + // Linux and mac don't require adjusting the library search path + if cfg!(unix) { + format!("{} {}", prog, args.connect(" ")) + } else { + // Build the LD_LIBRARY_PATH variable as it would be seen on the command line + // for diagnostic purposes + fn lib_path_cmd_prefix(path: &str) -> String { + format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) + } - format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.connect(" ")) + format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.connect(" ")) + } } fn dump_output(config: &Config, testfile: &Path, out: &str, err: &str) { @@ -1409,25 +1425,25 @@ fn dump_output(config: &Config, testfile: &Path, out: &str, err: &str) { fn dump_output_file(config: &Config, testfile: &Path, out: &str, extension: &str) { let outfile = make_out_name(config, testfile, extension); - File::create(&outfile).write_all(out.as_bytes()).unwrap(); + File::create(&outfile).unwrap().write_all(out.as_bytes()).unwrap(); } -fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> Path { +fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> PathBuf { output_base_name(config, testfile).with_extension(extension) } -fn aux_output_dir_name(config: &Config, testfile: &Path) -> Path { +fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf { let f = output_base_name(config, testfile); - let mut fname = f.filename().unwrap().to_vec(); - fname.extend("libaux".bytes()); - f.with_filename(fname) + let mut fname = f.file_name().unwrap().to_os_string(); + fname.push("libaux"); + f.with_file_name(&fname) } -fn output_testname(testfile: &Path) -> Path { - Path::new(testfile.filestem().unwrap()) +fn output_testname(testfile: &Path) -> PathBuf { + PathBuf::from(testfile.file_stem().unwrap()) } -fn output_base_name(config: &Config, testfile: &Path) -> Path { +fn output_base_name(config: &Config, testfile: &Path) -> PathBuf { config.build_base .join(&output_testname(testfile)) .with_extension(&config.stage_id) @@ -1542,11 +1558,11 @@ fn _arm_exec_compiled_test(config: &Config, Some("".to_string())) .expect(&format!("failed to exec `{}`", config.adb_path)); - let mut exitcode: int = 0; + let mut exitcode: i32 = 0; for c in exitcode_out.chars() { if !c.is_numeric() { break; } exitcode = exitcode * 10 + match c { - '0' ... '9' => c as int - ('0' as int), + '0' ... '9' => c as i32 - ('0' as i32), _ => 101, } } @@ -1587,7 +1603,7 @@ fn _arm_exec_compiled_test(config: &Config, &stderr_out); ProcRes { - status: process::ProcessExit::ExitStatus(exitcode), + status: Status::Parsed(exitcode), stdout: stdout_out, stderr: stderr_out, cmdline: cmdline @@ -1597,16 +1613,17 @@ fn _arm_exec_compiled_test(config: &Config, fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) { let tdir = aux_output_dir_name(config, testfile); - let dirs = fs::readdir(&tdir).unwrap(); - for file in &dirs { - if file.extension_str() == Some("so") { + let dirs = fs::read_dir(&tdir).unwrap(); + for file in dirs { + let file = file.unwrap().path(); + if file.extension().and_then(|s| s.to_str()) == Some("so") { // FIXME (#9639): This needs to handle non-utf8 paths let copy_result = procsrv::run("", &config.adb_path, None, &[ "push".to_string(), - file.as_str() + file.to_str() .unwrap() .to_string(), config.adb_test_dir.to_string(), @@ -1627,14 +1644,14 @@ fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) { // codegen tests (vs. clang) -fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path { +fn append_suffix_to_stem(p: &Path, suffix: &str) -> PathBuf { if suffix.len() == 0 { - (*p).clone() + p.to_path_buf() } else { - let mut stem = p.filestem().unwrap().to_vec(); - stem.extend("-".bytes()); - stem.extend(suffix.bytes()); - p.with_filename(stem) + let mut stem = p.file_stem().unwrap().to_os_string(); + stem.push("-"); + stem.push(suffix); + p.with_file_name(&stem) } } @@ -1643,7 +1660,7 @@ fn compile_test_and_save_bitcode(config: &Config, props: &TestProps, let aux_dir = aux_output_dir_name(config, testfile); // FIXME (#9639): This needs to handle non-utf8 paths let mut link_args = vec!("-L".to_string(), - aux_dir.as_str().unwrap().to_string()); + aux_dir.to_str().unwrap().to_string()); let llvm_args = vec!("--emit=llvm-bc,obj".to_string(), "--crate-type=lib".to_string()); link_args.extend(llvm_args.into_iter()); @@ -1651,7 +1668,8 @@ fn compile_test_and_save_bitcode(config: &Config, props: &TestProps, props, link_args, |a, b| TargetLocation::ThisDirectory( - output_base_name(a, b).dir_path()), + output_base_name(a, b).parent() + .unwrap().to_path_buf()), testfile); compose_and_run_compiler(config, props, testfile, args, None) } @@ -1663,12 +1681,12 @@ fn compile_cc_with_clang_and_save_bitcode(config: &Config, _props: &TestProps, let testcc = testfile.with_extension("cc"); let proc_args = ProcArgs { // FIXME (#9639): This needs to handle non-utf8 paths - prog: config.clang_path.as_ref().unwrap().as_str().unwrap().to_string(), + prog: config.clang_path.as_ref().unwrap().to_str().unwrap().to_string(), args: vec!("-c".to_string(), "-emit-llvm".to_string(), "-o".to_string(), - bitcodefile.as_str().unwrap().to_string(), - testcc.as_str().unwrap().to_string()) + bitcodefile.to_str().unwrap().to_string(), + testcc.to_str().unwrap().to_string()) }; compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None) } @@ -1682,10 +1700,10 @@ fn extract_function_from_bitcode(config: &Config, _props: &TestProps, let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-extract"); let proc_args = ProcArgs { // FIXME (#9639): This needs to handle non-utf8 paths - prog: prog.as_str().unwrap().to_string(), + prog: prog.to_str().unwrap().to_string(), args: vec!(format!("-func={}", fname), - format!("-o={}", extracted_bc.as_str().unwrap()), - bitcodefile.as_str().unwrap().to_string()) + format!("-o={}", extracted_bc.to_str().unwrap()), + bitcodefile.to_str().unwrap().to_string()) }; compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None) } @@ -1699,16 +1717,17 @@ fn disassemble_extract(config: &Config, _props: &TestProps, let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-dis"); let proc_args = ProcArgs { // FIXME (#9639): This needs to handle non-utf8 paths - prog: prog.as_str().unwrap().to_string(), - args: vec!(format!("-o={}", extracted_ll.as_str().unwrap()), - extracted_bc.as_str().unwrap().to_string()) + prog: prog.to_str().unwrap().to_string(), + args: vec!(format!("-o={}", extracted_ll.to_str().unwrap()), + extracted_bc.to_str().unwrap().to_string()) }; compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None) } -fn count_extracted_lines(p: &Path) -> uint { - let x = File::open(&p.with_extension("ll")).read_to_end().unwrap(); +fn count_extracted_lines(p: &Path) -> usize { + let mut x = Vec::new(); + File::open(&p.with_extension("ll")).unwrap().read_to_end(&mut x).unwrap(); let x = str::from_utf8(&x).unwrap(); x.lines().count() } diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs index c046a89cba..a8b26cb3ef 100644 --- a/src/compiletest/util.rs +++ b/src/compiletest/util.rs @@ -8,22 +8,39 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use common::Config; - -#[cfg(target_os = "windows")] use std::env; +use common::Config; /// Conversion table from triple OS name to Rust SYSNAME -static OS_TABLE: &'static [(&'static str, &'static str)] = &[ - ("mingw32", "windows"), - ("win32", "windows"), - ("windows", "windows"), - ("darwin", "macos"), +const OS_TABLE: &'static [(&'static str, &'static str)] = &[ ("android", "android"), - ("linux", "linux"), - ("freebsd", "freebsd"), + ("bitrig", "bitrig"), + ("darwin", "macos"), ("dragonfly", "dragonfly"), + ("freebsd", "freebsd"), + ("ios", "ios"), + ("linux", "linux"), + ("mingw32", "windows"), ("openbsd", "openbsd"), + ("win32", "windows"), + ("windows", "windows"), +]; + +const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ + ("aarch64", "aarch64"), + ("amd64", "x86_64"), + ("arm", "arm"), + ("arm64", "aarch64"), + ("hexagon", "hexagon"), + ("i386", "x86"), + ("i686", "x86"), + ("mips", "mips"), + ("msp430", "msp430"), + ("powerpc", "powerpc"), + ("s390x", "systemz"), + ("sparc", "sparc"), + ("x86_64", "x86_64"), + ("xcore", "xcore"), ]; pub fn get_os(triple: &str) -> &'static str { @@ -34,25 +51,29 @@ pub fn get_os(triple: &str) -> &'static str { } panic!("Cannot determine OS from triple"); } +pub fn get_arch(triple: &str) -> &'static str { + for &(triple_arch, arch) in ARCH_TABLE { + if triple.contains(triple_arch) { + return arch + } + } + panic!("Cannot determine Architecture from triple"); +} -#[cfg(target_os = "windows")] pub fn make_new_path(path: &str) -> String { - + assert!(cfg!(windows)); // Windows just uses PATH as the library search path, so we have to // maintain the current value while adding our own match env::var(lib_path_env_var()) { - Ok(curr) => { - format!("{}{}{}", path, path_div(), curr) - } - Err(..) => path.to_string() + Ok(curr) => { + format!("{}{}{}", path, path_div(), curr) + } + Err(..) => path.to_string() } } -#[cfg(target_os = "windows")] pub fn lib_path_env_var() -> &'static str { "PATH" } - -#[cfg(target_os = "windows")] -pub fn path_div() -> &'static str { ";" } +fn path_div() -> &'static str { ";" } pub fn logv(config: &Config, s: String) { debug!("{}", s); diff --git a/src/doc/complement-design-faq.md b/src/doc/complement-design-faq.md index e57953db3a..3edbcbe62c 100644 --- a/src/doc/complement-design-faq.md +++ b/src/doc/complement-design-faq.md @@ -174,3 +174,10 @@ bindings. See also [a long thread][alt] on renaming `let mut` to `var`. [alt]: https://mail.mozilla.org/pipermail/rust-dev/2014-January/008319.html + +## Why no `--x` or `x++`? + +Preincrement and postincrement, while convenient, are also fairly complex. They +require knowledge of evaluation order, and often lead to subtle bugs and +undefined behavior in C and C++. `x = x + 1` or `x += 1` is only slightly +longer, but unambiguous. diff --git a/src/doc/grammar.md b/src/doc/grammar.md index d7a29ea530..1ea3c7d7bd 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -290,7 +290,7 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']' # Items and attributes -**FIXME:** grammar? +**FIXME:** grammar? ## Items @@ -301,7 +301,7 @@ item : mod_item | fn_item | type_item | struct_item | enum_item ### Type Parameters -**FIXME:** grammar? +**FIXME:** grammar? ### Modules @@ -338,35 +338,35 @@ path_item : ident | "mod" ; ### Functions -**FIXME:** grammar? +**FIXME:** grammar? #### Generic functions -**FIXME:** grammar? +**FIXME:** grammar? #### Unsafety -**FIXME:** grammar? +**FIXME:** grammar? ##### Unsafe functions -**FIXME:** grammar? +**FIXME:** grammar? ##### Unsafe blocks -**FIXME:** grammar? +**FIXME:** grammar? #### Diverging functions -**FIXME:** grammar? +**FIXME:** grammar? ### Type definitions -**FIXME:** grammar? +**FIXME:** grammar? ### Structures -**FIXME:** grammar? +**FIXME:** grammar? ### Constant items @@ -382,15 +382,15 @@ static_item : "static" ident ':' type '=' expr ';' ; #### Mutable statics -**FIXME:** grammar? +**FIXME:** grammar? ### Traits -**FIXME:** grammar? +**FIXME:** grammar? ### Implementations -**FIXME:** grammar? +**FIXME:** grammar? ### External blocks @@ -401,11 +401,11 @@ extern_block : [ foreign_fn ] * ; ## Visibility and Privacy -**FIXME:** grammar? +**FIXME:** grammar? ### Re-exporting and Visibility -**FIXME:** grammar? +**FIXME:** grammar? ## Attributes @@ -420,11 +420,11 @@ meta_seq : meta_item [ ',' meta_seq ] ? ; ## Statements -**FIXME:** grammar? +**FIXME:** grammar? ### Declaration statements -**FIXME:** grammar? +**FIXME:** grammar? A _declaration statement_ is one that introduces one or more *names* into the enclosing statement block. The declared names may denote new slots or new @@ -432,7 +432,7 @@ items. #### Item declarations -**FIXME:** grammar? +**FIXME:** grammar? An _item declaration statement_ has a syntactic form identical to an [item](#items) declaration within a module. Declaring an item — a @@ -450,35 +450,35 @@ init : [ '=' ] expr ; ### Expression statements -**FIXME:** grammar? +**FIXME:** grammar? ## Expressions -**FIXME:** grammar? +**FIXME:** grammar? #### Lvalues, rvalues and temporaries -**FIXME:** grammar? +**FIXME:** grammar? #### Moved and copied types -**FIXME:** Do we want to capture this in the grammar as different productions? +**FIXME:** Do we want to capture this in the grammar as different productions? ### Literal expressions -**FIXME:** grammar? +**FIXME:** grammar? ### Path expressions -**FIXME:** grammar? +**FIXME:** grammar? ### Tuple expressions -**FIXME:** grammar? +**FIXME:** grammar? ### Unit expressions -**FIXME:** grammar? +**FIXME:** grammar? ### Structure expressions @@ -514,7 +514,7 @@ field_expr : expr '.' ident ; ### Array expressions ```antlr -array_expr : '[' "mut" ? vec_elems? ']' ; +array_expr : '[' "mut" ? array_elems? ']' ; array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ; ``` @@ -527,7 +527,7 @@ idx_expr : expr '[' expr ']' ; ### Unary operator expressions -**FIXME:** grammar? +**FIXME:** grammar? ### Binary operator expressions @@ -537,31 +537,31 @@ binop_expr : expr binop expr ; #### Arithmetic operators -**FIXME:** grammar? +**FIXME:** grammar? #### Bitwise operators -**FIXME:** grammar? +**FIXME:** grammar? #### Lazy boolean operators -**FIXME:** grammar? +**FIXME:** grammar? #### Comparison operators -**FIXME:** grammar? +**FIXME:** grammar? #### Type cast expressions -**FIXME:** grammar? +**FIXME:** grammar? #### Assignment expressions -**FIXME:** grammar? +**FIXME:** grammar? #### Compound assignment expressions -**FIXME:** grammar? +**FIXME:** grammar? #### Operator precedence @@ -680,49 +680,49 @@ return_expr : "return" expr ? ; # Type system -**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? +**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? ## Types ### Primitive types -**FIXME:** grammar? +**FIXME:** grammar? #### Machine types -**FIXME:** grammar? +**FIXME:** grammar? #### Machine-dependent integer types -**FIXME:** grammar? +**FIXME:** grammar? ### Textual types -**FIXME:** grammar? +**FIXME:** grammar? ### Tuple types -**FIXME:** grammar? +**FIXME:** grammar? ### Array, and Slice types -**FIXME:** grammar? +**FIXME:** grammar? ### Structure types -**FIXME:** grammar? +**FIXME:** grammar? ### Enumerated types -**FIXME:** grammar? +**FIXME:** grammar? ### Pointer types -**FIXME:** grammar? +**FIXME:** grammar? ### Function types -**FIXME:** grammar? +**FIXME:** grammar? ### Closure types @@ -739,15 +739,15 @@ bound := path | lifetime ### Object types -**FIXME:** grammar? +**FIXME:** grammar? ### Type parameters -**FIXME:** grammar? +**FIXME:** grammar? ### Self types -**FIXME:** grammar? +**FIXME:** grammar? ## Type kinds @@ -755,7 +755,7 @@ bound := path | lifetime # Memory and concurrency models -**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? +**FIXME:** is this entire chapter relevant here? Or should it all have been covered by some production already? ## Memory model diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index 197559bef0..21217bf54d 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -1,4 +1,4 @@ % The (old) Rust Threads and Communication Guide This content has moved into -[the Rust Programming Language book](book/tasks.html). +[the Rust Programming Language book](book/concurrency.html). diff --git a/src/doc/index.md b/src/doc/index.md index a4f7941222..f6b0a18824 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -68,7 +68,7 @@ There are questions that are asked quite often, and so we've made FAQs for them: * [Language Design FAQ](complement-design-faq.html) * [Language FAQ](complement-lang-faq.html) * [Project FAQ](complement-project-faq.html) -* [How to submit a bug report](complement-bugreport.html) +* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports) # The standard library diff --git a/src/doc/intro.md b/src/doc/intro.md index d9bfe71e2e..b711085ddb 100644 --- a/src/doc/intro.md +++ b/src/doc/intro.md @@ -140,7 +140,7 @@ right at home if you've used tools like [Bundler](http://bundler.io/), [npm](https://www.npmjs.org/), or [pip](https://pip.pypa.io/en/latest/). There's no `Makefile`s or endless `autotools` output here. (Rust's tooling does [play nice with external libraries written in those -tools](http://crates.io/native-build.html), if you need to.) +tools](http://doc.crates.io/build-script.html), if you need to.) Enough about tools, let's talk code! @@ -389,11 +389,11 @@ safe concurrent programs. Here's an example of a concurrent Rust program: ```{rust} -use std::thread::Thread; +use std::thread; fn main() { let guards: Vec<_> = (0..10).map(|_| { - Thread::scoped(|| { + thread::scoped(|| { println!("Hello, world!"); }) }).collect(); @@ -421,44 +421,41 @@ problem. Let's see an example. This Rust code will not compile: ```{rust,ignore} -use std::thread::Thread; +use std::thread; fn main() { let mut numbers = vec![1, 2, 3]; - for i in 0..3 { - Thread::spawn(move || { - for j in 0..3 { numbers[j] += 1 } - }); - } + let guards: Vec<_> = (0..3).map(|i| { + thread::scoped(move || { + numbers[i] += 1; + println!("numbers[{}] is {}", i, numbers[i]); + }) + }).collect(); } ``` It gives us this error: ```text -6:71 error: capture of moved value: `numbers` - for j in 0..3 { numbers[j] += 1 } - ^~~~~~~ -7:50 note: `numbers` moved into closure environment here - spawn(move || { - for j in 0..3 { numbers[j] += 1 } - }); -6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing) - for j in 0..3 { numbers[j] += 1 } - ^~~~~~~~~~~~~~~ +7:25: 10:6 error: cannot move out of captured outer variable in an `FnMut` closure +7 thread::scoped(move || { +8 numbers[i] += 1; +9 println!("numbers[{}] is {}", i, numbers[i]); +10 }) +error: aborting due to previous error ``` -It mentions that "numbers moved into closure environment". Because we -declared the closure as a moving closure, and it referred to -`numbers`, the closure will try to take ownership of the vector. But -the closure itself is created in a loop, and hence we will actually -create three closures, one for every iteration of the loop. This means -that all three of those closures would try to own `numbers`, which is -impossible -- `numbers` must have just one owner. Rust detects this -and gives us the error: we claim that `numbers` has ownership, but our -code tries to make three owners. This may cause a safety problem, so -Rust disallows it. +This is a little confusing because there are two closures here: the one passed +to `map`, and the one passed to `thread::scoped`. In this case, the closure for +`thread::scoped` is attempting to reference `numbers`, a `Vec`. This +closure is a `FnOnce` closure, as that’s what `thread::scoped` takes as an +argument. `FnOnce` closures take ownership of their environment. That’s fine, +but there’s one detail: because of `map`, we’re going to make three of these +closures. And since all three try to take ownership of `numbers`, that would be +a problem. That’s what it means by ‘cannot move out of captured outer +variable’: our `thread::scoped` closure wants to take ownership, and it can’t, +because the closure for `map` won’t let it. What to do here? Rust has two types that helps us: `Arc` and `Mutex`. *Arc* stands for "atomically reference counted". In other words, an Arc will @@ -474,20 +471,20 @@ mutation doesn't cause a data race. Here's what using an Arc with a Mutex looks like: ```{rust} -use std::thread::Thread; +use std::thread; use std::sync::{Arc,Mutex}; fn main() { let numbers = Arc::new(Mutex::new(vec![1, 2, 3])); - for i in 0..3 { + let guards: Vec<_> = (0..3).map(|i| { let number = numbers.clone(); - Thread::spawn(move || { + thread::scoped(move || { let mut array = number.lock().unwrap(); array[i] += 1; println!("numbers[{}] is {}", i, array[i]); - }); - } + }) + }).collect(); } ``` @@ -516,8 +513,10 @@ numbers[1] is 3 numbers[0] is 2 ``` -Each time, we get a slightly different output, because each thread works in a -different order. You may not get the same output as this sample, even. +Each time, we can get a slightly different output because the threads are not +guaranteed to run in any set order. If you get the same order every time it is +because each of these threads are very small and complete too fast for their +indeterminate behavior to surface. The important part here is that the Rust compiler was able to use ownership to give us assurance _at compile time_ that we weren't doing something incorrect @@ -536,16 +535,16 @@ As an example, Rust's ownership system is _entirely_ at compile time. The safety check that makes this an error about moved values: ```{rust,ignore} -use std::thread::Thread; +use std::thread; fn main() { - let vec = vec![1, 2, 3]; + let numbers = vec![1, 2, 3]; - for i in 0..3 { - Thread::spawn(move || { - println!("{}", vec[i]); - }); - } + let guards: Vec<_> = (0..3).map(|i| { + thread::scoped(move || { + println!("{}", numbers[i]); + }) + }).collect(); } ``` @@ -569,7 +568,7 @@ while retaining safety. The answer is iterators: ```{rust} let vec = vec![1, 2, 3]; -for x in vec.iter() { +for x in &vec { println!("{}", x); } ``` diff --git a/src/doc/not_found.md b/src/doc/not_found.md index c746c5773d..eae2bf1925 100644 --- a/src/doc/not_found.md +++ b/src/doc/not_found.md @@ -63,4 +63,3 @@ function populate_rust_search() { populate_site_search(); populate_rust_search(); - diff --git a/src/doc/reference.md b/src/doc/reference.md index db94094704..cc90a69fd2 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -229,14 +229,14 @@ cases mentioned in [Number literals](#number-literals) below. ##### Characters and strings -| | Example | Number of `#` pairs allowed | Available characters | Escapes | Equivalent to | -|---|---------|-----------------------------|----------------------|---------|---------------| -| [Character](#character-literals) | `'H'` | `N/A` | All unicode | `\'` & [Byte escapes](#byte-escapes) & [Unicode escapes](#unicode-escapes) | `N/A` | -| [String](#string-literals) | `"hello"` | `N/A` | All unicode | `\"` & [Byte escapes](#byte-escapes) & [Unicode escapes](#unicode-escapes) | `N/A` | -| [Raw](#raw-string-literals) | `r##"hello"##` | `0...` | All unicode | `N/A` | `N/A` | -| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | `\'` & [Byte escapes](#byte-escapes) | `u8` | -| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | `\"` & [Byte escapes](#byte-escapes) | `&'static [u8]` | -| [Raw byte string](#raw-byte-string-literals) | `br##"hello"##` | `0...` | All ASCII | `N/A` | `&'static [u8]` (unsure...not stated) | +| | Example | `#` sets | Characters | Escapes | +|----------------------------------------------|-----------------|------------|-------------|---------------------| +| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | `\'` & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | +| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | `\"` & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | +| [Raw](#raw-string-literals) | `r#"hello"#` | `0...` | All Unicode | `N/A` | +| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | `\'` & [Byte](#byte-escapes) | +| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | `\"` & [Byte](#byte-escapes) | +| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | `0...` | All ASCII | `N/A` | ##### Byte escapes @@ -302,7 +302,7 @@ nonzero_dec: '1' | '2' | '3' | '4' A _character literal_ is a single Unicode character enclosed within two `U+0027` (single-quote) characters, with the exception of `U+0027` itself, -which must be _escaped_ by a preceding U+005C character (`\`). +which must be _escaped_ by a preceding `U+005C` character (`\`). ##### String literals @@ -311,6 +311,19 @@ A _string literal_ is a sequence of any Unicode characters enclosed within two which must be _escaped_ by a preceding `U+005C` character (`\`), or a _raw string literal_. +A multi-line string literal may be defined by terminating each line with a +`U+005C` character (`\`) immediately before the newline. This causes the +`U+005C` character, the newline, and all whitespace at the beginning of the +next line to be ignored. + +```rust +let a = "foobar"; +let b = "foo\ + bar"; + +assert_eq!(a,b); +``` + ##### Character escapes Some additional _escapes_ are available in either character or non-raw string @@ -515,6 +528,9 @@ This last example is different because it is not possible to use the suffix syntax with a floating point literal ending in a period. `2.f64` would attempt to call a method named `f64` on `2`. +The representation semantics of floating-point numbers are described in +["Machine Types"](#machine-types). + #### Boolean literals The two values of the boolean type are written `true` and `false`. @@ -629,18 +645,7 @@ fn bar() { A number of minor features of Rust are not central enough to have their own syntax, and yet are not implementable as functions. Instead, they are given -names, and invoked through a consistent syntax: `name!(...)`. Examples include: - -* `format!` : format data into a string -* `env!` : look up an environment variable's value at compile time -* `file!`: return the path to the file being compiled -* `stringify!` : pretty-print the Rust expression given as an argument -* `include!` : include the Rust expression in the given file -* `include_str!` : include the contents of the given file as a string -* `include_bytes!` : include the contents of the given file as a binary blob -* `error!`, `warn!`, `info!`, `debug!` : provide diagnostic information. - -All of the above extensions are expressions with values. +names, and invoked through a consistent syntax: `some_extension!(...)`. Users of `rustc` can define new syntax extensions in two ways: @@ -728,23 +733,6 @@ Rust syntax is restricted in two ways: pairs when they occur at the beginning of, or immediately after, a `$(...)*`; requiring a distinctive token in front can solve the problem. -## Syntax extensions useful for the macro author - -* `log_syntax!` : print out the arguments at compile time -* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging -* `stringify!` : turn the identifier argument into a string literal -* `concat!` : concatenates a comma-separated list of literals -* `concat_idents!` : create a new identifier by concatenating the arguments - -The following attributes are used for quasiquoting in procedural macros: - -* `quote_expr!` -* `quote_item!` -* `quote_pat!` -* `quote_stmt!` -* `quote_tokens!` -* `quote_ty!` - # Crates and source files Rust is a *compiled* language. Its semantics obey a *phase distinction* @@ -785,8 +773,7 @@ may optionally begin with any number of `attributes` that apply to the containing module. Attributes on the anonymous crate module define important metadata that influences the behavior of the compiler. -```{.rust} -# #![allow(unused_attribute)] +```no_run // Crate name #![crate_name = "projx"] @@ -950,7 +937,7 @@ extern crate pcre; extern crate std; // equivalent to: extern crate std as std; -extern crate "std" as ruststd; // linking to 'std' under another name +extern crate std as ruststd; // linking to 'std' under another name ``` ##### Use declarations @@ -989,7 +976,7 @@ Use declarations support a number of convenient shortcuts: An example of `use` declarations: ``` -use std::iter::range_step; +# #![feature(core)] use std::option::Option::{Some, None}; use std::collections::hash_map::{self, HashMap}; @@ -997,9 +984,6 @@ fn foo(_: T){} fn bar(map1: HashMap, map2: hash_map::HashMap){} fn main() { - // Equivalent to 'std::iter::range_step(0, 10, 2);' - range_step(0, 10, 2); - // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), // std::option::Option::None]);' foo(vec![Some(1.0f64), None]); @@ -1049,6 +1033,7 @@ declarations. An example of what will and will not work for `use` items: ``` +# #![feature(core)] # #![allow(unused_imports)] use foo::core::iter; // good: foo is at the root of the crate use foo::baz::foobaz; // good: foo is at the root of the crate @@ -1199,12 +1184,15 @@ the guarantee that these issues are never caused by safe code. * Data races * Dereferencing a null/dangling raw pointer -* Mutating an immutable value/reference without `UnsafeCell` * Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values) (uninitialized) memory * Breaking the [pointer aliasing rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules) with raw pointers (a subset of the rules used by C) +* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T` + contains an `UnsafeCell`. Unsafe code must not violate these aliasing + guarantees. +* Mutating an immutable value/reference without `UnsafeCell` * Invoking undefined behavior via compiler intrinsics: * Indexing outside of the bounds of an object with `std::ptr::offset` (`offset` intrinsic), with @@ -1221,6 +1209,8 @@ the guarantee that these issues are never caused by safe code. code. Rust's failure system is not compatible with exception handling in other languages. Unwinding must be caught and handled at FFI boundaries. +[noalias]: http://llvm.org/docs/LangRef.html#noalias + ##### Behaviour not considered unsafe This is a list of behaviour not considered *unsafe* in Rust terms, but that may @@ -1233,7 +1223,7 @@ be undesired. * Sending signals * Accessing/modifying the file system * Unsigned integer overflow (well-defined as wrapping) -* Signed integer overflow (well-defined as two's complement representation +* Signed integer overflow (well-defined as two’s complement representation wrapping) #### Diverging functions @@ -1489,22 +1479,6 @@ statics: Constants should in general be preferred over statics, unless large amounts of data are being stored, or single-address and mutability properties are required. -``` -use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - -// Note that ATOMIC_USIZE_INIT is a *const*, but it may be used to initialize a -// static. This static can be modified, so it is not placed in read-only memory. -static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; - -// This table is a candidate to be placed in read-only memory. -static TABLE: &'static [usize] = &[1, 2, 3, /* ... */]; - -for slot in TABLE.iter() { - println!("{}", slot); -} -COUNTER.fetch_add(1, Ordering::SeqCst); -``` - #### Mutable statics If a static item is declared with the `mut` keyword, then it is allowed to @@ -1674,7 +1648,7 @@ specific type. Implementations are defined with the keyword `impl`. ``` -# #[derive(Copy)] +# #[derive(Copy, Clone)] # struct Point {x: f64, y: f64}; # type Surface = i32; # struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; @@ -1687,6 +1661,10 @@ struct Circle { impl Copy for Circle {} +impl Clone for Circle { + fn clone(&self) -> Circle { *self } +} + impl Shape for Circle { fn draw(&self, s: Surface) { do_draw_circle(s, *self); } fn bounding_box(&self) -> BoundingBox { @@ -1750,6 +1728,7 @@ functions, with the exception that they may not have a body and are instead terminated by a semicolon. ``` +# #![feature(libc)] extern crate libc; use libc::{c_char, FILE}; @@ -1930,16 +1909,18 @@ module through the rules above. It essentially allows public access into the re-exported item. For example, this program is valid: ``` -pub use self::implementation as api; +pub use self::implementation::api; mod implementation { - pub fn f() {} + pub mod api { + pub fn f() {} + } } # fn main() {} ``` -This means that any external crate referencing `implementation::f` would +This means that any external crate referencing `implementation::api::f` would receive a privacy violation, while the path `api::f` would be allowed. When re-exporting a private item, it can be thought of as allowing the "privacy @@ -1949,7 +1930,7 @@ the namespace hierarchy as it normally would. ## Attributes ```{.ebnf .gram} -attribute : "#!" ? '[' meta_item ']' ; +attribute : '#' '!' ? '[' meta_item ']' ; meta_item : ident [ '=' literal | '(' meta_seq ')' ] ? ; meta_seq : meta_item [ ',' meta_seq ] ? ; @@ -2035,7 +2016,7 @@ type int8_t = i8; item](#language-items) for more details. - `test` - indicates that this function is a test function, to only be compiled in case of `--test`. -- `should_fail` - indicates that this test function should panic, inverting the success condition. +- `should_panic` - indicates that this test function should panic, inverting the success condition. - `cold` - The function is unlikely to be executed, so optimize it (and calls to it) differently. @@ -2162,7 +2143,7 @@ fn needs_foo_or_bar() { // This function is only included when compiling for a unixish OS with a 32-bit // architecture -#[cfg(all(unix, target_word_size = "32"))] +#[cfg(all(unix, target_pointer_width = "32"))] fn on_32bit_unix() { // ... } @@ -2188,11 +2169,11 @@ The following configurations must be defined by the implementation: `"unix"` or `"windows"`. The value of this configuration option is defined as a configuration itself, like `unix` or `windows`. * `target_os = "..."`. Operating system of the target, examples include - `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"` or - `"openbsd"`. -* `target_word_size = "..."`. Target word size in bits. This is set to `"32"` - for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit - pointers. + `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`, + `"bitrig"` or `"openbsd"`. +* `target_pointer_width = "..."`. Target pointer width in bits. This is set + to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for + 64-bit pointers. * `unix`. See `target_family`. * `windows`. See `target_family`. @@ -2341,18 +2322,6 @@ impl PartialEq for Foo { } ``` -Supported traits for `derive` are: - -* Comparison traits: `PartialEq`, `Eq`, `PartialOrd`, `Ord`. -* Serialization: `Encodable`, `Decodable`. These require `serialize`. -* `Clone`, to create `T` from `&T` via a copy. -* `Default`, to create an empty instance of a data type. -* `FromPrimitive`, to create an instance from a numeric primitive. -* `Hash`, to iterate over the bytes in a data type. -* `Rand`, to create a random instance of a data type. -* `Debug`, to format a value using the `{:?}` formatter. -* `Copy`, for "Plain Old Data" types which can be copied by simply moving bits. - ### Compiler Features Certain aspects of Rust may be implemented in the compiler, but they're not @@ -2373,9 +2342,13 @@ considered off, and using the features will result in a compiler error. The currently implemented features of the reference compiler are: -* `advanced_slice_patterns` - see the [match expressions](#match-expressions) +* `advanced_slice_patterns` - See the [match expressions](#match-expressions) section for discussion; the exact semantics of - slice patterns are subject to change. + slice patterns are subject to change, so some types + are still unstable. + +* `slice_patterns` - OK, actually, slice patterns are just scary and + completely unstable. * `asm` - The `asm!` macro provides a means for inline assembly. This is often useful, but the exact syntax for this feature along with its @@ -2398,12 +2371,13 @@ The currently implemented features of the reference compiler are: so that new attributes can be added in a bacwards compatible manner (RFC 572). +* `custom_derive` - Allows the use of `#[derive(Foo,Bar)]` as sugar for + `#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax + extensions. + * `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics are inherently unstable and no promise about them is made. -* `int_uint` - Allows the use of the `int` and `uint` types, which are deprecated. - Use `isize` and `usize` instead. - * `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`, lang items are inherently unstable and no promise about them is made. @@ -2472,6 +2446,12 @@ The currently implemented features of the reference compiler are: * `staged_api` - Allows usage of stability markers and `#![staged_api]` in a crate +* `static_assert` - The `#[static_assert]` functionality is experimental and + unstable. The attribute can be attached to a `static` of + type `bool` and the compiler will error if the `bool` is + `false` at compile time. This version of this functionality + is unintuitive and suboptimal. + * `start` - Allows use of the `#[start]` attribute, which changes the entry point into a Rust program. This capabiilty, especially the signature for the annotated function, is subject to change. @@ -2518,6 +2498,14 @@ The currently implemented features of the reference compiler are: types, e.g. as the return type of a public function. This capability may be removed in the future. +* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the + `#[allow_internal_unstable]` attribute, designed + to allow `std` macros to call + `#[unstable]`/feature-gated functionality + internally without imposing on callers + (i.e. making them behave like function calls in + terms of encapsulation). + If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about #[feature] directives which enabled the new feature (because the directive is no longer necessary). However, if a @@ -2706,7 +2694,7 @@ The following are examples of structure expressions: ``` # struct Point { x: f64, y: f64 } # struct TuplePoint(f64, f64); -# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: uint } } +# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } # struct Cookie; fn some_fn(t: T) {} Point {x: 10.0, y: 20.0}; TuplePoint(10.0, 20.0); @@ -2798,7 +2786,7 @@ automatically dereferenced to make the field access possible. ### Array expressions ```{.ebnf .gram} -array_expr : '[' "mut" ? vec_elems? ']' ; +array_expr : '[' "mut" ? array_elems? ']' ; array_elems : [expr [',' expr]*] | [expr ';' expr] ; ``` @@ -2908,10 +2896,10 @@ meaning of the operators on standard types is given here. : Exclusive or. Calls the `bitxor` method of the `std::ops::BitXor` trait. * `<<` - : Logical left shift. + : Left shift. Calls the `shl` method of the `std::ops::Shl` trait. * `>>` - : Logical right shift. + : Right shift. Calls the `shr` method of the `std::ops::Shr` trait. #### Lazy boolean operators @@ -2958,10 +2946,6 @@ A type cast expression is denoted with the binary operator `as`. Executing an `as` expression casts the value on the left-hand side to the type on the right-hand side. -A numeric value can be cast to any numeric type. A raw pointer value can be -cast to or from any integral type or raw pointer type. Any other cast is -unsupported and will fail to compile. - An example of an `as` expression: ``` @@ -3111,7 +3095,7 @@ ten_times(|j| println!("hello, {}", j)); ### While loops ```{.ebnf .gram} -while_expr : "while" no_struct_literal_expr '{' block '}' ; +while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ; ``` A `while` loop begins by evaluating the boolean loop conditional expression. @@ -3176,7 +3160,7 @@ A `continue` expression is only permitted in the body of a loop. ### For expressions ```{.ebnf .gram} -for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ; +for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ; ``` A `for` expression is a syntactic construct for looping over elements provided @@ -3280,7 +3264,7 @@ array, like `[.., 42, ..]`. If preceded by a variable name, it will bind the corresponding slice to the variable. Example: ``` -# #![feature(advanced_slice_patterns)] +# #![feature(advanced_slice_patterns, slice_patterns)] fn is_symmetric(list: &[u32]) -> bool { match list { [] | [_] => true, @@ -3353,7 +3337,7 @@ subpattern`. For example: #![feature(box_patterns)] #![feature(box_syntax)] -enum List { Nil, Cons(uint, Box) } +enum List { Nil, Cons(u32, Box) } fn is_sorted(list: &List) -> bool { match *list { @@ -3554,7 +3538,8 @@ Tuple types and values are denoted by listing the types or values of their elements, respectively, in a parenthesized, comma-separated list. Because tuple elements don't have a name, they can only be accessed by -pattern-matching. +pattern-matching or by using `N` directly as a field to access the +`N`th element. An example of a tuple type and its use: @@ -3563,6 +3548,7 @@ type Pair<'a> = (i32, &'a str); let p: Pair<'static> = (10, "hello"); let (a, b) = p; assert!(b != "world"); +assert!(p.0 == 10); ``` ### Array, and Slice types @@ -3740,9 +3726,9 @@ An example of creating and calling a closure: ```rust let captured_var = 10; -let closure_no_args = |&:| println!("captured_var={}", captured_var); +let closure_no_args = || println!("captured_var={}", captured_var); -let closure_args = |&: arg: i32| -> i32 { +let closure_args = |arg: i32| -> i32 { println!("captured_var={}, arg={}", captured_var, arg); arg // Note lack of semicolon after 'arg' }; @@ -3835,75 +3821,27 @@ impl Printable for String { `self` refers to the value of type `String` that is the receiver for a call to the method `make_string`. -## Type kinds - -Types in Rust are categorized into kinds, based on various properties of the -components of the type. The kinds are: - -* `Send` - : Types of this kind can be safely sent between threads. - This kind includes scalars, boxes, procs, and - structural types containing only other owned types. - All `Send` types are `'static`. -* `Copy` - : Types of this kind consist of "Plain Old Data" - which can be copied by simply moving bits. - All values of this kind can be implicitly copied. - This kind includes scalars and immutable references, - as well as structural types containing other `Copy` types. -* `'static` - : Types of this kind do not contain any references (except for - references with the `static` lifetime, which are allowed). - This can be a useful guarantee for code - that breaks borrowing assumptions - using [`unsafe` operations](#unsafe-functions). -* `Drop` - : This is not strictly a kind, - but its presence interacts with kinds: - the `Drop` trait provides a single method `drop` - that takes no parameters, - and is run when values of the type are dropped. - Such a method is called a "destructor", - and are always executed in "top-down" order: - a value is completely destroyed - before any of the values it owns run their destructors. - Only `Send` types can implement `Drop`. - -* _Default_ - : Types with destructors, closure environments, - and various other _non-first-class_ types, - are not copyable at all. - Such types can usually only be accessed through pointers, - or in some cases, moved between mutable locations. - -Kinds can be supplied as _bounds_ on type parameters, like traits, in which -case the parameter is constrained to types satisfying that kind. - -By default, type parameters do not carry any assumed kind-bounds at all. When -instantiating a type parameter, the kind bounds on the parameter are checked to -be the same or narrower than the kind of the type that it is instantiated with. - -Sending operations are not part of the Rust language, but are implemented in -the library. Generic functions that send values bound the kind of these values -to sendable. - -# Memory and concurrency models - -Rust has a memory model centered around concurrently-executing _threads_. Thus -its memory model and its concurrency model are best discussed simultaneously, -as parts of each only make sense when considered from the perspective of the -other. - -When reading about the memory model, keep in mind that it is partitioned in -order to support threads; and when reading about threads, keep in mind that their -isolation and communication mechanisms are only possible due to the ownership -and lifetime semantics of the memory model. - -## Memory model - -A Rust program's memory consists of a static set of *items*, a set of -[threads](#threads) each with its own *stack*, and a *heap*. Immutable portions of -the heap may be shared between threads, mutable portions may not. +# The `Copy` trait + +Rust has a special trait, `Copy`, which when implemented changes the semantics +of a value. Values whose type implements `Copy` are copied rather than moved +upon assignment. + +# The `Sized` trait + +`Sized` is a special trait which indicates that the size of this type is known +at compile-time. + +# The `Drop` trait + +The `Drop` trait provides a destructor, to be run whenever a value of this type +is to be destroyed. + +# Memory model + +A Rust program's memory consists of a static set of *items* and a *heap*. +Immutable portions of the heap may be shared between threads, mutable portions +may not. Allocations in the stack consist of *slots*, and allocations in the heap consist of *boxes*. @@ -3914,10 +3852,6 @@ The _items_ of a program are those functions, modules and types that have their value calculated at compile-time and stored uniquely in the memory image of the rust process. Items are neither dynamically allocated nor freed. -A thread's _stack_ consists of activation frames automatically allocated on entry -to each function as the thread executes. A stack allocation is reclaimed when -control leaves the frame containing it. - The _heap_ is a general term that describes boxes. The lifetime of an allocation in the heap depends on the lifetime of the box values pointing to it. Since box values may themselves be passed in and out of frames, or stored @@ -3925,25 +3859,11 @@ in the heap, heap allocations may outlive the frame they are allocated within. ### Memory ownership -A thread owns all memory it can *safely* reach through local variables, as well -as boxes and references. - -When a thread sends a value that has the `Send` trait to another thread, it loses -ownership of the value sent and can no longer refer to it. This is statically -guaranteed by the combined use of "move semantics", and the compiler-checked -_meaning_ of the `Send` trait: it is only instantiated for (transitively) -sendable kinds of data constructor and pointers, never including references. - When a stack frame is exited, its local allocations are all released, and its references to boxes are dropped. -When a thread finishes, its stack is necessarily empty and it therefore has no -references to any boxes; the remainder of its heap is immediately freed. - ### Memory slots -A thread's stack contains slots. - A _slot_ is a component of a stack frame, either a function parameter, a [temporary](#lvalues,-rvalues-and-temporaries), or a local variable. @@ -3973,86 +3893,6 @@ state. Subsequent statements within a function may or may not initialize the local variables. Local variables can be used only after they have been initialized; this is enforced by the compiler. -### Boxes - -A _box_ is a reference to a heap allocation holding another value, which is -constructed by the prefix operator `box`. When the standard library is in use, -the type of a box is `std::owned::Box`. - -An example of a box type and value: - -``` -let x: Box = Box::new(10); -``` - -Box values exist in 1:1 correspondence with their heap allocation, copying a -box value makes a shallow copy of the pointer. Rust will consider a shallow -copy of a box to move ownership of the value. After a value has been moved, -the source location cannot be used unless it is reinitialized. - -``` -let x: Box = Box::new(10); -let y = x; -// attempting to use `x` will result in an error here -``` - -## Threads - -Rust's primary concurrency mechanism is called a **thread**. - -### Communication between threads - -Rust threads are isolated and generally unable to interfere with one another's -memory directly, except through [`unsafe` code](#unsafe-functions). All -contact between threads is mediated by safe forms of ownership transfer, and data -races on memory are prohibited by the type system. - -When you wish to send data between threads, the values are restricted to the -[`Send` type-kind](#type-kinds). Restricting communication interfaces to this -kind ensures that no references move between threads. Thus access to an entire -data structure can be mediated through its owning "root" value; no further -locking or copying is required to avoid data races within the substructure of -such a value. - -### Thread - -The _lifecycle_ of a threads consists of a finite set of states and events that -cause transitions between the states. The lifecycle states of a thread are: - -* running -* blocked -* panicked -* dead - -A thread begins its lifecycle — once it has been spawned — in the -*running* state. In this state it executes the statements of its entry -function, and any functions called by the entry function. - -A thread may transition from the *running* state to the *blocked* state any time -it makes a blocking communication call. When the call can be completed — -when a message arrives at a sender, or a buffer opens to receive a message -— then the blocked thread will unblock and transition back to *running*. - -A thread may transition to the *panicked* state at any time, due being killed by -some external event or internally, from the evaluation of a `panic!()` macro. -Once *panicking*, a thread unwinds its stack and transitions to the *dead* state. -Unwinding the stack of a thread is done by the thread itself, on its own control -stack. If a value with a destructor is freed during unwinding, the code for the -destructor is run, also on the thread's control stack. Running the destructor -code causes a temporary transition to a *running* state, and allows the -destructor code to cause any subsequent state transitions. The original thread -of unwinding and panicking thereby may suspend temporarily, and may involve -(recursive) unwinding of the stack of a failed destructor. Nonetheless, the -outermost unwinding activity will continue until the stack is unwound and the -thread transitions to the *dead* state. There is no way to "recover" from thread -panics. Once a thread has temporarily suspended its unwinding in the *panicking* -state, a panic occurring from within this destructor results in *hard* panic. -A hard panic currently results in the process aborting. - -A thread in the *dead* state cannot transition to other states; it exists only to -have its termination status inspected by other threads, and/or to await -reclamation when the last reference to it drops. - # Runtime services, linkage and debugging The Rust _runtime_ is a relatively compact collection of Rust code that diff --git a/src/doc/rust.css b/src/doc/rust.css index c2a25cd7a5..cd15828318 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -56,6 +56,7 @@ /* General structure */ body { + background-color: white; margin: 0 auto; padding: 0 15px; font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif; diff --git a/src/doc/style/errors/ergonomics.md b/src/doc/style/errors/ergonomics.md index 33f1e82b18..d2fcf27e93 100644 --- a/src/doc/style/errors/ergonomics.md +++ b/src/doc/style/errors/ergonomics.md @@ -22,9 +22,9 @@ fn write_info(info: &Info) -> Result<(), IoError> { let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write); // Early return on error - try!(file.write_line(format!("name: {}", info.name).as_slice())); - try!(file.write_line(format!("age: {}", info.age).as_slice())); - try!(file.write_line(format!("rating: {}", info.rating).as_slice())); + try!(file.write_line(&format!("name: {}", info.name))); + try!(file.write_line(&format!("age: {}", info.age))); + try!(file.write_line(&format!("rating: {}", info.rating))); return Ok(()); } ``` @@ -44,15 +44,15 @@ fn write_info(info: &Info) -> Result<(), IoError> { let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write); // Early return on error - match file.write_line(format!("name: {}", info.name).as_slice()) { + match file.write_line(&format!("name: {}", info.name)) { Ok(_) => (), Err(e) => return Err(e) } - match file.write_line(format!("age: {}", info.age).as_slice()) { + match file.write_line(&format!("age: {}", info.age)) { Ok(_) => (), Err(e) => return Err(e) } - return file.write_line(format!("rating: {}", info.rating).as_slice()); + return file.write_line(&format!("rating: {}", info.rating)); } ``` diff --git a/src/doc/trpl/README.md b/src/doc/trpl/README.md index eb9e2b24ac..4a866d6224 100644 --- a/src/doc/trpl/README.md +++ b/src/doc/trpl/README.md @@ -11,8 +11,7 @@ navigate through the menu on the left.

Basics

This section is a linear introduction to the basic syntax and semantics of -Rust. It has individual sections on each part of Rust's syntax, and culminates -in a small project: a guessing game. +Rust. It has individual sections on each part of Rust's syntax. After reading "Basics," you will have a good foundation to learn more about Rust, and can write very simple programs. @@ -29,7 +28,12 @@ and will be able to understand most Rust code and write more complex programs. In a similar fashion to "Intermediate," this section is full of individual, deep-dive chapters, which stand alone and can be read in any order. These -chapters focus on the most complex features, as well as some things that -are only available in upcoming versions of Rust. +chapters focus on the most complex features, -After reading "Advanced," you'll be a Rust expert! +

Unstable

+ +In a similar fashion to "Intermediate," this section is full of individual, +deep-dive chapters, which stand alone and can be read in any order. + +This chapter contains things that are only available on the nightly channel of +Rust. diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index d57aff7f4f..11e62aff42 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -1,6 +1,6 @@ # Summary -* [I: The Basics](basic.md) +* [The Basics](basic.md) * [Installing Rust](installing-rust.md) * [Hello, world!](hello-world.md) * [Hello, Cargo!](hello-cargo.md) @@ -13,16 +13,15 @@ * [Looping](looping.md) * [Strings](strings.md) * [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md) - * [Standard Input](standard-input.md) - * [Guessing Game](guessing-game.md) -* [II: Intermediate Rust](intermediate.md) - * [More Strings](more-strings.md) +* [Intermediate Rust](intermediate.md) * [Crates and Modules](crates-and-modules.md) * [Testing](testing.md) * [Pointers](pointers.md) * [Ownership](ownership.md) + * [More Strings](more-strings.md) * [Patterns](patterns.md) * [Method Syntax](method-syntax.md) + * [Associated Types](associated-types.md) * [Closures](closures.md) * [Iterators](iterators.md) * [Generics](generics.md) @@ -32,10 +31,18 @@ * [Concurrency](concurrency.md) * [Error Handling](error-handling.md) * [Documentation](documentation.md) -* [III: Advanced Topics](advanced.md) +* [Advanced Topics](advanced.md) * [FFI](ffi.md) * [Unsafe Code](unsafe.md) * [Advanced Macros](advanced-macros.md) +* [Unstable Rust](unstable.md) * [Compiler Plugins](plugins.md) + * [Inline Assembly](inline-assembly.md) + * [No stdlib](no-stdlib.md) + * [Intrinsics](intrinsics.md) + * [Lang items](lang-items.md) + * [Link args](link-args.md) + * [Benchmark Tests](benchmark-tests.md) + * [Box Syntax and Patterns](box-syntax-and-patterns.md) * [Conclusion](conclusion.md) * [Glossary](glossary.md) diff --git a/src/doc/trpl/advanced-macros.md b/src/doc/trpl/advanced-macros.md index aff365051a..fef458caaa 100644 --- a/src/doc/trpl/advanced-macros.md +++ b/src/doc/trpl/advanced-macros.md @@ -6,9 +6,11 @@ off. # Syntactic requirements Even when Rust code contains un-expanded macros, it can be parsed as a full -syntax tree. This property can be very useful for editors and other tools that -process code. It also has a few consequences for the design of Rust's macro -system. +[syntax tree][ast]. This property can be very useful for editors and other +tools that process code. It also has a few consequences for the design of +Rust's macro system. + +[ast]: glossary.html#abstract-syntax-tree One consequence is that Rust must determine, when it parses a macro invocation, whether the macro stands in for @@ -192,19 +194,49 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may only appear at the root of your crate, not inside `mod`. This ensures that `$crate` is a single identifier. -# A final note +# The deep end + +The introductory chapter mentioned recursive macros, but it did not give the +full story. Recursive macros are useful for another reason: Each recursive +invocation gives you another opportunity to pattern-match the macro's +arguments. + +As an extreme example, it is possible, though hardly advisable, to implement +the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton +within Rust's macro system. + +```rust +macro_rules! bct { + // cmd 0: d ... => ... + (0, $($ps:tt),* ; $_d:tt) + => (bct!($($ps),*, 0 ; )); + (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*) + => (bct!($($ps),*, 0 ; $($ds),*)); + + // cmd 1p: 1 ... => 1 ... p + (1, $p:tt, $($ps:tt),* ; 1) + => (bct!($($ps),*, 1, $p ; 1, $p)); + (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*) + => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p)); + + // cmd 1p: 0 ... => 0 ... + (1, $p:tt, $($ps:tt),* ; $($ds:tt),*) + => (bct!($($ps),*, 1, $p ; $($ds),*)); + + // halt on empty data string + ( $($ps:tt),* ; ) + => (()); +} +``` + +Exercise: use macros to reduce duplication in the above definition of the +`bct!` macro. -Macros, as currently implemented, are not for the faint of heart. Even -ordinary syntax errors can be more difficult to debug when they occur inside a -macro, and errors caused by parse problems in generated code can be very -tricky. Invoking the `log_syntax!` macro can help elucidate intermediate -states, invoking `trace_macros!(true)` will automatically print those -intermediate states out, and passing the flag `--pretty expanded` as a -command-line argument to the compiler will show the result of expansion. +# Procedural macros If Rust's macro system can't do what you need, you may want to write a [compiler plugin](plugins.html) instead. Compared to `macro_rules!` macros, this is significantly more work, the interfaces are much less stable, -and the warnings about debugging apply ten-fold. In exchange you get the +and bugs can be much harder to track down. In exchange you get the flexibility of running arbitrary Rust code within the compiler. Syntax extension plugins are sometimes called *procedural macros* for this reason. diff --git a/src/doc/trpl/arrays-vectors-and-slices.md b/src/doc/trpl/arrays-vectors-and-slices.md index d4e2ad5cd5..2916dca2c0 100644 --- a/src/doc/trpl/arrays-vectors-and-slices.md +++ b/src/doc/trpl/arrays-vectors-and-slices.md @@ -49,7 +49,7 @@ languages. A *vector* is a dynamic or "growable" array, implemented as the standard library type [`Vec`](../std/vec/) (we'll talk about what the `` means -later). Vectors always allocate their data on the heap. Vectors are to slices +later). Vectors always allocate their data on the heap. Vectors are to slices what `String` is to `&str`. You can create them with the `vec!` macro: ```{rust} @@ -60,6 +60,12 @@ let v = vec![1, 2, 3]; // v: Vec brackets `[]` with `vec!`. Rust allows you to use either in either situation, this is just convention.) +There's an alternate form of `vec!` for repeating an initial value: + +``` +let v = vec![0; 10]; // ten zeroes +``` + You can get the length of, iterate over, and subscript vectors just like arrays. In addition, (mutable) vectors can grow automatically: @@ -93,7 +99,4 @@ You can also take a slice of a vector, `String`, or `&str`, because they are backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover generics. -We have now learned all of the most basic Rust concepts. We're ready to start -building ourselves a guessing game, we just need to know one last thing: how to -get input from the keyboard. You can't have a guessing game without the ability -to guess! +We have now learned all of the most basic Rust concepts. diff --git a/src/doc/trpl/associated-types.md b/src/doc/trpl/associated-types.md new file mode 100644 index 0000000000..7161cd33f8 --- /dev/null +++ b/src/doc/trpl/associated-types.md @@ -0,0 +1,202 @@ +% Associated Types + +Associated types are a powerful part of Rust's type system. They're related to +the idea of a 'type family', in other words, grouping multiple types together. That +description is a bit abstract, so let's dive right into an example. If you want +to write a `Graph` trait, you have two types to be generic over: the node type +and the edge type. So you might write a trait, `Graph`, that looks like +this: + +```rust +trait Graph { + fn has_edge(&self, &N, &N) -> bool; + fn edges(&self, &N) -> Vec; + // etc +} +``` + +While this sort of works, it ends up being awkward. For example, any function +that wants to take a `Graph` as a parameter now _also_ needs to be generic over +the `N`ode and `E`dge types too: + +```rust,ignore +fn distance>(graph: &G, start: &N, end: &N) -> u32 { ... } +``` + +Our distance calculation works regardless of our `Edge` type, so the `E` stuff in +this signature is just a distraction. + +What we really want to say is that a certain `E`dge and `N`ode type come together +to form each kind of `Graph`. We can do that with associated types: + +```rust +trait Graph { + type N; + type E; + + fn has_edge(&self, &Self::N, &Self::N) -> bool; + fn edges(&self, &Self::N) -> Vec; + // etc +} +``` + +Now, our clients can be abstract over a given `Graph`: + +```rust,ignore +fn distance(graph: &G, start: &G::N, end: &G::N) -> uint { ... } +``` + +No need to deal with the `E`dge type here! + +Let's go over all this in more detail. + +## Defining associated types + +Let's build that `Graph` trait. Here's the definition: + +```rust +trait Graph { + type N; + type E; + + fn has_edge(&self, &Self::N, &Self::N) -> bool; + fn edges(&self, &Self::N) -> Vec; +} +``` + +Simple enough. Associated types use the `type` keyword, and go inside the body +of the trait, with the functions. + +These `type` declarations can have all the same thing as functions do. For example, +if we wanted our `N` type to implement `Display`, so we can print the nodes out, +we could do this: + +```rust +use std::fmt; + +trait Graph { + type N: fmt::Display; + type E; + + fn has_edge(&self, &Self::N, &Self::N) -> bool; + fn edges(&self, &Self::N) -> Vec; +} +``` + +## Implementing associated types + +Just like any trait, traits that use associated types use the `impl` keyword to +provide implementations. Here's a simple implementation of Graph: + +```rust +# trait Graph { +# type N; +# type E; +# fn has_edge(&self, &Self::N, &Self::N) -> bool; +# fn edges(&self, &Self::N) -> Vec; +# } +struct Node; + +struct Edge; + +struct MyGraph; + +impl Graph for MyGraph { + type N = Node; + type E = Edge; + + fn has_edge(&self, n1: &Node, n2: &Node) -> bool { + true + } + + fn edges(&self, n: &Node) -> Vec { + Vec::new() + } +} +``` + +This silly implementation always returns `true` and an empty `Vec`, but it +gives you an idea of how to implement this kind of thing. We first need three +`struct`s, one for the graph, one for the node, and one for the edge. If it made +more sense to use a different type, that would work as well, we're just going to +use `struct`s for all three here. + +Next is the `impl` line, which is just like implementing any other trait. + +From here, we use `=` to define our associated types. The name the trait uses +goes on the left of the `=`, and the concrete type we're `impl`ementing this +for goes on the right. Finally, we use the concrete types in our function +declarations. + +## Trait objects with associated types + +There’s one more bit of syntax we should talk about: trait objects. If you +try to create a trait object from an associated type, like this: + +```rust,ignore +# trait Graph { +# type N; +# type E; +# fn has_edge(&self, &Self::N, &Self::N) -> bool; +# fn edges(&self, &Self::N) -> Vec; +# } +# struct Node; +# struct Edge; +# struct MyGraph; +# impl Graph for MyGraph { +# type N = Node; +# type E = Edge; +# fn has_edge(&self, n1: &Node, n2: &Node) -> bool { +# true +# } +# fn edges(&self, n: &Node) -> Vec { +# Vec::new() +# } +# } +let graph = MyGraph; +let obj = Box::new(graph) as Box; +``` + +You’ll get two errors: + +```text +error: the value of the associated type `E` (from the trait `main::Graph`) must +be specified [E0191] +let obj = Box::new(graph) as Box; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +24:44 error: the value of the associated type `N` (from the trait +`main::Graph`) must be specified [E0191] +let obj = Box::new(graph) as Box; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` + +We can’t create a trait object like this, because we don’t know the associated +types. Instead, we can write this: + +```rust +# trait Graph { +# type N; +# type E; +# fn has_edge(&self, &Self::N, &Self::N) -> bool; +# fn edges(&self, &Self::N) -> Vec; +# } +# struct Node; +# struct Edge; +# struct MyGraph; +# impl Graph for MyGraph { +# type N = Node; +# type E = Edge; +# fn has_edge(&self, n1: &Node, n2: &Node) -> bool { +# true +# } +# fn edges(&self, n: &Node) -> Vec { +# Vec::new() +# } +# } +let graph = MyGraph; +let obj = Box::new(graph) as Box>; +``` + +The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N` +type parameter. Same with `E=Edge`. If we didn’t proide this constraint, we +couldn’t be sure which `impl` to match this trait object to. diff --git a/src/doc/trpl/basic.md b/src/doc/trpl/basic.md index 087121d0e7..c267830e6e 100644 --- a/src/doc/trpl/basic.md +++ b/src/doc/trpl/basic.md @@ -1,8 +1,7 @@ % Basics This section is a linear introduction to the basic syntax and semantics of -Rust. It has individual sections on each part of Rust's syntax, and cumulates -in a small project: a guessing game. +Rust. It has individual sections on each part of Rust's syntax. After reading "Basics," you will have a good foundation to learn more about Rust, and can write very simple programs. diff --git a/src/doc/trpl/benchmark-tests.md b/src/doc/trpl/benchmark-tests.md new file mode 100644 index 0000000000..8879653759 --- /dev/null +++ b/src/doc/trpl/benchmark-tests.md @@ -0,0 +1,152 @@ +% Benchmark tests + +Rust supports benchmark tests, which can test the performance of your +code. Let's make our `src/lib.rs` look like this (comments elided): + +```{rust,ignore} +#![feature(test)] + +extern crate test; + +pub fn add_two(a: i32) -> i32 { + a + 2 +} + +#[cfg(test)] +mod tests { + use super::*; + use test::Bencher; + + #[test] + fn it_works() { + assert_eq!(4, add_two(2)); + } + + #[bench] + fn bench_add_two(b: &mut Bencher) { + b.iter(|| add_two(2)); + } +} +``` + +Note the `test` feature gate, which enables this unstable feature. + +We've imported the `test` crate, which contains our benchmarking support. +We have a new function as well, with the `bench` attribute. Unlike regular +tests, which take no arguments, benchmark tests take a `&mut Bencher`. This +`Bencher` provides an `iter` method, which takes a closure. This closure +contains the code we'd like to benchmark. + +We can run benchmark tests with `cargo bench`: + +```bash +$ cargo bench + Compiling adder v0.0.1 (file:///home/steve/tmp/adder) + Running target/release/adder-91b3e234d4ed382a + +running 2 tests +test tests::it_works ... ignored +test tests::bench_add_two ... bench: 1 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured +``` + +Our non-benchmark test was ignored. You may have noticed that `cargo bench` +takes a bit longer than `cargo test`. This is because Rust runs our benchmark +a number of times, and then takes the average. Because we're doing so little +work in this example, we have a `1 ns/iter (+/- 0)`, but this would show +the variance if there was one. + +Advice on writing benchmarks: + + +* Move setup code outside the `iter` loop; only put the part you want to measure inside +* Make the code do "the same thing" on each iteration; do not accumulate or change state +* Make the outer function idempotent too; the benchmark runner is likely to run + it many times +* Make the inner `iter` loop short and fast so benchmark runs are fast and the + calibrator can adjust the run-length at fine resolution +* 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 +compiler might recognize that some calculation has no external effects and +remove it entirely. + +```{rust,ignore} +#![feature(test)] + +extern crate test; +use test::Bencher; + +#[bench] +fn bench_xor_1000_ints(b: &mut Bencher) { + b.iter(|| { + (0..1000).fold(0, |old, new| old ^ new); + }); +} +``` + +gives the following results + +```text +running 1 test +test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured +``` + +The benchmarking runner offers two ways to avoid this. Either, the closure that +the `iter` method receives can return an arbitrary value which forces the +optimizer to consider the result used and ensures it cannot remove the +computation entirely. This could be done for the example above by adjusting the +`b.iter` call to + +```rust +# struct X; +# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; +b.iter(|| { + // note lack of `;` (could also use an explicit `return`). + (0..1000).fold(0, |old, new| old ^ new) +}); +``` + +Or, the other option is to call the generic `test::black_box` function, which +is an opaque "black box" to the optimizer and so forces it to consider any +argument as used. + +```rust +#![feature(test)] + +extern crate test; + +# fn main() { +# struct X; +# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; +b.iter(|| { + let n = test::black_box(1000); + + (0..n).fold(0, |a, b| a ^ b) +}) +# } +``` + +Neither of these read or modify the value, and are very cheap for small values. +Larger values can be passed indirectly to reduce overhead (e.g. +`black_box(&huge_struct)`). + +Performing either of the above changes gives the following benchmarking results + +```text +running 1 test +test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3) + +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. diff --git a/src/doc/trpl/box-syntax-and-patterns.md b/src/doc/trpl/box-syntax-and-patterns.md new file mode 100644 index 0000000000..839f07d984 --- /dev/null +++ b/src/doc/trpl/box-syntax-and-patterns.md @@ -0,0 +1,100 @@ +% Box Syntax and Patterns + +Currently the only stable way to create a `Box` is via the `Box::new` method. +Also it is not possible in stable Rust to destructure a `Box` in a match +pattern. The unstable `box` keyword can be used to both create and destructure +a `Box`. An example usage would be: + +``` +#![feature(box_syntax, box_patterns)] + +fn main() { + let b = Some(box 5); + match b { + Some(box n) if n < 0 => { + println!("Box contains negative number {}", n); + }, + Some(box n) if n >= 0 => { + println!("Box contains non-negative number {}", n); + }, + None => { + println!("No box"); + }, + _ => unreachable!() + } +} +``` + +Note that these features are currently hidden behind the `box_syntax` (box +creation) and `box_patterns` (destructuring and pattern matching) gates +because the syntax may still change in the future. + +# Returning Pointers + +In many languages with pointers, you'd return a pointer from a function +so as to avoid copying a large data structure. For example: + +```{rust} +struct BigStruct { + one: i32, + two: i32, + // etc + one_hundred: i32, +} + +fn foo(x: Box) -> Box { + Box::new(*x) +} + +fn main() { + let x = Box::new(BigStruct { + one: 1, + two: 2, + one_hundred: 100, + }); + + let y = foo(x); +} +``` + +The idea is that by passing around a box, you're only copying a pointer, rather +than the hundred `int`s that make up the `BigStruct`. + +This is an antipattern in Rust. Instead, write this: + +```rust +#![feature(box_syntax)] + +struct BigStruct { + one: i32, + two: i32, + // etc + one_hundred: i32, +} + +fn foo(x: Box) -> BigStruct { + *x +} + +fn main() { + let x = Box::new(BigStruct { + one: 1, + two: 2, + one_hundred: 100, + }); + + let y: Box = box foo(x); +} +``` + +This gives you flexibility without sacrificing performance. + +You may think that this gives us terrible performance: return a value and then +immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is +smarter than that. There is no copy in this code. `main` allocates enough room +for the `box`, passes a pointer to that memory into `foo` as `x`, and then +`foo` writes the value straight into the `Box`. + +This is important enough that it bears repeating: pointers are not for +optimizing returning values from your code. Allow the caller to choose how they +want to use your output. diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index 8cc6be7387..01b8163ffd 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -1,214 +1,478 @@ % Closures -So far, we've made lots of functions in Rust, but we've given them all names. -Rust also allows us to create anonymous functions. Rust's anonymous -functions are called *closures*. By themselves, closures aren't all that -interesting, but when you combine them with functions that take closures as -arguments, really powerful things are possible. +Rust not only has named functions, but anonymous functions as well. Anonymous +functions that have an associated environment are called 'closures', because they +close over an environment. Rust has a really great implementation of them, as +we'll see. -Let's make a closure: +# Syntax -```{rust} -let add_one = |x| { 1 + x }; +Closures look like this: -println!("The sum of 5 plus 1 is {}.", add_one(5)); +```rust +let plus_one = |x: i32| x + 1; + +assert_eq!(2, plus_one(1)); +``` + +We create a binding, `plus_one`, and assign it to a closure. The closure's +arguments go between the pipes (`|`), and the body is an expression, in this +case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line +closures too: + +```rust +let plus_two = |x| { + let mut result: i32 = x; + + result += 1; + result += 1; + + result +}; + +assert_eq!(4, plus_two(2)); +``` + +You'll notice a few things about closures that are a bit different than regular +functions defined with `fn`. The first of which is that we did not need to +annotate the types of arguments the closure takes or the values it returns. We +can: + +```rust +let plus_one = |x: i32| -> i32 { x + 1 }; + +assert_eq!(2, plus_one(1)); +``` + +But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons. +While specifying the full type for named functions is helpful with things like +documentation and type inference, the types of closures are rarely documented +since they’re anonymous, and they don’t cause the kinds of error-at-a-distance +that inferring named function types can. + +The second is that the syntax is similar, but a bit different. I've added spaces +here to make them look a little closer: + +```rust +fn plus_one_v1 ( x: i32 ) -> i32 { x + 1 } +let plus_one_v2 = |x: i32 | -> i32 { x + 1 }; +let plus_one_v3 = |x: i32 | x + 1 ; ``` -We create a closure using the `|...| { ... }` syntax, and then we create a -binding so we can use it later. Note that we call the function using the -binding name and two parentheses, just like we would for a named function. +Small differences, but they're similar in ways. -Let's compare syntax. The two are pretty close: +# Closures and their environment -```{rust} -let add_one = |x: i32| -> i32 { 1 + x }; -fn add_one (x: i32) -> i32 { 1 + x } +Closures are called such because they 'close over their environment.' It +looks like this: + +```rust +let num = 5; +let plus_num = |x: i32| x + num; + +assert_eq!(10, plus_num(5)); ``` -As you may have noticed, closures infer their argument and return types, so you -don't need to declare one. This is different from named functions, which -default to returning unit (`()`). +This closure, `plus_num`, refers to a `let` binding in its scope: `num`. More +specifically, it borrows the binding. If we do something that would conflict +with that binding, we get an error. Like this one: + +```rust,ignore +let mut num = 5; +let plus_num = |x: i32| x + num; -There's one big difference between a closure and named functions, and it's in -the name: a closure "closes over its environment." What does that mean? It means -this: +let y = &mut num; +``` -```{rust} +Which errors with: + +```text +error: cannot borrow `num` as mutable because it is also borrowed as immutable + let y = &mut num; + ^~~ +note: previous borrow of `num` occurs here due to use in closure; the immutable + borrow prevents subsequent moves or mutable borrows of `num` until the borrow + ends + let plus_num = |x| x + num; + ^~~~~~~~~~~ +note: previous borrow ends here fn main() { - let x: i32 = 5; + let mut num = 5; + let plus_num = |x| x + num; + + let y = &mut num; +} +^ +``` + +A verbose yet helpful error message! As it says, we can't take a mutable borrow +on `num` because the closure is already borrowing it. If we let the closure go +out of scope, we can: + +```rust +let mut num = 5; +{ + let plus_num = |x: i32| x + num; + +} // plus_num goes out of scope, borrow of num ends - let printer = || { println!("x is: {}", x); }; +let y = &mut num; +``` + +If your closure requires it, however, Rust will take ownership and move +the environment instead: + +```rust,ignore +let nums = vec![1, 2, 3]; + +let takes_nums = || nums; + +println!("{:?}", nums); +``` + +This gives us: + +```text +note: `nums` moved into closure environment here because it has type + `[closure(()) -> collections::vec::Vec]`, which is non-copyable +let takes_nums = || nums; + ^~~~~~~ +``` + +`Vec` has ownership over its contents, and therefore, when we refer to it +in our closure, we have to take ownership of `nums`. It's the same as if we'd +passed `nums` to a function that took ownership of it. + +## `move` closures + +We can force our closure to take ownership of its environment with the `move` +keyword: - printer(); // prints "x is: 5" +```rust +let num = 5; + +let owns_num = move |x: i32| x + num; +``` + +Now, even though the keyword is `move`, the variables follow normal move semantics. +In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy +of `num`. So what's the difference? + +```rust +let mut num = 5; + +{ + let mut add_num = |x: i32| num += x; + + add_num(5); } + +assert_eq!(10, num); ``` -The `||` syntax means this is an anonymous closure that takes no arguments. -Without it, we'd just have a block of code in `{}`s. +So in this case, our closure took a mutable reference to `num`, and then when +we called `add_num`, it mutated the underlying value, as we'd expect. We also +needed to declare `add_num` as `mut` too, because we’re mutating its +environment. -In other words, a closure has access to variables in the scope where it's -defined. The closure borrows any variables it uses, so this will error: +We also had to declare `add_num` as mut, since we will be modifying its +environment. -```{rust,ignore} -fn main() { - let mut x: i32 = 5; +If we change to a `move` closure, it's different: + +```rust +let mut num = 5; - let printer = || { println!("x is: {}", x); }; +{ + let mut add_num = move |x: i32| num += x; - x = 6; // error: cannot assign to `x` because it is borrowed + add_num(5); } + +assert_eq!(5, num); ``` -## Moving closures +We only get `5`. Rather than taking a mutable borrow out on our `num`, we took +ownership of a copy. + +Another way to think about `move` closures: they give a closure its own stack +frame. Without `move`, a closure may be tied to the stack frame that created +it, while a `move` closure is self-contained. This means that you cannot +generally return a non-`move` closure from a function, for example. + +But before we talk about taking and returning closures, we should talk some more +about the way that closures are implemented. As a systems language, Rust gives +you tons of control over what your code does, and closures are no different. -Rust has a second type of closure, called a *moving closure*. Moving -closures are indicated using the `move` keyword (e.g., `move || x * -x`). The difference between a moving closure and an ordinary closure -is that a moving closure always takes ownership of all variables that -it uses. Ordinary closures, in contrast, just create a reference into -the enclosing stack frame. Moving closures are most useful with Rust's -concurrency features, and so we'll just leave it at this for -now. We'll talk about them more in the "Threads" section of the guide. +# Closure implementation -## Accepting closures as arguments +Rust's implementation of closures is a bit different than other languages. They +are effectively syntax sugar for traits. You'll want to make sure to have read +the [traits chapter][traits] before this one, as well as the chapter on [static +and dynamic dispatch][dispatch], which talks about trait objects. -Closures are most useful as an argument to another function. Here's an example: +[traits]: traits.html +[dispatch]: static-and-dynamic-dispatch.html -```{rust} -fn twice i32>(x: i32, f: F) -> i32 { - f(x) + f(x) +Got all that? Good. + +The key to understanding how closures work under the hood is something a bit +strange: Using `()` to call a function, like `foo()`, is an overloadable +operator. From this, everything else clicks into place. In Rust, we use the +trait system to overload operators. Calling functions is no different. We have +three separate traits to overload with: + +```rust +# mod foo { +pub trait Fn : FnMut { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; } -fn main() { - let square = |x: i32| { x * x }; +pub trait FnMut : FnOnce { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +pub trait FnOnce { + type Output; - twice(5, square); // evaluates to 50 + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } +# } ``` -Let's break the example down, starting with `main`: +You'll notice a few differences between these traits, but a big one is `self`: +`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This +covers all three kinds of `self` via the usual method call syntax. But we've +split them up into three traits, rather than having a single one. This gives us +a large amount of control over what kind of closures we can take. -```{rust} -let square = |x: i32| { x * x }; -``` +The `|| {}` syntax for closures is sugar for these three traits. Rust will +generate a struct for the environment, `impl` the appropriate trait, and then +use it. + +# Taking closures as arguments + +Now that we know that closures are traits, we already know how to accept and +return closures: just like any other trait! + +This also means that we can choose static vs dynamic dispatch as well. First, +let's write a function which takes something callable, calls it, and returns +the result: + +```rust +fn call_with_one(some_closure: F) -> i32 + where F : Fn(i32) -> i32 { + + some_closure(1) +} -We've seen this before. We make a closure that takes an integer, and returns -its square. +let answer = call_with_one(|x| x + 2); -```{rust} -# fn twice i32>(x: i32, f: F) -> i32 { f(x) + f(x) } -# let square = |x: i32| { x * x }; -twice(5, square); // evaluates to 50 +assert_eq!(3, answer); ``` -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 i32, and one is a function." +We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it +suggests: it calls the closure, giving it `1` as an argument. -Next, let's look at how `twice` is defined: +Let's examine the signature of `call_with_one` in more depth: -```{rust,ignore} -fn twice i32>(x: i32, f: F) -> i32 { +```rust +fn call_with_one(some_closure: F) -> i32 +# where F : Fn(i32) -> i32 { +# some_closure(1) } ``` -`twice` takes two arguments, `x` and `f`. That's why we called it with two -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`. This is -what the requirement `Fn(i32) -> i32` for the type parameter `F` says. -Now `F` represents *any* function that takes an `i32` and returns an `i32`. +We take one parameter, and it has the type `F`. We also return a `i32`. This part +isn't interesting. The next part is: -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. The good news is that this kind of passing a closure around -can be very efficient. With all the type information available at compile-time -the compiler can do wonders. +```rust +# fn call_with_one(some_closure: F) -> i32 + where F : Fn(i32) -> i32 { +# some_closure(1) } +``` + +Because `Fn` is a trait, we can bound our generic with it. In this case, our closure +takes a `i32` as an argument and returns an `i32`, and so the generic bound we use +is `Fn(i32) -> i32`. -Finally, `twice` returns an `i32` as well. +There's one other key point here: because we're bounding a generic with a +trait, this will get monomorphized, and therefore, we'll be doing static +dispatch into the closure. That's pretty neat. In many langauges, closures are +inherently heap allocated, and will always involve dynamic dispatch. In Rust, +we can stack allocate our closure environment, and statically dispatch the +call. This happens quite often with iterators and their adapters, which often +take closures as arguments. -Okay, let's look at the body of `twice`: +Of course, if we want dynamic dispatch, we can get that too. A trait object +handles this case, as usual: -```{rust} -fn twice i32>(x: i32, f: F) -> i32 { - f(x) + f(x) +```rust +fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { + some_closure(1) } + +let answer = call_with_one(&|x| x + 2); + +assert_eq!(3, answer); ``` -Since our closure is named `f`, we can call it just like we called our closures -before, and we pass in our `x` argument to each one, hence the name `twice`. +Now we take a trait object, a `&Fn`. And we have to make a reference +to our closure when we pass it to `call_with_one`, so we use `&||`. -If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get. +# Returning closures -Play around with this concept until you're comfortable with it. Rust's standard -library uses lots of closures where appropriate, so you'll be using -this technique a lot. +It’s very common for functional-style code to return closures in various +situations. If you try to return a closure, you may run into an error. At +first, it may seem strange, but we'll figure it out. Here's how you'd probably +try to return a closure from a function: -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,ignore +fn factory() -> (Fn(i32) -> Vec) { + let vec = vec![1, 2, 3]; -```{rust} -fn twice i32>(x: i32, f: F) -> i32 { - f(x) + f(x) + |n| vec.push(n) } -fn main() { - twice(5, |x: i32| { x * x }); // evaluates to 50 -} +let f = factory(); + +let answer = f(4); +assert_eq!(vec![1, 2, 3, 4], answer); ``` -A named function's name can be used wherever you'd use a closure. Another -way of writing the previous example: +This gives us these long, related errors: + +```text +error: the trait `core::marker::Sized` is not implemented for the type +`core::ops::Fn(i32) -> collections::vec::Vec` [E0277] +f = factory(); +^ +note: `core::ops::Fn(i32) -> collections::vec::Vec` does not have a +constant size known at compile-time +f = factory(); +^ +error: the trait `core::marker::Sized` is not implemented for the type +`core::ops::Fn(i32) -> collections::vec::Vec` [E0277] +factory() -> (Fn(i32) -> Vec) { + ^~~~~~~~~~~~~~~~~~~~~ +note: `core::ops::Fn(i32) -> collections::vec::Vec` does not have a constant size known at compile-time +fa ctory() -> (Fn(i32) -> Vec) { + ^~~~~~~~~~~~~~~~~~~~~ -```{rust} -fn twice i32>(x: i32, f: F) -> i32 { - f(x) + f(x) -} +``` -fn square(x: i32) -> i32 { x * x } +In order to return something from a function, Rust needs to know what +size the return type is. But since `Fn` is a trait, it could be various +things of various sizes: many different types can implement `Fn`. An easy +way to give something a size is to take a reference to it, as references +have a known size. So we'd write this: -fn main() { - twice(5, square); // evaluates to 50 +```rust,ignore +fn factory() -> &(Fn(i32) -> Vec) { + let vec = vec![1, 2, 3]; + + |n| vec.push(n) } + +let f = factory(); + +let answer = f(4); +assert_eq!(vec![1, 2, 3, 4], answer); +``` + +But we get another error: + +```text +error: missing lifetime specifier [E0106] +fn factory() -> &(Fn(i32) -> i32) { + ^~~~~~~~~~~~~~~~~ ``` -Doing this is not particularly common, but it's useful every once in a while. +Right. Because we have a reference, we need to give it a lifetime. But +our `factory()` function takes no arguments, so elision doesn't kick in +here. What lifetime can we choose? `'static`: -Before we move on, let us look at a function that accepts two closures. +```rust,ignore +fn factory() -> &'static (Fn(i32) -> i32) { + let num = 5; -```{rust} -fn compose(x: i32, f: F, g: G) -> i32 - where F: Fn(i32) -> i32, G: Fn(i32) -> i32 { - g(f(x)) + |x| x + num } -fn main() { - compose(5, - |n: i32| { n + 42 }, - |n: i32| { n * 2 }); // evaluates to 94 +let f = factory(); + +let answer = f(1); +assert_eq!(6, answer); +``` + +But we get another error: + +```text +error: mismatched types: + expected `&'static core::ops::Fn(i32) -> i32`, + found `[closure :7:9: 7:20]` +(expected &-ptr, + found closure) [E0308] + |x| x + num + ^~~~~~~~~~~ + +``` + +This error is letting us know that we don't have a `&'static Fn(i32) -> i32`, +we have a `[closure :7:9: 7:20]`. Wait, what? + +Because each closure generates its own environment `struct` and implementation +of `Fn` and friends, these types are anonymous. They exist just solely for +this closure. So Rust shows them as `closure `, rather than some +autogenerated name. + +But why doesn't our closure implement `&'static Fn`? Well, as we discussed before, +closures borrow their environment. And in this case, our environment is based +on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime +of the stack frame. So if we returned this closure, the function call would be +over, the stack frame would go away, and our closure is capturing an environment +of garbage memory! + +So what to do? This _almost_ works: + +```rust,ignore +fn factory() -> Box i32> { + let num = 5; + + Box::new(|x| x + num) } +# fn main() { +let f = factory(); + +let answer = f(1); +assert_eq!(6, answer); +# } ``` -You might ask yourself: why do we need to introduce two type -parameters `F` and `G` here? Evidently, both `f` and `g` have the -same signature: `Fn(i32) -> i32`. +We use a trait object, by `Box`ing up the `Fn`. There's just one last problem: -That is because in Rust each closure has its own unique type. -So, not only do closures with different signatures have different types, -but different closures with the *same* signature have *different* -types, as well! +```text +error: `num` does not live long enough +Box::new(|x| x + num) + ^~~~~~~~~~~ +``` + +We still have a reference to the parent stack frame. With one last fix, we can +make this work: -You can think of it this way: the behavior of a closure is part of its -type. Therefore, using a single type parameter for both closures -will accept the first of them, rejecting the second. The distinct -type of the second closure does not allow it to be represented by the -same type parameter as that of the first. We acknowledge this, and -use two different type parameters `F` and `G`. +```rust +fn factory() -> Box i32> { + let num = 5; -This also introduces the `where` clause, which lets us describe type -parameters in a more flexible manner. + Box::new(move |x| x + num) +} +# fn main() { +let f = factory(); + +let answer = f(1); +assert_eq!(6, answer); +# } +``` -That's all you need to get the hang of closures! Closures are a little bit -strange at first, but once you're used to them, you'll miss them -in other languages. Passing functions to other functions is -incredibly powerful, as you will see in the following chapter about iterators. +By making the inner closure a `move Fn`, we create a new stack frame for our +closure. By `Box`ing it up, we've given it a known size, and allowing it to +escape our stack frame. diff --git a/src/doc/trpl/comments.md b/src/doc/trpl/comments.md index 66670c7c63..441496e6a7 100644 --- a/src/doc/trpl/comments.md +++ b/src/doc/trpl/comments.md @@ -28,7 +28,7 @@ The other kind of comment is a doc comment. Doc comments use `///` instead of /// /// * `name` - The name of the person you'd like to greet. /// -/// # Example +/// # Examples /// /// ```rust /// let name = "Steve"; diff --git a/src/doc/trpl/compound-data-types.md b/src/doc/trpl/compound-data-types.md index 85d67262c4..e44d2edd66 100644 --- a/src/doc/trpl/compound-data-types.md +++ b/src/doc/trpl/compound-data-types.md @@ -6,8 +6,8 @@ strings, but next, let's talk about some more complicated ways of storing data. ## Tuples -The first compound data type we're going to talk about are called *tuples*. -Tuples are an ordered list of a fixed size. Like this: +The first compound data type we're going to talk about is called the *tuple*. +A tuple is an ordered list of fixed size. Like this: ```rust let x = (1, "hello"); @@ -47,7 +47,7 @@ This pattern is very powerful, and we'll see it repeated more later. There are also a few things you can do with a tuple as a whole, without destructuring. You can assign one tuple into another, if they have the same -contained types and arity. Tuples have the same arity when they have the same +contained types and [arity]. Tuples have the same arity when they have the same length. ```rust @@ -196,8 +196,9 @@ Now, we have actual names, rather than positions. Good names are important, and with a struct, we have actual names. There _is_ one case when a tuple struct is very useful, though, and that's a -tuple struct with only one element. We call this a *newtype*, because it lets -you create a new type that's similar to another one: +tuple struct with only one element. We call this the *newtype* pattern, because +it allows you to create a new type, distinct from that of its contained value +and expressing its own semantic meaning: ```{rust} struct Inches(i32); @@ -216,7 +217,7 @@ destructuring `let`, as we discussed previously in 'tuples.' In this case, the Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful feature of Rust, and are used throughout the standard library. An `enum` is -a type which ties a set of alternates to a specific name. For example, below +a type which relates a set of alternates to a specific name. For example, below we define `Character` to be either a `Digit` or something else. These can be used via their fully scoped names: `Character::Other` (more about `::` below). @@ -228,8 +229,8 @@ enum Character { } ``` -An `enum` variant can be defined as most normal types. Below are some example -types have been listed which also would be allowed in an `enum`. +Most normal types are allowed as the variant components of an `enum`. Here are +some examples: ```rust struct Empty; @@ -239,15 +240,15 @@ struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 } struct HeightDatabase(Vec); ``` -So you see that depending on the sub-datastructure, the `enum` variant, same as -a struct, may or may not hold data. That is, in `Character`, `Digit` is a name -tied to an `i32` where `Other` is just a name. However, the fact that they are -distinct makes this very useful. +You see that, depending on its type, an `enum` variant may or may not hold data. +In `Character`, for instance, `Digit` gives a meaningful name for an `i32` +value, where `Other` is only a name. However, the fact that they represent +distinct categories of `Character` is a very useful property. -As with structures, enums don't by default have access to operators such as -compare ( `==` and `!=`), binary operations (`*` and `+`), and order -(`<` and `>=`). As such, using the previous `Character` type, the -following code is invalid: +As with structures, the variants of an enum by default are not comparable with +equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not +support other binary operations such as `*` and `+`. As such, the following code +is invalid for the example `Character` type: ```{rust,ignore} // These assignments both succeed @@ -265,9 +266,10 @@ let four_equals_ten = four == ten; ``` This may seem rather limiting, but it's a limitation which we can overcome. -There are two ways: by implementing equality ourselves, or by using the -[`match`][match] keyword. We don't know enough about Rust to implement equality -yet, but we can use the `Ordering` enum from the standard library, which does: +There are two ways: by implementing equality ourselves, or by pattern matching +variants with [`match`][match] expressions, which you'll learn in the next +chapter. We don't know enough about Rust to implement equality yet, but we can +use the `Ordering` enum from the standard library, which does: ``` enum Ordering { @@ -277,9 +279,8 @@ enum Ordering { } ``` -Because we did not define `Ordering`, we must import it (from the std -library) with the `use` keyword. Here's an example of how `Ordering` is -used: +Because `Ordering` has already been defined for us, we will import it with the +`use` keyword. Here's an example of how it is used: ```{rust} use std::cmp::Ordering; @@ -313,17 +314,17 @@ the standard library if you need them. Okay, let's talk about the actual code in the example. `cmp` is a function that compares two things, and returns an `Ordering`. We return either -`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if -the two values are less, greater, or equal. Note that each variant of the -`enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not -`Greater`. +`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on +whether the first value is less than, greater than, or equal to the second. Note +that each variant of the `enum` is namespaced under the `enum` itself: it's +`Ordering::Greater`, not `Greater`. The `ordering` variable has the type `Ordering`, and so contains one of the three values. We then do a bunch of `if`/`else` comparisons to check which one it is. -This `Ordering::Greater` notation is too long. Let's use `use` to import the -`enum` variants instead. This will avoid full scoping: +This `Ordering::Greater` notation is too long. Let's use another form of `use` +to import the `enum` variants instead. This will avoid full scoping: ```{rust} use std::cmp::Ordering::{self, Equal, Less, Greater}; @@ -347,16 +348,17 @@ fn main() { ``` Importing variants is convenient and compact, but can also cause name conflicts, -so do this with caution. It's considered good style to rarely import variants -for this reason. +so do this with caution. For this reason, it's normally considered better style +to `use` an enum rather than its variants directly. -As you can see, `enum`s are quite a powerful tool for data representation, and are -even more useful when they're [generic][generics] across types. Before we -get to generics, though, let's talk about how to use them with pattern matching, a -tool that will let us deconstruct this sum type (the type theory term for enums) -in a very elegant way and avoid all these messy `if`/`else`s. +As you can see, `enum`s are quite a powerful tool for data representation, and +are even more useful when they're [generic][generics] across types. Before we +get to generics, though, let's talk about how to use enums with pattern +matching, a tool that will let us deconstruct sum types (the type theory term +for enums) like `Ordering` in a very elegant way that avoids all these messy +and brittle `if`/`else`s. +[arity]: ./glossary.html#arity [match]: ./match.html -[game]: ./guessing-game.html#comparing-guesses [generics]: ./generics.html diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 842957bd60..6b814a6854 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -40,14 +40,14 @@ us enforce that it can't leave the current thread. ### `Sync` -The second of these two trait is called [`Sync`](../std/marker/trait.Sync.html). +The second of these traits is called [`Sync`](../std/marker/trait.Sync.html). When a type `T` implements `Sync`, it indicates to the compiler that something of this type has no possibility of introducing memory unsafety when used from multiple threads concurrently. For example, sharing immutable data with an atomic reference count is threadsafe. Rust provides a type like this, `Arc`, and it implements `Sync`, -so that it could be safely shared between threads. +so it is safe to share between threads. These two traits allow you to use the type system to make strong guarantees about the properties of your code under concurrency. Before we demonstrate @@ -69,7 +69,7 @@ fn main() { } ``` -The `Thread::scoped()` method accepts a closure, which is executed in a new +The `thread::scoped()` method accepts a closure, which is executed in a new thread. It's called `scoped` because this thread returns a join guard: ``` @@ -88,6 +88,7 @@ When `guard` goes out of scope, it will block execution until the thread is finished. If we didn't want this behaviour, we could use `thread::spawn()`: ``` +# #![feature(old_io, std_misc)] use std::thread; use std::old_io::timer; use std::time::Duration; @@ -146,6 +147,7 @@ As an example, here is a Rust program that would have a data race in many languages. It will not compile: ```ignore +# #![feature(old_io, std_misc)] use std::thread; use std::old_io::timer; use std::time::Duration; @@ -185,6 +187,7 @@ only one person at a time can mutate what's inside. For that, we can use the but for a different reason: ```ignore +# #![feature(old_io, std_misc)] use std::thread; use std::old_io::timer; use std::time::Duration; @@ -208,10 +211,10 @@ Here's the error: ```text :11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec>` [E0277] -:11 Thread::spawn(move || { +:11 thread::spawn(move || { ^~~~~~~~~~~~~ :11:9: 11:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec>` cannot be sent between threads safely -:11 Thread::spawn(move || { +:11 thread::spawn(move || { ^~~~~~~~~~~~~ ``` @@ -223,19 +226,13 @@ method which has this signature: fn lock(&self) -> LockResult> ``` -If we [look at the code for MutexGuard](https://github.com/rust-lang/rust/blob/ca4b9674c26c1de07a2042cb68e6a062d7184cef/src/libstd/sync/mutex.rs#L172), we'll see -this: - -```ignore -__marker: marker::NoSend, -``` - -Because our guard is `NoSend`, it's not `Send`. Which means we can't actually -transfer the guard across thread boundaries, which gives us our error. +Because `Send` is not implemented for `MutexGuard`, we can't transfer the +guard across thread boundaries, which gives us our error. We can use `Arc` to fix this. Here's the working version: ``` +# #![feature(old_io, std_misc)] use std::sync::{Arc, Mutex}; use std::thread; use std::old_io::timer; @@ -261,6 +258,7 @@ handle is then moved into the new thread. Let's examine the body of the thread more closely: ``` +# #![feature(old_io, std_misc)] # use std::sync::{Arc, Mutex}; # use std::thread; # use std::old_io::timer; @@ -282,13 +280,15 @@ it returns an `Result`, and because this is just an example, we `unwrap()` it to get a reference to the data. Real code would have more robust error handling here. We're then free to mutate it, since we have the lock. -This timer bit is a bit awkward, however. We have picked a reasonable amount of -time to wait, but it's entirely possible that we've picked too high, and that -we could be taking less time. It's also possible that we've picked too low, -and that we aren't actually finishing this computation. +Lastly, while the threads are running, we wait on a short timer. But +this is not ideal: we may have picked a reasonable amount of time to +wait but it's more likely we'll either be waiting longer than +necessary or not long enough, depending on just how much time the +threads actually take to finish computing when the program runs. -Rust's standard library provides a few more mechanisms for two threads to -synchronize with each other. Let's talk about one: channels. +A more precise alternative to the timer would be to use one of the +mechanisms provided by the Rust standard library for synchronizing +threads with each other. Let's talk about one of them: channels. ## Channels @@ -329,7 +329,6 @@ While this channel is just sending a generic signal, we can send any data that is `Send` over the channel! ``` -use std::sync::{Arc, Mutex}; use std::thread; use std::sync::mpsc; @@ -346,7 +345,7 @@ fn main() { }); } - rx.recv().ok().expect("Could not recieve answer"); + rx.recv().ok().expect("Could not receive answer"); } ``` diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 1f5d3eadae..0cc54c9b16 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -1,6 +1,6 @@ % Crates and Modules -When a project starts getting large, it's considered a good software +When a project starts getting large, it's considered good software engineering practice to split it up into a bunch of smaller pieces, and then fit them together. It's also important to have a well-defined interface, so that some of your functionality is private, and some is public. To facilitate @@ -12,7 +12,7 @@ Rust has two distinct terms that relate to the module system: *crate* and *module*. A crate is synonymous with a *library* or *package* in other languages. Hence "Cargo" as the name of Rust's package management tool: you ship your crates to others with Cargo. Crates can produce an executable or a -shared library, depending on the project. +library, depending on the project. Each crate has an implicit *root module* that contains the code for that crate. You can then define a tree of sub-modules under that root module. Modules allow @@ -24,23 +24,23 @@ in different languages. To keep things simple, we'll stick to "greetings" and two languages for those phrases to be in. We'll use this module layout: ```text - +-----------+ - +---| greetings | - | +-----------+ - +---------+ | - | english |---+ - +---------+ | +-----------+ - | +---| farewells | -+---------+ | +-----------+ + +-----------+ + +---| greetings | + | +-----------+ + +---------+ | + +---| english |---+ + | +---------+ | +-----------+ + | +---| farewells | ++---------+ | +-----------+ | phrases |---+ -+---------+ | +-----------+ - | +---| greetings | - +----------+ | +-----------+ - | japanese |---+ - +----------+ | - | +-----------+ - +---| farewells | - +-----------+ ++---------+ | +-----------+ + | +---| greetings | + | +----------+ | +-----------+ + +---| japanese |--+ + +----------+ | + | +-----------+ + +---| farewells | + +-----------+ ``` In this example, `phrases` is the name of our crate. All of the rest are @@ -76,25 +76,19 @@ To define each of our modules, we use the `mod` keyword. Let's make our `src/lib.rs` look like this: ``` -// in src/lib.rs - mod english { mod greetings { - } mod farewells { - } } mod japanese { mod greetings { - } mod farewells { - } } ``` @@ -145,11 +139,7 @@ mod english; ``` If we do that, Rust will expect to find either a `english.rs` file, or a -`english/mod.rs` file with the contents of our module: - -```{rust,ignore} -// contents of our module go here -``` +`english/mod.rs` file with the contents of our module. Note that in these files, you don't need to re-declare the module: that's already been done with the initial `mod` declaration. @@ -181,10 +171,7 @@ $ tree . `src/lib.rs` is our crate root, and looks like this: ```{rust,ignore} -// in src/lib.rs - mod english; - mod japanese; ``` @@ -195,10 +182,7 @@ chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look like this: ```{rust,ignore} -// both src/english/mod.rs and src/japanese/mod.rs - mod greetings; - mod farewells; ``` @@ -214,8 +198,6 @@ both empty at the moment. Let's add some functions. Put this in `src/english/greetings.rs`: ```rust -// in src/english/greetings.rs - fn hello() -> String { "Hello!".to_string() } @@ -224,8 +206,6 @@ fn hello() -> String { Put this in `src/english/farewells.rs`: ```rust -// in src/english/farewells.rs - fn goodbye() -> String { "Goodbye.".to_string() } @@ -248,8 +228,6 @@ about the module system. Put this in `src/japanese/farewells.rs`: ```rust -// in src/japanese/farewells.rs - fn goodbye() -> String { "さようなら".to_string() } @@ -265,11 +243,9 @@ another crate. We have a library crate. Let's make an executable crate that imports and uses our library. -Make a `src/main.rs` and put this in it: (it won't quite compile yet) +Make a `src/main.rs` and put this in it (it won't quite compile yet): ```rust,ignore -// in src/main.rs - extern crate phrases; fn main() { @@ -320,8 +296,6 @@ keyword. Let's focus on the `english` module first, so let's reduce our `src/mai to just this: ```{rust,ignore} -// in src/main.rs - extern crate phrases; fn main() { @@ -333,28 +307,20 @@ fn main() { In our `src/lib.rs`, let's add `pub` to the `english` module declaration: ```{rust,ignore} -// in src/lib.rs - pub mod english; - mod japanese; ``` And in our `src/english/mod.rs`, let's make both `pub`: ```{rust,ignore} -// in src/english/mod.rs - pub mod greetings; - pub mod farewells; ``` In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration: ```{rust,ignore} -// in src/english/greetings.rs - pub fn hello() -> String { "Hello!".to_string() } @@ -363,8 +329,6 @@ pub fn hello() -> String { And also in `src/english/farewells.rs`: ```{rust,ignore} -// in src/english/farewells.rs - pub fn goodbye() -> String { "Goodbye.".to_string() } @@ -400,8 +364,6 @@ Rust has a `use` keyword, which allows us to import names into our local scope. Let's change our `src/main.rs` to look like this: ```{rust,ignore} -// in src/main.rs - extern crate phrases; use phrases::english::greetings; @@ -430,7 +392,7 @@ fn main() { } ``` -But it is not idiomatic. This is significantly more likely to introducing a +But it is not idiomatic. This is significantly more likely to introduce a naming conflict. In our short program, it's not a big deal, but as it grows, it becomes a problem. If we have conflicting names, Rust will give a compilation error. For example, if we made the `japanese` functions public, and tried to do @@ -460,21 +422,19 @@ Could not compile `phrases`. ``` If we're importing multiple names from the same module, we don't have to type it out -twice. Rust has a shortcut syntax for writing this: +twice. Instead of this: ```{rust,ignore} use phrases::english::greetings; use phrases::english::farewells; ``` -You use curly braces: +We can use this shortcut: ```{rust,ignore} use phrases::english::{greetings, farewells}; ``` -These two declarations are equivalent, but the second is a lot less typing. - ## Re-exporting with `pub use` You don't just use `use` to shorten identifiers. You can also use it inside of your crate @@ -484,8 +444,6 @@ interface that may not directly map to your internal code organization. Let's look at an example. Modify your `src/main.rs` to read like this: ```{rust,ignore} -// in src/main.rs - extern crate phrases; use phrases::english::{greetings,farewells}; @@ -503,18 +461,13 @@ fn main() { Then, modify your `src/lib.rs` to make the `japanese` mod public: ```{rust,ignore} -// in src/lib.rs - pub mod english; - pub mod japanese; ``` Next, make the two functions public, first in `src/japanese/greetings.rs`: ```{rust,ignore} -// in src/japanese/greetings.rs - pub fn hello() -> String { "こんにちは".to_string() } @@ -523,8 +476,6 @@ pub fn hello() -> String { And then in `src/japanese/farewells.rs`: ```{rust,ignore} -// in src/japanese/farewells.rs - pub fn goodbye() -> String { "さようなら".to_string() } @@ -533,13 +484,10 @@ pub fn goodbye() -> String { Finally, modify your `src/japanese/mod.rs` to read like this: ```{rust,ignore} -// in src/japanese/mod.rs - pub use self::greetings::hello; pub use self::farewells::goodbye; mod greetings; - mod farewells; ``` @@ -551,9 +499,21 @@ module, we now have a `phrases::japanese::hello()` function and a `phrases::japanese::farewells::goodbye()`. Our internal organization doesn't define our external interface. -Here we have a `pub use` for each function we want to bring into the +Here we have a `pub use` for each function we want to bring into the `japanese` scope. We could alternatively use the wildcard syntax to include -everything from `greetings` into the current scope: `pub use self::greetings::*`. +everything from `greetings` into the current scope: `pub use self::greetings::*`. + +What about the `self`? Well, by default, `use` declarations are absolute paths, +starting from your crate root. `self` makes that path relative to your current +place in the hierarchy instead. There's one more special form of `use`: you can +`use super::` to reach one level up the tree from your current location. Some +people like to think of `self` as `.` and `super` as `..`, from many shells' +display for the current directory and the parent directory. + +Outside of `use`, paths are relative: `foo::bar()` refers to a function inside +of `foo` relative to where we are. If that's prefixed with `::`, as in +`::foo::bar()`, it refers to a different `foo`, an absolute path from your +crate root. Also, note that we `pub use`d before we declared our `mod`s. Rust requires that `use` declarations go first. diff --git a/src/doc/trpl/documentation.md b/src/doc/trpl/documentation.md index ded30063eb..06071a8f15 100644 --- a/src/doc/trpl/documentation.md +++ b/src/doc/trpl/documentation.md @@ -1,319 +1,562 @@ % Documentation -`rustdoc` is the built-in tool for generating documentation. It integrates -with the compiler to provide accurate hyperlinking between usage of types and -their documentation. Furthermore, by not using a separate parser, it will -never reject your valid Rust code. +Documentation is an important part of any software project, and it's +first-class in Rust. Let's talk about the tooling Rust gives you to +document your project. -# Creating Documentation +## About `rustdoc` -Documenting Rust APIs is quite simple. To document a given item, we have "doc -comments": +The Rust distribution includes a tool, `rustdoc`, that generates documentation. +`rustdoc` is also used by Cargo through `cargo doc`. -~~~ -# #![allow(unused_attribute)] -// the "link" crate attribute is currently required for rustdoc, but normally -// isn't needed. -#![crate_id = "universe"] -#![crate_type= "lib"] - -//! Tools for dealing with universes (this is a doc comment, and is shown on -//! the crate index page. The ! makes it apply to the parent of the comment, -//! rather than what follows). - -# mod workaround_the_outer_function_rustdoc_inserts { -/// Widgets are very common (this is a doc comment, and will show up on -/// Widget's documentation). -pub struct Widget { - /// All widgets have a purpose (this is a doc comment, and will show up - /// the field's documentation). - purpose: String, - /// Humans are not allowed to understand some widgets - understandable: bool +Documentation can be generated in two ways: from source code, and from +standalone Markdown files. + +## Documenting source code + +The primary way of documenting a Rust project is through annotating the source +code. You can use documentation comments for this purpose: + +```rust,ignore +/// Constructs a new `Rc`. +/// +/// # Examples +/// +/// ``` +/// use std::rc::Rc; +/// +/// let five = Rc::new(5); +/// ``` +pub fn new(value: T) -> Rc { + // implementation goes here +} +``` + +This code generates documentation that looks [like this][rc-new]. I've left the +implementation out, with a regular comment in its place. That's the first thing +to notice about this annotation: it uses `///`, instead of `//`. The triple slash +indicates a documentation comment. + +Documentation comments are written in Markdown. + +Rust keeps track of these comments, and uses them when generating +documentation. This is important when documenting things like enums: + +``` +/// The `Option` type. See [the module level documentation](../) for more. +enum Option { + /// No value + None, + /// Some value `T` + Some(T), } +``` + +The above works, but this does not: -pub fn recalibrate() { - //! Recalibrate a pesky universe (this is also a doc comment, like above, - //! the documentation will be applied to the *parent* item, so - //! `recalibrate`). - /* ... */ +```rust,ignore +/// The `Option` type. See [the module level documentation](../) for more. +enum Option { + None, /// No value + Some(T), /// Some value `T` } -# } -~~~ +``` -Documentation can also be controlled via the `doc` attribute on items. This is -implicitly done by the compiler when using the above form of doc comments -(converting the slash-based comments to `#[doc]` attributes). +You'll get an error: -~~~ -#[doc = " -Calculates the factorial of a number. +```text +hello.rs:4:1: 4:2 error: expected ident, found `}` +hello.rs:4 } + ^ +``` -Given the input integer `n`, this function will calculate `n!` and return it. -"] -pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n - 1)} } -# fn main() {} -~~~ +This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is +correct: documentation comments apply to the thing after them, and there's no +thing after that last comment. -The `doc` attribute can also be used to control how rustdoc emits documentation -in some cases. +[rc-new]: http://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new + +### Writing documentation comments + +Anyway, let's cover each part of this comment in detail: ``` -// Rustdoc will inline documentation of a `pub use` into this crate when the -// `pub use` reaches across crates, but this behavior can also be disabled. -#[doc(no_inline)] -pub use std::option::Option; -# fn main() {} +/// Constructs a new `Rc`. +# fn foo() {} ``` -Doc comments are markdown, and are currently parsed with the -[hoedown][hoedown] library. rustdoc does not yet do any fanciness such as -referencing other items inline, like javadoc's `@see`. One exception to this -is that the first paragraph will be used as the "summary" of an item in the -generated documentation: +The first line of a documentation comment should be a short summary of its +functionality. One sentence. Just the basics. High level. -~~~ -/// A whizbang. Does stuff. (this line is the summary) +``` /// -/// Whizbangs are ... -struct Whizbang; -~~~ +/// Other details about constructing `Rc`s, maybe describing complicated +/// semantics, maybe additional options, all kinds of stuff. +/// +# fn foo() {} +``` -To generate the docs, run `rustdoc universe.rs`. By default, it generates a -directory called `doc`, with the documentation for `universe` being in -`doc/universe/index.html`. If you are using other crates with `extern crate`, -rustdoc will even link to them when you use their types, as long as their -documentation has already been generated by a previous run of rustdoc, or the -crate advertises that its documentation is hosted at a given URL. +Our original example had just a summary line, but if we had more things to say, +we could have added more explanation in a new paragraph. -The generated output can be controlled with the `doc` crate attribute, which -is how the above advertisement works. An example from the `libstd` -documentation: +#### Special sections -~~~ -#[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/")]; -~~~ +``` +/// # Examples +# fn foo() {} +``` -The `html_root_url` is the prefix that rustdoc will apply to any references to -that crate's types etc. +Next, are special sections. These are indicated with a header, `#`. There +are three kinds of headers that are commonly used. They aren't special syntax, +just convention, for now. -rustdoc can also generate JSON, for consumption by other tools, with -`rustdoc --output-format json`, and also consume already-generated JSON with -`rustdoc --input-format json`. +``` +/// # Panics +# fn foo() {} +``` -rustdoc also supports personalizing the output from crates' documentation, -similar to markdown options. +Unrecoverable misuses of a function (i.e. programming errors) in Rust are +usually indicated by panics, which kill the whole current thread at the very +least. If your function has a non-trivial contract like this, that is +detected/enforced by panics, documenting it is very important. -- `--html-in-header FILE`: includes the contents of `FILE` at the - end of the `...` section. -- `--html-before-content FILE`: includes the contents of `FILE` - directly after ``, before the rendered content (including the - search bar). -- `--html-after-content FILE`: includes the contents of `FILE` - after all the rendered content. +``` +/// # Failures +# fn foo() {} +``` -# Using the Documentation +If your function or method returns a `Result`, then describing the +conditions under which it returns `Err(E)` is a nice thing to do. This is +slightly less important than `Panics`, because failure is encoded into the type +system, but it's still a good thing to do. -The web pages generated by rustdoc present the same logical hierarchy that one -writes a library with. Every kind of item (function, struct, etc) has its own -color, and one can always click on a colored type to jump to its -documentation. There is a search bar at the top, which is powered by some -JavaScript and a statically-generated search index. No special web server is -required for the search. +``` +/// # Safety +# fn foo() {} +``` -[hoedown]: https://github.com/hoedown/hoedown +If your function is `unsafe`, you should explain which invariants the caller is +responsible for upholding. -# Testing the Documentation +``` +/// # Examples +/// +/// ``` +/// use std::rc::Rc; +/// +/// let five = Rc::new(5); +/// ``` +# fn foo() {} +``` -`rustdoc` has support for testing code examples which appear in the -documentation. This is helpful for keeping code examples up to date with the -source code. +Third, `Examples`. Include one or more examples of using your function or +method, and your users will love you for it. These examples go inside of +code block annotations, which we'll talk about in a moment, and can have +more than one section: -To test documentation, the `--test` argument is passed to rustdoc: +``` +/// # Examples +/// +/// Simple `&str` patterns: +/// +/// ``` +/// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); +/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); +/// ``` +/// +/// More complex patterns with a lambda: +/// +/// ``` +/// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); +/// assert_eq!(v, vec!["abc", "def", "ghi"]); +/// ``` +# fn foo() {} +``` -~~~ {.sh} -rustdoc --test crate.rs -~~~ +Let's discuss the details of these code blocks. -## Defining tests +#### Code block annotations -Rust documentation currently uses the markdown format, and rustdoc treats all -code blocks as testable-by-default unless they carry a language tag of another -language. In order to not run a test over a block of code, the `ignore` string -can be added to the three-backtick form of markdown code block. +To write some Rust code in a comment, use the triple graves: -~~~md ``` -// This is a testable code block +/// ``` +/// println!("Hello, world"); +/// ``` +# fn foo() {} ``` -```rust{.example} -// This is rust and also testable +If you want something that's not Rust code, you can add an annotation: + +``` +/// ```c +/// printf("Hello, world\n"); +/// ``` +# fn foo() {} ``` -```ignore -// This is not a testable code block +This will highlight according to whatever language you're showing off. +If you're just showing plain text, choose `text`. + +It's important to choose the correct annotation here, because `rustdoc` uses it +in an interesting way: It can be used to actually test your examples, so that +they don't get out of date. If you have some C code but `rustdoc` thinks it's +Rust because you left off the annotation, `rustdoc` will complain when trying to +generate the documentation. + +## Documentation as tests + +Let's discuss our sample example documentation: + +``` +/// ``` +/// println!("Hello, world"); +/// ``` +# fn foo() {} ``` - // This is a testable code block (4-space indent) +You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will +automatically add a main() wrapper around your code, and in the right place. +For example: -```sh -# this is shell code and not tested ``` -~~~ +/// ``` +/// use std::rc::Rc; +/// +/// let five = Rc::new(5); +/// ``` +# fn foo() {} +``` -You can specify that the test's execution should fail with the `should_fail` -directive. +This will end up testing: -~~~md -```should_fail -// This code block is expected to generate a panic when run ``` -~~~ +fn main() { + use std::rc::Rc; + let five = Rc::new(5); +} +``` + +Here's the full algorithm rustdoc uses to postprocess examples: + +1. Any leading `#![foo]` attributes are left intact as crate attributes. +2. Some common `allow` attributes are inserted, including + `unused_variables`, `unused_assignments`, `unused_mut`, + `unused_attributes`, and `dead_code`. Small examples often trigger + these lints. +3. If the example does not contain `extern crate`, then `extern crate + ;` is inserted. +2. Finally, if the example does not contain `fn main`, the remainder of the + text is wrapped in `fn main() { your_code }` -You can specify that the code block should be compiled but not run with the -`no_run` directive. +Sometimes, this isn't enough, though. For example, all of these code samples +with `///` we've been talking about? The raw text: -~~~md -```no_run -// This code will be compiled but not executed +```text +/// Some documentation. +# fn foo() {} ``` -~~~ -Lastly, you can specify that a code block be compiled as if `--test` -were passed to the compiler using the `test_harness` directive. +looks different than the output: -~~~md -```test_harness -#[test] -fn foo() { - panic!("oops! (will run & register as a failed test)") -} ``` -~~~ +/// Some documentation. +# fn foo() {} +``` + +Yes, that's right: you can add lines that start with `# `, and they will +be hidden from the output, but will be used when compiling your code. You +can use this to your advantage. In this case, documentation comments need +to apply to some kind of function, so if I want to show you just a +documentation comment, I need to add a little function definition below +it. At the same time, it's just there to satisfy the compiler, so hiding +it makes the example more clear. You can use this technique to explain +longer examples in detail, while still preserving the testability of your +documentation. For example, this code: + +``` +let x = 5; +let y = 6; +println!("{}", x + y); +``` + +Here's an explanation, rendered: -Rustdoc also supplies some extra sugar for helping with some tedious -documentation examples. If a line is prefixed with `# `, then the line -will not show up in the HTML documentation, but it will be used when -testing the code block (NB. the space after the `#` is required, so -that one can still write things like `#[derive(Eq)]`). +First, we set `x` to five: -~~~md ``` -# /!\ The three following lines are comments, which are usually stripped off by -# the doc-generating tool. In order to display them anyway in this particular -# case, the character following the leading '#' is not a usual space like in -# these first five lines but a non breakable one. -# // showing 'fib' in this documentation would just be tedious and detracts from -# // what's actually being documented. -# fn fib(n: int) { n + 2 } +let x = 5; +# let y = 6; +# println!("{}", x + y); +``` + +Next, we set `y` to six: -spawn(move || { fib(200); }) ``` -~~~ +# let x = 5; +let y = 6; +# println!("{}", x + y); +``` -The documentation online would look like `spawn(move || { fib(200); })`, but when -testing this code, the `fib` function will be included (so it can compile). +Finally, we print the sum of `x` and `y`: -Rustdoc will automatically add a `main()` wrapper around your code, and in the right -place. For example: +``` +# let x = 5; +# let y = 6; +println!("{}", x + y); +``` + +Here's the same explanation, in raw text: + +> First, we set `x` to five: +> +> ```text +> let x = 5; +> # let y = 6; +> # println!("{}", x + y); +> ``` +> +> Next, we set `y` to six: +> +> ```text +> # let x = 5; +> let y = 6; +> # println!("{}", x + y); +> ``` +> +> Finally, we print the sum of `x` and `y`: +> +> ```text +> # let x = 5; +> # let y = 6; +> println!("{}", x + y); +> ``` + +By repeating all parts of the example, you can ensure that your example still +compiles, while only showing the parts that are relevant to that part of your +explanation. + +### Documenting macros + +Here’s an example of documenting a macro: ``` +/// Panic with a given message unless an expression evaluates to true. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate foo; +/// # fn main() { +/// panic_unless!(1 + 1 == 2, “Math is broken.”); +/// # } /// ``` -/// use std::rc::Rc; /// -/// let five = Rc::new(5); +/// ```should_panic +/// # #[macro_use] extern crate foo; +/// # fn main() { +/// panic_unless!(true == false, “I’m broken.”); +/// # } +/// ``` +#[macro_export] +macro_rules! panic_unless { + ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); +} +# fn main() {} +``` + +You’ll note three things: we need to add our own `extern crate` line, so that +we can add the `#[macro_use]` attribute. Second, we’ll need to add our own +`main()` as well. Finally, a judicious use of `#` to comment out those two +things, so they don’t show up in the output. + +### Running documentation tests + +To run the tests, either + +```bash +$ rustdoc --test path/to/my/crate/root.rs +# or +$ cargo test +``` + +That's right, `cargo test` tests embedded documentation too. + +There are a few more annotations that are useful to help `rustdoc` do the right +thing when testing your code: + +``` +/// ```ignore +/// fn foo() { /// ``` # fn foo() {} ``` -This will end up testing: +The `ignore` directive tells Rust to ignore your code. This is almost never +what you want, as it's the most generic. Instead, consider annotating it +with `text` if it's not code, or using `#`s to get a working example that +only shows the part you care about. ``` -fn main() { - use std::rc::Rc; - let five = Rc::new(5); +/// ```should_panic +/// assert!(false); +/// ``` +# fn foo() {} +``` + +`should_panic` tells `rustdoc` that the code should compile correctly, but +not actually pass as a test. + +``` +/// ```no_run +/// loop { +/// println!("Hello, world"); +/// } +/// ``` +# fn foo() {} +``` + +The `no_run` attribute will compile your code, but not run it. This is +important for examples such as "Here's how to start up a network service," +which you would want to make sure compile, but might run in an infinite loop! + +### Documenting modules + +Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words: + +``` +mod foo { + //! This is documentation for the `foo` module. + //! + //! # Examples + + // ... } ``` -Here's the full algorithm: +This is where you'll see `//!` used most often: for module documentation. If +you have a module in `foo.rs`, you'll often open its code and see this: + +``` +//! A module for using `foo`s. +//! +//! The `foo` module contains a lot of useful functionality blah blah blah +``` + +### Documentation comment style + +Check out [RFC 505][rfc505] for full conventions around the style and format of +documentation. -1. Given a code block, if it does not contain `fn main`, it is wrapped in `fn main() { your_code }` -2. Given that result, if it contains no `extern crate` directives but it also - contains the name of the crate being tested, then `extern crate ` is - injected at the top. -3. Some common `allow` attributes are added for documentation examples at the top. +[rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md + +## Other documentation + +All of this behavior works in non-Rust source files too. Because comments +are written in Markdown, they're often `.md` files. + +When you write documentation in Markdown files, you don't need to prefix +the documentation with comments. For example: + +``` +/// # Examples +/// +/// ``` +/// use std::rc::Rc; +/// +/// let five = Rc::new(5); +/// ``` +# fn foo() {} +``` -## Running tests (advanced) +is just -Running tests often requires some special configuration to filter tests, find -libraries, or try running ignored examples. The testing framework that rustdoc -uses is built on crate `test`, which is also used when you compile crates with -rustc's `--test` flag. Extra arguments can be passed to rustdoc's test harness -with the `--test-args` flag. +~~~markdown +# Examples -~~~console -# Only run tests containing 'foo' in their name -$ rustdoc --test lib.rs --test-args 'foo' +``` +use std::rc::Rc; -# See what's possible when running tests -$ rustdoc --test lib.rs --test-args '--help' +let five = Rc::new(5); +``` ~~~ -When testing a library, code examples will often show how functions are used, -and this code often requires `use`-ing paths from the crate. To accommodate this, -rustdoc will implicitly add `extern crate ;` where `` is the name of -the crate being tested to the top of each code example. This means that rustdoc -must be able to find a compiled version of the library crate being tested. Extra -search paths may be added via the `-L` flag to `rustdoc`. +when it's in a Markdown file. There is one wrinkle though: Markdown files need +to have a title like this: -# Standalone Markdown files +```markdown +% The title -As well as Rust crates, rustdoc supports rendering pure Markdown files -into HTML and testing the code snippets from them. A Markdown file is -detected by a `.md` or `.markdown` extension. +This is the example documentation. +``` -There are 4 options to modify the output that Rustdoc creates. +This `%` line needs to be the very first line of the file. -- `--markdown-css PATH`: adds a `` tag pointing to `PATH`. -- `--html-in-header FILE`: includes the contents of `FILE` at the - end of the `...` section. -- `--html-before-content FILE`: includes the contents of `FILE` - directly after ``, before the rendered content (including the - title). -- `--html-after-content FILE`: includes the contents of `FILE` - directly before ``, after all the rendered content. +## `doc` attributes -All of these can be specified multiple times, and they are output in -the order in which they are specified. The first line of the file being rendered must -be the title, prefixed with `%` (e.g. this page has `% Rust -Documentation` on the first line). +At a deeper level, documentation comments are sugar for documentation attributes: + +``` +/// this +# fn foo() {} -Like with a Rust crate, the `--test` argument will run the code -examples to check they compile, and obeys any `--test-args` flags. The -tests are named after the last `#` heading. +#[doc="this"] +# fn bar() {} +``` + +are the same, as are these: + +``` +//! this + +#![doc="/// this"] +``` -# Re-exports +You won't often see this attribute used for writing documentation, but it +can be useful when changing some options, or when writing a macro. -Rustdoc will show the documentation for a publc re-export in both places: +### Re-exports -```{rust,ignore} +`rustdoc` will show the documentation for a public re-export in both places: + +```ignore extern crate foo; pub use foo::bar; ``` -This will create documentation for `bar` both inside the documentation for -the crate `foo`, as well as the documentation for your crate. It will use -the same documentation in both places. +This will create documentation for bar both inside the documentation for the +crate `foo`, as well as the documentation for your crate. It will use the same +documentation in both places. -This behavior can be supressed with `no_inline`: +This behavior can be suppressed with `no_inline`: -```{rust,ignore} +```ignore extern crate foo; #[doc(no_inline)] pub use foo::bar; ``` + +### Controlling HTML + +You can control a few aspects of the HTML that `rustdoc` generates through the +`#![doc]` version of the attribute: + +``` +#![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/")]; +``` + +This sets a few different options, with a logo, favicon, and a root URL. + +## Generation options + +`rustdoc` also contains a few other options on the command line, for further customiziation: + +- `--html-in-header FILE`: includes the contents of FILE at the end of the + `...` section. +- `--html-before-content FILE`: includes the contents of FILE directly after + ``, before the rendered content (including the search bar). +- `--html-after-content FILE`: includes the contents of FILE after all the rendered content. diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 68b36e7a4b..b9e7bd78c5 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -200,15 +200,15 @@ Because these kinds of situations are relatively rare, use panics sparingly. # Upgrading failures to panics In certain circumstances, even though a function may fail, we may want to treat -it as a panic instead. For example, `io::stdin().read_line()` returns an -`IoResult`, a form of `Result`, when there is an error reading the -line. This allows us to handle and possibly recover from this sort of error. +it as a panic instead. For example, `io::stdin().read_line(&mut buffer)` returns +an `Result`, when there is an error reading the line. This allows us to +handle and possibly recover from error. If we don't want to handle this error, and would rather just abort the program, we can use the `unwrap()` method: ```{rust,ignore} -io::stdin().read_line().unwrap(); +io::stdin().read_line(&mut buffer).unwrap(); ``` `unwrap()` will `panic!` if the `Option` is `None`. This basically says "Give @@ -219,10 +219,83 @@ shorter. Sometimes, just crashing is appropriate. There's another way of doing this that's a bit nicer than `unwrap()`: ```{rust,ignore} -let input = io::stdin().read_line() +let mut buffer = String::new(); +let input = io::stdin().read_line(&mut buffer) .ok() .expect("Failed to read line"); ``` -`ok()` converts the `IoResult` into an `Option`, and `expect()` does the same + +`ok()` converts the `Result` into an `Option`, and `expect()` does the same thing as `unwrap()`, but takes a message. This message is passed along to the underlying `panic!`, providing a better error message if the code errors. + +# Using `try!` + +When writing code that calls many functions that return the `Result` type, the +error handling can be tedious. The `try!` macro hides some of the boilerplate +of propagating errors up the call stack. + +It replaces this: + +```rust +use std::fs::File; +use std::io; +use std::io::prelude::*; + +struct Info { + name: String, + age: i32, + rating: i32, +} + +fn write_info(info: &Info) -> io::Result<()> { + let mut file = File::open("my_best_friends.txt").unwrap(); + + if let Err(e) = writeln!(&mut file, "name: {}", info.name) { + return Err(e) + } + if let Err(e) = writeln!(&mut file, "age: {}", info.age) { + return Err(e) + } + if let Err(e) = writeln!(&mut file, "rating: {}", info.rating) { + return Err(e) + } + + return Ok(()); +} +``` + +With this: + +```rust +use std::fs::File; +use std::io; +use std::io::prelude::*; + +struct Info { + name: String, + age: i32, + rating: i32, +} + +fn write_info(info: &Info) -> io::Result<()> { + let mut file = try!(File::open("my_best_friends.txt")); + + try!(writeln!(&mut file, "name: {}", info.name)); + try!(writeln!(&mut file, "age: {}", info.age)); + try!(writeln!(&mut file, "rating: {}", info.rating)); + + return Ok(()); +} +``` + +Wrapping an expression in `try!` will result in the unwrapped success (`Ok`) +value, unless the result is `Err`, in which case `Err` is returned early from +the enclosing function. + +It's worth noting that you can only use `try!` from a function that returns a +`Result`, which means that you cannot use `try!` inside of `main()`, because +`main()` doesn't return anything. + +`try!` makes use of [`FromError`](../std/error/#the-fromerror-trait) to determine +what to return in the error case. diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md index 97e826579f..23f6e17b86 100644 --- a/src/doc/trpl/ffi.md +++ b/src/doc/trpl/ffi.md @@ -12,6 +12,7 @@ The following is a minimal example of calling a foreign function which will compile if snappy is installed: ```no_run +# #![feature(libc)] extern crate libc; use libc::size_t; @@ -45,6 +46,7 @@ keeping the binding correct at runtime. The `extern` block can be extended to cover the entire snappy API: ```no_run +# #![feature(libc)] extern crate libc; use libc::{c_int, size_t}; @@ -80,6 +82,7 @@ length is number of elements currently contained, and the capacity is the total the allocated memory. The length is less than or equal to the capacity. ``` +# #![feature(libc)] # extern crate libc; # use libc::{c_int, size_t}; # unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 } @@ -104,6 +107,7 @@ required capacity to hold the compressed output. The vector can then be passed t the true length after compression for setting the length. ``` +# #![feature(libc)] # extern crate libc; # use libc::{size_t, c_int}; # unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8, @@ -130,6 +134,7 @@ Decompression is similar, because snappy stores the uncompressed size as part of format and `snappy_uncompressed_length` will retrieve the exact buffer size required. ``` +# #![feature(libc)] # extern crate libc; # use libc::{size_t, c_int}; # unsafe fn snappy_uncompress(compressed: *const u8, @@ -170,6 +175,8 @@ Foreign libraries often hand off ownership of resources to the calling code. When this occurs, we must use Rust's destructors to provide safety and guarantee the release of these resources (especially in the case of panic). +For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). + # Callbacks from C code to Rust functions Some external libraries require the usage of callbacks to report back their @@ -359,31 +366,6 @@ A few examples of how this model can be used are: On OSX, frameworks behave with the same semantics as a dynamic library. -## The `link_args` attribute - -There is one other way to tell rustc how to customize linking, and that is via -the `link_args` attribute. This attribute is applied to `extern` blocks and -specifies raw flags which need to get passed to the linker when producing an -artifact. An example usage would be: - -``` no_run -#![feature(link_args)] - -#[link_args = "-foo -bar -baz"] -extern {} -# fn main() {} -``` - -Note that this feature is currently hidden behind the `feature(link_args)` gate -because this is not a sanctioned way of performing linking. Right now rustc -shells out to the system linker, so it makes sense to provide extra command line -arguments, but this will not always be the case. In the future rustc may use -LLVM directly to link native libraries in which case `link_args` will have no -meaning. - -It is highly recommended to *not* use this attribute, and rather use the more -formal `#[link(...)]` attribute on `extern` blocks instead. - # Unsafe blocks Some operations, like dereferencing unsafe pointers or calling functions that have been marked @@ -394,7 +376,7 @@ Unsafe functions, on the other hand, advertise it to the world. An unsafe functi this: ``` -unsafe fn kaboom(ptr: *const int) -> int { *ptr } +unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } ``` This function can only be called from an `unsafe` block or another `unsafe` function. @@ -406,6 +388,7 @@ global state. In order to access these variables, you declare them in `extern` blocks with the `static` keyword: ```no_run +# #![feature(libc)] extern crate libc; #[link(name = "readline")] @@ -415,7 +398,7 @@ extern { fn main() { println!("You have readline version {} installed.", - rl_readline_version as int); + rl_readline_version as i32); } ``` @@ -424,6 +407,7 @@ interface. To do this, statics can be declared with `mut` so we can mutate them. ```no_run +# #![feature(libc)] extern crate libc; use std::ffi::CString; @@ -456,6 +440,7 @@ calling foreign functions. Some foreign functions, most notably the Windows API, conventions. Rust provides a way to tell the compiler which convention to use: ``` +# #![feature(libc)] extern crate libc; #[cfg(all(target_os = "win32", target_arch = "x86"))] @@ -543,4 +528,3 @@ The `extern` makes this function adhere to the C calling convention, as discussed above in "[Foreign Calling Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` attribute turns off Rust's name mangling, so that it is easier to link to. - diff --git a/src/doc/trpl/functions.md b/src/doc/trpl/functions.md index ca1385fde9..8e8ee8d63d 100644 --- a/src/doc/trpl/functions.md +++ b/src/doc/trpl/functions.md @@ -179,7 +179,7 @@ Because this function will cause a crash, it will never return, and so it has the type '`!`', which is read "diverges." A diverging function can be used as any type: -```should_fail +```should_panic # fn diverges() -> ! { # panic!("This function never returns!"); # } diff --git a/src/doc/trpl/glossary.md b/src/doc/trpl/glossary.md index 156f337486..9789832484 100644 --- a/src/doc/trpl/glossary.md +++ b/src/doc/trpl/glossary.md @@ -14,3 +14,26 @@ let z = (8, 2, 6); ``` In the example above `x` and `y` have arity 2. `z` has arity 3. + +### Abstract Syntax Tree + +When a compiler is compiling your program, it does a number of different +things. One of the things that it does is turn the text of your program into an +'abstract syntax tree,' or 'AST.' This tree is a representation of the +structure of your program. For example, `2 + 3` can be turned into a tree: + +```text + + + / \ +2 3 +``` + +And `2 + (3 * 4)` would look like this: + +```text + + + / \ +2 * + / \ + 3 4 +``` diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md deleted file mode 100644 index 01f270f195..0000000000 --- a/src/doc/trpl/guessing-game.md +++ /dev/null @@ -1,893 +0,0 @@ -% Guessing Game - -Okay! We've got the basics of Rust down. Let's write a bigger program. - -For our first project, we'll implement a classic beginner programming problem: -the guessing game. Here's how it works: Our program will generate a random -integer between one and a hundred. It will then prompt us to enter a guess. -Upon entering our guess, it will tell us if we're too low or too high. Once we -guess correctly, it will congratulate us. Sound good? - -## Set up - -Let's set up a new project. Go to your projects directory. Remember how we -had to create our directory structure and a `Cargo.toml` for `hello_world`? Cargo -has a command that does that for us. Let's give it a shot: - -```{bash} -$ cd ~/projects -$ cargo new guessing_game --bin -$ cd guessing_game -``` - -We pass the name of our project to `cargo new`, and then the `--bin` flag, -since we're making a binary, rather than a library. - -Check out the generated `Cargo.toml`: - -```toml -[package] - -name = "guessing_game" -version = "0.0.1" -authors = ["Your Name "] -``` - -Cargo gets this information from your environment. If it's not correct, go ahead -and fix that. - -Finally, Cargo generated a "Hello, world!" for us. Check out `src/main.rs`: - -```{rust} -fn main() { - println!("Hello, world!") -} -``` - -Let's try compiling what Cargo gave us: - -```{bash} -$ cargo build - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) -``` - -Excellent! Open up your `src/main.rs` again. We'll be writing all of -our code in this file. We'll talk about multiple-file projects later on in the -guide. - -Before we move on, let me show you one more Cargo command: `run`. `cargo run` -is kind of like `cargo build`, but it also then runs the produced executable. -Try it out: - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Hello, world! -``` - -Great! The `run` command comes in handy when you need to rapidly iterate on a project. -Our game is just such a project, we need to quickly test each iteration before moving on to the next one. - -## Processing a Guess - -Let's get to it! The first thing we need to do for our guessing game is -allow our player to input a guess. Put this in your `src/main.rs`: - -```{rust,no_run} -use std::old_io; - -fn main() { - println!("Guess the number!"); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - - println!("You guessed: {}", input); -} -``` - -You've seen this code before, when we talked about standard input. We -import the `std::io` module with `use`, and then our `main` function contains -our program's logic. We print a little message announcing the game, ask the -user to input a guess, get their input, and then print it out. - -Because we talked about this in the section on standard I/O, I won't go into -more details here. If you need a refresher, go re-read that section. - -## Generating a secret number - -Next, we need to generate a secret number. To do that, we need to use Rust's -random number generation, which we haven't talked about yet. Rust includes a -bunch of interesting functions in its standard library. If you need a bit of -code, it's possible that it's already been written for you! In this case, -we do know that Rust has random number generation, but we don't know how to -use it. - -Enter the docs. Rust has a page specifically to document the standard library. -You can find that page [here](../std/index.html). There's a lot of information on -that page, but the best part is the search bar. Right up at the top, there's -a box that you can enter in a search term. The search is pretty primitive -right now, but is getting better all the time. If you type "random" in that -box, the page will update to [this one](../std/index.html?search=random). The very -first result is a link to [`std::rand::random`](../std/rand/fn.random.html). If we -click on that result, we'll be taken to its documentation page. - -This page shows us a few things: the type signature of the function, some -explanatory text, and then an example. Let's try to modify our code to add in the -`random` function and see what happens: - -```{rust,ignore} -use std::old_io; -use std::rand; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random() % 100) + 1; // secret_number: i32 - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - - - println!("You guessed: {}", input); -} -``` - -The first thing we changed was to `use std::rand`, as the docs -explained. We then added in a `let` expression to create a variable binding -named `secret_number`, and we printed out its result. - -Also, you may wonder why we are using `%` on the result of `rand::random()`. -This operator is called *modulo*, and it returns the remainder of a division. -By taking the modulo of the result of `rand::random()`, we're limiting the -values to be between 0 and 99. Then, we add one to the result, making it from 1 -to 100. Using modulo can give you a very, very small bias in the result, but -for this example, it is not important. - -Let's try to compile this using `cargo build`: - -```bash -$ 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() % 100) + 1; - ^~~~~~~~ -error: aborting due to previous error -``` - -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 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::(); -``` - -This says "please give me a random `i32` value." We can change our code to use -this hint: - -```{rust,no_run} -use std::old_io; -use std::rand; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - - - println!("You guessed: {}", input); -} -``` - -Try running our new program a few times: - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Guess the number! -The secret number is: 7 -Please input your guess. -4 -You guessed: 4 -$ ./target/guessing_game -Guess the number! -The secret number is: 83 -Please input your guess. -5 -You guessed: 5 -$ ./target/guessing_game -Guess the number! -The secret number is: -29 -Please input your guess. -42 -You guessed: 42 -``` - -Wait. Negative 29? We wanted a number between one and a hundred! We have two -options here: we can either ask `random()` to generate an unsigned integer, which -can only be positive, or we can use the `abs()` function. Let's go with the -unsigned integer approach. If we want a random positive number, we should ask for -a random positive number. Our code looks like this now: - -```{rust,no_run} -use std::old_io; -use std::rand; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - - - println!("You guessed: {}", input); -} -``` - -And trying it out: - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Guess the number! -The secret number is: 57 -Please input your guess. -3 -You guessed: 3 -``` - -Great! Next up: let's compare our guess to the secret guess. - -## Comparing guesses - -If you remember, earlier in the guide, we made a `cmp` function that compared -two numbers. Let's add that in, along with a `match` statement to compare our -guess to the secret number: - -```{rust,ignore} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - - - println!("You guessed: {}", input); - - match cmp(input, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} - -fn cmp(a: i32, b: i32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -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 `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 `i32` but found `u32` (expected i32 but found u32) -src/main.rs:20 match cmp(input, secret_number) { - ^~~~~~~~~~~~~ -error: aborting due to 2 previous errors -``` - -This often happens when writing Rust programs, and is one of Rust's greatest -strengths. You try out some code, see if it compiles, and Rust tells you that -you've done something wrong. In this case, our `cmp` function works on integers, -but we've given it unsigned integers. In this case, the fix is easy, because -we wrote the `cmp` function! Let's change it to take `u32`s: - -```{rust,ignore} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - - - println!("You guessed: {}", input); - - match cmp(input, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -And try compiling again: - -```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 `u32` but found `collections::string::String` (expected u32 but found struct collections::string::String) -src/main.rs:20 match cmp(input, secret_number) { - ^~~~~ -error: aborting due to previous error -``` - -This error is similar to the last one: we expected to get a `u32`, but we got -a `String` instead! That's because our `input` variable is coming from the -standard input, and you can guess anything. Try it: - -```bash -$ ./target/guessing_game -Guess the number! -The secret number is: 73 -Please input your guess. -hello -You guessed: hello -``` - -Oops! Also, you'll note that we just ran our program even though it didn't compile. -This works because the older version we did successfully compile was still lying -around. Gotta be careful! - -Anyway, we have a `String`, but we need a `u32`. What to do? Well, there's -a function for that: - -```{rust,ignore} -let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); -let input_num: Result = input.parse(); -``` - -The `parse` function takes in a `&str` value and converts it into something. -We tell it what kind of something with a type hint. Remember our type hint with -`random()`? It looked like this: - -```{rust,ignore} -rand::random::(); -``` - -There's an alternate way of providing a hint too, and that's declaring the type -in a `let`: - -```{rust,ignore} -let x: u32 = rand::random(); -``` - -In this case, we say `x` is a `u32` explicitly, so Rust is able to properly -tell `random()` what to generate. In a similar fashion, both of these work: - -```{rust,ignore} -let input_num = "5".parse::(); // input_num: Option -let input_num: Result = "5".parse(); // input_num: Result::Err> -``` - -Here we're converting the `Result` returned by `parse` to an `Option` by using -the `ok` method as well. Anyway, with us now converting our input to a number, -our code looks like this: - -```{rust,ignore} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.parse(); - - println!("You guessed: {:?}", input_num); - - match cmp(input_num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -Let's try it out! - -```bash -$ cargo build - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) -src/main.rs:22:15: 22:24 error: mismatched types: expected `u32` but found `core::option::Option` (expected u32 but found enum core::option::Option) -src/main.rs:22 match cmp(input_num, secret_number) { - ^~~~~~~~~ -error: aborting due to previous error -``` - -Oh yeah! Our `input_num` has the type `Option`, rather than `u32`. We -need to unwrap the Option. If you remember from before, `match` is a great way -to do that. Try this code: - -```{rust,no_run} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.parse(); - - let num = match input_num { - Ok(num) => num, - Err(_) => { - println!("Please input a number!"); - return; - } - }; - - - println!("You guessed: {}", num); - - match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -We use a `match` to either give us the `u32` inside of the `Option`, or else -print an error message and return. Let's give this a shot: - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Guess the number! -The secret number is: 17 -Please input your guess. -5 -Please input a number! -``` - -Uh, what? But we did! - -... actually, we didn't. See, when you get a line of input from `stdin()`, -you get all the input. Including the `\n` character from you pressing Enter. -Therefore, `parse()` sees the string `"5\n"` and says "nope, that's not a -number; there's non-number stuff in there!" Luckily for us, `&str`s have an easy -method we can use defined on them: `trim()`. One small modification, and our -code looks like this: - -```{rust,no_run} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.trim().parse(); - - let num = match input_num { - Ok(num) => num, - Err(_) => { - println!("Please input a number!"); - return; - } - }; - - - println!("You guessed: {}", num); - - match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -Let's try it! - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Guess the number! -The secret number is: 58 -Please input your guess. - 76 -You guessed: 76 -Too big! -``` - -Nice! You can see I even added spaces before my guess, and it still figured -out that I guessed 76. Run the program a few times, and verify that guessing -the number works, as well as guessing a number too small. - -The Rust compiler helped us out quite a bit there! This technique is called -"leaning on the compiler", and it's often useful when working on some code. -Let the error messages help guide you towards the correct types. - -Now we've got most of the game working, but we can only make one guess. Let's -change that by adding loops! - -## Looping - -As we already discussed, the `loop` keyword gives us an infinite loop. -Let's add that in: - -```{rust,no_run} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - loop { - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.trim().parse(); - - let num = match input_num { - Ok(num) => num, - Err(_) => { - println!("Please input a number!"); - return; - } - }; - - - println!("You guessed: {}", num); - - match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), - } - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -And try it out. But wait, didn't we just add an infinite loop? Yup. Remember -that `return`? If we give a non-number answer, we'll `return` and quit. Observe: - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Guess the number! -The secret number is: 59 -Please input your guess. -45 -You guessed: 45 -Too small! -Please input your guess. -60 -You guessed: 60 -Too big! -Please input your guess. -59 -You guessed: 59 -You win! -Please input your guess. -quit -Please input a number! -``` - -Ha! `quit` actually quits. As does any other non-number input. Well, this is -suboptimal to say the least. First, let's actually quit when you win the game: - -```{rust,no_run} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - loop { - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.trim().parse(); - - let num = match input_num { - Ok(num) => num, - Err(_) => { - println!("Please input a number!"); - return; - } - }; - - - println!("You guessed: {}", num); - - match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - return; - }, - } - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -By adding the `return` line after the `You win!`, we'll exit the program when -we win. We have just one more tweak to make: when someone inputs a non-number, -we don't want to quit, we just want to ignore it. Change that `return` to -`continue`: - - -```{rust,no_run} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - println!("The secret number is: {}", secret_number); - - loop { - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.trim().parse(); - - let num = match input_num { - Ok(num) => num, - Err(_) => { - println!("Please input a number!"); - continue; - } - }; - - - println!("You guessed: {}", num); - - match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - return; - }, - } - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -Now we should be good! Let's try: - -```bash -$ cargo run - Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) - Running `target/guessing_game` -Guess the number! -The secret number is: 61 -Please input your guess. -10 -You guessed: 10 -Too small! -Please input your guess. -99 -You guessed: 99 -Too big! -Please input your guess. -foo -Please input a number! -Please input your guess. -61 -You guessed: 61 -You win! -``` - -Awesome! With one tiny last tweak, we have finished the guessing game. Can you -think of what it is? That's right, we don't want to print out the secret number. -It was good for testing, but it kind of ruins the game. Here's our final source: - -```{rust,no_run} -use std::old_io; -use std::rand; -use std::cmp::Ordering; - -fn main() { - println!("Guess the number!"); - - let secret_number = (rand::random::() % 100) + 1; - - loop { - - println!("Please input your guess."); - - let input = old_io::stdin().read_line() - .ok() - .expect("Failed to read line"); - let input_num: Result = input.trim().parse(); - - let num = match input_num { - Ok(num) => num, - Err(_) => { - println!("Please input a number!"); - continue; - } - }; - - - println!("You guessed: {}", num); - - match cmp(num, secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - return; - }, - } - } -} - -fn cmp(a: u32, b: u32) -> Ordering { - if a < b { Ordering::Less } - else if a > b { Ordering::Greater } - else { Ordering::Equal } -} -``` - -## Complete! - -At this point, you have successfully built the Guessing Game! Congratulations! - -You've now learned the basic syntax of Rust. All of this is relatively close to -various other programming languages you have used in the past. These -fundamental syntactical and semantic elements will form the foundation for the -rest of your Rust education. - -Now that you're an expert at the basics, it's time to learn about some of -Rust's more unique features. diff --git a/src/doc/trpl/hello-cargo.md b/src/doc/trpl/hello-cargo.md index 5eb6cd7c5c..b45211e3a0 100644 --- a/src/doc/trpl/hello-cargo.md +++ b/src/doc/trpl/hello-cargo.md @@ -18,13 +18,15 @@ the Cargo README](https://github.com/rust-lang/cargo#installing-cargo-from-nightlies) for specific instructions about installing it. +## Converting to Cargo + 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: -```{bash} +```bash $ mkdir src $ mv main.rs src/main.rs ``` @@ -36,7 +38,7 @@ place for everything, and everything in its place. Next, our configuration file: -```{bash} +```bash $ editor Cargo.toml ``` @@ -73,19 +75,21 @@ well as what it is named. Once you have this file in place, we should be ready to build! Try this: -```{bash} +```bash $ cargo build Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) -$ ./target/hello_world +$ ./target/debug/hello_world 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 +`./target/debug/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` more than once, 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. +just `cargo build`, and it'll work the right way. When your project is finally +ready for release, you can use `cargo build --release` to compile your crates with +optimizations. You'll also notice that Cargo has created a new file: `Cargo.lock`. @@ -103,6 +107,62 @@ That's it! We've successfully built `hello_world` with Cargo. Even though our program is simple, it's using much of the real tooling that you'll use for the rest of your Rust career. +## A New Project + +You don't have to go through this whole process every time you want to start a new +project! Cargo has the ability to make a bare-bones project directory in which you +can start developing right away. + +To start a new project with Cargo, use `cargo new`: + +```bash +$ cargo new hello_world --bin +``` + +We're passing `--bin` because we're making a binary program: if we +were making a library, we'd leave it off. + +Let's check out what Cargo has generated for us: + +```bash +$ cd hello_world +$ tree . +. +├── Cargo.toml +└── src + └── main.rs + +1 directory, 2 files +``` + +If you don't have the `tree` command, you can probably get it from your distro's package +manager. It's not necessary, but it's certainly useful. + +This is all we need to get started. First, let's check out `Cargo.toml`: + +```toml +[package] + +name = "hello_world" +version = "0.0.1" +authors = ["Your Name "] +``` + +Cargo has populated this file with reasonable defaults based off the arguments you gave +it and your `git` global configuration. You may notice that Cargo has also initialized +the `hello_world` directory as a `git` repository. + +Here's what's in `src/main.rs`: + +```rust +fn main() { + println!("Hello, world!"); +} +``` + +Cargo has generated a "Hello World!" for us, and you're ready to start coding! A +much more in-depth guide to Cargo can be found [here](http://doc.crates.io/guide.html). + Now that you've got the tools down, let's actually learn more about the Rust language itself. These are the basics that will serve you well through the rest of your time with Rust. diff --git a/src/doc/trpl/if.md b/src/doc/trpl/if.md index a350df67b1..7dac49987d 100644 --- a/src/doc/trpl/if.md +++ b/src/doc/trpl/if.md @@ -34,6 +34,20 @@ if x == 5 { } ``` +If there is more than one case, use an `else if`: + +```rust +let x = 5; + +if x == 5 { + println!("x is five!"); +} else if x == 6 { + println!("x is six!"); +} else { + println!("x is not five or six :("); +} +``` + This is all pretty standard. However, you can also do this: diff --git a/src/doc/trpl/inline-assembly.md b/src/doc/trpl/inline-assembly.md new file mode 100644 index 0000000000..1a4592f980 --- /dev/null +++ b/src/doc/trpl/inline-assembly.md @@ -0,0 +1,141 @@ +% Inline Assembly + +For extremely low-level manipulations and performance reasons, one +might wish to control the CPU directly. Rust supports using inline +assembly to do this via the `asm!` macro. The syntax roughly matches +that of GCC & Clang: + +```ignore +asm!(assembly template + : output operands + : input operands + : clobbers + : options + ); +``` + +Any use of `asm` is feature gated (requires `#![feature(asm)]` on the +crate to allow) and of course requires an `unsafe` block. + +> **Note**: the examples here are given in x86/x86-64 assembly, but +> all platforms are supported. + +## Assembly template + +The `assembly template` is the only required parameter and must be a +literal string (i.e. `""`) + +``` +#![feature(asm)] + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn foo() { + unsafe { + asm!("NOP"); + } +} + +// other platforms +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +fn foo() { /* ... */ } + +fn main() { + // ... + foo(); + // ... +} +``` + +(The `feature(asm)` and `#[cfg]`s are omitted from now on.) + +Output operands, input operands, clobbers and options are all optional +but you must add the right number of `:` if you skip them: + +``` +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { unsafe { +asm!("xor %eax, %eax" + : + : + : "eax" + ); +# } } +``` + +Whitespace also doesn't matter: + +``` +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { unsafe { +asm!("xor %eax, %eax" ::: "eax"); +# } } +``` + +## Operands + +Input and output operands follow the same format: `: +"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand +expressions must be mutable lvalues: + +``` +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn add(a: i32, b: i32) -> i32 { + let mut c = 0; + unsafe { + asm!("add $2, $0" + : "=r"(c) + : "0"(a), "r"(b) + ); + } + c +} +# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +# fn add(a: i32, b: i32) -> i32 { a + b } + +fn main() { + assert_eq!(add(3, 14159), 14162) +} +``` + +## Clobbers + +Some instructions modify registers which might otherwise have held +different values so we use the clobbers list to indicate to the +compiler not to assume any values loaded into those registers will +stay valid. + +``` +# #![feature(asm)] +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +# fn main() { unsafe { +// Put the value 0x200 in eax +asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); +# } } +``` + +Input and output registers need not be listed since that information +is already communicated by the given constraints. Otherwise, any other +registers used either implicitly or explicitly should be listed. + +If the assembly changes the condition code register `cc` should be +specified as one of the clobbers. Similarly, if the assembly modifies +memory, `memory` should also be specified. + +## Options + +The last section, `options` is specific to Rust. The format is comma +separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to +specify some extra info about the inline assembly: + +Current valid options are: + +1. *volatile* - specifying this is analogous to + `__asm__ __volatile__ (...)` in gcc/clang. +2. *alignstack* - certain instructions expect the stack to be + aligned a certain way (i.e. SSE) and specifying this indicates to + the compiler to insert its usual stack alignment code +3. *intel* - use intel syntax instead of the default AT&T. + diff --git a/src/doc/trpl/installing-rust.md b/src/doc/trpl/installing-rust.md index 5bc33d0a23..288a4a158f 100644 --- a/src/doc/trpl/installing-rust.md +++ b/src/doc/trpl/installing-rust.md @@ -6,14 +6,14 @@ 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 -sf -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 +$ curl -f -L https://static.rust-lang.org/rustup.sh -O $ sudo sh rustup.sh ``` @@ -70,14 +70,19 @@ If you've got Rust installed, you can open up a shell, and type this: $ rustc --version ``` -You should see some output that looks something like this: +You should see the version number, commit hash, commit date and build date: ```bash -rustc 1.0.0-nightly (f11f3e7ba 2015-01-04 20:02:14 +0000) +rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06) ``` If you did, Rust has been installed successfully! Congrats! +This installer also installs a copy of the documentation locally, so you can +read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. +On Windows, it's in a `share/doc` directory, inside wherever you installed Rust +to. + If not, there are a number of places where you can get help. The easiest is [the #rust IRC channel on irc.mozilla.org](irc://irc.mozilla.org/#rust), which you can access through diff --git a/src/doc/trpl/intrinsics.md b/src/doc/trpl/intrinsics.md new file mode 100644 index 0000000000..25f7c54493 --- /dev/null +++ b/src/doc/trpl/intrinsics.md @@ -0,0 +1,25 @@ +% Intrinsics + +> **Note**: intrinsics will forever have an unstable interface, it is +> recommended to use the stable interfaces of libcore rather than intrinsics +> directly. + +These are imported as if they were FFI functions, with the special +`rust-intrinsic` ABI. For example, if one was in a freestanding +context, but wished to be able to `transmute` between types, and +perform efficient pointer arithmetic, one would import those functions +via a declaration like + +``` +# #![feature(intrinsics)] +# fn main() {} + +extern "rust-intrinsic" { + fn transmute(x: T) -> U; + + fn offset(dst: *const T, offset: isize) -> *const T; +} +``` + +As with any other FFI functions, these are always `unsafe` to call. + diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 45c08af04f..55776bee3b 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -57,14 +57,13 @@ for i in 0..nums.len() { } ``` -This is strictly worse than using an actual iterator. The `.iter()` method on -vectors returns an iterator which iterates through a reference to each element -of the vector in turn. So write this: +This is strictly worse than using an actual iterator. You can iterate over vectors +directly, so write this: ```rust let nums = vec![1, 2, 3]; -for num in nums.iter() { +for num in &nums { println!("{}", num); } ``` @@ -86,16 +85,17 @@ see it. This code works fine too: ```rust let nums = vec![1, 2, 3]; -for num in nums.iter() { +for num in &nums { println!("{}", *num); } ``` -Now we're explicitly dereferencing `num`. Why does `iter()` give us references? -Well, if it gave us the data itself, we would have to be its owner, which would -involve making a copy of the data and giving us the copy. With references, -we're just borrowing a reference to the data, and so it's just passing -a reference, without needing to do the copy. +Now we're explicitly dereferencing `num`. Why does `&nums` give us +references? Firstly, because we explicitly asked it to with +`&`. Secondly, if it gave us the data itself, we would have to be its +owner, which would involve making a copy of the data and giving us the +copy. With references, we're just borrowing a reference to the data, +and so it's just passing a reference, without needing to do the move. So, now that we've established that ranges are often not what you want, let's talk about what you do want instead. @@ -230,9 +230,9 @@ let nums = (1..100).collect::>(); Now, `collect()` will require that the range gives it some numbers, and so it will do the work of generating the sequence. -Ranges are one of two basic iterators that you'll see. The other is `iter()`, -which you've used before. `iter()` can turn a vector into a simple iterator -that gives you each element in turn: +Ranges are one of two basic iterators that you'll see. The other is `iter()`. +`iter()` can turn a vector into a simple iterator that gives you each element +in turn: ```rust let nums = [1, 2, 3]; @@ -243,10 +243,12 @@ for num in nums.iter() { ``` These two basic iterators should serve you well. There are some more -advanced iterators, including ones that are infinite. Like `count`: +advanced iterators, including ones that are infinite. Like using range syntax +and `step_by`: ```rust -std::iter::count(1, 5); +# #![feature(step_by)] +(1..).step_by(5); ``` This iterator counts up from one, adding five each time. It will give @@ -291,10 +293,11 @@ just use `for` instead. There are tons of interesting iterator adapters. `take(n)` will return an iterator over the next `n` elements of the original iterator, note that this has no side effect on the original iterator. Let's try it out with our infinite -iterator from before, `count()`: +iterator from before: ```rust -for i in std::iter::count(1, 5).take(5) { +# #![feature(step_by)] +for i in (1..).step_by(5).take(5) { println!("{}", i); } ``` diff --git a/src/doc/trpl/lang-items.md b/src/doc/trpl/lang-items.md new file mode 100644 index 0000000000..5c27c03e8e --- /dev/null +++ b/src/doc/trpl/lang-items.md @@ -0,0 +1,79 @@ +% Lang items + +> **Note**: lang items are often provided by crates in the Rust distribution, +> and lang items themselves have an unstable interface. It is recommended to use +> officially distributed crates instead of defining your own lang items. + +The `rustc` compiler has certain pluggable operations, that is, +functionality that isn't hard-coded into the language, but is +implemented in libraries, with a special marker to tell the compiler +it exists. The marker is the attribute `#[lang="..."]` and there are +various different values of `...`, i.e. various different 'lang +items'. + +For example, `Box` pointers require two lang items, one for allocation +and one for deallocation. A freestanding program that uses the `Box` +sugar for dynamic allocations via `malloc` and `free`: + +``` +#![feature(lang_items, box_syntax, start, no_std, libc)] +#![no_std] + +extern crate libc; + +extern { + fn abort() -> !; +} + +#[lang = "owned_box"] +pub struct Box(*mut T); + +#[lang="exchange_malloc"] +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + let p = libc::malloc(size as libc::size_t) as *mut u8; + + // malloc failed + if p as usize == 0 { + abort(); + } + + p +} +#[lang="exchange_free"] +unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { + libc::free(ptr as *mut libc::c_void) +} + +#[start] +fn main(argc: isize, argv: *const *const u8) -> isize { + let x = box 1; + + 0 +} + +#[lang = "stack_exhausted"] extern fn stack_exhausted() {} +#[lang = "eh_personality"] extern fn eh_personality() {} +#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } +``` + +Note the use of `abort`: the `exchange_malloc` lang item is assumed to +return a valid pointer, and so needs to do the check internally. + +Other features provided by lang items include: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `ord`, + `deref`, and `add` respectively. +- stack unwinding and general failure; the `eh_personality`, `fail` + and `fail_bounds_checks` lang items. +- the traits in `std::marker` used to indicate types of + various kinds; lang items `send`, `sync` and `copy`. +- the marker types and variance indicators found in + `std::marker`; lang items `covariant_type`, + `contravariant_lifetime`, etc. + +Lang items are loaded lazily by the compiler; e.g. if one never uses +`Box` then there is no need to define functions for `exchange_malloc` +and `exchange_free`. `rustc` will emit an error when an item is needed +but not found in the current crate or any that it depends on. diff --git a/src/doc/trpl/link-args.md b/src/doc/trpl/link-args.md new file mode 100644 index 0000000000..ee5159afb8 --- /dev/null +++ b/src/doc/trpl/link-args.md @@ -0,0 +1,25 @@ +% Link args + +There is one other way to tell rustc how to customize linking, and that is via +the `link_args` attribute. This attribute is applied to `extern` blocks and +specifies raw flags which need to get passed to the linker when producing an +artifact. An example usage would be: + +``` no_run +#![feature(link_args)] + +#[link_args = "-foo -bar -baz"] +extern {} +# fn main() {} +``` + +Note that this feature is currently hidden behind the `feature(link_args)` gate +because this is not a sanctioned way of performing linking. Right now rustc +shells out to the system linker, so it makes sense to provide extra command line +arguments, but this will not always be the case. In the future rustc may use +LLVM directly to link native libraries in which case `link_args` will have no +meaning. + +It is highly recommended to *not* use this attribute, and rather use the more +formal `#[link(...)]` attribute on `extern` blocks instead. + diff --git a/src/doc/trpl/looping.md b/src/doc/trpl/looping.md index 4301149d1f..28f02b1ffe 100644 --- a/src/doc/trpl/looping.md +++ b/src/doc/trpl/looping.md @@ -123,7 +123,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 0u32..10 { +for x in 0..10 { if x % 2 == 0 { continue; } println!("{}", x); diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index ce6fa3ce94..7e19ec94ee 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -37,7 +37,7 @@ number of elements. ```rust let x: Vec = vec![1, 2, 3]; -# assert_eq!(&[1,2,3], &x); +# assert_eq!(x, [1, 2, 3]); ``` This can't be an ordinary function, because it takes any number of arguments. @@ -51,7 +51,7 @@ let x: Vec = { temp_vec.push(3); temp_vec }; -# assert_eq!(&[1,2,3], &x); +# assert_eq!(x, [1, 2, 3]); ``` We can implement this shorthand, using a macro: [^actual] @@ -73,7 +73,7 @@ macro_rules! vec { }; } # fn main() { -# assert_eq!(&[1,2,3], &vec![1,2,3]); +# assert_eq!(vec![1,2,3], [1, 2, 3]); # } ``` @@ -189,14 +189,12 @@ shorthand for a data type could be valid as either an expression or a pattern. ## Repetition -The repetition behavior can seem somewhat magical, especially when multiple -names are bound at multiple nested levels of repetition. The two rules to keep -in mind are: +The repetition operator follows two principal rules: -1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for -all of the `$name`s it contains, in lockstep, and +1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s + it contains, in lockstep, and 2. each `$name` must be under at least as many `$(...)*`s as it was matched -against. If it is under more, it'll be duplicated, as appropriate. + against. If it is under more, it'll be duplicated, as appropriate. This baroque macro illustrates the duplication of variables from outer repetition levels. @@ -226,6 +224,10 @@ That's most of the matcher syntax. These examples use `$(...)*`, which is a more" match. Both forms optionally include a separator, which can be any token except `+` or `*`. +This system is based on +"[Macro-by-Example](http://www.cs.indiana.edu/ftp/techreports/TR206.pdf)" +(PDF link). + # Hygiene Some languages implement macros using simple text substitution, which leads to @@ -273,19 +275,26 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks. }) ``` -This looks reasonable, but watch what happens in this example: +Here's a simple use case that goes terribly wrong: ```text const char *state = "reticulating splines"; -LOG(state); +LOG(state) ``` -The program will likely segfault, after it tries to execute +This expands to ```text -printf("log(%d): %s\n", state, state); +const char *state = "reticulating splines"; +int state = get_log_state(); +if (state > 0) { + printf("log(%d): %s\n", state, state); +} ``` +The second variable named `state` shadows the first one. This is a problem +because the print statement should refer to both of them. + The equivalent Rust macro has the desired behavior. ```rust @@ -357,6 +366,64 @@ fn main() { [items]: ../reference.html#items +# Recursive macros + +A macro's expansion can include more macro invocations, including invocations +of the very same macro being expanded. These recursive macros are useful for +processing tree-structured input, as illustrated by this (simplistic) HTML +shorthand: + +```rust +# #![allow(unused_must_use)] +macro_rules! write_html { + ($w:expr, ) => (()); + + ($w:expr, $e:tt) => (write!($w, "{}", $e)); + + ($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{ + write!($w, "<{}>", stringify!($tag)); + write_html!($w, $($inner)*); + write!($w, "", stringify!($tag)); + write_html!($w, $($rest)*); + }}; +} + +fn main() { +# // FIXME(#21826) + use std::fmt::Write; + let mut out = String::new(); + + write_html!(&mut out, + html[ + head[title["Macros guide"]] + body[h1["Macros are the best!"]] + ]); + + assert_eq!(out, + "Macros guide\ +

Macros are the best!

"); +} +``` + +# Debugging macro code + +To see the results of expanding macros, run `rustc --pretty expanded`. The +output represents a whole crate, so you can also feed it back in to `rustc`, +which will sometimes produce better error messages than the original +compilation. Note that the `--pretty expanded` output may have a different +meaning if multiple variables of the same name (but different syntax contexts) +are in play in the same scope. In this case `--pretty expanded,hygiene` will +tell you about the syntax contexts. + +`rustc` provides two syntax extensions that help with macro debugging. For now, +they are unstable and require feature gates. + +* `log_syntax!(...)` will print its arguments to standard output, at compile + time, and "expand" to nothing. + +* `trace_macros!(true)` will enable a compiler message every time a macro is + expanded. Use `trace_macros!(false)` later in expansion to turn it off. + # Further reading The [advanced macros chapter][] goes into more detail about macro syntax. It diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index 64d540582a..18542e58bb 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -23,6 +23,7 @@ the ability to use this *method call syntax* via the `impl` keyword. Here's how it works: ```{rust} +# #![feature(core)] struct Circle { x: f64, y: f64, @@ -45,12 +46,35 @@ This will print `12.566371`. We've made a struct that represents a circle. We then write an `impl` block, and inside it, define a method, `area`. Methods take a special first -parameter, `&self`. There are three variants: `self`, `&self`, and `&mut self`. +parameter, of which there are three variants: `self`, `&self`, and `&mut self`. You can think of this first parameter as being the `x` in `x.foo()`. The three variants correspond to the three kinds of thing `x` could be: `self` if it's just a value on the stack, `&self` if it's a reference, and `&mut self` if it's -a mutable reference. We should default to using `&self`, as it's the most -common. +a mutable reference. We should default to using `&self`, as you should prefer +borrowing over taking ownership, as well as taking immutable references +over mutable ones. Here's an example of all three variants: + +```rust +struct Circle { + x: f64, + y: f64, + radius: f64, +} + +impl Circle { + fn reference(&self) { + println!("taking self by reference!"); + } + + fn mutable_reference(&mut self) { + println!("taking self by mutable reference!"); + } + + fn takes_ownership(self) { + println!("taking ownership of self!"); + } +} +``` Finally, as you may remember, the value of the area of a circle is `π*r²`. Because we took the `&self` parameter to `area`, we can use it just like any @@ -65,6 +89,7 @@ original example, `foo.bar().baz()`? This is called 'method chaining', and we can do it by returning `self`. ``` +# #![feature(core)] struct Circle { x: f64, y: f64, @@ -76,8 +101,8 @@ impl Circle { std::f64::consts::PI * (self.radius * self.radius) } - fn grow(&self) -> Circle { - Circle { x: self.x, y: self.y, radius: (self.radius * 10.0) } + fn grow(&self, increment: f64) -> Circle { + Circle { x: self.x, y: self.y, radius: self.radius + increment } } } @@ -85,7 +110,7 @@ fn main() { let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; println!("{}", c.area()); - let d = c.grow().area(); + let d = c.grow(2.0).area(); println!("{}", d); } ``` @@ -100,7 +125,7 @@ fn grow(&self) -> Circle { ``` We just say we're returning a `Circle`. With this method, we can grow a new -circle with an area that's 100 times larger than the old one. +circle to any arbitrary size. ## Static methods @@ -142,6 +167,7 @@ have method overloading, named arguments, or variable arguments. We employ the builder pattern instead. It looks like this: ``` +# #![feature(core)] struct Circle { x: f64, y: f64, @@ -155,38 +181,46 @@ impl Circle { } struct CircleBuilder { - coordinate: f64, + x: f64, + y: f64, radius: f64, } impl CircleBuilder { fn new() -> CircleBuilder { - CircleBuilder { coordinate: 0.0, radius: 0.0, } + CircleBuilder { x: 0.0, y: 0.0, radius: 0.0, } } - fn coordinate(&mut self, coordinate: f64) -> &mut CircleBuilder { - self.coordinate = coordinate; - self + fn x(&mut self, coordinate: f64) -> &mut CircleBuilder { + self.x = coordinate; + self + } + + fn y(&mut self, coordinate: f64) -> &mut CircleBuilder { + self.x = coordinate; + self } fn radius(&mut self, radius: f64) -> &mut CircleBuilder { - self.radius = radius; - self + self.radius = radius; + self } fn finalize(&self) -> Circle { - Circle { x: self.coordinate, y: self.coordinate, radius: self.radius } + Circle { x: self.x, y: self.y, radius: self.radius } } } fn main() { let c = CircleBuilder::new() - .coordinate(10.0) - .radius(5.0) + .x(1.0) + .y(2.0) + .radius(2.0) .finalize(); - println!("area: {}", c.area()); + println!("x: {}", c.x); + println!("y: {}", c.y); } ``` diff --git a/src/doc/trpl/more-strings.md b/src/doc/trpl/more-strings.md index 20f1406aeb..17a463842e 100644 --- a/src/doc/trpl/more-strings.md +++ b/src/doc/trpl/more-strings.md @@ -12,7 +12,7 @@ Additionally, strings are not null-terminated and can contain null bytes. Rust has two main types of strings: `&str` and `String`. -# &str +# `&str` The first kind is a `&str`. This is pronounced a 'string slice'. String literals are of the type `&str`: @@ -36,10 +36,40 @@ Like vector slices, string slices are simply a pointer plus a length. This means that they're a 'view' into an already-allocated string, such as a string literal or a `String`. -# String +## `str` -A `String` is a heap-allocated string. This string is growable, and is also -guaranteed to be UTF-8. +You may occasionally see references to a `str` type, without the `&`. While +this type does exist, it’s not something you want to use yourself. Sometimes, +people confuse `str` for `String`, and write this: + +```rust +struct S { + s: str, +} +``` + +This leads to ugly errors: + +```text +error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277] +note: `str` does not have a constant size known at compile-time +``` + +Instead, this `struct` should be + +```rust +struct S { + s: String, +} +``` + +So let’s talk about `String`s. + +# `String` + +A `String` is a heap-allocated string. This string is growable, and is +also guaranteed to be UTF-8. `String`s are commonly created by +converting from a string slice using the `to_string` method. ``` let mut s = "Hello".to_string(); @@ -49,7 +79,7 @@ s.push_str(", world."); println!("{}", s); ``` -You can coerce a `String` into a `&str` by dereferencing it: +A reference to a `String` will automatically coerce to a string slice: ``` fn takes_slice(slice: &str) { @@ -58,7 +88,7 @@ fn takes_slice(slice: &str) { fn main() { let s = "Hello".to_string(); - takes_slice(&*s); + takes_slice(&s); } ``` @@ -99,7 +129,7 @@ need, and it can make your lifetimes more complex. To write a function that's generic over types of strings, use `&str`. ``` -fn some_string_length(x: &str) -> uint { +fn some_string_length(x: &str) -> usize { x.len() } @@ -147,6 +177,7 @@ Rust provides iterators for each of these situations: Usually, the `graphemes()` method on `&str` is what you want: ``` +# #![feature(unicode)] let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé"; for l in s.graphemes(true) { @@ -277,7 +308,18 @@ This will print: Many more bytes than graphemes! -# Other Documentation +# `Deref` coercions + +References to `String`s will automatically coerce into `&str`s. Like this: -* [the `&str` API documentation](../std/str/index.html) -* [the `String` API documentation](../std/string/index.html) +``` +fn hello(s: &str) { + println!("Hello, {}!", s); +} + +let slice = "Steve"; +let string = "Steve".to_string(); + +hello(slice); +hello(&string); +``` diff --git a/src/doc/trpl/no-stdlib.md b/src/doc/trpl/no-stdlib.md new file mode 100644 index 0000000000..094c82a08c --- /dev/null +++ b/src/doc/trpl/no-stdlib.md @@ -0,0 +1,168 @@ +% No stdlib + +By default, `std` is linked to every Rust crate. In some contexts, +this is undesirable, and can be avoided with the `#![no_std]` +attribute attached to the crate. + +```ignore +// a minimal library +#![crate_type="lib"] +#![feature(no_std)] +#![no_std] +# // fn main() {} tricked you, rustdoc! +``` + +Obviously there's more to life than just libraries: one can use +`#[no_std]` with an executable, controlling the entry point is +possible in two ways: the `#[start]` attribute, or overriding the +default shim for the C `main` function with your own. + +The function marked `#[start]` is passed the command line parameters +in the same format as C: + +``` +#![feature(lang_items, start, no_std, libc)] +#![no_std] + +// Pull in the system libc library for what crt0.o likely requires +extern crate libc; + +// Entry point for this program +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +// These functions and traits are used by the compiler, but not +// for a bare-bones hello world. These are normally +// provided by libstd. +#[lang = "stack_exhausted"] extern fn stack_exhausted() {} +#[lang = "eh_personality"] extern fn eh_personality() {} +#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } +# // fn main() {} tricked you, rustdoc! +``` + +To override the compiler-inserted `main` shim, one has to disable it +with `#![no_main]` and then create the appropriate symbol with the +correct ABI and the correct name, which requires overriding the +compiler's name mangling too: + +```ignore +#![feature(no_std)] +#![no_std] +#![no_main] +#![feature(lang_items, start)] + +extern crate libc; + +#[no_mangle] // ensure that this symbol is called `main` in the output +pub extern fn main(argc: i32, argv: *const *const u8) -> i32 { + 0 +} + +#[lang = "stack_exhausted"] extern fn stack_exhausted() {} +#[lang = "eh_personality"] extern fn eh_personality() {} +#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } +# // fn main() {} tricked you, rustdoc! +``` + + +The compiler currently makes a few assumptions about symbols which are available +in the executable to call. Normally these functions are provided by the standard +library, but without it you must define your own. + +The first of these three functions, `stack_exhausted`, is invoked whenever stack +overflow is detected. This function has a number of restrictions about how it +can be called and what it must do, but if the stack limit register is not being +maintained then a thread always has an "infinite stack" and this function +shouldn't get triggered. + +The second of these three functions, `eh_personality`, is used by the +failure mechanisms of the compiler. This is often mapped to GCC's +personality function (see the +[libstd implementation](../std/rt/unwind/index.html) for more +information), but crates which do not trigger a panic can be assured +that this function is never called. The final function, `panic_fmt`, is +also used by the failure mechanisms of the compiler. + +## Using libcore + +> **Note**: the core library's structure is unstable, and it is recommended to +> use the standard library instead wherever possible. + +With the above techniques, we've got a bare-metal executable running some Rust +code. There is a good deal of functionality provided by the standard library, +however, that is necessary to be productive in Rust. If the standard library is +not sufficient, then [libcore](../core/index.html) is designed to be used +instead. + +The core library has very few dependencies and is much more portable than the +standard library itself. Additionally, the core library has most of the +necessary functionality for writing idiomatic and effective Rust code. + +As an example, here is a program that will calculate the dot product of two +vectors provided from C, using idiomatic Rust practices. + +``` +#![feature(lang_items, start, no_std, core, libc)] +#![no_std] + +# extern crate libc; +extern crate core; + +use core::prelude::*; + +use core::mem; + +#[no_mangle] +pub extern fn dot_product(a: *const u32, a_len: u32, + b: *const u32, b_len: u32) -> u32 { + use core::raw::Slice; + + // Convert the provided arrays into Rust slices. + // The core::raw module guarantees that the Slice + // structure has the same memory layout as a &[T] + // slice. + // + // This is an unsafe operation because the compiler + // cannot tell the pointers are valid. + let (a_slice, b_slice): (&[u32], &[u32]) = unsafe { + mem::transmute(( + Slice { data: a, len: a_len as usize }, + Slice { data: b, len: b_len as usize }, + )) + }; + + // Iterate over the slices, collecting the result + let mut ret = 0; + for (i, j) in a_slice.iter().zip(b_slice.iter()) { + ret += (*i) * (*j); + } + return ret; +} + +#[lang = "panic_fmt"] +extern fn panic_fmt(args: &core::fmt::Arguments, + file: &str, + line: u32) -> ! { + loop {} +} + +#[lang = "stack_exhausted"] extern fn stack_exhausted() {} +#[lang = "eh_personality"] extern fn eh_personality() {} +# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 } +# fn main() {} +``` + +Note that there is one extra lang item here which differs from the examples +above, `panic_fmt`. This must be defined by consumers of libcore because the +core library declares panics, but it does not define it. The `panic_fmt` +lang item is this crate's definition of panic, and it must be guaranteed to +never return. + +As can be seen in this example, the core library is intended to provide the +power of Rust in all circumstances, regardless of platform requirements. Further +libraries, such as liballoc, add functionality to libcore which make other +platform-specific assumptions, but continue to be more portable than the +standard library itself. + diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md index 6aced23ede..223085cc40 100644 --- a/src/doc/trpl/ownership.md +++ b/src/doc/trpl/ownership.md @@ -472,10 +472,15 @@ thread-safe counterpart of `Rc`. ## 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. +Rust supports powerful local type inference in function bodies, but it’s +forbidden in item signatures to allow reasoning about the types just based in +the item signature alone. However, for ergonomic reasons a very restricted +secondary inference algorithm called “lifetime elision” applies in function +signatures. It infers only based on the signature components themselves and not +based on the body of the function, only infers lifetime parameters, and does +this with only three easily memorizable and unambiguous rules. This makes +lifetime elision a shorthand for writing an item signature, while not hiding +away the actual types involved as full local inference would if applied to it. When talking about lifetime elision, we use the term *input lifetime* and *output lifetime*. An *input lifetime* is a lifetime associated with a parameter @@ -513,8 +518,8 @@ 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: +Here are some examples of functions with elided lifetimes. We've paired each +example of an elided lifetime with its expanded form. ```{rust,ignore} fn print(s: &str); // elided diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index 9e82e48fd1..4ebf696aa5 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -177,6 +177,7 @@ match origin { If you want to match against a slice or array, you can use `&`: ```{rust} +# #![feature(slice_patterns)] fn main() { let v = vec!["match_this", "1"]; diff --git a/src/doc/trpl/plugins.md b/src/doc/trpl/plugins.md index 79502f3cd1..9eb22a7f69 100644 --- a/src/doc/trpl/plugins.md +++ b/src/doc/trpl/plugins.md @@ -1,29 +1,5 @@ % Compiler Plugins -
- -

-Warning: Plugins are an advanced, unstable feature! For many details, -the only available documentation is the libsyntax and librustc API docs, or even the source -code itself. These internal compiler APIs are also subject to change at any -time. -

- -

-For defining new syntax it is often much easier to use Rust's built-in macro system. -

- -

-The code in this document uses language features not covered in the Rust -Guide. See the Reference Manual for more -information. -

- -
- # Introduction `rustc` can load compiler plugins, which are user-provided libraries that @@ -63,7 +39,7 @@ that implements Roman numeral integer literals. ```ignore #![crate_type="dylib"] -#![feature(plugin_registrar)] +#![feature(plugin_registrar, rustc_private)] extern crate syntax; extern crate rustc; @@ -71,8 +47,8 @@ extern crate rustc; use syntax::codemap::Span; use syntax::parse::token; use syntax::ast::{TokenTree, TtToken}; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr}; -use syntax::ext::build::AstBuilder; // trait for expr_uint +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc::plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) @@ -92,13 +68,13 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } }; - let mut text = &text; + let mut text = &*text; let mut total = 0; while !text.is_empty() { match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) { Some(&(rn, val)) => { total += val; - text = text.slice_from(rn.len()); + text = &text[rn.len()..]; } None => { cx.span_err(sp, "invalid Roman numeral"); @@ -107,7 +83,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } } - MacExpr::new(cx.expr_uint(sp, total)) + MacEager::expr(cx.expr_u32(sp, total)) } #[plugin_registrar] @@ -146,14 +122,7 @@ a more involved macro example, see ## Tips and tricks -To see the results of expanding syntax extensions, run -`rustc --pretty expanded`. The output represents a whole crate, so you -can also feed it back in to `rustc`, which will sometimes produce better -error messages than the original compilation. Note that the -`--pretty expanded` output may have a different meaning if multiple -variables of the same name (but different syntax contexts) are in play -in the same scope. In this case `--pretty expanded,hygiene` will tell -you about the syntax contexts. +Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable. You can use [`syntax::parse`](../syntax/parse/index.html) to turn token trees into higher-level syntax elements like expressions: @@ -184,8 +153,13 @@ and return [`DummyResult`](../syntax/ext/base/struct.DummyResult.html), so that the compiler can continue and find further errors. +To print syntax fragments for debugging, you can use +[`span_note`](../syntax/ext/base/struct.ExtCtxt.html#method.span_note) together +with +[`syntax::print::pprust::*_to_string`](http://doc.rust-lang.org/syntax/print/pprust/index.html#functions). + The example above produced an integer literal using -[`AstBuilder::expr_uint`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint). +[`AstBuilder::expr_usize`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_usize). As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of [quasiquote macros](../syntax/ext/quote/index.html). They are undocumented and very rough around the edges. However, the implementation may be a good diff --git a/src/doc/trpl/pointers.md b/src/doc/trpl/pointers.md index 9c649cd227..1b3f2a5b77 100644 --- a/src/doc/trpl/pointers.md +++ b/src/doc/trpl/pointers.md @@ -361,16 +361,16 @@ duration a *lifetime*. Let's try a more complex example: ```{rust} fn main() { - let x = &mut 5; + let mut x = 5; - if *x < 10 { + if x < 10 { let y = &x; println!("Oh no: {}", y); return; } - *x -= 1; + x -= 1; println!("Oh no: {}", x); } @@ -382,17 +382,18 @@ mutated, and therefore, lets us pass. This wouldn't work: ```{rust,ignore} fn main() { - let x = &mut 5; + let mut x = 5; - if *x < 10 { + if x < 10 { let y = &x; - *x -= 1; + + x -= 1; println!("Oh no: {}", y); return; } - *x -= 1; + x -= 1; println!("Oh no: {}", x); } @@ -401,12 +402,12 @@ fn main() { It gives this error: ```text -test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed -test.rs:5 *x -= 1; - ^~ -test.rs:4:16: 4:18 note: borrow of `*x` occurs here -test.rs:4 let y = &x; - ^~ +test.rs:7:9: 7:15 error: cannot assign to `x` because it is borrowed +test.rs:7 x -= 1; + ^~~~~~ +test.rs:5:18: 5:19 note: borrow of `x` occurs here +test.rs:5 let y = &x; + ^ ``` As you might guess, this kind of analysis is complex for a human, and therefore @@ -497,13 +498,10 @@ they go out of scope: However, boxes do _not_ use reference counting or garbage collection. Boxes are what's called an *affine type*. This means that the Rust compiler, at compile time, determines when the box comes into and goes out of scope, and inserts the -appropriate calls there. Furthermore, boxes are a specific kind of affine type, -known as a *region*. You can read more about regions [in this paper on the -Cyclone programming -language](http://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf). +appropriate calls there. -You don't need to fully grok the theory of affine types or regions to grok -boxes, though. As a rough approximation, you can treat this Rust code: +You don't need to fully grok the theory of affine types to grok boxes, though. +As a rough approximation, you can treat this Rust code: ```{rust} { @@ -560,43 +558,44 @@ fn main() { In this case, Rust knows that `x` is being *borrowed* by the `add_one()` function, and since it's only reading the value, allows it. -We can borrow `x` multiple times, as long as it's not simultaneous: +We can borrow `x` as read-only multiple times, even simultaneously: ```{rust} -fn add_one(x: &i32) -> i32 { - *x + 1 +fn add(x: &i32, y: &i32) -> i32 { + *x + *y } fn main() { let x = Box::new(5); - println!("{}", add_one(&*x)); - println!("{}", add_one(&*x)); - println!("{}", add_one(&*x)); + println!("{}", add(&*x, &*x)); + println!("{}", add(&*x, &*x)); } ``` -Or as long as it's not a mutable borrow. This will error: +We can mutably borrow `x` multiple times, but only if x itself is mutable, and +it may not be *simultaneously* borrowed: ```{rust,ignore} -fn add_one(x: &mut i32) -> i32 { - *x + 1 +fn increment(x: &mut i32) { + *x += 1; } fn main() { - let x = Box::new(5); + // If variable x is not "mut", this will not compile + let mut x = Box::new(5); - println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference - // of `&`-pointer as mutable + increment(&mut x); + increment(&mut x); + println!("{}", x); } ``` -Notice we changed the signature of `add_one()` to request a mutable reference. +Notice the signature of `increment()` requests a mutable reference. ## Best practices -Boxes are appropriate to use in two situations: Recursive data structures, -and occasionally, when returning data. +Boxes are most appropriate to use when defining recursive data structures. ### Recursive data structures @@ -630,14 +629,6 @@ we don't know the size, and therefore, we need to heap allocate our list. Working with recursive or other unknown-sized data structures is the primary use-case for boxes. -### Returning data - -This is important enough to have its own section entirely. The TL;DR is this: -you don't generally want to return pointers, even when you might in a language -like C or C++. - -See [Returning Pointers](#returning-pointers) below for more. - # Rc and Arc This part is coming soon. @@ -654,74 +645,6 @@ This part is coming soon. This part is coming soon. -# Returning Pointers - -In many languages with pointers, you'd return a pointer from a function -so as to avoid copying a large data structure. For example: - -```{rust} -struct BigStruct { - one: i32, - two: i32, - // etc - one_hundred: i32, -} - -fn foo(x: Box) -> Box { - Box::new(*x) -} - -fn main() { - let x = Box::new(BigStruct { - one: 1, - two: 2, - one_hundred: 100, - }); - - let y = foo(x); -} -``` - -The idea is that by passing around a box, you're only copying a pointer, rather -than the hundred `int`s that make up the `BigStruct`. - -This is an antipattern in Rust. Instead, write this: - -```{rust} -struct BigStruct { - one: i32, - two: i32, - // etc - one_hundred: i32, -} - -fn foo(x: Box) -> BigStruct { - *x -} - -fn main() { - let x = Box::new(BigStruct { - one: 1, - two: 2, - one_hundred: 100, - }); - - let y = Box::new(foo(x)); -} -``` - -This gives you flexibility without sacrificing performance. - -You may think that this gives us terrible performance: return a value and then -immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is -smarter than that. There is no copy in this code. `main` allocates enough room -for the `box`, passes a pointer to that memory into `foo` as `x`, and then -`foo` writes the value straight into the `Box`. - -This is important enough that it bears repeating: pointers are not for -optimizing returning values from your code. Allow the caller to choose how they -want to use your output. - # Creating your own Pointers This part is coming soon. diff --git a/src/doc/trpl/standard-input.md b/src/doc/trpl/standard-input.md deleted file mode 100644 index 794b1df756..0000000000 --- a/src/doc/trpl/standard-input.md +++ /dev/null @@ -1,159 +0,0 @@ -% Standard Input - -Getting input from the keyboard is pretty easy, but uses some things -we haven't seen before. Here's a simple program that reads some input, -and then prints it back out: - -```{rust,ignore} -fn main() { - println!("Type something!"); - - let input = std::old_io::stdin().read_line().ok().expect("Failed to read line"); - - println!("{}", input); -} -``` - -Let's go over these chunks, one by one: - -```{rust,ignore} -std::old_io::stdin(); -``` - -This calls a function, `stdin()`, that lives inside the `std::old_io` module. As -you can imagine, everything in `std` is provided by Rust, the 'standard -library.' We'll talk more about the module system later. - -Since writing the fully qualified name all the time is annoying, we can use -the `use` statement to import it in: - -```{rust} -use std::old_io::stdin; - -stdin(); -``` - -However, it's considered better practice to not import individual functions, but -to import the module, and only use one level of qualification: - -```{rust} -use std::old_io; - -old_io::stdin(); -``` - -Let's update our example to use this style: - -```{rust,ignore} -use std::old_io; - -fn main() { - println!("Type something!"); - - let input = old_io::stdin().read_line().ok().expect("Failed to read line"); - - println!("{}", input); -} -``` - -Next up: - -```{rust,ignore} -.read_line() -``` - -The `read_line()` method can be called on the result of `stdin()` to return -a full line of input. Nice and easy. - -```{rust,ignore} -.ok().expect("Failed to read line"); -``` - -Do you remember this code? - -```{rust} -enum OptionalInt { - Value(i32), - Missing, -} - -fn main() { - let x = OptionalInt::Value(5); - let y = OptionalInt::Missing; - - match x { - OptionalInt::Value(n) => println!("x is {}", n), - OptionalInt::Missing => println!("x is missing!"), - } - - match y { - OptionalInt::Value(n) => println!("y is {}", n), - OptionalInt::Missing => println!("y is missing!"), - } -} -``` - -We had to match each time to see if we had a value or not. In this case, -though, we _know_ that `x` has a `Value`, but `match` forces us to handle -the `missing` case. This is what we want 99% of the time, but sometimes, we -know better than the compiler. - -Likewise, `read_line()` does not return a line of input. It _might_ return a -line of input, though it might also fail to do so. This could happen if our program -isn't running in a terminal, but as part of a cron job, or some other context -where there's no standard input. Because of this, `read_line` returns a type -very similar to our `OptionalInt`: an `IoResult`. We haven't talked about -`IoResult` 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 `i32`s. - -Rust provides a method on these `IoResult`s called `ok()`, which does the -same thing as our `match` statement but assumes that we have a valid value. -We then call `expect()` on the result, which will terminate our program if we -don't have a valid value. In this case, if we can't get input, our program -doesn't work, so we're okay with that. In most cases, we would want to handle -the error case explicitly. `expect()` allows us to give an error message if -this crash happens. - -We will cover the exact details of how all of this works later in the Guide. -For now, this gives you enough of a basic understanding to work with. - -Back to the code we were working on! Here's a refresher: - -```{rust,ignore} -use std::old_io; - -fn main() { - println!("Type something!"); - - let input = old_io::stdin().read_line().ok().expect("Failed to read line"); - - println!("{}", input); -} -``` - -With long lines like this, Rust gives you some flexibility with the whitespace. -We _could_ write the example like this: - -```{rust,ignore} -use std::old_io; - -fn main() { - println!("Type something!"); - - // here, we'll show the types at each step - - let input = old_io::stdin() // std::old_io::stdio::StdinReader - .read_line() // IoResult - .ok() // Option - .expect("Failed to read line"); // String - - println!("{}", input); -} -``` - -Sometimes, this makes things more readable – sometimes, less. Use your judgement -here. - -That's all you need to get basic input from the standard input! It's not too -complicated, but there are a number of small parts. diff --git a/src/doc/trpl/static-and-dynamic-dispatch.md b/src/doc/trpl/static-and-dynamic-dispatch.md index 9421dac7bf..a779481415 100644 --- a/src/doc/trpl/static-and-dynamic-dispatch.md +++ b/src/doc/trpl/static-and-dynamic-dispatch.md @@ -79,12 +79,13 @@ fn main() { } ``` -This has some upsides: static dispatching of any method calls, allowing for -inlining and hence usually higher performance. It also has some downsides: -causing code bloat due to many copies of the same function existing in the -binary, one for each type. +This has a great upside: static dispatch allows function calls to be +inlined because the callee is known at compile time, and inlining is +the key to good optimization. Static dispatch is fast, but it comes at +a tradeoff: 'code bloat', due to many copies of the same function +existing in the binary, one for each type. -Furthermore, compilers aren’t perfect and may “optimise” code to become slower. +Furthermore, compilers aren’t perfect and may “optimize” code to become slower. For example, functions inlined too eagerly will bloat the instruction cache (cache rules everything around us). This is part of the reason that `#[inline]` and `#[inline(always)]` should be used carefully, and one reason why using a @@ -92,61 +93,100 @@ dynamic dispatch is sometimes more efficient. However, the common case is that it is more efficient to use static dispatch, and one can always have a thin statically-dispatched wrapper function that does -a dynamic, but not vice versa, meaning static calls are more flexible. The -standard library tries to be statically dispatched where possible for this -reason. +a dynamic dispatch, but not vice versa, meaning static calls are more flexible. +The standard library tries to be statically dispatched where possible for this +reason. ## Dynamic dispatch Rust provides dynamic dispatch through a feature called 'trait objects.' Trait objects, like `&Foo` or `Box`, are normal values that store a value of *any* type that implements the given trait, where the precise type can only be -known at runtime. The methods of the trait can be called on a trait object via -a special record of function pointers (created and managed by the compiler). +known at runtime. -A function that takes a trait object is not specialised to each of the types -that implements `Foo`: only one copy is generated, often (but not always) -resulting in less code bloat. However, this comes at the cost of requiring -slower virtual function calls, and effectively inhibiting any chance of -inlining and related optimisations from occurring. +A trait object can be obtained from a pointer to a concrete type that +implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it +(e.g. using `&x` as an argument to a function that takes `&Foo`). -Trait objects are both simple and complicated: their core representation and -layout is quite straight-forward, but there are some curly error messages and -surprising behaviours to discover. +These trait object coercions and casts also work for pointers like `&mut T` to +`&mut Foo` and `Box` to `Box`, but that's all at the moment. Coercions +and casts are identical. + +This operation can be seen as "erasing" the compiler's knowledge about the +specific type of the pointer, and hence trait objects are sometimes referred to +as "type erasure". + +Coming back to the example above, we can use the same trait to perform dynamic +dispatch with trait objects by casting: -### Obtaining a trait object +```rust +# trait Foo { fn method(&self) -> String; } +# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } +# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -There's two similar ways to get a trait object value: casts and coercions. If -`T` is a type that implements a trait `Foo` (e.g. `u8` for the `Foo` above), -then the two ways to get a `Foo` trait object out of a pointer to `T` look -like: +fn do_something(x: &Foo) { + x.method(); +} -```{rust,ignore} -let ref_to_t: &T = ...; +fn main() { + let x = 5u8; + do_something(&x as &Foo); +} +``` + +or by coercing: -// `as` keyword for casting -let cast = ref_to_t as &Foo; +```rust +# trait Foo { fn method(&self) -> String; } +# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } +# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -// using a `&T` in a place that has a known type of `&Foo` will implicitly coerce: -let coerce: &Foo = ref_to_t; +fn do_something(x: &Foo) { + x.method(); +} -fn also_coerce(_unused: &Foo) {} -also_coerce(ref_to_t); +fn main() { + let x = "Hello".to_string(); + do_something(&x); +} ``` -These trait object coercions and casts also work for pointers like `&mut T` to -`&mut Foo` and `Box` to `Box`, but that's all at the moment. Coercions -and casts are identical. +A function that takes a trait object is not specialized to each of the types +that implements `Foo`: only one copy is generated, often (but not always) +resulting in less code bloat. However, this comes at the cost of requiring +slower virtual function calls, and effectively inhibiting any chance of +inlining and related optimisations from occurring. -This operation can be seen as "erasing" the compiler's knowledge about the -specific type of the pointer, and hence trait objects are sometimes referred to -"type erasure". +### Why pointers? + +Rust does not put things behind a pointer by default, unlike many managed +languages, so types can have different sizes. Knowing the size of the value at +compile time is important for things like passing it as an argument to a +function, moving it about on the stack and allocating (and deallocating) space +on the heap to store it. + +For `Foo`, we would need to have a value that could be at least either a +`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which +dependent crates may implement `Foo` (any number of bytes at all). There's no +way to guarantee that this last point can work if the values are stored without +a pointer, because those other types can be arbitrarily large. + +Putting the value behind a pointer means the size of the value is not relevant +when we are tossing a trait object around, only the size of the pointer itself. ### Representation +The methods of the trait can be called on a trait object via a special record +of function pointers traditionally called a 'vtable' (created and managed by +the compiler). + +Trait objects are both simple and complicated: their core representation and +layout is quite straight-forward, but there are some curly error messages and +surprising behaviors to discover. + Let's start simple, with the runtime representation of a trait object. The `std::raw` module contains structs with layouts that are the same as the -complicated build-in types, [including trait objects][stdraw]: +complicated built-in types, [including trait objects][stdraw]: ```rust # mod foo { @@ -223,14 +263,14 @@ static Foo_for_String_vtable: FooVtable = FooVtable { The `destructor` field in each vtable points to a function that will clean up any resources of the vtable's type, for `u8` it is trivial, but for `String` it will free the memory. This is necessary for owning trait objects like -`Box`, which need to clean-up both the `Box` allocation and as well as the +`Box`, which need to clean-up both the `Box` allocation as well as the internal type when they go out of scope. The `size` and `align` fields store the size of the erased type, and its alignment requirements; these are essentially unused at the moment since the information is embedded in the -destructor, but will be used in future, as trait objects are progressively made -more flexible. +destructor, but will be used in the future, as trait objects are progressively +made more flexible. -Suppose we've got some values that implement `Foo`, the explicit form of +Suppose we've got some values that implement `Foo`, then the explicit form of construction and use of `Foo` trait objects might look a bit like (ignoring the type mismatches: they're all just pointers anyway): @@ -264,23 +304,3 @@ let y = TraitObject { If `b` or `y` were owning trait objects (`Box`), there would be a `(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of scope. - -### Why pointers? - -The use of language like "fat pointer" implies that a trait object is -always a pointer of some form, but why? - -Rust does not put things behind a pointer by default, unlike many managed -languages, so types can have different sizes. Knowing the size of the value at -compile time is important for things like passing it as an argument to a -function, moving it about on the stack and allocating (and deallocating) space -on the heap to store it. - -For `Foo`, we would need to have a value that could be at least either a -`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which -dependent crates may implement `Foo` (any number of bytes at all). There's no -way to guarantee that this last point can work if the values are stored without -a pointer, because those other types can be arbitrarily large. - -Putting the value behind a pointer means the size of the value is not relevant -when we are tossing a trait object around, only the size of the pointer itself. diff --git a/src/doc/trpl/strings.md b/src/doc/trpl/strings.md index 8ebebc98ba..2c2e6a8c7c 100644 --- a/src/doc/trpl/strings.md +++ b/src/doc/trpl/strings.md @@ -25,8 +25,10 @@ compiled program, and exists for the entire duration it runs. The `string` binding is a reference to this statically allocated string. String slices have a fixed size, and cannot be mutated. -A `String`, on the other hand, is an in-memory string. This string is -growable, and is also guaranteed to be UTF-8. +A `String`, on the other hand, is a heap-allocated string. This string +is growable, and is also guaranteed to be UTF-8. `String`s are +commonly created by converting from a string slice using the +`to_string` method. ```{rust} let mut s = "Hello".to_string(); // mut s: String diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md index 54c74fdd3e..fddb4c1903 100644 --- a/src/doc/trpl/testing.md +++ b/src/doc/trpl/testing.md @@ -1,7 +1,7 @@ % Testing > Program testing can be a very effective way to show the presence of bugs, but -> it is hopelessly inadequate for showing their absence. +> it is hopelessly inadequate for showing their absence. > > Edsger W. Dijkstra, "The Humble Programmer" (1972) @@ -129,11 +129,11 @@ $ echo $? This is useful if you want to integrate `cargo test` into other tooling. -We can invert our test's failure with another attribute: `should_fail`: +We can invert our test's failure with another attribute: `should_panic`: ```rust #[test] -#[should_fail] +#[should_panic] fn it_works() { assert!(false); } @@ -163,13 +163,13 @@ equality: ```rust #[test] -#[should_fail] +#[should_panic] fn it_works() { assert_eq!("Hello", "world"); } ``` -Does this test pass or fail? Because of the `should_fail` attribute, it +Does this test pass or fail? Because of the `should_panic` attribute, it passes: ```bash @@ -189,15 +189,15 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -`should_fail` tests can be fragile, as it's hard to guarantee that the test +`should_panic` tests can be fragile, as it's hard to guarantee that the test didn't fail for an unexpected reason. To help with this, an optional `expected` -parameter can be added to the `should_fail` attribute. The test harness will +parameter can be added to the `should_panic` attribute. The test harness will make sure that the failure message contains the provided text. A safer version of the example above would be: ``` #[test] -#[should_fail(expected = "assertion failed")] +#[should_panic(expected = "assertion failed")] fn it_works() { assert_eq!("Hello", "world"); } @@ -231,7 +231,7 @@ pub fn add_two(a: i32) -> i32 { } #[cfg(test)] -mod tests { +mod test { use super::add_two; #[test] @@ -241,7 +241,7 @@ mod tests { } ``` -There's a few changes here. The first is the introduction of a `mod tests` with +There's a few changes here. The first is the introduction of a `mod test` with a `cfg` attribute. The module allows us to group all of our tests together, and to also define helper functions if needed, that don't become a part of the rest of our crate. The `cfg` attribute only compiles our test code if we're @@ -260,7 +260,7 @@ pub fn add_two(a: i32) -> i32 { } #[cfg(test)] -mod tests { +mod test { use super::*; #[test] @@ -308,7 +308,7 @@ extern crate adder; #[test] fn it_works() { assert_eq!(4, adder::add_two(2)); -} +} ``` This looks similar to our previous tests, but slightly different. We now have @@ -430,147 +430,3 @@ documentation tests: the `_0` is generated for the module test, and `add_two_0` for the function test. These will auto increment with names like `add_two_1` as you add more examples. -# Benchmark tests - -Rust also supports benchmark tests, which can test the performance of your -code. Let's make our `src/lib.rs` look like this (comments elided): - -```{rust,ignore} -extern crate test; - -pub fn add_two(a: i32) -> i32 { - a + 2 -} - -#[cfg(test)] -mod tests { - use super::*; - use test::Bencher; - - #[test] - fn it_works() { - assert_eq!(4, add_two(2)); - } - - #[bench] - fn bench_add_two(b: &mut Bencher) { - b.iter(|| add_two(2)); - } -} -``` - -We've imported the `test` crate, which contains our benchmarking support. -We have a new function as well, with the `bench` attribute. Unlike regular -tests, which take no arguments, benchmark tests take a `&mut Bencher`. This -`Bencher` provides an `iter` method, which takes a closure. This closure -contains the code we'd like to benchmark. - -We can run benchmark tests with `cargo bench`: - -```bash -$ cargo bench - Compiling adder v0.0.1 (file:///home/steve/tmp/adder) - Running target/release/adder-91b3e234d4ed382a - -running 2 tests -test tests::it_works ... ignored -test tests::bench_add_two ... bench: 1 ns/iter (+/- 0) - -test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured -``` - -Our non-benchmark test was ignored. You may have noticed that `cargo bench` -takes a bit longer than `cargo test`. This is because Rust runs our benchmark -a number of times, and then takes the average. Because we're doing so little -work in this example, we have a `1 ns/iter (+/- 0)`, but this would show -the variance if there was one. - -Advice on writing benchmarks: - - -* Move setup code outside the `iter` loop; only put the part you want to measure inside -* Make the code do "the same thing" on each iteration; do not accumulate or change state -* Make the outer function idempotent too; the benchmark runner is likely to run - it many times -* Make the inner `iter` loop short and fast so benchmark runs are fast and the - calibrator can adjust the run-length at fine resolution -* 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 -compiler might recognize that some calculation has no external effects and -remove it entirely. - -```{rust,ignore} -extern crate test; -use test::Bencher; - -#[bench] -fn bench_xor_1000_ints(b: &mut Bencher) { - b.iter(|| { - (0..1000).fold(0, |old, new| old ^ new); - }); -} -``` - -gives the following results - -```text -running 1 test -test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0) - -test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured -``` - -The benchmarking runner offers two ways to avoid this. Either, the closure that -the `iter` method receives can return an arbitrary value which forces the -optimizer to consider the result used and ensures it cannot remove the -computation entirely. This could be done for the example above by adjusting the -`b.iter` call to - -```rust -# struct X; -# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; -b.iter(|| { - // note lack of `;` (could also use an explicit `return`). - (0..1000).fold(0, |old, new| old ^ new) -}); -``` - -Or, the other option is to call the generic `test::black_box` function, which -is an opaque "black box" to the optimizer and so forces it to consider any -argument as used. - -```rust -extern crate test; - -# fn main() { -# struct X; -# impl X { fn iter(&self, _: F) where F: FnMut() -> T {} } let b = X; -b.iter(|| { - let n = test::black_box(1000); - - (0..n).fold(0, |a, b| a ^ b) -}) -# } -``` - -Neither of these read or modify the value, and are very cheap for small values. -Larger values can be passed indirectly to reduce overhead (e.g. -`black_box(&huge_struct)`). - -Performing either of the above changes gives the following benchmarking results - -```text -running 1 test -test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3) - -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. diff --git a/src/doc/trpl/tracing-macros.md b/src/doc/trpl/tracing-macros.md new file mode 100644 index 0000000000..6226ea9f3e --- /dev/null +++ b/src/doc/trpl/tracing-macros.md @@ -0,0 +1,91 @@ +% Tracing Macros + +The `trace_macros` feature allows you to use a special feature: tracing macro +invocations. + +In the advanced macros chapter, we defined a `bct` macro: + +```rust +macro_rules! bct { + // cmd 0: d ... => ... + (0, $($ps:tt),* ; $_d:tt) + => (bct!($($ps),*, 0 ; )); + (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*) + => (bct!($($ps),*, 0 ; $($ds),*)); + + // cmd 1p: 1 ... => 1 ... p + (1, $p:tt, $($ps:tt),* ; 1) + => (bct!($($ps),*, 1, $p ; 1, $p)); + (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*) + => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p)); + + // cmd 1p: 0 ... => 0 ... + (1, $p:tt, $($ps:tt),* ; $($ds:tt),*) + => (bct!($($ps),*, 1, $p ; $($ds),*)); + + // halt on empty data string + ( $($ps:tt),* ; ) + => (()); +} +``` + +This is pretty complex! we can see the output + +```rust,ignore +#![feature(trace_macros)] + +macro_rules! bct { + // cmd 0: d ... => ... + (0, $($ps:tt),* ; $_d:tt) + => (bct!($($ps),*, 0 ; )); + (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*) + => (bct!($($ps),*, 0 ; $($ds),*)); + + // cmd 1p: 1 ... => 1 ... p + (1, $p:tt, $($ps:tt),* ; 1) + => (bct!($($ps),*, 1, $p ; 1, $p)); + (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*) + => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p)); + + // cmd 1p: 0 ... => 0 ... + (1, $p:tt, $($ps:tt),* ; $($ds:tt),*) + => (bct!($($ps),*, 1, $p ; $($ds),*)); + + // halt on empty data string + ( $($ps:tt),* ; ) + => (()); +} + +fn main() { + trace_macros!(true); + + bct!(0, 0, 1, 1, 1 ; 1, 0, 1); +} +``` + +This will print out a wall of text: + +```text +bct! { 0 , 0 , 1 , 1 , 1 ; 1 , 0 , 1 } +bct! { 0 , 1 , 1 , 1 , 0 ; 0 , 1 } +bct! { 1 , 1 , 1 , 0 , 0 ; 1 } +bct! { 1 , 0 , 0 , 1 , 1 ; 1 , 1 } +bct! { 0 , 1 , 1 , 1 , 0 ; 1 , 1 , 0 } +bct! { 1 , 1 , 1 , 0 , 0 ; 1 , 0 } +bct! { 1 , 0 , 0 , 1 , 1 ; 1 , 0 , 1 } +bct! { 0 , 1 , 1 , 1 , 0 ; 1 , 0 , 1 , 0 } +bct! { 1 , 1 , 1 , 0 , 0 ; 0 , 1 , 0 } +bct! { 1 , 0 , 0 , 1 , 1 ; 0 , 1 , 0 } +bct! { 0 , 1 , 1 , 1 , 0 ; 0 , 1 , 0 } +``` + +And eventually, error: + +```text +18:45 error: recursion limit reached while expanding the macro `bct` + => (bct!($($ps),*, 1, $p ; $($ds),*)); + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` + +The `trace_macros!` call is what produces this output, showing how we match +each time. diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md index abd9af1af3..341c90a708 100644 --- a/src/doc/trpl/traits.md +++ b/src/doc/trpl/traits.md @@ -4,6 +4,7 @@ Do you remember the `impl` keyword, used to call a function with method syntax? ```{rust} +# #![feature(core)] struct Circle { x: f64, y: f64, @@ -21,6 +22,7 @@ Traits are similar, except that we define a trait with just the method signature, then implement the trait for that struct. Like this: ```{rust} +# #![feature(core)] struct Circle { x: f64, y: f64, @@ -84,6 +86,7 @@ which implements `HasArea` will have an `.area()` method. Here's an extended example of how this works: ```{rust} +# #![feature(core)] trait HasArea { fn area(&self) -> f64; } @@ -225,6 +228,7 @@ If we add a `use` line right above `main` and make the right things public, everything is fine: ```{rust} +# #![feature(core)] use shapes::HasArea; mod shapes { @@ -273,6 +277,29 @@ One last thing about traits: generic functions with a trait bound use dispatched. What's that mean? Check out the chapter on [static and dynamic dispatch](static-and-dynamic-dispatch.html) for more. +## Multiple trait bounds + +You’ve seen that you can bound a generic type parameter with a trait: + +```rust +fn foo(x: T) { + x.clone(); +} +``` + +If you need more than one bound, you can use `+`: + +```rust +use std::fmt::Debug; + +fn foo(x: T) { + x.clone(); + println!("{:?}", x); +} +``` + +`T` now needs to be both `Clone` as well as `Debug`. + ## Where clause Writing functions with only a few generic types and a small number of trait @@ -408,6 +435,7 @@ but instead, we found a floating-point variable. We need a different bound. `Flo to the rescue: ``` +# #![feature(std_misc)] use std::num::Float; fn inverse(x: T) -> Result { @@ -423,6 +451,7 @@ from the `Float` trait. Both `f32` and `f64` implement `Float`, so our function works just fine: ``` +# #![feature(std_misc)] # use std::num::Float; # fn inverse(x: T) -> Result { # if x == Float::zero() { return Err("x cannot be zero!".to_string()) } @@ -435,3 +464,46 @@ println!("the inverse of {} is {:?}", 2.0f64, inverse(2.0f64)); println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32)); println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64)); ``` + +## Default methods + +There's one last feature of traits we should cover: default methods. It's +easiest just to show an example: + +```rust +trait Foo { + fn bar(&self); + + fn baz(&self) { println!("We called baz."); } +} +``` + +Implementors of the `Foo` trait need to implement `bar()`, but they don't +need to implement `baz()`. They'll get this default behavior. They can +override the default if they so choose: + +```rust +# trait Foo { +# fn bar(&self); +# fn baz(&self) { println!("We called baz."); } +# } +struct UseDefault; + +impl Foo for UseDefault { + fn bar(&self) { println!("We called bar."); } +} + +struct OverrideDefault; + +impl Foo for OverrideDefault { + fn bar(&self) { println!("We called bar."); } + + fn baz(&self) { println!("Override baz!"); } +} + +let default = UseDefault; +default.baz(); // prints "We called baz." + +let over = OverrideDefault; +over.baz(); // prints "Override baz!" +``` diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md index 4e14085599..3ca3cfd058 100644 --- a/src/doc/trpl/unsafe.md +++ b/src/doc/trpl/unsafe.md @@ -93,10 +93,6 @@ offered by the Rust language and libraries. For example, they - are plain-old-data, that is, they don't move ownership, again unlike `Box`, hence the Rust compiler cannot protect against bugs like use-after-free; -- are considered sendable (if their contents is considered sendable), - so the compiler offers no assistance with ensuring their use is - thread-safe; for example, one can concurrently access a `*mut i32` - from two threads without synchronization. - lack any form of lifetimes, unlike `&`, and so the compiler cannot reason about dangling pointers; and - have no guarantees about aliasing or mutability other than mutation @@ -185,533 +181,3 @@ code: that clean-up is always run, even when the thread panics. - ensure that any data stored behind a raw pointer is destroyed at the appropriate time. - -As an example, we give a reimplementation of owned boxes by wrapping -`malloc` and `free`. Rust's move semantics and lifetimes mean this -reimplementation is as safe as the `Box` type. - -``` -#![feature(unsafe_destructor)] - -extern crate libc; -use libc::{c_void, size_t, malloc, free}; -use std::mem; -use std::ptr; - -// Define a wrapper around the handle returned by the foreign code. -// Unique has the same semantics as Box -pub struct Unique { - // It contains a single raw, mutable pointer to the object in question. - ptr: *mut T -} - -// Implement methods for creating and using the values in the box. - -// NB: For simplicity and correctness, we require that T has kind Send -// (owned boxes relax this restriction). -impl Unique { - pub fn new(value: T) -> Unique { - unsafe { - let ptr = malloc(mem::size_of::() as size_t) as *mut T; - // we *need* valid pointer. - assert!(!ptr.is_null()); - // `*ptr` is uninitialized, and `*ptr = value` would - // attempt to destroy it `overwrite` moves a value into - // this memory without attempting to drop the original - // value. - ptr::write(&mut *ptr, value); - Unique{ptr: ptr} - } - } - - // the 'r lifetime results in the same semantics as `&*x` with - // Box - pub fn borrow<'r>(&'r self) -> &'r T { - // By construction, self.ptr is valid - unsafe { &*self.ptr } - } - - // the 'r lifetime results in the same semantics as `&mut *x` with - // Box - pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T { - unsafe { &mut *self.ptr } - } -} - -// A key ingredient for safety, we associate a destructor with -// Unique, making the struct manage the raw pointer: when the -// struct goes out of scope, it will automatically free the raw pointer. -// -// NB: This is an unsafe destructor, because rustc will not normally -// allow destructors to be associated with parameterized types, due to -// bad interaction with managed boxes. (With the Send restriction, -// we don't have this problem.) Note that the `#[unsafe_destructor]` -// feature gate is required to use unsafe destructors. -#[unsafe_destructor] -impl Drop for Unique { - fn drop(&mut self) { - unsafe { - // Copy the object out from the pointer onto the stack, - // where it is covered by normal Rust destructor semantics - // and cleans itself up, if necessary - ptr::read(self.ptr); - - // clean-up our allocation - free(self.ptr as *mut c_void) - } - } -} - -// A comparison between the built-in `Box` and this reimplementation -fn main() { - { - let mut x = Box::new(5); - *x = 10; - } // `x` is freed here - - { - let mut y = Unique::new(5); - *y.borrow_mut() = 10; - } // `y` is freed here -} -``` - -Notably, the only way to construct a `Unique` is via the `new` -function, and this function ensures that the internal pointer is valid -and hidden in the private field. The two `borrow` methods are safe -because the compiler statically guarantees that objects are never used -before creation or after destruction (unless you use some `unsafe` -code...). - -# Inline assembly - -For extremely low-level manipulations and performance reasons, one -might wish to control the CPU directly. Rust supports using inline -assembly to do this via the `asm!` macro. The syntax roughly matches -that of GCC & Clang: - -```ignore -asm!(assembly template - : output operands - : input operands - : clobbers - : options - ); -``` - -Any use of `asm` is feature gated (requires `#![feature(asm)]` on the -crate to allow) and of course requires an `unsafe` block. - -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. - -## Assembly template - -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) - -``` -#![feature(asm)] - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn foo() { - unsafe { - asm!("NOP"); - } -} - -// other platforms -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn foo() { /* ... */ } - -fn main() { - // ... - foo(); - // ... -} -``` - -(The `feature(asm)` and `#[cfg]`s are omitted from now on.) - -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: - -``` -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -asm!("xor %eax, %eax" - : - : - : "eax" - ); -# } } -``` - -Whitespace also doesn't matter: - -``` -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -asm!("xor %eax, %eax" ::: "eax"); -# } } -``` - -## Operands - -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable lvalues: - -``` -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn add(a: i32, b: i32) -> i32 { - let mut c = 0; - unsafe { - asm!("add $2, $0" - : "=r"(c) - : "0"(a), "r"(b) - ); - } - c -} -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn add(a: i32, b: i32) -> i32 { a + b } - -fn main() { - assert_eq!(add(3, 14159), 14162) -} -``` - -## Clobbers - -Some instructions modify registers which might otherwise have held -different values so we use the clobbers list to indicate to the -compiler not to assume any values loaded into those registers will -stay valid. - -``` -# #![feature(asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -// Put the value 0x200 in eax -asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); -# } } -``` - -Input and output registers need not be listed since that information -is already communicated by the given constraints. Otherwise, any other -registers used either implicitly or explicitly should be listed. - -If the assembly changes the condition code register `cc` should be -specified as one of the clobbers. Similarly, if the assembly modifies -memory, `memory` should also be specified. - -## Options - -The last section, `options` is specific to Rust. The format is comma -separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to -specify some extra info about the inline assembly: - -Current valid options are: - -1. *volatile* - specifying this is analogous to - `__asm__ __volatile__ (...)` in gcc/clang. -2. *alignstack* - certain instructions expect the stack to be - aligned a certain way (i.e. SSE) and specifying this indicates to - the compiler to insert its usual stack alignment code -3. *intel* - use intel syntax instead of the default AT&T. - -# Avoiding the standard library - -By default, `std` is linked to every Rust crate. In some contexts, -this is undesirable, and can be avoided with the `#![no_std]` -attribute attached to the crate. - -```ignore -// a minimal library -#![crate_type="lib"] -#![feature(no_std)] -#![no_std] -# // fn main() {} tricked you, rustdoc! -``` - -Obviously there's more to life than just libraries: one can use -`#[no_std]` with an executable, controlling the entry point is -possible in two ways: the `#[start]` attribute, or overriding the -default shim for the C `main` function with your own. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: - -``` -#![feature(lang_items, start, no_std)] -#![no_std] - -// Pull in the system libc library for what crt0.o likely requires -extern crate libc; - -// Entry point for this program -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions and traits are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "stack_exhausted"] extern fn stack_exhausted() {} -#[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -# // fn main() {} tricked you, rustdoc! -``` - -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: - -```ignore -#![feature(no_std)] -#![no_std] -#![no_main] -#![feature(lang_items, start)] - -extern crate libc; - -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(argc: i32, argv: *const *const u8) -> i32 { - 0 -} - -#[lang = "stack_exhausted"] extern fn stack_exhausted() {} -#[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -# // fn main() {} tricked you, rustdoc! -``` - - -The compiler currently makes a few assumptions about symbols which are available -in the executable to call. Normally these functions are provided by the standard -library, but without it you must define your own. - -The first of these three functions, `stack_exhausted`, is invoked whenever stack -overflow is detected. This function has a number of restrictions about how it -can be called and what it must do, but if the stack limit register is not being -maintained then a thread always has an "infinite stack" and this function -shouldn't get triggered. - -The second of these three functions, `eh_personality`, is used by the -failure mechanisms of the compiler. This is often mapped to GCC's -personality function (see the -[libstd implementation](../std/rt/unwind/index.html) for more -information), but crates which do not trigger a panic can be assured -that this function is never called. The final function, `panic_fmt`, is -also used by the failure mechanisms of the compiler. - -## Using libcore - -> **Note**: the core library's structure is unstable, and it is recommended to -> use the standard library instead wherever possible. - -With the above techniques, we've got a bare-metal executable running some Rust -code. There is a good deal of functionality provided by the standard library, -however, that is necessary to be productive in Rust. If the standard library is -not sufficient, then [libcore](../core/index.html) is designed to be used -instead. - -The core library has very few dependencies and is much more portable than the -standard library itself. Additionally, the core library has most of the -necessary functionality for writing idiomatic and effective Rust code. - -As an example, here is a program that will calculate the dot product of two -vectors provided from C, using idiomatic Rust practices. - -``` -#![feature(lang_items, start, no_std)] -#![no_std] - -# extern crate libc; -extern crate core; - -use core::prelude::*; - -use core::mem; - -#[no_mangle] -pub extern fn dot_product(a: *const u32, a_len: u32, - b: *const u32, b_len: u32) -> u32 { - use core::raw::Slice; - - // Convert the provided arrays into Rust slices. - // The core::raw module guarantees that the Slice - // structure has the same memory layout as a &[T] - // slice. - // - // This is an unsafe operation because the compiler - // cannot tell the pointers are valid. - let (a_slice, b_slice): (&[u32], &[u32]) = unsafe { - mem::transmute(( - Slice { data: a, len: a_len as usize }, - Slice { data: b, len: b_len as usize }, - )) - }; - - // Iterate over the slices, collecting the result - let mut ret = 0; - for (i, j) in a_slice.iter().zip(b_slice.iter()) { - ret += (*i) * (*j); - } - return ret; -} - -#[lang = "panic_fmt"] -extern fn panic_fmt(args: &core::fmt::Arguments, - file: &str, - line: u32) -> ! { - loop {} -} - -#[lang = "stack_exhausted"] extern fn stack_exhausted() {} -#[lang = "eh_personality"] extern fn eh_personality() {} -# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 } -# fn main() {} -``` - -Note that there is one extra lang item here which differs from the examples -above, `panic_fmt`. This must be defined by consumers of libcore because the -core library declares panics, but it does not define it. The `panic_fmt` -lang item is this crate's definition of panic, and it must be guaranteed to -never return. - -As can be seen in this example, the core library is intended to provide the -power of Rust in all circumstances, regardless of platform requirements. Further -libraries, such as liballoc, add functionality to libcore which make other -platform-specific assumptions, but continue to be more portable than the -standard library itself. - -# Interacting with the compiler internals - -> **Note**: this section is specific to the `rustc` compiler; these -> parts of the language may never be fully specified and so details may -> differ wildly between implementations (and even versions of `rustc` -> itself). -> -> Furthermore, this is just an overview; the best form of -> documentation for specific instances of these features are their -> definitions and uses in `std`. - -The Rust language currently has two orthogonal mechanisms for allowing -libraries to interact directly with the compiler and vice versa: - -- intrinsics, functions built directly into the compiler providing - very basic low-level functionality, -- lang-items, special functions, types and traits in libraries marked - with specific `#[lang]` attributes - -## Intrinsics - -> **Note**: intrinsics will forever have an unstable interface, it is -> recommended to use the stable interfaces of libcore rather than intrinsics -> directly. - -These are imported as if they were FFI functions, with the special -`rust-intrinsic` ABI. For example, if one was in a freestanding -context, but wished to be able to `transmute` between types, and -perform efficient pointer arithmetic, one would import those functions -via a declaration like - -``` -# #![feature(intrinsics)] -# fn main() {} - -extern "rust-intrinsic" { - fn transmute(x: T) -> U; - - fn offset(dst: *const T, offset: isize) -> *const T; -} -``` - -As with any other FFI functions, these are always `unsafe` to call. - -## Lang items - -> **Note**: lang items are often provided by crates in the Rust distribution, -> and lang items themselves have an unstable interface. It is recommended to use -> officially distributed crates instead of defining your own lang items. - -The `rustc` compiler has certain pluggable operations, that is, -functionality that isn't hard-coded into the language, but is -implemented in libraries, with a special marker to tell the compiler -it exists. The marker is the attribute `#[lang="..."]` and there are -various different values of `...`, i.e. various different 'lang -items'. - -For example, `Box` pointers require two lang items, one for allocation -and one for deallocation. A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: - -``` -#![feature(lang_items, box_syntax, start, no_std)] -#![no_std] - -extern crate libc; - -extern { - fn abort() -> !; -} - -#[lang = "owned_box"] -pub struct Box(*mut T); - -#[lang="exchange_malloc"] -unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; - - // malloc failed - if p as usize == 0 { - abort(); - } - - p -} -#[lang="exchange_free"] -unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { - libc::free(ptr as *mut libc::c_void) -} - -#[start] -fn main(argc: isize, argv: *const *const u8) -> isize { - let x = box 1; - - 0 -} - -#[lang = "stack_exhausted"] extern fn stack_exhausted() {} -#[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } -``` - -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. - -Other features provided by lang items include: - -- overloadable operators via traits: the traits corresponding to the - `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all - marked with lang items; those specific four are `eq`, `ord`, - `deref`, and `add` respectively. -- stack unwinding and general failure; the `eh_personality`, `fail` - and `fail_bounds_checks` lang items. -- the traits in `std::marker` used to indicate types of - various kinds; lang items `send`, `sync` and `copy`. -- the marker types and variance indicators found in - `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, etc. - -Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define functions for `exchange_malloc` -and `exchange_free`. `rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. diff --git a/src/doc/trpl/unstable.md b/src/doc/trpl/unstable.md new file mode 100644 index 0000000000..e8e02cc9d0 --- /dev/null +++ b/src/doc/trpl/unstable.md @@ -0,0 +1 @@ +% Unstable Rust diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 6b56c2b630..c5c58bb49a 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -12,9 +12,9 @@ #![cfg_attr(rustdoc, feature(rustdoc))] #[cfg(rustdoc)] -extern crate "rustdoc" as this; +extern crate rustdoc as this; #[cfg(rustc)] -extern crate "rustc_driver" as this; +extern crate rustc_driver as this; fn main() { this::main() } diff --git a/src/etc/check-sanitycheck.py b/src/etc/check-sanitycheck.py new file mode 100644 index 0000000000..0d9c430ec3 --- /dev/null +++ b/src/etc/check-sanitycheck.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# +# 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import os +import sys +import functools +import resource + +STATUS = 0 + + +def error_unless_permitted(env_var, message): + global STATUS + if not os.getenv(env_var): + sys.stderr.write(message) + STATUS = 1 + + +def only_on(platforms): + def decorator(func): + @functools.wraps(func) + def inner(): + if any(map(lambda x: sys.platform.startswith(x), platforms)): + func() + return inner + return decorator + + +@only_on(('linux', 'darwin', 'freebsd', 'openbsd')) +def check_rlimit_core(): + soft, hard = resource.getrlimit(resource.RLIMIT_CORE) + if soft > 0: + error_unless_permitted('ALLOW_NONZERO_RLIMIT_CORE', """\ +RLIMIT_CORE is set to a nonzero value (%d). During debuginfo, the test suite +will segfault many rustc's, creating many potentially large core files. +set ALLOW_NONZERO_RLIMIT_CORE to ignore this warning +""" % (soft)) + + +def main(): + check_rlimit_core() + +if __name__ == '__main__': + main() + sys.exit(STATUS) diff --git a/src/etc/featureck.py b/src/etc/featureck.py index ce972c91c8..86fa779cce 100644 --- a/src/etc/featureck.py +++ b/src/etc/featureck.py @@ -242,4 +242,3 @@ print for line in lines: print "* " + line print - diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index c5587bb10d..4e489df7dd 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -27,9 +27,18 @@ def rust_pretty_printer_lookup_function(val): if type_code == gdb.TYPE_CODE_STRUCT: struct_kind = classify_struct(val.type) + if struct_kind == STRUCT_KIND_SLICE: + return RustSlicePrinter(val) + if struct_kind == STRUCT_KIND_STR_SLICE: return RustStringSlicePrinter(val) + if struct_kind == STRUCT_KIND_STD_VEC: + return RustStdVecPrinter(val) + + if struct_kind == STRUCT_KIND_STD_STRING: + return RustStdStringPrinter(val) + if struct_kind == STRUCT_KIND_TUPLE: return RustTuplePrinter(val) @@ -172,6 +181,28 @@ class RustTupleStructPrinter: def display_hint(self): return "array" +class RustSlicePrinter: + def __init__(self, val): + self.val = val + + def display_hint(self): + return "array" + + def to_string(self): + length = int(self.val["length"]) + return self.val.type.tag + ("(len: %i)" % length) + + def children(self): + cs = [] + length = int(self.val["length"]) + data_ptr = self.val["data_ptr"] + assert data_ptr.type.code == gdb.TYPE_CODE_PTR + pointee_type = data_ptr.type.target() + + for index in range(0, length): + cs.append((str(index), (data_ptr + index).dereference())) + + return cs class RustStringSlicePrinter: def __init__(self, val): @@ -181,6 +212,35 @@ class RustStringSlicePrinter: slice_byte_len = self.val["length"] return '"%s"' % self.val["data_ptr"].string(encoding="utf-8", length=slice_byte_len) +class RustStdVecPrinter: + def __init__(self, val): + self.val = val + + def display_hint(self): + return "array" + + def to_string(self): + length = int(self.val["len"]) + cap = int(self.val["cap"]) + return self.val.type.tag + ("(len: %i, cap: %i)" % (length, cap)) + + def children(self): + cs = [] + (length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val) + pointee_type = data_ptr.type.target() + + for index in range(0, length): + cs.append((str(index), (data_ptr + index).dereference())) + return cs + +class RustStdStringPrinter: + def __init__(self, val): + self.val = val + + def to_string(self): + (length, data_ptr) = extract_length_and_data_ptr_from_std_vec(self.val["vec"]) + return '"%s"' % data_ptr.string(encoding="utf-8", length=length) + class RustCStyleEnumPrinter: def __init__(self, val): @@ -204,19 +264,38 @@ STRUCT_KIND_TUPLE = 2 STRUCT_KIND_TUPLE_VARIANT = 3 STRUCT_KIND_STRUCT_VARIANT = 4 STRUCT_KIND_CSTYLE_VARIANT = 5 -STRUCT_KIND_STR_SLICE = 6 +STRUCT_KIND_SLICE = 6 +STRUCT_KIND_STR_SLICE = 7 +STRUCT_KIND_STD_VEC = 8 +STRUCT_KIND_STD_STRING = 9 def classify_struct(type): + # print("\nclassify_struct: tag=%s\n" % type.tag) if type.tag == "&str": return STRUCT_KIND_STR_SLICE + if type.tag.startswith("&[") and type.tag.endswith("]"): + return STRUCT_KIND_SLICE + fields = list(type.fields()) field_count = len(fields) if field_count == 0: return STRUCT_KIND_REGULAR_STRUCT + if (field_count == 3 and + fields[0].name == "ptr" and + fields[1].name == "len" and + fields[2].name == "cap" and + type.tag.startswith("Vec<")): + return STRUCT_KIND_STD_VEC + + if (field_count == 1 and + fields[0].name == "vec" and + type.tag == "String"): + return STRUCT_KIND_STD_STRING + if fields[0].name == "RUST$ENUM$DISR": if field_count == 1: return STRUCT_KIND_CSTYLE_VARIANT @@ -254,3 +333,11 @@ def get_field_at_index(val, index): return field i += 1 return None + +def extract_length_and_data_ptr_from_std_vec(vec_val): + length = int(vec_val["len"]) + vec_ptr_val = vec_val["ptr"] + unique_ptr_val = vec_ptr_val[first_field(vec_ptr_val)] + data_ptr = unique_ptr_val[first_field(unique_ptr_val)] + assert data_ptr.type.code == gdb.TYPE_CODE_PTR + return (length, data_ptr) diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 22792ff763..a212e3a043 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -96,6 +96,9 @@ There are a number of supported commands: highlights for example. If you want to simply check the presence of given node or attribute, use an empty string (`""`) as a `PATTERN`. +* `@count PATH XPATH COUNT' checks for the occurrence of given XPath + in the given file. The number of occurrences must match the given count. + All conditions can be negated with `!`. `@!has foo/type.NoSuch.html` checks if the given file does not exist, for example. @@ -333,6 +336,11 @@ def check_tree_text(tree, path, pat, regexp): return ret +def check_tree_count(tree, path, count): + path = normalize_xpath(path) + return len(tree.findall(path)) == count + + def check(target, commands): cache = CachedFiles(target) for c in commands: @@ -360,6 +368,13 @@ def check(target, commands): raise RuntimeError('Invalid number of @{} arguments \ at line {}'.format(c.cmd, c.lineno)) + elif c.cmd == 'count': # count test + if len(c.args) == 3: # @count = count test + ret = check_tree_count(cache.get_tree(c.args[0]), c.args[1], int(c.args[2])) + else: + raise RuntimeError('Invalid number of @{} arguments \ + at line {}'.format(c.cmd, c.lineno)) + elif c.cmd == 'valid-html': raise RuntimeError('Unimplemented @valid-html at line {}'.format(c.lineno)) diff --git a/src/etc/libc.c b/src/etc/libc.c index 2bf919d7e2..249b5d22b6 100644 --- a/src/etc/libc.c +++ b/src/etc/libc.c @@ -165,6 +165,16 @@ void posix88_consts() { put_const(S_IWUSR, int); put_const(S_IRUSR, int); + put_const(S_IRWXG, int); + put_const(S_IXGRP, int); + put_const(S_IWGRP, int); + put_const(S_IRGRP, int); + + put_const(S_IRWXO, int); + put_const(S_IXOTH, int); + put_const(S_IWOTH, int); + put_const(S_IROTH, int); + #ifdef F_OK put_const(F_OK, int); #endif diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py index 42c83b6a42..20f9b1ce66 100644 --- a/src/etc/lldb_rust_formatters.py +++ b/src/etc/lldb_rust_formatters.py @@ -40,31 +40,12 @@ def print_struct_val(val, internal_dict): if is_vec_slice(val): return print_vec_slice_val(val, internal_dict) + elif is_std_vec(val): + return print_std_vec_val(val, internal_dict) else: return print_struct_val_starting_from(0, val, internal_dict) -def print_vec_slice_val(val, internal_dict): - length = val.GetChildAtIndex(1).GetValueAsUnsigned() - - data_ptr_val = val.GetChildAtIndex(0) - data_ptr_type = data_ptr_val.GetType() - assert data_ptr_type.IsPointerType() - - element_type = data_ptr_type.GetPointeeType() - element_type_size = element_type.GetByteSize() - - start_address = data_ptr_val.GetValueAsUnsigned() - - def render_element(i): - address = start_address + i * element_type_size - element_val = val.CreateValueFromAddress(val.GetName() + - ("[%s]" % i), address, element_type) - return print_val(element_val, internal_dict) - - return "&[%s]" % (', '.join([render_element(i) for i in range(length)])) - - def print_struct_val_starting_from(field_start_index, val, internal_dict): ''' Prints a struct, tuple, or tuple struct value with Rust syntax. @@ -100,6 +81,16 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict): this += field_name + ": " field_val = val.GetChildAtIndex(child_index) + + if not field_val.IsValid(): + field = t.GetFieldAtIndex(child_index) + # LLDB is not good at handling zero-sized values, so we have to help + # it a little + if field.GetType().GetByteSize() == 0: + return this + extract_type_name(field.GetType().GetName()) + else: + return this + "" + return this + print_val(field_val, internal_dict) body = separator.join([render_child(idx) for idx in range(field_start_index, num_children)]) @@ -195,6 +186,30 @@ def print_fixed_size_vec_val(val, internal_dict): return output +def print_vec_slice_val(val, internal_dict): + length = val.GetChildAtIndex(1).GetValueAsUnsigned() + + data_ptr_val = val.GetChildAtIndex(0) + data_ptr_type = data_ptr_val.GetType() + + return "&[%s]" % print_array_of_values(val.GetName(), + data_ptr_val, + length, + internal_dict) + + +def print_std_vec_val(val, internal_dict): + length = val.GetChildAtIndex(1).GetValueAsUnsigned() + + # Vec<> -> Unique<> -> NonZero<> -> *T + data_ptr_val = val.GetChildAtIndex(0).GetChildAtIndex(0).GetChildAtIndex(0) + data_ptr_type = data_ptr_val.GetType() + + return "vec![%s]" % print_array_of_values(val.GetName(), + data_ptr_val, + length, + internal_dict) + #=-------------------------------------------------------------------------------------------------- # Helper Functions #=-------------------------------------------------------------------------------------------------- @@ -243,3 +258,44 @@ def is_vec_slice(val): type_name = extract_type_name(ty.GetName()).replace("&'static", "&").replace(" ", "") return type_name.startswith("&[") and type_name.endswith("]") + +def is_std_vec(val): + ty = val.GetType() + if ty.GetTypeClass() != lldb.eTypeClassStruct: + return False + + if ty.GetNumberOfFields() != 3: + return False + + if ty.GetFieldAtIndex(0).GetName() != "ptr": + return False + + if ty.GetFieldAtIndex(1).GetName() != "len": + return False + + if ty.GetFieldAtIndex(2).GetName() != "cap": + return False + + return ty.GetName().startswith("collections::vec::Vec<") + + +def print_array_of_values(array_name, data_ptr_val, length, internal_dict): + '''Prints a contigous memory range, interpreting it as values of the + pointee-type of data_ptr_val.''' + + data_ptr_type = data_ptr_val.GetType() + assert data_ptr_type.IsPointerType() + + element_type = data_ptr_type.GetPointeeType() + element_type_size = element_type.GetByteSize() + + start_address = data_ptr_val.GetValueAsUnsigned() + + def render_element(i): + address = start_address + i * element_type_size + element_val = data_ptr_val.CreateValueFromAddress(array_name + ("[%s]" % i), + address, + element_type) + return print_val(element_val, internal_dict) + + return ', '.join([render_element(i) for i in range(length)]) diff --git a/src/etc/local_stage0.sh b/src/etc/local_stage0.sh index b506aff94e..ca59b1c7d3 100755 --- a/src/etc/local_stage0.sh +++ b/src/etc/local_stage0.sh @@ -18,7 +18,7 @@ LIB_PREFIX=lib OS=`uname -s` case $OS in - ("Linux"|"FreeBSD"|"DragonFly"|"OpenBSD") + ("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD") BIN_SUF= LIB_SUF=.so ;; diff --git a/src/etc/mingw-fix-include/README.txt b/src/etc/mingw-fix-include/README.txt index 876db17a24..e36e6abde9 100644 --- a/src/etc/mingw-fix-include/README.txt +++ b/src/etc/mingw-fix-include/README.txt @@ -1,6 +1,6 @@ The purpose of these headers is to fix issues with mingw v4.0, as described in #9246. -This works by adding this directory to GCC include search path before mingw system headers directories, +This works by adding this directory to GCC include search path before mingw system headers directories, so we can intercept their inclusions and add missing definitions without having to modify files in mingw/include. Once mingw fixes all 3 issues mentioned in #9246, this directory and all references to it from rust/mk/* may be removed. diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py index a4234159cb..e5e8c9f11b 100644 --- a/src/etc/mklldeps.py +++ b/src/etc/mklldeps.py @@ -57,7 +57,16 @@ else: args.extend(components) out = run(args) for lib in out.strip().replace("\n", ' ').split(' '): - lib = lib.strip()[2:] # chop of the leading '-l' + if len(lib) == 0: + continue + # in some cases we get extra spaces in between libs so ignore those + if len(lib) == 1 and lib == ' ': + continue + # not all libs strictly follow -lfoo, on Bitrig, there is -pthread + if lib[0:2] == '-l': + lib = lib.strip()[2:] + elif lib[0] == '-': + lib = lib.strip()[1:] f.write("#[link(name = \"" + lib + "\"") # LLVM libraries are all static libraries if 'LLVM' in lib: diff --git a/src/etc/rustup.sh b/src/etc/rustup.sh index d4f1071c72..918c0c66f7 100755 --- a/src/etc/rustup.sh +++ b/src/etc/rustup.sh @@ -288,6 +288,7 @@ VAL_OPTIONS="" flag uninstall "only uninstall from the installation prefix" valopt prefix "" "set installation prefix" valopt date "" "use the YYYY-MM-DD nightly instead of the current nightly" +valopt channel "beta" "use the selected release channel [beta]" flag save "save the downloaded nightlies to ~/.rustup" if [ $HELP -eq 1 ] @@ -307,7 +308,7 @@ CFG_CPUTYPE=$(uname -m) if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ] then - # Darwin's `uname -s` lies and always returns i386. We have to use sysctl + # Darwin's `uname -m` lies and always returns i386. We have to use sysctl # instead. if sysctl hw.optional.x86_64 | grep -q ': 1' then @@ -335,7 +336,7 @@ case $CFG_OSTYPE in MINGW32*) CFG_OSTYPE=pc-mingw32 ;; -# Thad's Cygwin identifers below +# Thad's Cygwin identifiers below # Vista 32 bit CYGWIN_NT-6.0) @@ -437,7 +438,7 @@ CFG_TMP_DIR=$(mktemp -d 2>/dev/null \ || create_tmp_dir) # If we're saving nightlies and we didn't specify which one, grab the latest -# verison from the perspective of the server. Buildbot has typically finished +# version from the perspective of the server. Buildbot has typically finished # building and uploading by ~8UTC, but we want to include a little buffer. # # FIXME It would be better to use the known most recent nightly that has been @@ -449,18 +450,28 @@ then fi RUST_URL="https://static.rust-lang.org/dist" -RUST_PACKAGE_NAME=rust-nightly +case "$CFG_CHANNEL" in + nightly) + # add a date suffix if we want a particular nightly. + if [ -n "${CFG_DATE}" ]; + then + RUST_URL="${RUST_URL}/${CFG_DATE}" + fi + + RUST_PACKAGE_NAME=rust-nightly + ;; + beta) + RUST_PACKAGE_NAME=rust-1.0.0-beta + ;; + *) + err "Currently 'beta' and 'nightly' are the only supported channels" +esac + RUST_PACKAGE_NAME_AND_TRIPLE="${RUST_PACKAGE_NAME}-${HOST_TRIPLE}" 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" -# add a date suffix if we want a particular nighly. -if [ -n "${CFG_DATE}" ]; -then - RUST_URL="${RUST_URL}/${CFG_DATE}" -fi - download_hash() { msg "Downloading ${remote_sha256}" remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"` diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index 264af5f985..0349ccf9b6 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -46,13 +46,13 @@ snapshot_files = { "winnt": ["bin/rustc.exe"], "freebsd": ["bin/rustc"], "dragonfly": ["bin/rustc"], + "bitrig": ["bin/rustc"], "openbsd": ["bin/rustc"], } winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"] winnt_runtime_deps_64 = ["libgcc_s_seh-1.dll", "libstdc++-6.dll"] - def parse_line(n, line): global snapshotfile @@ -101,6 +101,8 @@ def get_kernel(triple): return "freebsd" if os_name == "dragonfly": return "dragonfly" + if os_name == "bitrig": + return "bitrig" if os_name == "openbsd": return "openbsd" return "linux" diff --git a/src/etc/snapshot.pyc b/src/etc/snapshot.pyc index 8c6cf9addc8995d436807763eef12d0e7a59739b..05ba658a918cee76555609ed16aecf423f43a1d3 100644 GIT binary patch delta 1535 zcmZ8gOKe+J5WVw~+VwAKe*VOc9mk(INgL5Z=z>O23Q@u*MYnu}RW*6Zb!=1DcJ0?l z4TY!@S&*iMFqXrqf5<3G<1Z8^F)A@)peaiH!qNVbK z$_)I=qsj!;2TJ8*%7larDH9eFS0*APq0FF=VP&F1lFGz{j3_fCB&AGTNLrbMkc^r) z!@{!4B!!GBGa@9XOiIX@GHD^>%4CF0D3cX(RGCpB$CLqeE|+UfT1m_6q9T{dPNQ6G z&39h4U=T0+-@y~^TfPu^beN%EY*U9ff(LBma5@M|%@Xbgig?m91)t$1&yC#_wV%RqeS+sq_zA@S+XK|zn-15B-HT3!4JTl3K z6YPSv>#~0hR$IUMPXerAy6bB=g+F!ez&dVrpLNafoH6{RdjmFbx+jKTbf8w@;+=sI+{JqX-@u#*_%IlNFI$g-+wkgXTIaY43f0we zqgK@{ff(wxQ)(9K`gtD(DmPckm4Z;aUN2OQgwOE~bUHtT@562jBe$&~$&WYF z;|vmqPl>lYgR`+Mc+mPW=7)7r_eq}f62mJDvMxnTGI8t%2i1#g=px|qnx&evz~-jj zmx7}lNSNg-R%%Oai8v2w6x$fx;K5-6T#O%e86rA^pTtKmOt6D1y;x{e3l-hZE@?h) zIft(!M}0!C@{lW{^mL8>y3PYuVx_vkVTE6^o#hfGDKgGsD6s+GwLVWo!58E;?LNlU zR0@9`K9Y~JZIK~C;CKic1>020RoY^NOg>1v&lw3-T5@ zbP``nZo(g}pOe=C?Nr#(VG4SFU4*~EGyWS|Z?TOd>YEJGWEo;P9}ih2eT#whIS^Y8 z>LYff8UCLI+dd}9(Z_(-{0q2~j)E5-q-PRxl5&V#lYW=sD#LY#DLkGDN6!)!WlMIm zR4FgD8@^;8*B8)ao*H<8r%JkeovRc0Rc5ZR#-1X>3WF5KO{Tdny?4vCXmW~ea#d%U z?e}J$hvyljYq*j0Cc`!Z%00fH?SUnHn0;p43xN(l_$^P!bBNxc$L;B)zl)IHJ{r3S Ik9i{h0H13sApigX delta 1433 zcmZ9LO>7%g5XaxMQ#e#{F zloW}EuL{wGq;xJE5f_9wl*$MY7d|eLia2lu32{O~93q5-5GQ8Fg($?zZ~rs%-oBaH zdHeHU&YRvp!of!Mmvf8a&fgJyR`I_xaLbHJ>4UrFiOq$S&{3gdV%Z}W(n1gat4*Qf z;te4dGD45A$O@fckrO(}A}@4`MM3B^i=xmbi&3F7EJ{LWS(Js&v8V{0XE7%9$pWi! zp^Gdmp+{L96}rS?Lg+G!yM(T=m=t=9#gx!eoVCWg4|$57uI}6L$Q1nSe;!WxcZ?CN zR3!*8^z9$Af9U@}Zo_MVEuS{<1tBN}=U_GXnan}OD8ggLNm+qiqhMIL-}2B)Cg2O> zid==`q4SX`avY9 zC<8Ym_Z&D|aCRsm-^9QPIfsi{kc?*JR`-GEvK*Yot!^J;(QY(U6+ViYG7EdLTXGjJ z5AT(d^y(BLOE3|fG4JU#?KRcw$#-#6z7M~~Kb5E9y^$B?huvi29cfi@z3WFf%}Xoo zR#Q>Q>{zqiddFE)52HiP!uQFvK_^(W7<>9>^0vI${W|roC(9|&K6R8(MYvuB?Vg28 znQeKy>&=GbCO7UrT62c*IDz+#qT)kcyS=p1a8!*P0|=_1Q*XI7a(C20wN(t>$&J=h zhn5?y3%xE-9-M-$wR(Y!egy2~CVg}rR2ja?jXyg<0UzR`({4Hq6{8T33=NM<_k~Wq zSFMvt6=8a+iBHucgF3O)tkJQoS8aE(j!AOIPQzUOs{E$=ZQhhdoc8o45`Hh-Kba<* zYE(Id8$h%jTQ^pkxV=a&s^?sL-BDS1vY3k;O!IjRr~+ImUX%OX!04+o9VHLvK1}NH zStZyj9pB`hU!&;Zlhqda=s>ki;1MdLvJ5h*LF#P+z1|HXmRjpg%^ySUP@qKke|F^C zMbNh;z;FH<{8Tn&Km1*OG|wNgiXkNlFA+8fuMno8R!N%kD7mS1yHjthT;fz&?}0uiPF diff --git a/src/etc/third-party/COPYING.RUNTIME b/src/etc/third-party/COPYING.RUNTIME index e1b3c69c17..e86f7fb58a 100644 --- a/src/etc/third-party/COPYING.RUNTIME +++ b/src/etc/third-party/COPYING.RUNTIME @@ -70,4 +70,3 @@ consistent with the licensing of the Independent Modules. The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. - diff --git a/src/etc/tidy.py b/src/etc/tidy.py index fd3309dce1..c524fae7f0 100644 --- a/src/etc/tidy.py +++ b/src/etc/tidy.py @@ -13,7 +13,7 @@ import fileinput import subprocess import re import os -from licenseck import * +from licenseck import check_license import snapshot err = 0 @@ -22,13 +22,8 @@ cr_flag = "ignore-tidy-cr" tab_flag = "ignore-tidy-tab" linelength_flag = "ignore-tidy-linelength" -# Be careful to support Python 2.4, 2.6, and 3.x here! -config_proc = subprocess.Popen(["git", "config", "core.autocrlf"], - stdout=subprocess.PIPE) -result = config_proc.communicate()[0] - -true = "true".encode('utf8') -autocrlf = result.strip() == true if result is not None else False +interesting_files = ['.rs', '.py', '.js', '.sh', '.c', '.h'] +uninteresting_files = ['miniz.c', 'jquery', 'rust_android_dummy'] def report_error_name_no(name, no, s): @@ -51,6 +46,34 @@ def do_license_check(name, contents): if not check_license(name, contents): report_error_name_no(name, 1, "incorrect license") + +def update_counts(current_name): + global file_counts + global count_other_linted_files + + _, ext = os.path.splitext(current_name) + + if ext in interesting_files: + file_counts[ext] += 1 + else: + count_other_linted_files += 1 + + +def interesting_file(f): + if any(x in f for x in uninteresting_files): + return False + + return any(os.path.splitext(f)[1] == ext for ext in interesting_files) + + +# Be careful to support Python 2.4, 2.6, and 3.x here! +config_proc = subprocess.Popen(["git", "config", "core.autocrlf"], + stdout=subprocess.PIPE) +result = config_proc.communicate()[0] + +true = "true".encode('utf8') +autocrlf = result.strip() == true if result is not None else False + current_name = "" current_contents = "" check_tab = True @@ -63,28 +86,16 @@ if len(sys.argv) < 2: src_dir = sys.argv[1] -try: - count_lines = 0 - count_non_blank_lines = 0 +count_lines = 0 +count_non_blank_lines = 0 +count_other_linted_files = 0 - interesting_files = ['.rs', '.py', '.js', '.sh', '.c', '.h'] +file_counts = {ext: 0 for ext in interesting_files} - file_counts = {ext: 0 for ext in interesting_files} - file_counts['other'] = 0 - - def update_counts(current_name): - global file_counts - _, ext = os.path.splitext(current_name) - - if ext in file_counts: - file_counts[ext] += 1 - else: - file_counts['other'] += 1 - - all_paths = set() +all_paths = set() +try: for (dirpath, dirnames, filenames) in os.walk(src_dir): - # Skip some third-party directories skippable_dirs = { 'src/jemalloc', @@ -103,14 +114,6 @@ try: if any(d in dirpath for d in skippable_dirs): continue - def interesting_file(f): - if "miniz.c" in f \ - or "jquery" in f \ - or "rust_android_dummy" in f: - return False - - return any(os.path.splitext(f)[1] == ext for ext in interesting_files) - file_names = [os.path.join(dirpath, f) for f in filenames if interesting_file(f) and not f.endswith("_gen.rs") @@ -196,10 +199,11 @@ except UnicodeDecodeError as e: report_err("UTF-8 decoding error " + str(e)) print -for ext in file_counts: - print "* linted " + str(file_counts[ext]) + " " + ext + " files" -print "* total lines of code: " + str(count_lines) -print "* total non-blank lines of code: " + str(count_non_blank_lines) +for ext in sorted(file_counts, key=file_counts.get, reverse=True): + print "* linted {} {} files".format(file_counts[ext], ext) +print "* linted {} other files".format(count_other_linted_files) +print "* total lines of code: {}".format(count_lines) +print "* total non-blank lines of code: {}".format(count_non_blank_lines) print sys.exit(err) diff --git a/src/etc/unicode.py b/src/etc/unicode.py index dc8716d137..312076b1b1 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -84,8 +84,8 @@ def fetch(f): sys.stderr.write("cannot load %s" % f) exit(1) -def is_valid_unicode(n): - return 0 <= n <= 0xD7FF or 0xE000 <= n <= 0x10FFFF +def is_surrogate(n): + return 0xD800 <= n <= 0xDFFF def load_unicode_data(f): fetch(f) @@ -96,19 +96,28 @@ def load_unicode_data(f): canon_decomp = {} compat_decomp = {} + udict = {}; + range_start = -1; for line in fileinput.input(f): - fields = line.split(";") - if len(fields) != 15: + data = line.split(';'); + if len(data) != 15: continue - [code, name, gencat, combine, bidi, - decomp, deci, digit, num, mirror, - old, iso, upcase, lowcase, titlecase ] = fields - - code_org = code - code = int(code, 16) - - if not is_valid_unicode(code): + cp = int(data[0], 16); + if is_surrogate(cp): continue + if range_start >= 0: + for i in xrange(range_start, cp): + udict[i] = data; + range_start = -1; + if data[1].endswith(", First>"): + range_start = cp; + continue; + udict[cp] = data; + + for code in udict: + [code_org, name, gencat, combine, bidi, + decomp, deci, digit, num, mirror, + old, iso, upcase, lowcase, titlecase ] = udict[code]; # generate char to char direct common and simple conversions # uppercase to lowercase @@ -290,11 +299,11 @@ def emit_bsearch_range_table(f): fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { use core::cmp::Ordering::{Equal, Less, Greater}; use core::slice::SliceExt; - r.binary_search(|&(lo,hi)| { + r.binary_search_by(|&(lo,hi)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } - }).found().is_some() + }).is_ok() }\n """) @@ -303,7 +312,7 @@ def emit_table(f, name, t_data, t_type = "&'static [(char, char)]", is_pub=True, pub_string = "" if is_pub: pub_string = "pub " - f.write(" %sstatic %s: %s = &[\n" % (pub_string, name, t_type)) + f.write(" %sconst %s: %s = &[\n" % (pub_string, name, t_type)) data = "" first = True for dat in t_data: @@ -329,14 +338,14 @@ def emit_property_module(f, mod, tbl, emit_fn): def emit_regex_module(f, cats, w_data): f.write("pub mod regex {\n") regex_class = "&'static [(char, char)]" - class_table = "&'static [(&'static str, &'static %s)]" % regex_class + class_table = "&'static [(&'static str, %s)]" % regex_class emit_table(f, "UNICODE_CLASSES", cats, class_table, - pfun=lambda x: "(\"%s\",&super::%s::%s_table)" % (x[0], x[1], x[0])) + pfun=lambda x: "(\"%s\",super::%s::%s_table)" % (x[0], x[1], x[0])) - f.write(" pub static PERLD: &'static %s = &super::general_category::Nd_table;\n\n" + f.write(" pub const PERLD: %s = super::general_category::Nd_table;\n\n" % regex_class) - f.write(" pub static PERLS: &'static %s = &super::property::White_Space_table;\n\n" + f.write(" pub const PERLS: %s = super::property::White_Space_table;\n\n" % regex_class) emit_table(f, "PERLW", w_data, regex_class) @@ -350,7 +359,7 @@ def emit_conversions_module(f, lowerupper, upperlower): use core::slice::SliceExt; use core::option::Option; use core::option::Option::{Some, None}; - use core::slice; + use core::result::Result::{Ok, Err}; pub fn to_lower(c: char) -> char { match bsearch_case_table(c, LuLl_table) { @@ -367,13 +376,13 @@ def emit_conversions_module(f, lowerupper, upperlower): } fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option { - match table.binary_search(|&(key, _)| { + match table.binary_search_by(|&(key, _)| { if c == key { Equal } else if key < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(i) => Some(i), - slice::BinarySearchResult::NotFound(_) => None, + Ok(i) => Some(i), + Err(_) => None, } } @@ -386,10 +395,9 @@ def emit_conversions_module(f, lowerupper, upperlower): def emit_grapheme_module(f, grapheme_table, grapheme_cats): f.write("""pub mod grapheme { - use core::kinds::Copy; use core::slice::SliceExt; pub use self::GraphemeCat::*; - use core::slice; + use core::result::Result::{Ok, Err}; #[allow(non_camel_case_types)] #[derive(Clone, Copy)] @@ -401,16 +409,16 @@ def emit_grapheme_module(f, grapheme_table, grapheme_cats): fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat { use core::cmp::Ordering::{Equal, Less, Greater}; - match r.binary_search(|&(lo, hi, _)| { + match r.binary_search_by(|&(lo, hi, _)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, _, cat) = r[idx]; cat } - slice::BinarySearchResult::NotFound(_) => GC_Any + Err(_) => GC_Any } } @@ -430,20 +438,20 @@ def emit_charwidth_module(f, width_table): f.write(" use core::option::Option;\n") f.write(" use core::option::Option::{Some, None};\n") f.write(" use core::slice::SliceExt;\n") - f.write(" use core::slice;\n") + f.write(" use core::result::Result::{Ok, Err};\n") f.write(""" fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 { use core::cmp::Ordering::{Equal, Less, Greater}; - match r.binary_search(|&(lo, hi, _, _)| { + match r.binary_search_by(|&(lo, hi, _, _)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, _, r_ncjk, r_cjk) = r[idx]; if is_cjk { r_cjk } else { r_ncjk } } - slice::BinarySearchResult::NotFound(_) => 1 + Err(_) => 1 } } """) @@ -530,17 +538,17 @@ def emit_norm_module(f, canon, compat, combine, norm_props): fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 { use core::cmp::Ordering::{Equal, Less, Greater}; use core::slice::SliceExt; - use core::slice; - match r.binary_search(|&(lo, hi, _)| { + use core::result::Result::{Ok, Err}; + match r.binary_search_by(|&(lo, hi, _)| { if lo <= c && c <= hi { Equal } else if hi < c { Less } else { Greater } }) { - slice::BinarySearchResult::Found(idx) => { + Ok(idx) => { let (_, _, result) = r[idx]; result } - slice::BinarySearchResult::NotFound(_) => 0 + Err(_) => 0 } }\n """) @@ -609,7 +617,7 @@ if __name__ == "__main__": unicode_version = re.search(pattern, readme.read()).groups() rf.write(""" /// 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: (u64, u64, u64) = (%s, %s, %s); """ % unicode_version) (canon_decomp, compat_decomp, gencats, combines, diff --git a/src/jemalloc/VERSION b/src/jemalloc/VERSION index 2d2a25e9e0..595434747d 100644 --- a/src/jemalloc/VERSION +++ b/src/jemalloc/VERSION @@ -1 +1 @@ -0.12.0-5823-g522d09dfecbeca1595f25ac58c6d0178bbd21d7d +0.12.0-7693-g9854143cba679834bc4ef932858cd5303f015a0e diff --git a/src/jemalloc/configure b/src/jemalloc/configure index b584c44d8a..5a2b1c9175 100755 --- a/src/jemalloc/configure +++ b/src/jemalloc/configure @@ -4880,6 +4880,12 @@ case "${host}" in abi="elf" $as_echo "#define JEMALLOC_PURGE_MADVISE_FREE " >>confdefs.h + ;; + *-*-openbsd*|*-*-bitrig*) + CFLAGS="$CFLAGS" + abi="elf" + $as_echo "#define JEMALLOC_PURGE_MADVISE_FREE " >>confdefs.h + ;; *-*-linux*) CFLAGS="$CFLAGS" diff --git a/src/jemalloc/configure.ac b/src/jemalloc/configure.ac index e4afe88906..fd7554d668 100644 --- a/src/jemalloc/configure.ac +++ b/src/jemalloc/configure.ac @@ -288,6 +288,11 @@ case "${host}" in abi="elf" AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) ;; + *-*-openbsd*|*-*-bitrig*) + CFLAGS="$CFLAGS" + abi="elf" + AC_DEFINE([JEMALLOC_PURGE_MADVISE_FREE], [ ]) + ;; *-*-linux*) CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 934e6ab215..8b884c5650 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -33,7 +33,7 @@ //! //! Sharing some immutable data between tasks: //! -//! ``` +//! ```no_run //! use std::sync::Arc; //! use std::thread; //! @@ -50,7 +50,7 @@ //! //! Sharing mutable data safely between tasks with a `Mutex`: //! -//! ``` +//! ```no_run //! use std::sync::{Arc, Mutex}; //! use std::thread; //! @@ -69,12 +69,14 @@ //! } //! ``` +use boxed::Box; + use core::prelude::*; use core::atomic; use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; use core::fmt; -use core::cmp::{Ordering}; +use core::cmp::Ordering; use core::default::Default; use core::mem::{min_align_of, size_of}; use core::mem; @@ -86,13 +88,17 @@ use heap::deallocate; /// An atomically reference counted wrapper for shared state. /// -/// # Example +/// # Examples /// /// In this example, a large vector of floats is shared between several tasks. /// With simple pipes, without `Arc`, a copy would have to be made for each /// task. /// -/// ```rust +/// When you clone an `Arc`, it will create another pointer to the data and +/// increase the reference counter. +/// +/// ``` +/// # #![feature(alloc, core)] /// use std::sync::Arc; /// use std::thread; /// @@ -104,7 +110,7 @@ use heap::deallocate; /// let child_numbers = shared_numbers.clone(); /// /// thread::spawn(move || { -/// let local_numbers = child_numbers.as_slice(); +/// let local_numbers = &child_numbers[..]; /// /// // Work with the local numbers /// }); @@ -125,8 +131,8 @@ unsafe impl Sync for Arc { } /// A weak pointer to an `Arc`. /// -/// Weak pointers will not keep the data inside of the `Arc` alive, and can be used to break cycles -/// between `Arc` pointers. +/// Weak pointers will not keep the data inside of the `Arc` alive, and can be +/// used to break cycles between `Arc` pointers. #[unsafe_no_drop_flag] #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module.")] @@ -139,6 +145,13 @@ pub struct Weak { unsafe impl Send for Weak { } unsafe impl Sync for Weak { } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "(Weak)") + } +} + struct ArcInner { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, @@ -163,7 +176,7 @@ impl Arc { pub fn new(data: T) -> Arc { // Start the weak pointer count as 1 which is the weak pointer that's // held by all the strong pointers (kinda), see std/rc.rs for more info - let x = box ArcInner { + let x: Box<_> = box ArcInner { strong: atomic::AtomicUsize::new(1), weak: atomic::AtomicUsize::new(1), data: data, @@ -176,6 +189,7 @@ impl Arc { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// let five = Arc::new(5); @@ -194,12 +208,28 @@ impl Arc { impl Arc { #[inline] fn inner(&self) -> &ArcInner { - // This unsafety is ok because while this arc is alive we're guaranteed that the inner - // pointer is valid. Furthermore, we know that the `ArcInner` structure itself is `Sync` - // because the inner data is `Sync` as well, so we're ok loaning out an immutable pointer - // to these contents. + // This unsafety is ok because while this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` because the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. unsafe { &**self._ptr } } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + let ptr = *self._ptr; + + // Destroy the data at this time, even though we may not free the box + // allocation itself (there may still be weak pointers lying around). + drop(ptr::read(&self.inner().data)); + + if self.inner().weak.fetch_sub(1, Release) == 1 { + atomic::fence(Acquire); + deallocate(ptr as *mut u8, size_of::>(), min_align_of::>()) + } + } } /// Get the number of weak references to this value. @@ -212,6 +242,41 @@ pub fn weak_count(this: &Arc) -> usize { this.inner().weak.load(SeqCst) - #[unstable(feature = "alloc")] pub fn strong_count(this: &Arc) -> usize { this.inner().strong.load(SeqCst) } + +/// Try accessing a mutable reference to the contents behind an unique `Arc`. +/// +/// The access is granted only if this is the only reference to the object. +/// Otherwise, `None` is returned. +/// +/// # Examples +/// +/// ``` +/// # #![feature(alloc)] +/// extern crate alloc; +/// # fn main() { +/// use alloc::arc; +/// +/// let mut four = arc::Arc::new(4); +/// +/// arc::unique(&mut four).map(|num| *num = 5); +/// # } +/// ``` +#[inline] +#[unstable(feature = "alloc")] +pub fn unique(this: &mut Arc) -> Option<&mut T> { + if strong_count(this) == 1 && weak_count(this) == 0 { + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + let inner = unsafe { &mut **this._ptr }; + Some(&mut inner.data) + }else { + None + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Arc { /// Makes a clone of the `Arc`. @@ -221,6 +286,7 @@ impl Clone for Arc { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// let five = Arc::new(5); @@ -229,13 +295,15 @@ impl Clone for Arc { /// ``` #[inline] fn clone(&self) -> Arc { - // Using a relaxed ordering is alright here, as knowledge of the original reference - // prevents other threads from erroneously deleting the object. + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object. // - // As explained in the [Boost documentation][1], Increasing the reference counter can - // always be done with memory_order_relaxed: New references to an object can only be formed - // from an existing reference, and passing an existing reference from one thread to another - // must already provide any required synchronization. + // As explained in the [Boost documentation][1], Increasing the + // reference counter can always be done with memory_order_relaxed: New + // references to an object can only be formed from an existing + // reference, and passing an existing reference from one thread to + // another must already provide any required synchronization. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) self.inner().strong.fetch_add(1, Relaxed); @@ -253,15 +321,16 @@ impl Deref for Arc { } } -impl Arc { +impl Arc { /// Make a mutable reference from the given `Arc`. /// - /// This is also referred to as a copy-on-write operation because the inner data is cloned if - /// the reference count is greater than one. + /// This is also referred to as a copy-on-write operation because the inner + /// data is cloned if the reference count is greater than one. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// let mut five = Arc::new(5); @@ -271,16 +340,15 @@ impl Arc { #[inline] #[unstable(feature = "alloc")] pub fn make_unique(&mut self) -> &mut T { - // Note that we hold a strong reference, which also counts as a weak reference, so we only - // clone if there is an additional reference of either kind. + // Note that we hold a strong reference, which also counts as a weak + // reference, so we only clone if there is an additional reference of + // either kind. if self.inner().strong.load(SeqCst) != 1 || self.inner().weak.load(SeqCst) != 1 { *self = Arc::new((**self).clone()) } - // This unsafety is ok because we're guaranteed that the pointer returned is the *only* - // pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at - // this point, and we required the Arc itself to be `mut`, so we're returning the only - // possible reference to the inner data. + // As with `unique()`, the unsafety is ok because our reference was + // either unique to begin with, or became one upon cloning the contents. let inner = unsafe { &mut **self._ptr }; &mut inner.data } @@ -288,15 +356,17 @@ impl Arc { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Arc { +impl Drop for Arc { /// Drops the `Arc`. /// - /// This will decrement the strong reference count. If the strong reference count becomes zero - /// and the only other references are `Weak` ones, `drop`s the inner value. + /// This will decrement the strong reference count. If the strong reference + /// count becomes zero and the only other references are `Weak` ones, + /// `drop`s the inner value. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// { @@ -313,58 +383,59 @@ impl Drop for Arc { /// /// } // implicit drop /// ``` + #[inline] fn drop(&mut self) { - // This structure has #[unsafe_no_drop_flag], so this drop glue may run more than once (but - // it is guaranteed to be zeroed after the first if it's run more than once) + // This structure has #[unsafe_no_drop_flag], so this drop glue may run + // more than once (but it is guaranteed to be zeroed after the first if + // it's run more than once) let ptr = *self._ptr; - if ptr.is_null() { return } + // if ptr.is_null() { return } + if ptr.is_null() || ptr as usize == mem::POST_DROP_USIZE { return } - // Because `fetch_sub` is already atomic, we do not need to synchronize with other threads - // unless we are going to delete the object. This same logic applies to the below - // `fetch_sub` to the `weak` count. + // Because `fetch_sub` is already atomic, we do not need to synchronize + // with other threads unless we are going to delete the object. This + // same logic applies to the below `fetch_sub` to the `weak` count. if self.inner().strong.fetch_sub(1, Release) != 1 { return } - // This fence is needed to prevent reordering of use of the data and deletion of the data. - // Because it is marked `Release`, the decreasing of the reference count synchronizes with - // this `Acquire` fence. This means that use of the data happens before decreasing the - // reference count, which happens before this fence, which happens before the deletion of - // the data. + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. // // As explained in the [Boost documentation][1], // - // > It is important to enforce any possible access to the object in one thread (through an - // > existing reference) to *happen before* deleting the object in a different thread. This - // > is achieved by a "release" operation after dropping a reference (any access to the - // > object through this reference must obviously happened before), and an "acquire" - // > operation before deleting the object. + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) atomic::fence(Acquire); - // Destroy the data at this time, even though we may not free the box allocation itself - // (there may still be weak pointers lying around). - unsafe { drop(ptr::read(&self.inner().data)); } - - if self.inner().weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); - unsafe { deallocate(ptr as *mut u8, size_of::>(), - min_align_of::>()) } + unsafe { + self.drop_slow() } } } #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module.")] -impl Weak { +impl Weak { /// Upgrades a weak reference to a strong reference. /// /// Upgrades the `Weak` reference to an `Arc`, if possible. /// - /// Returns `None` if there were no strong references and the data was destroyed. + /// Returns `None` if there were no strong references and the data was + /// destroyed. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// let five = Arc::new(5); @@ -374,8 +445,8 @@ impl Weak { /// let strong_five: Option> = weak_five.upgrade(); /// ``` pub fn upgrade(&self) -> Option> { - // We use a CAS loop to increment the strong count instead of a fetch_add because once the - // count hits 0 is must never be above 0. + // We use a CAS loop to increment the strong count instead of a + // fetch_add because once the count hits 0 is must never be above 0. let inner = self.inner(); loop { let n = inner.strong.load(SeqCst); @@ -394,7 +465,7 @@ impl Weak { #[unstable(feature = "alloc", reason = "Weak pointers may not belong in this module.")] -impl Clone for Weak { +impl Clone for Weak { /// Makes a clone of the `Weak`. /// /// This increases the weak reference count. @@ -402,6 +473,7 @@ impl Clone for Weak { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// let weak_five = Arc::new(5).downgrade(); @@ -418,7 +490,7 @@ impl Clone for Weak { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Weak { +impl Drop for Weak { /// Drops the `Weak`. /// /// This will decrement the weak reference count. @@ -426,6 +498,7 @@ impl Drop for Weak { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::sync::Arc; /// /// { @@ -448,10 +521,11 @@ impl Drop for Weak { let ptr = *self._ptr; // see comments above for why this check is here - if ptr.is_null() { return } + if ptr.is_null() || ptr as usize == mem::POST_DROP_USIZE { return } - // If we find out that we were the last weak pointer, then its time to deallocate the data - // entirely. See the discussion in Arc::drop() about the memory orderings + // If we find out that we were the last weak pointer, then its time to + // deallocate the data entirely. See the discussion in Arc::drop() about + // the memory orderings if self.inner().weak.fetch_sub(1, Release) == 1 { atomic::fence(Acquire); unsafe { deallocate(ptr as *mut u8, size_of::>(), @@ -598,13 +672,6 @@ impl Default for Arc { fn default() -> Arc { Arc::new(Default::default()) } } -#[cfg(stage0)] -impl> Hash for Arc { - fn hash(&self, state: &mut H) { - (**self).hash(state) - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Arc { fn hash(&self, state: &mut H) { @@ -624,7 +691,7 @@ mod tests { use std::sync::atomic::Ordering::{Acquire, SeqCst}; use std::thread; use std::vec::Vec; - use super::{Arc, Weak, weak_count, strong_count}; + use super::{Arc, Weak, weak_count, strong_count, unique}; use std::sync::Mutex; struct Canary(*mut atomic::AtomicUsize); @@ -660,6 +727,21 @@ mod tests { assert_eq!((*arc_v)[4], 5); } + #[test] + fn test_arc_unique() { + let mut x = Arc::new(10); + assert!(unique(&mut x).is_some()); + { + let y = x.clone(); + assert!(unique(&mut x).is_none()); + } + { + let z = x.downgrade(); + assert!(unique(&mut x).is_none()); + } + assert!(unique(&mut x).is_some()); + } + #[test] fn test_cowarc_clone_make_unique() { let mut cow0 = Arc::new(75); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index a3516bd667..2801cf38cb 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -42,7 +42,7 @@ //! } //! ``` //! -//! This will print `Cons(1i32, Box(Cons(2i32, Box(Nil))))`. +//! This will print `Cons(1, Box(Cons(2, Box(Nil))))`. #![stable(feature = "rust1", since = "1.0.0")] @@ -51,20 +51,20 @@ use core::prelude::*; use core::any::Any; use core::cmp::Ordering; use core::default::Default; -use core::error::{Error, FromError}; use core::fmt; use core::hash::{self, Hash}; use core::mem; use core::ops::{Deref, DerefMut}; -use core::ptr::Unique; -use core::raw::TraitObject; +use core::ptr::{Unique}; +use core::raw::{TraitObject}; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. /// /// The following two examples are equivalent: /// -/// ```rust +/// ``` +/// # #![feature(alloc)] /// #![feature(box_syntax)] /// use std::boxed::HEAP; /// @@ -83,6 +83,7 @@ pub static HEAP: () = (); /// See the [module-level documentation](../../std/boxed/index.html) for more. #[lang = "owned_box"] #[stable(feature = "rust1", since = "1.0.0")] +#[fundamental] pub struct Box(Unique); impl Box { @@ -94,6 +95,7 @@ impl Box { /// let x = Box::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] pub fn new(x: T) -> Box { box x } @@ -105,15 +107,16 @@ impl Box { /// After this function call, pointer is owned by resulting box. /// In particular, it means that `Box` destructor calls destructor /// of `T` and releases memory. Since the way `Box` allocates and - /// releases memory is unspecified, so the only valid pointer to - /// pass to this function is the one taken from another `Box` with - /// `box::into_raw` function. + /// releases memory is unspecified, the only valid pointer to pass + /// to this function is the one taken from another `Box` with + /// `boxed::into_raw` function. /// /// Function is unsafe, because improper use of this function may /// lead to memory problems like double-free, for example if the /// function is called twice on the same raw pointer. #[unstable(feature = "alloc", reason = "may be renamed or moved out of Box scope")] + #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { mem::transmute(raw) } @@ -131,8 +134,9 @@ impl Box { /// automatically managed that may lead to memory or other resource /// leak. /// -/// # Example +/// # Examples /// ``` +/// # #![feature(alloc)] /// use std::boxed; /// /// let seventeen = Box::new(17u32); @@ -141,6 +145,7 @@ impl Box { /// ``` #[unstable(feature = "alloc", reason = "may be renamed")] +#[inline] pub unsafe fn into_raw(b: Box) -> *mut T { mem::transmute(b) } @@ -154,7 +159,7 @@ impl Default for Box { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box<[T]> { #[stable(feature = "rust1", since = "1.0.0")] - fn default() -> Box<[T]> { box [] } + fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -175,6 +180,7 @@ impl Clone for Box { /// # Examples /// /// ``` + /// # #![feature(alloc, core)] /// let x = Box::new(5); /// let mut y = Box::new(10); /// @@ -220,14 +226,6 @@ impl Ord for Box { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Box {} -#[cfg(stage0)] -impl> Hash for Box { - #[inline] - fn hash(&self, state: &mut S) { - (**self).hash(state); - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Box { fn hash(&self, state: &mut H) { @@ -235,32 +233,19 @@ impl Hash for Box { } } -/// Extension methods for an owning `Any` trait object. -#[unstable(feature = "alloc", - reason = "this trait will likely disappear once compiler bugs blocking \ - a direct impl on `Box` have been fixed ")] -// FIXME(#18737): this should be a direct impl on `Box`. If you're -// removing this please make sure that you can downcase on -// `Box` as well as `Box` -pub trait BoxAny { - /// Returns the boxed value if it is of type `T`, or - /// `Err(Self)` if it isn't. - #[stable(feature = "rust1", since = "1.0.0")] - fn downcast(self) -> Result, Self>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl BoxAny for Box { +impl Box { #[inline] - fn downcast(self) -> Result, Box> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Box> { if self.is::() { unsafe { // Get the raw representation of the trait object + let raw = into_raw(self); let to: TraitObject = - mem::transmute::, TraitObject>(self); + mem::transmute::<*mut Any, TraitObject>(raw); // Extract the data pointer - Ok(mem::transmute(to.data)) + Ok(Box::from_raw(to.data as *mut T)) } } else { Err(self) @@ -268,6 +253,14 @@ impl BoxAny for Box { } } +impl Box { + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn downcast(self) -> Result, Box> { + >::downcast(self) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Box { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -282,13 +275,6 @@ impl fmt::Debug for Box { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Box { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Box") - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Box { type Target = T; @@ -314,9 +300,74 @@ impl DoubleEndedIterator for Box { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Box {} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> FromError for Box { - fn from_error(err: E) -> Box { - Box::new(err) + +/// `FnBox` is a version of the `FnOnce` intended for use with boxed +/// closure objects. The idea is that where one would normally store a +/// `Box` in a data structure, you should use +/// `Box`. The two traits behave essentially the same, except +/// that a `FnBox` closure can only be called if it is boxed. (Note +/// that `FnBox` may be deprecated in the future if `Box` +/// closures become directly usable.) +/// +/// ### Example +/// +/// Here is a snippet of code which creates a hashmap full of boxed +/// once closures and then removes them one by one, calling each +/// closure as it is removed. Note that the type of the closures +/// stored in the map is `Box i32>` and not `Box i32>`. +/// +/// ``` +/// #![feature(core)] +/// +/// use std::boxed::FnBox; +/// use std::collections::HashMap; +/// +/// fn make_map() -> HashMap i32>> { +/// let mut map: HashMap i32>> = HashMap::new(); +/// map.insert(1, Box::new(|| 22)); +/// map.insert(2, Box::new(|| 44)); +/// map +/// } +/// +/// fn main() { +/// let mut map = make_map(); +/// for i in &[1, 2] { +/// let f = map.remove(&i).unwrap(); +/// assert_eq!(f(), i * 22); +/// } +/// } +/// ``` +#[rustc_paren_sugar] +#[unstable(feature = "core", reason = "Newly introduced")] +pub trait FnBox { + type Output; + + fn call_box(self: Box, args: A) -> Self::Output; +} + +impl FnBox for F + where F: FnOnce +{ + type Output = F::Output; + + fn call_box(self: Box, args: A) -> F::Output { + self.call_once(args) + } +} + +impl<'a,A,R> FnOnce for Box+'a> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) + } +} + +impl<'a,A,R> FnOnce for Box+Send+'a> { + type Output = R; + + extern "rust-call" fn call_once(self, args: A) -> R { + self.call_box(args) } } diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs index b7bacaa0ca..fc44ac4eac 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/boxed_test.rs @@ -17,7 +17,6 @@ use core::clone::Clone; use std::boxed; use std::boxed::Box; -use std::boxed::BoxAny; #[test] fn test_owned_clone() { @@ -56,29 +55,29 @@ fn test_show() { let b = Box::new(Test) as Box; let a_str = format!("{:?}", a); let b_str = format!("{:?}", b); - assert_eq!(a_str, "Box"); - assert_eq!(b_str, "Box"); + assert_eq!(a_str, "Any"); + assert_eq!(b_str, "Any"); static EIGHT: usize = 8; static TEST: Test = Test; let a = &EIGHT as &Any; let b = &TEST as &Any; let s = format!("{:?}", a); - assert_eq!(s, "&Any"); + assert_eq!(s, "Any"); let s = format!("{:?}", b); - assert_eq!(s, "&Any"); + assert_eq!(s, "Any"); } #[test] fn deref() { fn homura>(_: T) { } - homura(Box::new(765i32)); + homura(Box::new(765)); } #[test] fn raw_sized() { unsafe { - let x = Box::new(17i32); + let x = Box::new(17); let p = boxed::into_raw(x); assert_eq!(17, *p); *p = 19; diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index d3d86270d1..57baa811b9 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[cfg(not(test))] -use core::ptr::PtrExt; - // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` /// Return a pointer to `size` bytes of memory aligned to `align`. @@ -29,6 +26,9 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { /// /// On failure, return a null pointer and leave the original allocation intact. /// +/// If the allocation was relocated, the memory at the passed-in pointer is +/// undefined after the call. +/// /// Behavior is undefined if the requested size is 0 or the alignment is not a /// power of 2. The alignment must be no larger than the largest supported page /// size on the platform. @@ -189,7 +189,6 @@ mod imp { use core::option::Option; use core::option::Option::None; use core::ptr::{null_mut, null}; - use core::num::Int; use libc::{c_char, c_int, c_void, size_t}; use super::MIN_ALIGN; @@ -198,6 +197,7 @@ mod imp { extern {} extern { + #[allocator] fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void; fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; @@ -300,7 +300,7 @@ mod imp { libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 } else { let new_ptr = allocate(size, align); - ptr::copy_memory(new_ptr, ptr, cmp::min(size, old_size)); + ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); deallocate(ptr, old_size, align); new_ptr } @@ -386,7 +386,7 @@ mod imp { mod test { extern crate test; use self::test::Bencher; - use core::ptr::PtrExt; + use boxed::Box; use heap; #[test] @@ -404,7 +404,7 @@ mod test { #[bench] fn alloc_owned_small(b: &mut Bencher) { b.iter(|| { - box 10 + let _: Box<_> = box 10; }) } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index bc349ebebd..a8be63d637 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -56,6 +56,8 @@ //! The [`heap`](heap/index.html) module defines the low-level interface to the //! default global allocator. It is not compatible with the libc allocator API. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "alloc"] #![unstable(feature = "alloc")] #![feature(staged_api)] @@ -64,15 +66,21 @@ #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] +#![doc(test(no_crate_inject))] #![feature(no_std)] #![no_std] +#![feature(allocator)] +#![feature(custom_attribute)] +#![feature(fundamental)] #![feature(lang_items, unsafe_destructor)] #![feature(box_syntax)] #![feature(optin_builtin_traits)] #![feature(unboxed_closures)] -#![feature(unsafe_no_drop_flag)] +#![feature(unsafe_no_drop_flag, filling_drop)] #![feature(core)] +#![feature(unique)] +#![cfg_attr(test, feature(test, alloc, rustc_private))] #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")), feature(libc))] @@ -94,9 +102,15 @@ pub mod heap; // Primitive types using the heaps above +// Need to conditionally define the mod from `boxed.rs` to avoid +// duplicating the lang-items when building in test cfg; but also need +// to allow code to have `use boxed::HEAP;` +// and `use boxed::Box;` declarations. #[cfg(not(test))] pub mod boxed; #[cfg(test)] +mod boxed { pub use std::boxed::{Box, HEAP}; } +#[cfg(test)] mod boxed_test; pub mod arc; pub mod rc; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9d39511543..7cdd488842 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -32,6 +32,7 @@ //! and have the `Owner` remain allocated as long as any `Gadget` points at it. //! //! ```rust +//! # #![feature(alloc, collections)] //! use std::rc::Rc; //! //! struct Owner { @@ -58,12 +59,12 @@ //! //! drop(gadget_owner); //! -//! // Despite dropping gadget_owner, we're still able to print out the name of -//! // the Owner of the Gadgets. This is because we've only dropped the +//! // Despite dropping gadget_owner, we're still able to print out the name +//! // of the Owner of the Gadgets. This is because we've only dropped the //! // reference count object, not the Owner it wraps. As long as there are -//! // other `Rc` objects pointing at the same Owner, it will remain allocated. Notice -//! // that the `Rc` wrapper around Gadget.owner gets automatically dereferenced -//! // for us. +//! // other `Rc` objects pointing at the same Owner, it will remain +//! // allocated. Notice that the `Rc` wrapper around Gadget.owner gets +//! // automatically dereferenced for us. //! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); //! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); //! @@ -73,21 +74,25 @@ //! } //! ``` //! -//! If our requirements change, and we also need to be able to traverse from Owner → Gadget, we -//! will run into problems: an `Rc` pointer from Owner → Gadget introduces a cycle between the -//! objects. This means that their reference counts can never reach 0, and the objects will remain -//! allocated: a memory leak. In order to get around this, we can use `Weak` pointers. These -//! pointers don't contribute to the total count. +//! If our requirements change, and we also need to be able to traverse from +//! Owner → Gadget, we will run into problems: an `Rc` pointer from Owner +//! → Gadget introduces a cycle between the objects. This means that their +//! reference counts can never reach 0, and the objects will remain allocated: a +//! memory leak. In order to get around this, we can use `Weak` pointers. +//! These pointers don't contribute to the total count. //! -//! Rust actually makes it somewhat difficult to produce this loop in the first place: in order to -//! end up with two objects that point at each other, one of them needs to be mutable. This is -//! problematic because `Rc` enforces memory safety by only giving out shared references to the -//! object it wraps, and these don't allow direct mutation. We need to wrap the part of the object -//! we wish to mutate in a `RefCell`, which provides *interior mutability*: a method to achieve -//! mutability through a shared reference. `RefCell` enforces Rust's borrowing rules at runtime. -//! Read the `Cell` documentation for more details on interior mutability. +//! Rust actually makes it somewhat difficult to produce this loop in the first +//! place: in order to end up with two objects that point at each other, one of +//! them needs to be mutable. This is problematic because `Rc` enforces +//! memory safety by only giving out shared references to the object it wraps, +//! and these don't allow direct mutation. We need to wrap the part of the +//! object we wish to mutate in a `RefCell`, which provides *interior +//! mutability*: a method to achieve mutability through a shared reference. +//! `RefCell` enforces Rust's borrowing rules at runtime. Read the `Cell` +//! documentation for more details on interior mutability. //! //! ```rust +//! # #![feature(alloc)] //! use std::rc::Rc; //! use std::rc::Weak; //! use std::cell::RefCell; @@ -128,9 +133,10 @@ //! for gadget_opt in gadget_owner.gadgets.borrow().iter() { //! //! // gadget_opt is a Weak. Since weak pointers can't guarantee -//! // that their object is still allocated, we need to call upgrade() on them -//! // to turn them into a strong reference. This returns an Option, which -//! // contains a reference to our object if it still exists. +//! // that their object is still allocated, we need to call upgrade() +//! // on them to turn them into a strong reference. This returns an +//! // Option, which contains a reference to our object if it still +//! // exists. //! let gadget = gadget_opt.upgrade().unwrap(); //! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name); //! } @@ -143,7 +149,10 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] - +#[cfg(not(test))] +use boxed; +#[cfg(test)] +use std::boxed; use core::cell::Cell; use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; @@ -151,12 +160,12 @@ use core::default::Default; use core::fmt; use core::hash::{Hasher, Hash}; use core::marker; -use core::mem::{transmute, min_align_of, size_of, forget}; +use core::mem::{self, min_align_of, size_of, forget}; use core::nonzero::NonZero; use core::ops::{Deref, Drop}; use core::option::Option; use core::option::Option::{Some, None}; -use core::ptr::{self, PtrExt}; +use core::ptr; use core::result::Result; use core::result::Result::{Ok, Err}; use core::intrinsics::assume; @@ -175,8 +184,8 @@ struct RcBox { #[unsafe_no_drop_flag] #[stable(feature = "rust1", since = "1.0.0")] pub struct Rc { - // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained - // type via Deref + // FIXME #12808: strange names to try to avoid interfering with field + // accesses of the contained type via Deref _ptr: NonZero<*mut RcBox>, } @@ -198,10 +207,11 @@ impl Rc { pub fn new(value: T) -> Rc { unsafe { Rc { - // there is an implicit weak pointer owned by all the strong pointers, which - // ensures that the weak destructor never frees the allocation while the strong - // destructor is running, even if the weak pointer is stored inside the strong one. - _ptr: NonZero::new(transmute(box RcBox { + // there is an implicit weak pointer owned by all the strong + // pointers, which ensures that the weak destructor never frees + // the allocation while the strong destructor is running, even + // if the weak pointer is stored inside the strong one. + _ptr: NonZero::new(boxed::into_raw(box RcBox { value: value, strong: Cell::new(1), weak: Cell::new(1) @@ -215,6 +225,7 @@ impl Rc { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// let five = Rc::new(5); @@ -239,11 +250,13 @@ pub fn weak_count(this: &Rc) -> usize { this.weak() - 1 } #[unstable(feature = "alloc")] pub fn strong_count(this: &Rc) -> usize { this.strong() } -/// Returns true if there are no other `Rc` or `Weak` values that share the same inner value. +/// Returns true if there are no other `Rc` or `Weak` values that share the +/// same inner value. /// /// # Examples /// /// ``` +/// # #![feature(alloc)] /// use std::rc; /// use std::rc::Rc; /// @@ -261,9 +274,10 @@ pub fn is_unique(rc: &Rc) -> bool { /// /// If the `Rc` is not unique, an `Err` is returned with the same `Rc`. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(alloc)] /// use std::rc::{self, Rc}; /// /// let x = Rc::new(3); @@ -295,9 +309,10 @@ pub fn try_unwrap(rc: Rc) -> Result> { /// /// Returns `None` if the `Rc` is not unique. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(alloc)] /// use std::rc::{self, Rc}; /// /// let mut x = Rc::new(3); @@ -321,12 +336,13 @@ pub fn get_mut<'a, T>(rc: &'a mut Rc) -> Option<&'a mut T> { impl Rc { /// Make a mutable reference from the given `Rc`. /// - /// This is also referred to as a copy-on-write operation because the inner data is cloned if - /// the reference count is greater than one. + /// This is also referred to as a copy-on-write operation because the inner + /// data is cloned if the reference count is greater than one. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// let mut five = Rc::new(5); @@ -339,10 +355,11 @@ impl Rc { if !is_unique(self) { *self = Rc::new((**self).clone()) } - // This unsafety is ok because we're guaranteed that the pointer returned is the *only* - // pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at - // this point, and we required the `Rc` itself to be `mut`, so we're returning the only - // possible reference to the inner value. + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the `Rc` itself to be `mut`, so we're returning the only possible + // reference to the inner value. let inner = unsafe { &mut **self._ptr }; &mut inner.value } @@ -363,12 +380,14 @@ impl Deref for Rc { impl Drop for Rc { /// Drops the `Rc`. /// - /// This will decrement the strong reference count. If the strong reference count becomes zero - /// and the only other references are `Weak` ones, `drop`s the inner value. + /// This will decrement the strong reference count. If the strong reference + /// count becomes zero and the only other references are `Weak` ones, + /// `drop`s the inner value. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// { @@ -388,13 +407,13 @@ impl Drop for Rc { fn drop(&mut self) { unsafe { let ptr = *self._ptr; - if !ptr.is_null() { + if !ptr.is_null() && ptr as usize != mem::POST_DROP_USIZE { self.dec_strong(); if self.strong() == 0 { ptr::read(&**self); // destroy the contained object - // remove the implicit "strong weak" pointer now that we've destroyed the - // contents. + // remove the implicit "strong weak" pointer now that we've + // destroyed the contents. self.dec_weak(); if self.weak() == 0 { @@ -412,11 +431,13 @@ impl Clone for Rc { /// Makes a clone of the `Rc`. /// - /// This increases the strong reference count. + /// When you clone an `Rc`, it will create another pointer to the data and + /// increase the strong reference counter. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// let five = Rc::new(5); @@ -592,14 +613,6 @@ impl Ord for Rc { } // FIXME (#18248) Make `T` `Sized?` -#[cfg(stage0)] -impl> Hash for Rc { - #[inline] - fn hash(&self, state: &mut S) { - (**self).hash(state); - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Rc { fn hash(&self, state: &mut H) { @@ -623,7 +636,8 @@ impl fmt::Debug for Rc { /// A weak version of `Rc`. /// -/// Weak references do not count when determining if the inner value should be dropped. +/// Weak references do not count when determining if the inner value should be +/// dropped. /// /// See the [module level documentation](./index.html) for more. #[unsafe_no_drop_flag] @@ -648,11 +662,13 @@ impl Weak { /// /// Upgrades the `Weak` reference to an `Rc`, if possible. /// - /// Returns `None` if there were no strong references and the data was destroyed. + /// Returns `None` if there were no strong references and the data was + /// destroyed. /// /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// let five = Rc::new(5); @@ -681,6 +697,7 @@ impl Drop for Weak { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// { @@ -702,10 +719,10 @@ impl Drop for Weak { fn drop(&mut self) { unsafe { let ptr = *self._ptr; - if !ptr.is_null() { + if !ptr.is_null() && ptr as usize != mem::POST_DROP_USIZE { self.dec_weak(); - // the weak count starts at 1, and will only go to zero if all the strong pointers - // have disappeared. + // the weak count starts at 1, and will only go to zero if all + // the strong pointers have disappeared. if self.weak() == 0 { deallocate(ptr as *mut u8, size_of::>(), min_align_of::>()) @@ -726,6 +743,7 @@ impl Clone for Weak { /// # Examples /// /// ``` + /// # #![feature(alloc)] /// use std::rc::Rc; /// /// let weak_five = Rc::new(5).downgrade(); @@ -800,6 +818,7 @@ impl RcBoxPtr for Weak { #[cfg(test)] mod tests { use super::{Rc, Weak, weak_count, strong_count}; + use std::boxed::Box; use std::cell::RefCell; use std::option::Option; use std::option::Option::{Some, None}; @@ -831,7 +850,7 @@ mod tests { #[test] fn test_destructor() { - let x = Rc::new(box 5); + let x: Rc> = Rc::new(box 5); assert_eq!(**x, 5); } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b43f9adfb2..7843be0b48 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -19,6 +19,8 @@ //! arena but can only hold objects of a single type, and `Arena`, which is a //! more complex, slower arena which can hold objects of any type. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "arena"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -40,11 +42,9 @@ extern crate alloc; use std::cell::{Cell, RefCell}; use std::cmp; -use std::intrinsics::{TyDesc, get_tydesc}; use std::intrinsics; use std::marker; use std::mem; -use std::num::{Int, UnsignedInt}; use std::ptr; use std::rc::Rc; use std::rt::heap::{allocate, deallocate}; @@ -183,6 +183,25 @@ fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) { ((p & !1) as *const TyDesc, p & 1 == 1) } +// HACK(eddyb) TyDesc replacement using a trait object vtable. +// This could be replaced in the future with a custom DST layout, +// or `&'static (drop_glue, size, align)` created by a `const fn`. +struct TyDesc { + drop_glue: fn(*const i8), + size: usize, + align: usize +} + +unsafe fn get_tydesc() -> *const TyDesc { + use std::raw::TraitObject; + + let ptr = &*(1 as *const T); + + // Can use any trait that is implemented for all types. + let obj = mem::transmute::<&marker::MarkerTrait, TraitObject>(ptr); + obj.vtable as *const TyDesc +} + impl<'longer_than_self> Arena<'longer_than_self> { fn chunk_size(&self) -> usize { self.copy_head.borrow().capacity() @@ -321,7 +340,7 @@ fn test_arena_destructors() { } #[test] -#[should_fail] +#[should_panic] fn test_arena_destructors_fail() { let arena = Arena::new(); // Put some stuff in the arena. @@ -410,7 +429,8 @@ impl TypedArenaChunk { // Destroy the next chunk. let next = self.next; let size = calculate_size::(self.capacity); - deallocate(self as *mut TypedArenaChunk as *mut u8, size, + let self_ptr: *mut TypedArenaChunk = self; + deallocate(self_ptr as *mut u8, size, mem::min_align_of::>()); if !next.is_null() { let capacity = (*next).capacity; @@ -581,11 +601,11 @@ mod tests { #[bench] pub fn bench_copy_nonarena(b: &mut Bencher) { b.iter(|| { - box Point { + let _: Box<_> = box Point { x: 1, y: 2, z: 3, - } + }; }) } @@ -634,10 +654,10 @@ mod tests { #[bench] pub fn bench_noncopy_nonarena(b: &mut Bencher) { b.iter(|| { - box Noncopy { + let _: Box<_> = box Noncopy { string: "hello world".to_string(), array: vec!( 1, 2, 3, 4, 5 ), - } + }; }) } diff --git a/src/libbacktrace/Makefile.am b/src/libbacktrace/Makefile.am index 6add85d734..4372899829 100644 --- a/src/libbacktrace/Makefile.am +++ b/src/libbacktrace/Makefile.am @@ -6,12 +6,12 @@ # met: # (1) Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. +# notice, this list of conditions and the following disclaimer. # (2) Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the -# distribution. +# distribution. # (3) The name of the author may not be used to # endorse or promote products derived from this software without diff --git a/src/libbacktrace/Makefile.in b/src/libbacktrace/Makefile.in index 18c1ecaca5..93ccec2dbf 100644 --- a/src/libbacktrace/Makefile.in +++ b/src/libbacktrace/Makefile.in @@ -23,12 +23,12 @@ # met: # (1) Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. +# notice, this list of conditions and the following disclaimer. # (2) Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the -# distribution. +# distribution. # (3) The name of the author may not be used to # endorse or promote products derived from this software without @@ -117,10 +117,10 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \ $(btest_SOURCES) -MULTISRCTOP = -MULTIBUILDTOP = -MULTIDIRS = -MULTISUBDIR = +MULTISRCTOP = +MULTIBUILDTOP = +MULTIDIRS = +MULTISUBDIR = MULTIDO = true MULTICLEAN = true ETAGS = etags @@ -362,7 +362,7 @@ config.h: stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h -$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ @@ -380,7 +380,7 @@ clean-noinstLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) +libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(LINK) $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @@ -391,7 +391,7 @@ clean-checkPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) +btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) @rm -f btest$(EXEEXT) $(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS) diff --git a/src/libbacktrace/alloc.c b/src/libbacktrace/alloc.c index 37eca65349..4aa85d050f 100644 --- a/src/libbacktrace/alloc.c +++ b/src/libbacktrace/alloc.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/atomic.c b/src/libbacktrace/atomic.c index f139d74aa5..b31fa64c79 100644 --- a/src/libbacktrace/atomic.c +++ b/src/libbacktrace/atomic.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/backtrace-supported.h.in b/src/libbacktrace/backtrace-supported.h.in index 901e3f72a4..28488167c4 100644 --- a/src/libbacktrace/backtrace-supported.h.in +++ b/src/libbacktrace/backtrace-supported.h.in @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/backtrace.c b/src/libbacktrace/backtrace.c index cc3105c06c..4b90357df5 100644 --- a/src/libbacktrace/backtrace.c +++ b/src/libbacktrace/backtrace.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/backtrace.h b/src/libbacktrace/backtrace.h index 03b5479081..3f77093f76 100644 --- a/src/libbacktrace/backtrace.h +++ b/src/libbacktrace/backtrace.h @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/btest.c b/src/libbacktrace/btest.c index 4b67c3d8bd..a1818f1ef8 100644 --- a/src/libbacktrace/btest.c +++ b/src/libbacktrace/btest.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. @@ -460,7 +460,7 @@ f23 (int f1line, int f2line) (unsigned int) bdata.index, j + 1); bdata.failed = 1; } - } + } check ("test3", 0, all, f3line, "f23", &bdata.failed); check ("test3", 1, all, f2line, "f22", &bdata.failed); diff --git a/src/libbacktrace/configure b/src/libbacktrace/configure index 14a9fd4f45..d5e08d93f6 100755 --- a/src/libbacktrace/configure +++ b/src/libbacktrace/configure @@ -5650,7 +5650,7 @@ else lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + netbsd* | freebsd* | openbsd* | darwin* | dragonfly* | bitrig*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -9332,7 +9332,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly* | openbsd*) + freebsd* | dragonfly* | bitrig* | openbsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -15153,4 +15153,3 @@ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi - diff --git a/src/libbacktrace/configure.ac b/src/libbacktrace/configure.ac index 878bd2c158..d661c7b256 100644 --- a/src/libbacktrace/configure.ac +++ b/src/libbacktrace/configure.ac @@ -6,13 +6,13 @@ # met: # (1) Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. +# notice, this list of conditions and the following disclaimer. # (2) Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the -# distribution. - +# distribution. + # (3) The name of the author may not be used to # endorse or promote products derived from this software without # specific prior written permission. diff --git a/src/libbacktrace/dwarf.c b/src/libbacktrace/dwarf.c index ad52d73b75..5ecae71179 100644 --- a/src/libbacktrace/dwarf.c +++ b/src/libbacktrace/dwarf.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. @@ -1241,7 +1241,7 @@ add_unit_ranges (struct backtrace_state *state, uintptr_t base_address, static int find_address_ranges (struct backtrace_state *state, uintptr_t base_address, - struct dwarf_buf *unit_buf, + struct dwarf_buf *unit_buf, const unsigned char *dwarf_str, size_t dwarf_str_size, const unsigned char *dwarf_ranges, size_t dwarf_ranges_size, @@ -1599,7 +1599,7 @@ read_line_header (struct backtrace_state *state, struct unit *u, if (!advance (line_buf, hdrlen)) return 0; - + hdr->min_insn_len = read_byte (&hdr_buf); if (hdr->version < 4) hdr->max_ops_per_insn = 1; @@ -1608,7 +1608,7 @@ read_line_header (struct backtrace_state *state, struct unit *u, /* We don't care about default_is_stmt. */ read_byte (&hdr_buf); - + hdr->line_base = read_sbyte (&hdr_buf); hdr->line_range = read_byte (&hdr_buf); diff --git a/src/libbacktrace/elf.c b/src/libbacktrace/elf.c index 6c5b179e90..5fc74add05 100644 --- a/src/libbacktrace/elf.c +++ b/src/libbacktrace/elf.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/fileline.c b/src/libbacktrace/fileline.c index bab5351cab..f45cccff71 100644 --- a/src/libbacktrace/fileline.c +++ b/src/libbacktrace/fileline.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/hashtab.h b/src/libbacktrace/hashtab.h index 4bb65d6c7a..3736622e67 100644 --- a/src/libbacktrace/hashtab.h +++ b/src/libbacktrace/hashtab.h @@ -1,4 +1,4 @@ -/* An expandable hash tables datatype. +/* An expandable hash tables datatype. Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2009, 2010 Free Software Foundation, Inc. Contributed by Vladimir Makarov (vmakarov@cygnus.com). @@ -61,7 +61,7 @@ typedef int (*htab_eq) (const void *, const void *); /* Cleanup function called whenever a live element is removed from the hash table. */ typedef void (*htab_del) (void *); - + /* Function called by htab_traverse for each live element. The first arg is the slot of the element (which can be passed to htab_clear_slot if desired), the second arg is the auxiliary pointer handed to diff --git a/src/libbacktrace/internal.h b/src/libbacktrace/internal.h index dd109db24a..a13c775b62 100644 --- a/src/libbacktrace/internal.h +++ b/src/libbacktrace/internal.h @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/ltmain.sh b/src/libbacktrace/ltmain.sh index 9503ec85d7..84f5be9249 100644 --- a/src/libbacktrace/ltmain.sh +++ b/src/libbacktrace/ltmain.sh @@ -4741,7 +4741,7 @@ func_mode_link () # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; @@ -8633,4 +8633,3 @@ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # sh-indentation:2 # End: # vi:sw=2 - diff --git a/src/libbacktrace/mmap.c b/src/libbacktrace/mmap.c index b530e38238..1c691b02e7 100644 --- a/src/libbacktrace/mmap.c +++ b/src/libbacktrace/mmap.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/mmapio.c b/src/libbacktrace/mmapio.c index 72940b403a..8b8f124da9 100644 --- a/src/libbacktrace/mmapio.c +++ b/src/libbacktrace/mmapio.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/nounwind.c b/src/libbacktrace/nounwind.c index 0097966b42..f8fdbdc85a 100644 --- a/src/libbacktrace/nounwind.c +++ b/src/libbacktrace/nounwind.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/posix.c b/src/libbacktrace/posix.c index dba9e525e0..7f1c35ab97 100644 --- a/src/libbacktrace/posix.c +++ b/src/libbacktrace/posix.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/print.c b/src/libbacktrace/print.c index bd224e6bf4..70e347f62c 100644 --- a/src/libbacktrace/print.c +++ b/src/libbacktrace/print.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/read.c b/src/libbacktrace/read.c index c618a50b36..e373b61de2 100644 --- a/src/libbacktrace/read.c +++ b/src/libbacktrace/read.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/simple.c b/src/libbacktrace/simple.c index efa8b6fc63..dd70f831de 100644 --- a/src/libbacktrace/simple.c +++ b/src/libbacktrace/simple.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/state.c b/src/libbacktrace/state.c index a7d4e07d1a..bef47bd1a0 100644 --- a/src/libbacktrace/state.c +++ b/src/libbacktrace/state.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libbacktrace/unknown.c b/src/libbacktrace/unknown.c index c1fe8811d4..e5e8421b3a 100644 --- a/src/libbacktrace/unknown.c +++ b/src/libbacktrace/unknown.c @@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the - distribution. - + distribution. + (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 9f549fd723..3804874a65 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -30,7 +30,7 @@ //! use std::collections::BinaryHeap; //! use std::usize; //! -//! #[derive(Copy, Eq, PartialEq)] +//! #[derive(Copy, Clone, Eq, PartialEq)] //! struct State { //! cost: usize, //! position: usize, @@ -163,6 +163,11 @@ use vec::{self, Vec}; /// A priority queue implemented with a binary heap. /// /// This will be a max-heap. +/// +/// It is a logic error for an item to be modified in such a way that the +/// item's ordering relative to any other item, as determined by the `Ord` +/// trait, changes while it is in the heap. This is normally only possible +/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap { @@ -211,6 +216,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let heap = BinaryHeap::from_vec(vec![9, 1, 2, 7, 3, 2]); /// ``` @@ -230,6 +236,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); /// @@ -250,6 +257,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]); /// @@ -355,6 +363,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::from_vec(vec![1, 3]); /// @@ -400,6 +409,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); /// heap.push(1); @@ -431,6 +441,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::new(); /// @@ -456,6 +467,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4, 5, 6, 7]); /// let vec = heap.into_vec(); @@ -473,6 +485,7 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BinaryHeap; /// /// let mut heap = BinaryHeap::from_vec(vec![1, 2, 4, 5, 7]); @@ -480,7 +493,7 @@ impl BinaryHeap { /// heap.push(3); /// /// let vec = heap.into_sorted_vec(); - /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]); /// ``` pub fn into_sorted_vec(mut self) -> Vec { let mut end = self.len(); @@ -550,6 +563,8 @@ impl BinaryHeap { pub fn is_empty(&self) -> bool { self.len() == 0 } /// Clears the binary heap, returning an iterator over the removed elements. + /// + /// The elements are removed in arbitrary order. #[inline] #[unstable(feature = "collections", reason = "matches collection reform specification, waiting for dust to settle")] @@ -688,218 +703,3 @@ impl Extend for BinaryHeap { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - - use super::BinaryHeap; - - #[test] - fn test_iterator() { - let data = vec![5, 9, 3]; - let iterout = [9, 5, 3]; - let heap = BinaryHeap::from_vec(data); - let mut i = 0; - for el in &heap { - assert_eq!(*el, iterout[i]); - i += 1; - } - } - - #[test] - fn test_iterator_reverse() { - let data = vec![5, 9, 3]; - let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from_vec(data); - - let v: Vec<_> = pq.iter().rev().cloned().collect(); - assert_eq!(v, iterout); - } - - #[test] - fn test_move_iter() { - let data = vec![5, 9, 3]; - let iterout = vec![9, 5, 3]; - let pq = BinaryHeap::from_vec(data); - - let v: Vec<_> = pq.into_iter().collect(); - assert_eq!(v, iterout); - } - - #[test] - fn test_move_iter_size_hint() { - let data = vec![5, 9]; - let pq = BinaryHeap::from_vec(data); - - let mut it = pq.into_iter(); - - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next(), Some(9)); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next(), Some(5)); - - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_move_iter_reverse() { - let data = vec![5, 9, 3]; - let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from_vec(data); - - let v: Vec<_> = pq.into_iter().rev().collect(); - assert_eq!(v, iterout); - } - - #[test] - fn test_peek_and_pop() { - let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; - let mut sorted = data.clone(); - sorted.sort(); - let mut heap = BinaryHeap::from_vec(data); - while !heap.is_empty() { - assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); - assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); - } - } - - #[test] - fn test_push() { - let mut heap = BinaryHeap::from_vec(vec![2, 4, 9]); - assert_eq!(heap.len(), 3); - assert!(*heap.peek().unwrap() == 9); - heap.push(11); - assert_eq!(heap.len(), 4); - assert!(*heap.peek().unwrap() == 11); - heap.push(5); - assert_eq!(heap.len(), 5); - assert!(*heap.peek().unwrap() == 11); - heap.push(27); - assert_eq!(heap.len(), 6); - assert!(*heap.peek().unwrap() == 27); - heap.push(3); - assert_eq!(heap.len(), 7); - assert!(*heap.peek().unwrap() == 27); - heap.push(103); - assert_eq!(heap.len(), 8); - assert!(*heap.peek().unwrap() == 103); - } - - #[test] - fn test_push_unique() { - let mut heap = BinaryHeap::from_vec(vec![box 2, box 4, box 9]); - assert_eq!(heap.len(), 3); - assert!(*heap.peek().unwrap() == box 9); - heap.push(box 11); - assert_eq!(heap.len(), 4); - assert!(*heap.peek().unwrap() == box 11); - heap.push(box 5); - assert_eq!(heap.len(), 5); - assert!(*heap.peek().unwrap() == box 11); - heap.push(box 27); - assert_eq!(heap.len(), 6); - assert!(*heap.peek().unwrap() == box 27); - heap.push(box 3); - assert_eq!(heap.len(), 7); - assert!(*heap.peek().unwrap() == box 27); - heap.push(box 103); - assert_eq!(heap.len(), 8); - assert!(*heap.peek().unwrap() == box 103); - } - - #[test] - fn test_push_pop() { - let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(6), 6); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(0), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(4), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(1), 4); - assert_eq!(heap.len(), 5); - } - - #[test] - fn test_replace() { - let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(6).unwrap(), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(0).unwrap(), 6); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(4).unwrap(), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(1).unwrap(), 4); - assert_eq!(heap.len(), 5); - } - - fn check_to_vec(mut data: Vec) { - let heap = BinaryHeap::from_vec(data.clone()); - let mut v = heap.clone().into_vec(); - v.sort(); - data.sort(); - - assert_eq!(v, data); - assert_eq!(heap.into_sorted_vec(), data); - } - - #[test] - fn test_to_vec() { - check_to_vec(vec![]); - check_to_vec(vec![5]); - check_to_vec(vec![3, 2]); - check_to_vec(vec![2, 3]); - check_to_vec(vec![5, 1, 2]); - check_to_vec(vec![1, 100, 2, 3]); - check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); - check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); - check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); - check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); - check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); - } - - #[test] - fn test_empty_pop() { - let mut heap = BinaryHeap::::new(); - assert!(heap.pop().is_none()); - } - - #[test] - fn test_empty_peek() { - let empty = BinaryHeap::::new(); - assert!(empty.peek().is_none()); - } - - #[test] - fn test_empty_replace() { - let mut heap = BinaryHeap::new(); - assert!(heap.replace(5).is_none()); - } - - #[test] - fn test_from_iter() { - let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; - - let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); - - for &x in &xs { - assert_eq!(q.pop().unwrap(), x); - } - } - - #[test] - fn test_drain() { - let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); - - assert_eq!(q.drain().take(5).count(), 5); - - assert!(q.is_empty()); - } -} diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 11c576eab1..8874ac6eb8 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -38,6 +38,7 @@ //! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes //! //! ``` +//! # #![feature(collections, core, step_by)] //! use std::collections::{BitSet, BitVec}; //! use std::num::Float; //! use std::iter; @@ -59,7 +60,7 @@ //! if bv[i] { //! // Mark all multiples of i as non-prime (any multiples below i * i //! // will have been marked as non-prime previously) -//! for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) } +//! for j in (i * i..max_prime).step_by(i) { bv.set(j, false) } //! } //! } //! BitSet::from_bit_vec(bv) @@ -90,7 +91,6 @@ use core::hash; use core::iter::RandomAccessIterator; use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned}; use core::iter::{self, FromIterator, IntoIterator}; -use core::num::Int; use core::ops::Index; use core::slice; use core::{u8, u32, usize}; @@ -110,7 +110,7 @@ fn reverse_bits(byte: u8) -> u8 { result } -// Take two BitV's, and return iterators of their words, where the shorter one +// Take two BitVec's, and return iterators of their words, where the shorter one // has been padded with 0's fn match_words <'a,'b>(a: &'a BitVec, b: &'b BitVec) -> (MatchWords<'a>, MatchWords<'b>) { let a_len = a.storage.len(); @@ -118,11 +118,11 @@ fn match_words <'a,'b>(a: &'a BitVec, b: &'b BitVec) -> (MatchWords<'a>, MatchWo // have to uselessly pretend to pad the longer one for type matching if a_len < b_len { - (a.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(b_len).skip(a_len)), - b.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(0).skip(0))) + (a.blocks().enumerate().chain(iter::repeat(0).enumerate().take(b_len).skip(a_len)), + b.blocks().enumerate().chain(iter::repeat(0).enumerate().take(0).skip(0))) } else { - (a.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(0).skip(0)), - b.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(a_len).skip(b_len))) + (a.blocks().enumerate().chain(iter::repeat(0).enumerate().take(0).skip(0)), + b.blocks().enumerate().chain(iter::repeat(0).enumerate().take(a_len).skip(b_len))) } } @@ -133,7 +133,8 @@ static FALSE: bool = false; /// /// # Examples /// -/// ```rust +/// ``` +/// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(10, false); @@ -170,8 +171,8 @@ impl Index for BitVec { type Output = bool; #[inline] - fn index(&self, i: &usize) -> &bool { - if self.get(*i).expect("index out of bounds") { + fn index(&self, i: usize) -> &bool { + if self.get(i).expect("index out of bounds") { &TRUE } else { &FALSE @@ -189,17 +190,17 @@ fn blocks_for_bits(bits: usize) -> usize { // // Note that we can technically avoid this branch with the expression // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost usize::MAX this will overflow. - if bits % u32::BITS == 0 { - bits / u32::BITS + if bits % u32::BITS as usize == 0 { + bits / u32::BITS as usize } else { - bits / u32::BITS + 1 + bits / u32::BITS as usize + 1 } } /// Computes the bitmask for the final word of the vector fn mask_for_bits(bits: usize) -> u32 { // Note especially that a perfect multiple of u32::BITS should mask all 1s. - !0u32 >> (u32::BITS - bits % u32::BITS) % u32::BITS + !0 >> (u32::BITS as usize - bits % u32::BITS as usize) % u32::BITS as usize } impl BitVec { @@ -237,7 +238,7 @@ impl BitVec { /// An operation might screw up the unused bits in the last block of the /// `BitVec`. As per (3), it's assumed to be all 0s. This method fixes it up. fn fix_last_block(&mut self) { - let extra_bits = self.len() % u32::BITS; + let extra_bits = self.len() % u32::BITS as usize; if extra_bits > 0 { let mask = (1 << extra_bits) - 1; let storage_len = self.storage.len(); @@ -250,6 +251,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// let mut bv = BitVec::new(); /// ``` @@ -264,6 +266,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(10, false); @@ -275,7 +278,7 @@ impl BitVec { pub fn from_elem(nbits: usize, bit: bool) -> BitVec { let nblocks = blocks_for_bits(nbits); let mut bit_vec = BitVec { - storage: repeat(if bit { !0u32 } else { 0u32 }).take(nblocks).collect(), + storage: repeat(if bit { !0 } else { 0 }).take(nblocks).collect(), nbits: nbits }; bit_vec.fix_last_block(); @@ -304,6 +307,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let bv = BitVec::from_bytes(&[0b10100000, 0b00010010]); @@ -313,7 +317,7 @@ impl BitVec { /// false, false, true, false])); /// ``` pub fn from_bytes(bytes: &[u8]) -> BitVec { - let len = bytes.len().checked_mul(u8::BITS).expect("capacity overflow"); + let len = bytes.len().checked_mul(u8::BITS as usize).expect("capacity overflow"); let mut bit_vec = BitVec::with_capacity(len); let complete_words = bytes.len() / 4; let extra_bytes = bytes.len() % 4; @@ -330,7 +334,7 @@ impl BitVec { } if extra_bytes > 0 { - let mut last_word = 0u32; + let mut last_word = 0; for (i, &byte) in bytes[complete_words*4..].iter().enumerate() { last_word |= (reverse_bits(byte) as u32) << (i * 8); } @@ -346,6 +350,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let bv = BitVec::from_fn(5, |i| { i % 2 == 0 }); @@ -364,6 +369,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let bv = BitVec::from_bytes(&[0b01100000]); @@ -380,8 +386,8 @@ impl BitVec { if i >= self.nbits { return None; } - let w = i / u32::BITS; - let b = i % u32::BITS; + let w = i / u32::BITS as usize; + let b = i % u32::BITS as usize; self.storage.get(w).map(|&block| (block & (1 << b)) != 0 ) @@ -396,6 +402,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(5, false); @@ -407,8 +414,8 @@ impl BitVec { reason = "panic semantics are likely to change in the future")] pub fn set(&mut self, i: usize, x: bool) { assert!(i < self.nbits); - let w = i / u32::BITS; - let b = i % u32::BITS; + let w = i / u32::BITS as usize; + let b = i % u32::BITS as usize; let flag = 1 << b; let val = if x { self.storage[w] | flag } else { self.storage[w] & !flag }; @@ -420,6 +427,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let before = 0b01100000; @@ -431,7 +439,7 @@ impl BitVec { /// ``` #[inline] pub fn set_all(&mut self) { - for w in &mut self.storage { *w = !0u32; } + for w in &mut self.storage { *w = !0; } self.fix_last_block(); } @@ -440,6 +448,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let before = 0b01100000; @@ -468,6 +477,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let a = 0b01100100; @@ -498,6 +508,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let a = 0b01100100; @@ -528,6 +539,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let a = 0b01100100; @@ -557,6 +569,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(5, true); @@ -566,12 +579,12 @@ impl BitVec { /// assert_eq!(bv.all(), false); /// ``` pub fn all(&self) -> bool { - let mut last_word = !0u32; + let mut last_word = !0; // Check that every block but the last is all-ones... self.blocks().all(|elem| { let tmp = last_word; last_word = elem; - tmp == !0u32 + tmp == !0 // and then check the last one has enough ones }) && (last_word == mask_for_bits(self.nbits)) } @@ -581,6 +594,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let bv = BitVec::from_bytes(&[0b01110100, 0b10010010]); @@ -597,6 +611,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(10, false); @@ -614,6 +629,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(10, false); @@ -635,18 +651,19 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(3, true); /// bv.set(1, false); /// - /// assert_eq!(bv.to_bytes(), vec!(0b10100000)); + /// assert_eq!(bv.to_bytes(), [0b10100000]); /// /// let mut bv = BitVec::from_elem(9, false); /// bv.set(2, true); /// bv.set(8, true); /// - /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); + /// assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); /// ``` pub fn to_bytes(&self) -> Vec { fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 { @@ -682,6 +699,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let bv = BitVec::from_bytes(&[0b10100000]); @@ -702,6 +720,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_bytes(&[0b01001011]); @@ -728,6 +747,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(3, false); @@ -758,6 +778,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_elem(3, false); @@ -780,6 +801,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::new(); @@ -789,7 +811,7 @@ impl BitVec { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn capacity(&self) -> usize { - self.storage.capacity().checked_mul(u32::BITS).unwrap_or(usize::MAX) + self.storage.capacity().checked_mul(u32::BITS as usize).unwrap_or(usize::MAX) } /// Grows the `BitVec` in-place, adding `n` copies of `value` to the `BitVec`. @@ -801,12 +823,13 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_bytes(&[0b01001011]); /// bv.grow(2, true); /// assert_eq!(bv.len(), 10); - /// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000)); + /// assert_eq!(bv.to_bytes(), [0b01001011, 0b11000000]); /// ``` pub fn grow(&mut self, n: usize, value: bool) { // Note: we just bulk set all the bits in the last word in this fn in multiple places @@ -818,11 +841,11 @@ impl BitVec { let full_value = if value { !0 } else { 0 }; // Correct the old tail word, setting or clearing formerly unused bits - let old_last_word = blocks_for_bits(self.nbits) - 1; - if self.nbits % u32::BITS > 0 { + let num_cur_blocks = blocks_for_bits(self.nbits); + if self.nbits % u32::BITS as usize > 0 { let mask = mask_for_bits(self.nbits); if value { - self.storage[old_last_word] |= !mask; + self.storage[num_cur_blocks - 1] |= !mask; } else { // Extra bits are already zero by invariant. } @@ -830,7 +853,7 @@ impl BitVec { // Fill in words after the old tail word let stop_idx = cmp::min(self.storage.len(), new_nblocks); - for idx in old_last_word + 1..stop_idx { + for idx in num_cur_blocks..stop_idx { self.storage[idx] = full_value; } @@ -851,6 +874,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::from_bytes(&[0b01001001]); @@ -868,7 +892,7 @@ impl BitVec { // (3) self.set(i, false); self.nbits = i; - if self.nbits % u32::BITS == 0 { + if self.nbits % u32::BITS as usize == 0 { // (2) self.storage.pop(); } @@ -881,6 +905,7 @@ impl BitVec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitVec; /// /// let mut bv = BitVec::new(); @@ -890,7 +915,7 @@ impl BitVec { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, elem: bool) { - if self.nbits % u32::BITS == 0 { + if self.nbits % u32::BITS as usize == 0 { self.storage.push(0); } let insert_pos = self.nbits; @@ -912,7 +937,7 @@ impl BitVec { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { - for w in &mut self.storage { *w = 0u32; } + for w in &mut self.storage { *w = 0; } } } @@ -978,24 +1003,13 @@ impl Ord for BitVec { impl fmt::Debug for BitVec { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { for bit in self { - try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 })); + try!(write!(fmt, "{}", if bit { 1 } else { 0 })); } Ok(()) } } #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(stage0)] -impl hash::Hash for BitVec { - fn hash(&self, state: &mut S) { - self.nbits.hash(state); - for elem in self.blocks() { - elem.hash(state); - } - } -} -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl hash::Hash for BitVec { fn hash(&self, state: &mut H) { self.nbits.hash(state); @@ -1102,6 +1116,7 @@ impl<'a> IntoIterator for &'a BitVec { /// # Examples /// /// ``` +/// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// // It's a regular set @@ -1198,6 +1213,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::new(); @@ -1214,6 +1230,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::with_capacity(100); @@ -1231,6 +1248,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitVec, BitSet}; /// /// let bv = BitVec::from_bytes(&[0b01100000]); @@ -1246,20 +1264,13 @@ impl BitSet { BitSet { bit_vec: bit_vec } } - /// Deprecated: use `from_bit_vec`. - #[inline] - #[deprecated(since = "1.0.0", reason = "renamed to from_bit_vec")] - #[unstable(feature = "collections")] - pub fn from_bitv(bit_vec: BitVec) -> BitSet { - BitSet { bit_vec: bit_vec } - } - /// Returns the capacity in bits for this bit vector. Inserting any /// element less than this amount will not trigger a resizing. /// /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::with_capacity(100); @@ -1281,6 +1292,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::new(); @@ -1307,6 +1319,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::new(); @@ -1327,6 +1340,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::new(); @@ -1347,6 +1361,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::new(); @@ -1393,6 +1408,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BitSet; /// /// let mut s = BitSet::new(); @@ -1417,7 +1433,7 @@ impl BitSet { // Truncate let trunc_len = cmp::max(old_len - n, 1); bit_vec.storage.truncate(trunc_len); - bit_vec.nbits = trunc_len * u32::BITS; + bit_vec.nbits = trunc_len * u32::BITS as usize; } /// Iterator over each u32 stored in the `BitSet`. @@ -1425,6 +1441,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitVec, BitSet}; /// /// let s = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01001010])); @@ -1446,6 +1463,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitVec, BitSet}; /// /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000])); @@ -1476,6 +1494,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitVec, BitSet}; /// /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000])); @@ -1506,6 +1525,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000])); @@ -1544,6 +1564,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000])); @@ -1573,6 +1594,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// let a = 0b01101000; @@ -1596,6 +1618,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// let a = 0b01101000; @@ -1620,6 +1643,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// let a = 0b01101000; @@ -1652,6 +1676,7 @@ impl BitSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::{BitSet, BitVec}; /// /// let a = 0b01101000; @@ -1674,7 +1699,7 @@ impl BitSet { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { - self.bit_vec.blocks().fold(0, |acc, n| acc + n.count_ones()) + self.bit_vec.blocks().fold(0, |acc, n| acc + n.count_ones() as usize) } /// Returns whether there are no bits set in this set @@ -1763,7 +1788,7 @@ impl BitSet { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for BitSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(write!(fmt, "BitSet {{")); + try!(write!(fmt, "{{")); let mut first = true; for n in self { if !first { @@ -1776,16 +1801,7 @@ impl fmt::Debug for BitSet { } } -#[cfg(stage0)] -impl hash::Hash for BitSet { - fn hash(&self, state: &mut S) { - for pos in self { - pos.hash(state); - } - } -} #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl hash::Hash for BitSet { fn hash(&self, state: &mut H) { for pos in self { @@ -1812,12 +1828,16 @@ struct TwoBitPositions<'a> { next_idx: usize } +#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Union<'a>(TwoBitPositions<'a>); +#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection<'a>(Take>); +#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference<'a>(TwoBitPositions<'a>); +#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SymmetricDifference<'a>(TwoBitPositions<'a>); @@ -1851,13 +1871,13 @@ impl<'a> Iterator for TwoBitPositions<'a> { fn next(&mut self) -> Option { while self.next_idx < self.set.bit_vec.len() || self.next_idx < self.other.bit_vec.len() { - let bit_idx = self.next_idx % u32::BITS; + let bit_idx = self.next_idx % u32::BITS as usize; if bit_idx == 0 { let s_bit_vec = &self.set.bit_vec; let o_bit_vec = &self.other.bit_vec; // Merging the two words is a bit of an awkward dance since // one BitVec might be longer than the other - let word_idx = self.next_idx / u32::BITS; + let word_idx = self.next_idx / u32::BITS as usize; let w1 = if word_idx < s_bit_vec.storage.len() { s_bit_vec.storage[word_idx] } else { 0 }; @@ -1923,1183 +1943,3 @@ impl<'a> IntoIterator for &'a BitSet { self.iter() } } - -#[cfg(test)] -mod tests { - use prelude::*; - use core::u32; - - use super::BitVec; - - #[test] - fn test_to_str() { - let zerolen = BitVec::new(); - assert_eq!(format!("{:?}", zerolen), ""); - - let eightbits = BitVec::from_elem(8, false); - assert_eq!(format!("{:?}", eightbits), "00000000") - } - - #[test] - fn test_0_elements() { - let act = BitVec::new(); - let exp = Vec::new(); - assert!(act.eq_vec(&exp)); - assert!(act.none() && act.all()); - } - - #[test] - fn test_1_element() { - let mut act = BitVec::from_elem(1, false); - assert!(act.eq_vec(&[false])); - assert!(act.none() && !act.all()); - act = BitVec::from_elem(1, true); - assert!(act.eq_vec(&[true])); - assert!(!act.none() && act.all()); - } - - #[test] - fn test_2_elements() { - let mut b = BitVec::from_elem(2, false); - b.set(0, true); - b.set(1, false); - assert_eq!(format!("{:?}", b), "10"); - assert!(!b.none() && !b.all()); - } - - #[test] - fn test_10_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(10, false); - assert!((act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false]))); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(10, true); - assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(5, true); - act.set(6, true); - act.set(7, true); - act.set(8, true); - act.set(9, true); - assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(10, false); - act.set(0, true); - act.set(3, true); - act.set(6, true); - act.set(9, true); - assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_31_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(31, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(31, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(31, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_32_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(32, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(32, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true, true])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(32, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_33_elements() { - let mut act; - // all 0 - - act = BitVec::from_elem(33, false); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false])); - assert!(act.none() && !act.all()); - // all 1 - - act = BitVec::from_elem(33, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true])); - assert!(!act.none() && act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(0, true); - act.set(1, true); - act.set(2, true); - act.set(3, true); - act.set(4, true); - act.set(5, true); - act.set(6, true); - act.set(7, true); - assert!(act.eq_vec( - &[true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(16, true); - act.set(17, true); - act.set(18, true); - act.set(19, true); - act.set(20, true); - act.set(21, true); - act.set(22, true); - act.set(23, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(24, true); - act.set(25, true); - act.set(26, true); - act.set(27, true); - act.set(28, true); - act.set(29, true); - act.set(30, true); - act.set(31, true); - assert!(act.eq_vec( - &[false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, - false, false, true, true, true, true, true, true, true, true, false])); - assert!(!act.none() && !act.all()); - // mixed - - act = BitVec::from_elem(33, false); - act.set(3, true); - act.set(17, true); - act.set(30, true); - act.set(31, true); - act.set(32, true); - assert!(act.eq_vec( - &[false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true, true])); - assert!(!act.none() && !act.all()); - } - - #[test] - fn test_equal_differing_sizes() { - let v0 = BitVec::from_elem(10, false); - let v1 = BitVec::from_elem(11, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_greatly_differing_sizes() { - let v0 = BitVec::from_elem(10, false); - let v1 = BitVec::from_elem(110, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_sneaky_small() { - let mut a = BitVec::from_elem(1, false); - a.set(0, true); - - let mut b = BitVec::from_elem(1, true); - b.set(0, true); - - assert_eq!(a, b); - } - - #[test] - fn test_equal_sneaky_big() { - let mut a = BitVec::from_elem(100, false); - for i in 0..100 { - a.set(i, true); - } - - let mut b = BitVec::from_elem(100, true); - for i in 0..100 { - b.set(i, true); - } - - assert_eq!(a, b); - } - - #[test] - fn test_from_bytes() { - let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); - let str = concat!("10110110", "00000000", "11111111"); - assert_eq!(format!("{:?}", bit_vec), str); - } - - #[test] - fn test_to_bytes() { - let mut bv = BitVec::from_elem(3, true); - bv.set(1, false); - assert_eq!(bv.to_bytes(), vec!(0b10100000)); - - let mut bv = BitVec::from_elem(9, false); - bv.set(2, true); - bv.set(8, true); - assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); - } - - #[test] - fn test_from_bools() { - let bools = vec![true, false, true, true]; - let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); - assert_eq!(format!("{:?}", bit_vec), "1011"); - } - - #[test] - fn test_to_bools() { - let bools = vec![false, false, true, false, false, true, true, false]; - assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::>(), bools); - } - - #[test] - fn test_bit_vec_iterator() { - let bools = vec![true, false, true, true]; - let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); - - assert_eq!(bit_vec.iter().collect::>(), bools); - - let long: Vec<_> = (0i32..10000).map(|i| i % 2 == 0).collect(); - let bit_vec: BitVec = long.iter().map(|n| *n).collect(); - assert_eq!(bit_vec.iter().collect::>(), long) - } - - #[test] - fn test_small_difference() { - let mut b1 = BitVec::from_elem(3, false); - let mut b2 = BitVec::from_elem(3, false); - b1.set(0, true); - b1.set(1, true); - b2.set(1, true); - b2.set(2, true); - assert!(b1.difference(&b2)); - assert!(b1[0]); - assert!(!b1[1]); - assert!(!b1[2]); - } - - #[test] - fn test_big_difference() { - let mut b1 = BitVec::from_elem(100, false); - let mut b2 = BitVec::from_elem(100, false); - b1.set(0, true); - b1.set(40, true); - b2.set(40, true); - b2.set(80, true); - assert!(b1.difference(&b2)); - assert!(b1[0]); - assert!(!b1[40]); - assert!(!b1[80]); - } - - #[test] - fn test_small_clear() { - let mut b = BitVec::from_elem(14, true); - assert!(!b.none() && b.all()); - b.clear(); - assert!(b.none() && !b.all()); - } - - #[test] - fn test_big_clear() { - let mut b = BitVec::from_elem(140, true); - assert!(!b.none() && b.all()); - b.clear(); - assert!(b.none() && !b.all()); - } - - #[test] - fn test_bit_vec_lt() { - let mut a = BitVec::from_elem(5, false); - let mut b = BitVec::from_elem(5, false); - - assert!(!(a < b) && !(b < a)); - b.set(2, true); - assert!(a < b); - a.set(3, true); - assert!(a < b); - a.set(2, true); - assert!(!(a < b) && b < a); - b.set(0, true); - assert!(a < b); - } - - #[test] - fn test_ord() { - let mut a = BitVec::from_elem(5, false); - let mut b = BitVec::from_elem(5, false); - - assert!(a <= b && a >= b); - a.set(1, true); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - b.set(1, true); - b.set(2, true); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - - #[test] - fn test_small_bit_vec_tests() { - let v = BitVec::from_bytes(&[0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = BitVec::from_bytes(&[0b00010100]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = BitVec::from_bytes(&[0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_big_bit_vec_tests() { - let v = BitVec::from_bytes(&[ // 88 bits - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = BitVec::from_bytes(&[ // 88 bits - 0, 0, 0b00010100, 0, - 0, 0, 0, 0b00110100, - 0, 0, 0]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = BitVec::from_bytes(&[ // 88 bits - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_bit_vec_push_pop() { - let mut s = BitVec::from_elem(5 * u32::BITS - 2, false); - assert_eq!(s.len(), 5 * u32::BITS - 2); - assert_eq!(s[5 * u32::BITS - 3], false); - s.push(true); - s.push(true); - assert_eq!(s[5 * u32::BITS - 2], true); - assert_eq!(s[5 * u32::BITS - 1], true); - // Here the internal vector will need to be extended - s.push(false); - assert_eq!(s[5 * u32::BITS], false); - s.push(false); - assert_eq!(s[5 * u32::BITS + 1], false); - assert_eq!(s.len(), 5 * u32::BITS + 2); - // Pop it all off - assert_eq!(s.pop(), Some(false)); - assert_eq!(s.pop(), Some(false)); - assert_eq!(s.pop(), Some(true)); - assert_eq!(s.pop(), Some(true)); - assert_eq!(s.len(), 5 * u32::BITS - 2); - } - - #[test] - fn test_bit_vec_truncate() { - let mut s = BitVec::from_elem(5 * u32::BITS, true); - - assert_eq!(s, BitVec::from_elem(5 * u32::BITS, true)); - assert_eq!(s.len(), 5 * u32::BITS); - s.truncate(4 * u32::BITS); - assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true)); - assert_eq!(s.len(), 4 * u32::BITS); - // Truncating to a size > s.len() should be a noop - s.truncate(5 * u32::BITS); - assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true)); - assert_eq!(s.len(), 4 * u32::BITS); - s.truncate(3 * u32::BITS - 10); - assert_eq!(s, BitVec::from_elem(3 * u32::BITS - 10, true)); - assert_eq!(s.len(), 3 * u32::BITS - 10); - s.truncate(0); - assert_eq!(s, BitVec::from_elem(0, true)); - assert_eq!(s.len(), 0); - } - - #[test] - fn test_bit_vec_reserve() { - let mut s = BitVec::from_elem(5 * u32::BITS, true); - // Check capacity - assert!(s.capacity() >= 5 * u32::BITS); - s.reserve(2 * u32::BITS); - assert!(s.capacity() >= 7 * u32::BITS); - s.reserve(7 * u32::BITS); - assert!(s.capacity() >= 12 * u32::BITS); - s.reserve_exact(7 * u32::BITS); - assert!(s.capacity() >= 12 * u32::BITS); - s.reserve(7 * u32::BITS + 1); - assert!(s.capacity() >= 12 * u32::BITS + 1); - // Check that length hasn't changed - assert_eq!(s.len(), 5 * u32::BITS); - s.push(true); - s.push(false); - s.push(true); - assert_eq!(s[5 * u32::BITS - 1], true); - assert_eq!(s[5 * u32::BITS - 0], true); - assert_eq!(s[5 * u32::BITS + 1], false); - assert_eq!(s[5 * u32::BITS + 2], true); - } - - #[test] - fn test_bit_vec_grow() { - let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); - bit_vec.grow(32, true); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF])); - bit_vec.grow(64, false); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); - bit_vec.grow(16, true); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); - } - - #[test] - fn test_bit_vec_extend() { - let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); - let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); - bit_vec.extend(ext.iter()); - assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111, - 0b01001001, 0b10010010, 0b10111101])); - } -} - - - - -#[cfg(test)] -mod bit_vec_bench { - use std::prelude::v1::*; - use std::rand; - use std::rand::Rng; - use std::u32; - use test::{Bencher, black_box}; - - use super::BitVec; - - static BENCH_BITS : usize = 1 << 14; - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_usize_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = 0 as usize; - b.iter(|| { - for _ in 0..100 { - bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_big_fixed(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_big_variable(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen()); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_set_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitVec::from_elem(u32::BITS, false); - b.iter(|| { - for _ in 0..100 { - bit_vec.set((r.next_u32() as usize) % u32::BITS, true); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vec_big_union(b: &mut Bencher) { - let mut b1 = BitVec::from_elem(BENCH_BITS, false); - let b2 = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - b1.union(&b2) - }) - } - - #[bench] - fn bench_bit_vec_small_iter(b: &mut Bencher) { - let bit_vec = BitVec::from_elem(u32::BITS, false); - b.iter(|| { - let mut sum = 0; - for _ in 0..10 { - for pres in &bit_vec { - sum += pres as usize; - } - } - sum - }) - } - - #[bench] - fn bench_bit_vec_big_iter(b: &mut Bencher) { - let bit_vec = BitVec::from_elem(BENCH_BITS, false); - b.iter(|| { - let mut sum = 0; - for pres in &bit_vec { - sum += pres as usize; - } - sum - }) - } -} - - - - - - - -#[cfg(test)] -mod bit_set_test { - use prelude::*; - use std::iter::range_step; - - use super::{BitVec, BitSet}; - - #[test] - fn test_bit_set_show() { - let mut s = BitSet::new(); - s.insert(1); - s.insert(10); - s.insert(50); - s.insert(2); - assert_eq!("BitSet {1, 2, 10, 50}", format!("{:?}", s)); - } - - #[test] - fn test_bit_set_from_usizes() { - let usizes = vec![0, 2, 2, 3]; - let a: BitSet = usizes.into_iter().collect(); - let mut b = BitSet::new(); - b.insert(0); - b.insert(2); - b.insert(3); - assert_eq!(a, b); - } - - #[test] - fn test_bit_set_iterator() { - let usizes = vec![0, 2, 2, 3]; - let bit_vec: BitSet = usizes.into_iter().collect(); - - let idxs: Vec<_> = bit_vec.iter().collect(); - assert_eq!(idxs, vec![0, 2, 3]); - - let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); - let real: Vec<_> = range_step(0, 10000, 2).collect(); - - let idxs: Vec<_> = long.iter().collect(); - assert_eq!(idxs, real); - } - - #[test] - fn test_bit_set_frombit_vec_init() { - let bools = [true, false]; - let lengths = [10, 64, 100]; - for &b in &bools { - for &l in &lengths { - let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b)); - assert_eq!(bitset.contains(&1), b); - assert_eq!(bitset.contains(&(l-1)), b); - assert!(!bitset.contains(&l)); - } - } - } - - #[test] - fn test_bit_vec_masking() { - let b = BitVec::from_elem(140, true); - let mut bs = BitSet::from_bit_vec(b); - assert!(bs.contains(&139)); - assert!(!bs.contains(&140)); - assert!(bs.insert(150)); - assert!(!bs.contains(&140)); - assert!(!bs.contains(&149)); - assert!(bs.contains(&150)); - assert!(!bs.contains(&151)); - } - - #[test] - fn test_bit_set_basic() { - let mut b = BitSet::new(); - assert!(b.insert(3)); - assert!(!b.insert(3)); - assert!(b.contains(&3)); - assert!(b.insert(4)); - assert!(!b.insert(4)); - assert!(b.contains(&3)); - assert!(b.insert(400)); - assert!(!b.insert(400)); - assert!(b.contains(&400)); - assert_eq!(b.len(), 3); - } - - #[test] - fn test_bit_set_intersection() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let expected = [3, 5, 11, 77]; - let actual: Vec<_> = a.intersection(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_difference() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(200)); - assert!(a.insert(500)); - - assert!(b.insert(3)); - assert!(b.insert(200)); - - let expected = [1, 5, 500]; - let actual: Vec<_> = a.difference(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_symmetric_difference() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(220)); - - let expected = [1, 5, 11, 14, 220]; - let actual: Vec<_> = a.symmetric_difference(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_union() { - let mut a = BitSet::new(); - let mut b = BitSet::new(); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(160)); - assert!(a.insert(19)); - assert!(a.insert(24)); - assert!(a.insert(200)); - - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; - let actual: Vec<_> = a.union(&b).collect(); - assert_eq!(actual, expected); - } - - #[test] - fn test_bit_set_subset() { - let mut set1 = BitSet::new(); - let mut set2 = BitSet::new(); - - assert!(set1.is_subset(&set2)); // {} {} - set2.insert(100); - assert!(set1.is_subset(&set2)); // {} { 1 } - set2.insert(200); - assert!(set1.is_subset(&set2)); // {} { 1, 2 } - set1.insert(200); - assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } - set1.insert(300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } - set2.insert(300); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } - set2.insert(400); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } - set2.remove(&100); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } - set2.remove(&300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } - set1.remove(&300); - assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } - } - - #[test] - fn test_bit_set_is_disjoint() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000])); - let c = BitSet::new(); - let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000])); - - assert!(!a.is_disjoint(&d)); - assert!(!d.is_disjoint(&a)); - - assert!(a.is_disjoint(&b)); - assert!(a.is_disjoint(&c)); - assert!(b.is_disjoint(&a)); - assert!(b.is_disjoint(&c)); - assert!(c.is_disjoint(&a)); - assert!(c.is_disjoint(&b)); - } - - #[test] - fn test_bit_set_union_with() { - //a should grow to include larger elements - let mut a = BitSet::new(); - a.insert(0); - let mut b = BitSet::new(); - b.insert(5); - let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); - a.union_with(&b); - assert_eq!(a, expected); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.union_with(&b); - b.union_with(&c); - assert_eq!(a.len(), 4); - assert_eq!(b.len(), 4); - } - - #[test] - fn test_bit_set_intersect_with() { - // Explicitly 0'ed bits - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::new(); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bit_set_difference_with() { - // Explicitly 0'ed bits - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitSet::new(); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); - let c = a.clone(); - a.difference_with(&b); - b.difference_with(&c); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - } - - #[test] - fn test_bit_set_symmetric_difference_with() { - //a should grow to include larger elements - let mut a = BitSet::new(); - a.insert(0); - a.insert(1); - let mut b = BitSet::new(); - b.insert(1); - b.insert(5); - let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); - a.symmetric_difference_with(&b); - assert_eq!(a, expected); - - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::new(); - let c = a.clone(); - a.symmetric_difference_with(&b); - assert_eq!(a, c); - - // Standard - let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010])); - let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010])); - let c = a.clone(); - a.symmetric_difference_with(&b); - b.symmetric_difference_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bit_set_eq() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = BitSet::new(); - - assert!(a == a); - assert!(a != b); - assert!(a != c); - assert!(b == b); - assert!(b == c); - assert!(c == c); - } - - #[test] - fn test_bit_set_cmp() { - let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); - let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); - let c = BitSet::new(); - - assert_eq!(a.cmp(&b), Greater); - assert_eq!(a.cmp(&c), Greater); - assert_eq!(b.cmp(&a), Less); - assert_eq!(b.cmp(&c), Equal); - assert_eq!(c.cmp(&a), Less); - assert_eq!(c.cmp(&b), Equal); - } - - #[test] - fn test_bit_vec_remove() { - let mut a = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.remove(&1)); - - assert!(a.insert(100)); - assert!(a.remove(&100)); - - assert!(a.insert(1000)); - assert!(a.remove(&1000)); - a.shrink_to_fit(); - } - - #[test] - fn test_bit_vec_clone() { - let mut a = BitSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(100)); - assert!(a.insert(1000)); - - let mut b = a.clone(); - - assert!(a == b); - - assert!(b.remove(&1)); - assert!(a.contains(&1)); - - assert!(a.remove(&1000)); - assert!(b.contains(&1000)); - } -} - - - - - -#[cfg(test)] -mod bit_set_bench { - use std::prelude::v1::*; - use std::rand; - use std::rand::Rng; - use std::u32; - use test::{Bencher, black_box}; - - use super::{BitVec, BitSet}; - - static BENCH_BITS : usize = 1 << 14; - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_bit_vecset_small(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitSet::new(); - b.iter(|| { - for _ in 0..100 { - bit_vec.insert((r.next_u32() as usize) % u32::BITS); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vecset_big(b: &mut Bencher) { - let mut r = rng(); - let mut bit_vec = BitSet::new(); - b.iter(|| { - for _ in 0..100 { - bit_vec.insert((r.next_u32() as usize) % BENCH_BITS); - } - black_box(&bit_vec); - }); - } - - #[bench] - fn bench_bit_vecset_iter(b: &mut Bencher) { - let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, - |idx| {idx % 3 == 0})); - b.iter(|| { - let mut sum = 0; - for idx in &bit_vec { - sum += idx as usize; - } - sum - }) - } -} diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 901d7a73b5..2fe769b73f 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -14,6 +14,7 @@ use core::clone::Clone; use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::convert::AsRef; use core::hash::{Hash, Hasher}; use core::marker::Sized; use core::ops::Deref; @@ -39,6 +40,24 @@ use self::Cow::*; #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrow from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Borrow; + /// + /// fn check>(s: T) { + /// assert_eq!("Hello", s.borrow()); + /// } + /// + /// let s = "Hello".to_string(); + /// + /// check(s); + /// + /// let s = "Hello"; + /// + /// check(s); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn borrow(&self) -> &Borrowed; } @@ -49,6 +68,20 @@ pub trait Borrow { #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut : Borrow { /// Mutably borrow from an owned value. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::BorrowMut; + /// + /// fn check>(mut v: T) { + /// assert_eq!(&mut [1, 2, 3], v.borrow_mut()); + /// } + /// + /// let v = vec![1, 2, 3]; + /// + /// check(v); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn borrow_mut(&mut self) -> &mut Borrowed; } @@ -127,12 +160,12 @@ impl ToOwned for T where T: Clone { /// is desired, `to_mut` will obtain a mutable references to an owned /// value, cloning if necessary. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::borrow::Cow; /// -/// fn abs_all(input: &mut Cow<[int]>) { +/// fn abs_all(input: &mut Cow<[i32]>) { /// for i in 0..input.len() { /// let v = input[i]; /// if v < 0 { @@ -170,6 +203,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { /// Acquire a mutable reference to the owned form of the data. /// /// Copies the data if it is not already owned. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); + /// + /// let hello = cow.to_mut(); + /// + /// assert_eq!(hello, &[1, 2, 3]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_mut(&mut self) -> &mut ::Owned { match *self { @@ -184,6 +229,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { /// Extract the owned data. /// /// Copies the data if it is not already owned. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// + /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]); + /// + /// let hello = cow.into_owned(); + /// + /// assert_eq!(vec![1, 2, 3], hello); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_owned(self) -> ::Owned { match self { @@ -191,26 +248,6 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { Owned(owned) => owned } } - - /// Returns true if this `Cow` wraps a borrowed value - #[deprecated(since = "1.0.0", reason = "match on the enum instead")] - #[unstable(feature = "std_misc")] - pub fn is_borrowed(&self) -> bool { - match *self { - Borrowed(_) => true, - _ => false, - } - } - - /// Returns true if this `Cow` wraps an owned value - #[deprecated(since = "1.0.0", reason = "match on the enum instead")] - #[unstable(feature = "std_misc")] - pub fn is_owned(&self) -> bool { - match *self { - Owned(_) => true, - _ => false, - } - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -282,16 +319,6 @@ impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where } #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(stage0)] -impl<'a, B: ?Sized, S: Hasher> Hash for Cow<'a, B> where B: Hash + ToOwned -{ - #[inline] - fn hash(&self, state: &mut S) { - Hash::hash(&**self, state) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned { #[inline] @@ -301,10 +328,9 @@ impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned } /// Trait for moving into a `Cow` -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")] pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { /// Moves `self` into `Cow` - #[stable(feature = "rust1", since = "1.0.0")] fn into_cow(self) -> Cow<'a, B>; } @@ -314,3 +340,10 @@ impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { self } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Clone> AsRef for Cow<'a, T> { + fn as_ref(&self) -> &T { + self + } +} diff --git a/src/libcollections/borrow_stage0.rs b/src/libcollections/borrow_stage0.rs deleted file mode 100644 index c1d74b16ce..0000000000 --- a/src/libcollections/borrow_stage0.rs +++ /dev/null @@ -1,313 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A module for working with borrowed data. - -#![stable(feature = "rust1", since = "1.0.0")] - -use core::clone::Clone; -use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; -use core::hash::{Hash, Hasher}; -use core::marker::Sized; -use core::ops::Deref; -use core::option::Option; - -use fmt; -use alloc::{rc, arc}; - -use self::Cow::*; - -/// A trait for borrowing data. -/// -/// In general, there may be several ways to "borrow" a piece of data. The -/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` -/// (a mutable borrow). But types like `Vec` provide additional kinds of -/// borrows: the borrowed slices `&[T]` and `&mut [T]`. -/// -/// When writing generic code, it is often desirable to abstract over all ways -/// of borrowing data from a given type. That is the role of the `Borrow` -/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given -/// type can be borrowed as multiple different types. In particular, `Vec: -/// Borrow>` and `Vec: Borrow<[T]>`. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Borrow { - /// Immutably borrow from an owned value. - #[stable(feature = "rust1", since = "1.0.0")] - fn borrow(&self) -> &Borrowed; -} - -/// A trait for mutably borrowing data. -/// -/// Similar to `Borrow`, but for mutable borrows. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait BorrowMut : Borrow { - /// Mutably borrow from an owned value. - #[stable(feature = "rust1", since = "1.0.0")] - fn borrow_mut(&mut self) -> &mut Borrowed; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for T { - fn borrow(&self) -> &T { self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl BorrowMut for T { - fn borrow_mut(&mut self) -> &mut T { self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> Borrow for &'a T { - fn borrow(&self) -> &T { &**self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> Borrow for &'a mut T { - fn borrow(&self) -> &T { &**self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: ?Sized> BorrowMut for &'a mut T { - fn borrow_mut(&mut self) -> &mut T { &mut **self } -} - -impl Borrow for rc::Rc { - fn borrow(&self) -> &T { &**self } -} - -impl Borrow for arc::Arc { - fn borrow(&self) -> &T { &**self } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Borrow for Cow<'a, B> where B: ToOwned, ::Owned: 'a { - fn borrow(&self) -> &B { - &**self - } -} - -/// A generalization of Clone to borrowed data. -/// -/// Some types make it possible to go from borrowed to owned, usually by -/// implementing the `Clone` trait. But `Clone` works only for going from `&T` -/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data -/// from any borrow of a given type. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait ToOwned { - #[stable(feature = "rust1", since = "1.0.0")] - type Owned: Borrow; - - /// Create owned data from borrowed data, usually by copying. - #[stable(feature = "rust1", since = "1.0.0")] - fn to_owned(&self) -> Self::Owned; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ToOwned for T where T: Clone { - type Owned = T; - fn to_owned(&self) -> T { self.clone() } -} - -/// A clone-on-write smart pointer. -/// -/// The type `Cow` is a smart pointer providing clone-on-write functionality: it -/// can enclose and provide immutable access to borrowed data, and clone the -/// data lazily when mutation or ownership is required. The type is designed to -/// work with general borrowed data via the `Borrow` trait. -/// -/// `Cow` implements both `Deref`, which means that you can call -/// non-mutating methods directly on the data it encloses. If mutation -/// is desired, `to_mut` will obtain a mutable references to an owned -/// value, cloning if necessary. -/// -/// # Example -/// -/// ```rust -/// use std::borrow::Cow; -/// -/// fn abs_all(input: &mut Cow<[int]>) { -/// for i in 0..input.len() { -/// let v = input[i]; -/// if v < 0 { -/// // clones into a vector the first time (if not already owned) -/// input.to_mut()[i] = -v; -/// } -/// } -/// } -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned { - /// Borrowed data. - #[stable(feature = "rust1", since = "1.0.0")] - Borrowed(&'a B), - - /// Owned data. - #[stable(feature = "rust1", since = "1.0.0")] - Owned(::Owned) -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { - fn clone(&self) -> Cow<'a, B> { - match *self { - Borrowed(b) => Borrowed(b), - Owned(ref o) => { - let b: &B = o.borrow(); - Owned(b.to_owned()) - }, - } - } -} - -impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned, ::Owned: 'a { - /// Acquire a mutable reference to the owned form of the data. - /// - /// Copies the data if it is not already owned. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn to_mut(&mut self) -> &mut ::Owned where ::Owned: 'a { - match *self { - Borrowed(borrowed) => { - *self = Owned(borrowed.to_owned()); - self.to_mut() - } - Owned(ref mut owned) => owned - } - } - - /// Extract the owned data. - /// - /// Copies the data if it is not already owned. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_owned(self) -> ::Owned { - match self { - Borrowed(borrowed) => borrowed.to_owned(), - Owned(owned) => owned - } - } - - /// Returns true if this `Cow` wraps a borrowed value - #[deprecated(since = "1.0.0", reason = "match on the enum instead")] - #[unstable(feature = "std_misc")] - pub fn is_borrowed(&self) -> bool { - match *self { - Borrowed(_) => true, - _ => false, - } - } - - /// Returns true if this `Cow` wraps an owned value - #[deprecated(since = "1.0.0", reason = "match on the enum instead")] - #[unstable(feature = "std_misc")] - pub fn is_owned(&self) -> bool { - match *self { - Owned(_) => true, - _ => false, - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Deref for Cow<'a, B> where - B: ToOwned, ::Owned: 'a -{ - type Target = B; - - fn deref(&self) -> &B { - match *self { - Borrowed(borrowed) => borrowed, - Owned(ref owned) => owned.borrow() - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned, ::Owned: 'a {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> Ord for Cow<'a, B> where - B: Ord + ToOwned, ::Owned: 'a -{ - #[inline] - fn cmp(&self, other: &Cow<'a, B>) -> Ordering { - Ord::cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> where - B: PartialEq + ToOwned, C: ToOwned, - ::Owned: 'a, ::Owned: 'b, -{ - #[inline] - fn eq(&self, other: &Cow<'b, C>) -> bool { - PartialEq::eq(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where - B: PartialOrd + ToOwned, ::Owned: 'a -{ - #[inline] - fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where - B: fmt::Debug + ToOwned, - ::Owned: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Borrowed(ref b) => fmt::Debug::fmt(b, f), - Owned(ref o) => fmt::Debug::fmt(o, f), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where - B: fmt::Display + ToOwned, - ::Owned: fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Borrowed(ref b) => fmt::Display::fmt(b, f), - Owned(ref o) => fmt::Display::fmt(o, f), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized, S: Hasher> Hash for Cow<'a, B> where - B: Hash + ToOwned, ::Owned: 'a -{ - #[inline] - fn hash(&self, state: &mut S) { - Hash::hash(&**self, state) - } -} - -/// Trait for moving into a `Cow` -#[stable(feature = "rust1", since = "1.0.0")] -pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { - /// Moves `self` into `Cow` - #[stable(feature = "rust1", since = "1.0.0")] - fn into_cow(self) -> Cow<'a, B>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - fn into_cow(self) -> Cow<'a, B> { - self - } -} diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 7823f536c7..adfb284dab 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -24,8 +24,8 @@ use core::default::Default; use core::fmt::Debug; use core::hash::{Hash, Hasher}; use core::iter::{Map, FromIterator, IntoIterator}; -use core::ops::{Index, IndexMut}; -use core::{iter, fmt, mem}; +use core::ops::Index; +use core::{iter, fmt, mem, usize}; use Bound::{self, Included, Excluded, Unbounded}; use borrow::Borrow; @@ -64,6 +64,10 @@ use super::node::{self, Node, Found, GoDown}; /// and possibly other factors. Using linear search, searching for a random element is expected /// to take O(B logBn) comparisons, which is generally worse than a BST. In practice, /// however, performance is excellent. +/// +/// It is a logic error for a key to be modified in such a way that the key's ordering relative to +/// any other key, as determined by the `Ord` trait, changes while it is in the map. This is +/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BTreeMap { @@ -74,6 +78,7 @@ pub struct BTreeMap { } /// An abstract base over-which all other BTree iterators are built. +#[derive(Clone)] struct AbsIter { traversals: VecDeque, size: usize, @@ -120,26 +125,26 @@ pub struct RangeMut<'a, K: 'a, V: 'a> { } /// A view into a single entry in a map, which may either be vacant or occupied. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, K:'a, V:'a> { /// A vacant Entry + #[stable(feature = "rust1", since = "1.0.0")] Vacant(VacantEntry<'a, K, V>), + /// An occupied Entry + #[stable(feature = "rust1", since = "1.0.0")] Occupied(OccupiedEntry<'a, K, V>), } /// A vacant Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry<'a, K:'a, V:'a> { key: K, stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>, } /// An occupied Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry<'a, K:'a, V:'a> { stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>, } @@ -260,7 +265,7 @@ impl BTreeMap { /// Some(x) => *x = "b", /// None => (), /// } - /// assert_eq!(map[1], "b"); + /// assert_eq!(map[&1], "b"); /// ``` // See `get` for implementation notes, this is basically a copy-paste with mut's added #[stable(feature = "rust1", since = "1.0.0")] @@ -322,7 +327,7 @@ impl BTreeMap { /// /// map.insert(37, "b"); /// assert_eq!(map.insert(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); + /// assert_eq!(map[&37], "c"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, mut key: K, mut value: V) -> Option { @@ -347,7 +352,7 @@ impl BTreeMap { let result = stack.with(move |pusher, node| { // Same basic logic as found in `find`, but with PartialSearchStack mediating the // actual nodes for us - return match Node::search(node, &key) { + match Node::search(node, &key) { Found(mut handle) => { // Perfect match, swap the values and return the old one mem::swap(handle.val_mut(), &mut value); @@ -372,7 +377,7 @@ impl BTreeMap { } }); match result { - Finished(ret) => { return ret; }, + Finished(ret) => return ret, Continue((new_stack, renewed_key, renewed_val)) => { stack = new_stack; key = renewed_key; @@ -439,7 +444,7 @@ impl BTreeMap { let mut stack = stack::PartialSearchStack::new(self); loop { let result = stack.with(move |pusher, node| { - return match Node::search(node, key) { + match Node::search(node, key) { Found(handle) => { // Perfect match. Terminate the stack here, and remove the entry Finished(Some(pusher.seal(handle).remove())) @@ -852,16 +857,6 @@ impl Extend<(K, V)> for BTreeMap { } } -#[cfg(stage0)] -#[stable(feature = "rust1", since = "1.0.0")] -impl, V: Hash> Hash for BTreeMap { - fn hash(&self, state: &mut S) { - for elt in self { - elt.hash(state); - } - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for BTreeMap { fn hash(&self, state: &mut H) { @@ -909,37 +904,22 @@ impl Ord for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for BTreeMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "BTreeMap {{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}: {:?}", *k, *v)); - } - - write!(f, "}}") + self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Index for BTreeMap +impl<'a, K: Ord, Q: ?Sized, V> Index<&'a Q> for BTreeMap where K: Borrow, Q: Ord { type Output = V; + #[inline] fn index(&self, key: &Q) -> &V { self.get(key).expect("no entry found for key") } } -#[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for BTreeMap - where K: Borrow, Q: Ord -{ - fn index_mut(&mut self, key: &Q) -> &mut V { - self.get_mut(key).expect("no entry found for key") - } -} - /// Genericises over how to get the correct type of iterator from the correct type /// of Node ownership. trait Traverse { @@ -1040,6 +1020,9 @@ impl DoubleEndedIterator for AbsIter where } } +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Iter<'a, K, V> { Iter { inner: self.inner.clone() } } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); @@ -1082,6 +1065,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} +impl<'a, K, V> Clone for Keys<'a, K, V> { + fn clone(&self) -> Keys<'a, K, V> { Keys { inner: self.inner.clone() } } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; @@ -1097,6 +1083,9 @@ impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {} +impl<'a, K, V> Clone for Values<'a, K, V> { + fn clone(&self) -> Values<'a, K, V> { Values { inner: self.inner.clone() } } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Values<'a, K, V> { type Item = &'a V; @@ -1111,6 +1100,9 @@ impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {} +impl<'a, K, V> Clone for Range<'a, K, V> { + fn clone(&self) -> Range<'a, K, V> { Range { inner: self.inner.clone() } } +} impl<'a, K, V> Iterator for Range<'a, K, V> { type Item = (&'a K, &'a V); @@ -1130,8 +1122,10 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { } impl<'a, K: Ord, V> Entry<'a, K, V> { - #[unstable(feature = "collections", - reason = "matches collection reform v2 specification, waiting for dust to settle")] + #[unstable(feature = "std_misc", + reason = "will soon be replaced by or_insert")] + #[deprecated(since = "1.0", + reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { @@ -1139,6 +1133,26 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { Vacant(entry) => Err(entry), } } + + #[stable(feature = "rust1", since = "1.0.0")] + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } } impl<'a, K: Ord, V> VacantEntry<'a, K, V> { @@ -1187,7 +1201,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { impl BTreeMap { /// Gets an iterator over the entries of the map. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::BTreeMap; @@ -1284,6 +1298,7 @@ impl BTreeMap { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); @@ -1291,7 +1306,7 @@ impl BTreeMap { /// a.insert(2, "b"); /// /// let keys: Vec = a.keys().cloned().collect(); - /// assert_eq!(keys, vec![1,2,]); + /// assert_eq!(keys, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { @@ -1306,6 +1321,7 @@ impl BTreeMap { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeMap; /// /// let mut a = BTreeMap::new(); @@ -1313,7 +1329,7 @@ impl BTreeMap { /// a.insert(2, "b"); /// /// let values: Vec<&str> = a.values().cloned().collect(); - /// assert_eq!(values, vec!["a","b"]); + /// assert_eq!(values, ["a", "b"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn values<'a>(&'a self) -> Values<'a, K, V> { @@ -1477,7 +1493,7 @@ macro_rules! range_impl { $Range { inner: AbsIter { traversals: traversals, - size: 0, // unused + size: usize::MAX, // unused } } } @@ -1493,6 +1509,7 @@ impl BTreeMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BTreeMap; /// use std::collections::Bound::{Included, Unbounded}; /// @@ -1519,6 +1536,7 @@ impl BTreeMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BTreeMap; /// use std::collections::Bound::{Included, Excluded}; /// @@ -1544,22 +1562,14 @@ impl BTreeMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; /// /// let mut count: BTreeMap<&str, usize> = BTreeMap::new(); /// /// // 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) { - /// Entry::Vacant(view) => { - /// view.insert(1); - /// }, - /// Entry::Occupied(mut view) => { - /// let v = view.get_mut(); - /// *v += 1; - /// }, - /// } + /// for x in vec!["a","b","a","c","a","b"] { + /// *count.entry(x).or_insert(0) += 1; /// } /// /// assert_eq!(count["a"], 3); @@ -1570,7 +1580,7 @@ impl BTreeMap { let mut stack = stack::PartialSearchStack::new(self); loop { let result = stack.with(move |pusher, node| { - return match Node::search(node, &key) { + match Node::search(node, &key) { Found(handle) => { // Perfect match Finished(Occupied(OccupiedEntry { @@ -1605,309 +1615,3 @@ impl BTreeMap { } } } - - - - - -#[cfg(test)] -mod test { - use prelude::*; - use std::iter::range_inclusive; - - use super::BTreeMap; - use super::Entry::{Occupied, Vacant}; - use Bound::{self, Included, Excluded, Unbounded}; - - #[test] - fn test_basic_large() { - let mut map = BTreeMap::new(); - let size = 10000; - assert_eq!(map.len(), 0); - - for i in 0..size { - assert_eq!(map.insert(i, 10*i), None); - assert_eq!(map.len(), i + 1); - } - - for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i*10)); - } - - for i in size..size*2 { - assert_eq!(map.get(&i), None); - } - - for i in 0..size { - assert_eq!(map.insert(i, 100*i), Some(10*i)); - assert_eq!(map.len(), size); - } - - for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i*100)); - } - - for i in 0..size/2 { - assert_eq!(map.remove(&(i*2)), Some(i*200)); - assert_eq!(map.len(), size - i - 1); - } - - for i in 0..size/2 { - assert_eq!(map.get(&(2*i)), None); - assert_eq!(map.get(&(2*i+1)).unwrap(), &(i*200 + 100)); - } - - for i in 0..size/2 { - assert_eq!(map.remove(&(2*i)), None); - assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100)); - assert_eq!(map.len(), size/2 - i - 1); - } - } - - #[test] - fn test_basic_small() { - let mut map = BTreeMap::new(); - assert_eq!(map.remove(&1), None); - assert_eq!(map.get(&1), None); - assert_eq!(map.insert(1, 1), None); - assert_eq!(map.get(&1), Some(&1)); - assert_eq!(map.insert(1, 2), Some(1)); - assert_eq!(map.get(&1), Some(&2)); - assert_eq!(map.insert(2, 4), None); - assert_eq!(map.get(&2), Some(&4)); - assert_eq!(map.remove(&1), Some(2)); - assert_eq!(map.remove(&2), Some(4)); - assert_eq!(map.remove(&1), None); - } - - #[test] - fn test_iter() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(size: usize, mut iter: T) where T: Iterator { - for i in 0..size { - assert_eq!(iter.size_hint(), (size - i, Some(size - i))); - assert_eq!(iter.next().unwrap(), (i, i)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter()); - } - - #[test] - fn test_iter_rev() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(size: usize, mut iter: T) where T: Iterator { - for i in 0..size { - assert_eq!(iter.size_hint(), (size - i, Some(size - i))); - assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().rev().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter().rev()); - } - - #[test] - fn test_iter_mixed() { - let size = 10000; - - // Forwards - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(size: usize, mut iter: T) - where T: Iterator + DoubleEndedIterator { - for i in 0..size / 4 { - assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); - assert_eq!(iter.next().unwrap(), (i, i)); - assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); - } - for i in size / 4..size * 3 / 4 { - assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); - assert_eq!(iter.next().unwrap(), (i, i)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter()); - } - - #[test] - fn test_range_small() { - let size = 5; - - // Forwards - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - let mut j = 0; - for ((&k, &v), i) in map.range(Included(&2), Unbounded).zip(2..size) { - assert_eq!(k, i); - assert_eq!(v, i); - j += 1; - } - assert_eq!(j, size - 2); - } - - #[test] - fn test_range_1000() { - let size = 1000; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { - let mut kvs = map.range(min, max).map(|(&k, &v)| (k, v)); - let mut pairs = (0..size).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - test(&map, size, Included(&0), Excluded(&size)); - test(&map, size, Unbounded, Excluded(&size)); - test(&map, size, Included(&0), Included(&(size - 1))); - test(&map, size, Unbounded, Included(&(size - 1))); - test(&map, size, Included(&0), Unbounded); - test(&map, size, Unbounded, Unbounded); - } - - #[test] - fn test_range() { - let size = 200; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - for i in 0..size { - for j in i..size { - let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); - let mut pairs = range_inclusive(i, j).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - } - } - - #[test] - fn test_entry(){ - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - *v *= 10; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } -} - - - - - - -#[cfg(test)] -mod bench { - use prelude::*; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - use super::BTreeMap; - - map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} - map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} - - map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} - map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} - - map_find_rand_bench!{find_rand_100, 100, BTreeMap} - map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} - - map_find_seq_bench!{find_seq_100, 100, BTreeMap} - map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} - - fn bench_iter(b: &mut Bencher, size: i32) { - let mut map = BTreeMap::::new(); - let mut rng = weak_rng(); - - for _ in 0..size { - map.insert(rng.gen(), rng.gen()); - } - - b.iter(|| { - for entry in &map { - black_box(entry); - } - }); - } - - #[bench] - pub fn iter_20(b: &mut Bencher) { - bench_iter(b, 20); - } - - #[bench] - pub fn iter_1000(b: &mut Bencher) { - bench_iter(b, 1000); - } - - #[bench] - pub fn iter_100000(b: &mut Bencher) { - bench_iter(b, 100000); - } -} diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index f0fc12da72..26c5725604 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -23,7 +23,7 @@ use core::iter::Zip; use core::marker::PhantomData; use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::ptr::Unique; -use core::{slice, mem, ptr, cmp, num, raw}; +use core::{slice, mem, ptr, cmp, raw}; use alloc::heap::{self, EMPTY}; use borrow::Borrow; @@ -105,7 +105,7 @@ struct MutNodeSlice<'a, K: 'a, V: 'a> { /// Fails if `target_alignment` is not a power of two. #[inline] fn round_up_to_next(unrounded: usize, target_alignment: usize) -> usize { - assert!(num::UnsignedInt::is_power_of_two(target_alignment)); + assert!(target_alignment.is_power_of_two()); (unrounded + target_alignment - 1) & !(target_alignment - 1) } @@ -280,9 +280,11 @@ impl Drop for RawItems { #[unsafe_destructor] impl Drop for Node { fn drop(&mut self) { - if self.keys.is_null() { + if self.keys.is_null() || + (unsafe { self.keys.get() as *const K as usize == mem::POST_DROP_USIZE }) + { // Since we have #[unsafe_no_drop_flag], we have to watch - // out for a null value being stored in self.keys. (Using + // out for the sentinel value being stored in self.keys. (Using // null is technically a violation of the `Unique` // requirements, though.) return; @@ -348,14 +350,8 @@ impl Node { #[inline] pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) { unsafe {( - mem::transmute(raw::Slice { - data: *self.keys as *const K, - len: self.len() - }), - mem::transmute(raw::Slice { - data: *self.vals as *const V, - len: self.len() - }) + slice::from_raw_parts(*self.keys, self.len()), + slice::from_raw_parts(*self.vals, self.len()), )} } @@ -530,7 +526,7 @@ impl Clone for Node { /// println!("Uninitialized memory: {:?}", handle.into_kv()); /// } /// ``` -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Handle { node: NodeRef, index: usize, @@ -1085,7 +1081,7 @@ impl Node { vals: RawItems::from_slice(self.vals()), edges: RawItems::from_slice(self.edges()), - ptr: *self.keys as *mut u8, + ptr: Unique::new(*self.keys as *mut u8), capacity: self.capacity(), is_leaf: self.is_leaf() }, @@ -1136,14 +1132,14 @@ impl Node { // This must be followed by insert_edge on an internal node. #[inline] unsafe fn insert_kv(&mut self, index: usize, key: K, val: V) -> &mut V { - ptr::copy_memory( - self.keys_mut().as_mut_ptr().offset(index as isize + 1), + ptr::copy( self.keys().as_ptr().offset(index as isize), + self.keys_mut().as_mut_ptr().offset(index as isize + 1), self.len() - index ); - ptr::copy_memory( - self.vals_mut().as_mut_ptr().offset(index as isize + 1), + ptr::copy( self.vals().as_ptr().offset(index as isize), + self.vals_mut().as_mut_ptr().offset(index as isize + 1), self.len() - index ); @@ -1158,9 +1154,9 @@ impl Node { // This can only be called immediately after a call to insert_kv. #[inline] unsafe fn insert_edge(&mut self, index: usize, edge: Node) { - ptr::copy_memory( - self.edges_mut().as_mut_ptr().offset(index as isize + 1), + ptr::copy( self.edges().as_ptr().offset(index as isize), + self.edges_mut().as_mut_ptr().offset(index as isize + 1), self.len() - index ); ptr::write(self.edges_mut().get_unchecked_mut(index), edge); @@ -1191,14 +1187,14 @@ impl Node { let key = ptr::read(self.keys().get_unchecked(index)); let val = ptr::read(self.vals().get_unchecked(index)); - ptr::copy_memory( - self.keys_mut().as_mut_ptr().offset(index as isize), + ptr::copy( self.keys().as_ptr().offset(index as isize + 1), + self.keys_mut().as_mut_ptr().offset(index as isize), self.len() - index - 1 ); - ptr::copy_memory( - self.vals_mut().as_mut_ptr().offset(index as isize), + ptr::copy( self.vals().as_ptr().offset(index as isize + 1), + self.vals_mut().as_mut_ptr().offset(index as isize), self.len() - index - 1 ); @@ -1212,10 +1208,11 @@ impl Node { unsafe fn remove_edge(&mut self, index: usize) -> Node { let edge = ptr::read(self.edges().get_unchecked(index)); - ptr::copy_memory( - self.edges_mut().as_mut_ptr().offset(index as isize), + ptr::copy( self.edges().as_ptr().offset(index as isize + 1), - self.len() - index + 1 + self.edges_mut().as_mut_ptr().offset(index as isize), + // index can be == len+1, so do the +1 first to avoid underflow. + (self.len() + 1) - index ); edge @@ -1239,20 +1236,20 @@ impl Node { unsafe { right._len = self.len() / 2; let right_offset = self.len() - right.len(); - ptr::copy_nonoverlapping_memory( - right.keys_mut().as_mut_ptr(), + ptr::copy_nonoverlapping( self.keys().as_ptr().offset(right_offset as isize), + right.keys_mut().as_mut_ptr(), right.len() ); - ptr::copy_nonoverlapping_memory( - right.vals_mut().as_mut_ptr(), + ptr::copy_nonoverlapping( self.vals().as_ptr().offset(right_offset as isize), + right.vals_mut().as_mut_ptr(), right.len() ); if !self.is_leaf() { - ptr::copy_nonoverlapping_memory( - right.edges_mut().as_mut_ptr(), + ptr::copy_nonoverlapping( self.edges().as_ptr().offset(right_offset as isize), + right.edges_mut().as_mut_ptr(), right.len() + 1 ); } @@ -1280,20 +1277,20 @@ impl Node { ptr::write(self.keys_mut().get_unchecked_mut(old_len), key); ptr::write(self.vals_mut().get_unchecked_mut(old_len), val); - ptr::copy_nonoverlapping_memory( - self.keys_mut().as_mut_ptr().offset(old_len as isize + 1), + ptr::copy_nonoverlapping( right.keys().as_ptr(), + self.keys_mut().as_mut_ptr().offset(old_len as isize + 1), right.len() ); - ptr::copy_nonoverlapping_memory( - self.vals_mut().as_mut_ptr().offset(old_len as isize + 1), + ptr::copy_nonoverlapping( right.vals().as_ptr(), + self.vals_mut().as_mut_ptr().offset(old_len as isize + 1), right.len() ); if !self.is_leaf() { - ptr::copy_nonoverlapping_memory( - self.edges_mut().as_mut_ptr().offset(old_len as isize + 1), + ptr::copy_nonoverlapping( right.edges().as_ptr(), + self.edges_mut().as_mut_ptr().offset(old_len as isize + 1), right.len() + 1 ); } @@ -1331,6 +1328,7 @@ trait TraversalImpl { /// A `TraversalImpl` that actually is backed by two iterators. This works in the non-moving case, /// as no deallocation needs to be done. +#[derive(Clone)] struct ElemsAndEdges(Elems, Edges); impl @@ -1354,11 +1352,14 @@ struct MoveTraversalImpl { edges: RawItems>, // For deallocation when we are done iterating. - ptr: *mut u8, + ptr: Unique, capacity: usize, is_leaf: bool } +unsafe impl Sync for MoveTraversalImpl {} +unsafe impl Send for MoveTraversalImpl {} + impl TraversalImpl for MoveTraversalImpl { type Item = (K, V); type Edge = Node; @@ -1401,11 +1402,12 @@ impl Drop for MoveTraversalImpl { let (alignment, size) = calculate_allocation_generic::(self.capacity, self.is_leaf); - unsafe { heap::deallocate(self.ptr, size, alignment) }; + unsafe { heap::deallocate(*self.ptr, size, alignment) }; } } /// An abstraction over all the different kinds of traversals a node supports +#[derive(Clone)] struct AbsTraversal { inner: Impl, head_is_edge: bool, @@ -1425,12 +1427,12 @@ pub enum TraversalItem { /// A traversal over a node's entries and edges pub type Traversal<'a, K, V> = AbsTraversal, slice::Iter<'a, V>>, - slice::Iter<'a, Node>>>; + slice::Iter<'a, Node>>>; /// A mutable traversal over a node's entries and edges pub type MutTraversal<'a, K, V> = AbsTraversal, slice::IterMut<'a, V>>, - slice::IterMut<'a, Node>>>; + slice::IterMut<'a, Node>>>; /// An owning traversal over a node's entries and edges pub type MoveTraversal = AbsTraversal>; @@ -1542,10 +1544,10 @@ macro_rules! node_slice_impl { edges: if !self.has_edges { self.edges } else { - self.edges.$index(&(pos ..)) + self.edges.$index(pos ..) }, keys: &self.keys[pos ..], - vals: self.vals.$index(&(pos ..)), + vals: self.vals.$index(pos ..), head_is_edge: !pos_is_kv, tail_is_edge: self.tail_is_edge, } @@ -1571,10 +1573,10 @@ macro_rules! node_slice_impl { edges: if !self.has_edges { self.edges } else { - self.edges.$index(&(.. (pos + 1))) + self.edges.$index(.. (pos + 1)) }, keys: &self.keys[..pos], - vals: self.vals.$index(&(.. pos)), + vals: self.vals.$index(.. pos), head_is_edge: self.head_is_edge, tail_is_edge: !pos_is_kv, } diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 929b2f5804..840110b5b2 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -30,6 +30,10 @@ use Bound; /// /// See BTreeMap's documentation for a detailed discussion of this collection's performance /// benefits and drawbacks. +/// +/// It is a logic error for an item to be modified in such a way that the item's ordering relative +/// to any other item, as determined by the `Ord` trait, changes while it is in the set. This is +/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. #[derive(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] #[stable(feature = "rust1", since = "1.0.0")] pub struct BTreeSet{ @@ -112,6 +116,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); @@ -121,7 +126,7 @@ impl BTreeSet { /// } /// /// let v: Vec = set.iter().cloned().collect(); - /// assert_eq!(v, vec![1,2,3,4]); + /// assert_eq!(v, [1, 2, 3, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { @@ -133,12 +138,13 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); /// /// let v: Vec = set.into_iter().collect(); - /// assert_eq!(v, vec![1,2,3,4]); + /// assert_eq!(v, [1, 2, 3, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { @@ -158,6 +164,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::BTreeSet; /// use std::collections::Bound::{Included, Unbounded}; /// @@ -186,6 +193,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let mut a = BTreeSet::new(); @@ -197,7 +205,7 @@ impl BTreeSet { /// b.insert(3); /// /// let diff: Vec = a.difference(&b).cloned().collect(); - /// assert_eq!(diff, vec![1]); + /// assert_eq!(diff, [1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { @@ -209,6 +217,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let mut a = BTreeSet::new(); @@ -220,7 +229,7 @@ impl BTreeSet { /// b.insert(3); /// /// let sym_diff: Vec = a.symmetric_difference(&b).cloned().collect(); - /// assert_eq!(sym_diff, vec![1,3]); + /// assert_eq!(sym_diff, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet) @@ -233,6 +242,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let mut a = BTreeSet::new(); @@ -244,7 +254,7 @@ impl BTreeSet { /// b.insert(3); /// /// let intersection: Vec = a.intersection(&b).cloned().collect(); - /// assert_eq!(intersection, vec![2]); + /// assert_eq!(intersection, [2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn intersection<'a>(&'a self, other: &'a BTreeSet) @@ -257,6 +267,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let mut a = BTreeSet::new(); @@ -266,7 +277,7 @@ impl BTreeSet { /// b.insert(2); /// /// let union: Vec = a.union(&b).cloned().collect(); - /// assert_eq!(union, vec![1,2]); + /// assert_eq!(union, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> { @@ -329,6 +340,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); @@ -346,6 +358,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); @@ -367,6 +380,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); @@ -409,6 +423,7 @@ impl BTreeSet { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::BTreeSet; /// /// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect(); @@ -534,7 +549,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a - &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![1, 2]); + /// assert_eq!(result_vec, [1, 2]); /// ``` fn sub(self, rhs: &BTreeSet) -> BTreeSet { self.difference(rhs).cloned().collect() @@ -557,7 +572,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a ^ &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![1, 4]); + /// assert_eq!(result_vec, [1, 4]); /// ``` fn bitxor(self, rhs: &BTreeSet) -> BTreeSet { self.symmetric_difference(rhs).cloned().collect() @@ -580,7 +595,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a & &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![2, 3]); + /// assert_eq!(result_vec, [2, 3]); /// ``` fn bitand(self, rhs: &BTreeSet) -> BTreeSet { self.intersection(rhs).cloned().collect() @@ -603,7 +618,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet> for &'a BTreeSet { /// /// let result = &a | &b; /// let result_vec: Vec<_> = result.into_iter().collect(); - /// assert_eq!(result_vec, vec![1, 2, 3, 4, 5]); + /// assert_eq!(result_vec, [1, 2, 3, 4, 5]); /// ``` fn bitor(self, rhs: &BTreeSet) -> BTreeSet { self.union(rhs).cloned().collect() @@ -613,17 +628,13 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet> for &'a BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for BTreeSet { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "BTreeSet {{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *x)); - } - - write!(f, "}}") + self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish() } } +impl<'a, T> Clone for Iter<'a, T> { + fn clone(&self) -> Iter<'a, T> { Iter { iter: self.iter.clone() } } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; @@ -654,6 +665,9 @@ impl DoubleEndedIterator for IntoIter { impl ExactSizeIterator for IntoIter {} +impl<'a, T> Clone for Range<'a, T> { + fn clone(&self) -> Range<'a, T> { Range { iter: self.iter.clone() } } +} impl<'a, T> Iterator for Range<'a, T> { type Item = &'a T; @@ -673,6 +687,11 @@ fn cmp_opt(x: Option<&T>, y: Option<&T>, } } +impl<'a, T> Clone for Difference<'a, T> { + fn clone(&self) -> Difference<'a, T> { + Difference { a: self.a.clone(), b: self.b.clone() } + } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Ord> Iterator for Difference<'a, T> { type Item = &'a T; @@ -688,6 +707,11 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { } } +impl<'a, T> Clone for SymmetricDifference<'a, T> { + fn clone(&self) -> SymmetricDifference<'a, T> { + SymmetricDifference { a: self.a.clone(), b: self.b.clone() } + } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { type Item = &'a T; @@ -703,6 +727,11 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { } } +impl<'a, T> Clone for Intersection<'a, T> { + fn clone(&self) -> Intersection<'a, T> { + Intersection { a: self.a.clone(), b: self.b.clone() } + } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Ord> Iterator for Intersection<'a, T> { type Item = &'a T; @@ -724,6 +753,11 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { } } +impl<'a, T> Clone for Union<'a, T> { + fn clone(&self) -> Union<'a, T> { + Union { a: self.a.clone(), b: self.b.clone() } + } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Ord> Iterator for Union<'a, T> { type Item = &'a T; @@ -738,180 +772,3 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { } } } - - -#[cfg(test)] -mod test { - use prelude::*; - - use super::BTreeSet; - use std::hash::{self, SipHasher}; - - #[test] - fn test_clone_eq() { - let mut m = BTreeSet::new(); - - m.insert(1); - m.insert(2); - - assert!(m.clone() == m); - } - - #[test] - fn test_hash() { - let mut x = BTreeSet::new(); - let mut y = BTreeSet::new(); - - x.insert(1); - x.insert(2); - x.insert(3); - - y.insert(3); - y.insert(2); - y.insert(1); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - struct Counter<'a, 'b> { - i: &'a mut usize, - expected: &'b [i32], - } - - impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> { - type Output = bool; - - extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool { - assert_eq!(x, self.expected[*self.i]); - *self.i += 1; - true - } - } - - fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) where - // FIXME Replace Counter with `Box _>` - F: FnOnce(&BTreeSet, &BTreeSet, Counter) -> bool, - { - let mut set_a = BTreeSet::new(); - let mut set_b = BTreeSet::new(); - - for x in a { assert!(set_a.insert(*x)) } - for y in b { assert!(set_b.insert(*y)) } - - let mut i = 0; - f(&set_a, &set_b, Counter { i: &mut i, expected: expected }); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_intersection() { - fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.intersection(y).all(f)) - } - - check_intersection(&[], &[], &[]); - check_intersection(&[1, 2, 3], &[], &[]); - check_intersection(&[], &[1, 2, 3], &[]); - check_intersection(&[2], &[1, 2, 3], &[2]); - check_intersection(&[1, 2, 3], &[2], &[2]); - check_intersection(&[11, 1, 3, 77, 103, 5, -5], - &[2, 11, 77, -9, -42, 5, 3], - &[3, 5, 11, 77]); - } - - #[test] - fn test_difference() { - fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.difference(y).all(f)) - } - - check_difference(&[], &[], &[]); - check_difference(&[1, 12], &[], &[1, 12]); - check_difference(&[], &[1, 2, 3, 9], &[]); - check_difference(&[1, 3, 5, 9, 11], - &[3, 9], - &[1, 5, 11]); - check_difference(&[-5, 11, 22, 33, 40, 42], - &[-12, -5, 14, 23, 34, 38, 39, 50], - &[11, 22, 33, 40, 42]); - } - - #[test] - fn test_symmetric_difference() { - fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) - } - - check_symmetric_difference(&[], &[], &[]); - check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); - check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); - check_symmetric_difference(&[1, 3, 5, 9, 11], - &[-2, 3, 9, 14, 22], - &[-2, 1, 5, 11, 14, 22]); - } - - #[test] - fn test_union() { - fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.union(y).all(f)) - } - - check_union(&[], &[], &[]); - check_union(&[1, 2, 3], &[2], &[1, 2, 3]); - check_union(&[2], &[1, 2, 3], &[1, 2, 3]); - check_union(&[1, 3, 5, 9, 11, 16, 19, 24], - &[-2, 1, 5, 9, 13, 19], - &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); - } - - #[test] - fn test_zip() { - let mut x = BTreeSet::new(); - x.insert(5); - x.insert(12); - x.insert(11); - - let mut y = BTreeSet::new(); - y.insert("foo"); - y.insert("bar"); - - let x = x; - let y = y; - let mut z = x.iter().zip(y.iter()); - - // FIXME: #5801: this needs a type hint to compile... - let result: Option<(&usize, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&5, &("bar"))); - - let result: Option<(&usize, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&11, &("foo"))); - - let result: Option<(&usize, & &'static str)> = z.next(); - assert!(result.is_none()); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: BTreeSet<_> = xs.iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - } - - #[test] - fn test_show() { - let mut set = BTreeSet::new(); - let empty = BTreeSet::::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert_eq!(set_str, "BTreeSet {1, 2}"); - assert_eq!(format!("{:?}", empty), "BTreeSet {}"); - } -} diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 0c95742606..0b206d381d 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -16,14 +16,18 @@ use core::prelude::*; use core::marker; use core::fmt; -use core::num::Int; use core::iter::{FromIterator, IntoIterator}; use core::ops::{Sub, BitOr, BitAnd, BitXor}; // FIXME(contentions): implement union family of methods? (general design may be wrong here) -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] /// A specialized set implementation to use enum types. +/// +/// It is a logic error for an item to be modified in such a way that the transformation of the +/// item to or from a `usize`, as determined by the `CLike` trait, changes while the item is in the +/// set. This is normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe +/// code. pub struct EnumSet { // We must maintain the invariant that no bits are set // for which no variant exists @@ -33,10 +37,14 @@ pub struct EnumSet { impl Copy for EnumSet {} +impl Clone for EnumSet { + fn clone(&self) -> EnumSet { *self } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for EnumSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(write!(fmt, "EnumSet {{")); + try!(write!(fmt, "{{")); let mut first = true; for e in self { if !first { @@ -78,7 +86,7 @@ pub trait CLike { fn bit(e: &E) -> usize { use core::usize; let value = e.to_usize(); - assert!(value < usize::BITS, + assert!(value < usize::BITS as usize, "EnumSet only supports up to {} variants.", usize::BITS - 1); 1 << value } @@ -95,7 +103,7 @@ impl EnumSet { #[unstable(feature = "collections", reason = "matches collection reform specification, waiting for dust to settle")] pub fn len(&self) -> usize { - self.bits.count_ones() + self.bits.count_ones() as usize } /// Returns true if the `EnumSet` is empty. @@ -250,7 +258,7 @@ impl Iterator for Iter { } fn size_hint(&self) -> (usize, Option) { - let exact = self.bits.count_ones(); + let exact = self.bits.count_ones() as usize; (exact, Some(exact)) } } @@ -280,241 +288,3 @@ impl Extend for EnumSet { } } } - -#[cfg(test)] -mod test { - use self::Foo::*; - use prelude::*; - use core::mem; - - use super::{EnumSet, CLike}; - - #[derive(Copy, PartialEq, Debug)] - #[repr(usize)] - enum Foo { - A, B, C - } - - impl CLike for Foo { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Foo { - unsafe { mem::transmute(v) } - } - } - - #[test] - fn test_new() { - let e: EnumSet = EnumSet::new(); - assert!(e.is_empty()); - } - - #[test] - fn test_show() { - let mut e = EnumSet::new(); - assert!(format!("{:?}", e) == "EnumSet {}"); - e.insert(A); - assert!(format!("{:?}", e) == "EnumSet {A}"); - e.insert(C); - assert!(format!("{:?}", e) == "EnumSet {A, C}"); - } - - #[test] - fn test_len() { - let mut e = EnumSet::new(); - assert_eq!(e.len(), 0); - e.insert(A); - e.insert(B); - e.insert(C); - assert_eq!(e.len(), 3); - e.remove(&A); - assert_eq!(e.len(), 2); - e.clear(); - assert_eq!(e.len(), 0); - } - - /////////////////////////////////////////////////////////////////////////// - // intersect - - #[test] - fn test_two_empties_do_not_intersect() { - let e1: EnumSet = EnumSet::new(); - let e2: EnumSet = EnumSet::new(); - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_empty_does_not_intersect_with_full() { - let e1: EnumSet = EnumSet::new(); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - e2.insert(C); - - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_disjoint_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - - assert!(e1.is_disjoint(&e2)); - } - - #[test] - fn test_overlapping_intersects() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - assert!(!e1.is_disjoint(&e2)); - } - - /////////////////////////////////////////////////////////////////////////// - // contains and contains_elem - - #[test] - fn test_superset() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(A); - e2.insert(B); - - let mut e3: EnumSet = EnumSet::new(); - e3.insert(C); - - assert!(e1.is_subset(&e2)); - assert!(e2.is_superset(&e1)); - assert!(!e3.is_superset(&e2)); - assert!(!e2.is_superset(&e3)) - } - - #[test] - fn test_contains() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - assert!(e1.contains(&A)); - assert!(!e1.contains(&B)); - assert!(!e1.contains(&C)); - - e1.insert(A); - e1.insert(B); - assert!(e1.contains(&A)); - assert!(e1.contains(&B)); - assert!(!e1.contains(&C)); - } - - /////////////////////////////////////////////////////////////////////////// - // iter - - #[test] - fn test_iterator() { - let mut e1: EnumSet = EnumSet::new(); - - let elems: ::vec::Vec = e1.iter().collect(); - assert!(elems.is_empty()); - - e1.insert(A); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A], elems); - - e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A,C], elems); - - e1.insert(C); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A,C], elems); - - e1.insert(B); - let elems: ::vec::Vec<_> = e1.iter().collect(); - assert_eq!(vec![A,B,C], elems); - } - - /////////////////////////////////////////////////////////////////////////// - // operators - - #[test] - fn test_operators() { - let mut e1: EnumSet = EnumSet::new(); - e1.insert(A); - e1.insert(C); - - let mut e2: EnumSet = EnumSet::new(); - e2.insert(B); - e2.insert(C); - - let e_union = e1 | e2; - let elems: ::vec::Vec<_> = e_union.iter().collect(); - assert_eq!(vec![A,B,C], elems); - - let e_intersection = e1 & e2; - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!(vec![C], elems); - - // Another way to express intersection - let e_intersection = e1 - (e1 - e2); - let elems: ::vec::Vec<_> = e_intersection.iter().collect(); - assert_eq!(vec![C], elems); - - let e_subtract = e1 - e2; - let elems: ::vec::Vec<_> = e_subtract.iter().collect(); - assert_eq!(vec![A], elems); - - // Bitwise XOR of two sets, aka symmetric difference - let e_symmetric_diff = e1 ^ e2; - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(vec![A,B], elems); - - // Another way to express symmetric difference - let e_symmetric_diff = (e1 - e2) | (e2 - e1); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(vec![A,B], elems); - - // Yet another way to express symmetric difference - let e_symmetric_diff = (e1 | e2) - (e1 & e2); - let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect(); - assert_eq!(vec![A,B], elems); - } - - #[test] - #[should_fail] - fn test_overflow() { - #[allow(dead_code)] - #[derive(Copy)] - #[repr(usize)] - enum Bar { - V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, - V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, - V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, - V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, - V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, - V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, - V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, - } - - impl CLike for Bar { - fn to_usize(&self) -> usize { - *self as usize - } - - fn from_usize(v: usize) -> Bar { - unsafe { mem::transmute(v) } - } - } - let mut set = EnumSet::new(); - set.insert(Bar::V64); - } -} diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 1b5018f4ad..46b1ad2138 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -16,7 +16,7 @@ //! This macro is implemented in the compiler to emit calls to this module in //! order to format arguments at runtime into strings and streams. //! -//! ## Usage +//! # Usage //! //! The `format!` macro is intended to be familiar to those coming from C's //! printf/fprintf functions or Python's `str.format` function. In its current @@ -41,7 +41,7 @@ //! will then parse the format string and determine if the list of arguments //! provided is suitable to pass to this format string. //! -//! ### Positional parameters +//! ## Positional parameters //! //! Each formatting argument is allowed to specify which value argument it's //! referencing, and if omitted it is assumed to be "the next argument". For @@ -54,7 +54,7 @@ //! iterator over the argument. Each time a "next argument" specifier is seen, //! the iterator advances. This leads to behavior like this: //! -//! ```rust +//! ``` //! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2" //! ``` //! @@ -68,7 +68,7 @@ //! compile-time error. You may refer to the same argument more than once in the //! format string, although it must always be referred to with the same type. //! -//! ### Named parameters +//! ## Named parameters //! //! Rust itself does not have a Python-like equivalent of named parameters to a //! function, but the `format!` macro is a syntax extension which allows it to @@ -91,7 +91,7 @@ //! arguments which have names. Like with positional parameters, it is illegal //! to provide named parameters that are unused by the format string. //! -//! ### Argument types +//! ## Argument types //! //! Each argument's type is dictated by the format string. It is a requirement //! that every argument is only ever referred to by one type. For example, this @@ -105,18 +105,25 @@ //! hexadecimal as well as an //! octal. //! -//! There are various parameters which do require a particular type, however. -//! Namely if the syntax `{:.*}` is used, then the number of characters to print -//! precedes the actual object being formatted, and the number of characters -//! must have the type `usize`. Although a `usize` can be printed with `{}`, it is -//! illegal to reference an argument as such. For example this is another +//! There are various parameters which do require a particular type, however. Namely, the `{:.*}` +//! syntax, which sets the number of numbers after the decimal in floating-point types: +//! +//! ``` +//! let formatted_number = format!("{:.*}", 2, 1.234567); +//! +//! assert_eq!("1.23", formatted_number) +//! ``` +//! +//! If this syntax is used, then the number of characters to print precedes the actual object being +//! formatted, and the number of characters must have the type `usize`. Although a `usize` can be +//! printed with `{}`, it is illegal to reference an argument as such. For example this is another //! invalid format string: //! //! ```text //! {:.*} {0} //! ``` //! -//! ### Formatting traits +//! ## Formatting traits //! //! When requesting that an argument be formatted with a particular type, you //! are actually requesting that an argument ascribes to a particular trait. @@ -142,7 +149,7 @@ //! When implementing a format trait for your own type, you will have to //! implement a method of the signature: //! -//! ```rust +//! ``` //! # use std::fmt; //! # struct Foo; // our custom type //! # impl fmt::Display for Foo { @@ -166,7 +173,8 @@ //! An example of implementing the formatting traits would look //! like: //! -//! ```rust +//! ``` +//! # #![feature(core, std_misc)] //! use std::fmt; //! use std::f64; //! use std::num::Float; @@ -198,7 +206,7 @@ //! // for details, and the function `pad` can be used to pad strings. //! let decimals = f.precision().unwrap_or(3); //! let string = f64::to_str_exact(magnitude, decimals); -//! f.pad_integral(true, "", string.as_slice()) +//! f.pad_integral(true, "", &string) //! } //! } //! @@ -211,7 +219,7 @@ //! } //! ``` //! -//! #### fmt::Display vs fmt::Debug +//! ### fmt::Display vs fmt::Debug //! //! These two formatting traits have distinct purposes: //! @@ -226,12 +234,12 @@ //! Some examples of the output from both traits: //! //! ``` -//! assert_eq!(format!("{} {:?}", 3i32, 4i32), "3 4"); +//! assert_eq!(format!("{} {:?}", 3, 4), "3 4"); //! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); //! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); //! ``` //! -//! ### Related macros +//! ## Related macros //! //! There are a number of related macros in the `format!` family. The ones that //! are currently implemented are: @@ -245,7 +253,7 @@ //! format_args! // described below. //! ``` //! -//! #### `write!` +//! ### `write!` //! //! This and `writeln` are two macros which are used to emit the format string //! to a specified stream. This is used to prevent intermediate allocations of @@ -253,24 +261,27 @@ //! function is actually invoking the `write` function defined in this module. //! Example usage is: //! -//! ```rust +//! ``` +//! # #![feature(old_io)] //! # #![allow(unused_must_use)] +//! use std::io::Write; //! let mut w = Vec::new(); //! write!(&mut w, "Hello {}!", "world"); //! ``` //! -//! #### `print!` +//! ### `print!` //! //! This and `println` emit their output to stdout. Similarly to the `write!` //! macro, the goal of these macros is to avoid intermediate allocations when //! printing output. Example usage is: //! -//! ```rust +//! ``` //! print!("Hello {}!", "world"); //! println!("I have a newline {}", "character at the end"); //! ``` //! -//! #### `format_args!` +//! ### `format_args!` +//! //! This is a curious macro which is used to safely pass around //! an opaque object describing the format string. This object //! does not require any heap allocations to create, and it only @@ -279,16 +290,17 @@ //! off, some example usage is: //! //! ``` +//! # #![feature(old_io)] //! use std::fmt; -//! use std::old_io; +//! use std::io::{self, Write}; //! //! fmt::format(format_args!("this returns {}", "String")); //! -//! let mut some_writer = old_io::stdout(); +//! let mut some_writer = io::stdout(); //! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); //! //! fn my_fmt_fn(args: fmt::Arguments) { -//! write!(&mut old_io::stdout(), "{}", args); +//! write!(&mut io::stdout(), "{}", args); //! } //! my_fmt_fn(format_args!("or a {} too", "function")); //! ``` @@ -303,7 +315,7 @@ //! it would internally pass around this structure until it has been determined //! where output should go to. //! -//! ## Syntax +//! # Syntax //! //! The syntax for the formatting language used is drawn from other languages, //! so it should not be too alien. Arguments are formatted with python-like @@ -326,14 +338,14 @@ //! parameter := integer '$' //! ``` //! -//! ## Formatting Parameters +//! # Formatting Parameters //! //! Each argument being formatted can be transformed by a number of formatting //! parameters (corresponding to `format_spec` in the syntax above). These //! parameters affect the string representation of what's being formatted. This //! syntax draws heavily from Python's, so it may seem a bit familiar. //! -//! ### Fill/Alignment +//! ## Fill/Alignment //! //! The fill character is provided normally in conjunction with the `width` //! parameter. This indicates that if the value being formatted is smaller than @@ -345,7 +357,7 @@ //! * `^` - the argument is center-aligned in `width` columns //! * `>` - the argument is right-aligned in `width` columns //! -//! ### Sign/#/0 +//! ## Sign/#/0 //! //! These can all be interpreted as flags for a particular formatter. //! @@ -356,19 +368,19 @@ //! should always be printed. //! * '-' - Currently not used //! * '#' - This flag is indicates that the "alternate" form of printing should -//! be used. By default, this only applies to the integer formatting -//! traits and performs like: -//! * `x` - precedes the argument with a "0x" -//! * `X` - precedes the argument with a "0x" -//! * `t` - precedes the argument with a "0b" -//! * `o` - precedes the argument with a "0o" +//! be used. For array slices, the alternate form omits the brackets. +//! For the integer formatting traits, the alternate forms are: +//! * `#x` - precedes the argument with a "0x" +//! * `#X` - precedes the argument with a "0x" +//! * `#t` - precedes the argument with a "0b" +//! * `#o` - precedes the argument with a "0o" //! * '0' - This is used to indicate for integer formats that the padding should //! both be done with a `0` character as well as be sign-aware. A format -//! like `{:08d}` would yield `00000001` for the integer `1`, while the +//! like `{:08}` would yield `00000001` for the integer `1`, while the //! same format would yield `-0000001` for the integer `-1`. Notice that //! the negative version has one fewer zero than the positive version. //! -//! ### Width +//! ## Width //! //! This is a parameter for the "minimum width" that the format should take up. //! If the value's string does not fill up this many characters, then the @@ -384,7 +396,7 @@ //! parameters by using the `2$` syntax indicating that the second argument is a //! `usize` specifying the width. //! -//! ### Precision +//! ## Precision //! //! For non-numeric types, this can be considered a "maximum width". If the //! resulting string is longer than this width, then it is truncated down to @@ -395,7 +407,7 @@ //! For floating-point types, this indicates how many digits after the decimal //! point should be printed. //! -//! ## Escaping +//! # Escaping //! //! The literal characters `{` and `}` may be included in a string by preceding //! them with the same character. For example, the `{` character is escaped with @@ -404,7 +416,7 @@ #![stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Formatter, Result, Write, rt}; -pub use core::fmt::{Show, String, Octal, Binary}; +pub use core::fmt::{Octal, Binary}; pub use core::fmt::{Display, Debug}; pub use core::fmt::{LowerHex, UpperHex, Pointer}; pub use core::fmt::{LowerExp, UpperExp}; @@ -420,9 +432,9 @@ use string; /// /// * args - a structure of arguments generated via the `format_args!` macro. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::fmt; /// /// let s = fmt::format(format_args!("Hello, {}!", "world")); @@ -434,15 +446,3 @@ pub fn format(args: Arguments) -> string::String { let _ = write!(&mut output, "{}", args); output } - -#[cfg(test)] -mod tests { - use prelude::*; - use fmt; - - #[test] - fn test_format() { - let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s.as_slice(), "Hello, world!"); - } -} diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 6569ab9c05..7658611d80 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -12,7 +12,8 @@ //! //! See [std::collections](../std/collections) for a detailed discussion of collections in Rust. - +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "collections"] #![unstable(feature = "collections")] #![staged_api] @@ -21,17 +22,25 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] +#![doc(test(no_crate_inject))] +#![allow(trivial_casts)] #![feature(alloc)] #![feature(box_syntax)] #![feature(box_patterns)] #![feature(core)] +#![feature(lang_items)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unsafe_destructor)] -#![feature(unsafe_no_drop_flag)] -#![cfg_attr(test, feature(rand, rustc_private, test))] +#![feature(unique)] +#![feature(unsafe_no_drop_flag, filling_drop)] +#![feature(step_by)] +#![feature(str_char)] +#![feature(slice_patterns)] +#![feature(debug_builders)] +#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))] #![cfg_attr(test, allow(deprecated))] // rand #![feature(no_std)] @@ -43,9 +52,8 @@ extern crate core; extern crate unicode; extern crate alloc; -#[cfg(test)] extern crate test; #[cfg(test)] #[macro_use] extern crate std; -#[cfg(test)] #[macro_use] extern crate log; +#[cfg(test)] extern crate test; pub use binary_heap::BinaryHeap; pub use bit_vec::BitVec; @@ -59,58 +67,30 @@ pub use string::String; pub use vec::Vec; pub use vec_map::VecMap; -#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")] -#[unstable(feature = "collections")] -pub use vec_deque as ring_buf; - -#[deprecated(since = "1.0.0", reason = "renamed to linked_list")] -#[unstable(feature = "collections")] -pub use linked_list as dlist; - -#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")] -#[unstable(feature = "collections")] -pub use bit_vec as bitv; - -#[deprecated(since = "1.0.0", reason = "renamed to bit_set")] -#[unstable(feature = "collections")] -pub use bit_set as bitv_set; - // Needed for the vec! macro pub use alloc::boxed; #[macro_use] mod macros; -#[cfg(test)] #[macro_use] mod bench; - pub mod binary_heap; mod bit; mod btree; -pub mod linked_list; +pub mod borrow; pub mod enum_set; pub mod fmt; -pub mod vec_deque; +pub mod linked_list; pub mod slice; pub mod str; pub mod string; pub mod vec; +pub mod vec_deque; pub mod vec_map; -#[cfg(stage0)] -#[path = "borrow_stage0.rs"] -pub mod borrow; - -#[cfg(not(stage0))] -pub mod borrow; - #[unstable(feature = "collections", reason = "RFC 509")] pub mod bit_vec { pub use bit::{BitVec, Iter}; - - #[deprecated(since = "1.0.0", reason = "renamed to BitVec")] - #[unstable(feature = "collections")] - pub use bit::BitVec as Bitv; } #[unstable(feature = "collections", @@ -118,10 +98,6 @@ pub mod bit_vec { pub mod bit_set { pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference}; pub use bit::SetIter as Iter; - - #[deprecated(since = "1.0.0", reason = "renamed to BitSet")] - #[unstable(feature = "collections")] - pub use bit::BitSet as BitvSet; } #[stable(feature = "rust1", since = "1.0.0")] @@ -144,41 +120,8 @@ mod std { pub use core::ops; // RangeFull } -#[cfg(test)] -mod prelude { - // from core. - pub use core::clone::Clone; - pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord}; - pub use core::cmp::Ordering::{Less, Equal, Greater}; - pub use core::iter::range; - pub use core::iter::{FromIterator, Extend, IteratorExt}; - pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator}; - pub use core::iter::{ExactSizeIterator}; - pub use core::marker::{Copy, Send, Sized, Sync}; - pub use core::mem::drop; - pub use core::ops::{Drop, Fn, FnMut, FnOnce}; - pub use core::option::Option; - pub use core::option::Option::{Some, None}; - pub use core::ptr::PtrExt; - pub use core::result::Result; - pub use core::result::Result::{Ok, Err}; - - // in core and collections (may differ). - pub use slice::{AsSlice, SliceExt}; - pub use str::{Str, StrExt}; - - // from other crates. - pub use alloc::boxed::Box; - pub use unicode::char::CharExt; - - // from collections. - pub use borrow::IntoCow; - pub use slice::SliceConcatExt; - pub use string::{String, ToString}; - pub use vec::Vec; -} - /// An endpoint of a range of keys. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum Bound { /// An inclusive bound. Included(T), diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index c142819a51..dbdb795657 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -28,16 +28,10 @@ use core::cmp::Ordering; use core::default::Default; use core::fmt; use core::hash::{Hasher, Hash}; -#[cfg(stage0)] -use core::hash::Writer; use core::iter::{self, FromIterator, IntoIterator}; use core::mem; use core::ptr; -#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")] -#[unstable(feature = "collections")] -pub use LinkedList as DList; - /// A doubly-linked list. #[stable(feature = "rust1", since = "1.0.0")] pub struct LinkedList { @@ -53,8 +47,8 @@ struct Rawlink { } impl Copy for Rawlink {} -unsafe impl Send for Rawlink {} -unsafe impl Sync for Rawlink {} +unsafe impl Send for Rawlink {} +unsafe impl Sync for Rawlink {} struct Node { next: Link, @@ -237,6 +231,7 @@ impl LinkedList { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut a = LinkedList::new(); @@ -253,6 +248,7 @@ impl LinkedList { /// } /// println!("{}", b.len()); // prints 0 /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn append(&mut self, other: &mut LinkedList) { match self.list_tail.resolve() { None => { @@ -485,6 +481,7 @@ impl LinkedList { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut dl = LinkedList::new(); @@ -532,6 +529,7 @@ impl LinkedList { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut d = LinkedList::new(); @@ -550,6 +548,7 @@ impl LinkedList { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut d = LinkedList::new(); @@ -575,6 +574,7 @@ impl LinkedList { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut d = LinkedList::new(); @@ -767,6 +767,7 @@ impl<'a, A> IterMut<'a, A> { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut list: LinkedList<_> = vec![1, 3, 4].into_iter().collect(); @@ -779,7 +780,7 @@ impl<'a, A> IterMut<'a, A> { /// } /// { /// let vec: Vec<_> = list.into_iter().collect(); - /// assert_eq!(vec, vec![1, 2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); /// } /// ``` #[inline] @@ -794,6 +795,7 @@ impl<'a, A> IterMut<'a, A> { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::LinkedList; /// /// let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect(); @@ -834,10 +836,12 @@ impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { self.list.pop_back() } } +impl ExactSizeIterator for IntoIter {} + #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for LinkedList { fn from_iter>(iter: T) -> LinkedList { - let mut ret = DList::new(); + let mut ret = LinkedList::new(); ret.extend(iter); ret } @@ -920,29 +924,11 @@ impl Clone for LinkedList { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for LinkedList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "LinkedList [")); - - for (i, e) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *e)); - } - - write!(f, "]") + self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(stage0)] -impl> Hash for LinkedList { - fn hash(&self, state: &mut S) { - self.len().hash(state); - for elt in self { - elt.hash(state); - } - } -} -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl Hash for LinkedList { fn hash(&self, state: &mut H) { self.len().hash(state); @@ -953,16 +939,21 @@ impl Hash for LinkedList { } #[cfg(test)] -mod tests { - use prelude::*; +mod test { + use std::clone::Clone; + use std::iter::Iterator; + use std::option::Option::{Some, None, self}; use std::rand; - use std::hash::{self, SipHasher}; use std::thread; - use test::Bencher; - use test; + use std::vec::Vec; use super::{LinkedList, Node}; + #[cfg(test)] + fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() + } + pub fn check_links(list: &LinkedList) { let mut len = 0; let mut last_ptr: Option<&Node> = None; @@ -995,56 +986,6 @@ mod tests { assert_eq!(len, list.length); } - #[test] - fn test_basic() { - let mut m = LinkedList::new(); - assert_eq!(m.pop_front(), None); - assert_eq!(m.pop_back(), None); - assert_eq!(m.pop_front(), None); - m.push_front(box 1); - assert_eq!(m.pop_front(), Some(box 1)); - m.push_back(box 2); - m.push_back(box 3); - assert_eq!(m.len(), 2); - assert_eq!(m.pop_front(), Some(box 2)); - assert_eq!(m.pop_front(), Some(box 3)); - assert_eq!(m.len(), 0); - assert_eq!(m.pop_front(), None); - m.push_back(box 1); - m.push_back(box 3); - m.push_back(box 5); - m.push_back(box 7); - assert_eq!(m.pop_front(), Some(box 1)); - - let mut n = LinkedList::new(); - n.push_front(2); - n.push_front(3); - { - assert_eq!(n.front().unwrap(), &3); - let x = n.front_mut().unwrap(); - assert_eq!(*x, 3); - *x = 0; - } - { - assert_eq!(n.back().unwrap(), &2); - let y = n.back_mut().unwrap(); - assert_eq!(*y, 2); - *y = 1; - } - assert_eq!(n.pop_front(), Some(0)); - assert_eq!(n.pop_front(), Some(1)); - } - - #[cfg(test)] - fn generate_test() -> LinkedList { - list_from(&[0,1,2,3,4,5,6]) - } - - #[cfg(test)] - fn list_from(v: &[T]) -> LinkedList { - v.iter().cloned().collect() - } - #[test] fn test_append() { // Empty to empty @@ -1102,166 +1043,6 @@ mod tests { check_links(&n); } - #[test] - fn test_split_off() { - // singleton - { - let mut m = LinkedList::new(); - m.push_back(1); - - let p = m.split_off(0); - assert_eq!(m.len(), 0); - assert_eq!(p.len(), 1); - assert_eq!(p.back(), Some(&1)); - assert_eq!(p.front(), Some(&1)); - } - - // not singleton, forwards - { - let u = vec![1,2,3,4,5]; - let mut m = list_from(&u); - let mut n = m.split_off(2); - assert_eq!(m.len(), 2); - assert_eq!(n.len(), 3); - for elt in 1..3 { - assert_eq!(m.pop_front(), Some(elt)); - } - for elt in 3..6 { - assert_eq!(n.pop_front(), Some(elt)); - } - } - // not singleton, backwards - { - let u = vec![1,2,3,4,5]; - let mut m = list_from(&u); - let mut n = m.split_off(4); - assert_eq!(m.len(), 4); - assert_eq!(n.len(), 1); - for elt in 1..5 { - assert_eq!(m.pop_front(), Some(elt)); - } - for elt in 5..6 { - assert_eq!(n.pop_front(), Some(elt)); - } - } - - // no-op on the last index - { - let mut m = LinkedList::new(); - m.push_back(1); - - let p = m.split_off(1); - assert_eq!(m.len(), 1); - assert_eq!(p.len(), 0); - assert_eq!(m.back(), Some(&1)); - assert_eq!(m.front(), Some(&1)); - } - - } - - #[test] - fn test_iterator() { - let m = generate_test(); - for (i, elt) in m.iter().enumerate() { - assert_eq!(i as i32, *elt); - } - let mut n = LinkedList::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_iterator_clone() { - let mut n = LinkedList::new(); - n.push_back(2); - n.push_back(3); - n.push_back(4); - let mut it = n.iter(); - it.next(); - let mut jt = it.clone(); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next_back(), jt.next_back()); - assert_eq!(it.next(), jt.next()); - } - - #[test] - fn test_iterator_double_end() { - let mut n = LinkedList::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - n.push_front(5); - n.push_front(6); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.next().unwrap(), &6); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next_back().unwrap(), &4); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next_back().unwrap(), &5); - assert_eq!(it.next_back(), None); - assert_eq!(it.next(), None); - } - - #[test] - fn test_rev_iter() { - let m = generate_test(); - for (i, elt) in m.iter().rev().enumerate() { - assert_eq!((6 - i) as i32, *elt); - } - let mut n = LinkedList::new(); - assert_eq!(n.iter().rev().next(), None); - n.push_front(4); - let mut it = n.iter().rev(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_mut_iter() { - let mut m = generate_test(); - let mut len = m.len(); - for (i, elt) in m.iter_mut().enumerate() { - assert_eq!(i as i32, *elt); - len -= 1; - } - assert_eq!(len, 0); - let mut n = LinkedList::new(); - assert!(n.iter_mut().next().is_none()); - n.push_front(4); - n.push_back(5); - let mut it = n.iter_mut(); - assert_eq!(it.size_hint(), (2, Some(2))); - assert!(it.next().is_some()); - assert!(it.next().is_some()); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_mut_double_end() { - let mut n = LinkedList::new(); - assert!(n.iter_mut().next_back().is_none()); - n.push_front(4); - n.push_front(5); - n.push_front(6); - let mut it = n.iter_mut(); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(*it.next().unwrap(), 6); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(*it.next_back().unwrap(), 4); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(*it.next_back().unwrap(), 5); - assert!(it.next_back().is_none()); - assert!(it.next().is_none()); - } - #[test] fn test_insert_prev() { let mut m = list_from(&[0,2,4,6,8]); @@ -1286,21 +1067,7 @@ mod tests { } check_links(&m); assert_eq!(m.len(), 3 + len * 2); - assert_eq!(m.into_iter().collect::>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]); - } - - #[test] - fn test_mut_rev_iter() { - let mut m = generate_test(); - for (i, elt) in m.iter_mut().rev().enumerate() { - assert_eq!((6 - i) as i32, *elt); - } - let mut n = LinkedList::new(); - assert!(n.iter_mut().rev().next().is_none()); - n.push_front(4); - let mut it = n.iter_mut().rev(); - assert!(it.next().is_some()); - assert!(it.next().is_none()); + assert_eq!(m.into_iter().collect::>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]); } #[test] @@ -1309,85 +1076,10 @@ mod tests { thread::spawn(move || { check_links(&n); let a: &[_] = &[&1,&2,&3]; - assert_eq!(a, n.iter().collect::>()); + assert_eq!(a, &n.iter().collect::>()[..]); }).join().ok().unwrap(); } - #[test] - fn test_eq() { - let mut n = list_from(&[]); - let mut m = list_from(&[]); - assert!(n == m); - n.push_front(1); - assert!(n != m); - m.push_back(1); - assert!(n == m); - - let n = list_from(&[2,3,4]); - let m = list_from(&[1,2,3]); - assert!(n != m); - } - - #[test] - fn test_hash() { - let mut x = LinkedList::new(); - let mut y = LinkedList::new(); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - - x.push_back(1); - x.push_back(2); - x.push_back(3); - - y.push_front(3); - y.push_front(2); - y.push_front(1); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_ord() { - let n = list_from(&[]); - let m = list_from(&[1,2,3]); - assert!(n < m); - assert!(m > n); - assert!(n <= n); - assert!(n >= n); - } - - #[test] - fn test_ord_nan() { - let nan = 0.0f64/0.0; - let n = list_from(&[nan]); - let m = list_from(&[nan]); - assert!(!(n < m)); - assert!(!(n > m)); - assert!(!(n <= m)); - assert!(!(n >= m)); - - let n = list_from(&[nan]); - let one = list_from(&[1.0f64]); - assert!(!(n < one)); - assert!(!(n > one)); - assert!(!(n <= one)); - assert!(!(n >= one)); - - let u = list_from(&[1.0f64,2.0,nan]); - let v = list_from(&[1.0f64,2.0,3.0]); - assert!(!(u < v)); - assert!(!(u > v)); - assert!(!(u <= v)); - assert!(!(u >= v)); - - let s = list_from(&[1.0f64,2.0,4.0,2.0]); - let t = list_from(&[1.0f64,2.0,3.0,2.0]); - assert!(!(s < t)); - assert!(s > one); - assert!(!(s <= one)); - assert!(s >= one); - } - #[test] fn test_fuzz() { for _ in 0..25 { @@ -1397,15 +1089,6 @@ mod tests { } } - #[test] - fn test_show() { - let list: LinkedList<_> = (0..10).collect(); - assert_eq!(format!("{:?}", list), "LinkedList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); - assert_eq!(format!("{:?}", list), "LinkedList [\"just\", \"one\", \"test\", \"more\"]"); - } - #[cfg(test)] fn fuzz_test(sz: i32) { let mut m: LinkedList<_> = LinkedList::new(); @@ -1444,79 +1127,4 @@ mod tests { } assert_eq!(i, v.len()); } - - #[bench] - fn bench_collect_into(b: &mut test::Bencher) { - let v = &[0; 64]; - b.iter(|| { - let _: LinkedList<_> = v.iter().cloned().collect(); - }) - } - - #[bench] - fn bench_push_front(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - }) - } - - #[bench] - fn bench_push_back(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - }) - } - - #[bench] - fn bench_push_back_pop_back(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - m.pop_back(); - }) - } - - #[bench] - fn bench_push_front_pop_front(b: &mut test::Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - m.pop_front(); - }) - } - - #[bench] - fn bench_iter(b: &mut test::Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().count() == 128); - }) - } - #[bench] - fn bench_iter_mut(b: &mut test::Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().count() == 128); - }) - } - #[bench] - fn bench_iter_rev(b: &mut test::Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().rev().count() == 128); - }) - } - #[bench] - fn bench_iter_mut_rev(b: &mut test::Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().rev().count() == 128); - }) - } } diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index ebcfb8d1cf..5f614f3649 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -26,12 +26,13 @@ /// /// ``` /// let v = vec![1; 3]; -/// assert_eq!(v, vec![1, 1, 1]); +/// assert_eq!(v, [1, 1, 1]); /// ``` /// /// Note that unlike array expressions this syntax supports all elements /// which implement `Clone` and the number of elements doesn't have to be /// a constant. +#[cfg(not(test))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! vec { @@ -39,8 +40,22 @@ macro_rules! vec { $crate::vec::from_elem($elem, $n) ); ($($x:expr),*) => ( - <[_] as $crate::slice::SliceExt>::into_vec( - $crate::boxed::Box::new([$($x),*])) + <[_]>::into_vec($crate::boxed::Box::new([$($x),*])) + ); + ($($x:expr,)*) => (vec![$($x),*]) +} + +// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is +// required for this macro definition, is not available. Instead use the +// `slice::into_vec` function which is only available with cfg(test) +// NB see the slice::hack module in slice.rs for more information +#[cfg(test)] +macro_rules! vec { + ($elem:expr; $n:expr) => ( + $crate::vec::from_elem($elem, $n) + ); + ($($x:expr),*) => ( + $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) ); ($($x:expr,)*) => (vec![$($x),*]) } @@ -48,7 +63,7 @@ macro_rules! vec { /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// -/// # Example +/// # Examples /// /// ``` /// format!("test"); diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 776b8b3af1..ff923fb190 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -13,24 +13,23 @@ //! The `slice` module contains useful code to help work with slice values. //! Slices are a view into a block of memory represented as a pointer and a length. //! -//! ```rust +//! ``` //! // slicing a Vec -//! let vec = vec!(1, 2, 3); -//! let int_slice = vec.as_slice(); +//! let vec = vec![1, 2, 3]; +//! let int_slice = &vec[..]; //! // coercing an array to a slice //! let str_slice: &[&str] = &["one", "two", "three"]; //! ``` //! //! Slices are either mutable or shared. The shared slice type is `&[T]`, -//! while the mutable slice type is `&mut[T]`. For example, you can mutate the -//! block of memory that a mutable slice points to: +//! while the mutable slice type is `&mut [T]`, where `T` represents the element +//! type. For example, you can mutate the block of memory that a mutable slice +//! points to: //! -//! ```rust -//! let x: &mut[i32] = &mut [1, 2, 3]; +//! ``` +//! let x = &mut [1, 2, 3]; //! x[1] = 7; -//! assert_eq!(x[0], 1); -//! assert_eq!(x[1], 7); -//! assert_eq!(x[2], 3); +//! assert_eq!(x, &[1, 7, 3]); //! ``` //! //! Here are some of the things this module contains: @@ -40,65 +39,58 @@ //! There are several structs that are useful for slices, such as `Iter`, which //! represents iteration over a slice. //! -//! ## Traits -//! -//! A number of traits add methods that allow you to accomplish tasks -//! with slices, the most important being `SliceExt`. Other traits -//! apply only to slices of elements satisfying certain bounds (like -//! `Ord`). -//! -//! An example is the `slice` method which enables slicing syntax `[a..b]` that -//! returns an immutable "view" into a `Vec` or another slice from the index -//! interval `[a, b)`: -//! -//! ```rust -//! fn main() { -//! let numbers = [0, 1, 2]; -//! let last_numbers = &numbers[1..3]; -//! // last_numbers is now &[1, 2] -//! } -//! ``` -//! -//! ## Implementations of other traits +//! ## Trait Implementations //! //! There are several implementations of common traits for slices. Some examples //! include: //! //! * `Clone` -//! * `Eq`, `Ord` - for immutable slices whose element type are `Eq` or `Ord`. +//! * `Eq`, `Ord` - for slices whose element type are `Eq` or `Ord`. //! * `Hash` - for slices whose element type is `Hash` //! //! ## Iteration //! -//! The method `iter()` returns an iteration value for a slice. The iterator -//! yields references to the slice's elements, so if the element -//! type of the slice is `isize`, the element type of the iterator is `&isize`. +//! The slices implement `IntoIterator`. The iterator yields references to the +//! slice elements. //! -//! ```rust -//! let numbers = [0, 1, 2]; -//! for &x in numbers.iter() { -//! println!("{} is a number!", x); +//! ``` +//! let numbers = &[0, 1, 2]; +//! for n in numbers { +//! println!("{} is a number!", n); //! } //! ``` //! -//! * `.iter_mut()` returns an iterator that allows modifying each value. -//! * Further iterators exist that split, chunk or permute the slice. - +//! The mutable slice yields mutable references to the elements: +//! +//! ``` +//! let mut scores = [7, 8, 9]; +//! for score in &mut scores[..] { +//! *score += 1; +//! } +//! ``` +//! +//! This iterator yields mutable references to the slice's elements, so while the element +//! type of the slice is `i32`, the element type of the iterator is `&mut i32`. +//! +//! * `.iter()` and `.iter_mut()` are the explicit methods to return the default +//! iterators. +//! * Further methods that return iterators are `.split()`, `.splitn()`, +//! `.chunks()`, `.windows()` and more. #![doc(primitive = "slice")] #![stable(feature = "rust1", since = "1.0.0")] use alloc::boxed::Box; +use core::convert::AsRef; 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_step, MultiplicativeIterator}; +use core::iter::Iterator; +use core::iter::MultiplicativeIterator; use core::marker::Sized; use core::mem::size_of; use core::mem; use core::ops::FnMut; use core::option::Option::{self, Some, None}; -use core::ptr::PtrExt; use core::ptr; use core::result::Result; use core::slice as core_slice; @@ -113,18 +105,124 @@ 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_parts, from_raw_parts_mut}; -pub use core::slice::{from_raw_buf, from_raw_mut_buf}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// +// HACK(japaric) needed for the implementation of `vec!` macro during testing +// NB see the hack module in this file for more details +#[cfg(test)] +pub use self::hack::into_vec; + +// HACK(japaric) needed for the implementation of `Vec::clone` during testing +// NB see the hack module in this file for more details +#[cfg(test)] +pub use self::hack::to_vec; + +// HACK(japaric): With cfg(test) `impl [T]` is not available, these three +// functions are actually methods that are in `impl [T]` but not in +// `core::slice::SliceExt` - we need to supply these functions for the +// `test_permutations` test +mod hack { + use alloc::boxed::Box; + use core::clone::Clone; + #[cfg(test)] + use core::iter::Iterator; + use core::mem; + #[cfg(test)] + use core::option::Option::{Some, None}; + + #[cfg(test)] + use string::ToString; + use vec::Vec; + + use super::{ElementSwaps, Permutations}; + + pub fn into_vec(mut b: Box<[T]>) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len()); + mem::forget(b); + xs + } + } + + pub fn permutations(s: &[T]) -> Permutations where T: Clone { + Permutations{ + swaps: ElementSwaps::new(s.len()), + v: to_vec(s), + } + } + + #[inline] + pub fn to_vec(s: &[T]) -> Vec where T: Clone { + let mut vector = Vec::with_capacity(s.len()); + vector.push_all(s); + vector + } + + // NB we can remove this hack if we move this test to libcollectionstest - + // but that can't be done right now because the test needs access to the + // private fields of Permutations + #[test] + fn test_permutations() { + { + let v: [i32; 0] = []; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = ["Hello".to_string()]; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 1); + assert_eq!(max_opt.unwrap(), 1); + assert_eq!(it.next(), Some(to_vec(&v))); + assert_eq!(it.next(), None); + } + { + let v = [1, 2, 3]; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3*2); + assert_eq!(max_opt.unwrap(), 3*2); + assert_eq!(it.next().unwrap(), [1,2,3]); + assert_eq!(it.next().unwrap(), [1,3,2]); + assert_eq!(it.next().unwrap(), [3,1,2]); + let (min_size, max_opt) = it.size_hint(); + assert_eq!(min_size, 3); + assert_eq!(max_opt.unwrap(), 3); + assert_eq!(it.next().unwrap(), [3,2,1]); + assert_eq!(it.next().unwrap(), [2,3,1]); + assert_eq!(it.next().unwrap(), [2,1,3]); + assert_eq!(it.next(), None); + } + { + // check that we have N! permutations + let v = ['A', 'B', 'C', 'D', 'E', 'F']; + let mut amt = 0; + let mut it = permutations(&v); + let (min_size, max_opt) = it.size_hint(); + for _perm in it.by_ref() { + amt += 1; + } + assert_eq!(amt, it.swaps.swaps_made); + assert_eq!(amt, min_size); + assert_eq!(amt, 2 * 3 * 4 * 5 * 6); + assert_eq!(amt, max_opt.unwrap()); + } + } +} + /// Allocating extension methods for slices. +#[lang = "slice"] +#[cfg(not(test))] #[stable(feature = "rust1", since = "1.0.0")] -pub trait SliceExt { - #[stable(feature = "rust1", since = "1.0.0")] - type Item; - +impl [T] { /// Sorts the slice, in place, using `compare` to compare /// elements. /// @@ -143,7 +241,10 @@ pub trait SliceExt { /// assert!(v == [5, 4, 3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn sort_by(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering; + #[inline] + pub fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { + merge_sort(self, compare) + } /// Consumes `src` and moves as many elements as it can into `self` /// from the range [start,end). @@ -160,6 +261,7 @@ pub trait SliceExt { /// # Examples /// /// ```rust + /// # #![feature(collections)] /// let mut a = [1, 2, 3, 4, 5]; /// let b = vec![6, 7, 8]; /// let num_moved = a.move_from(b, 0, 3); @@ -168,25 +270,13 @@ pub trait SliceExt { /// ``` #[unstable(feature = "collections", reason = "uncertain about this API approach")] - fn move_from(&mut self, src: Vec, start: usize, end: usize) -> usize; - - /// Deprecated: use `&s[start .. end]` notation instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")] - fn slice(&self, start: usize, end: usize) -> &[Self::Item]; - - /// Deprecated: use `&s[start..]` notation instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &s[start..] instead")] - fn slice_from(&self, start: usize) -> &[Self::Item]; - - /// Deprecated: use `&s[..end]` notation instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")] - fn slice_to(&self, end: usize) -> &[Self::Item]; + #[inline] + pub fn move_from(&mut self, mut src: Vec, start: usize, end: usize) -> usize { + for (a, b) in self.iter_mut().zip(src[start .. end].iter_mut()) { + mem::swap(a, b); + } + cmp::min(self.len(), end-start) + } /// Divides one slice into two at an index. /// @@ -205,11 +295,17 @@ pub trait SliceExt { /// assert_eq!([30, 20, 50], v2); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn split_at(&self, mid: usize) -> (&[Self::Item], &[Self::Item]); + #[inline] + pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { + core_slice::SliceExt::split_at(self, mid) + } /// Returns an iterator over the slice. #[stable(feature = "rust1", since = "1.0.0")] - fn iter(&self) -> Iter; + #[inline] + pub fn iter(&self) -> Iter { + core_slice::SliceExt::iter(self) + } /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. @@ -226,13 +322,18 @@ pub trait SliceExt { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn split(&self, pred: F) -> Split - where F: FnMut(&Self::Item) -> bool; + #[inline] + pub fn split(&self, pred: F) -> Split where F: FnMut(&T) -> bool { + core_slice::SliceExt::split(self, pred) + } /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to splitting at most `n` times. The matched element is + /// `pred`, limited to returning at most `n` items. The matched element is /// not contained in the subslices. /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// /// # Examples /// /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`, @@ -240,19 +341,24 @@ pub trait SliceExt { /// /// ``` /// let v = [10, 40, 30, 20, 60, 50]; - /// for group in v.splitn(1, |num| *num % 3 == 0) { + /// for group in v.splitn(2, |num| *num % 3 == 0) { /// println!("{:?}", group); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn splitn(&self, n: usize, pred: F) -> SplitN - where F: FnMut(&Self::Item) -> bool; + #[inline] + pub fn splitn(&self, n: usize, pred: F) -> SplitN where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn(self, n, pred) + } /// Returns an iterator over subslices separated by elements that match - /// `pred` limited to splitting at most `n` times. This starts at the end of + /// `pred` limited to returning at most `n` items. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. /// + /// The last element returned, if any, will contain the remainder of the + /// slice. + /// /// # Examples /// /// Print the slice split once, starting from the end, by numbers divisible @@ -260,13 +366,15 @@ pub trait SliceExt { /// /// ``` /// let v = [10, 40, 30, 20, 60, 50]; - /// for group in v.rsplitn(1, |num| *num % 3 == 0) { + /// for group in v.rsplitn(2, |num| *num % 3 == 0) { /// println!("{:?}", group); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn rsplitn(&self, n: usize, pred: F) -> RSplitN - where F: FnMut(&Self::Item) -> bool; + #[inline] + pub fn rsplitn(&self, n: usize, pred: F) -> RSplitN where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn(self, n, pred) + } /// Returns an iterator over all contiguous windows of length /// `size`. The windows overlap. If the slice is shorter than @@ -288,7 +396,10 @@ pub trait SliceExt { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn windows(&self, size: usize) -> Windows; + #[inline] + pub fn windows(&self, size: usize) -> Windows { + core_slice::SliceExt::windows(self, size) + } /// Returns an iterator over `size` elements of the slice at a /// time. The chunks do not overlap. If `size` does not divide the @@ -311,7 +422,10 @@ pub trait SliceExt { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn chunks(&self, size: usize) -> Chunks; + #[inline] + pub fn chunks(&self, size: usize) -> Chunks { + core_slice::SliceExt::chunks(self, size) + } /// Returns the element of a slice at the given index, or `None` if the /// index is out of bounds. @@ -324,7 +438,10 @@ pub trait SliceExt { /// assert_eq!(None, v.get(3)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn get(&self, index: usize) -> Option<&Self::Item>; + #[inline] + pub fn get(&self, index: usize) -> Option<&T> { + core_slice::SliceExt::get(self, index) + } /// Returns the first element of a slice, or `None` if it is empty. /// @@ -338,15 +455,24 @@ pub trait SliceExt { /// assert_eq!(None, w.first()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn first(&self) -> Option<&Self::Item>; + #[inline] + pub fn first(&self) -> Option<&T> { + core_slice::SliceExt::first(self) + } /// Returns all but the first element of a slice. #[unstable(feature = "collections", reason = "likely to be renamed")] - fn tail(&self) -> &[Self::Item]; + #[inline] + pub fn tail(&self) -> &[T] { + core_slice::SliceExt::tail(self) + } /// Returns all but the last element of a slice. #[unstable(feature = "collections", reason = "likely to be renamed")] - fn init(&self) -> &[Self::Item]; + #[inline] + pub fn init(&self) -> &[T] { + core_slice::SliceExt::init(self) + } /// Returns the last element of a slice, or `None` if it is empty. /// @@ -360,12 +486,18 @@ pub trait SliceExt { /// assert_eq!(None, w.last()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn last(&self) -> Option<&Self::Item>; + #[inline] + pub fn last(&self) -> Option<&T> { + core_slice::SliceExt::last(self) + } /// Returns a pointer to the element at the given index, without doing /// bounds checking. #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn get_unchecked(&self, index: usize) -> &Self::Item; + #[inline] + pub unsafe fn get_unchecked(&self, index: usize) -> &T { + core_slice::SliceExt::get_unchecked(self, index) + } /// Returns an unsafe pointer to the slice's buffer /// @@ -375,7 +507,10 @@ pub trait SliceExt { /// Modifying the slice may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. #[stable(feature = "rust1", since = "1.0.0")] - fn as_ptr(&self) -> *const Self::Item; + #[inline] + pub fn as_ptr(&self) -> *const T { + core_slice::SliceExt::as_ptr(self) + } /// Binary search a sorted slice with a comparator function. /// @@ -396,8 +531,8 @@ pub trait SliceExt { /// found; the fourth could match any position in `[1,4]`. /// /// ```rust + /// # #![feature(core)] /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); /// /// let seek = 13; /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9)); @@ -410,8 +545,10 @@ pub trait SliceExt { /// assert!(match r { Ok(1...4) => true, _ => false, }); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn binary_search_by(&self, f: F) -> Result where - F: FnMut(&Self::Item) -> Ordering; + #[inline] + pub fn binary_search_by(&self, f: F) -> Result where F: FnMut(&T) -> Ordering { + core_slice::SliceExt::binary_search_by(self, f) + } /// Return the number of elements in the slice /// @@ -422,7 +559,10 @@ pub trait SliceExt { /// assert_eq!(a.len(), 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn len(&self) -> usize; + #[inline] + pub fn len(&self) -> usize { + core_slice::SliceExt::len(self) + } /// Returns true if the slice has a length of 0 /// @@ -432,79 +572,91 @@ pub trait SliceExt { /// let a = [1, 2, 3]; /// assert!(!a.is_empty()); /// ``` - #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn is_empty(&self) -> bool { self.len() == 0 } + #[inline] + pub fn is_empty(&self) -> bool { + core_slice::SliceExt::is_empty(self) + } + /// Returns a mutable reference to the element at the given index, /// or `None` if the index is out of bounds #[stable(feature = "rust1", since = "1.0.0")] - fn get_mut(&mut self, index: usize) -> Option<&mut Self::Item>; - - /// Work with `self` as a mut slice. - /// Primarily intended for getting a &mut [T] from a [T; N]. - #[stable(feature = "rust1", since = "1.0.0")] - fn as_mut_slice(&mut self) -> &mut [Self::Item]; - - /// Deprecated: use `&mut s[start .. end]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")] - fn slice_mut(&mut self, start: usize, end: usize) -> &mut [Self::Item]; - - /// Deprecated: use `&mut s[start ..]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")] - fn slice_from_mut(&mut self, start: usize) -> &mut [Self::Item]; - - /// Deprecated: use `&mut s[.. end]` instead. - #[unstable(feature = "collections", - reason = "will be replaced by slice syntax")] - #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")] - fn slice_to_mut(&mut self, end: usize) -> &mut [Self::Item]; + #[inline] + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + core_slice::SliceExt::get_mut(self, index) + } /// Returns an iterator that allows modifying each value #[stable(feature = "rust1", since = "1.0.0")] - fn iter_mut(&mut self) -> IterMut; + #[inline] + pub fn iter_mut(&mut self) -> IterMut { + core_slice::SliceExt::iter_mut(self) + } /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty #[stable(feature = "rust1", since = "1.0.0")] - fn first_mut(&mut self) -> Option<&mut Self::Item>; + #[inline] + pub fn first_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::first_mut(self) + } /// Returns all but the first element of a mutable slice #[unstable(feature = "collections", reason = "likely to be renamed or removed")] - fn tail_mut(&mut self) -> &mut [Self::Item]; + #[inline] + pub fn tail_mut(&mut self) -> &mut [T] { + core_slice::SliceExt::tail_mut(self) + } /// Returns all but the last element of a mutable slice #[unstable(feature = "collections", reason = "likely to be renamed or removed")] - fn init_mut(&mut self) -> &mut [Self::Item]; + #[inline] + pub fn init_mut(&mut self) -> &mut [T] { + core_slice::SliceExt::init_mut(self) + } /// Returns a mutable pointer to the last item in the slice. #[stable(feature = "rust1", since = "1.0.0")] - fn last_mut(&mut self) -> Option<&mut Self::Item>; + #[inline] + pub fn last_mut(&mut self) -> Option<&mut T> { + core_slice::SliceExt::last_mut(self) + } /// Returns an iterator over mutable subslices separated by elements that /// match `pred`. The matched element is not contained in the subslices. #[stable(feature = "rust1", since = "1.0.0")] - fn split_mut(&mut self, pred: F) -> SplitMut - where F: FnMut(&Self::Item) -> bool; + #[inline] + pub fn split_mut(&mut self, pred: F) -> SplitMut where F: FnMut(&T) -> bool { + core_slice::SliceExt::split_mut(self, pred) + } /// Returns an iterator over subslices separated by elements that match - /// `pred`, limited to splitting at most `n` times. The matched element is + /// `pred`, limited to returning at most `n` items. The matched element is /// not contained in the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. #[stable(feature = "rust1", since = "1.0.0")] - fn splitn_mut(&mut self, n: usize, pred: F) -> SplitNMut - where F: FnMut(&Self::Item) -> bool; + #[inline] + pub fn splitn_mut(&mut self, n: usize, pred: F) -> SplitNMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::splitn_mut(self, n, pred) + } /// Returns an iterator over subslices separated by elements that match - /// `pred` limited to splitting at most `n` times. This starts at the end of + /// `pred` limited to returning at most `n` items. This starts at the end of /// the slice and works backwards. The matched element is not contained in /// the subslices. + /// + /// The last element returned, if any, will contain the remainder of the + /// slice. #[stable(feature = "rust1", since = "1.0.0")] - fn rsplitn_mut(&mut self, n: usize, pred: F) -> RSplitNMut - where F: FnMut(&Self::Item) -> bool; + #[inline] + pub fn rsplitn_mut(&mut self, n: usize, pred: F) -> RSplitNMut + where F: FnMut(&T) -> bool { + core_slice::SliceExt::rsplitn_mut(self, n, pred) + } /// 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 @@ -515,7 +667,10 @@ pub trait SliceExt { /// /// Panics if `chunk_size` is 0. #[stable(feature = "rust1", since = "1.0.0")] - fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut; + #[inline] + pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut { + core_slice::SliceExt::chunks_mut(self, chunk_size) + } /// Swaps two elements in a slice. /// @@ -536,7 +691,10 @@ pub trait SliceExt { /// assert!(v == ["a", "d", "c", "b"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn swap(&mut self, a: usize, b: usize); + #[inline] + pub fn swap(&mut self, a: usize, b: usize) { + core_slice::SliceExt::swap(self, a, b) + } /// Divides one `&mut` into two at an index. /// @@ -573,7 +731,10 @@ pub trait SliceExt { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn split_at_mut(&mut self, mid: usize) -> (&mut [Self::Item], &mut [Self::Item]); + #[inline] + pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + core_slice::SliceExt::split_at_mut(self, mid) + } /// Reverse the order of elements in a slice, in place. /// @@ -585,11 +746,17 @@ pub trait SliceExt { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn reverse(&mut self); + #[inline] + pub fn reverse(&mut self) { + core_slice::SliceExt::reverse(self) + } /// Returns an unsafe mutable pointer to the element in index #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut Self::Item; + #[inline] + pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { + core_slice::SliceExt::get_unchecked_mut(self, index) + } /// Return an unsafe mutable pointer to the slice's buffer. /// @@ -598,13 +765,19 @@ pub trait SliceExt { /// /// Modifying the slice may cause its buffer to be reallocated, which /// would also make any pointers to it invalid. - #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn as_mut_ptr(&mut self) -> *mut Self::Item; + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + core_slice::SliceExt::as_mut_ptr(self) + } /// Copies `self` into a new `Vec`. #[stable(feature = "rust1", since = "1.0.0")] - fn to_vec(&self) -> Vec where Self::Item: Clone; + #[inline] + pub fn to_vec(&self) -> Vec where T: Clone { + // NB see hack module in this file + hack::to_vec(self) + } /// Creates an iterator that yields every possible permutation of the /// vector in succession. @@ -612,6 +785,7 @@ pub trait SliceExt { /// # Examples /// /// ```rust + /// # #![feature(collections)] /// let v = [1, 2, 3]; /// let mut perms = v.permutations(); /// @@ -623,6 +797,7 @@ pub trait SliceExt { /// Iterating through permutations one by one. /// /// ```rust + /// # #![feature(collections)] /// let v = [1, 2, 3]; /// let mut perms = v.permutations(); /// @@ -631,7 +806,11 @@ pub trait SliceExt { /// assert_eq!(Some(vec![3, 1, 2]), perms.next()); /// ``` #[unstable(feature = "collections")] - fn permutations(&self) -> Permutations where Self::Item: Clone; + #[inline] + pub fn permutations(&self) -> Permutations where T: Clone { + // NB see hack module in this file + hack::permutations(self) + } /// Copies as many elements from `src` as it can into `self` (the /// shorter of `self.len()` and `src.len()`). Returns the number @@ -640,6 +819,7 @@ pub trait SliceExt { /// # Example /// /// ```rust + /// # #![feature(collections)] /// let mut dst = [0, 0, 0]; /// let src = [1, 2]; /// @@ -651,7 +831,9 @@ pub trait SliceExt { /// assert!(dst == [3, 4, 5]); /// ``` #[unstable(feature = "collections")] - fn clone_from_slice(&mut self, &[Self::Item]) -> usize where Self::Item: Clone; + pub fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone { + core_slice::SliceExt::clone_from_slice(self, src) + } /// Sorts the slice, in place. /// @@ -666,7 +848,10 @@ pub trait SliceExt { /// assert!(v == [-5, -3, 1, 2, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn sort(&mut self) where Self::Item: Ord; + #[inline] + pub fn sort(&mut self) where T: Ord { + self.sort_by(|a, b| a.cmp(b)) + } /// Binary search a sorted slice for a given element. /// @@ -682,8 +867,8 @@ pub trait SliceExt { /// found; the fourth could match any position in `[1,4]`. /// /// ```rust + /// # #![feature(core)] /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; - /// let s = s.as_slice(); /// /// assert_eq!(s.binary_search(&13), Ok(9)); /// assert_eq!(s.binary_search(&4), Err(7)); @@ -692,13 +877,8 @@ pub trait SliceExt { /// assert!(match r { Ok(1...4) => true, _ => false, }); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn binary_search(&self, x: &Self::Item) -> Result where Self::Item: Ord; - - /// Deprecated: use `binary_search` instead. - #[unstable(feature = "collections")] - #[deprecated(since = "1.0.0", reason = "use binary_search instead")] - fn binary_search_elem(&self, x: &Self::Item) -> Result where Self::Item: Ord { - self.binary_search(x) + pub fn binary_search(&self, x: &T) -> Result where T: Ord { + core_slice::SliceExt::binary_search(self, x) } /// Mutates the slice to the next lexicographic permutation. @@ -709,6 +889,7 @@ pub trait SliceExt { /// # Example /// /// ```rust + /// # #![feature(collections)] /// let v: &mut [_] = &mut [0, 1, 2]; /// v.next_permutation(); /// let b: &mut [_] = &mut [0, 2, 1]; @@ -719,7 +900,9 @@ pub trait SliceExt { /// ``` #[unstable(feature = "collections", reason = "uncertain if this merits inclusion in std")] - fn next_permutation(&mut self) -> bool where Self::Item: Ord; + pub fn next_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::next_permutation(self) + } /// Mutates the slice to the previous lexicographic permutation. /// @@ -729,6 +912,7 @@ pub trait SliceExt { /// # Example /// /// ```rust + /// # #![feature(collections)] /// let v: &mut [_] = &mut [1, 0, 2]; /// v.prev_permutation(); /// let b: &mut [_] = &mut [0, 2, 1]; @@ -739,15 +923,21 @@ pub trait SliceExt { /// ``` #[unstable(feature = "collections", reason = "uncertain if this merits inclusion in std")] - fn prev_permutation(&mut self) -> bool where Self::Item: Ord; + pub fn prev_permutation(&mut self) -> bool where T: Ord { + core_slice::SliceExt::prev_permutation(self) + } /// Find the first index containing a matching value. #[unstable(feature = "collections")] - fn position_elem(&self, t: &Self::Item) -> Option where Self::Item: PartialEq; + pub fn position_elem(&self, t: &T) -> Option where T: PartialEq { + core_slice::SliceExt::position_elem(self, t) + } /// Find the last index containing a matching value. #[unstable(feature = "collections")] - fn rposition_elem(&self, t: &Self::Item) -> Option where Self::Item: PartialEq; + pub fn rposition_elem(&self, t: &T) -> Option where T: PartialEq { + core_slice::SliceExt::rposition_elem(self, t) + } /// Returns true if the slice contains an element with the given value. /// @@ -759,7 +949,9 @@ pub trait SliceExt { /// assert!(!v.contains(&50)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq; + pub fn contains(&self, x: &T) -> bool where T: PartialEq { + core_slice::SliceExt::contains(self, x) + } /// Returns true if `needle` is a prefix of the slice. /// @@ -773,7 +965,9 @@ pub trait SliceExt { /// assert!(!v.starts_with(&[10, 50])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; + pub fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::starts_with(self, needle) + } /// Returns true if `needle` is a suffix of the slice. /// @@ -787,297 +981,18 @@ pub trait SliceExt { /// assert!(!v.ends_with(&[50, 30])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq; - - /// Convert `self` into a vector without clones or allocation. - #[unstable(feature = "collections")] - fn into_vec(self: Box) -> Vec; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl SliceExt for [T] { - type Item = T; - - #[inline] - fn sort_by(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering { - merge_sort(self, compare) - } - - #[inline] - fn move_from(&mut self, mut src: Vec, start: usize, end: usize) -> usize { - for (a, b) in self.iter_mut().zip(src[start .. end].iter_mut()) { - mem::swap(a, b); - } - cmp::min(self.len(), end-start) - } - - #[inline] - fn slice(&self, start: usize, end: usize) -> &[T] { - &self[start .. end] + pub fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { + core_slice::SliceExt::ends_with(self, needle) } + /// Convert `self` into a vector without clones or allocation. + #[stable(feature = "rust1", since = "1.0.0")] #[inline] - fn slice_from(&self, start: usize) -> &[T] { - &self[start ..] + pub fn into_vec(self: Box) -> Vec { + // NB see hack module in this file + hack::into_vec(self) } - - #[inline] - fn slice_to(&self, end: usize) -> &[T] { - &self[.. end] - } - - #[inline] - fn split_at(&self, mid: usize) -> (&[T], &[T]) { - core_slice::SliceExt::split_at(self, mid) - } - - #[inline] - fn iter(&self) -> Iter { - core_slice::SliceExt::iter(self) - } - - #[inline] - fn split(&self, pred: F) -> Split - where F: FnMut(&T) -> bool { - core_slice::SliceExt::split(self, pred) - } - - #[inline] - fn splitn(&self, n: usize, pred: F) -> SplitN - where F: FnMut(&T) -> bool { - core_slice::SliceExt::splitn(self, n, pred) - } - - #[inline] - fn rsplitn(&self, n: usize, pred: F) -> RSplitN - where F: FnMut(&T) -> bool { - core_slice::SliceExt::rsplitn(self, n, pred) - } - - #[inline] - fn windows(&self, size: usize) -> Windows { - core_slice::SliceExt::windows(self, size) - } - - #[inline] - fn chunks(&self, size: usize) -> Chunks { - core_slice::SliceExt::chunks(self, size) - } - - #[inline] - fn get(&self, index: usize) -> Option<&T> { - core_slice::SliceExt::get(self, index) - } - - #[inline] - fn first(&self) -> Option<&T> { - core_slice::SliceExt::first(self) - } - - #[inline] - fn tail(&self) -> &[T] { - core_slice::SliceExt::tail(self) - } - - #[inline] - fn init(&self) -> &[T] { - core_slice::SliceExt::init(self) - } - - #[inline] - fn last(&self) -> Option<&T> { - core_slice::SliceExt::last(self) - } - - #[inline] - unsafe fn get_unchecked(&self, index: usize) -> &T { - core_slice::SliceExt::get_unchecked(self, index) - } - - #[inline] - fn as_ptr(&self) -> *const T { - core_slice::SliceExt::as_ptr(self) - } - - #[inline] - fn binary_search_by(&self, f: F) -> Result - where F: FnMut(&T) -> Ordering { - core_slice::SliceExt::binary_search_by(self, f) - } - - #[inline] - fn len(&self) -> usize { - core_slice::SliceExt::len(self) - } - - #[inline] - fn is_empty(&self) -> bool { - core_slice::SliceExt::is_empty(self) - } - - #[inline] - fn get_mut(&mut self, index: usize) -> Option<&mut T> { - core_slice::SliceExt::get_mut(self, index) - } - - #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { - core_slice::SliceExt::as_mut_slice(self) - } - - #[inline] - fn slice_mut(&mut self, start: usize, end: usize) -> &mut [T] { - &mut self[start .. end] - } - - #[inline] - fn slice_from_mut(&mut self, start: usize) -> &mut [T] { - &mut self[start ..] - } - - #[inline] - fn slice_to_mut(&mut self, end: usize) -> &mut [T] { - &mut self[.. end] - } - - #[inline] - fn iter_mut(&mut self) -> IterMut { - core_slice::SliceExt::iter_mut(self) - } - - #[inline] - fn first_mut(&mut self) -> Option<&mut T> { - core_slice::SliceExt::first_mut(self) - } - - #[inline] - fn tail_mut(&mut self) -> &mut [T] { - core_slice::SliceExt::tail_mut(self) - } - - #[inline] - fn init_mut(&mut self) -> &mut [T] { - core_slice::SliceExt::init_mut(self) - } - - #[inline] - fn last_mut(&mut self) -> Option<&mut T> { - core_slice::SliceExt::last_mut(self) - } - - #[inline] - fn split_mut(&mut self, pred: F) -> SplitMut - where F: FnMut(&T) -> bool { - core_slice::SliceExt::split_mut(self, pred) - } - - #[inline] - fn splitn_mut(&mut self, n: usize, pred: F) -> SplitNMut - where F: FnMut(&T) -> bool { - core_slice::SliceExt::splitn_mut(self, n, pred) - } - - #[inline] - fn rsplitn_mut(&mut self, n: usize, pred: F) -> RSplitNMut - where F: FnMut(&T) -> bool { - core_slice::SliceExt::rsplitn_mut(self, n, pred) - } - - #[inline] - fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut { - core_slice::SliceExt::chunks_mut(self, chunk_size) - } - - #[inline] - fn swap(&mut self, a: usize, b: usize) { - core_slice::SliceExt::swap(self, a, b) - } - - #[inline] - fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { - core_slice::SliceExt::split_at_mut(self, mid) - } - - #[inline] - fn reverse(&mut self) { - core_slice::SliceExt::reverse(self) - } - - #[inline] - unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { - core_slice::SliceExt::get_unchecked_mut(self, index) - } - - #[inline] - fn as_mut_ptr(&mut self) -> *mut T { - core_slice::SliceExt::as_mut_ptr(self) - } - - /// Returns a copy of `v`. - #[inline] - fn to_vec(&self) -> Vec where T: Clone { - let mut vector = Vec::with_capacity(self.len()); - vector.push_all(self); - vector - } - - /// Returns an iterator over all permutations of a vector. - fn permutations(&self) -> Permutations where T: Clone { - Permutations{ - swaps: ElementSwaps::new(self.len()), - v: self.to_vec(), - } - } - - fn clone_from_slice(&mut self, src: &[T]) -> usize 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 binary_search(&self, x: &T) -> Result where T: Ord { - core_slice::SliceExt::binary_search(self, x) - } - - fn next_permutation(&mut self) -> bool where T: Ord { - core_slice::SliceExt::next_permutation(self) - } - - fn prev_permutation(&mut self) -> bool where T: Ord { - core_slice::SliceExt::prev_permutation(self) - } - - fn position_elem(&self, t: &T) -> Option where T: PartialEq { - core_slice::SliceExt::position_elem(self, t) - } - - fn rposition_elem(&self, t: &T) -> Option where T: PartialEq { - core_slice::SliceExt::rposition_elem(self, t) - } - - fn contains(&self, x: &T) -> bool where T: PartialEq { - core_slice::SliceExt::contains(self, x) - } - - fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq { - core_slice::SliceExt::starts_with(self, needle) - } - - fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq { - core_slice::SliceExt::ends_with(self, needle) - } - - fn into_vec(mut self: Box) -> Vec { - unsafe { - let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len()); - mem::forget(self); - xs - } - } -} +} //////////////////////////////////////////////////////////////////////////////// // Extension traits for slices over specific kinds of data @@ -1114,23 +1029,23 @@ pub trait SliceConcatExt { fn connect(&self, sep: &T) -> U; } -impl> SliceConcatExt> for [V] { +impl> SliceConcatExt> for [V] { fn concat(&self) -> Vec { - let size = self.iter().fold(0, |acc, v| acc + v.as_slice().len()); + let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len()); let mut result = Vec::with_capacity(size); for v in self { - result.push_all(v.as_slice()) + result.push_all(v.as_ref()) } result } fn connect(&self, sep: &T) -> Vec { - let size = self.iter().fold(0, |acc, v| acc + v.as_slice().len()); + let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len()); let mut result = Vec::with_capacity(size + self.len()); let mut first = true; for v in self { if first { first = false } else { result.push(sep.clone()) } - result.push_all(v.as_slice()) + result.push_all(v.as_ref()) } result } @@ -1188,7 +1103,15 @@ impl BorrowMut<[T]> for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for [T] { type Owned = Vec; + #[cfg(not(test))] fn to_owned(&self) -> Vec { self.to_vec() } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec`, which is required for this method + // definition, is not available. Since we don't require this method for testing purposes, I'll + // just stub it + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn to_owned(&self) -> Vec { panic!("not available with cfg(test)") } } //////////////////////////////////////////////////////////////////////////////// @@ -1209,10 +1132,14 @@ struct SizeDirection { impl Iterator for ElementSwaps { type Item = (usize, usize); - #[inline] + // #[inline] fn next(&mut self) -> Option<(usize, usize)> { + fn new_pos_wrapping(i: usize, s: Direction) -> usize { + i.wrapping_add(match s { Pos => 1, Neg => !0 /* aka -1 */ }) + } + fn new_pos(i: usize, s: Direction) -> usize { - i + match s { Pos => 1, Neg => -1 } + match s { Pos => i + 1, Neg => i - 1 } } // Find the index of the largest mobile element: @@ -1220,7 +1147,7 @@ impl Iterator for ElementSwaps { // swap should be with a smaller `size` element. let max = self.sdir.iter().cloned().enumerate() .filter(|&(i, sd)| - new_pos(i, sd.dir) < self.sdir.len() && + new_pos_wrapping(i, sd.dir) < self.sdir.len() && self.sdir[new_pos(i, sd.dir)].size < sd.size) .max_by(|&(_, sd)| sd.size); match max { @@ -1331,12 +1258,10 @@ fn insertion_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> O if i != j { let tmp = ptr::read(read_ptr); - ptr::copy_memory(buf_v.offset(j + 1), - &*buf_v.offset(j), - (i - j) as usize); - ptr::copy_nonoverlapping_memory(buf_v.offset(j), - &tmp, - 1); + ptr::copy(&*buf_v.offset(j), + buf_v.offset(j + 1), + (i - j) as usize); + ptr::copy_nonoverlapping(&tmp, buf_v.offset(j), 1); mem::forget(tmp); } } @@ -1345,8 +1270,8 @@ fn insertion_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> O fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering { // warning: this wildly uses unsafe. - static BASE_INSERTION: usize = 32; - static LARGE_INSERTION: usize = 16; + const BASE_INSERTION: usize = 32; + const LARGE_INSERTION: usize = 16; // FIXME #12092: smaller insertion runs seems to make sorting // vectors of large elements a little faster on some platforms, @@ -1384,7 +1309,7 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order // We could hardcode the sorting comparisons here, and we could // manipulate/step the pointers themselves, rather than repeatedly // .offset-ing. - for start in range_step(0, len, insertion) { + for start in (0.. len).step_by(insertion) { // start <= i < len; for i in start..cmp::min(start + insertion, len) { // j satisfies: start <= j <= i; @@ -1409,10 +1334,10 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order // j + 1 could be `len` (for the last `i`), but in // that case, `i == j` so we don't copy. The // `.offset(j)` is always in bounds. - ptr::copy_memory(buf_dat.offset(j + 1), - &*buf_dat.offset(j), - i - j as usize); - ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1); + ptr::copy(&*buf_dat.offset(j), + buf_dat.offset(j + 1), + i - j as usize); + ptr::copy_nonoverlapping(read_ptr, buf_dat.offset(j), 1); } } } @@ -1424,7 +1349,7 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order // a time, placing the result in `buf_tmp`. // 0 <= start <= len. - for start in range_step(0, len, 2 * width) { + for start in (0..len).step_by(2 * width) { // manipulate pointers directly for speed (rather than // using a `for` loop with `range` and `.offset` inside // that loop). @@ -1460,11 +1385,11 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order if left == right_start { // the number remaining in this run. let elems = (right_end as usize - right as usize) / mem::size_of::(); - ptr::copy_nonoverlapping_memory(out, &*right, elems); + ptr::copy_nonoverlapping(&*right, out, elems); break; } else if right == right_end { let elems = (right_start as usize - left as usize) / mem::size_of::(); - ptr::copy_nonoverlapping_memory(out, &*left, elems); + ptr::copy_nonoverlapping(&*left, out, elems); break; } @@ -1478,7 +1403,7 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order } else { step(&mut left) }; - ptr::copy_nonoverlapping_memory(out, &*to_copy, 1); + ptr::copy_nonoverlapping(&*to_copy, out, 1); step(&mut out); } } @@ -1492,7 +1417,7 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order // write the result to `v` in one go, so that there are never two copies // of the same object in `v`. unsafe { - ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len); + ptr::copy_nonoverlapping(&*buf_dat, v.as_mut_ptr(), len); } // increment the pointer, returning the old pointer. @@ -1503,1631 +1428,3 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order old } } - -#[cfg(test)] -mod tests { - use core::cmp::Ordering::{Greater, Less, Equal}; - use core::prelude::{Some, None, Clone}; - use core::prelude::{Iterator, IteratorExt}; - use core::prelude::{AsSlice}; - use core::prelude::Ord; - use core::default::Default; - use core::mem; - use std::iter::RandomAccessIterator; - use std::rand::{Rng, thread_rng}; - use std::rc::Rc; - use string::ToString; - use vec::Vec; - use super::{ElementSwaps, SliceConcatExt, SliceExt}; - - fn square(n: usize) -> usize { n * n } - - fn is_odd(n: &usize) -> bool { *n % 2 == 1 } - - #[test] - fn test_from_fn() { - // Test on-stack from_fn. - let mut v: Vec<_> = (0..3).map(square).collect(); - { - let v = v; - assert_eq!(v.len(), 3); - assert_eq!(v[0], 0); - assert_eq!(v[1], 1); - assert_eq!(v[2], 4); - } - - // Test on-heap from_fn. - v = (0..5).map(square).collect(); - { - let v = v; - assert_eq!(v.len(), 5); - assert_eq!(v[0], 0); - assert_eq!(v[1], 1); - assert_eq!(v[2], 4); - assert_eq!(v[3], 9); - assert_eq!(v[4], 16); - } - } - - #[test] - fn test_from_elem() { - // Test on-stack from_elem. - let mut v = vec![10, 10]; - { - let v = v; - assert_eq!(v.len(), 2); - assert_eq!(v[0], 10); - assert_eq!(v[1], 10); - } - - // Test on-heap from_elem. - v = vec![20; 6]; - { - let v = v.as_slice(); - assert_eq!(v[0], 20); - assert_eq!(v[1], 20); - assert_eq!(v[2], 20); - assert_eq!(v[3], 20); - assert_eq!(v[4], 20); - assert_eq!(v[5], 20); - } - } - - #[test] - fn test_is_empty() { - let xs: [i32; 0] = []; - assert!(xs.is_empty()); - assert!(![0].is_empty()); - } - - #[test] - fn test_len_divzero() { - type Z = [i8; 0]; - let v0 : &[Z] = &[]; - let v1 : &[Z] = &[[]]; - let v2 : &[Z] = &[[], []]; - assert_eq!(mem::size_of::(), 0); - assert_eq!(v0.len(), 0); - assert_eq!(v1.len(), 1); - assert_eq!(v2.len(), 2); - } - - #[test] - fn test_get() { - let mut a = vec![11]; - assert_eq!(a.get(1), None); - a = vec![11, 12]; - assert_eq!(a.get(1).unwrap(), &12); - a = vec![11, 12, 13]; - assert_eq!(a.get(1).unwrap(), &12); - } - - #[test] - fn test_first() { - let mut a = vec![]; - assert_eq!(a.first(), None); - a = vec![11]; - assert_eq!(a.first().unwrap(), &11); - a = vec![11, 12]; - assert_eq!(a.first().unwrap(), &11); - } - - #[test] - fn test_first_mut() { - let mut a = vec![]; - assert_eq!(a.first_mut(), None); - a = vec![11]; - assert_eq!(*a.first_mut().unwrap(), 11); - a = vec![11, 12]; - assert_eq!(*a.first_mut().unwrap(), 11); - } - - #[test] - fn test_tail() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.tail(), b); - a = vec![11, 12]; - let b: &[i32] = &[12]; - assert_eq!(a.tail(), b); - } - - #[test] - fn test_tail_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.tail_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [12]; - assert!(a.tail_mut() == b); - } - - #[test] - #[should_fail] - fn test_tail_empty() { - let a = Vec::::new(); - a.tail(); - } - - #[test] - #[should_fail] - fn test_tail_mut_empty() { - let mut a = Vec::::new(); - a.tail_mut(); - } - - #[test] - fn test_init() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert_eq!(a.init(), b); - a = vec![11, 12]; - let b: &[_] = &[11]; - assert_eq!(a.init(), b); - } - - #[test] - fn test_init_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(a.init_mut() == b); - a = vec![11, 12]; - let b: &mut [_] = &mut [11]; - assert!(a.init_mut() == b); - } - - #[test] - #[should_fail] - fn test_init_empty() { - let a = Vec::::new(); - a.init(); - } - - #[test] - #[should_fail] - fn test_init_mut_empty() { - let mut a = Vec::::new(); - a.init_mut(); - } - - #[test] - fn test_last() { - let mut a = vec![]; - assert_eq!(a.last(), None); - a = vec![11]; - assert_eq!(a.last().unwrap(), &11); - a = vec![11, 12]; - assert_eq!(a.last().unwrap(), &12); - } - - #[test] - fn test_last_mut() { - let mut a = vec![]; - assert_eq!(a.last_mut(), None); - a = vec![11]; - assert_eq!(*a.last_mut().unwrap(), 11); - a = vec![11, 12]; - assert_eq!(*a.last_mut().unwrap(), 12); - } - - #[test] - fn test_slice() { - // Test fixed length vector. - let vec_fixed = [1, 2, 3, 4]; - let v_a = vec_fixed[1..vec_fixed.len()].to_vec(); - assert_eq!(v_a.len(), 3); - - assert_eq!(v_a[0], 2); - assert_eq!(v_a[1], 3); - assert_eq!(v_a[2], 4); - - // Test on stack. - let vec_stack: &[_] = &[1, 2, 3]; - let v_b = vec_stack[1..3].to_vec(); - assert_eq!(v_b.len(), 2); - - assert_eq!(v_b[0], 2); - assert_eq!(v_b[1], 3); - - // Test `Box<[T]>` - let vec_unique = vec![1, 2, 3, 4, 5, 6]; - let v_d = vec_unique[1..6].to_vec(); - assert_eq!(v_d.len(), 5); - - assert_eq!(v_d[0], 2); - assert_eq!(v_d[1], 3); - assert_eq!(v_d[2], 4); - assert_eq!(v_d[3], 5); - assert_eq!(v_d[4], 6); - } - - #[test] - fn test_slice_from() { - let vec: &[_] = &[1, 2, 3, 4]; - assert_eq!(&vec[..], vec); - let b: &[_] = &[3, 4]; - assert_eq!(&vec[2..], b); - let b: &[_] = &[]; - assert_eq!(&vec[4..], b); - } - - #[test] - fn test_slice_to() { - let vec: &[_] = &[1, 2, 3, 4]; - assert_eq!(&vec[..4], vec); - let b: &[_] = &[1, 2]; - assert_eq!(&vec[..2], b); - let b: &[_] = &[]; - assert_eq!(&vec[..0], b); - } - - - #[test] - fn test_pop() { - let mut v = vec![5]; - let e = v.pop(); - assert_eq!(v.len(), 0); - assert_eq!(e, Some(5)); - let f = v.pop(); - assert_eq!(f, None); - let g = v.pop(); - assert_eq!(g, None); - } - - #[test] - fn test_swap_remove() { - let mut v = vec![1, 2, 3, 4, 5]; - let mut e = v.swap_remove(0); - assert_eq!(e, 1); - assert_eq!(v, vec![5, 2, 3, 4]); - e = v.swap_remove(3); - assert_eq!(e, 4); - assert_eq!(v, vec![5, 2, 3]); - } - - #[test] - #[should_fail] - fn test_swap_remove_fail() { - let mut v = vec![1]; - let _ = v.swap_remove(0); - let _ = v.swap_remove(0); - } - - #[test] - fn test_swap_remove_noncopyable() { - // Tests that we don't accidentally run destructors twice. - let mut v = Vec::new(); - v.push(box 0u8); - v.push(box 0u8); - v.push(box 0u8); - let mut _e = v.swap_remove(0); - assert_eq!(v.len(), 2); - _e = v.swap_remove(1); - assert_eq!(v.len(), 1); - _e = v.swap_remove(0); - assert_eq!(v.len(), 0); - } - - #[test] - fn test_push() { - // Test on-stack push(). - let mut v = vec![]; - v.push(1); - assert_eq!(v.len(), 1); - assert_eq!(v[0], 1); - - // Test on-heap push(). - v.push(2); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - } - - #[test] - fn test_truncate() { - let mut v = vec![box 6,box 5,box 4]; - v.truncate(1); - let v = v; - assert_eq!(v.len(), 1); - assert_eq!(*(v[0]), 6); - // If the unsafe block didn't drop things properly, we blow up here. - } - - #[test] - fn test_clear() { - let mut v = vec![box 6,box 5,box 4]; - v.clear(); - assert_eq!(v.len(), 0); - // If the unsafe block didn't drop things properly, we blow up here. - } - - #[test] - fn test_dedup() { - fn case(a: Vec, b: Vec) { - let mut v = a; - v.dedup(); - assert_eq!(v, b); - } - case(vec![], vec![]); - case(vec![1], vec![1]); - case(vec![1,1], vec![1]); - case(vec![1,2,3], vec![1,2,3]); - case(vec![1,1,2,3], vec![1,2,3]); - case(vec![1,2,2,3], vec![1,2,3]); - case(vec![1,2,3,3], vec![1,2,3]); - case(vec![1,1,2,2,2,3,3], vec![1,2,3]); - } - - #[test] - fn test_dedup_unique() { - let mut v0 = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1 = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2 = vec![box 1, box 2, box 3, box 3]; - v2.dedup(); - /* - * If the boxed pointers were leaked or otherwise misused, valgrind - * and/or rt should raise errors. - */ - } - - #[test] - fn test_dedup_shared() { - let mut v0 = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1 = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2 = vec![box 1, box 2, box 3, box 3]; - v2.dedup(); - /* - * If the pointers were leaked or otherwise misused, valgrind and/or - * rt should raise errors. - */ - } - - #[test] - fn test_retain() { - let mut v = vec![1, 2, 3, 4, 5]; - v.retain(is_odd); - assert_eq!(v, vec![1, 3, 5]); - } - - #[test] - fn test_element_swaps() { - let mut v = [1, 2, 3]; - for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { - v.swap(a, b); - match i { - 0 => assert!(v == [1, 3, 2]), - 1 => assert!(v == [3, 1, 2]), - 2 => assert!(v == [3, 2, 1]), - 3 => assert!(v == [2, 3, 1]), - 4 => assert!(v == [2, 1, 3]), - 5 => assert!(v == [1, 2, 3]), - _ => panic!(), - } - } - } - - #[test] - fn test_permutations() { - { - let v: [i32; 0] = []; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = ["Hello".to_string()]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 1); - assert_eq!(max_opt.unwrap(), 1); - assert_eq!(it.next(), Some(v.to_vec())); - assert_eq!(it.next(), None); - } - { - let v = [1, 2, 3]; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3*2); - assert_eq!(max_opt.unwrap(), 3*2); - assert_eq!(it.next(), Some(vec![1,2,3])); - assert_eq!(it.next(), Some(vec![1,3,2])); - assert_eq!(it.next(), Some(vec![3,1,2])); - let (min_size, max_opt) = it.size_hint(); - assert_eq!(min_size, 3); - assert_eq!(max_opt.unwrap(), 3); - assert_eq!(it.next(), Some(vec![3,2,1])); - assert_eq!(it.next(), Some(vec![2,3,1])); - assert_eq!(it.next(), Some(vec![2,1,3])); - assert_eq!(it.next(), None); - } - { - // check that we have N! permutations - let v = ['A', 'B', 'C', 'D', 'E', 'F']; - let mut amt = 0; - let mut it = v.permutations(); - let (min_size, max_opt) = it.size_hint(); - for _perm in it.by_ref() { - amt += 1; - } - assert_eq!(amt, it.swaps.swaps_made); - assert_eq!(amt, min_size); - assert_eq!(amt, 2 * 3 * 4 * 5 * 6); - assert_eq!(amt, max_opt.unwrap()); - } - } - - #[test] - fn test_lexicographic_permutations() { - let v : &mut[_] = &mut[1, 2, 3, 4, 5]; - assert!(v.prev_permutation() == false); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 3, 5, 4]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[1, 2, 3, 4, 5]; - assert!(v == b); - assert!(v.next_permutation()); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 4, 3, 5]; - assert!(v == b); - assert!(v.next_permutation()); - let b: &mut[_] = &mut[1, 2, 4, 5, 3]; - assert!(v == b); - - let v : &mut[_] = &mut[1, 0, 0, 0]; - assert!(v.next_permutation() == false); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 1, 0, 0]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 0, 1, 0]; - assert!(v == b); - assert!(v.prev_permutation()); - let b: &mut[_] = &mut[0, 0, 0, 1]; - assert!(v == b); - assert!(v.prev_permutation() == false); - } - - #[test] - fn test_lexicographic_permutations_empty_and_short() { - let empty : &mut[i32] = &mut[]; - assert!(empty.next_permutation() == false); - let b: &mut[i32] = &mut[]; - assert!(empty == b); - assert!(empty.prev_permutation() == false); - assert!(empty == b); - - let one_elem : &mut[_] = &mut[4]; - assert!(one_elem.prev_permutation() == false); - let b: &mut[_] = &mut[4]; - assert!(one_elem == b); - assert!(one_elem.next_permutation() == false); - assert!(one_elem == b); - - let two_elem : &mut[_] = &mut[1, 2]; - assert!(two_elem.prev_permutation() == false); - let b : &mut[_] = &mut[1, 2]; - let c : &mut[_] = &mut[2, 1]; - assert!(two_elem == b); - assert!(two_elem.next_permutation()); - assert!(two_elem == c); - assert!(two_elem.next_permutation() == false); - assert!(two_elem == c); - assert!(two_elem.prev_permutation()); - assert!(two_elem == b); - assert!(two_elem.prev_permutation() == false); - assert!(two_elem == b); - } - - #[test] - fn test_position_elem() { - assert!([].position_elem(&1).is_none()); - - let v1 = vec![1, 2, 3, 3, 2, 5]; - assert_eq!(v1.position_elem(&1), Some(0)); - assert_eq!(v1.position_elem(&2), Some(1)); - assert_eq!(v1.position_elem(&5), Some(5)); - assert!(v1.position_elem(&4).is_none()); - } - - #[test] - fn test_binary_search() { - assert_eq!([1,2,3,4,5].binary_search(&5).ok(), Some(4)); - assert_eq!([1,2,3,4,5].binary_search(&4).ok(), Some(3)); - assert_eq!([1,2,3,4,5].binary_search(&3).ok(), Some(2)); - assert_eq!([1,2,3,4,5].binary_search(&2).ok(), Some(1)); - assert_eq!([1,2,3,4,5].binary_search(&1).ok(), Some(0)); - - assert_eq!([2,4,6,8,10].binary_search(&1).ok(), None); - assert_eq!([2,4,6,8,10].binary_search(&5).ok(), None); - assert_eq!([2,4,6,8,10].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6,8,10].binary_search(&10).ok(), Some(4)); - - assert_eq!([2,4,6,8].binary_search(&1).ok(), None); - assert_eq!([2,4,6,8].binary_search(&5).ok(), None); - assert_eq!([2,4,6,8].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6,8].binary_search(&8).ok(), Some(3)); - - assert_eq!([2,4,6].binary_search(&1).ok(), None); - assert_eq!([2,4,6].binary_search(&5).ok(), None); - assert_eq!([2,4,6].binary_search(&4).ok(), Some(1)); - assert_eq!([2,4,6].binary_search(&6).ok(), Some(2)); - - assert_eq!([2,4].binary_search(&1).ok(), None); - assert_eq!([2,4].binary_search(&5).ok(), None); - assert_eq!([2,4].binary_search(&2).ok(), Some(0)); - assert_eq!([2,4].binary_search(&4).ok(), Some(1)); - - assert_eq!([2].binary_search(&1).ok(), None); - assert_eq!([2].binary_search(&5).ok(), None); - assert_eq!([2].binary_search(&2).ok(), Some(0)); - - assert_eq!([].binary_search(&1).ok(), None); - assert_eq!([].binary_search(&5).ok(), None); - - assert!([1,1,1,1,1].binary_search(&1).ok() != None); - assert!([1,1,1,1,2].binary_search(&1).ok() != None); - assert!([1,1,1,2,2].binary_search(&1).ok() != None); - assert!([1,1,2,2,2].binary_search(&1).ok() != None); - assert_eq!([1,2,2,2,2].binary_search(&1).ok(), Some(0)); - - assert_eq!([1,2,3,4,5].binary_search(&6).ok(), None); - assert_eq!([1,2,3,4,5].binary_search(&0).ok(), None); - } - - #[test] - fn test_reverse() { - let mut v = vec![10, 20]; - assert_eq!(v[0], 10); - assert_eq!(v[1], 20); - v.reverse(); - assert_eq!(v[0], 20); - assert_eq!(v[1], 10); - - let mut v3 = Vec::::new(); - v3.reverse(); - assert!(v3.is_empty()); - } - - #[test] - fn test_sort() { - for len in 4..25 { - for _ in 0..100 { - let mut v: Vec<_> = thread_rng().gen_iter::().take(len).collect(); - let mut v1 = v.clone(); - - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); - } - } - - // shouldn't panic - let mut v: [i32; 0] = []; - v.sort(); - - let mut v = [0xDEADBEEFu64]; - v.sort(); - assert!(v == [0xDEADBEEF]); - } - - #[test] - fn test_sort_stability() { - for len in 4..25 { - for _ in 0..10 { - let mut counts = [0; 10]; - - // create a vector like [(6, 1), (5, 1), (6, 2), ...], - // where the first item of each tuple is random, but - // the second item represents which occurrence of that - // number this element is, i.e. the second elements - // will occur in sorted order. - let mut v: Vec<_> = (0..len).map(|_| { - let n = thread_rng().gen::() % 10; - counts[n] += 1; - (n, counts[n]) - }).collect(); - - // only sort on the first element, so an unstable sort - // may mix up the counts. - v.sort_by(|&(a,_), &(b,_)| a.cmp(&b)); - - // this comparison includes the count (the second item - // of the tuple), so elements with equal first items - // will need to be ordered with increasing - // counts... i.e. exactly asserting that this sort is - // stable. - assert!(v.windows(2).all(|w| w[0] <= w[1])); - } - } - } - - #[test] - fn test_concat() { - let v: [Vec; 0] = []; - let c = v.concat(); - assert_eq!(c, []); - let d = [vec![1], vec![2,3]].concat(); - assert_eq!(d, vec![1, 2, 3]); - - let v: &[&[_]] = &[&[1], &[2, 3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 3]); - let v: &[&[_]] = &[&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]); - } - - #[test] - fn test_connect() { - let v: [Vec; 0] = []; - assert_eq!(v.connect(&0), vec![]); - assert_eq!([vec![1], vec![2, 3]].connect(&0), vec![1, 0, 2, 3]); - assert_eq!([vec![1], vec![2], vec![3]].connect(&0), vec![1, 0, 2, 0, 3]); - - let v: [&[_]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 3]); - let v: [&[_]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]); - } - - #[test] - fn test_insert() { - let mut a = vec![1, 2, 4]; - a.insert(2, 3); - assert_eq!(a, vec![1, 2, 3, 4]); - - let mut a = vec![1, 2, 3]; - a.insert(0, 0); - assert_eq!(a, vec![0, 1, 2, 3]); - - let mut a = vec![1, 2, 3]; - a.insert(3, 4); - assert_eq!(a, vec![1, 2, 3, 4]); - - let mut a = vec![]; - a.insert(0, 1); - assert_eq!(a, vec![1]); - } - - #[test] - #[should_fail] - fn test_insert_oob() { - let mut a = vec![1, 2, 3]; - a.insert(4, 5); - } - - #[test] - fn test_remove() { - let mut a = vec![1, 2, 3, 4]; - - assert_eq!(a.remove(2), 3); - assert_eq!(a, vec![1, 2, 4]); - - assert_eq!(a.remove(2), 4); - assert_eq!(a, vec![1, 2]); - - assert_eq!(a.remove(0), 1); - assert_eq!(a, vec![2]); - - assert_eq!(a.remove(0), 2); - assert_eq!(a, vec![]); - } - - #[test] - #[should_fail] - fn test_remove_fail() { - let mut a = vec![1]; - let _ = a.remove(0); - let _ = a.remove(0); - } - - #[test] - fn test_capacity() { - let mut v = vec![0]; - v.reserve_exact(10); - assert!(v.capacity() >= 11); - } - - #[test] - fn test_slice_2() { - let v = vec![1, 2, 3, 4, 5]; - let v = v.slice(1, 3); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 2); - assert_eq!(v[1], 3); - } - - #[test] - #[should_fail] - fn test_permute_fail() { - let v = [(box 0, Rc::new(0)), (box 0, Rc::new(0)), - (box 0, Rc::new(0)), (box 0, Rc::new(0))]; - let mut i = 0; - for _ in v.permutations() { - if i == 2 { - panic!() - } - i += 1; - } - } - - #[test] - fn test_total_ord() { - let c = &[1, 2, 3]; - [1, 2, 3, 4][..].cmp(c) == Greater; - let c = &[1, 2, 3, 4]; - [1, 2, 3][..].cmp(c) == Less; - let c = &[1, 2, 3, 6]; - [1, 2, 3, 4][..].cmp(c) == Equal; - let c = &[1, 2, 3, 4, 5, 6]; - [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; - let c = &[1, 2, 3, 4]; - [2, 2][..].cmp(c) == Greater; - } - - #[test] - fn test_iterator() { - let xs = [1, 2, 5, 10, 11]; - let mut it = xs.iter(); - assert_eq!(it.size_hint(), (5, Some(5))); - assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.size_hint(), (4, Some(4))); - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_random_access_iterator() { - let xs = [1, 2, 5, 10, 11]; - let mut it = xs.iter(); - - assert_eq!(it.indexable(), 5); - assert_eq!(it.idx(0).unwrap(), &1); - assert_eq!(it.idx(2).unwrap(), &5); - assert_eq!(it.idx(4).unwrap(), &11); - assert!(it.idx(5).is_none()); - - assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.indexable(), 4); - assert_eq!(it.idx(0).unwrap(), &2); - assert_eq!(it.idx(3).unwrap(), &11); - assert!(it.idx(4).is_none()); - - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.indexable(), 3); - assert_eq!(it.idx(1).unwrap(), &10); - assert!(it.idx(3).is_none()); - - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.indexable(), 2); - assert_eq!(it.idx(1).unwrap(), &11); - - assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.indexable(), 1); - assert_eq!(it.idx(0).unwrap(), &11); - assert!(it.idx(1).is_none()); - - assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.indexable(), 0); - assert!(it.idx(0).is_none()); - - assert!(it.next().is_none()); - } - - #[test] - fn test_iter_size_hints() { - let mut xs = [1, 2, 5, 10, 11]; - assert_eq!(xs.iter().size_hint(), (5, Some(5))); - assert_eq!(xs.iter_mut().size_hint(), (5, Some(5))); - } - - #[test] - fn test_iter_clone() { - let xs = [1, 2, 5]; - let mut it = xs.iter(); - it.next(); - let mut jt = it.clone(); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next(), jt.next()); - } - - #[test] - fn test_mut_iterator() { - let mut xs = [1, 2, 3, 4, 5]; - for x in &mut xs { - *x += 1; - } - assert!(xs == [2, 3, 4, 5, 6]) - } - - #[test] - fn test_rev_iterator() { - - let xs = [1, 2, 5, 10, 11]; - let ys = [11, 10, 5, 2, 1]; - let mut i = 0; - for &x in xs.iter().rev() { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, 5); - } - - #[test] - fn test_mut_rev_iterator() { - let mut xs = [1, 2, 3, 4, 5]; - for (i,x) in xs.iter_mut().rev().enumerate() { - *x += i; - } - assert!(xs == [5, 5, 5, 5, 5]) - } - - #[test] - fn test_move_iterator() { - let xs = vec![1,2,3,4,5]; - assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10*a + b), 12345); - } - - #[test] - fn test_move_rev_iterator() { - let xs = vec![1,2,3,4,5]; - assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10*a + b), 54321); - } - - #[test] - fn test_splitator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1], &[3], &[5]]; - assert_eq!(xs.split(|x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 1).collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4], &[]]; - assert_eq!(xs.split(|x| *x == 5).collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; - assert_eq!(xs.split(|_| true).collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); - } - - #[test] - fn test_splitnator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[1], &[3,4,5]]; - assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; - assert_eq!(xs.splitn(3, |_| true).collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.splitn(1, |x| *x == 5).collect::>(), splits); - } - - #[test] - fn test_splitnator_mut() { - let xs = &mut [1,2,3,4,5]; - - let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]]; - assert_eq!(xs.splitn_mut(0, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; - assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; - assert_eq!(xs.splitn_mut(3, |_| true).collect::>(), - splits); - - let xs: &mut [i32] = &mut []; - let splits: &[&mut[i32]] = &[&mut []]; - assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::>(), - splits); - } - - #[test] - fn test_rsplitator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[5], &[3], &[1]]; - assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[2,3,4,5], &[]]; - assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[1,2,3,4]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), - splits); - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); - } - - #[test] - fn test_rsplitnator() { - let xs = &[1,2,3,4,5]; - - let splits: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[5], &[1,2,3]]; - assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), - splits); - let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; - assert_eq!(xs.rsplitn(3, |_| true).collect::>(), - splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::>(), splits); - } - - #[test] - fn test_windowsator() { - let v = &[1,2,3,4]; - - let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; - assert_eq!(v.windows(2).collect::>(), wins); - - let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; - assert_eq!(v.windows(3).collect::>(), wins); - assert!(v.windows(6).next().is_none()); - - let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; - assert_eq!(v.windows(2).rev().collect::>(), wins); - let mut it = v.windows(2); - assert_eq!(it.indexable(), 3); - let win: &[_] = &[1,2]; - assert_eq!(it.idx(0).unwrap(), win); - let win: &[_] = &[2,3]; - assert_eq!(it.idx(1).unwrap(), win); - let win: &[_] = &[3,4]; - assert_eq!(it.idx(2).unwrap(), win); - assert_eq!(it.idx(3), None); - } - - #[test] - #[should_fail] - fn test_windowsator_0() { - let v = &[1,2,3,4]; - let _it = v.windows(0); - } - - #[test] - fn test_chunksator() { - use core::iter::ExactSizeIterator; - - let v = &[1,2,3,4,5]; - - assert_eq!(v.chunks(2).len(), 3); - - let chunks: &[&[_]] = &[&[1,2], &[3,4], &[5]]; - assert_eq!(v.chunks(2).collect::>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; - assert_eq!(v.chunks(3).collect::>(), chunks); - let chunks: &[&[_]] = &[&[1,2,3,4,5]]; - assert_eq!(v.chunks(6).collect::>(), chunks); - - let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; - assert_eq!(v.chunks(2).rev().collect::>(), chunks); - let mut it = v.chunks(2); - assert_eq!(it.indexable(), 3); - - let chunk: &[_] = &[1,2]; - assert_eq!(it.idx(0).unwrap(), chunk); - let chunk: &[_] = &[3,4]; - assert_eq!(it.idx(1).unwrap(), chunk); - let chunk: &[_] = &[5]; - assert_eq!(it.idx(2).unwrap(), chunk); - assert_eq!(it.idx(3), None); - } - - #[test] - #[should_fail] - fn test_chunksator_0() { - let v = &[1,2,3,4]; - let _it = v.chunks(0); - } - - #[test] - fn test_move_from() { - let mut a = [1,2,3,4,5]; - let b = vec![6,7,8]; - assert_eq!(a.move_from(b, 0, 3), 3); - assert!(a == [6,7,8,4,5]); - let mut a = [7,2,8,1]; - let b = vec![3,1,4,1,5,9]; - assert_eq!(a.move_from(b, 0, 6), 4); - assert!(a == [3,1,4,1]); - let mut a = [1,2,3,4]; - let b = vec![5,6,7,8,9,0]; - assert_eq!(a.move_from(b, 2, 3), 1); - assert!(a == [7,2,3,4]); - let mut a = [1,2,3,4,5]; - let b = vec![5,6,7,8,9,0]; - assert_eq!(a[2..4].move_from(b,1,6), 2); - assert!(a == [1,2,6,7,5]); - } - - #[test] - fn test_reverse_part() { - let mut values = [1,2,3,4,5]; - values[1..4].reverse(); - assert!(values == [1,4,3,2,5]); - } - - #[test] - fn test_show() { - macro_rules! test_show_vec { - ($x:expr, $x_str:expr) => ({ - let (x, x_str) = ($x, $x_str); - assert_eq!(format!("{:?}", x), x_str); - assert_eq!(format!("{:?}", x), x_str); - }) - } - let empty = Vec::::new(); - test_show_vec!(empty, "[]"); - test_show_vec!(vec![1], "[1]"); - test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); - test_show_vec!(vec![vec![], vec![1], vec![1, 1]], - "[[], [1], [1, 1]]"); - - let empty_mut: &mut [i32] = &mut[]; - test_show_vec!(empty_mut, "[]"); - let v = &mut[1]; - test_show_vec!(v, "[1]"); - let v = &mut[1, 2, 3]; - test_show_vec!(v, "[1, 2, 3]"); - let v: &mut[&mut[_]] = &mut[&mut[], &mut[1], &mut[1, 1]]; - test_show_vec!(v, "[[], [1], [1, 1]]"); - } - - #[test] - fn test_vec_default() { - macro_rules! t { - ($ty:ty) => {{ - let v: $ty = Default::default(); - assert!(v.is_empty()); - }} - } - - t!(&[i32]); - t!(Vec); - } - - #[test] - fn test_bytes_set_memory() { - use slice::bytes::MutableByteVector; - let mut values = [1u8,2,3,4,5]; - values[0..5].set_memory(0xAB); - assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); - values[2..4].set_memory(0xFF); - assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); - } - - #[test] - #[should_fail] - fn test_overflow_does_not_cause_segfault() { - let mut v = vec![]; - v.reserve_exact(-1); - v.push(1); - v.push(2); - } - - #[test] - #[should_fail] - fn test_overflow_does_not_cause_segfault_managed() { - let mut v = vec![Rc::new(1)]; - v.reserve_exact(-1); - v.push(Rc::new(2)); - } - - #[test] - fn test_mut_split_at() { - let mut values = [1u8,2,3,4,5]; - { - let (left, right) = values.split_at_mut(2); - { - let left: &[_] = left; - assert!(left[..left.len()] == [1, 2][]); - } - for p in left { - *p += 1; - } - - { - let right: &[_] = right; - assert!(right[..right.len()] == [3, 4, 5][]); - } - for p in right { - *p += 2; - } - } - - assert!(values == [2, 3, 5, 6, 7]); - } - - #[derive(Clone, PartialEq)] - struct Foo; - - #[test] - fn test_iter_zero_sized() { - let mut v = vec![Foo, Foo, Foo]; - assert_eq!(v.len(), 3); - let mut cnt = 0; - - for f in &v { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 3); - - for f in &v[1..3] { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 5); - - for f in &mut v { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 8); - - for f in v { - assert!(f == Foo); - cnt += 1; - } - assert_eq!(cnt, 11); - - let xs: [Foo; 3] = [Foo, Foo, Foo]; - cnt = 0; - for f in &xs { - assert!(*f == Foo); - cnt += 1; - } - assert!(cnt == 3); - } - - #[test] - fn test_shrink_to_fit() { - let mut xs = vec![0, 1, 2, 3]; - for i in 4..100 { - xs.push(i) - } - assert_eq!(xs.capacity(), 128); - xs.shrink_to_fit(); - assert_eq!(xs.capacity(), 100); - assert_eq!(xs, (0..100).collect::>()); - } - - #[test] - fn test_starts_with() { - assert!(b"foobar".starts_with(b"foo")); - assert!(!b"foobar".starts_with(b"oob")); - assert!(!b"foobar".starts_with(b"bar")); - assert!(!b"foo".starts_with(b"foobar")); - assert!(!b"bar".starts_with(b"foobar")); - assert!(b"foobar".starts_with(b"foobar")); - let empty: &[u8] = &[]; - assert!(empty.starts_with(empty)); - assert!(!empty.starts_with(b"foo")); - assert!(b"foobar".starts_with(empty)); - } - - #[test] - fn test_ends_with() { - assert!(b"foobar".ends_with(b"bar")); - assert!(!b"foobar".ends_with(b"oba")); - assert!(!b"foobar".ends_with(b"foo")); - assert!(!b"foo".ends_with(b"foobar")); - assert!(!b"bar".ends_with(b"foobar")); - assert!(b"foobar".ends_with(b"foobar")); - let empty: &[u8] = &[]; - assert!(empty.ends_with(empty)); - assert!(!empty.ends_with(b"foo")); - assert!(b"foobar".ends_with(empty)); - } - - #[test] - fn test_mut_splitator() { - let mut xs = [0,1,0,2,3,0,0,4,5,0]; - assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); - for slice in xs.split_mut(|x| *x == 0) { - slice.reverse(); - } - assert!(xs == [0,1,0,3,2,0,0,5,4,0]); - - let mut xs = [0,1,0,2,3,0,0,4,5,0,6,7]; - for slice in xs.split_mut(|x| *x == 0).take(5) { - slice.reverse(); - } - assert!(xs == [0,1,0,3,2,0,0,5,4,0,6,7]); - } - - #[test] - fn test_mut_splitator_rev() { - let mut xs = [1,2,0,3,4,0,0,5,6,0]; - for slice in xs.split_mut(|x| *x == 0).rev().take(4) { - slice.reverse(); - } - assert!(xs == [1,2,0,4,3,0,0,6,5,0]); - } - - #[test] - fn test_get_mut() { - let mut v = [0,1,2]; - assert_eq!(v.get_mut(3), None); - v.get_mut(1).map(|e| *e = 7); - assert_eq!(v[1], 7); - let mut x = 2; - assert_eq!(v.get_mut(2), Some(&mut x)); - } - - #[test] - fn test_mut_chunks() { - use core::iter::ExactSizeIterator; - - let mut v = [0u8, 1, 2, 3, 4, 5, 6]; - assert_eq!(v.chunks_mut(2).len(), 4); - for (i, chunk) in v.chunks_mut(3).enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0u8, 0, 0, 1, 1, 1, 2]; - assert!(v == result); - } - - #[test] - fn test_mut_chunks_rev() { - let mut v = [0u8, 1, 2, 3, 4, 5, 6]; - for (i, chunk) in v.chunks_mut(3).rev().enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [2u8, 2, 2, 1, 1, 1, 0]; - assert!(v == result); - } - - #[test] - #[should_fail] - fn test_mut_chunks_0() { - let mut v = [1, 2, 3, 4]; - let _it = v.chunks_mut(0); - } - - #[test] - fn test_mut_last() { - let mut x = [1, 2, 3, 4, 5]; - let h = x.last_mut(); - assert_eq!(*h.unwrap(), 5); - - let y: &mut [i32] = &mut []; - assert!(y.last_mut().is_none()); - } - - #[test] - fn test_to_vec() { - let xs = box [1, 2, 3]; - let ys = xs.to_vec(); - assert_eq!(ys, [1, 2, 3]); - } -} - -#[cfg(test)] -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}; - - #[bench] - fn iterator(b: &mut Bencher) { - // peculiar numbers to stop LLVM from optimising the summation - // out. - let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); - - b.iter(|| { - let mut sum = 0; - for x in &v { - sum += *x; - } - // sum == 11806, to stop dead code elimination. - if sum == 0 {panic!()} - }) - } - - #[bench] - fn mut_iterator(b: &mut Bencher) { - let mut v: Vec<_> = repeat(0).take(100).collect(); - - b.iter(|| { - let mut i = 0; - for x in &mut v { - *x = i; - i += 1; - } - }) - } - - #[bench] - fn concat(b: &mut Bencher) { - let xss: Vec> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.concat(); - }); - } - - #[bench] - fn connect(b: &mut Bencher) { - let xss: Vec> = - (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.connect(&0) - }); - } - - #[bench] - fn push(b: &mut Bencher) { - let mut vec = Vec::::new(); - b.iter(|| { - vec.push(0); - black_box(&vec); - }); - } - - #[bench] - fn starts_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.starts_with(&vec) - }) - } - - #[bench] - fn starts_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.starts_with(&vec) - }) - } - - #[bench] - fn starts_with_diff_one_element_at_end(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..99).collect(); - match_vec.push(0); - b.iter(|| { - vec.starts_with(&match_vec) - }) - } - - #[bench] - fn ends_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.ends_with(&vec) - }) - } - - #[bench] - fn ends_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| { - vec.ends_with(&vec) - }) - } - - #[bench] - fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..100).collect(); - match_vec[0] = 200; - b.iter(|| { - vec.starts_with(&match_vec) - }) - } - - #[bench] - fn contains_last_element(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| { - vec.contains(&99) - }) - } - - #[bench] - fn zero_1kb_from_elem(b: &mut Bencher) { - b.iter(|| { - repeat(0u8).take(1024).collect::>() - }); - } - - #[bench] - fn zero_1kb_set_memory(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::::with_capacity(1024); - unsafe { - let vp = v.as_mut_ptr(); - ptr::set_memory(vp, 0, 1024); - v.set_len(1024); - } - v - }); - } - - #[bench] - fn zero_1kb_loop_set(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for i in 0..1024 { - v[i] = 0; - } - }); - } - - #[bench] - fn zero_1kb_mut_iter(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for x in &mut v { - *x = 0; - } - v - }); - } - - #[bench] - fn random_inserts(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = repeat((0, 0)).take(30).collect(); - for _ in 0..100 { - let l = v.len(); - v.insert(rng.gen::() % (l + 1), - (1, 1)); - } - }) - } - #[bench] - fn random_removes(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = repeat((0, 0)).take(130).collect(); - for _ in 0..100 { - let l = v.len(); - v.remove(rng.gen::() % l); - } - }) - } - - #[bench] - fn sort_random_small(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::().take(5).collect(); - v.sort(); - }); - b.bytes = 5 * mem::size_of::() as u64; - } - - #[bench] - fn sort_random_medium(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::().take(100).collect(); - v.sort(); - }); - b.bytes = 100 * mem::size_of::() as u64; - } - - #[bench] - fn sort_random_large(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v: Vec<_> = rng.gen_iter::().take(10000).collect(); - v.sort(); - }); - b.bytes = 10000 * mem::size_of::() as u64; - } - - #[bench] - fn sort_sorted(b: &mut Bencher) { - let mut v: Vec<_> = (0..10000).collect(); - b.iter(|| { - v.sort(); - }); - b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; - } - - type BigSortable = (u64, u64, u64, u64); - - #[bench] - fn sort_big_random_small(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::().take(5) - .collect::>(); - v.sort(); - }); - b.bytes = 5 * mem::size_of::() as u64; - } - - #[bench] - fn sort_big_random_medium(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::().take(100) - .collect::>(); - v.sort(); - }); - b.bytes = 100 * mem::size_of::() as u64; - } - - #[bench] - fn sort_big_random_large(b: &mut Bencher) { - let mut rng = weak_rng(); - b.iter(|| { - let mut v = rng.gen_iter::().take(10000) - .collect::>(); - v.sort(); - }); - b.bytes = 10000 * mem::size_of::() as u64; - } - - #[bench] - fn sort_big_sorted(b: &mut Bencher) { - let mut v: Vec = (0..10000).map(|i| (i, i, i, i)).collect(); - b.iter(|| { - v.sort(); - }); - b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; - } -} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index ec0a487acd..c22b6fb928 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -10,43 +10,40 @@ // // ignore-lexer-test FIXME #15679 -//! Unicode string manipulation (`str` type) +//! Unicode string manipulation (the `str` type). //! -//! # Basic Usage +//! Rust's `str` type is one of the core primitive types of the language. `&str` +//! is the borrowed string type. This type of string can only be created from +//! other strings, unless it is a `&'static str` (see below). It is not possible +//! to move out of borrowed strings because they are owned elsewhere. //! -//! Rust's string type is one of the core primitive types of the language. While -//! represented by the name `str`, the name `str` is not actually a valid type in -//! Rust. Each string must also be decorated with a pointer. `String` is used -//! for an owned string, so there is only one commonly-used `str` type in Rust: -//! `&str`. +//! # Examples //! -//! `&str` is the borrowed string type. This type of string can only be created -//! from other strings, unless it is a static string (see below). As the word -//! "borrowed" implies, this type of string is owned elsewhere, and this string -//! cannot be moved out of. +//! Here's some code that uses a `&str`: //! -//! As an example, here's some code that uses a string. -//! -//! ```rust -//! fn main() { -//! let borrowed_string = "This string is borrowed with the 'static lifetime"; -//! } //! ``` +//! let s = "Hello, world."; +//! ``` +//! +//! This `&str` is a `&'static str`, which is the type of string literals. +//! They're `'static` because literals are available for the entire lifetime of +//! the program. +//! +//! You can get a non-`'static` `&str` by taking a slice of a `String`: //! -//! From the example above, you can guess that Rust's string literals have the -//! `'static` lifetime. This is akin to C's concept of a static string. -//! More precisely, string literals are immutable views with a 'static lifetime -//! (otherwise known as the lifetime of the entire program), and thus have the -//! type `&'static str`. +//! ``` +//! # let some_string = "Hello, world.".to_string(); +//! let s = &some_string; +//! ``` //! //! # Representation //! -//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a -//! stream of UTF-8 bytes. All [strings](../../reference.html#literals) are +//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as +//! a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are //! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are //! not null-terminated and can thus contain null bytes. //! -//! The actual representation of strings have direct mappings to slices: `&str` +//! The actual representation of `str`s have direct mappings to slices: `&str` //! is the same as `&[u8]`. #![doc(primitive = "str")] @@ -55,83 +52,77 @@ use self::RecompositionState::*; use self::DecompositionType::*; -use core::char::CharExt; use core::clone::Clone; use core::iter::AdditiveIterator; -use core::iter::{Iterator, IteratorExt}; -use core::ops::Index; -use core::ops::RangeFull; +use core::iter::{Iterator, Extend}; use core::option::Option::{self, Some, None}; use core::result::Result; -use core::slice::AsSlice; use core::str as core_str; use unicode::str::{UnicodeStr, Utf16Encoder}; +use core::convert::AsRef; use vec_deque::VecDeque; use borrow::{Borrow, ToOwned}; -use slice::SliceExt; use string::String; use unicode; use vec::Vec; use slice::SliceConcatExt; pub use core::str::{FromStr, Utf8Error, Str}; -pub use core::str::{Lines, LinesAny, MatchIndices, SplitStr, CharRange}; -pub use core::str::{Split, SplitTerminator}; -pub use core::str::{SplitN, RSplitN}; -pub use core::str::{from_utf8, CharEq, Chars, CharIndices, Bytes}; -pub use core::str::{from_utf8_unchecked, from_c_str, ParseBoolError}; +pub use core::str::{Lines, LinesAny, MatchIndices, CharRange}; +pub use core::str::{Split, SplitTerminator, SplitN}; +pub use core::str::{RSplit, RSplitN}; +pub use core::str::{from_utf8, Chars, CharIndices, Bytes}; +pub use core::str::{from_utf8_unchecked, ParseBoolError}; pub use unicode::str::{Words, Graphemes, GraphemeIndices}; +pub use core::str::Pattern; +pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep}; /* Section: Creating a string */ -impl SliceConcatExt for [S] { +impl> SliceConcatExt for [S] { fn concat(&self) -> String { - let s = self.as_slice(); - - if s.is_empty() { + if self.is_empty() { return String::new(); } // `len` calculation may overflow but push_str will check boundaries - let len = s.iter().map(|s| s.as_slice().len()).sum(); + let len = self.iter().map(|s| s.as_ref().len()).sum(); let mut result = String::with_capacity(len); - for s in s { - result.push_str(s.as_slice()) + for s in self { + result.push_str(s.as_ref()) } result } fn connect(&self, sep: &str) -> String { - let s = self.as_slice(); - - if s.is_empty() { + if self.is_empty() { return String::new(); } // concat is faster if sep.is_empty() { - return s.concat(); + return self.concat(); } // this is wrong without the guarantee that `self` is non-empty // `len` calculation may overflow but push_str but will check boundaries - let len = sep.len() * (s.len() - 1) - + s.iter().map(|s| s.as_slice().len()).sum(); + let len = sep.len() * (self.len() - 1) + + self.iter().map(|s| s.as_ref().len()).sum(); let mut result = String::with_capacity(len); let mut first = true; - for s in s { + for s in self { if first { first = false; } else { result.push_str(sep); } - result.push_str(s.as_slice()); + result.push_str(s.as_ref()); } result } @@ -164,10 +155,13 @@ enum DecompositionType { Compatible } -/// External iterator for a string's decomposition's characters. -/// Use with the `std::iter` module. +/// External iterator for a string decomposition's characters. +/// +/// For use with the `std::iter` module. #[derive(Clone)] -#[unstable(feature = "collections")] +#[unstable(feature = "unicode", + reason = "this functionality may be replaced with a more generic \ + unicode crate on crates.io")] pub struct Decompositions<'a> { kind: DecompositionType, iter: Chars<'a>, @@ -254,10 +248,13 @@ enum RecompositionState { Finished } -/// External iterator for a string's recomposition's characters. -/// Use with the `std::iter` module. +/// External iterator for a string recomposition's characters. +/// +/// For use with the `std::iter` module. #[derive(Clone)] -#[unstable(feature = "collections")] +#[unstable(feature = "unicode", + reason = "this functionality may be replaced with a more generic \ + unicode crate on crates.io")] pub struct Recompositions<'a> { iter: Decompositions<'a>, state: RecompositionState, @@ -352,7 +349,8 @@ impl<'a> Iterator for Recompositions<'a> { } /// External iterator for a string's UTF16 codeunits. -/// Use with the `std::iter` module. +/// +/// For use with the `std::iter` module. #[derive(Clone)] #[unstable(feature = "collections")] pub struct Utf16Units<'a> { @@ -383,7 +381,7 @@ macro_rules! utf8_first_byte { // return the value of $ch updated with continuation byte $byte macro_rules! utf8_acc_cont_byte { - ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32) + ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63) as u32) } #[stable(feature = "rust1", since = "1.0.0")] @@ -409,46 +407,47 @@ Section: CowString Section: Trait implementations */ + /// Any string that can be represented as a slice. +#[lang = "str"] +#[cfg(not(test))] #[stable(feature = "rust1", since = "1.0.0")] -pub trait StrExt: Index { +impl str { /// Escapes each char in `s` with `char::escape_default`. #[unstable(feature = "collections", reason = "return type may change to be an iterator")] - fn escape_default(&self) -> String { + pub fn escape_default(&self) -> String { self.chars().flat_map(|c| c.escape_default()).collect() } /// Escapes each char in `s` with `char::escape_unicode`. #[unstable(feature = "collections", reason = "return type may change to be an iterator")] - fn escape_unicode(&self) -> String { + pub fn escape_unicode(&self) -> String { self.chars().flat_map(|c| c.escape_unicode()).collect() } /// Replaces all occurrences of one string with another. /// - /// # Arguments - /// - /// * `from` - The string to replace - /// * `to` - The replacement string - /// - /// # Return value - /// - /// The original string with all occurrences of `from` replaced with `to`. + /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a second `&str` to + /// replace it with. If the original `&str` isn't found, no change occurs. /// /// # Examples /// - /// ```rust + /// ``` /// let s = "this is old"; /// /// assert_eq!(s.replace("old", "new"), "this is new"); + /// ``` + /// + /// When a `&str` isn't found: /// - /// // not found, so no change. + /// ``` + /// let s = "this is old"; /// assert_eq!(s.replace("cookie monster", "little lamb"), s); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn replace(&self, from: &str, to: &str) -> String { + pub fn replace(&self, from: &str, to: &str) -> String { let mut result = String::new(); let mut last_end = 0; for (start, end) in self.match_indices(from) { @@ -463,9 +462,10 @@ pub trait StrExt: Index { /// Returns an iterator over the string in Unicode Normalization Form D /// (canonical decomposition). #[inline] - #[unstable(feature = "collections", - reason = "this functionality may be moved to libunicode")] - fn nfd_chars(&self) -> Decompositions { + #[unstable(feature = "unicode", + reason = "this functionality may be replaced with a more generic \ + unicode crate on crates.io")] + pub fn nfd_chars(&self) -> Decompositions { Decompositions { iter: self[..].chars(), buffer: Vec::new(), @@ -477,9 +477,10 @@ pub trait StrExt: Index { /// Returns an iterator over the string in Unicode Normalization Form KD /// (compatibility decomposition). #[inline] - #[unstable(feature = "collections", - reason = "this functionality may be moved to libunicode")] - fn nfkd_chars(&self) -> Decompositions { + #[unstable(feature = "unicode", + reason = "this functionality may be replaced with a more generic \ + unicode crate on crates.io")] + pub fn nfkd_chars(&self) -> Decompositions { Decompositions { iter: self[..].chars(), buffer: Vec::new(), @@ -491,9 +492,10 @@ pub trait StrExt: Index { /// An Iterator over the string in Unicode Normalization Form C /// (canonical decomposition followed by canonical composition). #[inline] - #[unstable(feature = "collections", - reason = "this functionality may be moved to libunicode")] - fn nfc_chars(&self) -> Recompositions { + #[unstable(feature = "unicode", + reason = "this functionality may be replaced with a more generic \ + unicode crate on crates.io")] + pub fn nfc_chars(&self) -> Recompositions { Recompositions { iter: self.nfd_chars(), state: Composing, @@ -506,9 +508,10 @@ pub trait StrExt: Index { /// An Iterator over the string in Unicode Normalization Form KC /// (compatibility decomposition followed by canonical composition). #[inline] - #[unstable(feature = "collections", - reason = "this functionality may be moved to libunicode")] - fn nfkc_chars(&self) -> Recompositions { + #[unstable(feature = "unicode", + reason = "this functionality may be replaced with a more generic \ + unicode crate on crates.io")] + pub fn nfkc_chars(&self) -> Recompositions { Recompositions { iter: self.nfkd_chars(), state: Composing, @@ -518,400 +521,474 @@ pub trait StrExt: Index { } } - /// Returns true if a string contains a string pattern. + /// Returns `true` if `self` contains another `&str`. /// - /// # Arguments - /// - /// - pat - The string pattern to look for - /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert!("bananas".contains("nana")); + /// + /// assert!(!"bananas".contains("foobar")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn contains(&self, pat: &str) -> bool { + pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { core_str::StrExt::contains(&self[..], pat) } - /// Returns true if a string contains a char pattern. - /// - /// # Arguments + /// An iterator over the codepoints of `self`. /// - /// - pat - The char pattern to look for - /// - /// # Example + /// # Examples /// - /// ```rust - /// assert!("hello".contains_char('e')); /// ``` - #[unstable(feature = "collections", - reason = "might get removed in favour of a more generic contains()")] - fn contains_char(&self, pat: P) -> bool { - core_str::StrExt::contains_char(&self[..], pat) - } - - /// An iterator over the characters of `self`. Note, this iterates - /// over Unicode code-points, not Unicode graphemes. - /// - /// # Example - /// - /// ```rust /// let v: Vec = "abc åäö".chars().collect(); - /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); + /// + /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn chars(&self) -> Chars { + pub fn chars(&self) -> Chars { core_str::StrExt::chars(&self[..]) } - /// An iterator over the bytes of `self` + /// An iterator over the bytes of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let v: Vec = "bors".bytes().collect(); + /// /// assert_eq!(v, b"bors".to_vec()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn bytes(&self) -> Bytes { + pub fn bytes(&self) -> Bytes { core_str::StrExt::bytes(&self[..]) } /// An iterator over the characters of `self` and their byte offsets. + /// + /// # Examples + /// + /// ``` + /// let v: Vec<(usize, char)> = "abc".char_indices().collect(); + /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')]; + /// + /// assert_eq!(v, b); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn char_indices(&self) -> CharIndices { + pub fn char_indices(&self) -> CharIndices { core_str::StrExt::char_indices(&self[..]) } /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`. + /// matched by a pattern. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. /// - /// ```rust + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); - /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); + /// + /// let v: Vec<&str> = "".split('X').collect(); + /// assert_eq!(v, [""]); + /// ``` /// + /// More complex patterns with a lambda: + /// + /// ``` /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["abc", "def", "ghi"]); + /// assert_eq!(v, ["abc", "def", "ghi"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect(); - /// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]); - /// - /// let v: Vec<&str> = "".split('X').collect(); - /// assert_eq!(v, vec![""]); + /// assert_eq!(v, ["lion", "", "tiger", "leopard"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn split(&self, pat: P) -> Split

{ + pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { core_str::StrExt::split(&self[..], pat) } - /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`, restricted to splitting at most `count` - /// times. + /// An iterator over substrings of `self`, separated by characters matched + /// by a pattern, returning most `count` items. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. /// - /// ```rust - /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); - /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]); + /// The last element returned, if any, will contain the remainder of the + /// string. + /// + /// # Examples + /// + /// Simple `&str` patterns: /// - /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["abc", "def2ghi"]); + /// ``` + /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect(); + /// assert_eq!(v, ["Mary", "had a little lambda"]); /// /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect(); - /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]); + /// assert_eq!(v, ["lion", "XtigerXleopard"]); /// - /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect(); - /// assert_eq!(v, vec!["abcXdef"]); + /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect(); + /// assert_eq!(v, ["abcXdef"]); /// /// let v: Vec<&str> = "".splitn(1, 'X').collect(); - /// assert_eq!(v, vec![""]); + /// assert_eq!(v, [""]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".splitn(2, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def2ghi"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn splitn(&self, count: usize, pat: P) -> SplitN

{ + pub fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { core_str::StrExt::splitn(&self[..], count, pat) } /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`. + /// matched by a pattern. /// - /// Equivalent to `split`, except that the trailing substring - /// is skipped if empty (terminator semantics). + /// Equivalent to `split`, except that the trailing substring is skipped if empty. /// - /// # Example + /// The pattern can be a simple `&str`, or a closure that determines + /// the split. /// - /// ```rust + /// # Examples + /// + /// Simple `&str` patterns: + /// + /// ``` /// let v: Vec<&str> = "A.B.".split_terminator('.').collect(); - /// assert_eq!(v, vec!["A", "B"]); + /// assert_eq!(v, ["A", "B"]); /// /// let v: Vec<&str> = "A..B..".split_terminator('.').collect(); - /// assert_eq!(v, vec!["A", "", "B", ""]); - /// - /// let v: Vec<&str> = "Mary had a little lamb".split(' ').rev().collect(); - /// assert_eq!(v, vec!["lamb", "little", "a", "had", "Mary"]); + /// assert_eq!(v, ["A", "", "B", ""]); + /// ``` /// - /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).rev().collect(); - /// assert_eq!(v, vec!["ghi", "def", "abc"]); + /// More complex patterns with a lambda: /// - /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect(); - /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]); /// ``` - #[unstable(feature = "collections", reason = "might get removed")] - fn split_terminator(&self, pat: P) -> SplitTerminator

{ + /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["abc", "def", "ghi"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { core_str::StrExt::split_terminator(&self[..], pat) } - /// An iterator over substrings of `self`, separated by characters - /// matched by the pattern `pat`, starting from the end of the string. - /// Restricted to splitting at most `count` times. + /// An iterator over substrings of `self`, separated by a pattern, + /// starting from the end of the string. /// - /// # Example + /// # Examples /// - /// ```rust - /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect(); - /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]); + /// Simple patterns: /// - /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect(); - /// assert_eq!(v, vec!["ghi", "abc1def"]); + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect(); + /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect(); + /// assert_eq!(v, ["leopard", "tiger", "lion"]); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".rsplit(|c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["ghi", "def", "abc"]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + core_str::StrExt::rsplit(&self[..], pat) + } + + /// An iterator over substrings of `self`, separated by a pattern, + /// starting from the end of the string, restricted to returning + /// at most `count` items. + /// + /// The last element returned, if any, will contain the remainder of the + /// string. + /// + /// # Examples + /// + /// Simple patterns: + /// + /// ``` + /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect(); + /// assert_eq!(v, ["lamb", "little", "Mary had a"]); + /// + /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect(); + /// assert_eq!(v, ["leopard", "lion::tiger"]); + /// ``` + /// + /// More complex patterns with a lambda: /// - /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect(); - /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]); + /// ``` + /// let v: Vec<&str> = "abc1def2ghi".rsplitn(2, |c: char| c.is_numeric()).collect(); + /// assert_eq!(v, ["ghi", "abc1def"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn rsplitn(&self, count: usize, pat: P) -> RSplitN

{ + pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> + where P::Searcher: ReverseSearcher<'a> + { core_str::StrExt::rsplitn(&self[..], count, pat) } - /// An iterator over the start and end indices of the disjoint - /// matches of the pattern `pat` within `self`. + /// An iterator over the start and end indices of the disjoint matches of a `&str` within + /// `self`. /// - /// That is, each returned value `(start, end)` satisfies - /// `self.slice(start, end) == sep`. For matches of `sep` within - /// `self` that overlap, only the indices corresponding to the - /// first match are returned. + /// That is, each returned value `(start, end)` satisfies `self.slice(start, end) == sep`. For + /// matches of `sep` within `self` that overlap, only the indices corresponding to the first + /// match are returned. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(collections)] /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, vec![(0,3), (6,9), (12,15)]); + /// assert_eq!(v, [(0,3), (6,9), (12,15)]); /// /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, vec![(1,4), (4,7)]); + /// assert_eq!(v, [(1,4), (4,7)]); /// /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, vec![(0, 3)]); // only the first `aba` + /// assert_eq!(v, [(0, 3)]); // only the first `aba` /// ``` #[unstable(feature = "collections", reason = "might have its iterator type changed")] - fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> { + // NB: Right now MatchIndices yields `(usize, usize)`, + // but it would be more consistent and useful to return `(usize, &str)` + pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { core_str::StrExt::match_indices(&self[..], pat) } - /// An iterator over the substrings of `self` separated by the pattern `sep`. + /// An iterator over the lines of a string, separated by `\n`. /// - /// # Example + /// This does not include the empty string after a trailing `\n`. /// - /// ```rust - /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect(); - /// assert_eq!(v, vec!["", "XXX", "YYY", ""]); + /// # Examples /// - /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect(); - /// assert_eq!(v, vec!["1", "", "2"]); /// ``` - #[unstable(feature = "collections", - reason = "might get removed in the future in favor of a more generic split()")] - fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a> { - core_str::StrExt::split_str(&self[..], pat) - } - - /// An iterator over the lines of a string (subsequences separated - /// by `\n`). This does not include the empty string after a - /// trailing `\n`. + /// let four_lines = "foo\nbar\n\nbaz"; + /// let v: Vec<&str> = four_lines.lines().collect(); /// - /// # Example + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` /// - /// ```rust + /// Leaving off the trailing character: + /// + /// ``` /// let four_lines = "foo\nbar\n\nbaz\n"; /// let v: Vec<&str> = four_lines.lines().collect(); - /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn lines(&self) -> Lines { + pub fn lines(&self) -> Lines { core_str::StrExt::lines(&self[..]) } - /// An iterator over the lines of a string, separated by either - /// `\n` or `\r\n`. As with `.lines()`, this does not include an - /// empty trailing line. + /// An iterator over the lines of a string, separated by either `\n` or `\r\n`. /// - /// # Example + /// As with `.lines()`, this does not include an empty trailing line. /// - /// ```rust + /// # Examples + /// + /// ``` + /// let four_lines = "foo\r\nbar\n\r\nbaz"; + /// let v: Vec<&str> = four_lines.lines_any().collect(); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); + /// ``` + /// + /// Leaving off the trailing character: + /// + /// ``` /// let four_lines = "foo\r\nbar\n\r\nbaz\n"; /// let v: Vec<&str> = four_lines.lines_any().collect(); - /// assert_eq!(v, vec!["foo", "bar", "", "baz"]); + /// + /// assert_eq!(v, ["foo", "bar", "", "baz"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn lines_any(&self) -> LinesAny { + pub fn lines_any(&self) -> LinesAny { core_str::StrExt::lines_any(&self[..]) } - - /// Deprecated: use `s[a .. b]` instead. - #[unstable(feature = "collections", - reason = "use slice notation [a..b] instead")] - #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")] - fn slice(&self, begin: usize, end: usize) -> &str; - - /// Deprecated: use `s[a..]` instead. - #[unstable(feature = "collections", - reason = "use slice notation [a..b] instead")] - #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")] - fn slice_from(&self, begin: usize) -> &str; - - /// Deprecated: use `s[..a]` instead. - #[unstable(feature = "collections", - reason = "use slice notation [a..b] instead")] - #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")] - fn slice_to(&self, end: usize) -> &str; - - /// Returns a slice of the string from the character range - /// [`begin`..`end`). + /// Returns a slice of the string from the character range [`begin`..`end`). /// - /// That is, start at the `begin`-th code point of the string and - /// continue to the `end`-th code point. This does not detect or - /// handle edge cases such as leaving a combining character as the - /// first code point of the string. + /// That is, start at the `begin`-th code point of the string and continue + /// to the `end`-th code point. This does not detect or handle edge cases + /// such as leaving a combining character as the first code point of the + /// string. /// - /// Due to the design of UTF-8, this operation is `O(end)`. - /// See `slice`, `slice_to` and `slice_from` for `O(1)` - /// variants that use byte indices rather than code point - /// indices. + /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`, + /// `slice_to` and `slice_from` for `O(1)` variants that use byte indices + /// rather than code point indices. /// - /// Panics if `begin` > `end` or the either `begin` or `end` are - /// beyond the last character of the string. + /// # Panics /// - /// # Example + /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the + /// last character of the string. /// - /// ```rust + /// # Examples + /// + /// ``` + /// # #![feature(collections)] /// let s = "Löwe 老虎 Léopard"; + /// /// assert_eq!(s.slice_chars(0, 4), "Löwe"); /// assert_eq!(s.slice_chars(5, 7), "老虎"); /// ``` #[unstable(feature = "collections", reason = "may have yet to prove its worth")] - fn slice_chars(&self, begin: usize, end: usize) -> &str { + pub fn slice_chars(&self, begin: usize, end: usize) -> &str { core_str::StrExt::slice_chars(&self[..], begin, end) } - /// Takes a bytewise (not UTF-8) slice from a string. + /// Takes a bytewise slice from a string. /// /// Returns the substring from [`begin`..`end`). /// - /// Caller must check both UTF-8 character boundaries and the boundaries of - /// the entire slice as well. + /// # Unsafety + /// + /// Caller must check both UTF-8 character boundaries and the boundaries of the entire slice as + /// well. + /// + /// # Examples + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// + /// unsafe { + /// assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard"); + /// } + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { + pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { core_str::StrExt::slice_unchecked(&self[..], begin, end) } - /// Returns true if the pattern `pat` is a prefix of the string. + /// Returns `true` if the given `&str` is a prefix of the string. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert!("banana".starts_with("ba")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn starts_with(&self, pat: &str) -> bool { + pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { core_str::StrExt::starts_with(&self[..], pat) } - /// Returns true if the pattern `pat` is a suffix of the string. + /// Returns true if the given `&str` is a suffix of the string. /// - /// # Example + /// # Examples /// /// ```rust /// assert!("banana".ends_with("nana")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn ends_with(&self, pat: &str) -> bool { + pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { core_str::StrExt::ends_with(&self[..], pat) } - /// Returns a string with all pre- and suffixes that match - /// the pattern `pat` repeatedly removed. + /// Returns a string with all pre- and suffixes that match a pattern repeatedly removed. /// - /// # Arguments + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// * pat - a string pattern + /// # Examples /// - /// # Example + /// Simple `&str` patterns: /// - /// ```rust + /// ``` /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + /// /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn trim_matches(&self, pat: P) -> &str { + pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { core_str::StrExt::trim_matches(&self[..], pat) } - /// Returns a string with all prefixes that match - /// the pattern `pat` repeatedly removed. + /// Returns a string with all prefixes that match a pattern repeatedly removed. /// - /// # Arguments + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// * pat - a string pattern + /// # Examples /// - /// # Example + /// Simple `&str` patterns: /// - /// ```rust + /// ``` /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + /// /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn trim_left_matches(&self, pat: P) -> &str { + pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { core_str::StrExt::trim_left_matches(&self[..], pat) } - /// Returns a string with all suffixes that match - /// the pattern `pat` repeatedly removed. + /// Returns a string with all suffixes that match a pattern repeatedly removed. /// - /// # Arguments + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// * pat - a string pattern + /// # Examples /// - /// # Example + /// Simple `&str` patterns: /// - /// ```rust + /// ``` /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); /// let x: &[_] = &['1', '2']; /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar"); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` /// assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn trim_right_matches(&self, pat: P) -> &str { + pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { core_str::StrExt::trim_right_matches(&self[..], pat) } - /// Check that `index`-th byte lies at the start and/or end of a - /// UTF-8 code point sequence. + /// Check that `index`-th byte lies at the start and/or end of a UTF-8 code point sequence. /// - /// The start and end of the string (when `index == self.len()`) - /// are considered to be boundaries. + /// The start and end of the string (when `index == self.len()`) are considered to be + /// boundaries. + /// + /// # Panics /// /// Panics if `index` is greater than `self.len()`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(str_char)] /// let s = "Löwe 老虎 Léopard"; /// assert!(s.is_char_boundary(0)); /// // start of `老` @@ -924,25 +1001,31 @@ pub trait StrExt: Index { /// // third byte of `老` /// assert!(!s.is_char_boundary(8)); /// ``` - #[unstable(feature = "collections", - reason = "naming is uncertain with container conventions")] - fn is_char_boundary(&self, index: usize) -> bool { + #[unstable(feature = "str_char", + reason = "it is unclear whether this method pulls its weight \ + with the existence of the char_indices iterator or \ + this method may want to be replaced with checked \ + slicing")] + pub fn is_char_boundary(&self, index: usize) -> bool { core_str::StrExt::is_char_boundary(&self[..], index) } - /// Pluck a character out of a string and return the index of the next - /// character. + /// Given a byte position, return the next char and its index. /// - /// This function can be used to iterate over the Unicode characters of a - /// string. + /// This can be used to iterate over the Unicode characters of a string. /// - /// # Example + /// # Panics /// - /// This example manually iterates through the characters of a - /// string; this should normally be done by `.chars()` or - /// `.char_indices`. + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. /// - /// ```rust + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars()` or `.char_indices()`. + /// + /// ``` + /// # #![feature(str_char, core)] /// use std::str::CharRange; /// /// let s = "中华Việt Nam"; @@ -968,28 +1051,15 @@ pub trait StrExt: Index { /// 14: a /// 15: m /// ``` - /// - /// # Arguments - /// - /// * s - The string - /// * i - The byte offset of the char to extract - /// - /// # Return value - /// - /// A record {ch: char, next: usize} containing the char value and the byte - /// index of the next Unicode character. - /// - /// # Panics - /// - /// If `i` is greater than or equal to the length of the string. - /// If `i` is not the index of the beginning of a valid UTF-8 character. - #[unstable(feature = "collections", - reason = "naming is uncertain with container conventions")] - fn char_range_at(&self, start: usize) -> CharRange { + #[unstable(feature = "str_char", + reason = "often replaced by char_indices, this method may \ + be removed in favor of just char_at() or eventually \ + removed altogether")] + pub fn char_range_at(&self, start: usize) -> CharRange { core_str::StrExt::char_range_at(&self[..], start) } - /// Given a byte position and a str, return the previous char and its position. + /// Given a byte position, return the previous `char` and its position. /// /// This function can be used to iterate over a Unicode string in reverse. /// @@ -999,169 +1069,228 @@ pub trait StrExt: Index { /// /// If `i` is greater than the length of the string. /// If `i` is not an index following a valid UTF-8 character. - #[unstable(feature = "collections", - reason = "naming is uncertain with container conventions")] - fn char_range_at_reverse(&self, start: usize) -> CharRange { - core_str::StrExt::char_range_at_reverse(&self[..], start) - } - - /// Plucks the character starting at the `i`th byte of a string. /// - /// # Example + /// # Examples + /// + /// This example manually iterates through the characters of a string; this should normally be + /// done by `.chars().rev()` or `.char_indices()`. /// - /// ```rust - /// let s = "abπc"; - /// assert_eq!(s.char_at(1), 'b'); - /// assert_eq!(s.char_at(2), 'π'); - /// assert_eq!(s.char_at(4), 'c'); /// ``` + /// # #![feature(str_char, core)] + /// use std::str::CharRange; /// - /// # Panics + /// let s = "中华Việt Nam"; + /// let mut i = s.len(); + /// while i > 0 { + /// let CharRange {ch, next} = s.char_range_at_reverse(i); + /// println!("{}: {}", i, ch); + /// i = next; + /// } + /// ``` /// - /// If `i` is greater than or equal to the length of the string. - /// If `i` is not the index of the beginning of a valid UTF-8 character. - #[unstable(feature = "collections", - reason = "naming is uncertain with container conventions")] - fn char_at(&self, i: usize) -> char { - core_str::StrExt::char_at(&self[..], i) + /// This outputs: + /// + /// ```text + /// 16: m + /// 15: a + /// 14: N + /// 13: + /// 12: t + /// 11: ệ + /// 8: i + /// 7: V + /// 6: 华 + /// 3: 中 + /// ``` + #[unstable(feature = "str_char", + reason = "often replaced by char_indices, this method may \ + be removed in favor of just char_at_reverse() or \ + eventually removed altogether")] + pub fn char_range_at_reverse(&self, start: usize) -> CharRange { + core_str::StrExt::char_range_at_reverse(&self[..], start) } - /// Plucks the character ending at the `i`th byte of a string. + /// Given a byte position, return the `char` at that position. + /// + /// # Panics + /// + /// If `i` is greater than or equal to the length of the string. + /// If `i` is not the index of the beginning of a valid UTF-8 character. + /// + /// # Examples + /// + /// ``` + /// # #![feature(str_char)] + /// let s = "abπc"; + /// assert_eq!(s.char_at(1), 'b'); + /// assert_eq!(s.char_at(2), 'π'); + /// ``` + #[unstable(feature = "str_char", + reason = "frequently replaced by the chars() iterator, this \ + method may be removed or possibly renamed in the \ + future; it is normally replaced by chars/char_indices \ + iterators or by getting the first char from a \ + subslice")] + pub fn char_at(&self, i: usize) -> char { + core_str::StrExt::char_at(&self[..], i) + } + + /// Given a byte position, return the `char` at that position, counting from the end. /// /// # Panics /// /// If `i` is greater than the length of the string. /// If `i` is not an index following a valid UTF-8 character. - #[unstable(feature = "collections", - reason = "naming is uncertain with container conventions")] - fn char_at_reverse(&self, i: usize) -> char { + /// + /// # Examples + /// + /// ``` + /// # #![feature(str_char)] + /// let s = "abπc"; + /// assert_eq!(s.char_at_reverse(1), 'a'); + /// assert_eq!(s.char_at_reverse(2), 'b'); + /// ``` + #[unstable(feature = "str_char", + reason = "see char_at for more details, but reverse semantics \ + are also somewhat unclear, especially with which \ + cases generate panics")] + pub fn char_at_reverse(&self, i: usize) -> char { core_str::StrExt::char_at_reverse(&self[..], i) } - /// Work with the byte buffer of a string as a byte slice. + /// Convert `self` to a byte slice. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// assert_eq!("bors".as_bytes(), b"bors"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn as_bytes(&self) -> &[u8] { + pub fn as_bytes(&self) -> &[u8] { core_str::StrExt::as_bytes(&self[..]) } - /// Returns the byte index of the first character of `self` that - /// matches the pattern `pat`. + /// Returns the byte index of the first character of `self` that matches the pattern, if it + /// exists. /// - /// # Return value + /// Returns `None` if it doesn't exist. /// - /// `Some` containing the byte index of the last matching character - /// or `None` if there is no match + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// # Example + /// # Examples /// - /// ```rust + /// Simple `&str` patterns: + /// + /// ``` /// let s = "Löwe 老虎 Léopard"; /// /// assert_eq!(s.find('L'), Some(0)); /// assert_eq!(s.find('é'), Some(14)); /// - /// // the first space + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; + /// /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5)); + /// ``` /// - /// // neither are found + /// Not finding the pattern: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; /// let x: &[_] = &['1', '2']; + /// /// assert_eq!(s.find(x), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn find(&self, pat: P) -> Option { + pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { core_str::StrExt::find(&self[..], pat) } - /// Returns the byte index of the last character of `self` that - /// matches the pattern `pat`. + /// Returns the byte index of the last character of `self` that matches the pattern, if it + /// exists. /// - /// # Return value + /// Returns `None` if it doesn't exist. /// - /// `Some` containing the byte index of the last matching character - /// or `None` if there is no match. + /// The pattern can be a simple `&str`, or a closure that determines the split. /// - /// # Example + /// # Examples /// - /// ```rust + /// Simple `&str` patterns: + /// + /// ``` /// let s = "Löwe 老虎 Léopard"; /// /// assert_eq!(s.rfind('L'), Some(13)); /// assert_eq!(s.rfind('é'), Some(14)); + /// ``` + /// + /// More complex patterns with a lambda: + /// + /// ``` + /// let s = "Löwe 老虎 Léopard"; /// - /// // the second space /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12)); + /// ``` + /// + /// Not finding the pattern: /// - /// // searches for an occurrence of either `1` or `2`, but neither are found + /// ``` + /// let s = "Löwe 老虎 Léopard"; /// let x: &[_] = &['1', '2']; + /// /// assert_eq!(s.rfind(x), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn rfind(&self, pat: P) -> Option { + pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option + where P::Searcher: ReverseSearcher<'a> + { core_str::StrExt::rfind(&self[..], pat) } - /// Returns the byte index of the first matching substring - /// - /// # Arguments + /// Retrieves the first character from a `&str` and returns it. /// - /// * `needle` - The string to search for + /// This does not allocate a new string; instead, it returns a slice that points one character + /// beyond the character that was shifted. /// - /// # Return value - /// - /// `Some` containing the byte index of the first matching substring - /// or `None` if there is no match. - /// - /// # Example + /// If the slice does not contain any characters, None is returned instead. /// - /// ```rust - /// let s = "Löwe 老虎 Léopard"; + /// # Examples /// - /// assert_eq!(s.find_str("老虎 L"), Some(6)); - /// assert_eq!(s.find_str("muffin man"), None); /// ``` - #[unstable(feature = "collections", - reason = "might get removed in favor of a more generic find in the future")] - fn find_str(&self, needle: &str) -> Option { - core_str::StrExt::find_str(&self[..], needle) - } - - /// Retrieves the first character from a string slice and returns - /// it. This does not allocate a new string; instead, it returns a - /// slice that point one character beyond the character that was - /// shifted. If the string does not contain any characters, - /// None is returned instead. - /// - /// # Example - /// - /// ```rust + /// # #![feature(str_char)] /// let s = "Löwe 老虎 Léopard"; /// let (c, s1) = s.slice_shift_char().unwrap(); + /// /// assert_eq!(c, 'L'); /// assert_eq!(s1, "öwe 老虎 Léopard"); /// /// let (c, s2) = s1.slice_shift_char().unwrap(); + /// /// assert_eq!(c, 'ö'); /// assert_eq!(s2, "we 老虎 Léopard"); /// ``` - #[unstable(feature = "collections", - reason = "awaiting conventions about shifting and slices")] - fn slice_shift_char(&self) -> Option<(char, &str)> { + #[unstable(feature = "str_char", + reason = "awaiting conventions about shifting and slices and \ + may not be warranted with the existence of the chars \ + and/or char_indices iterators")] + pub fn slice_shift_char(&self) -> Option<(char, &str)> { core_str::StrExt::slice_shift_char(&self[..]) } /// Returns the byte offset of an inner slice relative to an enclosing outer slice. /// + /// # Panics + /// /// Panics if `inner` is not a direct slice contained within self. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(collections)] /// let string = "a\nb\nc"; /// let lines: Vec<&str> = string.lines().collect(); /// @@ -1171,1870 +1300,228 @@ pub trait StrExt: Index { /// ``` #[unstable(feature = "collections", reason = "awaiting convention about comparability of arbitrary slices")] - fn subslice_offset(&self, inner: &str) -> usize { + pub fn subslice_offset(&self, inner: &str) -> usize { core_str::StrExt::subslice_offset(&self[..], inner) } - /// Return an unsafe pointer to the strings buffer. + /// Return an unsafe pointer to the `&str`'s buffer. + /// + /// The caller must ensure that the string outlives this pointer, and that it is not + /// reallocated (e.g. by pushing to the string). /// - /// The caller must ensure that the string outlives this pointer, - /// and that it is not reallocated (e.g. by pushing to the - /// string). + /// # Examples + /// + /// ``` + /// let s = "Hello"; + /// let p = s.as_ptr(); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - fn as_ptr(&self) -> *const u8 { + pub fn as_ptr(&self) -> *const u8 { core_str::StrExt::as_ptr(&self[..]) } /// Return an iterator of `u16` over the string encoded as UTF-16. #[unstable(feature = "collections", reason = "this functionality may only be provided by libunicode")] - fn utf16_units(&self) -> Utf16Units { + pub fn utf16_units(&self) -> Utf16Units { Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) } } - /// Return the number of bytes in this string + /// Returns the length of `self` in bytes. /// - /// # Example + /// # Examples /// /// ``` /// assert_eq!("foo".len(), 3); - /// assert_eq!("ƒoo".len(), 4); + /// assert_eq!("ƒoo".len(), 4); // fancy f! /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - fn len(&self) -> usize { + pub fn len(&self) -> usize { core_str::StrExt::len(&self[..]) } - /// Returns true if this slice contains no bytes + /// Returns true if this slice has a length of zero bytes. /// - /// # Example + /// # Examples /// /// ``` /// assert!("".is_empty()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { core_str::StrExt::is_empty(&self[..]) } - /// Parse this string into the specified type. + /// Parses `self` into the specified type. + /// + /// # Failure + /// + /// Will return `Err` if it's not possible to parse `self` into the type. /// /// # Example /// /// ``` /// assert_eq!("4".parse::(), Ok(4)); + /// ``` + /// + /// Failing: + /// + /// ``` /// assert!("j".parse::().is_err()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn parse(&self) -> Result { + pub fn parse(&self) -> Result { core_str::StrExt::parse(&self[..]) } - /// Returns an iterator over the - /// [grapheme clusters](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) - /// of the string. + /// Returns an iterator over the [grapheme clusters][graphemes] of `self`. + /// + /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries /// /// If `is_extended` is true, the iterator is over the *extended grapheme clusters*; /// otherwise, the iterator is over the *legacy grapheme clusters*. /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) /// recommends extended grapheme cluster boundaries for general processing. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(unicode, core)] /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::>(); /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"]; - /// assert_eq!(gr1.as_slice(), b); + /// + /// assert_eq!(&gr1[..], b); + /// /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; - /// assert_eq!(gr2.as_slice(), b); + /// + /// assert_eq!(&gr2[..], b); /// ``` - #[unstable(feature = "collections", + #[unstable(feature = "unicode", reason = "this functionality may only be provided by libunicode")] - fn graphemes(&self, is_extended: bool) -> Graphemes { + pub fn graphemes(&self, is_extended: bool) -> Graphemes { UnicodeStr::graphemes(&self[..], is_extended) } - /// Returns an iterator over the grapheme clusters of self and their byte offsets. - /// See `graphemes()` method for more information. + /// Returns an iterator over the grapheme clusters of `self` and their byte offsets. See + /// `graphemes()` for more information. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(unicode, core)] /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::>(); /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; - /// assert_eq!(gr_inds.as_slice(), b); + /// + /// assert_eq!(&gr_inds[..], b); /// ``` - #[unstable(feature = "collections", + #[unstable(feature = "unicode", reason = "this functionality may only be provided by libunicode")] - fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices { + pub fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices { UnicodeStr::grapheme_indices(&self[..], is_extended) } - /// An iterator over the words of a string (subsequences separated - /// by any sequence of whitespace). Sequences of whitespace are - /// collapsed, so empty "words" are not included. + /// An iterator over the non-empty words of `self`. /// - /// # Example + /// A 'word' is a subsequence separated by any sequence of whitespace. Sequences of whitespace + /// are collapsed, so empty "words" are not included. /// - /// ```rust + /// # Examples + /// + /// ``` + /// # #![feature(str_words)] /// let some_words = " Mary had\ta little \n\t lamb"; /// let v: Vec<&str> = some_words.words().collect(); - /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); + /// + /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]); /// ``` #[unstable(feature = "str_words", reason = "the precise algorithm to use is unclear")] - fn words(&self) -> Words { + pub fn words(&self) -> Words { UnicodeStr::words(&self[..]) } - /// Returns a string's displayed width in columns, treating control - /// characters as zero-width. + /// Returns a string's displayed width in columns. /// - /// `is_cjk` determines behavior for characters in the Ambiguous category: - /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1. - /// In CJK locales, `is_cjk` should be `true`, else it should be `false`. - /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) - /// recommends that these characters be treated as 1 column (i.e., - /// `is_cjk` = `false`) if the locale is unknown. - #[unstable(feature = "collections", + /// Control characters have zero width. + /// + /// `is_cjk` determines behavior for characters in the Ambiguous category: if `is_cjk` is + /// `true`, these are 2 columns wide; otherwise, they are 1. In CJK locales, `is_cjk` should be + /// `true`, else it should be `false`. + /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) recommends that these + /// characters be treated as 1 column (i.e., `is_cjk = false`) if the locale is unknown. + #[unstable(feature = "unicode", reason = "this functionality may only be provided by libunicode")] - fn width(&self, is_cjk: bool) -> usize { + pub fn width(&self, is_cjk: bool) -> usize { UnicodeStr::width(&self[..], is_cjk) } - /// Returns a string with leading and trailing whitespace removed. + /// Returns a `&str` with leading and trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim(), "Hello\tworld"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn trim(&self) -> &str { + pub fn trim(&self) -> &str { UnicodeStr::trim(&self[..]) } - /// Returns a string with leading whitespace removed. + /// Returns a `&str` with leading whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_left(), "Hello\tworld\t"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn trim_left(&self) -> &str { + pub fn trim_left(&self) -> &str { UnicodeStr::trim_left(&self[..]) } - /// Returns a string with trailing whitespace removed. + /// Returns a `&str` with trailing whitespace removed. + /// + /// # Examples + /// + /// ``` + /// let s = " Hello\tworld\t"; + /// assert_eq!(s.trim_right(), " Hello\tworld"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn trim_right(&self) -> &str { + pub fn trim_right(&self) -> &str { UnicodeStr::trim_right(&self[..]) } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl StrExt for str { - fn slice(&self, begin: usize, end: usize) -> &str { - &self[begin..end] - } - - fn slice_from(&self, begin: usize) -> &str { - &self[begin..] - } - - fn slice_to(&self, end: usize) -> &str { - &self[..end] - } -} - -#[cfg(test)] -mod tests { - use prelude::*; - - use core::iter::AdditiveIterator; - use super::from_utf8; - use super::Utf8Error; - - #[test] - fn test_le() { - assert!("" <= ""); - assert!("" <= "foo"); - assert!("foo" <= "foo"); - assert!("foo" != "bar"); - } - - #[test] - fn test_len() { - assert_eq!("".len(), 0); - assert_eq!("hello world".len(), 11); - assert_eq!("\x63".len(), 1); - assert_eq!("\u{a2}".len(), 2); - assert_eq!("\u{3c0}".len(), 2); - assert_eq!("\u{2620}".len(), 3); - assert_eq!("\u{1d11e}".len(), 4); - - assert_eq!("".chars().count(), 0); - assert_eq!("hello world".chars().count(), 11); - assert_eq!("\x63".chars().count(), 1); - assert_eq!("\u{a2}".chars().count(), 1); - assert_eq!("\u{3c0}".chars().count(), 1); - assert_eq!("\u{2620}".chars().count(), 1); - assert_eq!("\u{1d11e}".chars().count(), 1); - assert_eq!("ประเทศไทย中华Việt Nam".chars().count(), 19); - - assert_eq!("hello".width(false), 10); - assert_eq!("hello".width(true), 10); - assert_eq!("\0\0\0\0\0".width(false), 0); - assert_eq!("\0\0\0\0\0".width(true), 0); - assert_eq!("".width(false), 0); - assert_eq!("".width(true), 0); - assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(false), 4); - assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(true), 8); - } - - #[test] - fn test_find() { - assert_eq!("hello".find('l'), Some(2)); - assert_eq!("hello".find(|c:char| c == 'o'), Some(4)); - assert!("hello".find('x').is_none()); - assert!("hello".find(|c:char| c == 'x').is_none()); - assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); - assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); - } - - #[test] - fn test_rfind() { - assert_eq!("hello".rfind('l'), Some(3)); - assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4)); - assert!("hello".rfind('x').is_none()); - assert!("hello".rfind(|c:char| c == 'x').is_none()); - assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); - assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); - } - - #[test] - fn test_collect() { - let empty = String::from_str(""); - let s: String = empty.chars().collect(); - assert_eq!(empty, s); - let data = String::from_str("ประเทศไทย中"); - let s: String = data.chars().collect(); - assert_eq!(data, s); - } - - #[test] - fn test_into_bytes() { - let data = String::from_str("asdf"); - let buf = data.into_bytes(); - assert_eq!(b"asdf", buf); - } - - #[test] - fn test_find_str() { - // byte positions - assert_eq!("".find_str(""), Some(0)); - assert!("banana".find_str("apple pie").is_none()); - - let data = "abcabc"; - assert_eq!(data[0..6].find_str("ab"), Some(0)); - assert_eq!(data[2..6].find_str("ab"), Some(3 - 2)); - assert!(data[2..4].find_str("ab").is_none()); - - let string = "ประเทศไทย中华Việt Nam"; - let mut data = String::from_str(string); - data.push_str(string); - assert!(data.find_str("ไท华").is_none()); - assert_eq!(data[0..43].find_str(""), Some(0)); - assert_eq!(data[6..43].find_str(""), Some(6 - 6)); - - assert_eq!(data[0..43].find_str("ประ"), Some( 0)); - assert_eq!(data[0..43].find_str("ทศไ"), Some(12)); - assert_eq!(data[0..43].find_str("ย中"), Some(24)); - assert_eq!(data[0..43].find_str("iệt"), Some(34)); - assert_eq!(data[0..43].find_str("Nam"), Some(40)); - - assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43)); - assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43)); - assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43)); - assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43)); - assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43)); - } - - #[test] - fn test_slice_chars() { - fn t(a: &str, b: &str, start: usize) { - assert_eq!(a.slice_chars(start, start + b.chars().count()), b); - } - t("", "", 0); - t("hello", "llo", 2); - t("hello", "el", 1); - t("αβλ", "β", 1); - t("αβλ", "", 3); - assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); - } - - fn s(x: &str) -> String { x.to_string() } - - macro_rules! test_concat { - ($expected: expr, $string: expr) => { - { - let s: String = $string.concat(); - assert_eq!($expected, s); - } - } - } - - #[test] - fn test_concat_for_different_types() { - test_concat!("ab", vec![s("a"), s("b")]); - test_concat!("ab", vec!["a", "b"]); - test_concat!("ab", vec!["a", "b"]); - test_concat!("ab", vec![s("a"), s("b")]); - } - - #[test] - fn test_concat_for_different_lengths() { - let empty: &[&str] = &[]; - test_concat!("", empty); - test_concat!("a", ["a"]); - test_concat!("ab", ["a", "b"]); - test_concat!("abc", ["", "a", "bc"]); - } - - macro_rules! test_connect { - ($expected: expr, $string: expr, $delim: expr) => { - { - let s = $string.connect($delim); - assert_eq!($expected, s); - } - } - } - - #[test] - fn test_connect_for_different_types() { - test_connect!("a-b", ["a", "b"], "-"); - let hyphen = "-".to_string(); - test_connect!("a-b", [s("a"), s("b")], &*hyphen); - test_connect!("a-b", vec!["a", "b"], &*hyphen); - test_connect!("a-b", &*vec!["a", "b"], "-"); - test_connect!("a-b", vec![s("a"), s("b")], "-"); - } - - #[test] - fn test_connect_for_different_lengths() { - let empty: &[&str] = &[]; - test_connect!("", empty, "-"); - test_connect!("a", ["a"], "-"); - test_connect!("a-b", ["a", "b"], "-"); - test_connect!("-a-bc", ["", "a", "bc"], "-"); - } - - #[test] - fn test_unsafe_slice() { - assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)}); - assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)}); - assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)}); - fn a_million_letter_a() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("aaaaaaaaaa"); - i += 1; - } - rs - } - fn half_a_million_letter_a() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("aaaaa"); - i += 1; - } - rs - } - let letters = a_million_letter_a(); - assert!(half_a_million_letter_a() == - unsafe {String::from_str(letters.slice_unchecked( - 0, - 500000))}); - } - - #[test] - fn test_starts_with() { - assert!(("".starts_with(""))); - assert!(("abc".starts_with(""))); - assert!(("abc".starts_with("a"))); - assert!((!"a".starts_with("abc"))); - assert!((!"".starts_with("abc"))); - assert!((!"ödd".starts_with("-"))); - assert!(("ödd".starts_with("öd"))); - } - - #[test] - fn test_ends_with() { - assert!(("".ends_with(""))); - assert!(("abc".ends_with(""))); - assert!(("abc".ends_with("c"))); - assert!((!"a".ends_with("abc"))); - assert!((!"".ends_with("abc"))); - assert!((!"ddö".ends_with("-"))); - assert!(("ddö".ends_with("dö"))); - } - - #[test] - fn test_is_empty() { - assert!("".is_empty()); - assert!(!"a".is_empty()); - } - - #[test] - fn test_replace() { - let a = "a"; - assert_eq!("".replace(a, "b"), String::from_str("")); - assert_eq!("a".replace(a, "b"), String::from_str("b")); - assert_eq!("ab".replace(a, "b"), String::from_str("bb")); - let test = "test"; - assert!(" test test ".replace(test, "toast") == - String::from_str(" toast toast ")); - assert_eq!(" test test ".replace(test, ""), String::from_str(" ")); - } - - #[test] - fn test_replace_2a() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let a = "ประเ"; - let a2 = "دولة الكويتทศไทย中华"; - assert_eq!(data.replace(a, repl), a2); - } - - #[test] - fn test_replace_2b() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let b = "ะเ"; - let b2 = "ปรدولة الكويتทศไทย中华"; - assert_eq!(data.replace(b, repl), b2); - } - #[test] - fn test_replace_2c() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let c = "中华"; - let c2 = "ประเทศไทยدولة الكويت"; - assert_eq!(data.replace(c, repl), c2); - } - - #[test] - fn test_replace_2d() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let d = "ไท华"; - assert_eq!(data.replace(d, repl), data); - } - - #[test] - fn test_slice() { - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3)); - - let data = "ประเทศไทย中华"; - assert_eq!("ป", data.slice(0, 3)); - assert_eq!("ร", data.slice(3, 6)); - assert_eq!("", data.slice(3, 3)); - assert_eq!("华", data.slice(30, 33)); - - fn a_million_letter_x() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("华华华华华华华华华华"); - i += 1; - } - rs - } - fn half_a_million_letter_x() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("华华华华华"); - i += 1; - } - rs - } - let letters = a_million_letter_x(); - assert!(half_a_million_letter_x() == - String::from_str(letters.slice(0, 3 * 500000))); - } - - #[test] - fn test_slice_2() { - let ss = "中华Việt Nam"; - - assert_eq!("华", ss.slice(3, 6)); - assert_eq!("Việt Nam", ss.slice(6, 16)); - - assert_eq!("ab", "abc".slice(0, 2)); - assert_eq!("bc", "abc".slice(1, 3)); - assert_eq!("", "abc".slice(1, 1)); - - assert_eq!("中", ss.slice(0, 3)); - assert_eq!("华V", ss.slice(3, 7)); - assert_eq!("", ss.slice(3, 3)); - /*0: 中 - 3: 华 - 6: V - 7: i - 8: ệ - 11: t - 12: - 13: N - 14: a - 15: m */ - } - - #[test] - #[should_fail] - fn test_slice_fail() { - "中华Việt Nam".slice(0, 2); - } - - #[test] - fn test_slice_from() { - assert_eq!("abcd".slice_from(0), "abcd"); - assert_eq!("abcd".slice_from(2), "cd"); - assert_eq!("abcd".slice_from(4), ""); - } - #[test] - fn test_slice_to() { - assert_eq!("abcd".slice_to(0), ""); - assert_eq!("abcd".slice_to(2), "ab"); - assert_eq!("abcd".slice_to(4), "abcd"); - } - - #[test] - fn test_trim_left_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** "); - assert_eq!(" *** *** ".trim_left_matches(chars), ""); - assert_eq!("foo *** ".trim_left_matches(chars), "foo *** "); - - assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12"); - assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); - } - - #[test] - fn test_trim_right_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo"); - assert_eq!(" *** *** ".trim_right_matches(chars), ""); - assert_eq!(" *** foo".trim_right_matches(chars), " *** foo"); - - assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar"); - assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); - } - - #[test] - fn test_trim_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); - assert_eq!(" *** *** ".trim_matches(chars), ""); - assert_eq!("foo".trim_matches(chars), "foo"); - - assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); - assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); - } - - #[test] - fn test_trim_left() { - assert_eq!("".trim_left(), ""); - assert_eq!("a".trim_left(), "a"); - assert_eq!(" ".trim_left(), ""); - assert_eq!(" blah".trim_left(), "blah"); - assert_eq!(" \u{3000} wut".trim_left(), "wut"); - assert_eq!("hey ".trim_left(), "hey "); - } - - #[test] - fn test_trim_right() { - assert_eq!("".trim_right(), ""); - assert_eq!("a".trim_right(), "a"); - assert_eq!(" ".trim_right(), ""); - assert_eq!("blah ".trim_right(), "blah"); - assert_eq!("wut \u{3000} ".trim_right(), "wut"); - assert_eq!(" hey".trim_right(), " hey"); - } - - #[test] - fn test_trim() { - assert_eq!("".trim(), ""); - assert_eq!("a".trim(), "a"); - assert_eq!(" ".trim(), ""); - assert_eq!(" blah ".trim(), "blah"); - assert_eq!("\nwut \u{3000} ".trim(), "wut"); - assert_eq!(" hey dude ".trim(), "hey dude"); - } - - #[test] - fn test_is_whitespace() { - assert!("".chars().all(|c| c.is_whitespace())); - assert!(" ".chars().all(|c| c.is_whitespace())); - assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space - assert!(" \n\t ".chars().all(|c| c.is_whitespace())); - assert!(!" _ ".chars().all(|c| c.is_whitespace())); - } - - #[test] - fn test_slice_shift_char() { - let data = "ประเทศไทย中"; - assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); - } - - #[test] - fn test_slice_shift_char_2() { - let empty = ""; - assert_eq!(empty.slice_shift_char(), None); - } - - #[test] - fn test_is_utf8() { - // deny overlong encodings - assert!(from_utf8(&[0xc0, 0x80]).is_err()); - assert!(from_utf8(&[0xc0, 0xae]).is_err()); - assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); - assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); - assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); - assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); - assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); - - // deny surrogates - assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); - assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); - - assert!(from_utf8(&[0xC2, 0x80]).is_ok()); - assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); - assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); - assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); - assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); - assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); - assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); - assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); - } - - #[test] - fn test_is_utf16() { - use unicode::str::is_utf16; - macro_rules! pos { - ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } - } - - // non-surrogates - pos!(&[0x0000], - &[0x0001, 0x0002], - &[0xD7FF], - &[0xE000]); - - // surrogate pairs (randomly generated with Python 3's - // .encode('utf-16be')) - pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45], - &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14], - &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]); - - // mixtures (also random) - pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65], - &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006], - &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); - - // negative tests - macro_rules! neg { - ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } - } - - neg!( - // surrogate + regular unit - &[0xdb45, 0x0000], - // surrogate + lead surrogate - &[0xd900, 0xd900], - // unterminated surrogate - &[0xd8ff], - // trail surrogate without a lead - &[0xddb7]); - - // random byte sequences that Python 3's .decode('utf-16be') - // failed on - neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7], - &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3], - &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca], - &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278], - &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e], - &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5], - &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee], - &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7], - &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a], - &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a], - &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe], - &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf], - &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e], - &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5], - &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f], - &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b], - &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7], - &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9], - &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8], - &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282], - &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]); - } - - #[test] - fn test_as_bytes() { - // no null - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let b: &[u8] = &[]; - assert_eq!("".as_bytes(), b); - assert_eq!("abc".as_bytes(), b"abc"); - assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); - } - - #[test] - #[should_fail] - fn test_as_bytes_fail() { - // Don't double free. (I'm not sure if this exercises the - // original problem code path anymore.) - let s = String::from_str(""); - let _bytes = s.as_bytes(); - panic!(); - } - - #[test] - fn test_as_ptr() { - let buf = "hello".as_ptr(); - unsafe { - assert_eq!(*buf.offset(0), b'h'); - assert_eq!(*buf.offset(1), b'e'); - assert_eq!(*buf.offset(2), b'l'); - assert_eq!(*buf.offset(3), b'l'); - assert_eq!(*buf.offset(4), b'o'); - } - } - - #[test] - fn test_subslice_offset() { - let a = "kernelsprite"; - let b = &a[7..a.len()]; - let c = &a[0..a.len() - 6]; - assert_eq!(a.subslice_offset(b), 7); - assert_eq!(a.subslice_offset(c), 0); - - let string = "a\nb\nc"; - let lines: Vec<&str> = string.lines().collect(); - assert_eq!(string.subslice_offset(lines[0]), 0); - assert_eq!(string.subslice_offset(lines[1]), 2); - assert_eq!(string.subslice_offset(lines[2]), 4); - } - - #[test] - #[should_fail] - fn test_subslice_offset_2() { - let a = "alchemiter"; - let b = "cruxtruder"; - a.subslice_offset(b); - } - - #[test] - fn vec_str_conversions() { - let s1: String = String::from_str("All mimsy were the borogoves"); - - let v: Vec = s1.as_bytes().to_vec(); - let s2: String = String::from_str(from_utf8(&v).unwrap()); - let mut i = 0; - let n1 = s1.len(); - let n2 = v.len(); - assert_eq!(n1, n2); - while i < n1 { - let a: u8 = s1.as_bytes()[i]; - let b: u8 = s2.as_bytes()[i]; - debug!("{}", a); - debug!("{}", b); - assert_eq!(a, b); - i += 1; - } - } - - #[test] - fn test_contains() { - assert!("abcde".contains("bcd")); - assert!("abcde".contains("abcd")); - assert!("abcde".contains("bcde")); - assert!("abcde".contains("")); - assert!("".contains("")); - assert!(!"abcde".contains("def")); - assert!(!"".contains("a")); - - let data = "ประเทศไทย中华Việt Nam"; - assert!(data.contains("ประเ")); - assert!(data.contains("ะเ")); - assert!(data.contains("中华")); - assert!(!data.contains("ไท华")); - } - - #[test] - fn test_contains_char() { - assert!("abc".contains_char('b')); - assert!("a".contains_char('a')); - assert!(!"abc".contains_char('d')); - assert!(!"".contains_char('a')); - } - - #[test] - fn test_char_at() { - let s = "ศไทย中华Việt Nam"; - let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = 0; - for ch in &v { - assert!(s.char_at(pos) == *ch); - pos += ch.to_string().len(); - } - } - - #[test] - fn test_char_at_reverse() { - let s = "ศไทย中华Việt Nam"; - let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - let mut pos = s.len(); - for ch in v.iter().rev() { - assert!(s.char_at_reverse(pos) == *ch); - pos -= ch.to_string().len(); - } - } - - #[test] - fn test_escape_unicode() { - assert_eq!("abc".escape_unicode(), - String::from_str("\\u{61}\\u{62}\\u{63}")); - assert_eq!("a c".escape_unicode(), - String::from_str("\\u{61}\\u{20}\\u{63}")); - assert_eq!("\r\n\t".escape_unicode(), - String::from_str("\\u{d}\\u{a}\\u{9}")); - assert_eq!("'\"\\".escape_unicode(), - String::from_str("\\u{27}\\u{22}\\u{5c}")); - assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), - String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}")); - assert_eq!("\u{100}\u{ffff}".escape_unicode(), - String::from_str("\\u{100}\\u{ffff}")); - assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), - String::from_str("\\u{10000}\\u{10ffff}")); - assert_eq!("ab\u{fb00}".escape_unicode(), - String::from_str("\\u{61}\\u{62}\\u{fb00}")); - assert_eq!("\u{1d4ea}\r".escape_unicode(), - String::from_str("\\u{1d4ea}\\u{d}")); - } - - #[test] - fn test_escape_default() { - assert_eq!("abc".escape_default(), String::from_str("abc")); - assert_eq!("a c".escape_default(), String::from_str("a c")); - assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t")); - assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\")); - assert_eq!("\u{100}\u{ffff}".escape_default(), - String::from_str("\\u{100}\\u{ffff}")); - assert_eq!("\u{10000}\u{10ffff}".escape_default(), - String::from_str("\\u{10000}\\u{10ffff}")); - assert_eq!("ab\u{fb00}".escape_default(), - String::from_str("ab\\u{fb00}")); - assert_eq!("\u{1d4ea}\r".escape_default(), - String::from_str("\\u{1d4ea}\\r")); - } - - #[test] - fn test_total_ord() { - "1234".cmp("123") == Greater; - "123".cmp("1234") == Less; - "1234".cmp("1234") == Equal; - "12345555".cmp("123456") == Less; - "22".cmp("1234") == Greater; - } - - #[test] - fn test_char_range_at() { - let data = "b¢€𤭢𤭢€¢b"; - assert_eq!('b', data.char_range_at(0).ch); - assert_eq!('¢', data.char_range_at(1).ch); - assert_eq!('€', data.char_range_at(3).ch); - assert_eq!('𤭢', data.char_range_at(6).ch); - assert_eq!('𤭢', data.char_range_at(10).ch); - assert_eq!('€', data.char_range_at(14).ch); - assert_eq!('¢', data.char_range_at(17).ch); - assert_eq!('b', data.char_range_at(19).ch); - } - - #[test] - fn test_char_range_at_reverse_underflow() { - assert_eq!("abc".char_range_at_reverse(0).next, 0); - } - - #[test] - fn test_iterator() { - let s = "ศไทย中华Việt Nam"; - let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - - let mut pos = 0; - let it = s.chars(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); - } - - #[test] - fn test_rev_iterator() { - let s = "ศไทย中华Việt Nam"; - let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; - - let mut pos = 0; - let it = s.chars().rev(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); - } - - #[test] - fn test_chars_decoding() { - let mut bytes = [0u8; 4]; - for c in (0u32..0x110000).filter_map(|c| ::core::char::from_u32(c)) { - let len = c.encode_utf8(&mut bytes).unwrap_or(0); - let s = ::core::str::from_utf8(&bytes[..len]).unwrap(); - if Some(c) != s.chars().next() { - panic!("character {:x}={} does not decode correctly", c as u32, c); - } - } - } - - #[test] - fn test_chars_rev_decoding() { - let mut bytes = [0u8; 4]; - for c in (0u32..0x110000).filter_map(|c| ::core::char::from_u32(c)) { - let len = c.encode_utf8(&mut bytes).unwrap_or(0); - let s = ::core::str::from_utf8(&bytes[..len]).unwrap(); - if Some(c) != s.chars().rev().next() { - panic!("character {:x}={} does not decode correctly", c as u32, c); - } - } - } - - #[test] - fn test_iterator_clone() { - let s = "ศไทย中华Việt Nam"; - let mut it = s.chars(); - it.next(); - assert!(it.clone().zip(it).all(|(x,y)| x == y)); - } - - #[test] - fn test_bytesator() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = 0; - - for b in s.bytes() { - assert_eq!(b, v[pos]); - pos += 1; - } - } - - #[test] - fn test_bytes_revator() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, - 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, - 109 - ]; - let mut pos = v.len(); - - for b in s.bytes().rev() { - pos -= 1; - assert_eq!(b, v[pos]); - } - } - - #[test] - fn test_char_indicesator() { - let s = "ศไทย中华Việt Nam"; - let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; - let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; - - let mut pos = 0; - let it = s.char_indices(); - - for c in it { - assert_eq!(c, (p[pos], v[pos])); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(pos, p.len()); - } - - #[test] - fn test_char_indices_revator() { - let s = "ศไทย中华Việt Nam"; - let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; - let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; - - let mut pos = 0; - let it = s.char_indices().rev(); - - for c in it { - assert_eq!(c, (p[pos], v[pos])); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(pos, p.len()); - } - - #[test] - fn test_splitn_char_iterator() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.splitn(3, ' ').collect(); - assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect(); - assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - // Unicode - let split: Vec<&str> = data.splitn(3, 'ä').collect(); - assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect(); - assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); - } - - #[test] - fn test_split_char_iterator_no_trailing() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.split('\n').collect(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]); - - let split: Vec<&str> = data.split_terminator('\n').collect(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]); - } - - #[test] - fn test_words() { - let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; - let words: Vec<&str> = data.words().collect(); - assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) - } - - #[test] - fn test_nfd_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfd_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "d\u{307}\u{1c4}"); - t!("\u{2026}", "\u{2026}"); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); - t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); - t!("a\u{301}", "a\u{301}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); - t!("\u{ac1c}", "\u{1100}\u{1162}"); - } - - #[test] - fn test_nfkd_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfkd_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "d\u{307}DZ\u{30c}"); - t!("\u{2026}", "..."); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); - t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); - t!("a\u{301}", "a\u{301}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); - t!("\u{ac1c}", "\u{1100}\u{1162}"); - } - - #[test] - fn test_nfc_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfc_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "\u{1e0b}\u{1c4}"); - t!("\u{2026}", "\u{2026}"); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); - t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); - t!("a\u{301}", "\u{e1}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{d4db}"); - t!("\u{ac1c}", "\u{ac1c}"); - t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); - } - - #[test] - fn test_nfkc_chars() { - macro_rules! t { - ($input: expr, $expected: expr) => { - assert_eq!($input.nfkc_chars().collect::(), $expected); - } - } - t!("abc", "abc"); - t!("\u{1e0b}\u{1c4}", "\u{1e0b}D\u{17d}"); - t!("\u{2026}", "..."); - t!("\u{2126}", "\u{3a9}"); - t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); - t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); - t!("a\u{301}", "\u{e1}"); - t!("\u{301}a", "\u{301}a"); - t!("\u{d4db}", "\u{d4db}"); - t!("\u{ac1c}", "\u{ac1c}"); - t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); - } - - #[test] - fn test_lines() { - let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]); - - let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]); - } - - #[test] - fn test_graphemes() { - use core::iter::order; - // official Unicode test data - // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt - let test_same: [(_, &[_]); 325] = [ - ("\u{20}\u{20}", &["\u{20}", "\u{20}"]), - ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]), - ("\u{20}\u{D}", &["\u{20}", "\u{D}"]), - ("\u{20}\u{308}\u{D}", &["\u{20}\u{308}", "\u{D}"]), - ("\u{20}\u{A}", &["\u{20}", "\u{A}"]), - ("\u{20}\u{308}\u{A}", &["\u{20}\u{308}", "\u{A}"]), - ("\u{20}\u{1}", &["\u{20}", "\u{1}"]), - ("\u{20}\u{308}\u{1}", &["\u{20}\u{308}", "\u{1}"]), - ("\u{20}\u{300}", &["\u{20}\u{300}"]), - ("\u{20}\u{308}\u{300}", &["\u{20}\u{308}\u{300}"]), - ("\u{20}\u{1100}", &["\u{20}", "\u{1100}"]), - ("\u{20}\u{308}\u{1100}", &["\u{20}\u{308}", "\u{1100}"]), - ("\u{20}\u{1160}", &["\u{20}", "\u{1160}"]), - ("\u{20}\u{308}\u{1160}", &["\u{20}\u{308}", "\u{1160}"]), - ("\u{20}\u{11A8}", &["\u{20}", "\u{11A8}"]), - ("\u{20}\u{308}\u{11A8}", &["\u{20}\u{308}", "\u{11A8}"]), - ("\u{20}\u{AC00}", &["\u{20}", "\u{AC00}"]), - ("\u{20}\u{308}\u{AC00}", &["\u{20}\u{308}", "\u{AC00}"]), - ("\u{20}\u{AC01}", &["\u{20}", "\u{AC01}"]), - ("\u{20}\u{308}\u{AC01}", &["\u{20}\u{308}", "\u{AC01}"]), - ("\u{20}\u{1F1E6}", &["\u{20}", "\u{1F1E6}"]), - ("\u{20}\u{308}\u{1F1E6}", &["\u{20}\u{308}", "\u{1F1E6}"]), - ("\u{20}\u{378}", &["\u{20}", "\u{378}"]), - ("\u{20}\u{308}\u{378}", &["\u{20}\u{308}", "\u{378}"]), - ("\u{D}\u{20}", &["\u{D}", "\u{20}"]), - ("\u{D}\u{308}\u{20}", &["\u{D}", "\u{308}", "\u{20}"]), - ("\u{D}\u{D}", &["\u{D}", "\u{D}"]), - ("\u{D}\u{308}\u{D}", &["\u{D}", "\u{308}", "\u{D}"]), - ("\u{D}\u{A}", &["\u{D}\u{A}"]), - ("\u{D}\u{308}\u{A}", &["\u{D}", "\u{308}", "\u{A}"]), - ("\u{D}\u{1}", &["\u{D}", "\u{1}"]), - ("\u{D}\u{308}\u{1}", &["\u{D}", "\u{308}", "\u{1}"]), - ("\u{D}\u{300}", &["\u{D}", "\u{300}"]), - ("\u{D}\u{308}\u{300}", &["\u{D}", "\u{308}\u{300}"]), - ("\u{D}\u{903}", &["\u{D}", "\u{903}"]), - ("\u{D}\u{1100}", &["\u{D}", "\u{1100}"]), - ("\u{D}\u{308}\u{1100}", &["\u{D}", "\u{308}", "\u{1100}"]), - ("\u{D}\u{1160}", &["\u{D}", "\u{1160}"]), - ("\u{D}\u{308}\u{1160}", &["\u{D}", "\u{308}", "\u{1160}"]), - ("\u{D}\u{11A8}", &["\u{D}", "\u{11A8}"]), - ("\u{D}\u{308}\u{11A8}", &["\u{D}", "\u{308}", "\u{11A8}"]), - ("\u{D}\u{AC00}", &["\u{D}", "\u{AC00}"]), - ("\u{D}\u{308}\u{AC00}", &["\u{D}", "\u{308}", "\u{AC00}"]), - ("\u{D}\u{AC01}", &["\u{D}", "\u{AC01}"]), - ("\u{D}\u{308}\u{AC01}", &["\u{D}", "\u{308}", "\u{AC01}"]), - ("\u{D}\u{1F1E6}", &["\u{D}", "\u{1F1E6}"]), - ("\u{D}\u{308}\u{1F1E6}", &["\u{D}", "\u{308}", "\u{1F1E6}"]), - ("\u{D}\u{378}", &["\u{D}", "\u{378}"]), - ("\u{D}\u{308}\u{378}", &["\u{D}", "\u{308}", "\u{378}"]), - ("\u{A}\u{20}", &["\u{A}", "\u{20}"]), - ("\u{A}\u{308}\u{20}", &["\u{A}", "\u{308}", "\u{20}"]), - ("\u{A}\u{D}", &["\u{A}", "\u{D}"]), - ("\u{A}\u{308}\u{D}", &["\u{A}", "\u{308}", "\u{D}"]), - ("\u{A}\u{A}", &["\u{A}", "\u{A}"]), - ("\u{A}\u{308}\u{A}", &["\u{A}", "\u{308}", "\u{A}"]), - ("\u{A}\u{1}", &["\u{A}", "\u{1}"]), - ("\u{A}\u{308}\u{1}", &["\u{A}", "\u{308}", "\u{1}"]), - ("\u{A}\u{300}", &["\u{A}", "\u{300}"]), - ("\u{A}\u{308}\u{300}", &["\u{A}", "\u{308}\u{300}"]), - ("\u{A}\u{903}", &["\u{A}", "\u{903}"]), - ("\u{A}\u{1100}", &["\u{A}", "\u{1100}"]), - ("\u{A}\u{308}\u{1100}", &["\u{A}", "\u{308}", "\u{1100}"]), - ("\u{A}\u{1160}", &["\u{A}", "\u{1160}"]), - ("\u{A}\u{308}\u{1160}", &["\u{A}", "\u{308}", "\u{1160}"]), - ("\u{A}\u{11A8}", &["\u{A}", "\u{11A8}"]), - ("\u{A}\u{308}\u{11A8}", &["\u{A}", "\u{308}", "\u{11A8}"]), - ("\u{A}\u{AC00}", &["\u{A}", "\u{AC00}"]), - ("\u{A}\u{308}\u{AC00}", &["\u{A}", "\u{308}", "\u{AC00}"]), - ("\u{A}\u{AC01}", &["\u{A}", "\u{AC01}"]), - ("\u{A}\u{308}\u{AC01}", &["\u{A}", "\u{308}", "\u{AC01}"]), - ("\u{A}\u{1F1E6}", &["\u{A}", "\u{1F1E6}"]), - ("\u{A}\u{308}\u{1F1E6}", &["\u{A}", "\u{308}", "\u{1F1E6}"]), - ("\u{A}\u{378}", &["\u{A}", "\u{378}"]), - ("\u{A}\u{308}\u{378}", &["\u{A}", "\u{308}", "\u{378}"]), - ("\u{1}\u{20}", &["\u{1}", "\u{20}"]), - ("\u{1}\u{308}\u{20}", &["\u{1}", "\u{308}", "\u{20}"]), - ("\u{1}\u{D}", &["\u{1}", "\u{D}"]), - ("\u{1}\u{308}\u{D}", &["\u{1}", "\u{308}", "\u{D}"]), - ("\u{1}\u{A}", &["\u{1}", "\u{A}"]), - ("\u{1}\u{308}\u{A}", &["\u{1}", "\u{308}", "\u{A}"]), - ("\u{1}\u{1}", &["\u{1}", "\u{1}"]), - ("\u{1}\u{308}\u{1}", &["\u{1}", "\u{308}", "\u{1}"]), - ("\u{1}\u{300}", &["\u{1}", "\u{300}"]), - ("\u{1}\u{308}\u{300}", &["\u{1}", "\u{308}\u{300}"]), - ("\u{1}\u{903}", &["\u{1}", "\u{903}"]), - ("\u{1}\u{1100}", &["\u{1}", "\u{1100}"]), - ("\u{1}\u{308}\u{1100}", &["\u{1}", "\u{308}", "\u{1100}"]), - ("\u{1}\u{1160}", &["\u{1}", "\u{1160}"]), - ("\u{1}\u{308}\u{1160}", &["\u{1}", "\u{308}", "\u{1160}"]), - ("\u{1}\u{11A8}", &["\u{1}", "\u{11A8}"]), - ("\u{1}\u{308}\u{11A8}", &["\u{1}", "\u{308}", "\u{11A8}"]), - ("\u{1}\u{AC00}", &["\u{1}", "\u{AC00}"]), - ("\u{1}\u{308}\u{AC00}", &["\u{1}", "\u{308}", "\u{AC00}"]), - ("\u{1}\u{AC01}", &["\u{1}", "\u{AC01}"]), - ("\u{1}\u{308}\u{AC01}", &["\u{1}", "\u{308}", "\u{AC01}"]), - ("\u{1}\u{1F1E6}", &["\u{1}", "\u{1F1E6}"]), - ("\u{1}\u{308}\u{1F1E6}", &["\u{1}", "\u{308}", "\u{1F1E6}"]), - ("\u{1}\u{378}", &["\u{1}", "\u{378}"]), - ("\u{1}\u{308}\u{378}", &["\u{1}", "\u{308}", "\u{378}"]), - ("\u{300}\u{20}", &["\u{300}", "\u{20}"]), - ("\u{300}\u{308}\u{20}", &["\u{300}\u{308}", "\u{20}"]), - ("\u{300}\u{D}", &["\u{300}", "\u{D}"]), - ("\u{300}\u{308}\u{D}", &["\u{300}\u{308}", "\u{D}"]), - ("\u{300}\u{A}", &["\u{300}", "\u{A}"]), - ("\u{300}\u{308}\u{A}", &["\u{300}\u{308}", "\u{A}"]), - ("\u{300}\u{1}", &["\u{300}", "\u{1}"]), - ("\u{300}\u{308}\u{1}", &["\u{300}\u{308}", "\u{1}"]), - ("\u{300}\u{300}", &["\u{300}\u{300}"]), - ("\u{300}\u{308}\u{300}", &["\u{300}\u{308}\u{300}"]), - ("\u{300}\u{1100}", &["\u{300}", "\u{1100}"]), - ("\u{300}\u{308}\u{1100}", &["\u{300}\u{308}", "\u{1100}"]), - ("\u{300}\u{1160}", &["\u{300}", "\u{1160}"]), - ("\u{300}\u{308}\u{1160}", &["\u{300}\u{308}", "\u{1160}"]), - ("\u{300}\u{11A8}", &["\u{300}", "\u{11A8}"]), - ("\u{300}\u{308}\u{11A8}", &["\u{300}\u{308}", "\u{11A8}"]), - ("\u{300}\u{AC00}", &["\u{300}", "\u{AC00}"]), - ("\u{300}\u{308}\u{AC00}", &["\u{300}\u{308}", "\u{AC00}"]), - ("\u{300}\u{AC01}", &["\u{300}", "\u{AC01}"]), - ("\u{300}\u{308}\u{AC01}", &["\u{300}\u{308}", "\u{AC01}"]), - ("\u{300}\u{1F1E6}", &["\u{300}", "\u{1F1E6}"]), - ("\u{300}\u{308}\u{1F1E6}", &["\u{300}\u{308}", "\u{1F1E6}"]), - ("\u{300}\u{378}", &["\u{300}", "\u{378}"]), - ("\u{300}\u{308}\u{378}", &["\u{300}\u{308}", "\u{378}"]), - ("\u{903}\u{20}", &["\u{903}", "\u{20}"]), - ("\u{903}\u{308}\u{20}", &["\u{903}\u{308}", "\u{20}"]), - ("\u{903}\u{D}", &["\u{903}", "\u{D}"]), - ("\u{903}\u{308}\u{D}", &["\u{903}\u{308}", "\u{D}"]), - ("\u{903}\u{A}", &["\u{903}", "\u{A}"]), - ("\u{903}\u{308}\u{A}", &["\u{903}\u{308}", "\u{A}"]), - ("\u{903}\u{1}", &["\u{903}", "\u{1}"]), - ("\u{903}\u{308}\u{1}", &["\u{903}\u{308}", "\u{1}"]), - ("\u{903}\u{300}", &["\u{903}\u{300}"]), - ("\u{903}\u{308}\u{300}", &["\u{903}\u{308}\u{300}"]), - ("\u{903}\u{1100}", &["\u{903}", "\u{1100}"]), - ("\u{903}\u{308}\u{1100}", &["\u{903}\u{308}", "\u{1100}"]), - ("\u{903}\u{1160}", &["\u{903}", "\u{1160}"]), - ("\u{903}\u{308}\u{1160}", &["\u{903}\u{308}", "\u{1160}"]), - ("\u{903}\u{11A8}", &["\u{903}", "\u{11A8}"]), - ("\u{903}\u{308}\u{11A8}", &["\u{903}\u{308}", "\u{11A8}"]), - ("\u{903}\u{AC00}", &["\u{903}", "\u{AC00}"]), - ("\u{903}\u{308}\u{AC00}", &["\u{903}\u{308}", "\u{AC00}"]), - ("\u{903}\u{AC01}", &["\u{903}", "\u{AC01}"]), - ("\u{903}\u{308}\u{AC01}", &["\u{903}\u{308}", "\u{AC01}"]), - ("\u{903}\u{1F1E6}", &["\u{903}", "\u{1F1E6}"]), - ("\u{903}\u{308}\u{1F1E6}", &["\u{903}\u{308}", "\u{1F1E6}"]), - ("\u{903}\u{378}", &["\u{903}", "\u{378}"]), - ("\u{903}\u{308}\u{378}", &["\u{903}\u{308}", "\u{378}"]), - ("\u{1100}\u{20}", &["\u{1100}", "\u{20}"]), - ("\u{1100}\u{308}\u{20}", &["\u{1100}\u{308}", "\u{20}"]), - ("\u{1100}\u{D}", &["\u{1100}", "\u{D}"]), - ("\u{1100}\u{308}\u{D}", &["\u{1100}\u{308}", "\u{D}"]), - ("\u{1100}\u{A}", &["\u{1100}", "\u{A}"]), - ("\u{1100}\u{308}\u{A}", &["\u{1100}\u{308}", "\u{A}"]), - ("\u{1100}\u{1}", &["\u{1100}", "\u{1}"]), - ("\u{1100}\u{308}\u{1}", &["\u{1100}\u{308}", "\u{1}"]), - ("\u{1100}\u{300}", &["\u{1100}\u{300}"]), - ("\u{1100}\u{308}\u{300}", &["\u{1100}\u{308}\u{300}"]), - ("\u{1100}\u{1100}", &["\u{1100}\u{1100}"]), - ("\u{1100}\u{308}\u{1100}", &["\u{1100}\u{308}", "\u{1100}"]), - ("\u{1100}\u{1160}", &["\u{1100}\u{1160}"]), - ("\u{1100}\u{308}\u{1160}", &["\u{1100}\u{308}", "\u{1160}"]), - ("\u{1100}\u{11A8}", &["\u{1100}", "\u{11A8}"]), - ("\u{1100}\u{308}\u{11A8}", &["\u{1100}\u{308}", "\u{11A8}"]), - ("\u{1100}\u{AC00}", &["\u{1100}\u{AC00}"]), - ("\u{1100}\u{308}\u{AC00}", &["\u{1100}\u{308}", "\u{AC00}"]), - ("\u{1100}\u{AC01}", &["\u{1100}\u{AC01}"]), - ("\u{1100}\u{308}\u{AC01}", &["\u{1100}\u{308}", "\u{AC01}"]), - ("\u{1100}\u{1F1E6}", &["\u{1100}", "\u{1F1E6}"]), - ("\u{1100}\u{308}\u{1F1E6}", &["\u{1100}\u{308}", "\u{1F1E6}"]), - ("\u{1100}\u{378}", &["\u{1100}", "\u{378}"]), - ("\u{1100}\u{308}\u{378}", &["\u{1100}\u{308}", "\u{378}"]), - ("\u{1160}\u{20}", &["\u{1160}", "\u{20}"]), - ("\u{1160}\u{308}\u{20}", &["\u{1160}\u{308}", "\u{20}"]), - ("\u{1160}\u{D}", &["\u{1160}", "\u{D}"]), - ("\u{1160}\u{308}\u{D}", &["\u{1160}\u{308}", "\u{D}"]), - ("\u{1160}\u{A}", &["\u{1160}", "\u{A}"]), - ("\u{1160}\u{308}\u{A}", &["\u{1160}\u{308}", "\u{A}"]), - ("\u{1160}\u{1}", &["\u{1160}", "\u{1}"]), - ("\u{1160}\u{308}\u{1}", &["\u{1160}\u{308}", "\u{1}"]), - ("\u{1160}\u{300}", &["\u{1160}\u{300}"]), - ("\u{1160}\u{308}\u{300}", &["\u{1160}\u{308}\u{300}"]), - ("\u{1160}\u{1100}", &["\u{1160}", "\u{1100}"]), - ("\u{1160}\u{308}\u{1100}", &["\u{1160}\u{308}", "\u{1100}"]), - ("\u{1160}\u{1160}", &["\u{1160}\u{1160}"]), - ("\u{1160}\u{308}\u{1160}", &["\u{1160}\u{308}", "\u{1160}"]), - ("\u{1160}\u{11A8}", &["\u{1160}\u{11A8}"]), - ("\u{1160}\u{308}\u{11A8}", &["\u{1160}\u{308}", "\u{11A8}"]), - ("\u{1160}\u{AC00}", &["\u{1160}", "\u{AC00}"]), - ("\u{1160}\u{308}\u{AC00}", &["\u{1160}\u{308}", "\u{AC00}"]), - ("\u{1160}\u{AC01}", &["\u{1160}", "\u{AC01}"]), - ("\u{1160}\u{308}\u{AC01}", &["\u{1160}\u{308}", "\u{AC01}"]), - ("\u{1160}\u{1F1E6}", &["\u{1160}", "\u{1F1E6}"]), - ("\u{1160}\u{308}\u{1F1E6}", &["\u{1160}\u{308}", "\u{1F1E6}"]), - ("\u{1160}\u{378}", &["\u{1160}", "\u{378}"]), - ("\u{1160}\u{308}\u{378}", &["\u{1160}\u{308}", "\u{378}"]), - ("\u{11A8}\u{20}", &["\u{11A8}", "\u{20}"]), - ("\u{11A8}\u{308}\u{20}", &["\u{11A8}\u{308}", "\u{20}"]), - ("\u{11A8}\u{D}", &["\u{11A8}", "\u{D}"]), - ("\u{11A8}\u{308}\u{D}", &["\u{11A8}\u{308}", "\u{D}"]), - ("\u{11A8}\u{A}", &["\u{11A8}", "\u{A}"]), - ("\u{11A8}\u{308}\u{A}", &["\u{11A8}\u{308}", "\u{A}"]), - ("\u{11A8}\u{1}", &["\u{11A8}", "\u{1}"]), - ("\u{11A8}\u{308}\u{1}", &["\u{11A8}\u{308}", "\u{1}"]), - ("\u{11A8}\u{300}", &["\u{11A8}\u{300}"]), - ("\u{11A8}\u{308}\u{300}", &["\u{11A8}\u{308}\u{300}"]), - ("\u{11A8}\u{1100}", &["\u{11A8}", "\u{1100}"]), - ("\u{11A8}\u{308}\u{1100}", &["\u{11A8}\u{308}", "\u{1100}"]), - ("\u{11A8}\u{1160}", &["\u{11A8}", "\u{1160}"]), - ("\u{11A8}\u{308}\u{1160}", &["\u{11A8}\u{308}", "\u{1160}"]), - ("\u{11A8}\u{11A8}", &["\u{11A8}\u{11A8}"]), - ("\u{11A8}\u{308}\u{11A8}", &["\u{11A8}\u{308}", "\u{11A8}"]), - ("\u{11A8}\u{AC00}", &["\u{11A8}", "\u{AC00}"]), - ("\u{11A8}\u{308}\u{AC00}", &["\u{11A8}\u{308}", "\u{AC00}"]), - ("\u{11A8}\u{AC01}", &["\u{11A8}", "\u{AC01}"]), - ("\u{11A8}\u{308}\u{AC01}", &["\u{11A8}\u{308}", "\u{AC01}"]), - ("\u{11A8}\u{1F1E6}", &["\u{11A8}", "\u{1F1E6}"]), - ("\u{11A8}\u{308}\u{1F1E6}", &["\u{11A8}\u{308}", "\u{1F1E6}"]), - ("\u{11A8}\u{378}", &["\u{11A8}", "\u{378}"]), - ("\u{11A8}\u{308}\u{378}", &["\u{11A8}\u{308}", "\u{378}"]), - ("\u{AC00}\u{20}", &["\u{AC00}", "\u{20}"]), - ("\u{AC00}\u{308}\u{20}", &["\u{AC00}\u{308}", "\u{20}"]), - ("\u{AC00}\u{D}", &["\u{AC00}", "\u{D}"]), - ("\u{AC00}\u{308}\u{D}", &["\u{AC00}\u{308}", "\u{D}"]), - ("\u{AC00}\u{A}", &["\u{AC00}", "\u{A}"]), - ("\u{AC00}\u{308}\u{A}", &["\u{AC00}\u{308}", "\u{A}"]), - ("\u{AC00}\u{1}", &["\u{AC00}", "\u{1}"]), - ("\u{AC00}\u{308}\u{1}", &["\u{AC00}\u{308}", "\u{1}"]), - ("\u{AC00}\u{300}", &["\u{AC00}\u{300}"]), - ("\u{AC00}\u{308}\u{300}", &["\u{AC00}\u{308}\u{300}"]), - ("\u{AC00}\u{1100}", &["\u{AC00}", "\u{1100}"]), - ("\u{AC00}\u{308}\u{1100}", &["\u{AC00}\u{308}", "\u{1100}"]), - ("\u{AC00}\u{1160}", &["\u{AC00}\u{1160}"]), - ("\u{AC00}\u{308}\u{1160}", &["\u{AC00}\u{308}", "\u{1160}"]), - ("\u{AC00}\u{11A8}", &["\u{AC00}\u{11A8}"]), - ("\u{AC00}\u{308}\u{11A8}", &["\u{AC00}\u{308}", "\u{11A8}"]), - ("\u{AC00}\u{AC00}", &["\u{AC00}", "\u{AC00}"]), - ("\u{AC00}\u{308}\u{AC00}", &["\u{AC00}\u{308}", "\u{AC00}"]), - ("\u{AC00}\u{AC01}", &["\u{AC00}", "\u{AC01}"]), - ("\u{AC00}\u{308}\u{AC01}", &["\u{AC00}\u{308}", "\u{AC01}"]), - ("\u{AC00}\u{1F1E6}", &["\u{AC00}", "\u{1F1E6}"]), - ("\u{AC00}\u{308}\u{1F1E6}", &["\u{AC00}\u{308}", "\u{1F1E6}"]), - ("\u{AC00}\u{378}", &["\u{AC00}", "\u{378}"]), - ("\u{AC00}\u{308}\u{378}", &["\u{AC00}\u{308}", "\u{378}"]), - ("\u{AC01}\u{20}", &["\u{AC01}", "\u{20}"]), - ("\u{AC01}\u{308}\u{20}", &["\u{AC01}\u{308}", "\u{20}"]), - ("\u{AC01}\u{D}", &["\u{AC01}", "\u{D}"]), - ("\u{AC01}\u{308}\u{D}", &["\u{AC01}\u{308}", "\u{D}"]), - ("\u{AC01}\u{A}", &["\u{AC01}", "\u{A}"]), - ("\u{AC01}\u{308}\u{A}", &["\u{AC01}\u{308}", "\u{A}"]), - ("\u{AC01}\u{1}", &["\u{AC01}", "\u{1}"]), - ("\u{AC01}\u{308}\u{1}", &["\u{AC01}\u{308}", "\u{1}"]), - ("\u{AC01}\u{300}", &["\u{AC01}\u{300}"]), - ("\u{AC01}\u{308}\u{300}", &["\u{AC01}\u{308}\u{300}"]), - ("\u{AC01}\u{1100}", &["\u{AC01}", "\u{1100}"]), - ("\u{AC01}\u{308}\u{1100}", &["\u{AC01}\u{308}", "\u{1100}"]), - ("\u{AC01}\u{1160}", &["\u{AC01}", "\u{1160}"]), - ("\u{AC01}\u{308}\u{1160}", &["\u{AC01}\u{308}", "\u{1160}"]), - ("\u{AC01}\u{11A8}", &["\u{AC01}\u{11A8}"]), - ("\u{AC01}\u{308}\u{11A8}", &["\u{AC01}\u{308}", "\u{11A8}"]), - ("\u{AC01}\u{AC00}", &["\u{AC01}", "\u{AC00}"]), - ("\u{AC01}\u{308}\u{AC00}", &["\u{AC01}\u{308}", "\u{AC00}"]), - ("\u{AC01}\u{AC01}", &["\u{AC01}", "\u{AC01}"]), - ("\u{AC01}\u{308}\u{AC01}", &["\u{AC01}\u{308}", "\u{AC01}"]), - ("\u{AC01}\u{1F1E6}", &["\u{AC01}", "\u{1F1E6}"]), - ("\u{AC01}\u{308}\u{1F1E6}", &["\u{AC01}\u{308}", "\u{1F1E6}"]), - ("\u{AC01}\u{378}", &["\u{AC01}", "\u{378}"]), - ("\u{AC01}\u{308}\u{378}", &["\u{AC01}\u{308}", "\u{378}"]), - ("\u{1F1E6}\u{20}", &["\u{1F1E6}", "\u{20}"]), - ("\u{1F1E6}\u{308}\u{20}", &["\u{1F1E6}\u{308}", "\u{20}"]), - ("\u{1F1E6}\u{D}", &["\u{1F1E6}", "\u{D}"]), - ("\u{1F1E6}\u{308}\u{D}", &["\u{1F1E6}\u{308}", "\u{D}"]), - ("\u{1F1E6}\u{A}", &["\u{1F1E6}", "\u{A}"]), - ("\u{1F1E6}\u{308}\u{A}", &["\u{1F1E6}\u{308}", "\u{A}"]), - ("\u{1F1E6}\u{1}", &["\u{1F1E6}", "\u{1}"]), - ("\u{1F1E6}\u{308}\u{1}", &["\u{1F1E6}\u{308}", "\u{1}"]), - ("\u{1F1E6}\u{300}", &["\u{1F1E6}\u{300}"]), - ("\u{1F1E6}\u{308}\u{300}", &["\u{1F1E6}\u{308}\u{300}"]), - ("\u{1F1E6}\u{1100}", &["\u{1F1E6}", "\u{1100}"]), - ("\u{1F1E6}\u{308}\u{1100}", &["\u{1F1E6}\u{308}", "\u{1100}"]), - ("\u{1F1E6}\u{1160}", &["\u{1F1E6}", "\u{1160}"]), - ("\u{1F1E6}\u{308}\u{1160}", &["\u{1F1E6}\u{308}", "\u{1160}"]), - ("\u{1F1E6}\u{11A8}", &["\u{1F1E6}", "\u{11A8}"]), - ("\u{1F1E6}\u{308}\u{11A8}", &["\u{1F1E6}\u{308}", "\u{11A8}"]), - ("\u{1F1E6}\u{AC00}", &["\u{1F1E6}", "\u{AC00}"]), - ("\u{1F1E6}\u{308}\u{AC00}", &["\u{1F1E6}\u{308}", "\u{AC00}"]), - ("\u{1F1E6}\u{AC01}", &["\u{1F1E6}", "\u{AC01}"]), - ("\u{1F1E6}\u{308}\u{AC01}", &["\u{1F1E6}\u{308}", "\u{AC01}"]), - ("\u{1F1E6}\u{1F1E6}", &["\u{1F1E6}\u{1F1E6}"]), - ("\u{1F1E6}\u{308}\u{1F1E6}", &["\u{1F1E6}\u{308}", "\u{1F1E6}"]), - ("\u{1F1E6}\u{378}", &["\u{1F1E6}", "\u{378}"]), - ("\u{1F1E6}\u{308}\u{378}", &["\u{1F1E6}\u{308}", "\u{378}"]), - ("\u{378}\u{20}", &["\u{378}", "\u{20}"]), - ("\u{378}\u{308}\u{20}", &["\u{378}\u{308}", "\u{20}"]), - ("\u{378}\u{D}", &["\u{378}", "\u{D}"]), - ("\u{378}\u{308}\u{D}", &["\u{378}\u{308}", "\u{D}"]), - ("\u{378}\u{A}", &["\u{378}", "\u{A}"]), - ("\u{378}\u{308}\u{A}", &["\u{378}\u{308}", "\u{A}"]), - ("\u{378}\u{1}", &["\u{378}", "\u{1}"]), - ("\u{378}\u{308}\u{1}", &["\u{378}\u{308}", "\u{1}"]), - ("\u{378}\u{300}", &["\u{378}\u{300}"]), - ("\u{378}\u{308}\u{300}", &["\u{378}\u{308}\u{300}"]), - ("\u{378}\u{1100}", &["\u{378}", "\u{1100}"]), - ("\u{378}\u{308}\u{1100}", &["\u{378}\u{308}", "\u{1100}"]), - ("\u{378}\u{1160}", &["\u{378}", "\u{1160}"]), - ("\u{378}\u{308}\u{1160}", &["\u{378}\u{308}", "\u{1160}"]), - ("\u{378}\u{11A8}", &["\u{378}", "\u{11A8}"]), - ("\u{378}\u{308}\u{11A8}", &["\u{378}\u{308}", "\u{11A8}"]), - ("\u{378}\u{AC00}", &["\u{378}", "\u{AC00}"]), - ("\u{378}\u{308}\u{AC00}", &["\u{378}\u{308}", "\u{AC00}"]), - ("\u{378}\u{AC01}", &["\u{378}", "\u{AC01}"]), - ("\u{378}\u{308}\u{AC01}", &["\u{378}\u{308}", "\u{AC01}"]), - ("\u{378}\u{1F1E6}", &["\u{378}", "\u{1F1E6}"]), - ("\u{378}\u{308}\u{1F1E6}", &["\u{378}\u{308}", "\u{1F1E6}"]), - ("\u{378}\u{378}", &["\u{378}", "\u{378}"]), - ("\u{378}\u{308}\u{378}", &["\u{378}\u{308}", "\u{378}"]), - ("\u{61}\u{1F1E6}\u{62}", &["\u{61}", "\u{1F1E6}", "\u{62}"]), - ("\u{1F1F7}\u{1F1FA}", &["\u{1F1F7}\u{1F1FA}"]), - ("\u{1F1F7}\u{1F1FA}\u{1F1F8}", &["\u{1F1F7}\u{1F1FA}\u{1F1F8}"]), - ("\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}", - &["\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}"]), - ("\u{1F1F7}\u{1F1FA}\u{200B}\u{1F1F8}\u{1F1EA}", - &["\u{1F1F7}\u{1F1FA}", "\u{200B}", "\u{1F1F8}\u{1F1EA}"]), - ("\u{1F1E6}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{1F1E7}\u{1F1E8}"]), - ("\u{1F1E6}\u{200D}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{200D}", - "\u{1F1E7}\u{1F1E8}"]), - ("\u{1F1E6}\u{1F1E7}\u{200D}\u{1F1E8}", - &["\u{1F1E6}\u{1F1E7}\u{200D}", "\u{1F1E8}"]), - ("\u{20}\u{200D}\u{646}", &["\u{20}\u{200D}", "\u{646}"]), - ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]), - ]; - - let test_diff: [(_, &[_], &[_]); 23] = [ - ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}", - &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}", - &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}", - &["\u{A}", "\u{308}\u{903}"], &["\u{A}", "\u{308}", "\u{903}"]), ("\u{1}\u{308}\u{903}", - &["\u{1}", "\u{308}\u{903}"], &["\u{1}", "\u{308}", "\u{903}"]), ("\u{300}\u{903}", - &["\u{300}\u{903}"], &["\u{300}", "\u{903}"]), ("\u{300}\u{308}\u{903}", - &["\u{300}\u{308}\u{903}"], &["\u{300}\u{308}", "\u{903}"]), ("\u{903}\u{903}", - &["\u{903}\u{903}"], &["\u{903}", "\u{903}"]), ("\u{903}\u{308}\u{903}", - &["\u{903}\u{308}\u{903}"], &["\u{903}\u{308}", "\u{903}"]), ("\u{1100}\u{903}", - &["\u{1100}\u{903}"], &["\u{1100}", "\u{903}"]), ("\u{1100}\u{308}\u{903}", - &["\u{1100}\u{308}\u{903}"], &["\u{1100}\u{308}", "\u{903}"]), ("\u{1160}\u{903}", - &["\u{1160}\u{903}"], &["\u{1160}", "\u{903}"]), ("\u{1160}\u{308}\u{903}", - &["\u{1160}\u{308}\u{903}"], &["\u{1160}\u{308}", "\u{903}"]), ("\u{11A8}\u{903}", - &["\u{11A8}\u{903}"], &["\u{11A8}", "\u{903}"]), ("\u{11A8}\u{308}\u{903}", - &["\u{11A8}\u{308}\u{903}"], &["\u{11A8}\u{308}", "\u{903}"]), ("\u{AC00}\u{903}", - &["\u{AC00}\u{903}"], &["\u{AC00}", "\u{903}"]), ("\u{AC00}\u{308}\u{903}", - &["\u{AC00}\u{308}\u{903}"], &["\u{AC00}\u{308}", "\u{903}"]), ("\u{AC01}\u{903}", - &["\u{AC01}\u{903}"], &["\u{AC01}", "\u{903}"]), ("\u{AC01}\u{308}\u{903}", - &["\u{AC01}\u{308}\u{903}"], &["\u{AC01}\u{308}", "\u{903}"]), ("\u{1F1E6}\u{903}", - &["\u{1F1E6}\u{903}"], &["\u{1F1E6}", "\u{903}"]), ("\u{1F1E6}\u{308}\u{903}", - &["\u{1F1E6}\u{308}\u{903}"], &["\u{1F1E6}\u{308}", "\u{903}"]), ("\u{378}\u{903}", - &["\u{378}\u{903}"], &["\u{378}", "\u{903}"]), ("\u{378}\u{308}\u{903}", - &["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]), - ]; - - for &(s, g) in &test_same[..] { - // test forward iterator - assert!(order::equals(s.graphemes(true), g.iter().cloned())); - assert!(order::equals(s.graphemes(false), g.iter().cloned())); - - // test reverse iterator - assert!(order::equals(s.graphemes(true).rev(), g.iter().rev().cloned())); - assert!(order::equals(s.graphemes(false).rev(), g.iter().rev().cloned())); - } - - for &(s, gt, gf) in &test_diff { - // test forward iterator - assert!(order::equals(s.graphemes(true), gt.iter().cloned())); - assert!(order::equals(s.graphemes(false), gf.iter().cloned())); - - // test reverse iterator - assert!(order::equals(s.graphemes(true).rev(), gt.iter().rev().cloned())); - assert!(order::equals(s.graphemes(false).rev(), gf.iter().rev().cloned())); - } - - // test the indices iterators - let s = "a̐éö̲\r\n"; - let gr_inds = s.grapheme_indices(true).collect::>(); - let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; - assert_eq!(gr_inds, b); - let gr_inds = s.grapheme_indices(true).rev().collect::>(); - let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0, "a̐")]; - assert_eq!(gr_inds, b); - let mut gr_inds_iter = s.grapheme_indices(true); - { - let gr_inds = gr_inds_iter.by_ref(); - let e1 = gr_inds.size_hint(); - assert_eq!(e1, (1, Some(13))); - let c = gr_inds.count(); - assert_eq!(c, 4); - } - let e2 = gr_inds_iter.size_hint(); - assert_eq!(e2, (0, Some(0))); - - // make sure the reverse iterator does the right thing with "\n" at beginning of string - let s = "\n\r\n\r"; - let gr = s.graphemes(true).rev().collect::>(); - let b: &[_] = &["\r", "\r\n", "\n"]; - assert_eq!(gr, b); - } - - #[test] - fn test_split_strator() { - fn t(s: &str, sep: &str, u: &[&str]) { - let v: Vec<&str> = s.split_str(sep).collect(); - assert_eq!(v, u); - } - t("--1233345--", "12345", &["--1233345--"]); - t("abc::hello::there", "::", &["abc", "hello", "there"]); - t("::hello::there", "::", &["", "hello", "there"]); - t("hello::there::", "::", &["hello", "there", ""]); - t("::hello::there::", "::", &["", "hello", "there", ""]); - t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); - t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); - t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); - t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); - t("", ".", &[""]); - t("zz", "zz", &["",""]); - t("ok", "z", &["ok"]); - t("zzz", "zz", &["","z"]); - t("zzzzz", "zz", &["","","z"]); - } - - #[test] - fn test_str_default() { - use core::default::Default; - fn t() { - let s: S = Default::default(); - assert_eq!(s.as_slice(), ""); - } - - t::<&str>(); - t::(); - } - - #[test] - fn test_str_container() { - fn sum_len(v: &[&str]) -> usize { - v.iter().map(|x| x.len()).sum() - } - - let s = String::from_str("01234"); - assert_eq!(5, sum_len(&["012", "", "34"])); - assert_eq!(5, sum_len(&[&String::from_str("01"), - &String::from_str("2"), - &String::from_str("34"), - &String::from_str("")])); - assert_eq!(5, sum_len(&[&s])); - } - - #[test] - fn test_str_from_utf8() { - let xs = b"hello"; - assert_eq!(from_utf8(xs), Ok("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF"; - assert_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); - } -} - -#[cfg(test)] -mod bench { - use super::*; - use prelude::{SliceExt, IteratorExt, SliceConcatExt}; - use test::Bencher; - use test::black_box; - - #[bench] - fn char_iterator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); - } - - #[bench] - fn char_iterator_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars() { black_box(ch); } - }); - } - - #[bench] - fn char_iterator_ascii(b: &mut Bencher) { - let s = "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"; - - b.iter(|| s.chars().count()); - } - - #[bench] - fn char_iterator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().rev().count()); - } - - #[bench] - fn char_iterator_rev_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars().rev() { black_box(ch); } - }); - } - - #[bench] - fn char_indicesator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); - - b.iter(|| assert_eq!(s.char_indices().count(), len)); - } - - #[bench] - fn char_indicesator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); - - b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); - } - - #[bench] - fn split_unicode_ascii(b: &mut Bencher) { - let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; - - b.iter(|| assert_eq!(s.split('V').count(), 3)); - } - - #[bench] - fn split_unicode_not_ascii(b: &mut Bencher) { - struct NotAscii(char); - impl CharEq for NotAscii { - fn matches(&mut self, c: char) -> bool { - let NotAscii(cc) = *self; - cc == c - } - fn only_ascii(&self) -> bool { false } - } - let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; - - b.iter(|| assert_eq!(s.split(NotAscii('V')).count(), 3)); - } - - - #[bench] - fn split_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(' ').count(), len)); - } - - #[bench] - fn split_not_ascii(b: &mut Bencher) { - struct NotAscii(char); - impl CharEq for NotAscii { - #[inline] - fn matches(&mut self, c: char) -> bool { - let NotAscii(cc) = *self; - cc == c - } - fn only_ascii(&self) -> bool { false } - } - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(NotAscii(' ')).count(), len)); - } - - #[bench] - fn split_extern_fn(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - fn pred(c: char) -> bool { c == ' ' } - - b.iter(|| assert_eq!(s.split(pred).count(), len)); - } - - #[bench] - fn split_closure(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); - } - - #[bench] - fn split_slice(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - let c: &[char] = &[' ']; - b.iter(|| assert_eq!(s.split(c).count(), len)); - } - - #[bench] - fn bench_connect(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let sep = "→"; - let v = vec![s, s, s, s, s, s, s, s, s, s]; - b.iter(|| { - assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); - }) - } - - #[bench] - fn bench_contains_short_short(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "sit"; - - b.iter(|| { - assert!(haystack.contains(needle)); - }) - } - - #[bench] - fn bench_contains_short_long(b: &mut Bencher) { - let haystack = "\ -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ -ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ -eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ -sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ -tempus vel, gravida nec quam. - -In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ -sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ -diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ -lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ -eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ -interdum. Curabitur ut nisi justo. - -Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ -mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ -lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ -est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ -felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ -ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ -feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ -Aliquam sit amet placerat lorem. - -Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ -mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ -Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ -lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ -suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ -cursus accumsan. - -Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ -feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ -vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ -leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ -malesuada sollicitudin quam eu fermentum."; - let needle = "english"; - - b.iter(|| { - assert!(!haystack.contains(needle)); - }) - } - - #[bench] - fn bench_contains_bad_naive(b: &mut Bencher) { - let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let needle = "aaaaaaaab"; - - b.iter(|| { - assert!(!haystack.contains(needle)); - }) + /// Returns the lowercase equivalent of this string. + /// + /// # Examples + /// + /// let s = "HELLO"; + /// assert_eq!(s.to_lowercase(), "hello"); + #[unstable(feature = "collections")] + pub fn to_lowercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self[..].chars().flat_map(|c| c.to_lowercase())); + return s; } - #[bench] - fn bench_contains_equal(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - - b.iter(|| { - assert!(haystack.contains(needle)); - }) + /// Returns the uppercase equivalent of this string. + /// + /// # Examples + /// + /// let s = "hello"; + /// assert_eq!(s.to_uppercase(), "HELLO"); + #[unstable(feature = "collections")] + pub fn to_uppercase(&self) -> String { + let mut s = String::with_capacity(self.len()); + s.extend(self[..].chars().flat_map(|c| c.to_uppercase())); + return s; } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 3b179d0b94..7a77253209 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -17,19 +17,19 @@ use core::prelude::*; use core::default::Default; -use core::error::Error; use core::fmt; use core::hash; use core::iter::{IntoIterator, FromIterator}; use core::mem; use core::ops::{self, Deref, Add, Index}; use core::ptr; -use core::raw::Slice as RawSlice; +use core::slice; +use core::str::Pattern; use unicode::str as unicode_str; use unicode::str::Utf16Item; use borrow::{Cow, IntoCow}; -use str::{self, CharRange, FromStr, Utf8Error}; +use str::{self, FromStr, Utf8Error}; use vec::{DerefVec, Vec, as_vec}; /// A growable string stored as a UTF-8 encoded buffer. @@ -90,14 +90,26 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections, core)] /// let s = String::from_str("hello"); - /// assert_eq!(s.as_slice(), "hello"); + /// assert_eq!(&s[..], "hello"); /// ``` #[inline] #[unstable(feature = "collections", reason = "needs investigation to see if to_string() can match perf")] + #[cfg(not(test))] pub fn from_str(string: &str) -> String { - String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) } + String { vec: <[_]>::to_vec(string.as_bytes()) } + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Since we don't + // require this method for testing purposes, I'll just stub it + // NB see the slice::hack module in slice.rs for more information + #[inline] + #[cfg(test)] + pub fn from_str(_: &str) -> String { + panic!("not available with cfg(test)"); } /// Returns the vector as a string buffer, if possible, taking care not to @@ -110,7 +122,8 @@ impl String { /// /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::str::Utf8Error; /// /// let hello_vec = vec![104, 101, 108, 108, 111]; @@ -120,7 +133,7 @@ impl String { /// let invalid_vec = vec![240, 144, 128]; /// let s = String::from_utf8(invalid_vec).err().unwrap(); /// assert_eq!(s.utf8_error(), Utf8Error::TooShort); - /// assert_eq!(s.into_bytes(), vec![240, 144, 128]); + /// assert_eq!(s.into_bytes(), [240, 144, 128]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -136,10 +149,10 @@ impl String { /// /// # Examples /// - /// ```rust + /// ``` /// let input = b"Hello \xF0\x90\x80World"; /// let output = String::from_utf8_lossy(input); - /// assert_eq!(output.as_slice(), "Hello \u{FFFD}World"); + /// assert_eq!(output, "Hello \u{FFFD}World"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { @@ -153,8 +166,8 @@ impl String { } } - static TAG_CONT_U8: u8 = 128u8; - static REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 + const TAG_CONT_U8: u8 = 128; + const REPLACEMENT: &'static [u8] = b"\xEF\xBF\xBD"; // U+FFFD in UTF-8 let total = v.len(); fn unsafe_get(xs: &[u8], i: usize) -> u8 { unsafe { *xs.get_unchecked(i) } @@ -195,14 +208,14 @@ impl String { } })} - if byte < 128u8 { + if byte < 128 { // subseqidx handles this } else { let w = unicode_str::utf8_char_width(byte); match w { 2 => { - if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 { + if safe_get(v, i, total) & 192 != TAG_CONT_U8 { error!(); continue; } @@ -220,7 +233,7 @@ impl String { } } i += 1; - if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 { + if safe_get(v, i, total) & 192 != TAG_CONT_U8 { error!(); continue; } @@ -237,12 +250,12 @@ impl String { } } i += 1; - if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 { + if safe_get(v, i, total) & 192 != TAG_CONT_U8 { error!(); continue; } i += 1; - if safe_get(v, i, total) & 192u8 != TAG_CONT_U8 { + if safe_get(v, i, total) & 192 != TAG_CONT_U8 { error!(); continue; } @@ -268,7 +281,7 @@ impl String { /// /// # Examples /// - /// ```rust + /// ``` /// // 𝄞music /// let mut v = &mut [0xD834, 0xDD1E, 0x006d, 0x0075, /// 0x0073, 0x0069, 0x0063]; @@ -296,7 +309,7 @@ impl String { /// /// # Examples /// - /// ```rust + /// ``` /// // 𝄞music /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, /// 0x0073, 0xDD1E, 0x0069, 0x0063, @@ -314,6 +327,7 @@ impl String { /// Creates a new `String` from a length, capacity, and pointer. /// /// This is unsafe because: + /// /// * We call `Vec::from_raw_parts` to get a `Vec`; /// * We assume that the `Vec` contains valid UTF-8. #[inline] @@ -338,9 +352,10 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let s = String::from_str("hello"); /// let bytes = s.into_bytes(); - /// assert_eq!(bytes, vec![104, 101, 108, 108, 111]); + /// assert_eq!(bytes, [104, 101, 108, 108, 111]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -348,14 +363,23 @@ impl String { self.vec } + /// Extract a string slice containing the entire string. + #[inline] + #[unstable(feature = "convert", + reason = "waiting on RFC revision")] + pub fn as_str(&self) -> &str { + self + } + /// Pushes the given string onto this string buffer. /// /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("foo"); /// s.push_str("bar"); - /// assert_eq!(s.as_slice(), "foobar"); + /// assert_eq!(s, "foobar"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -429,6 +453,7 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("foo"); /// s.reserve(100); /// assert!(s.capacity() >= 100); @@ -446,11 +471,12 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("abc"); /// s.push('1'); /// s.push('2'); /// s.push('3'); - /// assert_eq!(s.as_slice(), "abc123"); + /// assert_eq!(s, "abc123"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -467,11 +493,11 @@ impl String { unsafe { // Attempt to not use an intermediate buffer by just pushing bytes // directly onto this string. - let slice = RawSlice { - data: self.vec.as_ptr().offset(cur_len as isize), - len: 4, - }; - let used = ch.encode_utf8(mem::transmute(slice)).unwrap_or(0); + let slice = slice::from_raw_parts_mut ( + self.vec.as_mut_ptr().offset(cur_len as isize), + 4 + ); + let used = ch.encode_utf8(slice).unwrap_or(0); self.vec.set_len(cur_len + used); } } @@ -481,6 +507,7 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let s = String::from_str("hello"); /// let b: &[_] = &[104, 101, 108, 108, 111]; /// assert_eq!(s.as_bytes(), b); @@ -501,9 +528,10 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("hello"); /// s.truncate(2); - /// assert_eq!(s.as_slice(), "he"); + /// assert_eq!(s, "he"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -518,6 +546,7 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("foo"); /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); @@ -532,9 +561,9 @@ impl String { return None } - let CharRange {ch, next} = self.char_range_at_reverse(len); + let ch = self.char_at_reverse(len); unsafe { - self.vec.set_len(next); + self.vec.set_len(len - ch.len_utf8()); } Some(ch) } @@ -555,6 +584,7 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("foo"); /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); @@ -566,11 +596,12 @@ impl String { let len = self.len(); assert!(idx <= len); - let CharRange { ch, next } = self.char_range_at(idx); + let ch = self.char_at(idx); + let next = idx + ch.len_utf8(); unsafe { - ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize), - self.vec.as_ptr().offset(next as isize), - len - next); + ptr::copy(self.vec.as_ptr().offset(next as isize), + self.vec.as_mut_ptr().offset(idx as isize), + len - next); self.vec.set_len(len - (next - idx)); } ch @@ -598,12 +629,12 @@ impl String { let amt = ch.encode_utf8(&mut bits).unwrap(); unsafe { - ptr::copy_memory(self.vec.as_mut_ptr().offset((idx + amt) as isize), - self.vec.as_ptr().offset(idx as isize), - len - idx); - ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize), - bits.as_ptr(), - amt); + ptr::copy(self.vec.as_ptr().offset(idx as isize), + self.vec.as_mut_ptr().offset((idx + amt) as isize), + len - idx); + ptr::copy(bits.as_ptr(), + self.vec.as_mut_ptr().offset(idx as isize), + amt); self.vec.set_len(len + amt); } } @@ -616,13 +647,14 @@ impl String { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut s = String::from_str("hello"); /// unsafe { /// let vec = s.as_mut_vec(); - /// assert!(vec == &mut vec![104, 101, 108, 108, 111]); + /// assert!(vec == &[104, 101, 108, 108, 111]); /// vec.reverse(); /// } - /// assert_eq!(s.as_slice(), "olleh"); + /// assert_eq!(s, "olleh"); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -690,11 +722,6 @@ impl fmt::Display for FromUtf8Error { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf8Error { - fn description(&self) -> &str { "invalid utf-8" } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for FromUtf16Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -702,11 +729,6 @@ impl fmt::Display for FromUtf16Error { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf16Error { - fn description(&self) -> &str { "invalid utf-16" } -} - #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { fn from_iter>(iter: I) -> String { @@ -752,6 +774,25 @@ impl<'a> Extend<&'a str> for String { } } +/// A convenience impl that delegates to the impl for `&str` +impl<'a, 'b> Pattern<'a> for &'b String { + type Searcher = <&'b str as Pattern<'a>>::Searcher; + + fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher { + self[..].into_searcher(haystack) + } + + #[inline] + fn is_contained_in(self, haystack: &'a str) -> bool { + self[..].is_contained_in(haystack) + } + + #[inline] + fn is_prefix_of(self, haystack: &'a str) -> bool { + self[..].is_prefix_of(haystack) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for String { #[inline] @@ -801,9 +842,9 @@ impl<'a, 'b> PartialEq> for &'b str { } #[unstable(feature = "collections", reason = "waiting on Str stabilization")] +#[allow(deprecated)] impl Str for String { #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn as_slice(&self) -> &str { unsafe { mem::transmute(&*self.vec) } } @@ -834,16 +875,7 @@ impl fmt::Debug for String { } } -#[unstable(feature = "collections", reason = "waiting on Hash stabilization")] -#[cfg(stage0)] -impl hash::Hash for String { - #[inline] - fn hash(&self, hasher: &mut H) { - (**self).hash(hasher) - } -} #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl hash::Hash for String { #[inline] fn hash(&self, hasher: &mut H) { @@ -866,32 +898,36 @@ impl<'a> Add<&'a str> for String { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for String { type Output = str; + #[inline] - fn index(&self, index: &ops::Range) -> &str { - &self[..][*index] + fn index(&self, index: ops::Range) -> &str { + &self[..][index] } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for String { type Output = str; + #[inline] - fn index(&self, index: &ops::RangeTo) -> &str { - &self[..][*index] + fn index(&self, index: ops::RangeTo) -> &str { + &self[..][index] } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for String { type Output = str; + #[inline] - fn index(&self, index: &ops::RangeFrom) -> &str { - &self[..][*index] + fn index(&self, index: ops::RangeFrom) -> &str { + &self[..][index] } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for String { type Output = str; + #[inline] - fn index(&self, _index: &ops::RangeFull) -> &str { + fn index(&self, _index: ops::RangeFull) -> &str { unsafe { mem::transmute(&*self.vec) } } } @@ -926,6 +962,7 @@ impl<'a> Deref for DerefString<'a> { /// # Examples /// /// ``` +/// # #![feature(collections)] /// use std::string::as_string; /// /// fn string_consumer(s: String) { @@ -970,6 +1007,44 @@ impl ToString for T { } #[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for String { + fn as_ref(&self) -> &str { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&'a str> for String { + #[inline] + fn from(s: &'a str) -> String { + s.to_string() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&'a str> for Cow<'a, str> { + #[inline] + fn from(s: &'a str) -> Cow<'a, str> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From for Cow<'a, str> { + #[inline] + fn from(s: String) -> Cow<'a, str> { + Cow::Owned(s) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Into> for String { + fn into(self) -> Vec { + self.into_bytes() + } +} + +#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")] impl IntoCow<'static, str> for String { #[inline] fn into_cow(self) -> Cow<'static, str> { @@ -977,7 +1052,7 @@ impl IntoCow<'static, str> for String { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")] impl<'a> IntoCow<'a, str> for &'a str { #[inline] fn into_cow(self) -> Cow<'a, str> { @@ -985,6 +1060,7 @@ impl<'a> IntoCow<'a, str> for &'a str { } } +#[allow(deprecated)] impl<'a> Str for Cow<'a, str> { #[inline] fn as_slice<'b>(&'b self) -> &'b str { @@ -992,11 +1068,6 @@ impl<'a> Str for Cow<'a, str> { } } -/// A clone-on-write string -#[deprecated(since = "1.0.0", reason = "use Cow<'a, str> instead")] -#[stable(feature = "rust1", since = "1.0.0")] -pub type CowString<'a> = Cow<'a, str>; - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { #[inline] @@ -1005,450 +1076,3 @@ impl fmt::Write for String { Ok(()) } } - -#[cfg(test)] -mod tests { - use prelude::*; - use test::Bencher; - - use str::Utf8Error; - use core::iter::repeat; - use super::{as_string, CowString}; - - #[test] - fn test_as_string() { - let x = "foo"; - assert_eq!(x, &**as_string(x)); - } - - #[test] - fn test_from_str() { - let owned: Option<::std::string::String> = "string".parse().ok(); - assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); - } - - #[test] - fn test_unsized_to_string() { - let s: &str = "abc"; - let _: String = (*s).to_string(); - } - - #[test] - fn test_from_utf8() { - let xs = b"hello".to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), - String::from_str("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), - String::from_str("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF".to_vec(); - let err = String::from_utf8(xs).err().unwrap(); - assert_eq!(err.utf8_error(), Utf8Error::TooShort); - assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); - } - - #[test] - fn test_from_utf8_lossy() { - let xs = b"hello"; - let ys: CowString = "hello".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - let ys: CowString = "ศไทย中华Việt Nam".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = b"Hello\xC2 There\xFF Goodbye"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()); - - let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()); - - let xs = b"\xF5foo\xF5\x80bar"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()); - - let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()); - - let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; - assert_eq!(String::from_utf8_lossy(xs), - String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()); - - let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; - assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\ - foo\u{10000}bar").into_cow()); - - // surrogates - let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; - assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}foo\ - \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()); - } - - #[test] - fn test_from_utf16() { - let pairs = - [(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), - vec![0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16, - 0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16, - 0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16, - 0xd800_u16, 0xdf30_u16, 0x000a_u16]), - - (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), - vec![0xd801_u16, 0xdc12_u16, 0xd801_u16, - 0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16, - 0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16, - 0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16, - 0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16, - 0x000a_u16]), - - (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), - vec![0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16, - 0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16, - 0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16, - 0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16, - 0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16, - 0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16, - 0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]), - - (String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), - vec![0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16, - 0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16, - 0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16, - 0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16, - 0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16, - 0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16, - 0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16, - 0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16, - 0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16, - 0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16, - 0x000a_u16 ]), - // Issue #12318, even-numbered non-BMP planes - (String::from_str("\u{20000}"), - vec![0xD840, 0xDC00])]; - - for p in &pairs { - let (s, u) = (*p).clone(); - let s_as_utf16 = s.utf16_units().collect::>(); - let u_as_string = String::from_utf16(&u).unwrap(); - - assert!(::unicode::str::is_utf16(&u)); - assert_eq!(s_as_utf16, u); - - assert_eq!(u_as_string, s); - assert_eq!(String::from_utf16_lossy(&u), s); - - assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s); - assert_eq!(u_as_string.utf16_units().collect::>(), u); - } - } - - #[test] - fn test_utf16_invalid() { - // completely positive cases tested above. - // lead + eof - assert!(String::from_utf16(&[0xD800]).is_err()); - // lead + lead - assert!(String::from_utf16(&[0xD800, 0xD800]).is_err()); - - // isolated trail - assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err()); - - // general - assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err()); - } - - #[test] - fn test_from_utf16_lossy() { - // completely positive cases tested above. - // lead + eof - assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from_str("\u{FFFD}")); - // lead + lead - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), - String::from_str("\u{FFFD}\u{FFFD}")); - - // isolated trail - assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}")); - - // general - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), - String::from_str("\u{FFFD}𐒋\u{FFFD}")); - } - - #[test] - fn test_push_bytes() { - let mut s = String::from_str("ABC"); - unsafe { - let mv = s.as_mut_vec(); - mv.push_all(&[b'D']); - } - assert_eq!(s, "ABCD"); - } - - #[test] - fn test_push_str() { - let mut s = String::new(); - s.push_str(""); - assert_eq!(&s[0..], ""); - s.push_str("abc"); - assert_eq!(&s[0..], "abc"); - s.push_str("ประเทศไทย中华Việt Nam"); - assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam"); - } - - #[test] - fn test_push() { - let mut data = String::from_str("ประเทศไทย中"); - data.push('华'); - data.push('b'); // 1 byte - data.push('¢'); // 2 byte - data.push('€'); // 3 byte - data.push('𤭢'); // 4 byte - assert_eq!(data, "ประเทศไทย中华b¢€𤭢"); - } - - #[test] - fn test_pop() { - let mut data = String::from_str("ประเทศไทย中华b¢€𤭢"); - assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes - assert_eq!(data.pop().unwrap(), '€'); // 3 bytes - assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes - assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes - assert_eq!(data.pop().unwrap(), '华'); - assert_eq!(data, "ประเทศไทย中"); - } - - #[test] - fn test_str_truncate() { - let mut s = String::from_str("12345"); - s.truncate(5); - assert_eq!(s, "12345"); - s.truncate(3); - assert_eq!(s, "123"); - s.truncate(0); - assert_eq!(s, ""); - - let mut s = String::from_str("12345"); - let p = s.as_ptr(); - s.truncate(3); - s.push_str("6"); - let p_ = s.as_ptr(); - assert_eq!(p_, p); - } - - #[test] - #[should_fail] - fn test_str_truncate_invalid_len() { - let mut s = String::from_str("12345"); - s.truncate(6); - } - - #[test] - #[should_fail] - fn test_str_truncate_split_codepoint() { - let mut s = String::from_str("\u{FC}"); // ü - s.truncate(1); - } - - #[test] - fn test_str_clear() { - let mut s = String::from_str("12345"); - s.clear(); - assert_eq!(s.len(), 0); - assert_eq!(s, ""); - } - - #[test] - fn test_str_add() { - let a = String::from_str("12345"); - let b = a + "2"; - let b = b + "2"; - assert_eq!(b.len(), 7); - assert_eq!(b, "1234522"); - } - - #[test] - fn remove() { - let mut s = "ศไทย中华Việt Nam; foobar".to_string();; - assert_eq!(s.remove(0), 'ศ'); - assert_eq!(s.len(), 33); - assert_eq!(s, "ไทย中华Việt Nam; foobar"); - assert_eq!(s.remove(17), 'ệ'); - assert_eq!(s, "ไทย中华Vit Nam; foobar"); - } - - #[test] #[should_fail] - fn remove_bad() { - "ศ".to_string().remove(1); - } - - #[test] - fn insert() { - let mut s = "foobar".to_string(); - s.insert(0, 'ệ'); - assert_eq!(s, "ệfoobar"); - s.insert(6, 'ย'); - assert_eq!(s, "ệfooยbar"); - } - - #[test] #[should_fail] fn insert_bad1() { "".to_string().insert(1, 't'); } - #[test] #[should_fail] fn insert_bad2() { "ệ".to_string().insert(1, 't'); } - - #[test] - fn test_slicing() { - let s = "foobar".to_string(); - assert_eq!("foobar", &s[..]); - assert_eq!("foo", &s[..3]); - assert_eq!("bar", &s[3..]); - assert_eq!("oob", &s[1..4]); - } - - #[test] - fn test_simple_types() { - assert_eq!(1.to_string(), "1"); - assert_eq!((-1).to_string(), "-1"); - assert_eq!(200.to_string(), "200"); - assert_eq!(2u8.to_string(), "2"); - assert_eq!(true.to_string(), "true"); - assert_eq!(false.to_string(), "false"); - assert_eq!(("hi".to_string()).to_string(), "hi"); - } - - #[test] - fn test_vectors() { - let x: Vec = vec![]; - assert_eq!(format!("{:?}", x), "[]"); - assert_eq!(format!("{:?}", vec![1]), "[1]"); - assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); - assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == - "[[], [1], [1, 1]]"); - } - - #[test] - fn test_from_iterator() { - let s = "ศไทย中华Việt Nam".to_string(); - let t = "ศไทย中华"; - let u = "Việt Nam"; - - let a: String = s.chars().collect(); - assert_eq!(s, a); - - let mut b = t.to_string(); - b.extend(u.chars()); - assert_eq!(s, b); - - let c: String = vec![t, u].into_iter().collect(); - assert_eq!(s, c); - - let mut d = t.to_string(); - d.extend(vec![u].into_iter()); - assert_eq!(s, d); - } - - #[bench] - fn bench_with_capacity(b: &mut Bencher) { - b.iter(|| { - String::with_capacity(100) - }); - } - - #[bench] - fn bench_push_str(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - b.iter(|| { - let mut r = String::new(); - r.push_str(s); - }); - } - - const REPETITIONS: u64 = 10_000; - - #[bench] - fn bench_push_str_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push_str("a") - } - }); - } - - #[bench] - fn bench_push_char_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('a') - } - }); - } - - #[bench] - fn bench_push_char_two_bytes(b: &mut Bencher) { - b.bytes = REPETITIONS * 2; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('â') - } - }); - } - - #[bench] - fn from_utf8_lossy_100_ascii(b: &mut Bencher) { - let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { - let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_invalid(b: &mut Bencher) { - let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); - } - - #[bench] - fn from_utf8_lossy_100_invalid(b: &mut Bencher) { - let s = repeat(0xf5u8).take(100).collect::>(); - b.iter(|| { - let _ = String::from_utf8_lossy(&s); - }); - } - - #[bench] - fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - // ensure our operation produces an exact-size string before we benchmark it - let mut r = String::with_capacity(s.len()); - r.push_str(s); - assert_eq!(r.len(), r.capacity()); - b.iter(|| { - let mut r = String::with_capacity(s.len()); - r.push_str(s); - r.shrink_to_fit(); - r - }); - } -} diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 1cc2a5235a..087b065031 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A growable list type with heap-allocated contents, written `Vec` but pronounced 'vector.' +//! A growable list type with heap-allocated contents, written `Vec` but +//! pronounced 'vector.' //! //! Vectors have `O(1)` indexing, push (to the end) and pop (from the end). //! @@ -51,7 +52,7 @@ use core::prelude::*; use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::cmp::max; -use core::cmp::{Ordering}; +use core::cmp::Ordering; use core::default::Default; use core::fmt; use core::hash::{self, Hash}; @@ -59,12 +60,10 @@ use core::intrinsics::assume; use core::iter::{repeat, FromIterator, IntoIterator}; use core::marker::PhantomData; use core::mem; -use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut, Deref, Add}; use core::ops; use core::ptr; use core::ptr::Unique; -use core::raw::Slice as RawSlice; use core::slice; use core::usize; @@ -75,6 +74,7 @@ use borrow::{Cow, IntoCow}; /// # Examples /// /// ``` +/// # #![feature(collections)] /// let mut vec = Vec::new(); /// vec.push(1); /// vec.push(2); @@ -93,7 +93,7 @@ use borrow::{Cow, IntoCow}; /// for x in vec.iter() { /// println!("{}", x); /// } -/// assert_eq!(vec, vec![7, 1, 2, 3]); +/// assert_eq!(vec, [7, 1, 2, 3]); /// ``` /// /// The `vec!` macro is provided to make initialization more convenient: @@ -101,7 +101,7 @@ use borrow::{Cow, IntoCow}; /// ``` /// let mut vec = vec![1, 2, 3]; /// vec.push(4); -/// assert_eq!(vec, vec![1, 2, 3, 4]); +/// assert_eq!(vec, [1, 2, 3, 4]); /// ``` /// /// Use a `Vec` as an efficient stack: @@ -125,17 +125,19 @@ use borrow::{Cow, IntoCow}; /// /// # Capacity and reallocation /// -/// The capacity of a vector is the amount of space allocated for any future elements that will be -/// added onto the vector. This is not to be confused with the *length* of a vector, which -/// specifies the number of actual elements within the vector. If a vector's length exceeds its -/// capacity, its capacity will automatically be increased, but its elements will have to be +/// The capacity of a vector is the amount of space allocated for any future +/// elements that will be added onto the vector. This is not to be confused with +/// the *length* of a vector, which specifies the number of actual elements +/// within the vector. If a vector's length exceeds its capacity, its capacity +/// will automatically be increased, but its elements will have to be /// reallocated. /// -/// For example, a vector with capacity 10 and length 0 would be an empty vector with space for 10 -/// more elements. Pushing 10 or fewer elements onto the vector will not change its capacity or -/// cause reallocation to occur. However, if the vector's length is increased to 11, it will have -/// to reallocate, which can be slow. For this reason, it is recommended to use -/// `Vec::with_capacity` whenever possible to specify how big the vector is expected to get. +/// For example, a vector with capacity 10 and length 0 would be an empty vector +/// with space for 10 more elements. Pushing 10 or fewer elements onto the +/// vector will not change its capacity or cause reallocation to occur. However, +/// if the vector's length is increased to 11, it will have to reallocate, which +/// can be slow. For this reason, it is recommended to use `Vec::with_capacity` +/// whenever possible to specify how big the vector is expected to get. #[unsafe_no_drop_flag] #[stable(feature = "rust1", since = "1.0.0")] pub struct Vec { @@ -242,7 +244,7 @@ impl Vec { /// /// // Put everything back together into a Vec /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, vec![4, 5, 6]); + /// assert_eq!(rebuilt, [4, 5, 6]); /// } /// } /// ``` @@ -258,16 +260,17 @@ impl Vec { /// Creates a vector by copying the elements from a raw pointer. /// - /// This function will copy `elts` contiguous elements starting at `ptr` into a new allocation - /// owned by the returned `Vec`. The elements of the buffer are copied into the vector - /// without cloning, as if `ptr::read()` were called on them. + /// This function will copy `elts` contiguous elements starting at `ptr` + /// into a new allocation owned by the returned `Vec`. The elements of + /// the buffer are copied into the vector without cloning, as if + /// `ptr::read()` were called on them. #[inline] #[unstable(feature = "collections", reason = "may be better expressed via composition")] pub unsafe fn from_raw_buf(ptr: *const T, elts: usize) -> Vec { let mut dst = Vec::with_capacity(elts); dst.set_len(elts); - ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts); + ptr::copy_nonoverlapping(ptr, dst.as_mut_ptr(), elts); dst } @@ -286,8 +289,9 @@ impl Vec { self.cap } - /// Reserves capacity for at least `additional` more elements to be inserted in the given - /// `Vec`. The collection may reserve more space to avoid frequent reallocations. + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. /// /// # Panics /// @@ -347,6 +351,7 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut vec = Vec::with_capacity(10); /// vec.push_all(&[1, 2, 3]); /// assert_eq!(vec.capacity(), 10); @@ -384,11 +389,11 @@ impl Vec { /// Note that this will drop any excess capacity. Calling this and /// converting back to a vector with `into_vec()` is equivalent to calling /// `shrink_to_fit()`. - #[unstable(feature = "collections")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_boxed_slice(mut self) -> Box<[T]> { self.shrink_to_fit(); unsafe { - let xs: Box<[T]> = mem::transmute(&mut *self); + let xs: Box<[T]> = Box::from_raw(&mut *self); mem::forget(self); xs } @@ -402,9 +407,10 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut vec = vec![1, 2, 3, 4]; /// vec.truncate(2); - /// assert_eq!(vec, vec![1, 2]); + /// assert_eq!(vec, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, len: usize) { @@ -419,25 +425,20 @@ impl Vec { } } - /// Returns a mutable slice of the elements of `self`. - /// - /// # Examples - /// - /// ``` - /// fn foo(slice: &mut [i32]) {} - /// - /// let mut vec = vec![1, 2]; - /// foo(vec.as_mut_slice()); - /// ``` + /// Extract a slice containing the entire vector. #[inline] - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "convert", + reason = "waiting on RFC revision")] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Deprecated: use `&mut s[..]` instead. + #[inline] + #[unstable(feature = "convert", + reason = "waiting on RFC revision")] pub fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { - mem::transmute(RawSlice { - data: *self.ptr, - len: self.len, - }) - } + &mut self[..] } /// Creates a consuming iterator, that is, one that moves each value out of @@ -458,6 +459,7 @@ impl Vec { pub fn into_iter(self) -> IntoIter { unsafe { let ptr = *self.ptr; + assume(!ptr.is_null()); let cap = self.cap; let begin = ptr as *const T; let end = if mem::size_of::() == 0 { @@ -505,10 +507,10 @@ impl Vec { /// let mut v = vec!["foo", "bar", "baz", "qux"]; /// /// assert_eq!(v.swap_remove(1), "bar"); - /// assert_eq!(v, vec!["foo", "qux", "baz"]); + /// assert_eq!(v, ["foo", "qux", "baz"]); /// /// assert_eq!(v.swap_remove(0), "foo"); - /// assert_eq!(v, vec!["baz", "qux"]); + /// assert_eq!(v, ["baz", "qux"]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -531,9 +533,9 @@ impl Vec { /// ``` /// let mut vec = vec![1, 2, 3]; /// vec.insert(1, 4); - /// assert_eq!(vec, vec![1, 4, 2, 3]); + /// assert_eq!(vec, [1, 4, 2, 3]); /// vec.insert(4, 5); - /// assert_eq!(vec, vec![1, 4, 2, 3, 5]); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, index: usize, element: T) { @@ -548,7 +550,7 @@ impl Vec { let p = self.as_mut_ptr().offset(index as isize); // Shift everything over to make space. (Duplicating the // `index`th element into two consecutive places.) - ptr::copy_memory(p.offset(1), &*p, len - index); + ptr::copy(&*p, p.offset(1), len - index); // Write it in, overwriting the first copy of the `index`th // element. ptr::write(&mut *p, element); @@ -567,9 +569,10 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut v = vec![1, 2, 3]; /// assert_eq!(v.remove(1), 2); - /// assert_eq!(v, vec![1, 3]); + /// assert_eq!(v, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, index: usize) -> T { @@ -585,7 +588,7 @@ impl Vec { ret = ptr::read(ptr); // Shift everything down to fill in that spot. - ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1); + ptr::copy(&*ptr.offset(1), ptr, len - index - 1); } self.set_len(len - 1); ret @@ -603,7 +606,7 @@ impl Vec { /// ``` /// let mut vec = vec![1, 2, 3, 4]; /// vec.retain(|&x| x%2 == 0); - /// assert_eq!(vec, vec![2, 4]); + /// assert_eq!(vec, [2, 4]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool { @@ -633,14 +636,28 @@ impl Vec { /// /// # Examples /// - /// ```rust + /// ``` /// let mut vec = vec!(1, 2); /// vec.push(3); - /// assert_eq!(vec, vec!(1, 2, 3)); + /// assert_eq!(vec, [1, 2, 3]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, value: T) { + #[cold] + #[inline(never)] + fn resize(vec: &mut Vec) { + let old_size = vec.cap * mem::size_of::(); + let size = max(old_size, 2 * mem::size_of::()) * 2; + if old_size > size { panic!("capacity overflow") } + unsafe { + let ptr = alloc_or_realloc(*vec.ptr, old_size, size); + if ptr.is_null() { ::alloc::oom() } + vec.ptr = Unique::new(ptr); + } + vec.cap = max(vec.cap, 2) * 2; + } + if mem::size_of::() == 0 { // zero-size types consume no memory, so we can't rely on the // address space running out @@ -648,16 +665,9 @@ impl Vec { unsafe { mem::forget(value); } return } + if self.len == self.cap { - let old_size = self.cap * mem::size_of::(); - let size = max(old_size, 2 * mem::size_of::()) * 2; - if old_size > size { panic!("capacity overflow") } - unsafe { - let ptr = alloc_or_realloc(*self.ptr, old_size, size); - if ptr.is_null() { ::alloc::oom() } - self.ptr = Unique::new(ptr); - } - self.cap = max(self.cap, 2) * 2; + resize(self); } unsafe { @@ -671,10 +681,10 @@ impl Vec { /// /// # Examples /// - /// ```rust + /// ``` /// let mut vec = vec![1, 2, 3]; /// assert_eq!(vec.pop(), Some(3)); - /// assert_eq!(vec, vec![1, 2]); + /// assert_eq!(vec, [1, 2]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -698,11 +708,12 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut vec = vec![1, 2, 3]; /// let mut vec2 = vec![4, 5, 6]; /// vec.append(&mut vec2); - /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]); - /// assert_eq!(vec2, vec![]); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); /// ``` #[inline] #[unstable(feature = "collections", @@ -718,9 +729,9 @@ impl Vec { self.reserve(other.len()); let len = self.len(); unsafe { - ptr::copy_nonoverlapping_memory( - self.get_unchecked_mut(len), + ptr::copy_nonoverlapping( other.as_ptr(), + self.get_unchecked_mut(len), other.len()); } @@ -734,6 +745,7 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut v = vec!["a".to_string(), "b".to_string()]; /// for s in v.drain() { /// // s has type String, not &String @@ -815,15 +827,16 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections, core)] /// let v = vec![0, 1, 2]; /// let w = v.map_in_place(|i| i + 3); - /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice()); + /// assert_eq!(&w[..], &[3, 4, 5]); /// /// #[derive(PartialEq, Debug)] /// struct Newtype(u8); /// let bytes = vec![0x11, 0x22]; /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x)); - /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice()); + /// assert_eq!(&newtyped_bytes[..], &[Newtype(0x11), Newtype(0x22)]); /// ``` #[unstable(feature = "collections", reason = "API may change to provide stronger guarantees")] @@ -1017,10 +1030,11 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut vec = vec![1,2,3]; /// let vec2 = vec.split_off(1); - /// assert_eq!(vec, vec![1]); - /// assert_eq!(vec2, vec![2, 3]); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); /// ``` #[inline] #[unstable(feature = "collections", @@ -1036,9 +1050,9 @@ impl Vec { self.set_len(at); other.set_len(other_len); - ptr::copy_nonoverlapping_memory( - other.as_mut_ptr(), + ptr::copy_nonoverlapping( self.as_ptr().offset(at as isize), + other.as_mut_ptr(), other.len()); } other @@ -1055,13 +1069,14 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut vec = vec!["hello"]; /// vec.resize(3, "world"); - /// assert_eq!(vec, vec!["hello", "world", "world"]); + /// assert_eq!(vec, ["hello", "world", "world"]); /// /// let mut vec = vec![1, 2, 3, 4]; /// vec.resize(2, 0); - /// assert_eq!(vec, vec![1, 2]); + /// assert_eq!(vec, [1, 2]); /// ``` #[unstable(feature = "collections", reason = "matches collection reform specification; waiting for dust to settle")] @@ -1083,9 +1098,10 @@ impl Vec { /// # Examples /// /// ``` + /// # #![feature(collections)] /// let mut vec = vec![1]; /// vec.push_all(&[2, 3, 4]); - /// assert_eq!(vec, vec![1, 2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); /// ``` #[inline] #[unstable(feature = "collections", @@ -1121,7 +1137,7 @@ impl Vec { /// /// vec.dedup(); /// - /// assert_eq!(vec, vec![1, 2, 3, 2]); + /// assert_eq!(vec, [1, 2, 3, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn dedup(&mut self) { @@ -1188,8 +1204,8 @@ impl Vec { // Avoid bounds checks by using unsafe pointers. let p = self.as_mut_ptr(); - let mut r = 1; - let mut w = 1; + let mut r: usize = 1; + let mut w: usize = 1; while r < ln { let p_r = p.offset(r as isize); @@ -1283,7 +1299,17 @@ pub fn from_elem(elem: T, n: usize) -> Vec { #[unstable(feature = "collections")] impl Clone for Vec { - fn clone(&self) -> Vec { ::slice::SliceExt::to_vec(&**self) } + #[cfg(not(test))] + fn clone(&self) -> Vec { <[T]>::to_vec(&**self) } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn clone(&self) -> Vec { + ::slice::to_vec(&**self) + } fn clone_from(&mut self, other: &Vec) { // drop anything in self that will not be overwritten @@ -1303,15 +1329,7 @@ impl Clone for Vec { } } -#[cfg(stage0)] -impl> Hash for Vec { - #[inline] - fn hash(&self, state: &mut S) { - Hash::hash(&**self, state) - } -} #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl Hash for Vec { #[inline] fn hash(&self, state: &mut H) { @@ -1324,18 +1342,18 @@ impl Index for Vec { type Output = T; #[inline] - fn index(&self, index: &usize) -> &T { + fn index(&self, index: usize) -> &T { // NB built-in indexing via `&[T]` - &(**self)[*index] + &(**self)[index] } } #[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for Vec { #[inline] - fn index_mut(&mut self, index: &usize) -> &mut T { + fn index_mut(&mut self, index: usize) -> &mut T { // NB built-in indexing via `&mut [T]` - &mut (**self)[*index] + &mut (**self)[index] } } @@ -1343,62 +1361,70 @@ impl IndexMut for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for Vec { type Output = [T]; + #[inline] - fn index(&self, index: &ops::Range) -> &[T] { + fn index(&self, index: ops::Range) -> &[T] { Index::index(&**self, index) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for Vec { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeTo) -> &[T] { + fn index(&self, index: ops::RangeTo) -> &[T] { Index::index(&**self, index) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for Vec { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeFrom) -> &[T] { + fn index(&self, index: ops::RangeFrom) -> &[T] { Index::index(&**self, index) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for Vec { type Output = [T]; + #[inline] - fn index(&self, _index: &ops::RangeFull) -> &[T] { - self.as_slice() + fn index(&self, _index: ops::RangeFull) -> &[T] { + self } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for Vec { + #[inline] - fn index_mut(&mut self, index: &ops::Range) -> &mut [T] { + fn index_mut(&mut self, index: ops::Range) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for Vec { + #[inline] - fn index_mut(&mut self, index: &ops::RangeTo) -> &mut [T] { + fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for Vec { + #[inline] - fn index_mut(&mut self, index: &ops::RangeFrom) -> &mut [T] { + fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut for Vec { + #[inline] - fn index_mut(&mut self, _index: &ops::RangeFull) -> &mut [T] { - self.as_mut_slice() + fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] { + self } } @@ -1406,12 +1432,24 @@ impl ops::IndexMut for Vec { impl ops::Deref for Vec { type Target = [T]; - fn deref(&self) -> &[T] { self.as_slice() } + fn deref(&self) -> &[T] { + unsafe { + let p = *self.ptr; + assume(p != 0 as *mut T); + slice::from_raw_parts(p, self.len) + } + } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::DerefMut for Vec { - fn deref_mut(&mut self) -> &mut [T] { self.as_mut_slice() } + fn deref_mut(&mut self) -> &mut [T] { + unsafe { + let ptr = *self.ptr; + assume(!ptr.is_null()); + slice::from_raw_parts_mut(ptr, self.len) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1501,69 +1539,34 @@ impl Extend for Vec { } } -impl PartialEq> for Vec where A: PartialEq { - #[inline] - fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } -} - -macro_rules! impl_eq { - ($lhs:ty, $rhs:ty) => { - impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq { - #[inline] - fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } - } - - impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq { - #[inline] - fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) } - } +__impl_slice_eq1! { Vec, Vec } +__impl_slice_eq1! { Vec, &'b [B] } +__impl_slice_eq1! { Vec, &'b mut [B] } +__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone } +__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone } +__impl_slice_eq1! { Cow<'a, [A]>, Vec, Clone } + +macro_rules! array_impls { + ($($N: expr)+) => { + $( + // NOTE: some less important impls are omitted to reduce code bloat + __impl_slice_eq1! { Vec, [B; $N] } + __impl_slice_eq1! { Vec, &'b [B; $N] } + // __impl_slice_eq1! { Vec, &'b mut [B; $N] } + // __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone } + // __impl_slice_eq1! { Cow<'a, [A]>, &'b [B; $N], Clone } + // __impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B; $N], Clone } + )+ } } -impl_eq! { Vec, &'b [B] } -impl_eq! { Vec, &'b mut [B] } - -impl<'a, A, B> PartialEq> for Cow<'a, [A]> where A: PartialEq + Clone { - #[inline] - fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } -} - -impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { - #[inline] - fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) } -} - -macro_rules! impl_eq_for_cowvec { - ($rhs:ty) => { - impl<'a, 'b, A, B> PartialEq<$rhs> for Cow<'a, [A]> where A: PartialEq + Clone { - #[inline] - fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } - } - - impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { - #[inline] - fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) } - #[inline] - fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) } - } - } +array_impls! { + 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 } -impl_eq_for_cowvec! { &'b [B] } -impl_eq_for_cowvec! { &'b mut [B] } - #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Vec { #[inline] @@ -1583,30 +1586,15 @@ impl Ord for Vec { } } +#[unstable(feature = "collections", + reason = "will be replaced by slice syntax")] +#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")] +#[allow(deprecated)] impl AsSlice for Vec { - /// Returns a slice into `self`. - /// - /// # Examples - /// - /// ``` - /// fn foo(slice: &[i32]) {} - /// - /// let vec = vec![1, 2]; - /// foo(vec.as_slice()); - /// ``` + /// Deprecated: use `&mut s[..]` instead. #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn as_slice(&self) -> &[T] { - unsafe { - let p = *self.ptr; - if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot - assume(p != 0 as *mut T); - } - mem::transmute(RawSlice { - data: p, - len: self.len - }) - } + self } } @@ -1628,7 +1616,7 @@ impl Drop for Vec { fn drop(&mut self) { // This is (and should always remain) a no-op if the fields are // zeroed (when moving out, because of #[unsafe_no_drop_flag]). - if self.cap != 0 { + if self.cap != 0 && self.cap != mem::POST_DROP_USIZE { unsafe { for x in &*self { ptr::read(x); @@ -1654,15 +1642,43 @@ impl fmt::Debug for Vec { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef> for Vec { + fn as_ref(&self) -> &Vec { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for Vec { + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: Clone> From<&'a [T]> for Vec { + #[cfg(not(test))] + fn from(s: &'a [T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &'a [T]) -> Vec { + ::slice::to_vec(s) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> From<&'a str> for Vec { + fn from(s: &'a str) -> Vec { + From::from(s.as_bytes()) + } +} + //////////////////////////////////////////////////////////////////////////////// // Clone-on-write //////////////////////////////////////////////////////////////////////////////// -/// A clone-on-write vector -#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")] -#[unstable(feature = "collections")] -pub type CowVec<'a, T> = Cow<'a, [T]>; - #[unstable(feature = "collections")] impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { fn from_iter>(it: I) -> Cow<'a, [T]> { @@ -1800,6 +1816,9 @@ pub struct Drain<'a, T:'a> { marker: PhantomData<&'a T>, } +unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {} +unsafe impl<'a, T: Send> Send for Drain<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Drain<'a, T> { type Item = T; @@ -1868,7 +1887,7 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Drop for Drain<'a, T> { fn drop(&mut self) { - // self.ptr == self.end == null if drop has already been called, + // self.ptr == self.end == mem::POST_DROP_USIZE if drop has already been called, // so we can use #[unsafe_no_drop_flag]. // destroy the remaining elements @@ -1992,991 +2011,3 @@ impl Drop for PartialVecZeroSized { } } } - -#[cfg(test)] -mod tests { - use prelude::*; - use core::mem::size_of; - use core::iter::repeat; - use test::Bencher; - use super::as_vec; - - struct DropCounter<'a> { - count: &'a mut u32 - } - - #[unsafe_destructor] - impl<'a> Drop for DropCounter<'a> { - fn drop(&mut self) { - *self.count += 1; - } - } - - #[test] - fn test_as_vec() { - let xs = [1u8, 2u8, 3u8]; - assert_eq!(&**as_vec(&xs), xs); - } - - #[test] - fn test_as_vec_dtor() { - let (mut count_x, mut count_y) = (0, 0); - { - let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; - assert_eq!(as_vec(xs).len(), 2); - } - assert_eq!(count_x, 1); - assert_eq!(count_y, 1); - } - - #[test] - fn test_small_vec_struct() { - assert!(size_of::>() == size_of::() * 3); - } - - #[test] - fn test_double_drop() { - struct TwoVec { - x: Vec, - y: Vec - } - - let (mut count_x, mut count_y) = (0, 0); - { - let mut tv = TwoVec { - x: Vec::new(), - y: Vec::new() - }; - tv.x.push(DropCounter {count: &mut count_x}); - tv.y.push(DropCounter {count: &mut count_y}); - - // If Vec had a drop flag, here is where it would be zeroed. - // Instead, it should rely on its internal state to prevent - // doing anything significant when dropped multiple times. - drop(tv.x); - - // Here tv goes out of scope, tv.y should be dropped, but not tv.x. - } - - assert_eq!(count_x, 1); - assert_eq!(count_y, 1); - } - - #[test] - fn test_reserve() { - let mut v = Vec::new(); - assert_eq!(v.capacity(), 0); - - v.reserve(2); - assert!(v.capacity() >= 2); - - for i in 0..16 { - v.push(i); - } - - assert!(v.capacity() >= 16); - v.reserve(16); - assert!(v.capacity() >= 32); - - v.push(16); - - v.reserve(16); - assert!(v.capacity() >= 33) - } - - #[test] - fn test_extend() { - let mut v = Vec::new(); - let mut w = Vec::new(); - - v.extend(0..3); - for i in 0..3 { w.push(i) } - - assert_eq!(v, w); - - v.extend(3..10); - for i in 3..10 { w.push(i) } - - assert_eq!(v, w); - } - - #[test] - fn test_slice_from_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let slice = &mut values[2 ..]; - assert!(slice == [3, 4, 5]); - for p in slice { - *p += 2; - } - } - - assert!(values == [1, 2, 5, 6, 7]); - } - - #[test] - fn test_slice_to_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let slice = &mut values[.. 2]; - assert!(slice == [1, 2]); - for p in slice { - *p += 1; - } - } - - assert!(values == [2, 3, 3, 4, 5]); - } - - #[test] - fn test_split_at_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let (left, right) = values.split_at_mut(2); - { - let left: &[_] = left; - assert!(&left[..left.len()] == &[1, 2][]); - } - for p in left { - *p += 1; - } - - { - let right: &[_] = right; - assert!(&right[..right.len()] == &[3, 4, 5][]); - } - for p in right { - *p += 2; - } - } - - assert!(values == vec![2, 3, 5, 6, 7]); - } - - #[test] - fn test_clone() { - let v: Vec = vec![]; - let w = vec!(1, 2, 3); - - assert_eq!(v, v.clone()); - - let z = w.clone(); - assert_eq!(w, z); - // they should be disjoint in memory. - assert!(w.as_ptr() != z.as_ptr()) - } - - #[test] - fn test_clone_from() { - let mut v = vec!(); - let three = vec!(box 1, box 2, box 3); - let two = vec!(box 4, box 5); - // zero, long - v.clone_from(&three); - assert_eq!(v, three); - - // equal - v.clone_from(&three); - assert_eq!(v, three); - - // long, short - v.clone_from(&two); - assert_eq!(v, two); - - // short, long - v.clone_from(&three); - assert_eq!(v, three) - } - - #[test] - fn test_retain() { - let mut vec = vec![1, 2, 3, 4]; - vec.retain(|&x| x % 2 == 0); - assert!(vec == vec![2, 4]); - } - - #[test] - fn zero_sized_values() { - let mut v = Vec::new(); - assert_eq!(v.len(), 0); - v.push(()); - assert_eq!(v.len(), 1); - v.push(()); - assert_eq!(v.len(), 2); - assert_eq!(v.pop(), Some(())); - assert_eq!(v.pop(), Some(())); - assert_eq!(v.pop(), None); - - assert_eq!(v.iter().count(), 0); - v.push(()); - assert_eq!(v.iter().count(), 1); - v.push(()); - assert_eq!(v.iter().count(), 2); - - for &() in &v {} - - assert_eq!(v.iter_mut().count(), 2); - v.push(()); - assert_eq!(v.iter_mut().count(), 3); - v.push(()); - assert_eq!(v.iter_mut().count(), 4); - - for &mut () in &mut v {} - unsafe { v.set_len(0); } - assert_eq!(v.iter_mut().count(), 0); - } - - #[test] - fn test_partition() { - assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); - } - - #[test] - fn test_zip_unzip() { - let z1 = vec![(1, 4), (2, 5), (3, 6)]; - - let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip(); - - assert_eq!((1, 4), (left[0], right[0])); - assert_eq!((2, 5), (left[1], right[1])); - assert_eq!((3, 6), (left[2], right[2])); - } - - #[test] - fn test_unsafe_ptrs() { - unsafe { - // Test on-stack copy-from-buf. - let a = [1, 2, 3]; - let ptr = a.as_ptr(); - let b = Vec::from_raw_buf(ptr, 3); - assert_eq!(b, vec![1, 2, 3]); - - // Test on-heap copy-from-buf. - let c = vec![1, 2, 3, 4, 5]; - let ptr = c.as_ptr(); - let d = Vec::from_raw_buf(ptr, 5); - assert_eq!(d, vec![1, 2, 3, 4, 5]); - } - } - - #[test] - fn test_vec_truncate_drop() { - static mut drops: u32 = 0; - struct Elem(i32); - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; - assert_eq!(unsafe { drops }, 0); - v.truncate(3); - assert_eq!(unsafe { drops }, 2); - v.truncate(0); - assert_eq!(unsafe { drops }, 5); - } - - #[test] - #[should_fail] - fn test_vec_truncate_fail() { - struct BadElem(i32); - impl Drop for BadElem { - fn drop(&mut self) { - let BadElem(ref mut x) = *self; - if *x == 0xbadbeef { - panic!("BadElem panic: 0xbadbeef") - } - } - } - - let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; - v.truncate(0); - } - - #[test] - fn test_index() { - let vec = vec![1, 2, 3]; - assert!(vec[1] == 2); - } - - #[test] - #[should_fail] - fn test_index_out_of_bounds() { - let vec = vec![1, 2, 3]; - let _ = vec[3]; - } - - #[test] - #[should_fail] - fn test_slice_out_of_bounds_1() { - let x = vec![1, 2, 3, 4, 5]; - &x[-1..]; - } - - #[test] - #[should_fail] - fn test_slice_out_of_bounds_2() { - let x = vec![1, 2, 3, 4, 5]; - &x[..6]; - } - - #[test] - #[should_fail] - fn test_slice_out_of_bounds_3() { - let x = vec![1, 2, 3, 4, 5]; - &x[-1..4]; - } - - #[test] - #[should_fail] - fn test_slice_out_of_bounds_4() { - let x = vec![1, 2, 3, 4, 5]; - &x[1..6]; - } - - #[test] - #[should_fail] - fn test_slice_out_of_bounds_5() { - let x = vec![1, 2, 3, 4, 5]; - &x[3..2]; - } - - #[test] - #[should_fail] - fn test_swap_remove_empty() { - let mut vec= Vec::::new(); - vec.swap_remove(0); - } - - #[test] - fn test_move_iter_unwrap() { - let mut vec = Vec::with_capacity(7); - vec.push(1); - vec.push(2); - let ptr = vec.as_ptr(); - vec = vec.into_iter().into_inner(); - assert_eq!(vec.as_ptr(), ptr); - assert_eq!(vec.capacity(), 7); - assert_eq!(vec.len(), 0); - } - - #[test] - #[should_fail] - fn test_map_in_place_incompatible_types_fail() { - let v = vec![0, 1, 2]; - v.map_in_place(|_| ()); - } - - #[test] - fn test_map_in_place() { - let v = vec![0, 1, 2]; - assert_eq!(v.map_in_place(|i: u32| i as i32 - 1), [-1, 0, 1]); - } - - #[test] - fn test_map_in_place_zero_sized() { - let v = vec![(), ()]; - #[derive(PartialEq, Debug)] - struct ZeroSized; - assert_eq!(v.map_in_place(|_| ZeroSized), [ZeroSized, ZeroSized]); - } - - #[test] - fn test_map_in_place_zero_drop_count() { - use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; - - #[derive(Clone, PartialEq, Debug)] - struct Nothing; - impl Drop for Nothing { fn drop(&mut self) { } } - - #[derive(Clone, PartialEq, Debug)] - struct ZeroSized; - impl Drop for ZeroSized { - fn drop(&mut self) { - DROP_COUNTER.fetch_add(1, Ordering::Relaxed); - } - } - const NUM_ELEMENTS: usize = 2; - static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; - - let v = repeat(Nothing).take(NUM_ELEMENTS).collect::>(); - - DROP_COUNTER.store(0, Ordering::Relaxed); - - let v = v.map_in_place(|_| ZeroSized); - assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), 0); - drop(v); - assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), NUM_ELEMENTS); - } - - #[test] - fn test_move_items() { - let vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec { - vec2.push(i); - } - assert!(vec2 == vec![1, 2, 3]); - } - - #[test] - fn test_move_items_reverse() { - let vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.into_iter().rev() { - vec2.push(i); - } - assert!(vec2 == vec![3, 2, 1]); - } - - #[test] - fn test_move_items_zero_sized() { - let vec = vec![(), (), ()]; - let mut vec2 = vec![]; - for i in vec { - vec2.push(i); - } - assert!(vec2 == vec![(), (), ()]); - } - - #[test] - fn test_drain_items() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.drain() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [ 1, 2, 3 ]); - } - - #[test] - fn test_drain_items_reverse() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.drain().rev() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [3, 2, 1]); - } - - #[test] - fn test_drain_items_zero_sized() { - let mut vec = vec![(), (), ()]; - let mut vec2 = vec![]; - for i in vec.drain() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [(), (), ()]); - } - - #[test] - fn test_into_boxed_slice() { - let xs = vec![1, 2, 3]; - let ys = xs.into_boxed_slice(); - assert_eq!(ys, [1, 2, 3]); - } - - #[test] - fn test_append() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![4, 5, 6]; - vec.append(&mut vec2); - assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]); - assert_eq!(vec2, vec![]); - } - - #[test] - fn test_split_off() { - let mut vec = vec![1, 2, 3, 4, 5, 6]; - let vec2 = vec.split_off(4); - assert_eq!(vec, vec![1, 2, 3, 4]); - assert_eq!(vec2, vec![5, 6]); - } - - #[bench] - fn bench_new(b: &mut Bencher) { - b.iter(|| { - let v: Vec = Vec::new(); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), 0); - }) - } - - fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let v: Vec = Vec::with_capacity(src_len); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), src_len); - }) - } - - #[bench] - fn bench_with_capacity_0000(b: &mut Bencher) { - do_bench_with_capacity(b, 0) - } - - #[bench] - fn bench_with_capacity_0010(b: &mut Bencher) { - do_bench_with_capacity(b, 10) - } - - #[bench] - fn bench_with_capacity_0100(b: &mut Bencher) { - do_bench_with_capacity(b, 100) - } - - #[bench] - fn bench_with_capacity_1000(b: &mut Bencher) { - do_bench_with_capacity(b, 1000) - } - - fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let dst = (0..src_len).collect::>(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }) - } - - #[bench] - fn bench_from_fn_0000(b: &mut Bencher) { - do_bench_from_fn(b, 0) - } - - #[bench] - fn bench_from_fn_0010(b: &mut Bencher) { - do_bench_from_fn(b, 10) - } - - #[bench] - fn bench_from_fn_0100(b: &mut Bencher) { - do_bench_from_fn(b, 100) - } - - #[bench] - fn bench_from_fn_1000(b: &mut Bencher) { - do_bench_from_fn(b, 1000) - } - - fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec = repeat(5).take(src_len).collect(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().all(|x| *x == 5)); - }) - } - - #[bench] - fn bench_from_elem_0000(b: &mut Bencher) { - do_bench_from_elem(b, 0) - } - - #[bench] - fn bench_from_elem_0010(b: &mut Bencher) { - do_bench_from_elem(b, 10) - } - - #[bench] - fn bench_from_elem_0100(b: &mut Bencher) { - do_bench_from_elem(b, 100) - } - - #[bench] - fn bench_from_elem_1000(b: &mut Bencher) { - do_bench_from_elem(b, 1000) - } - - fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst = src.clone()[..].to_vec(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_from_slice_0000(b: &mut Bencher) { - do_bench_from_slice(b, 0) - } - - #[bench] - fn bench_from_slice_0010(b: &mut Bencher) { - do_bench_from_slice(b, 10) - } - - #[bench] - fn bench_from_slice_0100(b: &mut Bencher) { - do_bench_from_slice(b, 100) - } - - #[bench] - fn bench_from_slice_1000(b: &mut Bencher) { - do_bench_from_slice(b, 1000) - } - - fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter()); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_from_iter_0000(b: &mut Bencher) { - do_bench_from_iter(b, 0) - } - - #[bench] - fn bench_from_iter_0010(b: &mut Bencher) { - do_bench_from_iter(b, 10) - } - - #[bench] - fn bench_from_iter_0100(b: &mut Bencher) { - do_bench_from_iter(b, 100) - } - - #[bench] - fn bench_from_iter_1000(b: &mut Bencher) { - do_bench_from_iter(b, 1000) - } - - fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone().into_iter()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_extend_0000_0000(b: &mut Bencher) { - do_bench_extend(b, 0, 0) - } - - #[bench] - fn bench_extend_0000_0010(b: &mut Bencher) { - do_bench_extend(b, 0, 10) - } - - #[bench] - fn bench_extend_0000_0100(b: &mut Bencher) { - do_bench_extend(b, 0, 100) - } - - #[bench] - fn bench_extend_0000_1000(b: &mut Bencher) { - do_bench_extend(b, 0, 1000) - } - - #[bench] - fn bench_extend_0010_0010(b: &mut Bencher) { - do_bench_extend(b, 10, 10) - } - - #[bench] - fn bench_extend_0100_0100(b: &mut Bencher) { - do_bench_extend(b, 100, 100) - } - - #[bench] - fn bench_extend_1000_1000(b: &mut Bencher) { - do_bench_extend(b, 1000, 1000) - } - - fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.push_all(&src); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_push_all_0000_0000(b: &mut Bencher) { - do_bench_push_all(b, 0, 0) - } - - #[bench] - fn bench_push_all_0000_0010(b: &mut Bencher) { - do_bench_push_all(b, 0, 10) - } - - #[bench] - fn bench_push_all_0000_0100(b: &mut Bencher) { - do_bench_push_all(b, 0, 100) - } - - #[bench] - fn bench_push_all_0000_1000(b: &mut Bencher) { - do_bench_push_all(b, 0, 1000) - } - - #[bench] - fn bench_push_all_0010_0010(b: &mut Bencher) { - do_bench_push_all(b, 10, 10) - } - - #[bench] - fn bench_push_all_0100_0100(b: &mut Bencher) { - do_bench_push_all(b, 100, 100) - } - - #[bench] - fn bench_push_all_1000_1000(b: &mut Bencher) { - do_bench_push_all(b, 1000, 1000) - } - - fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone().into_iter()); - assert_eq!(dst.len(), dst_len + src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_push_all_move_0000_0000(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 0) - } - - #[bench] - fn bench_push_all_move_0000_0010(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 10) - } - - #[bench] - fn bench_push_all_move_0000_0100(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 100) - } - - #[bench] - fn bench_push_all_move_0000_1000(b: &mut Bencher) { - do_bench_push_all_move(b, 0, 1000) - } - - #[bench] - fn bench_push_all_move_0010_0010(b: &mut Bencher) { - do_bench_push_all_move(b, 10, 10) - } - - #[bench] - fn bench_push_all_move_0100_0100(b: &mut Bencher) { - do_bench_push_all_move(b, 100, 100) - } - - #[bench] - fn bench_push_all_move_1000_1000(b: &mut Bencher) { - do_bench_push_all_move(b, 1000, 1000) - } - - fn do_bench_clone(b: &mut Bencher, src_len: usize) { - let src: Vec = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst = src.clone(); - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); - }); - } - - #[bench] - fn bench_clone_0000(b: &mut Bencher) { - do_bench_clone(b, 0) - } - - #[bench] - fn bench_clone_0010(b: &mut Bencher) { - do_bench_clone(b, 10) - } - - #[bench] - fn bench_clone_0100(b: &mut Bencher) { - do_bench_clone(b, 100) - } - - #[bench] - fn bench_clone_1000(b: &mut Bencher) { - do_bench_clone(b, 1000) - } - - fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..src_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = (times * src_len) as u64; - - b.iter(|| { - let mut dst = dst.clone(); - - for _ in 0..times { - dst.clone_from(&src); - - assert_eq!(dst.len(), src_len); - assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); - } - }); - } - - #[bench] - fn bench_clone_from_01_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 0) - } - - #[bench] - fn bench_clone_from_01_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 10) - } - - #[bench] - fn bench_clone_from_01_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 100) - } - - #[bench] - fn bench_clone_from_01_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 10) - } - - #[bench] - fn bench_clone_from_01_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 100) - } - - #[bench] - fn bench_clone_from_01_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 100) - } - - #[bench] - fn bench_clone_from_01_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 1000) - } - - #[bench] - fn bench_clone_from_01_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 0) - } - - #[bench] - fn bench_clone_from_01_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 10) - } - - #[bench] - fn bench_clone_from_01_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 100) - } - - #[bench] - fn bench_clone_from_10_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 0) - } - - #[bench] - fn bench_clone_from_10_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 10) - } - - #[bench] - fn bench_clone_from_10_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 100) - } - - #[bench] - fn bench_clone_from_10_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 10) - } - - #[bench] - fn bench_clone_from_10_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 100) - } - - #[bench] - fn bench_clone_from_10_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 100) - } - - #[bench] - fn bench_clone_from_10_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 1000) - } - - #[bench] - fn bench_clone_from_10_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 0) - } - - #[bench] - fn bench_clone_from_10_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 10) - } - - #[bench] - fn bench_clone_from_10_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 100) - } -} diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 3ba22a41ff..49b0c22921 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -24,25 +24,18 @@ use core::cmp::Ordering; use core::default::Default; use core::fmt; use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; -use core::marker; use core::mem; -use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut}; use core::ptr::{self, Unique}; -use core::raw::Slice as RawSlice; +use core::slice; use core::hash::{Hash, Hasher}; -#[cfg(stage0)] use core::hash::Writer; use core::cmp; use alloc::heap; -#[deprecated(since = "1.0.0", reason = "renamed to VecDeque")] -#[unstable(feature = "collections")] -pub use VecDeque as RingBuf; - -static INITIAL_CAPACITY: usize = 7; // 2^3 - 1 -static MINIMUM_CAPACITY: usize = 1; // 2 - 1 +const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 +const MINIMUM_CAPACITY: usize = 1; // 2 - 1 /// `VecDeque` is a growable ring buffer, which can be used as a /// double-ended queue efficiently. @@ -60,12 +53,6 @@ pub struct VecDeque { ptr: Unique, } -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for VecDeque {} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for VecDeque {} - #[stable(feature = "rust1", since = "1.0.0")] impl Clone for VecDeque { fn clone(&self) -> VecDeque { @@ -98,13 +85,13 @@ impl VecDeque { /// Turn ptr into a slice #[inline] unsafe fn buffer_as_slice(&self) -> &[T] { - mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap }) + slice::from_raw_parts(*self.ptr, self.cap) } /// Turn ptr into a mut slice #[inline] unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] { - mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap }) + slice::from_raw_parts_mut(*self.ptr, self.cap) } /// Moves an element out of the buffer @@ -128,6 +115,20 @@ impl VecDeque { #[inline] fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) } + /// Returns the index in the underlying buffer for a given logical element + /// index + addend. + #[inline] + fn wrap_add(&self, idx: usize, addend: usize) -> usize { + wrap_index(idx.wrapping_add(addend), self.cap) + } + + /// Returns the index in the underlying buffer for a given logical element + /// index - subtrahend. + #[inline] + fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize { + wrap_index(idx.wrapping_sub(subtrahend), self.cap) + } + /// Copies a contiguous block of memory len long from src to dst #[inline] unsafe fn copy(&self, dst: usize, src: usize, len: usize) { @@ -135,9 +136,9 @@ impl VecDeque { self.cap); debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len, self.cap); - ptr::copy_memory( - self.ptr.offset(dst as isize), + ptr::copy( self.ptr.offset(src as isize), + self.ptr.offset(dst as isize), len); } @@ -148,9 +149,9 @@ impl VecDeque { 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 isize), + ptr::copy_nonoverlapping( self.ptr.offset(src as isize), + self.ptr.offset(dst as isize), len); } } @@ -193,7 +194,7 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -205,7 +206,7 @@ impl VecDeque { #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, i: usize) -> Option<&T> { if i < self.len() { - let idx = self.wrap_index(self.tail + i); + let idx = self.wrap_add(self.tail, i); unsafe { Some(&*self.ptr.offset(idx as isize)) } } else { None @@ -216,7 +217,7 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -235,7 +236,7 @@ impl VecDeque { #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, i: usize) -> Option<&mut T> { if i < self.len() { - let idx = self.wrap_index(self.tail + i); + let idx = self.wrap_add(self.tail, i); unsafe { Some(&mut *self.ptr.offset(idx as isize)) } } else { None @@ -250,7 +251,8 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -265,8 +267,8 @@ impl VecDeque { pub fn swap(&mut self, i: usize, j: usize) { assert!(i < self.len()); assert!(j < self.len()); - let ri = self.wrap_index(self.tail + i); - let rj = self.wrap_index(self.tail + j); + let ri = self.wrap_add(self.tail, i); + let rj = self.wrap_add(self.tail, j); unsafe { ptr::swap(self.ptr.offset(ri as isize), self.ptr.offset(rj as isize)) } @@ -278,6 +280,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let buf: VecDeque = VecDeque::with_capacity(10); @@ -301,6 +304,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf: VecDeque = vec![1].into_iter().collect(); @@ -322,6 +326,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf: VecDeque = vec![1].into_iter().collect(); @@ -397,6 +402,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::with_capacity(15); @@ -435,7 +441,7 @@ impl VecDeque { // [. . . 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); + let len = self.wrap_sub(self.head, target_cap); unsafe { self.copy_nonoverlapping(0, target_cap, len); } @@ -446,7 +452,7 @@ impl VecDeque { // [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); + debug_assert!(self.wrap_sub(self.head, 1) < target_cap); let len = self.cap - self.tail; let new_tail = target_cap - len; unsafe { @@ -483,6 +489,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -505,7 +512,8 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -513,7 +521,8 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// let b: &[_] = &[&5, &3, &4]; - /// assert_eq!(buf.iter().collect::>().as_slice(), b); + /// let c: Vec<&i32> = buf.iter().collect(); + /// assert_eq!(&c[..], b); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { @@ -528,7 +537,8 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -539,20 +549,18 @@ impl VecDeque { /// *num = *num - 2; /// } /// let b: &[_] = &[&mut 3, &mut 1, &mut 2]; - /// assert_eq!(&buf.iter_mut().collect::>()[], b); + /// assert_eq!(&buf.iter_mut().collect::>()[..], b); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut { IterMut { tail: self.tail, head: self.head, - cap: self.cap, - ptr: *self.ptr, - marker: marker::PhantomData, + ring: unsafe { self.buffer_as_mut_slice() }, } } - /// Consumes the list into an iterator yielding elements by value. + /// Consumes the list into a front-to-back iterator yielding elements by value. #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { IntoIter { @@ -640,6 +648,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut v = VecDeque::new(); @@ -785,7 +794,7 @@ impl VecDeque { None } else { let tail = self.tail; - self.tail = self.wrap_index(self.tail + 1); + self.tail = self.wrap_add(self.tail, 1); unsafe { Some(self.buffer_read(tail)) } } } @@ -809,7 +818,7 @@ impl VecDeque { debug_assert!(!self.is_full()); } - self.tail = self.wrap_index(self.tail - 1); + self.tail = self.wrap_sub(self.tail, 1); let tail = self.tail; unsafe { self.buffer_write(tail, t); } } @@ -818,7 +827,7 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -834,7 +843,7 @@ impl VecDeque { } let head = self.head; - self.head = self.wrap_index(self.head + 1); + self.head = self.wrap_add(self.head, 1); unsafe { self.buffer_write(head, t) } } @@ -843,7 +852,7 @@ impl VecDeque { /// /// # Examples /// - /// ```rust + /// ``` /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -857,7 +866,7 @@ impl VecDeque { if self.is_empty() { None } else { - self.head = self.wrap_index(self.head - 1); + self.head = self.wrap_sub(self.head, 1); let head = self.head; unsafe { Some(self.buffer_read(head)) } } @@ -878,6 +887,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -911,6 +921,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -943,7 +954,8 @@ impl VecDeque { /// Panics if `i` is greater than ringbuf's length /// /// # Examples - /// ```rust + /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -981,7 +993,7 @@ impl VecDeque { // A - The element that should be after the insertion point // M - Indicates element was moved - let idx = self.wrap_index(self.tail + i); + let idx = self.wrap_add(self.tail, i); let distance_to_tail = i; let distance_to_head = self.len() - i; @@ -1000,7 +1012,7 @@ impl VecDeque { // [A o o o o o o o . . . . . I] // - self.tail = self.wrap_index(self.tail - 1); + self.tail = self.wrap_sub(self.tail, 1); }, (true, true, _) => unsafe { // contiguous, insert closer to tail: @@ -1022,7 +1034,7 @@ impl VecDeque { // [o I A o o o o o . . . . . . . o] // M M - let new_tail = self.wrap_index(self.tail - 1); + let new_tail = self.wrap_sub(self.tail, 1); self.copy(new_tail, self.tail, 1); // Already moved the tail, so we only copy `i - 1` elements. @@ -1041,7 +1053,7 @@ impl VecDeque { // M M M self.copy(idx + 1, idx, self.head - idx); - self.head = self.wrap_index(self.head + 1); + self.head = self.wrap_add(self.head, 1); }, (false, true, true) => unsafe { // discontiguous, insert closer to tail, tail section: @@ -1133,7 +1145,7 @@ impl VecDeque { } // tail might've been changed so we need to recalculate - let new_idx = self.wrap_index(self.tail + i); + let new_idx = self.wrap_add(self.tail, i); unsafe { self.buffer_write(new_idx, t); } @@ -1145,7 +1157,7 @@ impl VecDeque { /// Returns `None` if `i` is out of bounds. /// /// # Examples - /// ```rust + /// ``` /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -1180,7 +1192,7 @@ impl VecDeque { // R - Indicates element that is being removed // M - Indicates element was moved - let idx = self.wrap_index(self.tail + i); + let idx = self.wrap_add(self.tail, i); let elem = unsafe { Some(self.buffer_read(idx)) @@ -1229,7 +1241,7 @@ impl VecDeque { // M M self.copy(self.tail + 1, self.tail, i); - self.tail = self.wrap_index(self.tail + 1); + self.tail = self.wrap_add(self.tail, 1); }, (false, false, false) => unsafe { // discontiguous, remove closer to head, head section: @@ -1275,7 +1287,7 @@ impl VecDeque { self.copy(0, 1, self.head - 1); } - self.head = self.wrap_index(self.head - 1); + self.head = self.wrap_sub(self.head, 1); }, (false, true, false) => unsafe { // discontiguous, remove closer to tail, head section: @@ -1296,7 +1308,7 @@ impl VecDeque { // move elements from tail to end forward, excluding the last one self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1); - self.tail = self.wrap_index(self.tail + 1); + self.tail = self.wrap_add(self.tail, 1); } } @@ -1317,6 +1329,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect(); @@ -1344,27 +1357,27 @@ impl VecDeque { // `at` lies in the first half. let amount_in_first = first_len - at; - ptr::copy_nonoverlapping_memory(*other.ptr, - first_half.as_ptr().offset(at as isize), - amount_in_first); + ptr::copy_nonoverlapping(first_half.as_ptr().offset(at as isize), + *other.ptr, + amount_in_first); // just take all of the second half. - ptr::copy_nonoverlapping_memory(other.ptr.offset(amount_in_first as isize), - second_half.as_ptr(), - second_len); + ptr::copy_nonoverlapping(second_half.as_ptr(), + other.ptr.offset(amount_in_first as isize), + second_len); } else { // `at` lies in the second half, need to factor in the elements we skipped // in the first half. let offset = at - first_len; let amount_in_second = second_len - offset; - ptr::copy_nonoverlapping_memory(*other.ptr, - second_half.as_ptr().offset(offset as isize), - amount_in_second); + ptr::copy_nonoverlapping(second_half.as_ptr().offset(offset as isize), + *other.ptr, + amount_in_second); } } // Cleanup where the ends of the buffers are - self.head = self.wrap_index(self.head - other_len); + self.head = self.wrap_sub(self.head, other_len); other.head = other.wrap_index(other_len); other @@ -1379,6 +1392,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); @@ -1403,6 +1417,7 @@ impl VecDeque { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -1439,7 +1454,7 @@ fn wrap_index(index: usize, size: usize) -> usize { #[inline] fn count(tail: usize, head: usize, size: usize) -> usize { // size is always a power of 2 - (head - tail) & (size - 1) + (head.wrapping_sub(tail)) & (size - 1) } /// `VecDeque` iterator. @@ -1471,7 +1486,7 @@ impl<'a, T> Iterator for Iter<'a, T> { return None; } let tail = self.tail; - self.tail = wrap_index(self.tail + 1, self.ring.len()); + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); unsafe { Some(self.ring.get_unchecked(tail)) } } @@ -1489,7 +1504,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { if self.tail == self.head { return None; } - self.head = wrap_index(self.head - 1, self.ring.len()); + self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); unsafe { Some(self.ring.get_unchecked(self.head)) } } } @@ -1510,23 +1525,18 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> { if j >= self.indexable() { None } else { - let idx = wrap_index(self.tail + j, self.ring.len()); + let idx = wrap_index(self.tail.wrapping_add(j), self.ring.len()); unsafe { Some(self.ring.get_unchecked(idx)) } } } } -// FIXME This was implemented differently from Iter because of a problem -// with returning the mutable reference. I couldn't find a way to -// make the lifetime checker happy so, but there should be a way. /// `VecDeque` mutable iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T:'a> { - ptr: *mut T, + ring: &'a mut [T], tail: usize, head: usize, - cap: usize, - marker: marker::PhantomData<&'a mut T>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -1539,16 +1549,17 @@ impl<'a, T> Iterator for IterMut<'a, T> { return None; } let tail = self.tail; - self.tail = wrap_index(self.tail + 1, self.cap); + self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len()); unsafe { - Some(&mut *self.ptr.offset(tail as isize)) + let elem = self.ring.get_unchecked_mut(tail); + Some(&mut *(elem as *mut _)) } } #[inline] fn size_hint(&self) -> (usize, Option) { - let len = count(self.tail, self.head, self.cap); + let len = count(self.tail, self.head, self.ring.len()); (len, Some(len)) } } @@ -1560,10 +1571,11 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { if self.tail == self.head { return None; } - self.head = wrap_index(self.head - 1, self.cap); + self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len()); unsafe { - Some(&mut *self.ptr.offset(self.head as isize)) + let elem = self.ring.get_unchecked_mut(self.head); + Some(&mut *(elem as *mut _)) } } } @@ -1572,6 +1584,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} /// A by-value VecDeque iterator +#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { inner: VecDeque, @@ -1675,17 +1688,6 @@ impl Ord for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(stage0)] -impl> Hash for VecDeque { - fn hash(&self, state: &mut S) { - self.len().hash(state); - for elt in self { - elt.hash(state); - } - } -} -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl Hash for VecDeque { fn hash(&self, state: &mut H) { self.len().hash(state); @@ -1700,16 +1702,16 @@ impl Index for VecDeque { type Output = A; #[inline] - fn index(&self, i: &usize) -> &A { - self.get(*i).expect("Out of bounds access") + fn index(&self, i: usize) -> &A { + self.get(i).expect("Out of bounds access") } } #[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for VecDeque { #[inline] - fn index_mut(&mut self, i: &usize) -> &mut A { - self.get_mut(*i).expect("Out of bounds access") + fn index_mut(&mut self, i: usize) -> &mut A { + self.get_mut(i).expect("Out of bounds access") } } @@ -1766,7 +1768,7 @@ impl Extend for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for VecDeque { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "VecDeque [")); + try!(write!(f, "[")); for (i, e) in self.iter().enumerate() { if i != 0 { try!(write!(f, ", ")); } @@ -1778,138 +1780,14 @@ impl fmt::Debug for VecDeque { } #[cfg(test)] -mod tests { - use self::Taggy::*; - use self::Taggypar::*; - use prelude::*; - use core::iter; - use std::fmt::Debug; - use std::hash::{self, SipHasher}; - use test::Bencher; +mod test { + use core::iter::{Iterator, self}; + use core::option::Option::Some; + use test; use super::VecDeque; - #[test] - #[allow(deprecated)] - fn test_simple() { - let mut d = VecDeque::new(); - assert_eq!(d.len(), 0); - d.push_front(17); - d.push_front(42); - d.push_back(137); - assert_eq!(d.len(), 3); - d.push_back(137); - assert_eq!(d.len(), 4); - assert_eq!(*d.front().unwrap(), 42); - assert_eq!(*d.back().unwrap(), 137); - let mut i = d.pop_front(); - assert_eq!(i, Some(42)); - i = d.pop_back(); - assert_eq!(i, Some(137)); - i = d.pop_back(); - assert_eq!(i, Some(137)); - i = d.pop_back(); - assert_eq!(i, Some(17)); - assert_eq!(d.len(), 0); - d.push_back(3); - assert_eq!(d.len(), 1); - d.push_front(2); - assert_eq!(d.len(), 2); - d.push_back(4); - assert_eq!(d.len(), 3); - d.push_front(1); - assert_eq!(d.len(), 4); - debug!("{}", d[0]); - debug!("{}", d[1]); - debug!("{}", d[2]); - debug!("{}", d[3]); - assert_eq!(d[0], 1); - assert_eq!(d[1], 2); - assert_eq!(d[2], 3); - assert_eq!(d[3], 4); - } - - #[cfg(test)] - fn test_parameterized(a: T, b: T, c: T, d: T) { - let mut deq = VecDeque::new(); - assert_eq!(deq.len(), 0); - deq.push_front(a.clone()); - deq.push_front(b.clone()); - deq.push_back(c.clone()); - assert_eq!(deq.len(), 3); - deq.push_back(d.clone()); - assert_eq!(deq.len(), 4); - assert_eq!((*deq.front().unwrap()).clone(), b.clone()); - assert_eq!((*deq.back().unwrap()).clone(), d.clone()); - assert_eq!(deq.pop_front().unwrap(), b.clone()); - assert_eq!(deq.pop_back().unwrap(), d.clone()); - assert_eq!(deq.pop_back().unwrap(), c.clone()); - assert_eq!(deq.pop_back().unwrap(), a.clone()); - assert_eq!(deq.len(), 0); - deq.push_back(c.clone()); - assert_eq!(deq.len(), 1); - deq.push_front(b.clone()); - assert_eq!(deq.len(), 2); - deq.push_back(d.clone()); - assert_eq!(deq.len(), 3); - deq.push_front(a.clone()); - assert_eq!(deq.len(), 4); - assert_eq!(deq[0].clone(), a.clone()); - assert_eq!(deq[1].clone(), b.clone()); - assert_eq!(deq[2].clone(), c.clone()); - assert_eq!(deq[3].clone(), d.clone()); - } - - #[test] - fn test_push_front_grow() { - let mut deq = VecDeque::new(); - for i in 0..66 { - deq.push_front(i); - } - assert_eq!(deq.len(), 66); - - for i in 0..66 { - assert_eq!(deq[i], 65 - i); - } - - let mut deq = VecDeque::new(); - for i in 0..66 { - deq.push_back(i); - } - - for i in 0..66 { - assert_eq!(deq[i], i); - } - } - - #[test] - fn test_index() { - let mut deq = VecDeque::new(); - for i in 1..4 { - deq.push_front(i); - } - assert_eq!(deq[1], 2); - } - - #[test] - #[should_fail] - fn test_index_out_of_bounds() { - let mut deq = VecDeque::new(); - for i in 1..4 { - deq.push_front(i); - } - deq[3]; - } - - #[bench] - fn bench_new(b: &mut test::Bencher) { - b.iter(|| { - let ring: VecDeque = VecDeque::new(); - test::black_box(ring); - }) - } - #[bench] fn bench_push_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); @@ -1960,666 +1838,6 @@ mod tests { }) } - #[bench] - fn bench_grow_1025(b: &mut test::Bencher) { - b.iter(|| { - let mut deq = VecDeque::new(); - for i in 0..1025 { - deq.push_front(i); - } - test::black_box(deq); - }) - } - - #[bench] - fn bench_iter_1000(b: &mut test::Bencher) { - let ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for &i in &ring { - sum += i; - } - test::black_box(sum); - }) - } - - #[bench] - fn bench_mut_iter_1000(b: &mut test::Bencher) { - let mut ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for i in &mut ring { - sum += *i; - } - test::black_box(sum); - }) - } - - #[derive(Clone, PartialEq, Debug)] - enum Taggy { - One(i32), - Two(i32, i32), - Three(i32, i32, i32), - } - - #[derive(Clone, PartialEq, Debug)] - enum Taggypar { - Onepar(T), - Twopar(T, T), - Threepar(T, T, T), - } - - #[derive(Clone, PartialEq, Debug)] - struct RecCy { - x: i32, - y: i32, - t: Taggy - } - - #[test] - fn test_param_int() { - test_parameterized::(5, 72, 64, 175); - } - - #[test] - fn test_param_taggy() { - test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); - } - - #[test] - fn test_param_taggypar() { - test_parameterized::>(Onepar::(1), - Twopar::(1, 2), - Threepar::(1, 2, 3), - Twopar::(17, 42)); - } - - #[test] - fn test_param_reccy() { - let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; - let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; - let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; - let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; - test_parameterized::(reccy1, reccy2, reccy3, reccy4); - } - - #[test] - fn test_with_capacity() { - let mut d = VecDeque::with_capacity(0); - d.push_back(1); - assert_eq!(d.len(), 1); - let mut d = VecDeque::with_capacity(50); - d.push_back(1); - assert_eq!(d.len(), 1); - } - - #[test] - fn test_with_capacity_non_power_two() { - let mut d3 = VecDeque::with_capacity(3); - d3.push_back(1); - - // X = None, | = lo - // [|1, X, X] - assert_eq!(d3.pop_front(), Some(1)); - // [X, |X, X] - assert_eq!(d3.front(), None); - - // [X, |3, X] - d3.push_back(3); - // [X, |3, 6] - d3.push_back(6); - // [X, X, |6] - assert_eq!(d3.pop_front(), Some(3)); - - // Pushing the lo past half way point to trigger - // the 'B' scenario for growth - // [9, X, |6] - d3.push_back(9); - // [9, 12, |6] - d3.push_back(12); - - d3.push_back(15); - // There used to be a bug here about how the - // VecDeque made growth assumptions about the - // underlying Vec which didn't hold and lead - // to corruption. - // (Vec grows to next power of two) - //good- [9, 12, 15, X, X, X, X, |6] - //bug- [15, 12, X, X, X, |6, X, X] - assert_eq!(d3.pop_front(), Some(6)); - - // Which leads us to the following state which - // would be a failure case. - //bug- [15, 12, X, X, X, X, |X, X] - assert_eq!(d3.front(), Some(&9)); - } - - #[test] - fn test_reserve_exact() { - let mut d = VecDeque::new(); - d.push_back(0); - d.reserve_exact(50); - assert!(d.capacity() >= 51); - } - - #[test] - fn test_reserve() { - let mut d = VecDeque::new(); - d.push_back(0); - d.reserve(50); - assert!(d.capacity() >= 51); - } - - #[test] - fn test_swap() { - let mut d: VecDeque<_> = (0..5).collect(); - d.pop_front(); - d.swap(0, 3); - assert_eq!(d.iter().cloned().collect::>(), vec!(4, 2, 3, 1)); - } - - #[test] - fn test_iter() { - let mut d = VecDeque::new(); - assert_eq!(d.iter().next(), None); - assert_eq!(d.iter().size_hint(), (0, Some(0))); - - for i in 0..5 { - d.push_back(i); - } - { - let b: &[_] = &[&0,&1,&2,&3,&4]; - assert_eq!(d.iter().collect::>(), b); - } - - for i in 6..9 { - d.push_front(i); - } - { - let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; - assert_eq!(d.iter().collect::>(), b); - } - - let mut it = d.iter(); - let mut len = d.len(); - loop { - match it.next() { - None => break, - _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } - } - } - } - - #[test] - fn test_rev_iter() { - let mut d = VecDeque::new(); - assert_eq!(d.iter().rev().next(), None); - - for i in 0..5 { - d.push_back(i); - } - { - let b: &[_] = &[&4,&3,&2,&1,&0]; - assert_eq!(d.iter().rev().collect::>(), b); - } - - for i in 6..9 { - d.push_front(i); - } - let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; - assert_eq!(d.iter().rev().collect::>(), b); - } - - #[test] - fn test_mut_rev_iter_wrap() { - let mut d = VecDeque::with_capacity(3); - assert!(d.iter_mut().rev().next().is_none()); - - d.push_back(1); - d.push_back(2); - d.push_back(3); - assert_eq!(d.pop_front(), Some(1)); - d.push_back(4); - - assert_eq!(d.iter_mut().rev().cloned().collect::>(), - vec![4, 3, 2]); - } - - #[test] - fn test_mut_iter() { - let mut d = VecDeque::new(); - assert!(d.iter_mut().next().is_none()); - - for i in 0..3 { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().enumerate() { - assert_eq!(*elt, 2 - i); - *elt = i; - } - - { - let mut it = d.iter_mut(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_mut_rev_iter() { - let mut d = VecDeque::new(); - assert!(d.iter_mut().rev().next().is_none()); - - for i in 0..3 { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().rev().enumerate() { - assert_eq!(*elt, i); - *elt = i; - } - - { - let mut it = d.iter_mut().rev(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_into_iter() { - - // Empty iter - { - let d: VecDeque = VecDeque::new(); - let mut iter = d.into_iter(); - - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - // simple iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - - let b = vec![0,1,2,3,4]; - assert_eq!(d.into_iter().collect::>(), b); - } - - // wrapped iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - let b = vec![8,7,6,0,1,2,3,4]; - assert_eq!(d.into_iter().collect::>(), b); - } - - // partially used - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - let mut it = d.into_iter(); - assert_eq!(it.size_hint(), (8, Some(8))); - assert_eq!(it.next(), Some(8)); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.size_hint(), (5, Some(5))); - } - } - - #[test] - fn test_drain() { - - // Empty iter - { - let mut d: VecDeque = VecDeque::new(); - - { - let mut iter = d.drain(); - - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert!(d.is_empty()); - } - - // simple iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - - assert_eq!(d.drain().collect::>(), [0, 1, 2, 3, 4]); - assert!(d.is_empty()); - } - - // wrapped iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - assert_eq!(d.drain().collect::>(), [8,7,6,0,1,2,3,4]); - assert!(d.is_empty()); - } - - // partially used - { - let mut d: VecDeque<_> = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - { - let mut it = d.drain(); - assert_eq!(it.size_hint(), (8, Some(8))); - assert_eq!(it.next(), Some(8)); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.size_hint(), (5, Some(5))); - } - assert!(d.is_empty()); - } - } - - #[test] - fn test_from_iter() { - use core::iter; - let v = vec!(1,2,3,4,5,6,7); - let deq: VecDeque<_> = v.iter().cloned().collect(); - let u: Vec<_> = deq.iter().cloned().collect(); - assert_eq!(u, v); - - let seq = iter::count(0, 2).take(256); - let deq: VecDeque<_> = seq.collect(); - for (i, &x) in deq.iter().enumerate() { - assert_eq!(2*i, x); - } - assert_eq!(deq.len(), 256); - } - - #[test] - fn test_clone() { - let mut d = VecDeque::new(); - d.push_front(17); - d.push_front(42); - d.push_back(137); - d.push_back(137); - assert_eq!(d.len(), 4); - let mut e = d.clone(); - assert_eq!(e.len(), 4); - while !d.is_empty() { - assert_eq!(d.pop_back(), e.pop_back()); - } - assert_eq!(d.len(), 0); - assert_eq!(e.len(), 0); - } - - #[test] - fn test_eq() { - let mut d = VecDeque::new(); - assert!(d == VecDeque::with_capacity(0)); - d.push_front(137); - d.push_front(17); - d.push_front(42); - d.push_back(137); - let mut e = VecDeque::with_capacity(0); - e.push_back(42); - e.push_back(17); - e.push_back(137); - e.push_back(137); - assert!(&e == &d); - e.pop_back(); - e.push_back(0); - assert!(e != d); - e.clear(); - assert!(e == VecDeque::new()); - } - - #[test] - fn test_hash() { - let mut x = VecDeque::new(); - let mut y = VecDeque::new(); - - x.push_back(1); - x.push_back(2); - x.push_back(3); - - y.push_back(0); - y.push_back(1); - y.pop_front(); - y.push_back(2); - y.push_back(3); - - assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_ord() { - let x = VecDeque::new(); - let mut y = VecDeque::new(); - y.push_back(1); - y.push_back(2); - y.push_back(3); - assert!(x < y); - assert!(y > x); - assert!(x <= x); - assert!(x >= x); - } - - #[test] - fn test_show() { - let ringbuf: VecDeque<_> = (0..10).collect(); - assert_eq!(format!("{:?}", ringbuf), "VecDeque [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter() - .cloned() - .collect(); - assert_eq!(format!("{:?}", ringbuf), "VecDeque [\"just\", \"one\", \"test\", \"more\"]"); - } - - #[test] - fn test_drop() { - static mut drops: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - drop(ring); - - assert_eq!(unsafe {drops}, 4); - } - - #[test] - fn test_drop_with_pop() { - static mut drops: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - - drop(ring.pop_back()); - drop(ring.pop_front()); - assert_eq!(unsafe {drops}, 2); - - drop(ring); - assert_eq!(unsafe {drops}, 4); - } - - #[test] - fn test_drop_clear() { - static mut drops: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { drops += 1; } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - ring.clear(); - assert_eq!(unsafe {drops}, 4); - - drop(ring); - assert_eq!(unsafe {drops}, 4); - } - - #[test] - fn test_reserve_grow() { - // test growth path A - // [T o o H] -> [T o o H . . . . ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - - // test growth path B - // [H T o o] -> [. T o o H . . . ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..1 { - ring.push_back(i); - assert_eq!(ring.pop_front(), Some(i)); - } - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - - // test growth path C - // [o o H T] -> [o o H . . . . T ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..3 { - ring.push_back(i); - assert_eq!(ring.pop_front(), Some(i)); - } - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - } - - #[test] - fn test_get() { - let mut ring = VecDeque::new(); - ring.push_back(0); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), None); - - ring.push_back(1); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), Some(&1)); - assert_eq!(ring.get(2), None); - - ring.push_back(2); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), Some(&1)); - assert_eq!(ring.get(2), Some(&2)); - assert_eq!(ring.get(3), None); - - assert_eq!(ring.pop_front(), Some(0)); - assert_eq!(ring.get(0), Some(&1)); - assert_eq!(ring.get(1), Some(&2)); - assert_eq!(ring.get(2), None); - - assert_eq!(ring.pop_front(), Some(1)); - assert_eq!(ring.get(0), Some(&2)); - assert_eq!(ring.get(1), None); - - assert_eq!(ring.pop_front(), Some(2)); - assert_eq!(ring.get(0), None); - assert_eq!(ring.get(1), None); - } - - #[test] - fn test_get_mut() { - let mut ring = VecDeque::new(); - for i in 0..3 { - ring.push_back(i); - } - - match ring.get_mut(1) { - Some(x) => *x = -1, - None => () - }; - - assert_eq!(ring.get_mut(0), Some(&mut 0)); - assert_eq!(ring.get_mut(1), Some(&mut -1)); - assert_eq!(ring.get_mut(2), Some(&mut 2)); - assert_eq!(ring.get_mut(3), None); - - assert_eq!(ring.pop_front(), Some(0)); - assert_eq!(ring.get_mut(0), Some(&mut -1)); - assert_eq!(ring.get_mut(1), Some(&mut 2)); - assert_eq!(ring.get_mut(2), None); - } - #[test] fn test_swap_front_back_remove() { fn test(back: bool) { @@ -2679,7 +1897,7 @@ mod tests { // len is the length *after* insertion for len in 1..cap { // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); + let expected = (0..).take(len).collect(); for tail_pos in 0..cap { for to_insert in 0..len { tester.tail = tail_pos; @@ -2712,7 +1930,7 @@ mod tests { // len is the length *after* removal for len in 0..cap - 1 { // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); + let expected = (0..).take(len).collect(); for tail_pos in 0..cap { for to_remove in 0..len + 1 { tester.tail = tail_pos; @@ -2750,7 +1968,7 @@ mod tests { for len in 0..cap + 1 { // 0, 1, 2, .., len - 1 - let expected = iter::count(0, 1).take(len).collect(); + let expected = (0..).take(len).collect(); for tail_pos in 0..max_cap + 1 { tester.tail = tail_pos; tester.head = tail_pos; @@ -2767,74 +1985,6 @@ mod tests { } } - #[test] - fn test_front() { - let mut ring = VecDeque::new(); - ring.push_back(10); - ring.push_back(20); - assert_eq!(ring.front(), Some(&10)); - ring.pop_front(); - assert_eq!(ring.front(), Some(&20)); - ring.pop_front(); - assert_eq!(ring.front(), None); - } - - #[test] - fn test_as_slices() { - let mut ring: VecDeque = VecDeque::with_capacity(127); - let cap = ring.capacity() as i32; - let first = cap/2; - let last = cap - first; - for i in 0..first { - ring.push_back(i); - - let (left, right) = ring.as_slices(); - let expected: Vec<_> = (0..i+1).collect(); - assert_eq!(left, expected); - assert_eq!(right, []); - } - - for j in -last..0 { - ring.push_front(j); - let (left, right) = ring.as_slices(); - let expected_left: Vec<_> = (-last..j+1).rev().collect(); - let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, expected_left); - assert_eq!(right, expected_right); - } - - assert_eq!(ring.len() as i32, cap); - assert_eq!(ring.capacity() as i32, cap); - } - - #[test] - fn test_as_mut_slices() { - let mut ring: VecDeque = VecDeque::with_capacity(127); - let cap = ring.capacity() as i32; - let first = cap/2; - let last = cap - first; - for i in 0..first { - ring.push_back(i); - - let (left, right) = ring.as_mut_slices(); - let expected: Vec<_> = (0..i+1).collect(); - assert_eq!(left, expected); - assert_eq!(right, []); - } - - for j in -last..0 { - ring.push_front(j); - let (left, right) = ring.as_mut_slices(); - let expected_left: Vec<_> = (-last..j+1).rev().collect(); - let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, expected_left); - assert_eq!(right, expected_right); - } - - assert_eq!(ring.len() as i32, cap); - assert_eq!(ring.capacity() as i32, cap); - } - #[test] fn test_split_off() { // This test checks that every single combination of tail position, length, and @@ -2851,9 +2001,9 @@ mod tests { // index to split at for at in 0..len + 1 { // 0, 1, 2, .., at - 1 (may be empty) - let expected_self = iter::count(0, 1).take(at).collect(); + let expected_self = (0..).take(at).collect(); // at, at + 1, .., len - 1 (may be empty) - let expected_other = iter::count(at, 1).take(len - at).collect(); + let expected_other = (at..).take(len - at).collect(); for tail_pos in 0..cap { tester.tail = tail_pos; @@ -2872,25 +2022,4 @@ mod tests { } } } - - #[test] - fn test_append() { - let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); - let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); - - // normal append - a.append(&mut b); - assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect(), vec![]); - - // append nothing to something - a.append(&mut b); - assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect(), vec![]); - - // append something to nothing - b.append(&mut a); - assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]); - assert_eq!(a.iter().cloned().collect(), vec![]); - } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 54589a3142..8900c79504 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -17,14 +17,13 @@ use self::Entry::*; use core::prelude::*; -use core::cmp::Ordering; +use core::cmp::{max, Ordering}; use core::default::Default; use core::fmt; use core::hash::{Hash, Hasher}; -#[cfg(stage0)] use core::hash::Writer; use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator}; use core::iter; -use core::mem::replace; +use core::mem::{replace, swap}; use core::ops::{Index, IndexMut}; use {vec, slice}; @@ -35,6 +34,7 @@ use vec::Vec; /// # Examples /// /// ``` +/// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut months = VecMap::new(); @@ -68,26 +68,28 @@ pub struct VecMap { } /// A view into a single entry in a map, which may either be vacant or occupied. -#[unstable(feature = "collections", - reason = "precise API still under development")] + +#[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, V:'a> { /// A vacant Entry + #[stable(feature = "rust1", since = "1.0.0")] Vacant(VacantEntry<'a, V>), + /// An occupied Entry + #[stable(feature = "rust1", since = "1.0.0")] Occupied(OccupiedEntry<'a, V>), } /// A vacant Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] + +#[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry<'a, V:'a> { map: &'a mut VecMap, index: usize, } /// An occupied Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry<'a, V:'a> { map: &'a mut VecMap, index: usize, @@ -113,21 +115,7 @@ impl Clone for VecMap { } } -#[cfg(stage0)] -impl> Hash for VecMap { - fn hash(&self, state: &mut S) { - // In order to not traverse the `VecMap` twice, count the elements - // during iteration. - let mut count: usize = 0; - for elt in self { - elt.hash(state); - count += 1; - } - count.hash(state); - } -} #[stable(feature = "rust1", since = "1.0.0")] -#[cfg(not(stage0))] impl Hash for VecMap { fn hash(&self, state: &mut H) { // In order to not traverse the `VecMap` twice, count the elements @@ -147,6 +135,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// let mut map: VecMap<&str> = VecMap::new(); /// ``` @@ -159,6 +148,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// let mut map: VecMap<&str> = VecMap::with_capacity(10); /// ``` @@ -173,6 +163,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// let map: VecMap = VecMap::with_capacity(10); /// assert!(map.capacity() >= 10); @@ -192,6 +183,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// let mut map: VecMap<&str> = VecMap::new(); /// map.reserve_len(10); @@ -216,6 +208,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// let mut map: VecMap<&str> = VecMap::new(); /// map.reserve_len_exact(10); @@ -255,6 +248,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -283,6 +277,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -314,6 +309,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -323,7 +319,7 @@ impl VecMap { /// /// let vec: Vec<(usize, &str)> = map.into_iter().collect(); /// - /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); + /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { @@ -335,6 +331,97 @@ impl VecMap { IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) } } + /// Moves all elements from `other` into the map while overwriting existing keys. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// use std::collections::VecMap; + /// + /// let mut a = VecMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// + /// let mut b = VecMap::new(); + /// b.insert(3, "c"); + /// b.insert(4, "d"); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 4); + /// assert_eq!(b.len(), 0); + /// assert_eq!(a[1], "a"); + /// assert_eq!(a[2], "b"); + /// assert_eq!(a[3], "c"); + /// assert_eq!(a[4], "d"); + /// ``` + #[unstable(feature = "collections", + reason = "recently added as part of collections reform 2")] + pub fn append(&mut self, other: &mut Self) { + self.extend(other.drain()); + } + + /// Splits the collection into two at the given key. + /// + /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`, + /// and the returned `Self` contains elements `[at, max_key)`. + /// + /// Note that the capacity of `self` does not change. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collections)] + /// use std::collections::VecMap; + /// + /// let mut a = VecMap::new(); + /// a.insert(1, "a"); + /// a.insert(2, "b"); + /// a.insert(3, "c"); + /// a.insert(4, "d"); + /// + /// let b = a.split_off(3); + /// + /// assert_eq!(a[1], "a"); + /// assert_eq!(a[2], "b"); + /// + /// assert_eq!(b[3], "c"); + /// assert_eq!(b[4], "d"); + /// ``` + #[unstable(feature = "collections", + reason = "recently added as part of collections reform 2")] + pub fn split_off(&mut self, at: usize) -> Self { + let mut other = VecMap::new(); + + if at == 0 { + // Move all elements to other + swap(self, &mut other); + return other + } else if at > self.v.len() { + // No elements to copy + return other; + } + + // Look up the index of the first non-None item + let first_index = self.v.iter().position(|el| el.is_some()); + let start_index = match first_index { + Some(index) => max(at, index), + None => { + // self has no elements + return other; + } + }; + + // Fill the new VecMap with `None`s until `start_index` + other.v.extend((0..start_index).map(|_| None)); + + // Move elements beginning with `start_index` from `self` into `other` + other.v.extend(self.v[start_index..].iter_mut().map(|el| el.take())); + + other + } + /// Returns an iterator visiting all key-value pairs in ascending order of /// the keys, emptying (but not consuming) the original `VecMap`. /// The iterator's element type is `(usize, &'r V)`. Keeps the allocated memory for reuse. @@ -342,6 +429,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -351,7 +439,7 @@ impl VecMap { /// /// let vec: Vec<(usize, &str)> = map.drain().collect(); /// - /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); + /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); /// ``` #[unstable(feature = "collections", reason = "matches collection reform specification, waiting for dust to settle")] @@ -369,6 +457,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut a = VecMap::new(); @@ -386,6 +475,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut a = VecMap::new(); @@ -403,6 +493,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut a = VecMap::new(); @@ -418,6 +509,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -442,6 +534,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -460,6 +553,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -488,6 +582,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -513,6 +608,7 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); @@ -534,22 +630,14 @@ impl VecMap { /// # Examples /// /// ``` + /// # #![feature(collections)] /// use std::collections::VecMap; - /// use std::collections::vec_map::Entry; /// /// let mut count: VecMap = VecMap::new(); /// /// // count the number of occurrences of numbers in the vec - /// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4].iter() { - /// match count.entry(*x) { - /// Entry::Vacant(view) => { - /// view.insert(1); - /// }, - /// Entry::Occupied(mut view) => { - /// let v = view.get_mut(); - /// *v += 1; - /// }, - /// } + /// for x in vec![1, 2, 1, 2, 3, 4, 1, 2, 4] { + /// *count.entry(x).or_insert(0) += 1; /// } /// /// assert_eq!(count[1], 3); @@ -577,7 +665,9 @@ impl VecMap { impl<'a, V> Entry<'a, V> { #[unstable(feature = "collections", - reason = "matches collection reform v2 specification, waiting for dust to settle")] + reason = "will soon be replaced by or_insert")] + #[deprecated(since = "1.0", + reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> { match self { @@ -585,6 +675,28 @@ impl<'a, V> Entry<'a, V> { Vacant(entry) => Err(entry), } } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + #[unstable(feature = "collections", + reason = "matches entry v3 specification, waiting for dust to settle")] + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } } impl<'a, V> VacantEntry<'a, V> { @@ -665,7 +777,7 @@ impl Ord for VecMap { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for VecMap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "VecMap {{")); + try!(write!(f, "{{")); for (i, (k, v)) in self.iter().enumerate() { if i != 0 { try!(write!(f, ", ")); } @@ -728,7 +840,16 @@ impl Index for VecMap { type Output = V; #[inline] - fn index<'a>(&'a self, i: &usize) -> &'a V { + fn index<'a>(&'a self, i: usize) -> &'a V { + self.get(&i).expect("key not present") + } +} + +impl<'a,V> Index<&'a usize> for VecMap { + type Output = V; + + #[inline] + fn index(&self, i: &usize) -> &V { self.get(i).expect("key not present") } } @@ -736,7 +857,15 @@ impl Index for VecMap { #[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for VecMap { #[inline] - fn index_mut<'a>(&'a mut self, i: &usize) -> &'a mut V { + fn index_mut(&mut self, i: usize) -> &mut V { + self.get_mut(&i).expect("key not present") + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, V> IndexMut<&'a usize> for VecMap { + #[inline] + fn index_mut(&mut self, i: &usize) -> &mut V { self.get_mut(i).expect("key not present") } } @@ -930,431 +1059,3 @@ impl Iterator for IntoIter { impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option<(usize, V)> { self.iter.next_back() } } - -#[cfg(test)] -mod test_map { - use prelude::*; - use core::hash::{hash, SipHasher}; - - use super::VecMap; - use super::Entry::{Occupied, Vacant}; - - #[test] - fn test_get_mut() { - let mut m = VecMap::new(); - assert!(m.insert(1, 12).is_none()); - assert!(m.insert(2, 8).is_none()); - assert!(m.insert(5, 14).is_none()); - let new = 100; - match m.get_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.get(&5), Some(&new)); - } - - #[test] - fn test_len() { - let mut map = VecMap::new(); - assert_eq!(map.len(), 0); - assert!(map.is_empty()); - assert!(map.insert(5, 20).is_none()); - assert_eq!(map.len(), 1); - assert!(!map.is_empty()); - assert!(map.insert(11, 12).is_none()); - assert_eq!(map.len(), 2); - assert!(!map.is_empty()); - assert!(map.insert(14, 22).is_none()); - assert_eq!(map.len(), 3); - assert!(!map.is_empty()); - } - - #[test] - fn test_clear() { - let mut map = VecMap::new(); - assert!(map.insert(5, 20).is_none()); - assert!(map.insert(11, 12).is_none()); - assert!(map.insert(14, 22).is_none()); - map.clear(); - assert!(map.is_empty()); - assert!(map.get(&5).is_none()); - assert!(map.get(&11).is_none()); - assert!(map.get(&14).is_none()); - } - - #[test] - fn test_insert() { - let mut m = VecMap::new(); - assert_eq!(m.insert(1, 2), None); - assert_eq!(m.insert(1, 3), Some(2)); - assert_eq!(m.insert(1, 4), Some(3)); - } - - #[test] - fn test_remove() { - let mut m = VecMap::new(); - m.insert(1, 2); - assert_eq!(m.remove(&1), Some(2)); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_keys() { - let mut map = VecMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let keys: Vec<_> = map.keys().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let mut map = VecMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let values: Vec<_> = map.values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - let mut it = m.iter(); - assert_eq!(it.size_hint(), (0, Some(11))); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.size_hint(), (0, Some(10))); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.size_hint(), (0, Some(9))); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.size_hint(), (0, Some(7))); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.size_hint(), (0, Some(4))); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_size_hints() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - assert_eq!(m.iter().size_hint(), (0, Some(11))); - assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); - } - - #[test] - fn test_mut_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - for (k, v) in &mut m { - *v += k as isize; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_rev_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - let mut it = m.iter().rev(); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.next().unwrap(), (0, &1)); - assert!(it.next().is_none()); - } - - #[test] - fn test_mut_rev_iterator() { - let mut m = VecMap::new(); - - assert!(m.insert(0, 1).is_none()); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(3, 5).is_none()); - assert!(m.insert(6, 10).is_none()); - assert!(m.insert(10, 11).is_none()); - - for (k, v) in m.iter_mut().rev() { - *v += k as isize; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_move_iter() { - let mut m = VecMap::new(); - m.insert(1, box 2); - let mut called = false; - for (k, v) in m { - assert!(!called); - called = true; - assert_eq!(k, 1); - assert_eq!(v, box 2); - } - assert!(called); - } - - #[test] - fn test_drain_iterator() { - let mut map = VecMap::new(); - map.insert(1, "a"); - map.insert(3, "c"); - map.insert(2, "b"); - - let vec: Vec<_> = map.drain().collect(); - - assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); - assert_eq!(map.len(), 0); - } - - #[test] - fn test_show() { - let mut map = VecMap::new(); - let empty = VecMap::::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{:?}", map); - assert!(map_str == "VecMap {1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "VecMap {}"); - } - - #[test] - fn test_clone() { - let mut a = VecMap::new(); - - a.insert(1, 'x'); - a.insert(4, 'y'); - a.insert(6, 'z'); - - assert!(a.clone() == a); - } - - #[test] - fn test_eq() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(a == b); - assert!(a.insert(0, 5).is_none()); - assert!(a != b); - assert!(b.insert(0, 4).is_none()); - assert!(a != b); - assert!(a.insert(5, 19).is_none()); - assert!(a != b); - assert!(!b.insert(0, 5).is_none()); - assert!(a != b); - assert!(b.insert(5, 19).is_none()); - assert!(a == b); - - a = VecMap::new(); - b = VecMap::with_capacity(1); - assert!(a == b); - } - - #[test] - fn test_lt() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2, 5).is_none()); - assert!(a < b); - assert!(a.insert(2, 7).is_none()); - assert!(!(a < b) && b < a); - assert!(b.insert(1, 0).is_none()); - assert!(b < a); - assert!(a.insert(0, 6).is_none()); - assert!(a < b); - assert!(a.insert(6, 2).is_none()); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = VecMap::new(); - let mut b = VecMap::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1, 1).is_none()); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2, 2).is_none()); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_hash() { - let mut x = VecMap::new(); - let mut y = VecMap::new(); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - x.insert(1, 'a'); - x.insert(2, 'b'); - x.insert(3, 'c'); - - y.insert(3, 'c'); - y.insert(2, 'b'); - y.insert(1, 'a'); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - - x.insert(1000, 'd'); - x.remove(&1000); - - assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); - } - - #[test] - fn test_from_iter() { - let xs = vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; - - let map: VecMap<_> = xs.iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_index() { - let mut map = VecMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[3], 4); - } - - #[test] - #[should_fail] - fn test_index_nonexistent() { - let mut map = VecMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } - - #[test] - fn test_entry(){ - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: VecMap<_> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - *v *= 10; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } -} - -#[cfg(test)] -mod bench { - use super::VecMap; - - map_insert_rand_bench!{insert_rand_100, 100, VecMap} - map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap} - - map_insert_seq_bench!{insert_seq_100, 100, VecMap} - map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap} - - map_find_rand_bench!{find_rand_100, 100, VecMap} - map_find_rand_bench!{find_rand_10_000, 10_000, VecMap} - - map_find_seq_bench!{find_seq_100, 100, VecMap} - map_find_seq_bench!{find_seq_10_000, 10_000, VecMap} -} diff --git a/src/libcollections/bench.rs b/src/libcollectionstest/bench.rs similarity index 92% rename from src/libcollections/bench.rs rename to src/libcollectionstest/bench.rs index 107f6031c1..8f2e71b666 100644 --- a/src/libcollections/bench.rs +++ b/src/libcollectionstest/bench.rs @@ -22,13 +22,13 @@ macro_rules! map_insert_rand_bench { let mut rng = rand::weak_rng(); for _ in 0..n { - let i = rng.gen() % n; + let i = rng.gen::() % n; map.insert(i, i); } // measure b.iter(|| { - let k = rng.gen() % n; + let k = rng.gen::() % n; map.insert(k, k); map.remove(&k); }); @@ -66,18 +66,18 @@ macro_rules! map_find_rand_bench { ($name: ident, $n: expr, $map: ident) => ( #[bench] pub fn $name(b: &mut ::test::Bencher) { - use std::rand; - use std::iter::IteratorExt; + use std::iter::Iterator; use std::rand::Rng; + use std::rand; + use std::vec::Vec; use test::black_box; - use vec::Vec; let mut map = $map::new(); let n: usize = $n; // setup let mut rng = rand::weak_rng(); - let mut keys: Vec<_> = (0..n).map(|_| rng.gen() % n).collect(); + let mut keys: Vec<_> = (0..n).map(|_| rng.gen::() % n).collect(); for &k in &keys { map.insert(k, k); diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs new file mode 100644 index 0000000000..47a366bb1e --- /dev/null +++ b/src/libcollectionstest/binary_heap.rs @@ -0,0 +1,219 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BinaryHeap; + +#[test] +fn test_iterator() { + let data = vec![5, 9, 3]; + let iterout = [9, 5, 3]; + let heap = BinaryHeap::from_vec(data); + let mut i = 0; + for el in &heap { + assert_eq!(*el, iterout[i]); + i += 1; + } +} + +#[test] +fn test_iterator_reverse() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from_vec(data); + + let v: Vec<_> = pq.iter().rev().cloned().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_move_iter() { + let data = vec![5, 9, 3]; + let iterout = vec![9, 5, 3]; + let pq = BinaryHeap::from_vec(data); + + let v: Vec<_> = pq.into_iter().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_move_iter_size_hint() { + let data = vec![5, 9]; + let pq = BinaryHeap::from_vec(data); + + let mut it = pq.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next(), Some(9)); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next(), Some(5)); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_move_iter_reverse() { + let data = vec![5, 9, 3]; + let iterout = vec![3, 5, 9]; + let pq = BinaryHeap::from_vec(data); + + let v: Vec<_> = pq.into_iter().rev().collect(); + assert_eq!(v, iterout); +} + +#[test] +fn test_peek_and_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from_vec(data); + while !heap.is_empty() { + assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } +} + +#[test] +fn test_push() { + let mut heap = BinaryHeap::from_vec(vec![2, 4, 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == 9); + heap.push(11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == 11); + heap.push(5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == 11); + heap.push(27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == 27); + heap.push(3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == 27); + heap.push(103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == 103); +} + +#[test] +fn test_push_unique() { + let mut heap = BinaryHeap::>::from_vec(vec![box 2, box 4, box 9]); + assert_eq!(heap.len(), 3); + assert!(*heap.peek().unwrap() == box 9); + heap.push(box 11); + assert_eq!(heap.len(), 4); + assert!(*heap.peek().unwrap() == box 11); + heap.push(box 5); + assert_eq!(heap.len(), 5); + assert!(*heap.peek().unwrap() == box 11); + heap.push(box 27); + assert_eq!(heap.len(), 6); + assert!(*heap.peek().unwrap() == box 27); + heap.push(box 3); + assert_eq!(heap.len(), 7); + assert!(*heap.peek().unwrap() == box 27); + heap.push(box 103); + assert_eq!(heap.len(), 8); + assert!(*heap.peek().unwrap() == box 103); +} + +#[test] +fn test_push_pop() { + let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(6), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(0), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(4), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(1), 4); + assert_eq!(heap.len(), 5); +} + +#[test] +fn test_replace() { + let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(6).unwrap(), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(0).unwrap(), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(4).unwrap(), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(1).unwrap(), 4); + assert_eq!(heap.len(), 5); +} + +fn check_to_vec(mut data: Vec) { + let heap = BinaryHeap::from_vec(data.clone()); + let mut v = heap.clone().into_vec(); + v.sort(); + data.sort(); + + assert_eq!(v, data); + assert_eq!(heap.into_sorted_vec(), data); +} + +#[test] +fn test_to_vec() { + check_to_vec(vec![]); + check_to_vec(vec![5]); + check_to_vec(vec![3, 2]); + check_to_vec(vec![2, 3]); + check_to_vec(vec![5, 1, 2]); + check_to_vec(vec![1, 100, 2, 3]); + check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); + check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); + check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); + check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); + check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); +} + +#[test] +fn test_empty_pop() { + let mut heap = BinaryHeap::::new(); + assert!(heap.pop().is_none()); +} + +#[test] +fn test_empty_peek() { + let empty = BinaryHeap::::new(); + assert!(empty.peek().is_none()); +} + +#[test] +fn test_empty_replace() { + let mut heap = BinaryHeap::new(); + assert!(heap.replace(5).is_none()); +} + +#[test] +fn test_from_iter() { + let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; + + let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); + + for &x in &xs { + assert_eq!(q.pop().unwrap(), x); + } +} + +#[test] +fn test_drain() { + let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); + + assert_eq!(q.drain().take(5).count(), 5); + + assert!(q.is_empty()); +} diff --git a/src/test/pretty/issue-929.rs b/src/libcollectionstest/bit/mod.rs similarity index 76% rename from src/test/pretty/issue-929.rs rename to src/libcollectionstest/bit/mod.rs index 75a6b91934..8e06524f2e 100644 --- a/src/test/pretty/issue-929.rs +++ b/src/libcollectionstest/bit/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,6 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f() { if (1 == panic!()) { } else { } } - -fn main() { } +mod set; +mod vec; diff --git a/src/libcollectionstest/bit/set.rs b/src/libcollectionstest/bit/set.rs new file mode 100644 index 0000000000..19ea25ee34 --- /dev/null +++ b/src/libcollectionstest/bit/set.rs @@ -0,0 +1,440 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::collections::{BitSet, BitVec}; + +#[test] +fn test_bit_set_show() { + let mut s = BitSet::new(); + s.insert(1); + s.insert(10); + s.insert(50); + s.insert(2); + assert_eq!("{1, 2, 10, 50}", format!("{:?}", s)); +} + +#[test] +fn test_bit_set_from_usizes() { + let usizes = vec![0, 2, 2, 3]; + let a: BitSet = usizes.into_iter().collect(); + let mut b = BitSet::new(); + b.insert(0); + b.insert(2); + b.insert(3); + assert_eq!(a, b); +} + +#[test] +fn test_bit_set_iterator() { + let usizes = vec![0, 2, 2, 3]; + let bit_vec: BitSet = usizes.into_iter().collect(); + + let idxs: Vec<_> = bit_vec.iter().collect(); + assert_eq!(idxs, [0, 2, 3]); + + let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect(); + let real: Vec<_> = (0..10000).step_by(2).collect(); + + let idxs: Vec<_> = long.iter().collect(); + assert_eq!(idxs, real); +} + +#[test] +fn test_bit_set_frombit_vec_init() { + let bools = [true, false]; + let lengths = [10, 64, 100]; + for &b in &bools { + for &l in &lengths { + let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b)); + assert_eq!(bitset.contains(&1), b); + assert_eq!(bitset.contains(&(l-1)), b); + assert!(!bitset.contains(&l)); + } + } +} + +#[test] +fn test_bit_vec_masking() { + let b = BitVec::from_elem(140, true); + let mut bs = BitSet::from_bit_vec(b); + assert!(bs.contains(&139)); + assert!(!bs.contains(&140)); + assert!(bs.insert(150)); + assert!(!bs.contains(&140)); + assert!(!bs.contains(&149)); + assert!(bs.contains(&150)); + assert!(!bs.contains(&151)); +} + +#[test] +fn test_bit_set_basic() { + let mut b = BitSet::new(); + assert!(b.insert(3)); + assert!(!b.insert(3)); + assert!(b.contains(&3)); + assert!(b.insert(4)); + assert!(!b.insert(4)); + assert!(b.contains(&3)); + assert!(b.insert(400)); + assert!(!b.insert(400)); + assert!(b.contains(&400)); + assert_eq!(b.len(), 3); +} + +#[test] +fn test_bit_set_intersection() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(11)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + + assert!(b.insert(2)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let expected = [3, 5, 11, 77]; + let actual: Vec<_> = a.intersection(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_difference() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(200)); + assert!(a.insert(500)); + + assert!(b.insert(3)); + assert!(b.insert(200)); + + let expected = [1, 5, 500]; + let actual: Vec<_> = a.difference(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_symmetric_difference() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(220)); + + let expected = [1, 5, 11, 14, 220]; + let actual: Vec<_> = a.symmetric_difference(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_union() { + let mut a = BitSet::new(); + let mut b = BitSet::new(); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(160)); + assert!(a.insert(19)); + assert!(a.insert(24)); + assert!(a.insert(200)); + + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; + let actual: Vec<_> = a.union(&b).collect(); + assert_eq!(actual, expected); +} + +#[test] +fn test_bit_set_subset() { + let mut set1 = BitSet::new(); + let mut set2 = BitSet::new(); + + assert!(set1.is_subset(&set2)); // {} {} + set2.insert(100); + assert!(set1.is_subset(&set2)); // {} { 1 } + set2.insert(200); + assert!(set1.is_subset(&set2)); // {} { 1, 2 } + set1.insert(200); + assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } + set1.insert(300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } + set2.insert(300); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } + set2.insert(400); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } + set2.remove(&100); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } + set2.remove(&300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } + set1.remove(&300); + assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } +} + +#[test] +fn test_bit_set_is_disjoint() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000])); + let c = BitSet::new(); + let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000])); + + assert!(!a.is_disjoint(&d)); + assert!(!d.is_disjoint(&a)); + + assert!(a.is_disjoint(&b)); + assert!(a.is_disjoint(&c)); + assert!(b.is_disjoint(&a)); + assert!(b.is_disjoint(&c)); + assert!(c.is_disjoint(&a)); + assert!(c.is_disjoint(&b)); +} + +#[test] +fn test_bit_set_union_with() { + //a should grow to include larger elements + let mut a = BitSet::new(); + a.insert(0); + let mut b = BitSet::new(); + b.insert(5); + let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); + a.union_with(&b); + assert_eq!(a, expected); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.union_with(&b); + b.union_with(&c); + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 4); +} + +#[test] +fn test_bit_set_intersect_with() { + // Explicitly 0'ed bits + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::new(); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); +} + +#[test] +fn test_bit_set_difference_with() { + // Explicitly 0'ed bits + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitSet::new(); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010])); + let c = a.clone(); + a.difference_with(&b); + b.difference_with(&c); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); +} + +#[test] +fn test_bit_set_symmetric_difference_with() { + //a should grow to include larger elements + let mut a = BitSet::new(); + a.insert(0); + a.insert(1); + let mut b = BitSet::new(); + b.insert(1); + b.insert(5); + let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100])); + a.symmetric_difference_with(&b); + assert_eq!(a, expected); + + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::new(); + let c = a.clone(); + a.symmetric_difference_with(&b); + assert_eq!(a, c); + + // Standard + let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010])); + let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010])); + let c = a.clone(); + a.symmetric_difference_with(&b); + b.symmetric_difference_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); +} + +#[test] +fn test_bit_set_eq() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = BitSet::new(); + + assert!(a == a); + assert!(a != b); + assert!(a != c); + assert!(b == b); + assert!(b == c); + assert!(c == c); +} + +#[test] +fn test_bit_set_cmp() { + let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010])); + let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000])); + let c = BitSet::new(); + + assert_eq!(a.cmp(&b), Greater); + assert_eq!(a.cmp(&c), Greater); + assert_eq!(b.cmp(&a), Less); + assert_eq!(b.cmp(&c), Equal); + assert_eq!(c.cmp(&a), Less); + assert_eq!(c.cmp(&b), Equal); +} + +#[test] +fn test_bit_vec_remove() { + let mut a = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.remove(&1)); + + assert!(a.insert(100)); + assert!(a.remove(&100)); + + assert!(a.insert(1000)); + assert!(a.remove(&1000)); + a.shrink_to_fit(); +} + +#[test] +fn test_bit_vec_clone() { + let mut a = BitSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(100)); + assert!(a.insert(1000)); + + let mut b = a.clone(); + + assert!(a == b); + + assert!(b.remove(&1)); + assert!(a.contains(&1)); + + assert!(a.remove(&1000)); + assert!(b.contains(&1000)); +} + +mod bench { + use std::collections::{BitSet, BitVec}; + use std::rand::{Rng, self}; + use std::u32; + + use test::{Bencher, black_box}; + + const BENCH_BITS : usize = 1 << 14; + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_bit_vecset_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitSet::new(); + b.iter(|| { + for _ in 0..100 { + bit_vec.insert((r.next_u32() as usize) % u32::BITS as usize); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vecset_big(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitSet::new(); + b.iter(|| { + for _ in 0..100 { + bit_vec.insert((r.next_u32() as usize) % BENCH_BITS); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vecset_iter(b: &mut Bencher) { + let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, + |idx| {idx % 3 == 0})); + b.iter(|| { + let mut sum = 0; + for idx in &bit_vec { + sum += idx as usize; + } + sum + }) + } +} diff --git a/src/libcollectionstest/bit/vec.rs b/src/libcollectionstest/bit/vec.rs new file mode 100644 index 0000000000..3826974d1a --- /dev/null +++ b/src/libcollectionstest/bit/vec.rs @@ -0,0 +1,729 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BitVec; +use std::u32; + +#[test] +fn test_to_str() { + let zerolen = BitVec::new(); + assert_eq!(format!("{:?}", zerolen), ""); + + let eightbits = BitVec::from_elem(8, false); + assert_eq!(format!("{:?}", eightbits), "00000000") +} + +#[test] +fn test_0_elements() { + let act = BitVec::new(); + let exp = Vec::new(); + assert!(act.eq_vec(&exp)); + assert!(act.none() && act.all()); +} + +#[test] +fn test_1_element() { + let mut act = BitVec::from_elem(1, false); + assert!(act.eq_vec(&[false])); + assert!(act.none() && !act.all()); + act = BitVec::from_elem(1, true); + assert!(act.eq_vec(&[true])); + assert!(!act.none() && act.all()); +} + +#[test] +fn test_2_elements() { + let mut b = BitVec::from_elem(2, false); + b.set(0, true); + b.set(1, false); + assert_eq!(format!("{:?}", b), "10"); + assert!(!b.none() && !b.all()); +} + +#[test] +fn test_10_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(10, false); + assert!((act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false]))); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(10, true); + assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(5, true); + act.set(6, true); + act.set(7, true); + act.set(8, true); + act.set(9, true); + assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(10, false); + act.set(0, true); + act.set(3, true); + act.set(6, true); + act.set(9, true); + assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_31_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(31, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(31, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(31, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_32_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(32, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(32, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true, true])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(32, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_33_elements() { + let mut act; + // all 0 + + act = BitVec::from_elem(33, false); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false])); + assert!(act.none() && !act.all()); + // all 1 + + act = BitVec::from_elem(33, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true])); + assert!(!act.none() && act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(0, true); + act.set(1, true); + act.set(2, true); + act.set(3, true); + act.set(4, true); + act.set(5, true); + act.set(6, true); + act.set(7, true); + assert!(act.eq_vec( + &[true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(16, true); + act.set(17, true); + act.set(18, true); + act.set(19, true); + act.set(20, true); + act.set(21, true); + act.set(22, true); + act.set(23, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(24, true); + act.set(25, true); + act.set(26, true); + act.set(27, true); + act.set(28, true); + act.set(29, true); + act.set(30, true); + act.set(31, true); + assert!(act.eq_vec( + &[false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, + false, false, true, true, true, true, true, true, true, true, false])); + assert!(!act.none() && !act.all()); + // mixed + + act = BitVec::from_elem(33, false); + act.set(3, true); + act.set(17, true); + act.set(30, true); + act.set(31, true); + act.set(32, true); + assert!(act.eq_vec( + &[false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true, true])); + assert!(!act.none() && !act.all()); +} + +#[test] +fn test_equal_differing_sizes() { + let v0 = BitVec::from_elem(10, false); + let v1 = BitVec::from_elem(11, false); + assert!(v0 != v1); +} + +#[test] +fn test_equal_greatly_differing_sizes() { + let v0 = BitVec::from_elem(10, false); + let v1 = BitVec::from_elem(110, false); + assert!(v0 != v1); +} + +#[test] +fn test_equal_sneaky_small() { + let mut a = BitVec::from_elem(1, false); + a.set(0, true); + + let mut b = BitVec::from_elem(1, true); + b.set(0, true); + + assert_eq!(a, b); +} + +#[test] +fn test_equal_sneaky_big() { + let mut a = BitVec::from_elem(100, false); + for i in 0..100 { + a.set(i, true); + } + + let mut b = BitVec::from_elem(100, true); + for i in 0..100 { + b.set(i, true); + } + + assert_eq!(a, b); +} + +#[test] +fn test_from_bytes() { + let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let str = concat!("10110110", "00000000", "11111111"); + assert_eq!(format!("{:?}", bit_vec), str); +} + +#[test] +fn test_to_bytes() { + let mut bv = BitVec::from_elem(3, true); + bv.set(1, false); + assert_eq!(bv.to_bytes(), [0b10100000]); + + let mut bv = BitVec::from_elem(9, false); + bv.set(2, true); + bv.set(8, true); + assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]); +} + +#[test] +fn test_from_bools() { + let bools = vec![true, false, true, true]; + let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); + assert_eq!(format!("{:?}", bit_vec), "1011"); +} + +#[test] +fn test_to_bools() { + let bools = vec![false, false, true, false, false, true, true, false]; + assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::>(), bools); +} + +#[test] +fn test_bit_vec_iterator() { + let bools = vec![true, false, true, true]; + let bit_vec: BitVec = bools.iter().map(|n| *n).collect(); + + assert_eq!(bit_vec.iter().collect::>(), bools); + + let long: Vec<_> = (0..10000).map(|i| i % 2 == 0).collect(); + let bit_vec: BitVec = long.iter().map(|n| *n).collect(); + assert_eq!(bit_vec.iter().collect::>(), long) +} + +#[test] +fn test_small_difference() { + let mut b1 = BitVec::from_elem(3, false); + let mut b2 = BitVec::from_elem(3, false); + b1.set(0, true); + b1.set(1, true); + b2.set(1, true); + b2.set(2, true); + assert!(b1.difference(&b2)); + assert!(b1[0]); + assert!(!b1[1]); + assert!(!b1[2]); +} + +#[test] +fn test_big_difference() { + let mut b1 = BitVec::from_elem(100, false); + let mut b2 = BitVec::from_elem(100, false); + b1.set(0, true); + b1.set(40, true); + b2.set(40, true); + b2.set(80, true); + assert!(b1.difference(&b2)); + assert!(b1[0]); + assert!(!b1[40]); + assert!(!b1[80]); +} + +#[test] +fn test_small_clear() { + let mut b = BitVec::from_elem(14, true); + assert!(!b.none() && b.all()); + b.clear(); + assert!(b.none() && !b.all()); +} + +#[test] +fn test_big_clear() { + let mut b = BitVec::from_elem(140, true); + assert!(!b.none() && b.all()); + b.clear(); + assert!(b.none() && !b.all()); +} + +#[test] +fn test_bit_vec_lt() { + let mut a = BitVec::from_elem(5, false); + let mut b = BitVec::from_elem(5, false); + + assert!(!(a < b) && !(b < a)); + b.set(2, true); + assert!(a < b); + a.set(3, true); + assert!(a < b); + a.set(2, true); + assert!(!(a < b) && b < a); + b.set(0, true); + assert!(a < b); +} + +#[test] +fn test_ord() { + let mut a = BitVec::from_elem(5, false); + let mut b = BitVec::from_elem(5, false); + + assert!(a <= b && a >= b); + a.set(1, true); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + b.set(1, true); + b.set(2, true); + assert!(b > a && b >= a); + assert!(a < b && a <= b); +} + + +#[test] +fn test_small_bit_vec_tests() { + let v = BitVec::from_bytes(&[0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = BitVec::from_bytes(&[0b00010100]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = BitVec::from_bytes(&[0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); +} + +#[test] +fn test_big_bit_vec_tests() { + let v = BitVec::from_bytes(&[ // 88 bits + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = BitVec::from_bytes(&[ // 88 bits + 0, 0, 0b00010100, 0, + 0, 0, 0, 0b00110100, + 0, 0, 0]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = BitVec::from_bytes(&[ // 88 bits + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); +} + +#[test] +fn test_bit_vec_push_pop() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize - 2, false); + assert_eq!(s.len(), 5 * u32::BITS as usize - 2); + assert_eq!(s[5 * u32::BITS as usize - 3], false); + s.push(true); + s.push(true); + assert_eq!(s[5 * u32::BITS as usize - 2], true); + assert_eq!(s[5 * u32::BITS as usize - 1], true); + // Here the internal vector will need to be extended + s.push(false); + assert_eq!(s[5 * u32::BITS as usize], false); + s.push(false); + assert_eq!(s[5 * u32::BITS as usize + 1], false); + assert_eq!(s.len(), 5 * u32::BITS as usize + 2); + // Pop it all off + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.len(), 5 * u32::BITS as usize - 2); +} + +#[test] +fn test_bit_vec_truncate() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); + + assert_eq!(s, BitVec::from_elem(5 * u32::BITS as usize, true)); + assert_eq!(s.len(), 5 * u32::BITS as usize); + s.truncate(4 * u32::BITS as usize); + assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); + assert_eq!(s.len(), 4 * u32::BITS as usize); + // Truncating to a size > s.len() should be a noop + s.truncate(5 * u32::BITS as usize); + assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true)); + assert_eq!(s.len(), 4 * u32::BITS as usize); + s.truncate(3 * u32::BITS as usize - 10); + assert_eq!(s, BitVec::from_elem(3 * u32::BITS as usize - 10, true)); + assert_eq!(s.len(), 3 * u32::BITS as usize - 10); + s.truncate(0); + assert_eq!(s, BitVec::from_elem(0, true)); + assert_eq!(s.len(), 0); +} + +#[test] +fn test_bit_vec_reserve() { + let mut s = BitVec::from_elem(5 * u32::BITS as usize, true); + // Check capacity + assert!(s.capacity() >= 5 * u32::BITS as usize); + s.reserve(2 * u32::BITS as usize); + assert!(s.capacity() >= 7 * u32::BITS as usize); + s.reserve(7 * u32::BITS as usize); + assert!(s.capacity() >= 12 * u32::BITS as usize); + s.reserve_exact(7 * u32::BITS as usize); + assert!(s.capacity() >= 12 * u32::BITS as usize); + s.reserve(7 * u32::BITS as usize + 1); + assert!(s.capacity() >= 12 * u32::BITS as usize + 1); + // Check that length hasn't changed + assert_eq!(s.len(), 5 * u32::BITS as usize); + s.push(true); + s.push(false); + s.push(true); + assert_eq!(s[5 * u32::BITS as usize - 1], true); + assert_eq!(s[5 * u32::BITS as usize - 0], true); + assert_eq!(s[5 * u32::BITS as usize + 1], false); + assert_eq!(s[5 * u32::BITS as usize + 2], true); +} + +#[test] +fn test_bit_vec_grow() { + let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); + bit_vec.grow(32, true); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF])); + bit_vec.grow(64, false); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); + bit_vec.grow(16, true); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); +} + +#[test] +fn test_bit_vec_extend() { + let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); + bit_vec.extend(ext.iter()); + assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111, + 0b01001001, 0b10010010, 0b10111101])); +} + +mod bench { + use std::collections::BitVec; + use std::u32; + use std::rand::{Rng, self}; + + use test::{Bencher, black_box}; + + const BENCH_BITS : usize = 1 << 14; + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_usize_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = 0 as usize; + b.iter(|| { + for _ in 0..100 { + bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS as usize); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_big_fixed(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_big_variable(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen()); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_set_small(b: &mut Bencher) { + let mut r = rng(); + let mut bit_vec = BitVec::from_elem(u32::BITS as usize, false); + b.iter(|| { + for _ in 0..100 { + bit_vec.set((r.next_u32() as usize) % u32::BITS as usize, true); + } + black_box(&bit_vec); + }); + } + + #[bench] + fn bench_bit_vec_big_union(b: &mut Bencher) { + let mut b1 = BitVec::from_elem(BENCH_BITS, false); + let b2 = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + b1.union(&b2) + }) + } + + #[bench] + fn bench_bit_vec_small_iter(b: &mut Bencher) { + let bit_vec = BitVec::from_elem(u32::BITS as usize, false); + b.iter(|| { + let mut sum = 0; + for _ in 0..10 { + for pres in &bit_vec { + sum += pres as usize; + } + } + sum + }) + } + + #[bench] + fn bench_bit_vec_big_iter(b: &mut Bencher) { + let bit_vec = BitVec::from_elem(BENCH_BITS, false); + b.iter(|| { + let mut sum = 0; + for pres in &bit_vec { + sum += pres as usize; + } + sum + }) + } +} diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs new file mode 100644 index 0000000000..10d69c9f5e --- /dev/null +++ b/src/libcollectionstest/btree/map.rs @@ -0,0 +1,299 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeMap; +use std::collections::Bound::{Excluded, Included, Unbounded, self}; +use std::collections::btree_map::Entry::{Occupied, Vacant}; +use std::iter::range_inclusive; + +#[test] +fn test_basic_large() { + let mut map = BTreeMap::new(); + let size = 10000; + assert_eq!(map.len(), 0); + + for i in 0..size { + assert_eq!(map.insert(i, 10*i), None); + assert_eq!(map.len(), i + 1); + } + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i*10)); + } + + for i in size..size*2 { + assert_eq!(map.get(&i), None); + } + + for i in 0..size { + assert_eq!(map.insert(i, 100*i), Some(10*i)); + assert_eq!(map.len(), size); + } + + for i in 0..size { + assert_eq!(map.get(&i).unwrap(), &(i*100)); + } + + for i in 0..size/2 { + assert_eq!(map.remove(&(i*2)), Some(i*200)); + assert_eq!(map.len(), size - i - 1); + } + + for i in 0..size/2 { + assert_eq!(map.get(&(2*i)), None); + assert_eq!(map.get(&(2*i+1)).unwrap(), &(i*200 + 100)); + } + + for i in 0..size/2 { + assert_eq!(map.remove(&(2*i)), None); + assert_eq!(map.remove(&(2*i+1)), Some(i*200 + 100)); + assert_eq!(map.len(), size/2 - i - 1); + } +} + +#[test] +fn test_basic_small() { + let mut map = BTreeMap::new(); + assert_eq!(map.remove(&1), None); + assert_eq!(map.get(&1), None); + assert_eq!(map.insert(1, 1), None); + assert_eq!(map.get(&1), Some(&1)); + assert_eq!(map.insert(1, 2), Some(1)); + assert_eq!(map.get(&1), Some(&2)); + assert_eq!(map.insert(2, 4), None); + assert_eq!(map.get(&2), Some(&4)); + assert_eq!(map.remove(&1), Some(2)); + assert_eq!(map.remove(&2), Some(4)); + assert_eq!(map.remove(&1), None); +} + +#[test] +fn test_iter() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) where T: Iterator { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_iter_rev() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) where T: Iterator { + for i in 0..size { + assert_eq!(iter.size_hint(), (size - i, Some(size - i))); + assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().rev().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter().rev()); +} + +#[test] +fn test_iter_mixed() { + let size = 10000; + + // Forwards + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(size: usize, mut iter: T) + where T: Iterator + DoubleEndedIterator { + for i in 0..size / 4 { + assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); + assert_eq!(iter.next().unwrap(), (i, i)); + assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); + } + for i in size / 4..size * 3 / 4 { + assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); + assert_eq!(iter.next().unwrap(), (i, i)); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + } + test(size, map.iter().map(|(&k, &v)| (k, v))); + test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); + test(size, map.into_iter()); +} + +#[test] +fn test_range_small() { + let size = 5; + + // Forwards + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + let mut j = 0; + for ((&k, &v), i) in map.range(Included(&2), Unbounded).zip(2..size) { + assert_eq!(k, i); + assert_eq!(v, i); + j += 1; + } + assert_eq!(j, size - 2); +} + +#[test] +fn test_range_1000() { + let size = 1000; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { + let mut kvs = map.range(min, max).map(|(&k, &v)| (k, v)); + let mut pairs = (0..size).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + test(&map, size, Included(&0), Excluded(&size)); + test(&map, size, Unbounded, Excluded(&size)); + test(&map, size, Included(&0), Included(&(size - 1))); + test(&map, size, Unbounded, Included(&(size - 1))); + test(&map, size, Included(&0), Unbounded); + test(&map, size, Unbounded, Unbounded); +} + +#[test] +fn test_range() { + let size = 200; + let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); + + for i in 0..size { + for j in i..size { + let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); + let mut pairs = range_inclusive(i, j).map(|i| (i, i)); + + for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { + assert_eq!(kv, pair); + } + assert_eq!(kvs.next(), None); + assert_eq!(pairs.next(), None); + } + } +} + +#[test] +fn test_entry(){ + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + *v *= 10; + } + } + assert_eq!(map.get(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get(&3), None); + assert_eq!(map.len(), 5); + + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); +} + +mod bench { + use std::collections::BTreeMap; + use std::rand::{Rng, weak_rng}; + + use test::{Bencher, black_box}; + + map_insert_rand_bench!{insert_rand_100, 100, BTreeMap} + map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap} + + map_insert_seq_bench!{insert_seq_100, 100, BTreeMap} + map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap} + + map_find_rand_bench!{find_rand_100, 100, BTreeMap} + map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap} + + map_find_seq_bench!{find_seq_100, 100, BTreeMap} + map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap} + + fn bench_iter(b: &mut Bencher, size: i32) { + let mut map = BTreeMap::::new(); + let mut rng = weak_rng(); + + for _ in 0..size { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for entry in &map { + black_box(entry); + } + }); + } + + #[bench] + pub fn iter_20(b: &mut Bencher) { + bench_iter(b, 20); + } + + #[bench] + pub fn iter_1000(b: &mut Bencher) { + bench_iter(b, 1000); + } + + #[bench] + pub fn iter_100000(b: &mut Bencher) { + bench_iter(b, 100000); + } +} diff --git a/src/libcoretest/num/int.rs b/src/libcollectionstest/btree/mod.rs similarity index 95% rename from src/libcoretest/num/int.rs rename to src/libcollectionstest/btree/mod.rs index be8dfd02ee..0db48f3ce9 100644 --- a/src/libcoretest/num/int.rs +++ b/src/libcollectionstest/btree/mod.rs @@ -8,4 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -int_module!(int, int); +mod map; +mod set; diff --git a/src/libcollectionstest/btree/set.rs b/src/libcollectionstest/btree/set.rs new file mode 100644 index 0000000000..234cd6e0fd --- /dev/null +++ b/src/libcollectionstest/btree/set.rs @@ -0,0 +1,186 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeSet; +use std::hash::{SipHasher, self}; + +#[test] +fn test_clone_eq() { + let mut m = BTreeSet::new(); + + m.insert(1); + m.insert(2); + + assert!(m.clone() == m); +} + +#[test] +fn test_hash() { + let mut x = BTreeSet::new(); + let mut y = BTreeSet::new(); + + x.insert(1); + x.insert(2); + x.insert(3); + + y.insert(3); + y.insert(2); + y.insert(1); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +struct Counter<'a, 'b> { + i: &'a mut usize, + expected: &'b [i32], +} + +impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> { + extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool { + assert_eq!(x, self.expected[*self.i]); + *self.i += 1; + true + } +} + +impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> { + type Output = bool; + + extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool { + self.call_mut(args) + } +} + +fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) where + // FIXME Replace Counter with `Box _>` + F: FnOnce(&BTreeSet, &BTreeSet, Counter) -> bool, +{ + let mut set_a = BTreeSet::new(); + let mut set_b = BTreeSet::new(); + + for x in a { assert!(set_a.insert(*x)) } + for y in b { assert!(set_b.insert(*y)) } + + let mut i = 0; + f(&set_a, &set_b, Counter { i: &mut i, expected: expected }); + assert_eq!(i, expected.len()); +} + +#[test] +fn test_intersection() { + fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection(&[], &[], &[]); + check_intersection(&[1, 2, 3], &[], &[]); + check_intersection(&[], &[1, 2, 3], &[]); + check_intersection(&[2], &[1, 2, 3], &[2]); + check_intersection(&[1, 2, 3], &[2], &[2]); + check_intersection(&[11, 1, 3, 77, 103, 5, -5], + &[2, 11, 77, -9, -42, 5, 3], + &[3, 5, 11, 77]); +} + +#[test] +fn test_difference() { + fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference(&[], &[], &[]); + check_difference(&[1, 12], &[], &[1, 12]); + check_difference(&[], &[1, 2, 3, 9], &[]); + check_difference(&[1, 3, 5, 9, 11], + &[3, 9], + &[1, 5, 11]); + check_difference(&[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 34, 38, 39, 50], + &[11, 22, 33, 40, 42]); +} + +#[test] +fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference(&[], &[], &[]); + check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); + check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); + check_symmetric_difference(&[1, 3, 5, 9, 11], + &[-2, 3, 9, 14, 22], + &[-2, 1, 5, 11, 14, 22]); +} + +#[test] +fn test_union() { + fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union(&[], &[], &[]); + check_union(&[1, 2, 3], &[2], &[1, 2, 3]); + check_union(&[2], &[1, 2, 3], &[1, 2, 3]); + check_union(&[1, 3, 5, 9, 11, 16, 19, 24], + &[-2, 1, 5, 9, 13, 19], + &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); +} + +#[test] +fn test_zip() { + let mut x = BTreeSet::new(); + x.insert(5); + x.insert(12); + x.insert(11); + + let mut y = BTreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = x.iter().zip(y.iter()); + + // FIXME: #5801: this needs a type hint to compile... + let result: Option<(&usize, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&5, &("bar"))); + + let result: Option<(&usize, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&11, &("foo"))); + + let result: Option<(&usize, & &'static str)> = z.next(); + assert!(result.is_none()); +} + +#[test] +fn test_from_iter() { + let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set: BTreeSet<_> = xs.iter().cloned().collect(); + + for x in &xs { + assert!(set.contains(x)); + } +} + +#[test] +fn test_show() { + let mut set = BTreeSet::new(); + let empty = BTreeSet::::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{:?}", set); + + assert_eq!(set_str, "{1, 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} diff --git a/src/libcollectionstest/enum_set.rs b/src/libcollectionstest/enum_set.rs new file mode 100644 index 0000000000..0a1eb0bcfa --- /dev/null +++ b/src/libcollectionstest/enum_set.rs @@ -0,0 +1,244 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::mem; + +use collections::enum_set::{CLike, EnumSet}; + +use self::Foo::*; + +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(usize)] +enum Foo { + A, B, C +} + +impl CLike for Foo { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Foo { + unsafe { mem::transmute(v) } + } +} + +#[test] +fn test_new() { + let e: EnumSet = EnumSet::new(); + assert!(e.is_empty()); +} + +#[test] +fn test_show() { + let mut e = EnumSet::new(); + assert!(format!("{:?}", e) == "{}"); + e.insert(A); + assert!(format!("{:?}", e) == "{A}"); + e.insert(C); + assert!(format!("{:?}", e) == "{A, C}"); +} + +#[test] +fn test_len() { + let mut e = EnumSet::new(); + assert_eq!(e.len(), 0); + e.insert(A); + e.insert(B); + e.insert(C); + assert_eq!(e.len(), 3); + e.remove(&A); + assert_eq!(e.len(), 2); + e.clear(); + assert_eq!(e.len(), 0); +} + +/////////////////////////////////////////////////////////////////////////// +// intersect + +#[test] +fn test_two_empties_do_not_intersect() { + let e1: EnumSet = EnumSet::new(); + let e2: EnumSet = EnumSet::new(); + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_empty_does_not_intersect_with_full() { + let e1: EnumSet = EnumSet::new(); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(A); + e2.insert(B); + e2.insert(C); + + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_disjoint_intersects() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(B); + + assert!(e1.is_disjoint(&e2)); +} + +#[test] +fn test_overlapping_intersects() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(A); + e2.insert(B); + + assert!(!e1.is_disjoint(&e2)); +} + +/////////////////////////////////////////////////////////////////////////// +// contains and contains_elem + +#[test] +fn test_superset() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(A); + e2.insert(B); + + let mut e3: EnumSet = EnumSet::new(); + e3.insert(C); + + assert!(e1.is_subset(&e2)); + assert!(e2.is_superset(&e1)); + assert!(!e3.is_superset(&e2)); + assert!(!e2.is_superset(&e3)) +} + +#[test] +fn test_contains() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + assert!(e1.contains(&A)); + assert!(!e1.contains(&B)); + assert!(!e1.contains(&C)); + + e1.insert(A); + e1.insert(B); + assert!(e1.contains(&A)); + assert!(e1.contains(&B)); + assert!(!e1.contains(&C)); +} + +/////////////////////////////////////////////////////////////////////////// +// iter + +#[test] +fn test_iterator() { + let mut e1: EnumSet = EnumSet::new(); + + let elems: Vec = e1.iter().collect(); + assert!(elems.is_empty()); + + e1.insert(A); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!(elems, [A]); + + e1.insert(C); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!(elems, [A,C]); + + e1.insert(C); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!(elems, [A,C]); + + e1.insert(B); + let elems: Vec<_> = e1.iter().collect(); + assert_eq!(elems, [A,B,C]); +} + +/////////////////////////////////////////////////////////////////////////// +// operators + +#[test] +fn test_operators() { + let mut e1: EnumSet = EnumSet::new(); + e1.insert(A); + e1.insert(C); + + let mut e2: EnumSet = EnumSet::new(); + e2.insert(B); + e2.insert(C); + + let e_union = e1 | e2; + let elems: Vec<_> = e_union.iter().collect(); + assert_eq!(elems, [A,B,C]); + + let e_intersection = e1 & e2; + let elems: Vec<_> = e_intersection.iter().collect(); + assert_eq!(elems, [C]); + + // Another way to express intersection + let e_intersection = e1 - (e1 - e2); + let elems: Vec<_> = e_intersection.iter().collect(); + assert_eq!(elems, [C]); + + let e_subtract = e1 - e2; + let elems: Vec<_> = e_subtract.iter().collect(); + assert_eq!(elems, [A]); + + // Bitwise XOR of two sets, aka symmetric difference + let e_symmetric_diff = e1 ^ e2; + let elems: Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!(elems, [A,B]); + + // Another way to express symmetric difference + let e_symmetric_diff = (e1 - e2) | (e2 - e1); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!(elems, [A,B]); + + // Yet another way to express symmetric difference + let e_symmetric_diff = (e1 | e2) - (e1 & e2); + let elems: Vec<_> = e_symmetric_diff.iter().collect(); + assert_eq!(elems, [A,B]); +} + +#[test] +#[should_panic] +fn test_overflow() { + #[allow(dead_code)] + #[derive(Copy, Clone)] + #[repr(usize)] + enum Bar { + V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, + V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, + V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, + V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, + V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, + V50, V51, V52, V53, V54, V55, V56, V57, V58, V59, + V60, V61, V62, V63, V64, V65, V66, V67, V68, V69, + } + + impl CLike for Bar { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Bar { + unsafe { mem::transmute(v) } + } + } + let mut set = EnumSet::new(); + set.insert(Bar::V64); +} diff --git a/src/libcollectionstest/fmt.rs b/src/libcollectionstest/fmt.rs new file mode 100644 index 0000000000..70e21c65a1 --- /dev/null +++ b/src/libcollectionstest/fmt.rs @@ -0,0 +1,17 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt; + +#[test] +fn test_format() { + let s = fmt::format(format_args!("Hello, {}!", "world")); + assert_eq!(s, "Hello, world!"); +} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs new file mode 100644 index 0000000000..456c658a9c --- /dev/null +++ b/src/libcollectionstest/lib.rs @@ -0,0 +1,45 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![feature(collections)] +#![feature(core)] +#![feature(hash)] +#![feature(rand)] +#![feature(rustc_private)] +#![feature(str_words)] +#![feature(test)] +#![feature(unboxed_closures)] +#![feature(unicode)] +#![feature(unsafe_destructor)] +#![feature(into_cow)] +#![feature(step_by)] +#![cfg_attr(test, feature(str_char))] + +#[macro_use] extern crate log; + +extern crate collections; +extern crate test; +extern crate unicode; + +#[cfg(test)] #[macro_use] mod bench; + +mod binary_heap; +mod bit; +mod btree; +mod enum_set; +mod fmt; +mod linked_list; +mod slice; +mod str; +mod string; +mod vec_deque; +mod vec_map; +mod vec; diff --git a/src/libcollectionstest/linked_list.rs b/src/libcollectionstest/linked_list.rs new file mode 100644 index 0000000000..fd73938095 --- /dev/null +++ b/src/libcollectionstest/linked_list.rs @@ -0,0 +1,397 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::LinkedList; +use std::hash::{SipHasher, self}; + +use test; + +#[test] +fn test_basic() { + let mut m = LinkedList::>::new(); + assert_eq!(m.pop_front(), None); + assert_eq!(m.pop_back(), None); + assert_eq!(m.pop_front(), None); + m.push_front(box 1); + assert_eq!(m.pop_front(), Some(box 1)); + m.push_back(box 2); + m.push_back(box 3); + assert_eq!(m.len(), 2); + assert_eq!(m.pop_front(), Some(box 2)); + assert_eq!(m.pop_front(), Some(box 3)); + assert_eq!(m.len(), 0); + assert_eq!(m.pop_front(), None); + m.push_back(box 1); + m.push_back(box 3); + m.push_back(box 5); + m.push_back(box 7); + assert_eq!(m.pop_front(), Some(box 1)); + + let mut n = LinkedList::new(); + n.push_front(2); + n.push_front(3); + { + assert_eq!(n.front().unwrap(), &3); + let x = n.front_mut().unwrap(); + assert_eq!(*x, 3); + *x = 0; + } + { + assert_eq!(n.back().unwrap(), &2); + let y = n.back_mut().unwrap(); + assert_eq!(*y, 2); + *y = 1; + } + assert_eq!(n.pop_front(), Some(0)); + assert_eq!(n.pop_front(), Some(1)); +} + +#[cfg(test)] +fn generate_test() -> LinkedList { + list_from(&[0,1,2,3,4,5,6]) +} + +#[cfg(test)] +fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() +} + +#[test] +fn test_split_off() { + // singleton + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(0); + assert_eq!(m.len(), 0); + assert_eq!(p.len(), 1); + assert_eq!(p.back(), Some(&1)); + assert_eq!(p.front(), Some(&1)); + } + + // not singleton, forwards + { + let u = vec![1,2,3,4,5]; + let mut m = list_from(&u); + let mut n = m.split_off(2); + assert_eq!(m.len(), 2); + assert_eq!(n.len(), 3); + for elt in 1..3 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 3..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + // not singleton, backwards + { + let u = vec![1,2,3,4,5]; + let mut m = list_from(&u); + let mut n = m.split_off(4); + assert_eq!(m.len(), 4); + assert_eq!(n.len(), 1); + for elt in 1..5 { + assert_eq!(m.pop_front(), Some(elt)); + } + for elt in 5..6 { + assert_eq!(n.pop_front(), Some(elt)); + } + } + + // no-op on the last index + { + let mut m = LinkedList::new(); + m.push_back(1); + + let p = m.split_off(1); + assert_eq!(m.len(), 1); + assert_eq!(p.len(), 0); + assert_eq!(m.back(), Some(&1)); + assert_eq!(m.front(), Some(&1)); + } + +} + +#[test] +fn test_iterator() { + let m = generate_test(); + for (i, elt) in m.iter().enumerate() { + assert_eq!(i as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iterator_clone() { + let mut n = LinkedList::new(); + n.push_back(2); + n.push_back(3); + n.push_back(4); + let mut it = n.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next_back(), jt.next_back()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_iterator_double_end() { + let mut n = LinkedList::new(); + assert_eq!(n.iter().next(), None); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next_back().unwrap(), &5); + assert_eq!(it.next_back(), None); + assert_eq!(it.next(), None); +} + +#[test] +fn test_rev_iter() { + let m = generate_test(); + for (i, elt) in m.iter().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert_eq!(n.iter().rev().next(), None); + n.push_front(4); + let mut it = n.iter().rev(); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &4); + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); +} + +#[test] +fn test_mut_iter() { + let mut m = generate_test(); + let mut len = m.len(); + for (i, elt) in m.iter_mut().enumerate() { + assert_eq!(i as i32, *elt); + len -= 1; + } + assert_eq!(len, 0); + let mut n = LinkedList::new(); + assert!(n.iter_mut().next().is_none()); + n.push_front(4); + n.push_back(5); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next().is_some()); + assert!(it.next().is_some()); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_mut_double_end() { + let mut n = LinkedList::new(); + assert!(n.iter_mut().next_back().is_none()); + n.push_front(4); + n.push_front(5); + n.push_front(6); + let mut it = n.iter_mut(); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(*it.next().unwrap(), 6); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(*it.next_back().unwrap(), 4); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(*it.next_back().unwrap(), 5); + assert!(it.next_back().is_none()); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iter() { + let mut m = generate_test(); + for (i, elt) in m.iter_mut().rev().enumerate() { + assert_eq!((6 - i) as i32, *elt); + } + let mut n = LinkedList::new(); + assert!(n.iter_mut().rev().next().is_none()); + n.push_front(4); + let mut it = n.iter_mut().rev(); + assert!(it.next().is_some()); + assert!(it.next().is_none()); +} + +#[test] +fn test_eq() { + let mut n = list_from(&[]); + let mut m = list_from(&[]); + assert!(n == m); + n.push_front(1); + assert!(n != m); + m.push_back(1); + assert!(n == m); + + let n = list_from(&[2,3,4]); + let m = list_from(&[1,2,3]); + assert!(n != m); +} + +#[test] +fn test_hash() { + let mut x = LinkedList::new(); + let mut y = LinkedList::new(); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); + + x.push_back(1); + x.push_back(2); + x.push_back(3); + + y.push_front(3); + y.push_front(2); + y.push_front(1); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_ord() { + let n = list_from(&[]); + let m = list_from(&[1,2,3]); + assert!(n < m); + assert!(m > n); + assert!(n <= n); + assert!(n >= n); +} + +#[test] +fn test_ord_nan() { + let nan = 0.0f64/0.0; + let n = list_from(&[nan]); + let m = list_from(&[nan]); + assert!(!(n < m)); + assert!(!(n > m)); + assert!(!(n <= m)); + assert!(!(n >= m)); + + let n = list_from(&[nan]); + let one = list_from(&[1.0f64]); + assert!(!(n < one)); + assert!(!(n > one)); + assert!(!(n <= one)); + assert!(!(n >= one)); + + let u = list_from(&[1.0f64,2.0,nan]); + let v = list_from(&[1.0f64,2.0,3.0]); + assert!(!(u < v)); + assert!(!(u > v)); + assert!(!(u <= v)); + assert!(!(u >= v)); + + let s = list_from(&[1.0f64,2.0,4.0,2.0]); + let t = list_from(&[1.0f64,2.0,3.0,2.0]); + assert!(!(s < t)); + assert!(s > one); + assert!(!(s <= one)); + assert!(s >= one); +} + +#[test] +fn test_show() { + let list: LinkedList<_> = (0..10).collect(); + assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); + assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[bench] +fn bench_collect_into(b: &mut test::Bencher) { + let v = &[0; 64]; + b.iter(|| { + let _: LinkedList<_> = v.iter().cloned().collect(); + }) +} + +#[bench] +fn bench_push_front(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + }) +} + +#[bench] +fn bench_push_back(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + }) +} + +#[bench] +fn bench_push_back_pop_back(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_back(0); + m.pop_back(); + }) +} + +#[bench] +fn bench_push_front_pop_front(b: &mut test::Bencher) { + let mut m: LinkedList<_> = LinkedList::new(); + b.iter(|| { + m.push_front(0); + m.pop_front(); + }) +} + +#[bench] +fn bench_iter(b: &mut test::Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().count() == 128); + }) +} +#[bench] +fn bench_iter_mut(b: &mut test::Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().count() == 128); + }) +} +#[bench] +fn bench_iter_rev(b: &mut test::Bencher) { + let v = &[0; 128]; + let m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter().rev().count() == 128); + }) +} +#[bench] +fn bench_iter_mut_rev(b: &mut test::Bencher) { + let v = &[0; 128]; + let mut m: LinkedList<_> = v.iter().cloned().collect(); + b.iter(|| { + assert!(m.iter_mut().rev().count() == 128); + }) +} diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs new file mode 100644 index 0000000000..5b0aceb76d --- /dev/null +++ b/src/libcollectionstest/slice.rs @@ -0,0 +1,1572 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::default::Default; +use std::iter::RandomAccessIterator; +use std::mem; +use std::rand::{Rng, thread_rng}; +use std::rc::Rc; +use std::slice::ElementSwaps; + +fn square(n: usize) -> usize { n * n } + +fn is_odd(n: &usize) -> bool { *n % 2 == 1 } + +#[test] +fn test_from_fn() { + // Test on-stack from_fn. + let mut v: Vec<_> = (0..3).map(square).collect(); + { + let v = v; + assert_eq!(v.len(), 3); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 4); + } + + // Test on-heap from_fn. + v = (0..5).map(square).collect(); + { + let v = v; + assert_eq!(v.len(), 5); + assert_eq!(v[0], 0); + assert_eq!(v[1], 1); + assert_eq!(v[2], 4); + assert_eq!(v[3], 9); + assert_eq!(v[4], 16); + } +} + +#[test] +fn test_from_elem() { + // Test on-stack from_elem. + let mut v = vec![10, 10]; + { + let v = v; + assert_eq!(v.len(), 2); + assert_eq!(v[0], 10); + assert_eq!(v[1], 10); + } + + // Test on-heap from_elem. + v = vec![20; 6]; + { + let v = &v[..]; + assert_eq!(v[0], 20); + assert_eq!(v[1], 20); + assert_eq!(v[2], 20); + assert_eq!(v[3], 20); + assert_eq!(v[4], 20); + assert_eq!(v[5], 20); + } +} + +#[test] +fn test_is_empty() { + let xs: [i32; 0] = []; + assert!(xs.is_empty()); + assert!(![0].is_empty()); +} + +#[test] +fn test_len_divzero() { + type Z = [i8; 0]; + let v0 : &[Z] = &[]; + let v1 : &[Z] = &[[]]; + let v2 : &[Z] = &[[], []]; + assert_eq!(mem::size_of::(), 0); + assert_eq!(v0.len(), 0); + assert_eq!(v1.len(), 1); + assert_eq!(v2.len(), 2); +} + +#[test] +fn test_get() { + let mut a = vec![11]; + assert_eq!(a.get(1), None); + a = vec![11, 12]; + assert_eq!(a.get(1).unwrap(), &12); + a = vec![11, 12, 13]; + assert_eq!(a.get(1).unwrap(), &12); +} + +#[test] +fn test_first() { + let mut a = vec![]; + assert_eq!(a.first(), None); + a = vec![11]; + assert_eq!(a.first().unwrap(), &11); + a = vec![11, 12]; + assert_eq!(a.first().unwrap(), &11); +} + +#[test] +fn test_first_mut() { + let mut a = vec![]; + assert_eq!(a.first_mut(), None); + a = vec![11]; + assert_eq!(*a.first_mut().unwrap(), 11); + a = vec![11, 12]; + assert_eq!(*a.first_mut().unwrap(), 11); +} + +#[test] +fn test_tail() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert_eq!(a.tail(), b); + a = vec![11, 12]; + let b: &[i32] = &[12]; + assert_eq!(a.tail(), b); +} + +#[test] +fn test_tail_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(a.tail_mut() == b); + a = vec![11, 12]; + let b: &mut [_] = &mut [12]; + assert!(a.tail_mut() == b); +} + +#[test] +#[should_panic] +fn test_tail_empty() { + let a = Vec::::new(); + a.tail(); +} + +#[test] +#[should_panic] +fn test_tail_mut_empty() { + let mut a = Vec::::new(); + a.tail_mut(); +} + +#[test] +fn test_init() { + let mut a = vec![11]; + let b: &[i32] = &[]; + assert_eq!(a.init(), b); + a = vec![11, 12]; + let b: &[_] = &[11]; + assert_eq!(a.init(), b); +} + +#[test] +fn test_init_mut() { + let mut a = vec![11]; + let b: &mut [i32] = &mut []; + assert!(a.init_mut() == b); + a = vec![11, 12]; + let b: &mut [_] = &mut [11]; + assert!(a.init_mut() == b); +} + +#[test] +#[should_panic] +fn test_init_empty() { + let a = Vec::::new(); + a.init(); +} + +#[test] +#[should_panic] +fn test_init_mut_empty() { + let mut a = Vec::::new(); + a.init_mut(); +} + +#[test] +fn test_last() { + let mut a = vec![]; + assert_eq!(a.last(), None); + a = vec![11]; + assert_eq!(a.last().unwrap(), &11); + a = vec![11, 12]; + assert_eq!(a.last().unwrap(), &12); +} + +#[test] +fn test_last_mut() { + let mut a = vec![]; + assert_eq!(a.last_mut(), None); + a = vec![11]; + assert_eq!(*a.last_mut().unwrap(), 11); + a = vec![11, 12]; + assert_eq!(*a.last_mut().unwrap(), 12); +} + +#[test] +fn test_slice() { + // Test fixed length vector. + let vec_fixed = [1, 2, 3, 4]; + let v_a = vec_fixed[1..vec_fixed.len()].to_vec(); + assert_eq!(v_a.len(), 3); + + assert_eq!(v_a[0], 2); + assert_eq!(v_a[1], 3); + assert_eq!(v_a[2], 4); + + // Test on stack. + let vec_stack: &[_] = &[1, 2, 3]; + let v_b = vec_stack[1..3].to_vec(); + assert_eq!(v_b.len(), 2); + + assert_eq!(v_b[0], 2); + assert_eq!(v_b[1], 3); + + // Test `Box<[T]>` + let vec_unique = vec![1, 2, 3, 4, 5, 6]; + let v_d = vec_unique[1..6].to_vec(); + assert_eq!(v_d.len(), 5); + + assert_eq!(v_d[0], 2); + assert_eq!(v_d[1], 3); + assert_eq!(v_d[2], 4); + assert_eq!(v_d[3], 5); + assert_eq!(v_d[4], 6); +} + +#[test] +fn test_slice_from() { + let vec: &[_] = &[1, 2, 3, 4]; + assert_eq!(&vec[..], vec); + let b: &[_] = &[3, 4]; + assert_eq!(&vec[2..], b); + let b: &[_] = &[]; + assert_eq!(&vec[4..], b); +} + +#[test] +fn test_slice_to() { + let vec: &[_] = &[1, 2, 3, 4]; + assert_eq!(&vec[..4], vec); + let b: &[_] = &[1, 2]; + assert_eq!(&vec[..2], b); + let b: &[_] = &[]; + assert_eq!(&vec[..0], b); +} + + +#[test] +fn test_pop() { + let mut v = vec![5]; + let e = v.pop(); + assert_eq!(v.len(), 0); + assert_eq!(e, Some(5)); + let f = v.pop(); + assert_eq!(f, None); + let g = v.pop(); + assert_eq!(g, None); +} + +#[test] +fn test_swap_remove() { + let mut v = vec![1, 2, 3, 4, 5]; + let mut e = v.swap_remove(0); + assert_eq!(e, 1); + assert_eq!(v, [5, 2, 3, 4]); + e = v.swap_remove(3); + assert_eq!(e, 4); + assert_eq!(v, [5, 2, 3]); +} + +#[test] +#[should_panic] +fn test_swap_remove_fail() { + let mut v = vec![1]; + let _ = v.swap_remove(0); + let _ = v.swap_remove(0); +} + +#[test] +fn test_swap_remove_noncopyable() { + // Tests that we don't accidentally run destructors twice. + let mut v: Vec> = Vec::new(); + v.push(box 0u8); + v.push(box 0u8); + v.push(box 0u8); + let mut _e = v.swap_remove(0); + assert_eq!(v.len(), 2); + _e = v.swap_remove(1); + assert_eq!(v.len(), 1); + _e = v.swap_remove(0); + assert_eq!(v.len(), 0); +} + +#[test] +fn test_push() { + // Test on-stack push(). + let mut v = vec![]; + v.push(1); + assert_eq!(v.len(), 1); + assert_eq!(v[0], 1); + + // Test on-heap push(). + v.push(2); + assert_eq!(v.len(), 2); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); +} + +#[test] +fn test_truncate() { + let mut v: Vec> = vec![box 6,box 5,box 4]; + v.truncate(1); + let v = v; + assert_eq!(v.len(), 1); + assert_eq!(*(v[0]), 6); + // If the unsafe block didn't drop things properly, we blow up here. +} + +#[test] +fn test_clear() { + let mut v: Vec> = vec![box 6,box 5,box 4]; + v.clear(); + assert_eq!(v.len(), 0); + // If the unsafe block didn't drop things properly, we blow up here. +} + +#[test] +fn test_dedup() { + fn case(a: Vec, b: Vec) { + let mut v = a; + v.dedup(); + assert_eq!(v, b); + } + case(vec![], vec![]); + case(vec![1], vec![1]); + case(vec![1,1], vec![1]); + case(vec![1,2,3], vec![1,2,3]); + case(vec![1,1,2,3], vec![1,2,3]); + case(vec![1,2,2,3], vec![1,2,3]); + case(vec![1,2,3,3], vec![1,2,3]); + case(vec![1,1,2,2,2,3,3], vec![1,2,3]); +} + +#[test] +fn test_dedup_unique() { + let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; + v2.dedup(); + /* + * If the boxed pointers were leaked or otherwise misused, valgrind + * and/or rt should raise errors. + */ +} + +#[test] +fn test_dedup_shared() { + let mut v0: Vec> = vec![box 1, box 1, box 2, box 3]; + v0.dedup(); + let mut v1: Vec> = vec![box 1, box 2, box 2, box 3]; + v1.dedup(); + let mut v2: Vec> = vec![box 1, box 2, box 3, box 3]; + v2.dedup(); + /* + * If the pointers were leaked or otherwise misused, valgrind and/or + * rt should raise errors. + */ +} + +#[test] +fn test_retain() { + let mut v = vec![1, 2, 3, 4, 5]; + v.retain(is_odd); + assert_eq!(v, [1, 3, 5]); +} + +#[test] +fn test_element_swaps() { + let mut v = [1, 2, 3]; + for (i, (a, b)) in ElementSwaps::new(v.len()).enumerate() { + v.swap(a, b); + match i { + 0 => assert!(v == [1, 3, 2]), + 1 => assert!(v == [3, 1, 2]), + 2 => assert!(v == [3, 2, 1]), + 3 => assert!(v == [2, 3, 1]), + 4 => assert!(v == [2, 1, 3]), + 5 => assert!(v == [1, 2, 3]), + _ => panic!(), + } + } +} + +#[test] +fn test_lexicographic_permutations() { + let v : &mut[_] = &mut[1, 2, 3, 4, 5]; + assert!(v.prev_permutation() == false); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 3, 5, 4]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[1, 2, 3, 4, 5]; + assert!(v == b); + assert!(v.next_permutation()); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 4, 3, 5]; + assert!(v == b); + assert!(v.next_permutation()); + let b: &mut[_] = &mut[1, 2, 4, 5, 3]; + assert!(v == b); + + let v : &mut[_] = &mut[1, 0, 0, 0]; + assert!(v.next_permutation() == false); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 1, 0, 0]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 0, 1, 0]; + assert!(v == b); + assert!(v.prev_permutation()); + let b: &mut[_] = &mut[0, 0, 0, 1]; + assert!(v == b); + assert!(v.prev_permutation() == false); +} + +#[test] +fn test_lexicographic_permutations_empty_and_short() { + let empty : &mut[i32] = &mut[]; + assert!(empty.next_permutation() == false); + let b: &mut[i32] = &mut[]; + assert!(empty == b); + assert!(empty.prev_permutation() == false); + assert!(empty == b); + + let one_elem : &mut[_] = &mut[4]; + assert!(one_elem.prev_permutation() == false); + let b: &mut[_] = &mut[4]; + assert!(one_elem == b); + assert!(one_elem.next_permutation() == false); + assert!(one_elem == b); + + let two_elem : &mut[_] = &mut[1, 2]; + assert!(two_elem.prev_permutation() == false); + let b : &mut[_] = &mut[1, 2]; + let c : &mut[_] = &mut[2, 1]; + assert!(two_elem == b); + assert!(two_elem.next_permutation()); + assert!(two_elem == c); + assert!(two_elem.next_permutation() == false); + assert!(two_elem == c); + assert!(two_elem.prev_permutation()); + assert!(two_elem == b); + assert!(two_elem.prev_permutation() == false); + assert!(two_elem == b); +} + +#[test] +fn test_position_elem() { + assert!([].position_elem(&1).is_none()); + + let v1 = vec![1, 2, 3, 3, 2, 5]; + assert_eq!(v1.position_elem(&1), Some(0)); + assert_eq!(v1.position_elem(&2), Some(1)); + assert_eq!(v1.position_elem(&5), Some(5)); + assert!(v1.position_elem(&4).is_none()); +} + +#[test] +fn test_binary_search() { + assert_eq!([1,2,3,4,5].binary_search(&5).ok(), Some(4)); + assert_eq!([1,2,3,4,5].binary_search(&4).ok(), Some(3)); + assert_eq!([1,2,3,4,5].binary_search(&3).ok(), Some(2)); + assert_eq!([1,2,3,4,5].binary_search(&2).ok(), Some(1)); + assert_eq!([1,2,3,4,5].binary_search(&1).ok(), Some(0)); + + assert_eq!([2,4,6,8,10].binary_search(&1).ok(), None); + assert_eq!([2,4,6,8,10].binary_search(&5).ok(), None); + assert_eq!([2,4,6,8,10].binary_search(&4).ok(), Some(1)); + assert_eq!([2,4,6,8,10].binary_search(&10).ok(), Some(4)); + + assert_eq!([2,4,6,8].binary_search(&1).ok(), None); + assert_eq!([2,4,6,8].binary_search(&5).ok(), None); + assert_eq!([2,4,6,8].binary_search(&4).ok(), Some(1)); + assert_eq!([2,4,6,8].binary_search(&8).ok(), Some(3)); + + assert_eq!([2,4,6].binary_search(&1).ok(), None); + assert_eq!([2,4,6].binary_search(&5).ok(), None); + assert_eq!([2,4,6].binary_search(&4).ok(), Some(1)); + assert_eq!([2,4,6].binary_search(&6).ok(), Some(2)); + + assert_eq!([2,4].binary_search(&1).ok(), None); + assert_eq!([2,4].binary_search(&5).ok(), None); + assert_eq!([2,4].binary_search(&2).ok(), Some(0)); + assert_eq!([2,4].binary_search(&4).ok(), Some(1)); + + assert_eq!([2].binary_search(&1).ok(), None); + assert_eq!([2].binary_search(&5).ok(), None); + assert_eq!([2].binary_search(&2).ok(), Some(0)); + + assert_eq!([].binary_search(&1).ok(), None); + assert_eq!([].binary_search(&5).ok(), None); + + assert!([1,1,1,1,1].binary_search(&1).ok() != None); + assert!([1,1,1,1,2].binary_search(&1).ok() != None); + assert!([1,1,1,2,2].binary_search(&1).ok() != None); + assert!([1,1,2,2,2].binary_search(&1).ok() != None); + assert_eq!([1,2,2,2,2].binary_search(&1).ok(), Some(0)); + + assert_eq!([1,2,3,4,5].binary_search(&6).ok(), None); + assert_eq!([1,2,3,4,5].binary_search(&0).ok(), None); +} + +#[test] +fn test_reverse() { + let mut v = vec![10, 20]; + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); + v.reverse(); + assert_eq!(v[0], 20); + assert_eq!(v[1], 10); + + let mut v3 = Vec::::new(); + v3.reverse(); + assert!(v3.is_empty()); +} + +#[test] +fn test_sort() { + for len in 4..25 { + for _ in 0..100 { + let mut v: Vec<_> = thread_rng().gen_iter::().take(len).collect(); + let mut v1 = v.clone(); + + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + v1.sort_by(|a, b| a.cmp(b)); + assert!(v1.windows(2).all(|w| w[0] <= w[1])); + + v1.sort_by(|a, b| b.cmp(a)); + assert!(v1.windows(2).all(|w| w[0] >= w[1])); + } + } + + // shouldn't panic + let mut v: [i32; 0] = []; + v.sort(); + + let mut v = [0xDEADBEEFu64]; + v.sort(); + assert!(v == [0xDEADBEEF]); +} + +#[test] +fn test_sort_stability() { + for len in 4..25 { + for _ in 0..10 { + let mut counts = [0; 10]; + + // create a vector like [(6, 1), (5, 1), (6, 2), ...], + // where the first item of each tuple is random, but + // the second item represents which occurrence of that + // number this element is, i.e. the second elements + // will occur in sorted order. + let mut v: Vec<_> = (0..len).map(|_| { + let n = thread_rng().gen::() % 10; + counts[n] += 1; + (n, counts[n]) + }).collect(); + + // only sort on the first element, so an unstable sort + // may mix up the counts. + v.sort_by(|&(a,_), &(b,_)| a.cmp(&b)); + + // this comparison includes the count (the second item + // of the tuple), so elements with equal first items + // will need to be ordered with increasing + // counts... i.e. exactly asserting that this sort is + // stable. + assert!(v.windows(2).all(|w| w[0] <= w[1])); + } + } +} + +#[test] +fn test_concat() { + let v: [Vec; 0] = []; + let c = v.concat(); + assert_eq!(c, []); + let d = [vec![1], vec![2, 3]].concat(); + assert_eq!(d, [1, 2, 3]); + + let v: &[&[_]] = &[&[1], &[2, 3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 3]); + let v: &[&[_]] = &[&[1], &[2], &[3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_connect() { + let v: [Vec; 0] = []; + assert_eq!(v.connect(&0), []); + assert_eq!([vec![1], vec![2, 3]].connect(&0), [1, 0, 2, 3]); + assert_eq!([vec![1], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]); + + let v: [&[_]; 2] = [&[1], &[2, 3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 3]); + let v: [&[_]; 3] = [&[1], &[2], &[3]]; + assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]); +} + +#[test] +fn test_insert() { + let mut a = vec![1, 2, 4]; + a.insert(2, 3); + assert_eq!(a, [1, 2, 3, 4]); + + let mut a = vec![1, 2, 3]; + a.insert(0, 0); + assert_eq!(a, [0, 1, 2, 3]); + + let mut a = vec![1, 2, 3]; + a.insert(3, 4); + assert_eq!(a, [1, 2, 3, 4]); + + let mut a = vec![]; + a.insert(0, 1); + assert_eq!(a, [1]); +} + +#[test] +#[should_panic] +fn test_insert_oob() { + let mut a = vec![1, 2, 3]; + a.insert(4, 5); +} + +#[test] +fn test_remove() { + let mut a = vec![1, 2, 3, 4]; + + assert_eq!(a.remove(2), 3); + assert_eq!(a, [1, 2, 4]); + + assert_eq!(a.remove(2), 4); + assert_eq!(a, [1, 2]); + + assert_eq!(a.remove(0), 1); + assert_eq!(a, [2]); + + assert_eq!(a.remove(0), 2); + assert_eq!(a, []); +} + +#[test] +#[should_panic] +fn test_remove_fail() { + let mut a = vec![1]; + let _ = a.remove(0); + let _ = a.remove(0); +} + +#[test] +fn test_capacity() { + let mut v = vec![0]; + v.reserve_exact(10); + assert!(v.capacity() >= 11); +} + +#[test] +fn test_slice_2() { + let v = vec![1, 2, 3, 4, 5]; + let v = &v[1..3]; + assert_eq!(v.len(), 2); + assert_eq!(v[0], 2); + assert_eq!(v[1], 3); +} + +#[test] +#[should_panic] +fn test_permute_fail() { + let v: [(Box<_>, Rc<_>); 4] = + [(box 0, Rc::new(0)), (box 0, Rc::new(0)), + (box 0, Rc::new(0)), (box 0, Rc::new(0))]; + let mut i = 0; + for _ in v.permutations() { + if i == 2 { + panic!() + } + i += 1; + } +} + +#[test] +fn test_total_ord() { + let c = &[1, 2, 3]; + [1, 2, 3, 4][..].cmp(c) == Greater; + let c = &[1, 2, 3, 4]; + [1, 2, 3][..].cmp(c) == Less; + let c = &[1, 2, 3, 6]; + [1, 2, 3, 4][..].cmp(c) == Equal; + let c = &[1, 2, 3, 4, 5, 6]; + [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; + let c = &[1, 2, 3, 4]; + [2, 2][..].cmp(c) == Greater; +} + +#[test] +fn test_iterator() { + let xs = [1, 2, 5, 10, 11]; + let mut it = xs.iter(); + assert_eq!(it.size_hint(), (5, Some(5))); + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.size_hint(), (4, Some(4))); + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.size_hint(), (3, Some(3))); + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.size_hint(), (2, Some(2))); + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.size_hint(), (1, Some(1))); + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_random_access_iterator() { + let xs = [1, 2, 5, 10, 11]; + let mut it = xs.iter(); + + assert_eq!(it.indexable(), 5); + assert_eq!(it.idx(0).unwrap(), &1); + assert_eq!(it.idx(2).unwrap(), &5); + assert_eq!(it.idx(4).unwrap(), &11); + assert!(it.idx(5).is_none()); + + assert_eq!(it.next().unwrap(), &1); + assert_eq!(it.indexable(), 4); + assert_eq!(it.idx(0).unwrap(), &2); + assert_eq!(it.idx(3).unwrap(), &11); + assert!(it.idx(4).is_none()); + + assert_eq!(it.next().unwrap(), &2); + assert_eq!(it.indexable(), 3); + assert_eq!(it.idx(1).unwrap(), &10); + assert!(it.idx(3).is_none()); + + assert_eq!(it.next().unwrap(), &5); + assert_eq!(it.indexable(), 2); + assert_eq!(it.idx(1).unwrap(), &11); + + assert_eq!(it.next().unwrap(), &10); + assert_eq!(it.indexable(), 1); + assert_eq!(it.idx(0).unwrap(), &11); + assert!(it.idx(1).is_none()); + + assert_eq!(it.next().unwrap(), &11); + assert_eq!(it.indexable(), 0); + assert!(it.idx(0).is_none()); + + assert!(it.next().is_none()); +} + +#[test] +fn test_iter_size_hints() { + let mut xs = [1, 2, 5, 10, 11]; + assert_eq!(xs.iter().size_hint(), (5, Some(5))); + assert_eq!(xs.iter_mut().size_hint(), (5, Some(5))); +} + +#[test] +fn test_iter_clone() { + let xs = [1, 2, 5]; + let mut it = xs.iter(); + it.next(); + let mut jt = it.clone(); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); + assert_eq!(it.next(), jt.next()); +} + +#[test] +fn test_mut_iterator() { + let mut xs = [1, 2, 3, 4, 5]; + for x in &mut xs { + *x += 1; + } + assert!(xs == [2, 3, 4, 5, 6]) +} + +#[test] +fn test_rev_iterator() { + + let xs = [1, 2, 5, 10, 11]; + let ys = [11, 10, 5, 2, 1]; + let mut i = 0; + for &x in xs.iter().rev() { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, 5); +} + +#[test] +fn test_mut_rev_iterator() { + let mut xs = [1, 2, 3, 4, 5]; + for (i,x) in xs.iter_mut().rev().enumerate() { + *x += i; + } + assert!(xs == [5, 5, 5, 5, 5]) +} + +#[test] +fn test_move_iterator() { + let xs = vec![1,2,3,4,5]; + assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10*a + b), 12345); +} + +#[test] +fn test_move_rev_iterator() { + let xs = vec![1,2,3,4,5]; + assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10*a + b), 54321); +} + +#[test] +fn test_splitator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1], &[3], &[5]]; + assert_eq!(xs.split(|x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 1).collect::>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4], &[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 10).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; + assert_eq!(xs.split(|_| true).collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitnator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[1], &[3,4,5]]; + assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[4,5]]; + assert_eq!(xs.splitn(4, |_| true).collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.splitn(2, |x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitnator_mut() { + let xs = &mut [1,2,3,4,5]; + + let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]]; + assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]]; + assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]]; + assert_eq!(xs.splitn_mut(4, |_| true).collect::>(), + splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&mut[i32]] = &[&mut []]; + assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::>(), + splits); +} + +#[test] +fn test_rsplitator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[5], &[3], &[1]]; + assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::>(), + splits); + let splits: &[&[_]] = &[&[2,3,4,5], &[]]; + assert_eq!(xs.split(|x| *x == 1).rev().collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[1,2,3,4]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), + splits); + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.split(|x| *x == 10).rev().collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split(|x| *x == 5).rev().collect::>(), splits); +} + +#[test] +fn test_rsplitnator() { + let xs = &[1,2,3,4,5]; + + let splits: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[5], &[1,2,3]]; + assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::>(), + splits); + let splits: &[&[_]] = &[&[], &[], &[], &[1,2]]; + assert_eq!(xs.rsplitn(4, |_| true).collect::>(), + splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::>(), splits); + assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none()); +} + +#[test] +fn test_windowsator() { + let v = &[1,2,3,4]; + + let wins: &[&[_]] = &[&[1,2], &[2,3], &[3,4]]; + assert_eq!(v.windows(2).collect::>(), wins); + + let wins: &[&[_]] = &[&[1,2,3], &[2,3,4]]; + assert_eq!(v.windows(3).collect::>(), wins); + assert!(v.windows(6).next().is_none()); + + let wins: &[&[_]] = &[&[3,4], &[2,3], &[1,2]]; + assert_eq!(v.windows(2).rev().collect::>(), wins); + let mut it = v.windows(2); + assert_eq!(it.indexable(), 3); + let win: &[_] = &[1,2]; + assert_eq!(it.idx(0).unwrap(), win); + let win: &[_] = &[2,3]; + assert_eq!(it.idx(1).unwrap(), win); + let win: &[_] = &[3,4]; + assert_eq!(it.idx(2).unwrap(), win); + assert_eq!(it.idx(3), None); +} + +#[test] +#[should_panic] +fn test_windowsator_0() { + let v = &[1,2,3,4]; + let _it = v.windows(0); +} + +#[test] +fn test_chunksator() { + let v = &[1,2,3,4,5]; + + assert_eq!(v.chunks(2).len(), 3); + + let chunks: &[&[_]] = &[&[1,2], &[3,4], &[5]]; + assert_eq!(v.chunks(2).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1,2,3], &[4,5]]; + assert_eq!(v.chunks(3).collect::>(), chunks); + let chunks: &[&[_]] = &[&[1,2,3,4,5]]; + assert_eq!(v.chunks(6).collect::>(), chunks); + + let chunks: &[&[_]] = &[&[5], &[3,4], &[1,2]]; + assert_eq!(v.chunks(2).rev().collect::>(), chunks); + let mut it = v.chunks(2); + assert_eq!(it.indexable(), 3); + + let chunk: &[_] = &[1,2]; + assert_eq!(it.idx(0).unwrap(), chunk); + let chunk: &[_] = &[3,4]; + assert_eq!(it.idx(1).unwrap(), chunk); + let chunk: &[_] = &[5]; + assert_eq!(it.idx(2).unwrap(), chunk); + assert_eq!(it.idx(3), None); +} + +#[test] +#[should_panic] +fn test_chunksator_0() { + let v = &[1,2,3,4]; + let _it = v.chunks(0); +} + +#[test] +fn test_move_from() { + let mut a = [1,2,3,4,5]; + let b = vec![6,7,8]; + assert_eq!(a.move_from(b, 0, 3), 3); + assert!(a == [6,7,8,4,5]); + let mut a = [7,2,8,1]; + let b = vec![3,1,4,1,5,9]; + assert_eq!(a.move_from(b, 0, 6), 4); + assert!(a == [3,1,4,1]); + let mut a = [1,2,3,4]; + let b = vec![5,6,7,8,9,0]; + assert_eq!(a.move_from(b, 2, 3), 1); + assert!(a == [7,2,3,4]); + let mut a = [1,2,3,4,5]; + let b = vec![5,6,7,8,9,0]; + assert_eq!(a[2..4].move_from(b,1,6), 2); + assert!(a == [1,2,6,7,5]); +} + +#[test] +fn test_reverse_part() { + let mut values = [1,2,3,4,5]; + values[1..4].reverse(); + assert!(values == [1,4,3,2,5]); +} + +#[test] +fn test_show() { + macro_rules! test_show_vec { + ($x:expr, $x_str:expr) => ({ + let (x, x_str) = ($x, $x_str); + assert_eq!(format!("{:?}", x), x_str); + assert_eq!(format!("{:?}", x), x_str); + }) + } + let empty = Vec::::new(); + test_show_vec!(empty, "[]"); + test_show_vec!(vec![1], "[1]"); + test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); + test_show_vec!(vec![vec![], vec![1], vec![1, 1]], + "[[], [1], [1, 1]]"); + + let empty_mut: &mut [i32] = &mut[]; + test_show_vec!(empty_mut, "[]"); + let v = &mut[1]; + test_show_vec!(v, "[1]"); + let v = &mut[1, 2, 3]; + test_show_vec!(v, "[1, 2, 3]"); + let v: &mut[&mut[_]] = &mut[&mut[], &mut[1], &mut[1, 1]]; + test_show_vec!(v, "[[], [1], [1, 1]]"); +} + +#[test] +fn test_vec_default() { + macro_rules! t { + ($ty:ty) => {{ + let v: $ty = Default::default(); + assert!(v.is_empty()); + }} + } + + t!(&[i32]); + t!(Vec); +} + +#[test] +fn test_bytes_set_memory() { + use std::slice::bytes::MutableByteVector; + + let mut values = [1,2,3,4,5]; + values[0..5].set_memory(0xAB); + assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); + values[2..4].set_memory(0xFF); + assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault() { + let mut v = vec![]; + v.reserve_exact(!0); + v.push(1); + v.push(2); +} + +#[test] +#[should_panic] +fn test_overflow_does_not_cause_segfault_managed() { + let mut v = vec![Rc::new(1)]; + v.reserve_exact(!0); + v.push(Rc::new(2)); +} + +#[test] +fn test_mut_split_at() { + let mut values = [1u8,2,3,4,5]; + { + let (left, right) = values.split_at_mut(2); + { + let left: &[_] = left; + assert!(left[..left.len()] == [1, 2]); + } + for p in left { + *p += 1; + } + + { + let right: &[_] = right; + assert!(right[..right.len()] == [3, 4, 5]); + } + for p in right { + *p += 2; + } + } + + assert!(values == [2, 3, 5, 6, 7]); +} + +#[derive(Clone, PartialEq)] +struct Foo; + +#[test] +fn test_iter_zero_sized() { + let mut v = vec![Foo, Foo, Foo]; + assert_eq!(v.len(), 3); + let mut cnt = 0; + + for f in &v { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 3); + + for f in &v[1..3] { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 5); + + for f in &mut v { + assert!(*f == Foo); + cnt += 1; + } + assert_eq!(cnt, 8); + + for f in v { + assert!(f == Foo); + cnt += 1; + } + assert_eq!(cnt, 11); + + let xs: [Foo; 3] = [Foo, Foo, Foo]; + cnt = 0; + for f in &xs { + assert!(*f == Foo); + cnt += 1; + } + assert!(cnt == 3); +} + +#[test] +fn test_shrink_to_fit() { + let mut xs = vec![0, 1, 2, 3]; + for i in 4..100 { + xs.push(i) + } + assert_eq!(xs.capacity(), 128); + xs.shrink_to_fit(); + assert_eq!(xs.capacity(), 100); + assert_eq!(xs, (0..100).collect::>()); +} + +#[test] +fn test_starts_with() { + assert!(b"foobar".starts_with(b"foo")); + assert!(!b"foobar".starts_with(b"oob")); + assert!(!b"foobar".starts_with(b"bar")); + assert!(!b"foo".starts_with(b"foobar")); + assert!(!b"bar".starts_with(b"foobar")); + assert!(b"foobar".starts_with(b"foobar")); + let empty: &[u8] = &[]; + assert!(empty.starts_with(empty)); + assert!(!empty.starts_with(b"foo")); + assert!(b"foobar".starts_with(empty)); +} + +#[test] +fn test_ends_with() { + assert!(b"foobar".ends_with(b"bar")); + assert!(!b"foobar".ends_with(b"oba")); + assert!(!b"foobar".ends_with(b"foo")); + assert!(!b"foo".ends_with(b"foobar")); + assert!(!b"bar".ends_with(b"foobar")); + assert!(b"foobar".ends_with(b"foobar")); + let empty: &[u8] = &[]; + assert!(empty.ends_with(empty)); + assert!(!empty.ends_with(b"foo")); + assert!(b"foobar".ends_with(empty)); +} + +#[test] +fn test_mut_splitator() { + let mut xs = [0,1,0,2,3,0,0,4,5,0]; + assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); + for slice in xs.split_mut(|x| *x == 0) { + slice.reverse(); + } + assert!(xs == [0,1,0,3,2,0,0,5,4,0]); + + let mut xs = [0,1,0,2,3,0,0,4,5,0,6,7]; + for slice in xs.split_mut(|x| *x == 0).take(5) { + slice.reverse(); + } + assert!(xs == [0,1,0,3,2,0,0,5,4,0,6,7]); +} + +#[test] +fn test_mut_splitator_rev() { + let mut xs = [1,2,0,3,4,0,0,5,6,0]; + for slice in xs.split_mut(|x| *x == 0).rev().take(4) { + slice.reverse(); + } + assert!(xs == [1,2,0,4,3,0,0,6,5,0]); +} + +#[test] +fn test_get_mut() { + let mut v = [0,1,2]; + assert_eq!(v.get_mut(3), None); + v.get_mut(1).map(|e| *e = 7); + assert_eq!(v[1], 7); + let mut x = 2; + assert_eq!(v.get_mut(2), Some(&mut x)); +} + +#[test] +fn test_mut_chunks() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(v.chunks_mut(2).len(), 4); + for (i, chunk) in v.chunks_mut(3).enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [0, 0, 0, 1, 1, 1, 2]; + assert!(v == result); +} + +#[test] +fn test_mut_chunks_rev() { + let mut v = [0, 1, 2, 3, 4, 5, 6]; + for (i, chunk) in v.chunks_mut(3).rev().enumerate() { + for x in chunk { + *x = i as u8; + } + } + let result = [2, 2, 2, 1, 1, 1, 0]; + assert!(v == result); +} + +#[test] +#[should_panic] +fn test_mut_chunks_0() { + let mut v = [1, 2, 3, 4]; + let _it = v.chunks_mut(0); +} + +#[test] +fn test_mut_last() { + let mut x = [1, 2, 3, 4, 5]; + let h = x.last_mut(); + assert_eq!(*h.unwrap(), 5); + + let y: &mut [i32] = &mut []; + assert!(y.last_mut().is_none()); +} + +#[test] +fn test_to_vec() { + let xs: Box<_> = box [1, 2, 3]; + let ys = xs.to_vec(); + assert_eq!(ys, [1, 2, 3]); +} + +mod bench { + use std::iter::repeat; + use std::{mem, ptr}; + use std::rand::{Rng, weak_rng}; + + use test::{Bencher, black_box}; + + #[bench] + fn iterator(b: &mut Bencher) { + // peculiar numbers to stop LLVM from optimising the summation + // out. + let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); + + b.iter(|| { + let mut sum = 0; + for x in &v { + sum += *x; + } + // sum == 11806, to stop dead code elimination. + if sum == 0 {panic!()} + }) + } + + #[bench] + fn mut_iterator(b: &mut Bencher) { + let mut v: Vec<_> = repeat(0).take(100).collect(); + + b.iter(|| { + let mut i = 0; + for x in &mut v { + *x = i; + i += 1; + } + }) + } + + #[bench] + fn concat(b: &mut Bencher) { + let xss: Vec> = + (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.concat(); + }); + } + + #[bench] + fn connect(b: &mut Bencher) { + let xss: Vec> = + (0..100).map(|i| (0..i).collect()).collect(); + b.iter(|| { + xss.connect(&0) + }); + } + + #[bench] + fn push(b: &mut Bencher) { + let mut vec = Vec::::new(); + b.iter(|| { + vec.push(0); + black_box(&vec); + }); + } + + #[bench] + fn starts_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.starts_with(&vec) + }) + } + + #[bench] + fn starts_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| { + vec.starts_with(&vec) + }) + } + + #[bench] + fn starts_with_diff_one_element_at_end(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..99).collect(); + match_vec.push(0); + b.iter(|| { + vec.starts_with(&match_vec) + }) + } + + #[bench] + fn ends_with_same_vector(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.ends_with(&vec) + }) + } + + #[bench] + fn ends_with_single_element(b: &mut Bencher) { + let vec: Vec<_> = vec![0]; + b.iter(|| { + vec.ends_with(&vec) + }) + } + + #[bench] + fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + let mut match_vec: Vec<_> = (0..100).collect(); + match_vec[0] = 200; + b.iter(|| { + vec.starts_with(&match_vec) + }) + } + + #[bench] + fn contains_last_element(b: &mut Bencher) { + let vec: Vec<_> = (0..100).collect(); + b.iter(|| { + vec.contains(&99) + }) + } + + #[bench] + fn zero_1kb_from_elem(b: &mut Bencher) { + b.iter(|| { + repeat(0u8).take(1024).collect::>() + }); + } + + #[bench] + fn zero_1kb_set_memory(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + let vp = v.as_mut_ptr(); + ptr::write_bytes(vp, 0, 1024); + v.set_len(1024); + } + v + }); + } + + #[bench] + fn zero_1kb_loop_set(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for i in 0..1024 { + v[i] = 0; + } + }); + } + + #[bench] + fn zero_1kb_mut_iter(b: &mut Bencher) { + b.iter(|| { + let mut v = Vec::::with_capacity(1024); + unsafe { + v.set_len(1024); + } + for x in &mut v { + *x = 0; + } + v + }); + } + + #[bench] + fn random_inserts(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = repeat((0, 0)).take(30).collect(); + for _ in 0..100 { + let l = v.len(); + v.insert(rng.gen::() % (l + 1), + (1, 1)); + } + }) + } + #[bench] + fn random_removes(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = repeat((0, 0)).take(130).collect(); + for _ in 0..100 { + let l = v.len(); + v.remove(rng.gen::() % l); + } + }) + } + + #[bench] + fn sort_random_small(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::().take(5).collect(); + v.sort(); + }); + b.bytes = 5 * mem::size_of::() as u64; + } + + #[bench] + fn sort_random_medium(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::().take(100).collect(); + v.sort(); + }); + b.bytes = 100 * mem::size_of::() as u64; + } + + #[bench] + fn sort_random_large(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v: Vec<_> = rng.gen_iter::().take(10000).collect(); + v.sort(); + }); + b.bytes = 10000 * mem::size_of::() as u64; + } + + #[bench] + fn sort_sorted(b: &mut Bencher) { + let mut v: Vec<_> = (0..10000).collect(); + b.iter(|| { + v.sort(); + }); + b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; + } + + type BigSortable = (u64, u64, u64, u64); + + #[bench] + fn sort_big_random_small(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::().take(5) + .collect::>(); + v.sort(); + }); + b.bytes = 5 * mem::size_of::() as u64; + } + + #[bench] + fn sort_big_random_medium(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::().take(100) + .collect::>(); + v.sort(); + }); + b.bytes = 100 * mem::size_of::() as u64; + } + + #[bench] + fn sort_big_random_large(b: &mut Bencher) { + let mut rng = weak_rng(); + b.iter(|| { + let mut v = rng.gen_iter::().take(10000) + .collect::>(); + v.sort(); + }); + b.bytes = 10000 * mem::size_of::() as u64; + } + + #[bench] + fn sort_big_sorted(b: &mut Bencher) { + let mut v: Vec = (0..10000).map(|i| (i, i, i, i)).collect(); + b.iter(|| { + v.sort(); + }); + b.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; + } +} diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs new file mode 100644 index 0000000000..495a961fa3 --- /dev/null +++ b/src/libcollectionstest/str.rs @@ -0,0 +1,1696 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering::{Equal, Greater, Less}; +use std::iter::AdditiveIterator; +use std::str::{Utf8Error, from_utf8}; + +#[test] +fn test_le() { + assert!("" <= ""); + assert!("" <= "foo"); + assert!("foo" <= "foo"); + assert!("foo" != "bar"); +} + +#[test] +fn test_len() { + assert_eq!("".len(), 0); + assert_eq!("hello world".len(), 11); + assert_eq!("\x63".len(), 1); + assert_eq!("\u{a2}".len(), 2); + assert_eq!("\u{3c0}".len(), 2); + assert_eq!("\u{2620}".len(), 3); + assert_eq!("\u{1d11e}".len(), 4); + + assert_eq!("".chars().count(), 0); + assert_eq!("hello world".chars().count(), 11); + assert_eq!("\x63".chars().count(), 1); + assert_eq!("\u{a2}".chars().count(), 1); + assert_eq!("\u{3c0}".chars().count(), 1); + assert_eq!("\u{2620}".chars().count(), 1); + assert_eq!("\u{1d11e}".chars().count(), 1); + assert_eq!("ประเทศไทย中华Việt Nam".chars().count(), 19); + + assert_eq!("hello".width(false), 10); + assert_eq!("hello".width(true), 10); + assert_eq!("\0\0\0\0\0".width(false), 0); + assert_eq!("\0\0\0\0\0".width(true), 0); + assert_eq!("".width(false), 0); + assert_eq!("".width(true), 0); + assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(false), 4); + assert_eq!("\u{2081}\u{2082}\u{2083}\u{2084}".width(true), 8); +} + +#[test] +fn test_find() { + assert_eq!("hello".find('l'), Some(2)); + assert_eq!("hello".find(|c:char| c == 'o'), Some(4)); + assert!("hello".find('x').is_none()); + assert!("hello".find(|c:char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); + assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); +} + +#[test] +fn test_rfind() { + assert_eq!("hello".rfind('l'), Some(3)); + assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4)); + assert!("hello".rfind('x').is_none()); + assert!("hello".rfind(|c:char| c == 'x').is_none()); + assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); + assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); +} + +#[test] +fn test_collect() { + let empty = String::from_str(""); + let s: String = empty.chars().collect(); + assert_eq!(empty, s); + let data = String::from_str("ประเทศไทย中"); + let s: String = data.chars().collect(); + assert_eq!(data, s); +} + +#[test] +fn test_into_bytes() { + let data = String::from_str("asdf"); + let buf = data.into_bytes(); + assert_eq!(buf, b"asdf"); +} + +#[test] +fn test_find_str() { + // byte positions + assert_eq!("".find(""), Some(0)); + assert!("banana".find("apple pie").is_none()); + + let data = "abcabc"; + assert_eq!(data[0..6].find("ab"), Some(0)); + assert_eq!(data[2..6].find("ab"), Some(3 - 2)); + assert!(data[2..4].find("ab").is_none()); + + let string = "ประเทศไทย中华Việt Nam"; + let mut data = String::from_str(string); + data.push_str(string); + assert!(data.find("ไท华").is_none()); + assert_eq!(data[0..43].find(""), Some(0)); + assert_eq!(data[6..43].find(""), Some(6 - 6)); + + assert_eq!(data[0..43].find("ประ"), Some( 0)); + assert_eq!(data[0..43].find("ทศไ"), Some(12)); + assert_eq!(data[0..43].find("ย中"), Some(24)); + assert_eq!(data[0..43].find("iệt"), Some(34)); + assert_eq!(data[0..43].find("Nam"), Some(40)); + + assert_eq!(data[43..86].find("ประ"), Some(43 - 43)); + assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43)); + assert_eq!(data[43..86].find("ย中"), Some(67 - 43)); + assert_eq!(data[43..86].find("iệt"), Some(77 - 43)); + assert_eq!(data[43..86].find("Nam"), Some(83 - 43)); +} + +#[test] +fn test_slice_chars() { + fn t(a: &str, b: &str, start: usize) { + assert_eq!(a.slice_chars(start, start + b.chars().count()), b); + } + t("", "", 0); + t("hello", "llo", 2); + t("hello", "el", 1); + t("αβλ", "β", 1); + t("αβλ", "", 3); + assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8)); +} + +fn s(x: &str) -> String { x.to_string() } + +macro_rules! test_concat { + ($expected: expr, $string: expr) => { + { + let s: String = $string.concat(); + assert_eq!($expected, s); + } + } +} + +#[test] +fn test_concat_for_different_types() { + test_concat!("ab", vec![s("a"), s("b")]); + test_concat!("ab", vec!["a", "b"]); + test_concat!("ab", vec!["a", "b"]); + test_concat!("ab", vec![s("a"), s("b")]); +} + +#[test] +fn test_concat_for_different_lengths() { + let empty: &[&str] = &[]; + test_concat!("", empty); + test_concat!("a", ["a"]); + test_concat!("ab", ["a", "b"]); + test_concat!("abc", ["", "a", "bc"]); +} + +macro_rules! test_connect { + ($expected: expr, $string: expr, $delim: expr) => { + { + let s = $string.connect($delim); + assert_eq!($expected, s); + } + } +} + +#[test] +fn test_connect_for_different_types() { + test_connect!("a-b", ["a", "b"], "-"); + let hyphen = "-".to_string(); + test_connect!("a-b", [s("a"), s("b")], &*hyphen); + test_connect!("a-b", vec!["a", "b"], &*hyphen); + test_connect!("a-b", &*vec!["a", "b"], "-"); + test_connect!("a-b", vec![s("a"), s("b")], "-"); +} + +#[test] +fn test_connect_for_different_lengths() { + let empty: &[&str] = &[]; + test_connect!("", empty, "-"); + test_connect!("a", ["a"], "-"); + test_connect!("a-b", ["a", "b"], "-"); + test_connect!("-a-bc", ["", "a", "bc"], "-"); +} + +#[test] +fn test_unsafe_slice() { + assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)}); + assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)}); + assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)}); + fn a_million_letter_a() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("aaaaaaaaaa"); + i += 1; + } + rs + } + fn half_a_million_letter_a() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("aaaaa"); + i += 1; + } + rs + } + let letters = a_million_letter_a(); + assert!(half_a_million_letter_a() == + unsafe {String::from_str(letters.slice_unchecked( + 0, + 500000))}); +} + +#[test] +fn test_starts_with() { + assert!(("".starts_with(""))); + assert!(("abc".starts_with(""))); + assert!(("abc".starts_with("a"))); + assert!((!"a".starts_with("abc"))); + assert!((!"".starts_with("abc"))); + assert!((!"ödd".starts_with("-"))); + assert!(("ödd".starts_with("öd"))); +} + +#[test] +fn test_ends_with() { + assert!(("".ends_with(""))); + assert!(("abc".ends_with(""))); + assert!(("abc".ends_with("c"))); + assert!((!"a".ends_with("abc"))); + assert!((!"".ends_with("abc"))); + assert!((!"ddö".ends_with("-"))); + assert!(("ddö".ends_with("dö"))); +} + +#[test] +fn test_is_empty() { + assert!("".is_empty()); + assert!(!"a".is_empty()); +} + +#[test] +fn test_replace() { + let a = "a"; + assert_eq!("".replace(a, "b"), String::from_str("")); + assert_eq!("a".replace(a, "b"), String::from_str("b")); + assert_eq!("ab".replace(a, "b"), String::from_str("bb")); + let test = "test"; + assert!(" test test ".replace(test, "toast") == + String::from_str(" toast toast ")); + assert_eq!(" test test ".replace(test, ""), String::from_str(" ")); +} + +#[test] +fn test_replace_2a() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let a = "ประเ"; + let a2 = "دولة الكويتทศไทย中华"; + assert_eq!(data.replace(a, repl), a2); +} + +#[test] +fn test_replace_2b() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let b = "ะเ"; + let b2 = "ปรدولة الكويتทศไทย中华"; + assert_eq!(data.replace(b, repl), b2); +} + +#[test] +fn test_replace_2c() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let c = "中华"; + let c2 = "ประเทศไทยدولة الكويت"; + assert_eq!(data.replace(c, repl), c2); +} + +#[test] +fn test_replace_2d() { + let data = "ประเทศไทย中华"; + let repl = "دولة الكويت"; + + let d = "ไท华"; + assert_eq!(data.replace(d, repl), data); +} + +#[test] +fn test_slice() { + assert_eq!("ab", &"abc"[0..2]); + assert_eq!("bc", &"abc"[1..3]); + assert_eq!("", &"abc"[1..1]); + assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]); + + let data = "ประเทศไทย中华"; + assert_eq!("ป", &data[0..3]); + assert_eq!("ร", &data[3..6]); + assert_eq!("", &data[3..3]); + assert_eq!("华", &data[30..33]); + + fn a_million_letter_x() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("华华华华华华华华华华"); + i += 1; + } + rs + } + fn half_a_million_letter_x() -> String { + let mut i = 0; + let mut rs = String::new(); + while i < 100000 { + rs.push_str("华华华华华"); + i += 1; + } + rs + } + let letters = a_million_letter_x(); + assert!(half_a_million_letter_x() == + String::from_str(&letters[0..3 * 500000])); +} + +#[test] +fn test_slice_2() { + let ss = "中华Việt Nam"; + + assert_eq!("华", &ss[3..6]); + assert_eq!("Việt Nam", &ss[6..16]); + + assert_eq!("ab", &"abc"[0..2]); + assert_eq!("bc", &"abc"[1..3]); + assert_eq!("", &"abc"[1..1]); + + assert_eq!("中", &ss[0..3]); + assert_eq!("华V", &ss[3..7]); + assert_eq!("", &ss[3..3]); + /*0: 中 + 3: 华 + 6: V + 7: i + 8: ệ + 11: t + 12: + 13: N + 14: a + 15: m */ +} + +#[test] +#[should_panic] +fn test_slice_fail() { + &"中华Việt Nam"[0..2]; +} + +#[test] +fn test_slice_from() { + assert_eq!(&"abcd"[0..], "abcd"); + assert_eq!(&"abcd"[2..], "cd"); + assert_eq!(&"abcd"[4..], ""); +} +#[test] +fn test_slice_to() { + assert_eq!(&"abcd"[..0], ""); + assert_eq!(&"abcd"[..2], "ab"); + assert_eq!(&"abcd"[..4], "abcd"); +} + +#[test] +fn test_trim_left_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** "); + assert_eq!(" *** *** ".trim_left_matches(chars), ""); + assert_eq!("foo *** ".trim_left_matches(chars), "foo *** "); + + assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12"); + assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123"); +} + +#[test] +fn test_trim_right_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo"); + assert_eq!(" *** *** ".trim_right_matches(chars), ""); + assert_eq!(" *** foo".trim_right_matches(chars), " *** foo"); + + assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar"); + assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar"); +} + +#[test] +fn test_trim_matches() { + let v: &[char] = &[]; + assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); + let chars: &[char] = &['*', ' ']; + assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); + assert_eq!(" *** *** ".trim_matches(chars), ""); + assert_eq!("foo".trim_matches(chars), "foo"); + + assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); + let chars: &[char] = &['1', '2']; + assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); + assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); +} + +#[test] +fn test_trim_left() { + assert_eq!("".trim_left(), ""); + assert_eq!("a".trim_left(), "a"); + assert_eq!(" ".trim_left(), ""); + assert_eq!(" blah".trim_left(), "blah"); + assert_eq!(" \u{3000} wut".trim_left(), "wut"); + assert_eq!("hey ".trim_left(), "hey "); +} + +#[test] +fn test_trim_right() { + assert_eq!("".trim_right(), ""); + assert_eq!("a".trim_right(), "a"); + assert_eq!(" ".trim_right(), ""); + assert_eq!("blah ".trim_right(), "blah"); + assert_eq!("wut \u{3000} ".trim_right(), "wut"); + assert_eq!(" hey".trim_right(), " hey"); +} + +#[test] +fn test_trim() { + assert_eq!("".trim(), ""); + assert_eq!("a".trim(), "a"); + assert_eq!(" ".trim(), ""); + assert_eq!(" blah ".trim(), "blah"); + assert_eq!("\nwut \u{3000} ".trim(), "wut"); + assert_eq!(" hey dude ".trim(), "hey dude"); +} + +#[test] +fn test_is_whitespace() { + assert!("".chars().all(|c| c.is_whitespace())); + assert!(" ".chars().all(|c| c.is_whitespace())); + assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space + assert!(" \n\t ".chars().all(|c| c.is_whitespace())); + assert!(!" _ ".chars().all(|c| c.is_whitespace())); +} + +#[test] +fn test_slice_shift_char() { + let data = "ประเทศไทย中"; + assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中"))); +} + +#[test] +fn test_slice_shift_char_2() { + let empty = ""; + assert_eq!(empty.slice_shift_char(), None); +} + +#[test] +fn test_is_utf8() { + // deny overlong encodings + assert!(from_utf8(&[0xc0, 0x80]).is_err()); + assert!(from_utf8(&[0xc0, 0xae]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); + assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); + assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); + assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); + assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); + + // deny surrogates + assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); + assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); + + assert!(from_utf8(&[0xC2, 0x80]).is_ok()); + assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); + assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); + assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); + assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); + assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); +} + +#[test] +fn test_is_utf16() { + use unicode::str::is_utf16; + + macro_rules! pos { + ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } } + } + + // non-surrogates + pos!(&[0x0000], + &[0x0001, 0x0002], + &[0xD7FF], + &[0xE000]); + + // surrogate pairs (randomly generated with Python 3's + // .encode('utf-16be')) + pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45], + &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14], + &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]); + + // mixtures (also random) + pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65], + &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006], + &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]); + + // negative tests + macro_rules! neg { + ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } } + } + + neg!( + // surrogate + regular unit + &[0xdb45, 0x0000], + // surrogate + lead surrogate + &[0xd900, 0xd900], + // unterminated surrogate + &[0xd8ff], + // trail surrogate without a lead + &[0xddb7]); + + // random byte sequences that Python 3's .decode('utf-16be') + // failed on + neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7], + &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3], + &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca], + &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278], + &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e], + &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5], + &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee], + &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7], + &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a], + &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a], + &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe], + &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf], + &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e], + &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5], + &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f], + &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b], + &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7], + &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9], + &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8], + &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282], + &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]); +} + +#[test] +fn test_as_bytes() { + // no null + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let b: &[u8] = &[]; + assert_eq!("".as_bytes(), b); + assert_eq!("abc".as_bytes(), b"abc"); + assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); +} + +#[test] +#[should_panic] +fn test_as_bytes_fail() { + // Don't double free. (I'm not sure if this exercises the + // original problem code path anymore.) + let s = String::from_str(""); + let _bytes = s.as_bytes(); + panic!(); +} + +#[test] +fn test_as_ptr() { + let buf = "hello".as_ptr(); + unsafe { + assert_eq!(*buf.offset(0), b'h'); + assert_eq!(*buf.offset(1), b'e'); + assert_eq!(*buf.offset(2), b'l'); + assert_eq!(*buf.offset(3), b'l'); + assert_eq!(*buf.offset(4), b'o'); + } +} + +#[test] +fn test_subslice_offset() { + let a = "kernelsprite"; + let b = &a[7..a.len()]; + let c = &a[0..a.len() - 6]; + assert_eq!(a.subslice_offset(b), 7); + assert_eq!(a.subslice_offset(c), 0); + + let string = "a\nb\nc"; + let lines: Vec<&str> = string.lines().collect(); + assert_eq!(string.subslice_offset(lines[0]), 0); + assert_eq!(string.subslice_offset(lines[1]), 2); + assert_eq!(string.subslice_offset(lines[2]), 4); +} + +#[test] +#[should_panic] +fn test_subslice_offset_2() { + let a = "alchemiter"; + let b = "cruxtruder"; + a.subslice_offset(b); +} + +#[test] +fn vec_str_conversions() { + let s1: String = String::from_str("All mimsy were the borogoves"); + + let v: Vec = s1.as_bytes().to_vec(); + let s2: String = String::from_str(from_utf8(&v).unwrap()); + let mut i = 0; + let n1 = s1.len(); + let n2 = v.len(); + assert_eq!(n1, n2); + while i < n1 { + let a: u8 = s1.as_bytes()[i]; + let b: u8 = s2.as_bytes()[i]; + debug!("{}", a); + debug!("{}", b); + assert_eq!(a, b); + i += 1; + } +} + +#[test] +fn test_contains() { + assert!("abcde".contains("bcd")); + assert!("abcde".contains("abcd")); + assert!("abcde".contains("bcde")); + assert!("abcde".contains("")); + assert!("".contains("")); + assert!(!"abcde".contains("def")); + assert!(!"".contains("a")); + + let data = "ประเทศไทย中华Việt Nam"; + assert!(data.contains("ประเ")); + assert!(data.contains("ะเ")); + assert!(data.contains("中华")); + assert!(!data.contains("ไท华")); +} + +#[test] +fn test_contains_char() { + assert!("abc".contains('b')); + assert!("a".contains('a')); + assert!(!"abc".contains('d')); + assert!(!"".contains('a')); +} + +#[test] +fn test_char_at() { + let s = "ศไทย中华Việt Nam"; + let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = 0; + for ch in &v { + assert!(s.char_at(pos) == *ch); + pos += ch.to_string().len(); + } +} + +#[test] +fn test_char_at_reverse() { + let s = "ศไทย中华Việt Nam"; + let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + let mut pos = s.len(); + for ch in v.iter().rev() { + assert!(s.char_at_reverse(pos) == *ch); + pos -= ch.to_string().len(); + } +} + +#[test] +fn test_escape_unicode() { + assert_eq!("abc".escape_unicode(), + String::from_str("\\u{61}\\u{62}\\u{63}")); + assert_eq!("a c".escape_unicode(), + String::from_str("\\u{61}\\u{20}\\u{63}")); + assert_eq!("\r\n\t".escape_unicode(), + String::from_str("\\u{d}\\u{a}\\u{9}")); + assert_eq!("'\"\\".escape_unicode(), + String::from_str("\\u{27}\\u{22}\\u{5c}")); + assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), + String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}")); + assert_eq!("\u{100}\u{ffff}".escape_unicode(), + String::from_str("\\u{100}\\u{ffff}")); + assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), + String::from_str("\\u{10000}\\u{10ffff}")); + assert_eq!("ab\u{fb00}".escape_unicode(), + String::from_str("\\u{61}\\u{62}\\u{fb00}")); + assert_eq!("\u{1d4ea}\r".escape_unicode(), + String::from_str("\\u{1d4ea}\\u{d}")); +} + +#[test] +fn test_escape_default() { + assert_eq!("abc".escape_default(), String::from_str("abc")); + assert_eq!("a c".escape_default(), String::from_str("a c")); + assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t")); + assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\")); + assert_eq!("\u{100}\u{ffff}".escape_default(), + String::from_str("\\u{100}\\u{ffff}")); + assert_eq!("\u{10000}\u{10ffff}".escape_default(), + String::from_str("\\u{10000}\\u{10ffff}")); + assert_eq!("ab\u{fb00}".escape_default(), + String::from_str("ab\\u{fb00}")); + assert_eq!("\u{1d4ea}\r".escape_default(), + String::from_str("\\u{1d4ea}\\r")); +} + +#[test] +fn test_total_ord() { + "1234".cmp("123") == Greater; + "123".cmp("1234") == Less; + "1234".cmp("1234") == Equal; + "12345555".cmp("123456") == Less; + "22".cmp("1234") == Greater; +} + +#[test] +fn test_char_range_at() { + let data = "b¢€𤭢𤭢€¢b"; + assert_eq!('b', data.char_range_at(0).ch); + assert_eq!('¢', data.char_range_at(1).ch); + assert_eq!('€', data.char_range_at(3).ch); + assert_eq!('𤭢', data.char_range_at(6).ch); + assert_eq!('𤭢', data.char_range_at(10).ch); + assert_eq!('€', data.char_range_at(14).ch); + assert_eq!('¢', data.char_range_at(17).ch); + assert_eq!('b', data.char_range_at(19).ch); +} + +#[test] +fn test_char_range_at_reverse_underflow() { + assert_eq!("abc".char_range_at_reverse(0).next, 0); +} + +#[test] +fn test_iterator() { + let s = "ศไทย中华Việt Nam"; + let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + + let mut pos = 0; + let it = s.chars(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + +#[test] +fn test_rev_iterator() { + let s = "ศไทย中华Việt Nam"; + let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; + + let mut pos = 0; + let it = s.chars().rev(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + +#[test] +fn test_chars_decoding() { + let mut bytes = [0; 4]; + for c in (0..0x110000).filter_map(::std::char::from_u32) { + let len = c.encode_utf8(&mut bytes).unwrap_or(0); + let s = ::std::str::from_utf8(&bytes[..len]).unwrap(); + if Some(c) != s.chars().next() { + panic!("character {:x}={} does not decode correctly", c as u32, c); + } + } +} + +#[test] +fn test_chars_rev_decoding() { + let mut bytes = [0; 4]; + for c in (0..0x110000).filter_map(::std::char::from_u32) { + let len = c.encode_utf8(&mut bytes).unwrap_or(0); + let s = ::std::str::from_utf8(&bytes[..len]).unwrap(); + if Some(c) != s.chars().rev().next() { + panic!("character {:x}={} does not decode correctly", c as u32, c); + } + } +} + +#[test] +fn test_iterator_clone() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert!(it.clone().zip(it).all(|(x,y)| x == y)); +} + +#[test] +fn test_bytesator() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = 0; + + for b in s.bytes() { + assert_eq!(b, v[pos]); + pos += 1; + } +} + +#[test] +fn test_bytes_revator() { + let s = "ศไทย中华Việt Nam"; + let v = [ + 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, + 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97, + 109 + ]; + let mut pos = v.len(); + + for b in s.bytes().rev() { + pos -= 1; + assert_eq!(b, v[pos]); + } +} + +#[test] +fn test_char_indicesator() { + let s = "ศไทย中华Việt Nam"; + let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; + let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; + + let mut pos = 0; + let it = s.char_indices(); + + for c in it { + assert_eq!(c, (p[pos], v[pos])); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(pos, p.len()); +} + +#[test] +fn test_char_indices_revator() { + let s = "ศไทย中华Việt Nam"; + let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; + let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ']; + + let mut pos = 0; + let it = s.char_indices().rev(); + + for c in it { + assert_eq!(c, (p[pos], v[pos])); + pos += 1; + } + assert_eq!(pos, v.len()); + assert_eq!(pos, p.len()); +} + +#[test] +fn test_splitn_char_iterator() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.splitn(4, ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect(); + assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); + + // Unicode + let split: Vec<&str> = data.splitn(4, 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); + + let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect(); + assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); +} + +#[test] +fn test_split_char_iterator_no_trailing() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split('\n').collect(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); + + let split: Vec<&str> = data.split_terminator('\n').collect(); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); +} + +#[test] +fn test_rsplit() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.rsplit(' ').collect(); + assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]); + + let split: Vec<&str> = data.rsplit("lämb").collect(); + assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]); + + let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect(); + assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]); +} + +#[test] +fn test_rsplitn() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.rsplitn(2, ' ').collect(); + assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]); + + let split: Vec<&str> = data.rsplitn(2, "lämb").collect(); + assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]); + + let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect(); + assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]); +} + +#[test] +fn test_words() { + let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; + let words: Vec<&str> = data.words().collect(); + assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) +} + +#[test] +fn test_nfd_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfd_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "d\u{307}\u{1c4}"); + t!("\u{2026}", "\u{2026}"); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); + t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); + t!("a\u{301}", "a\u{301}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); + t!("\u{ac1c}", "\u{1100}\u{1162}"); +} + +#[test] +fn test_nfkd_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfkd_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "d\u{307}DZ\u{30c}"); + t!("\u{2026}", "..."); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "d\u{323}\u{307}"); + t!("\u{1e0d}\u{307}", "d\u{323}\u{307}"); + t!("a\u{301}", "a\u{301}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{1111}\u{1171}\u{11b6}"); + t!("\u{ac1c}", "\u{1100}\u{1162}"); +} + +#[test] +fn test_nfc_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfc_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "\u{1e0b}\u{1c4}"); + t!("\u{2026}", "\u{2026}"); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); + t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); + t!("a\u{301}", "\u{e1}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{d4db}"); + t!("\u{ac1c}", "\u{ac1c}"); + t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); +} + +#[test] +fn test_nfkc_chars() { + macro_rules! t { + ($input: expr, $expected: expr) => { + assert_eq!($input.nfkc_chars().collect::(), $expected); + } + } + t!("abc", "abc"); + t!("\u{1e0b}\u{1c4}", "\u{1e0b}D\u{17d}"); + t!("\u{2026}", "..."); + t!("\u{2126}", "\u{3a9}"); + t!("\u{1e0b}\u{323}", "\u{1e0d}\u{307}"); + t!("\u{1e0d}\u{307}", "\u{1e0d}\u{307}"); + t!("a\u{301}", "\u{e1}"); + t!("\u{301}a", "\u{301}a"); + t!("\u{d4db}", "\u{d4db}"); + t!("\u{ac1c}", "\u{ac1c}"); + t!("a\u{300}\u{305}\u{315}\u{5ae}b", "\u{e0}\u{5ae}\u{305}\u{315}b"); +} + +#[test] +fn test_lines() { + let data = "\nMäry häd ä little lämb\n\nLittle lämb\n"; + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); + + let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n + let lines: Vec<&str> = data.lines().collect(); + assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); +} + +#[test] +fn test_graphemes() { + use std::iter::order; + + // official Unicode test data + // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt + let test_same: [(_, &[_]); 325] = [ + ("\u{20}\u{20}", &["\u{20}", "\u{20}"]), + ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]), + ("\u{20}\u{D}", &["\u{20}", "\u{D}"]), + ("\u{20}\u{308}\u{D}", &["\u{20}\u{308}", "\u{D}"]), + ("\u{20}\u{A}", &["\u{20}", "\u{A}"]), + ("\u{20}\u{308}\u{A}", &["\u{20}\u{308}", "\u{A}"]), + ("\u{20}\u{1}", &["\u{20}", "\u{1}"]), + ("\u{20}\u{308}\u{1}", &["\u{20}\u{308}", "\u{1}"]), + ("\u{20}\u{300}", &["\u{20}\u{300}"]), + ("\u{20}\u{308}\u{300}", &["\u{20}\u{308}\u{300}"]), + ("\u{20}\u{1100}", &["\u{20}", "\u{1100}"]), + ("\u{20}\u{308}\u{1100}", &["\u{20}\u{308}", "\u{1100}"]), + ("\u{20}\u{1160}", &["\u{20}", "\u{1160}"]), + ("\u{20}\u{308}\u{1160}", &["\u{20}\u{308}", "\u{1160}"]), + ("\u{20}\u{11A8}", &["\u{20}", "\u{11A8}"]), + ("\u{20}\u{308}\u{11A8}", &["\u{20}\u{308}", "\u{11A8}"]), + ("\u{20}\u{AC00}", &["\u{20}", "\u{AC00}"]), + ("\u{20}\u{308}\u{AC00}", &["\u{20}\u{308}", "\u{AC00}"]), + ("\u{20}\u{AC01}", &["\u{20}", "\u{AC01}"]), + ("\u{20}\u{308}\u{AC01}", &["\u{20}\u{308}", "\u{AC01}"]), + ("\u{20}\u{1F1E6}", &["\u{20}", "\u{1F1E6}"]), + ("\u{20}\u{308}\u{1F1E6}", &["\u{20}\u{308}", "\u{1F1E6}"]), + ("\u{20}\u{378}", &["\u{20}", "\u{378}"]), + ("\u{20}\u{308}\u{378}", &["\u{20}\u{308}", "\u{378}"]), + ("\u{D}\u{20}", &["\u{D}", "\u{20}"]), + ("\u{D}\u{308}\u{20}", &["\u{D}", "\u{308}", "\u{20}"]), + ("\u{D}\u{D}", &["\u{D}", "\u{D}"]), + ("\u{D}\u{308}\u{D}", &["\u{D}", "\u{308}", "\u{D}"]), + ("\u{D}\u{A}", &["\u{D}\u{A}"]), + ("\u{D}\u{308}\u{A}", &["\u{D}", "\u{308}", "\u{A}"]), + ("\u{D}\u{1}", &["\u{D}", "\u{1}"]), + ("\u{D}\u{308}\u{1}", &["\u{D}", "\u{308}", "\u{1}"]), + ("\u{D}\u{300}", &["\u{D}", "\u{300}"]), + ("\u{D}\u{308}\u{300}", &["\u{D}", "\u{308}\u{300}"]), + ("\u{D}\u{903}", &["\u{D}", "\u{903}"]), + ("\u{D}\u{1100}", &["\u{D}", "\u{1100}"]), + ("\u{D}\u{308}\u{1100}", &["\u{D}", "\u{308}", "\u{1100}"]), + ("\u{D}\u{1160}", &["\u{D}", "\u{1160}"]), + ("\u{D}\u{308}\u{1160}", &["\u{D}", "\u{308}", "\u{1160}"]), + ("\u{D}\u{11A8}", &["\u{D}", "\u{11A8}"]), + ("\u{D}\u{308}\u{11A8}", &["\u{D}", "\u{308}", "\u{11A8}"]), + ("\u{D}\u{AC00}", &["\u{D}", "\u{AC00}"]), + ("\u{D}\u{308}\u{AC00}", &["\u{D}", "\u{308}", "\u{AC00}"]), + ("\u{D}\u{AC01}", &["\u{D}", "\u{AC01}"]), + ("\u{D}\u{308}\u{AC01}", &["\u{D}", "\u{308}", "\u{AC01}"]), + ("\u{D}\u{1F1E6}", &["\u{D}", "\u{1F1E6}"]), + ("\u{D}\u{308}\u{1F1E6}", &["\u{D}", "\u{308}", "\u{1F1E6}"]), + ("\u{D}\u{378}", &["\u{D}", "\u{378}"]), + ("\u{D}\u{308}\u{378}", &["\u{D}", "\u{308}", "\u{378}"]), + ("\u{A}\u{20}", &["\u{A}", "\u{20}"]), + ("\u{A}\u{308}\u{20}", &["\u{A}", "\u{308}", "\u{20}"]), + ("\u{A}\u{D}", &["\u{A}", "\u{D}"]), + ("\u{A}\u{308}\u{D}", &["\u{A}", "\u{308}", "\u{D}"]), + ("\u{A}\u{A}", &["\u{A}", "\u{A}"]), + ("\u{A}\u{308}\u{A}", &["\u{A}", "\u{308}", "\u{A}"]), + ("\u{A}\u{1}", &["\u{A}", "\u{1}"]), + ("\u{A}\u{308}\u{1}", &["\u{A}", "\u{308}", "\u{1}"]), + ("\u{A}\u{300}", &["\u{A}", "\u{300}"]), + ("\u{A}\u{308}\u{300}", &["\u{A}", "\u{308}\u{300}"]), + ("\u{A}\u{903}", &["\u{A}", "\u{903}"]), + ("\u{A}\u{1100}", &["\u{A}", "\u{1100}"]), + ("\u{A}\u{308}\u{1100}", &["\u{A}", "\u{308}", "\u{1100}"]), + ("\u{A}\u{1160}", &["\u{A}", "\u{1160}"]), + ("\u{A}\u{308}\u{1160}", &["\u{A}", "\u{308}", "\u{1160}"]), + ("\u{A}\u{11A8}", &["\u{A}", "\u{11A8}"]), + ("\u{A}\u{308}\u{11A8}", &["\u{A}", "\u{308}", "\u{11A8}"]), + ("\u{A}\u{AC00}", &["\u{A}", "\u{AC00}"]), + ("\u{A}\u{308}\u{AC00}", &["\u{A}", "\u{308}", "\u{AC00}"]), + ("\u{A}\u{AC01}", &["\u{A}", "\u{AC01}"]), + ("\u{A}\u{308}\u{AC01}", &["\u{A}", "\u{308}", "\u{AC01}"]), + ("\u{A}\u{1F1E6}", &["\u{A}", "\u{1F1E6}"]), + ("\u{A}\u{308}\u{1F1E6}", &["\u{A}", "\u{308}", "\u{1F1E6}"]), + ("\u{A}\u{378}", &["\u{A}", "\u{378}"]), + ("\u{A}\u{308}\u{378}", &["\u{A}", "\u{308}", "\u{378}"]), + ("\u{1}\u{20}", &["\u{1}", "\u{20}"]), + ("\u{1}\u{308}\u{20}", &["\u{1}", "\u{308}", "\u{20}"]), + ("\u{1}\u{D}", &["\u{1}", "\u{D}"]), + ("\u{1}\u{308}\u{D}", &["\u{1}", "\u{308}", "\u{D}"]), + ("\u{1}\u{A}", &["\u{1}", "\u{A}"]), + ("\u{1}\u{308}\u{A}", &["\u{1}", "\u{308}", "\u{A}"]), + ("\u{1}\u{1}", &["\u{1}", "\u{1}"]), + ("\u{1}\u{308}\u{1}", &["\u{1}", "\u{308}", "\u{1}"]), + ("\u{1}\u{300}", &["\u{1}", "\u{300}"]), + ("\u{1}\u{308}\u{300}", &["\u{1}", "\u{308}\u{300}"]), + ("\u{1}\u{903}", &["\u{1}", "\u{903}"]), + ("\u{1}\u{1100}", &["\u{1}", "\u{1100}"]), + ("\u{1}\u{308}\u{1100}", &["\u{1}", "\u{308}", "\u{1100}"]), + ("\u{1}\u{1160}", &["\u{1}", "\u{1160}"]), + ("\u{1}\u{308}\u{1160}", &["\u{1}", "\u{308}", "\u{1160}"]), + ("\u{1}\u{11A8}", &["\u{1}", "\u{11A8}"]), + ("\u{1}\u{308}\u{11A8}", &["\u{1}", "\u{308}", "\u{11A8}"]), + ("\u{1}\u{AC00}", &["\u{1}", "\u{AC00}"]), + ("\u{1}\u{308}\u{AC00}", &["\u{1}", "\u{308}", "\u{AC00}"]), + ("\u{1}\u{AC01}", &["\u{1}", "\u{AC01}"]), + ("\u{1}\u{308}\u{AC01}", &["\u{1}", "\u{308}", "\u{AC01}"]), + ("\u{1}\u{1F1E6}", &["\u{1}", "\u{1F1E6}"]), + ("\u{1}\u{308}\u{1F1E6}", &["\u{1}", "\u{308}", "\u{1F1E6}"]), + ("\u{1}\u{378}", &["\u{1}", "\u{378}"]), + ("\u{1}\u{308}\u{378}", &["\u{1}", "\u{308}", "\u{378}"]), + ("\u{300}\u{20}", &["\u{300}", "\u{20}"]), + ("\u{300}\u{308}\u{20}", &["\u{300}\u{308}", "\u{20}"]), + ("\u{300}\u{D}", &["\u{300}", "\u{D}"]), + ("\u{300}\u{308}\u{D}", &["\u{300}\u{308}", "\u{D}"]), + ("\u{300}\u{A}", &["\u{300}", "\u{A}"]), + ("\u{300}\u{308}\u{A}", &["\u{300}\u{308}", "\u{A}"]), + ("\u{300}\u{1}", &["\u{300}", "\u{1}"]), + ("\u{300}\u{308}\u{1}", &["\u{300}\u{308}", "\u{1}"]), + ("\u{300}\u{300}", &["\u{300}\u{300}"]), + ("\u{300}\u{308}\u{300}", &["\u{300}\u{308}\u{300}"]), + ("\u{300}\u{1100}", &["\u{300}", "\u{1100}"]), + ("\u{300}\u{308}\u{1100}", &["\u{300}\u{308}", "\u{1100}"]), + ("\u{300}\u{1160}", &["\u{300}", "\u{1160}"]), + ("\u{300}\u{308}\u{1160}", &["\u{300}\u{308}", "\u{1160}"]), + ("\u{300}\u{11A8}", &["\u{300}", "\u{11A8}"]), + ("\u{300}\u{308}\u{11A8}", &["\u{300}\u{308}", "\u{11A8}"]), + ("\u{300}\u{AC00}", &["\u{300}", "\u{AC00}"]), + ("\u{300}\u{308}\u{AC00}", &["\u{300}\u{308}", "\u{AC00}"]), + ("\u{300}\u{AC01}", &["\u{300}", "\u{AC01}"]), + ("\u{300}\u{308}\u{AC01}", &["\u{300}\u{308}", "\u{AC01}"]), + ("\u{300}\u{1F1E6}", &["\u{300}", "\u{1F1E6}"]), + ("\u{300}\u{308}\u{1F1E6}", &["\u{300}\u{308}", "\u{1F1E6}"]), + ("\u{300}\u{378}", &["\u{300}", "\u{378}"]), + ("\u{300}\u{308}\u{378}", &["\u{300}\u{308}", "\u{378}"]), + ("\u{903}\u{20}", &["\u{903}", "\u{20}"]), + ("\u{903}\u{308}\u{20}", &["\u{903}\u{308}", "\u{20}"]), + ("\u{903}\u{D}", &["\u{903}", "\u{D}"]), + ("\u{903}\u{308}\u{D}", &["\u{903}\u{308}", "\u{D}"]), + ("\u{903}\u{A}", &["\u{903}", "\u{A}"]), + ("\u{903}\u{308}\u{A}", &["\u{903}\u{308}", "\u{A}"]), + ("\u{903}\u{1}", &["\u{903}", "\u{1}"]), + ("\u{903}\u{308}\u{1}", &["\u{903}\u{308}", "\u{1}"]), + ("\u{903}\u{300}", &["\u{903}\u{300}"]), + ("\u{903}\u{308}\u{300}", &["\u{903}\u{308}\u{300}"]), + ("\u{903}\u{1100}", &["\u{903}", "\u{1100}"]), + ("\u{903}\u{308}\u{1100}", &["\u{903}\u{308}", "\u{1100}"]), + ("\u{903}\u{1160}", &["\u{903}", "\u{1160}"]), + ("\u{903}\u{308}\u{1160}", &["\u{903}\u{308}", "\u{1160}"]), + ("\u{903}\u{11A8}", &["\u{903}", "\u{11A8}"]), + ("\u{903}\u{308}\u{11A8}", &["\u{903}\u{308}", "\u{11A8}"]), + ("\u{903}\u{AC00}", &["\u{903}", "\u{AC00}"]), + ("\u{903}\u{308}\u{AC00}", &["\u{903}\u{308}", "\u{AC00}"]), + ("\u{903}\u{AC01}", &["\u{903}", "\u{AC01}"]), + ("\u{903}\u{308}\u{AC01}", &["\u{903}\u{308}", "\u{AC01}"]), + ("\u{903}\u{1F1E6}", &["\u{903}", "\u{1F1E6}"]), + ("\u{903}\u{308}\u{1F1E6}", &["\u{903}\u{308}", "\u{1F1E6}"]), + ("\u{903}\u{378}", &["\u{903}", "\u{378}"]), + ("\u{903}\u{308}\u{378}", &["\u{903}\u{308}", "\u{378}"]), + ("\u{1100}\u{20}", &["\u{1100}", "\u{20}"]), + ("\u{1100}\u{308}\u{20}", &["\u{1100}\u{308}", "\u{20}"]), + ("\u{1100}\u{D}", &["\u{1100}", "\u{D}"]), + ("\u{1100}\u{308}\u{D}", &["\u{1100}\u{308}", "\u{D}"]), + ("\u{1100}\u{A}", &["\u{1100}", "\u{A}"]), + ("\u{1100}\u{308}\u{A}", &["\u{1100}\u{308}", "\u{A}"]), + ("\u{1100}\u{1}", &["\u{1100}", "\u{1}"]), + ("\u{1100}\u{308}\u{1}", &["\u{1100}\u{308}", "\u{1}"]), + ("\u{1100}\u{300}", &["\u{1100}\u{300}"]), + ("\u{1100}\u{308}\u{300}", &["\u{1100}\u{308}\u{300}"]), + ("\u{1100}\u{1100}", &["\u{1100}\u{1100}"]), + ("\u{1100}\u{308}\u{1100}", &["\u{1100}\u{308}", "\u{1100}"]), + ("\u{1100}\u{1160}", &["\u{1100}\u{1160}"]), + ("\u{1100}\u{308}\u{1160}", &["\u{1100}\u{308}", "\u{1160}"]), + ("\u{1100}\u{11A8}", &["\u{1100}", "\u{11A8}"]), + ("\u{1100}\u{308}\u{11A8}", &["\u{1100}\u{308}", "\u{11A8}"]), + ("\u{1100}\u{AC00}", &["\u{1100}\u{AC00}"]), + ("\u{1100}\u{308}\u{AC00}", &["\u{1100}\u{308}", "\u{AC00}"]), + ("\u{1100}\u{AC01}", &["\u{1100}\u{AC01}"]), + ("\u{1100}\u{308}\u{AC01}", &["\u{1100}\u{308}", "\u{AC01}"]), + ("\u{1100}\u{1F1E6}", &["\u{1100}", "\u{1F1E6}"]), + ("\u{1100}\u{308}\u{1F1E6}", &["\u{1100}\u{308}", "\u{1F1E6}"]), + ("\u{1100}\u{378}", &["\u{1100}", "\u{378}"]), + ("\u{1100}\u{308}\u{378}", &["\u{1100}\u{308}", "\u{378}"]), + ("\u{1160}\u{20}", &["\u{1160}", "\u{20}"]), + ("\u{1160}\u{308}\u{20}", &["\u{1160}\u{308}", "\u{20}"]), + ("\u{1160}\u{D}", &["\u{1160}", "\u{D}"]), + ("\u{1160}\u{308}\u{D}", &["\u{1160}\u{308}", "\u{D}"]), + ("\u{1160}\u{A}", &["\u{1160}", "\u{A}"]), + ("\u{1160}\u{308}\u{A}", &["\u{1160}\u{308}", "\u{A}"]), + ("\u{1160}\u{1}", &["\u{1160}", "\u{1}"]), + ("\u{1160}\u{308}\u{1}", &["\u{1160}\u{308}", "\u{1}"]), + ("\u{1160}\u{300}", &["\u{1160}\u{300}"]), + ("\u{1160}\u{308}\u{300}", &["\u{1160}\u{308}\u{300}"]), + ("\u{1160}\u{1100}", &["\u{1160}", "\u{1100}"]), + ("\u{1160}\u{308}\u{1100}", &["\u{1160}\u{308}", "\u{1100}"]), + ("\u{1160}\u{1160}", &["\u{1160}\u{1160}"]), + ("\u{1160}\u{308}\u{1160}", &["\u{1160}\u{308}", "\u{1160}"]), + ("\u{1160}\u{11A8}", &["\u{1160}\u{11A8}"]), + ("\u{1160}\u{308}\u{11A8}", &["\u{1160}\u{308}", "\u{11A8}"]), + ("\u{1160}\u{AC00}", &["\u{1160}", "\u{AC00}"]), + ("\u{1160}\u{308}\u{AC00}", &["\u{1160}\u{308}", "\u{AC00}"]), + ("\u{1160}\u{AC01}", &["\u{1160}", "\u{AC01}"]), + ("\u{1160}\u{308}\u{AC01}", &["\u{1160}\u{308}", "\u{AC01}"]), + ("\u{1160}\u{1F1E6}", &["\u{1160}", "\u{1F1E6}"]), + ("\u{1160}\u{308}\u{1F1E6}", &["\u{1160}\u{308}", "\u{1F1E6}"]), + ("\u{1160}\u{378}", &["\u{1160}", "\u{378}"]), + ("\u{1160}\u{308}\u{378}", &["\u{1160}\u{308}", "\u{378}"]), + ("\u{11A8}\u{20}", &["\u{11A8}", "\u{20}"]), + ("\u{11A8}\u{308}\u{20}", &["\u{11A8}\u{308}", "\u{20}"]), + ("\u{11A8}\u{D}", &["\u{11A8}", "\u{D}"]), + ("\u{11A8}\u{308}\u{D}", &["\u{11A8}\u{308}", "\u{D}"]), + ("\u{11A8}\u{A}", &["\u{11A8}", "\u{A}"]), + ("\u{11A8}\u{308}\u{A}", &["\u{11A8}\u{308}", "\u{A}"]), + ("\u{11A8}\u{1}", &["\u{11A8}", "\u{1}"]), + ("\u{11A8}\u{308}\u{1}", &["\u{11A8}\u{308}", "\u{1}"]), + ("\u{11A8}\u{300}", &["\u{11A8}\u{300}"]), + ("\u{11A8}\u{308}\u{300}", &["\u{11A8}\u{308}\u{300}"]), + ("\u{11A8}\u{1100}", &["\u{11A8}", "\u{1100}"]), + ("\u{11A8}\u{308}\u{1100}", &["\u{11A8}\u{308}", "\u{1100}"]), + ("\u{11A8}\u{1160}", &["\u{11A8}", "\u{1160}"]), + ("\u{11A8}\u{308}\u{1160}", &["\u{11A8}\u{308}", "\u{1160}"]), + ("\u{11A8}\u{11A8}", &["\u{11A8}\u{11A8}"]), + ("\u{11A8}\u{308}\u{11A8}", &["\u{11A8}\u{308}", "\u{11A8}"]), + ("\u{11A8}\u{AC00}", &["\u{11A8}", "\u{AC00}"]), + ("\u{11A8}\u{308}\u{AC00}", &["\u{11A8}\u{308}", "\u{AC00}"]), + ("\u{11A8}\u{AC01}", &["\u{11A8}", "\u{AC01}"]), + ("\u{11A8}\u{308}\u{AC01}", &["\u{11A8}\u{308}", "\u{AC01}"]), + ("\u{11A8}\u{1F1E6}", &["\u{11A8}", "\u{1F1E6}"]), + ("\u{11A8}\u{308}\u{1F1E6}", &["\u{11A8}\u{308}", "\u{1F1E6}"]), + ("\u{11A8}\u{378}", &["\u{11A8}", "\u{378}"]), + ("\u{11A8}\u{308}\u{378}", &["\u{11A8}\u{308}", "\u{378}"]), + ("\u{AC00}\u{20}", &["\u{AC00}", "\u{20}"]), + ("\u{AC00}\u{308}\u{20}", &["\u{AC00}\u{308}", "\u{20}"]), + ("\u{AC00}\u{D}", &["\u{AC00}", "\u{D}"]), + ("\u{AC00}\u{308}\u{D}", &["\u{AC00}\u{308}", "\u{D}"]), + ("\u{AC00}\u{A}", &["\u{AC00}", "\u{A}"]), + ("\u{AC00}\u{308}\u{A}", &["\u{AC00}\u{308}", "\u{A}"]), + ("\u{AC00}\u{1}", &["\u{AC00}", "\u{1}"]), + ("\u{AC00}\u{308}\u{1}", &["\u{AC00}\u{308}", "\u{1}"]), + ("\u{AC00}\u{300}", &["\u{AC00}\u{300}"]), + ("\u{AC00}\u{308}\u{300}", &["\u{AC00}\u{308}\u{300}"]), + ("\u{AC00}\u{1100}", &["\u{AC00}", "\u{1100}"]), + ("\u{AC00}\u{308}\u{1100}", &["\u{AC00}\u{308}", "\u{1100}"]), + ("\u{AC00}\u{1160}", &["\u{AC00}\u{1160}"]), + ("\u{AC00}\u{308}\u{1160}", &["\u{AC00}\u{308}", "\u{1160}"]), + ("\u{AC00}\u{11A8}", &["\u{AC00}\u{11A8}"]), + ("\u{AC00}\u{308}\u{11A8}", &["\u{AC00}\u{308}", "\u{11A8}"]), + ("\u{AC00}\u{AC00}", &["\u{AC00}", "\u{AC00}"]), + ("\u{AC00}\u{308}\u{AC00}", &["\u{AC00}\u{308}", "\u{AC00}"]), + ("\u{AC00}\u{AC01}", &["\u{AC00}", "\u{AC01}"]), + ("\u{AC00}\u{308}\u{AC01}", &["\u{AC00}\u{308}", "\u{AC01}"]), + ("\u{AC00}\u{1F1E6}", &["\u{AC00}", "\u{1F1E6}"]), + ("\u{AC00}\u{308}\u{1F1E6}", &["\u{AC00}\u{308}", "\u{1F1E6}"]), + ("\u{AC00}\u{378}", &["\u{AC00}", "\u{378}"]), + ("\u{AC00}\u{308}\u{378}", &["\u{AC00}\u{308}", "\u{378}"]), + ("\u{AC01}\u{20}", &["\u{AC01}", "\u{20}"]), + ("\u{AC01}\u{308}\u{20}", &["\u{AC01}\u{308}", "\u{20}"]), + ("\u{AC01}\u{D}", &["\u{AC01}", "\u{D}"]), + ("\u{AC01}\u{308}\u{D}", &["\u{AC01}\u{308}", "\u{D}"]), + ("\u{AC01}\u{A}", &["\u{AC01}", "\u{A}"]), + ("\u{AC01}\u{308}\u{A}", &["\u{AC01}\u{308}", "\u{A}"]), + ("\u{AC01}\u{1}", &["\u{AC01}", "\u{1}"]), + ("\u{AC01}\u{308}\u{1}", &["\u{AC01}\u{308}", "\u{1}"]), + ("\u{AC01}\u{300}", &["\u{AC01}\u{300}"]), + ("\u{AC01}\u{308}\u{300}", &["\u{AC01}\u{308}\u{300}"]), + ("\u{AC01}\u{1100}", &["\u{AC01}", "\u{1100}"]), + ("\u{AC01}\u{308}\u{1100}", &["\u{AC01}\u{308}", "\u{1100}"]), + ("\u{AC01}\u{1160}", &["\u{AC01}", "\u{1160}"]), + ("\u{AC01}\u{308}\u{1160}", &["\u{AC01}\u{308}", "\u{1160}"]), + ("\u{AC01}\u{11A8}", &["\u{AC01}\u{11A8}"]), + ("\u{AC01}\u{308}\u{11A8}", &["\u{AC01}\u{308}", "\u{11A8}"]), + ("\u{AC01}\u{AC00}", &["\u{AC01}", "\u{AC00}"]), + ("\u{AC01}\u{308}\u{AC00}", &["\u{AC01}\u{308}", "\u{AC00}"]), + ("\u{AC01}\u{AC01}", &["\u{AC01}", "\u{AC01}"]), + ("\u{AC01}\u{308}\u{AC01}", &["\u{AC01}\u{308}", "\u{AC01}"]), + ("\u{AC01}\u{1F1E6}", &["\u{AC01}", "\u{1F1E6}"]), + ("\u{AC01}\u{308}\u{1F1E6}", &["\u{AC01}\u{308}", "\u{1F1E6}"]), + ("\u{AC01}\u{378}", &["\u{AC01}", "\u{378}"]), + ("\u{AC01}\u{308}\u{378}", &["\u{AC01}\u{308}", "\u{378}"]), + ("\u{1F1E6}\u{20}", &["\u{1F1E6}", "\u{20}"]), + ("\u{1F1E6}\u{308}\u{20}", &["\u{1F1E6}\u{308}", "\u{20}"]), + ("\u{1F1E6}\u{D}", &["\u{1F1E6}", "\u{D}"]), + ("\u{1F1E6}\u{308}\u{D}", &["\u{1F1E6}\u{308}", "\u{D}"]), + ("\u{1F1E6}\u{A}", &["\u{1F1E6}", "\u{A}"]), + ("\u{1F1E6}\u{308}\u{A}", &["\u{1F1E6}\u{308}", "\u{A}"]), + ("\u{1F1E6}\u{1}", &["\u{1F1E6}", "\u{1}"]), + ("\u{1F1E6}\u{308}\u{1}", &["\u{1F1E6}\u{308}", "\u{1}"]), + ("\u{1F1E6}\u{300}", &["\u{1F1E6}\u{300}"]), + ("\u{1F1E6}\u{308}\u{300}", &["\u{1F1E6}\u{308}\u{300}"]), + ("\u{1F1E6}\u{1100}", &["\u{1F1E6}", "\u{1100}"]), + ("\u{1F1E6}\u{308}\u{1100}", &["\u{1F1E6}\u{308}", "\u{1100}"]), + ("\u{1F1E6}\u{1160}", &["\u{1F1E6}", "\u{1160}"]), + ("\u{1F1E6}\u{308}\u{1160}", &["\u{1F1E6}\u{308}", "\u{1160}"]), + ("\u{1F1E6}\u{11A8}", &["\u{1F1E6}", "\u{11A8}"]), + ("\u{1F1E6}\u{308}\u{11A8}", &["\u{1F1E6}\u{308}", "\u{11A8}"]), + ("\u{1F1E6}\u{AC00}", &["\u{1F1E6}", "\u{AC00}"]), + ("\u{1F1E6}\u{308}\u{AC00}", &["\u{1F1E6}\u{308}", "\u{AC00}"]), + ("\u{1F1E6}\u{AC01}", &["\u{1F1E6}", "\u{AC01}"]), + ("\u{1F1E6}\u{308}\u{AC01}", &["\u{1F1E6}\u{308}", "\u{AC01}"]), + ("\u{1F1E6}\u{1F1E6}", &["\u{1F1E6}\u{1F1E6}"]), + ("\u{1F1E6}\u{308}\u{1F1E6}", &["\u{1F1E6}\u{308}", "\u{1F1E6}"]), + ("\u{1F1E6}\u{378}", &["\u{1F1E6}", "\u{378}"]), + ("\u{1F1E6}\u{308}\u{378}", &["\u{1F1E6}\u{308}", "\u{378}"]), + ("\u{378}\u{20}", &["\u{378}", "\u{20}"]), + ("\u{378}\u{308}\u{20}", &["\u{378}\u{308}", "\u{20}"]), + ("\u{378}\u{D}", &["\u{378}", "\u{D}"]), + ("\u{378}\u{308}\u{D}", &["\u{378}\u{308}", "\u{D}"]), + ("\u{378}\u{A}", &["\u{378}", "\u{A}"]), + ("\u{378}\u{308}\u{A}", &["\u{378}\u{308}", "\u{A}"]), + ("\u{378}\u{1}", &["\u{378}", "\u{1}"]), + ("\u{378}\u{308}\u{1}", &["\u{378}\u{308}", "\u{1}"]), + ("\u{378}\u{300}", &["\u{378}\u{300}"]), + ("\u{378}\u{308}\u{300}", &["\u{378}\u{308}\u{300}"]), + ("\u{378}\u{1100}", &["\u{378}", "\u{1100}"]), + ("\u{378}\u{308}\u{1100}", &["\u{378}\u{308}", "\u{1100}"]), + ("\u{378}\u{1160}", &["\u{378}", "\u{1160}"]), + ("\u{378}\u{308}\u{1160}", &["\u{378}\u{308}", "\u{1160}"]), + ("\u{378}\u{11A8}", &["\u{378}", "\u{11A8}"]), + ("\u{378}\u{308}\u{11A8}", &["\u{378}\u{308}", "\u{11A8}"]), + ("\u{378}\u{AC00}", &["\u{378}", "\u{AC00}"]), + ("\u{378}\u{308}\u{AC00}", &["\u{378}\u{308}", "\u{AC00}"]), + ("\u{378}\u{AC01}", &["\u{378}", "\u{AC01}"]), + ("\u{378}\u{308}\u{AC01}", &["\u{378}\u{308}", "\u{AC01}"]), + ("\u{378}\u{1F1E6}", &["\u{378}", "\u{1F1E6}"]), + ("\u{378}\u{308}\u{1F1E6}", &["\u{378}\u{308}", "\u{1F1E6}"]), + ("\u{378}\u{378}", &["\u{378}", "\u{378}"]), + ("\u{378}\u{308}\u{378}", &["\u{378}\u{308}", "\u{378}"]), + ("\u{61}\u{1F1E6}\u{62}", &["\u{61}", "\u{1F1E6}", "\u{62}"]), + ("\u{1F1F7}\u{1F1FA}", &["\u{1F1F7}\u{1F1FA}"]), + ("\u{1F1F7}\u{1F1FA}\u{1F1F8}", &["\u{1F1F7}\u{1F1FA}\u{1F1F8}"]), + ("\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}", + &["\u{1F1F7}\u{1F1FA}\u{1F1F8}\u{1F1EA}"]), + ("\u{1F1F7}\u{1F1FA}\u{200B}\u{1F1F8}\u{1F1EA}", + &["\u{1F1F7}\u{1F1FA}", "\u{200B}", "\u{1F1F8}\u{1F1EA}"]), + ("\u{1F1E6}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{1F1E7}\u{1F1E8}"]), + ("\u{1F1E6}\u{200D}\u{1F1E7}\u{1F1E8}", &["\u{1F1E6}\u{200D}", + "\u{1F1E7}\u{1F1E8}"]), + ("\u{1F1E6}\u{1F1E7}\u{200D}\u{1F1E8}", + &["\u{1F1E6}\u{1F1E7}\u{200D}", "\u{1F1E8}"]), + ("\u{20}\u{200D}\u{646}", &["\u{20}\u{200D}", "\u{646}"]), + ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]), + ]; + + let test_diff: [(_, &[_], &[_]); 23] = [ + ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}", + &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}", + &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}", + &["\u{A}", "\u{308}\u{903}"], &["\u{A}", "\u{308}", "\u{903}"]), ("\u{1}\u{308}\u{903}", + &["\u{1}", "\u{308}\u{903}"], &["\u{1}", "\u{308}", "\u{903}"]), ("\u{300}\u{903}", + &["\u{300}\u{903}"], &["\u{300}", "\u{903}"]), ("\u{300}\u{308}\u{903}", + &["\u{300}\u{308}\u{903}"], &["\u{300}\u{308}", "\u{903}"]), ("\u{903}\u{903}", + &["\u{903}\u{903}"], &["\u{903}", "\u{903}"]), ("\u{903}\u{308}\u{903}", + &["\u{903}\u{308}\u{903}"], &["\u{903}\u{308}", "\u{903}"]), ("\u{1100}\u{903}", + &["\u{1100}\u{903}"], &["\u{1100}", "\u{903}"]), ("\u{1100}\u{308}\u{903}", + &["\u{1100}\u{308}\u{903}"], &["\u{1100}\u{308}", "\u{903}"]), ("\u{1160}\u{903}", + &["\u{1160}\u{903}"], &["\u{1160}", "\u{903}"]), ("\u{1160}\u{308}\u{903}", + &["\u{1160}\u{308}\u{903}"], &["\u{1160}\u{308}", "\u{903}"]), ("\u{11A8}\u{903}", + &["\u{11A8}\u{903}"], &["\u{11A8}", "\u{903}"]), ("\u{11A8}\u{308}\u{903}", + &["\u{11A8}\u{308}\u{903}"], &["\u{11A8}\u{308}", "\u{903}"]), ("\u{AC00}\u{903}", + &["\u{AC00}\u{903}"], &["\u{AC00}", "\u{903}"]), ("\u{AC00}\u{308}\u{903}", + &["\u{AC00}\u{308}\u{903}"], &["\u{AC00}\u{308}", "\u{903}"]), ("\u{AC01}\u{903}", + &["\u{AC01}\u{903}"], &["\u{AC01}", "\u{903}"]), ("\u{AC01}\u{308}\u{903}", + &["\u{AC01}\u{308}\u{903}"], &["\u{AC01}\u{308}", "\u{903}"]), ("\u{1F1E6}\u{903}", + &["\u{1F1E6}\u{903}"], &["\u{1F1E6}", "\u{903}"]), ("\u{1F1E6}\u{308}\u{903}", + &["\u{1F1E6}\u{308}\u{903}"], &["\u{1F1E6}\u{308}", "\u{903}"]), ("\u{378}\u{903}", + &["\u{378}\u{903}"], &["\u{378}", "\u{903}"]), ("\u{378}\u{308}\u{903}", + &["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]), + ]; + + for &(s, g) in &test_same[..] { + // test forward iterator + assert!(order::equals(s.graphemes(true), g.iter().cloned())); + assert!(order::equals(s.graphemes(false), g.iter().cloned())); + + // test reverse iterator + assert!(order::equals(s.graphemes(true).rev(), g.iter().rev().cloned())); + assert!(order::equals(s.graphemes(false).rev(), g.iter().rev().cloned())); + } + + for &(s, gt, gf) in &test_diff { + // test forward iterator + assert!(order::equals(s.graphemes(true), gt.iter().cloned())); + assert!(order::equals(s.graphemes(false), gf.iter().cloned())); + + // test reverse iterator + assert!(order::equals(s.graphemes(true).rev(), gt.iter().rev().cloned())); + assert!(order::equals(s.graphemes(false).rev(), gf.iter().rev().cloned())); + } + + // test the indices iterators + let s = "a̐éö̲\r\n"; + let gr_inds = s.grapheme_indices(true).collect::>(); + let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + assert_eq!(gr_inds, b); + let gr_inds = s.grapheme_indices(true).rev().collect::>(); + let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0, "a̐")]; + assert_eq!(gr_inds, b); + let mut gr_inds_iter = s.grapheme_indices(true); + { + let gr_inds = gr_inds_iter.by_ref(); + let e1 = gr_inds.size_hint(); + assert_eq!(e1, (1, Some(13))); + let c = gr_inds.count(); + assert_eq!(c, 4); + } + let e2 = gr_inds_iter.size_hint(); + assert_eq!(e2, (0, Some(0))); + + // make sure the reverse iterator does the right thing with "\n" at beginning of string + let s = "\n\r\n\r"; + let gr = s.graphemes(true).rev().collect::>(); + let b: &[_] = &["\r", "\r\n", "\n"]; + assert_eq!(gr, b); +} + +#[test] +fn test_splitator() { + fn t(s: &str, sep: &str, u: &[&str]) { + let v: Vec<&str> = s.split(sep).collect(); + assert_eq!(v, u); + } + t("--1233345--", "12345", &["--1233345--"]); + t("abc::hello::there", "::", &["abc", "hello", "there"]); + t("::hello::there", "::", &["", "hello", "there"]); + t("hello::there::", "::", &["hello", "there", ""]); + t("::hello::there::", "::", &["", "hello", "there", ""]); + t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); + t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); + t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); + t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); + t("", ".", &[""]); + t("zz", "zz", &["",""]); + t("ok", "z", &["ok"]); + t("zzz", "zz", &["","z"]); + t("zzzzz", "zz", &["","","z"]); +} + +#[test] +fn test_str_default() { + use std::default::Default; + + fn t>() { + let s: S = Default::default(); + assert_eq!(s.as_ref(), ""); + } + + t::<&str>(); + t::(); +} + +#[test] +fn test_str_container() { + fn sum_len(v: &[&str]) -> usize { + v.iter().map(|x| x.len()).sum() + } + + let s = String::from_str("01234"); + assert_eq!(5, sum_len(&["012", "", "34"])); + assert_eq!(5, sum_len(&[&String::from_str("01"), + &String::from_str("2"), + &String::from_str("34"), + &String::from_str("")])); + assert_eq!(5, sum_len(&[&s])); +} + +#[test] +fn test_str_from_utf8() { + let xs = b"hello"; + assert_eq!(from_utf8(xs), Ok("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF"; + assert_eq!(from_utf8(xs), Err(Utf8Error::TooShort)); +} + +mod bench { + use test::{Bencher, black_box}; + + #[bench] + fn char_iterator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().count()); + } + + #[bench] + fn char_iterator_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars() { black_box(ch); } + }); + } + + #[bench] + fn char_iterator_ascii(b: &mut Bencher) { + let s = "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"; + + b.iter(|| s.chars().count()); + } + + #[bench] + fn char_iterator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| s.chars().rev().count()); + } + + #[bench] + fn char_iterator_rev_for(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + + b.iter(|| { + for ch in s.chars().rev() { black_box(ch); } + }); + } + + #[bench] + fn char_indicesator(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().count(), len)); + } + + #[bench] + fn char_indicesator_rev(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let len = s.chars().count(); + + b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); + } + + #[bench] + fn split_unicode_ascii(b: &mut Bencher) { + let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; + + b.iter(|| assert_eq!(s.split('V').count(), 3)); + } + + #[bench] + fn split_ascii(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(' ').count(), len)); + } + + #[bench] + fn split_extern_fn(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + fn pred(c: char) -> bool { c == ' ' } + + b.iter(|| assert_eq!(s.split(pred).count(), len)); + } + + #[bench] + fn split_closure(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); + } + + #[bench] + fn split_slice(b: &mut Bencher) { + let s = "Mary had a little lamb, Little lamb, little-lamb."; + let len = s.split(' ').count(); + + let c: &[char] = &[' ']; + b.iter(|| assert_eq!(s.split(c).count(), len)); + } + + #[bench] + fn bench_connect(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + let sep = "→"; + let v = vec![s, s, s, s, s, s, s, s, s, s]; + b.iter(|| { + assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9); + }) + } + + #[bench] + fn bench_contains_short_short(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "sit"; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_short_long(b: &mut Bencher) { + let haystack = "\ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ +ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ +eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ +sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ +tempus vel, gravida nec quam. + +In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ +sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ +diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ +lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ +eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ +interdum. Curabitur ut nisi justo. + +Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ +mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ +lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ +est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ +felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ +ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ +feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ +Aliquam sit amet placerat lorem. + +Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ +mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ +Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ +lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ +suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ +cursus accumsan. + +Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ +feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ +vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ +leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ +malesuada sollicitudin quam eu fermentum."; + let needle = "english"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_bad_naive(b: &mut Bencher) { + let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let needle = "aaaaaaaab"; + + b.iter(|| { + assert!(!haystack.contains(needle)); + }) + } + + #[bench] + fn bench_contains_equal(b: &mut Bencher) { + let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + + b.iter(|| { + assert!(haystack.contains(needle)); + }) + } +} diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs new file mode 100644 index 0000000000..5d6aa8ac0d --- /dev/null +++ b/src/libcollectionstest/string.rs @@ -0,0 +1,453 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::{IntoCow, Cow}; +use std::iter::repeat; +use std::str::Utf8Error; +use std::string::as_string; + +use test::Bencher; + +#[test] +fn test_as_string() { + let x = "foo"; + assert_eq!(x, &**as_string(x)); +} + +#[test] +fn test_from_str() { + let owned: Option<::std::string::String> = "string".parse().ok(); + assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); +} + +#[test] +fn test_unsized_to_string() { + let s: &str = "abc"; + let _: String = (*s).to_string(); +} + +#[test] +fn test_from_utf8() { + let xs = b"hello".to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), + String::from_str("hello")); + + let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); + assert_eq!(String::from_utf8(xs).unwrap(), + String::from_str("ศไทย中华Việt Nam")); + + let xs = b"hello\xFF".to_vec(); + let err = String::from_utf8(xs).err().unwrap(); + assert_eq!(err.utf8_error(), Utf8Error::TooShort); + assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); +} + +#[test] +fn test_from_utf8_lossy() { + let xs = b"hello"; + let ys: Cow = "hello".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + let ys: Cow = "ศไทย中华Việt Nam".into_cow(); + assert_eq!(String::from_utf8_lossy(xs), ys); + + let xs = b"Hello\xC2 There\xFF Goodbye"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()); + + let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()); + + let xs = b"\xF5foo\xF5\x80bar"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()); + + let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()); + + let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; + assert_eq!(String::from_utf8_lossy(xs), + String::from_str("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()); + + let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; + assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\ + foo\u{10000}bar").into_cow()); + + // surrogates + let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; + assert_eq!(String::from_utf8_lossy(xs), String::from_str("\u{FFFD}\u{FFFD}\u{FFFD}foo\ + \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()); +} + +#[test] +fn test_from_utf16() { + let pairs = + [(String::from_str("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), + vec![0xd800, 0xdf45, 0xd800, 0xdf3f, + 0xd800, 0xdf3b, 0xd800, 0xdf46, + 0xd800, 0xdf39, 0xd800, 0xdf3b, + 0xd800, 0xdf30, 0x000a]), + + (String::from_str("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), + vec![0xd801, 0xdc12, 0xd801, + 0xdc49, 0xd801, 0xdc2e, 0xd801, + 0xdc40, 0xd801, 0xdc32, 0xd801, + 0xdc4b, 0x0020, 0xd801, 0xdc0f, + 0xd801, 0xdc32, 0xd801, 0xdc4d, + 0x000a]), + + (String::from_str("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), + vec![0xd800, 0xdf00, 0xd800, 0xdf16, + 0xd800, 0xdf0b, 0xd800, 0xdf04, + 0xd800, 0xdf11, 0xd800, 0xdf09, + 0x00b7, 0xd800, 0xdf0c, 0xd800, + 0xdf04, 0xd800, 0xdf15, 0xd800, + 0xdf04, 0xd800, 0xdf0b, 0xd800, + 0xdf09, 0xd800, 0xdf11, 0x000a ]), + + (String::from_str("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), + vec![0xd801, 0xdc8b, 0xd801, 0xdc98, + 0xd801, 0xdc88, 0xd801, 0xdc91, + 0xd801, 0xdc9b, 0xd801, 0xdc92, + 0x0020, 0xd801, 0xdc95, 0xd801, + 0xdc93, 0x0020, 0xd801, 0xdc88, + 0xd801, 0xdc9a, 0xd801, 0xdc8d, + 0x0020, 0xd801, 0xdc8f, 0xd801, + 0xdc9c, 0xd801, 0xdc92, 0xd801, + 0xdc96, 0xd801, 0xdc86, 0x0020, + 0xd801, 0xdc95, 0xd801, 0xdc86, + 0x000a ]), + // Issue #12318, even-numbered non-BMP planes + (String::from_str("\u{20000}"), + vec![0xD840, 0xDC00])]; + + for p in &pairs { + let (s, u) = (*p).clone(); + let s_as_utf16 = s.utf16_units().collect::>(); + let u_as_string = String::from_utf16(&u).unwrap(); + + assert!(::unicode::str::is_utf16(&u)); + assert_eq!(s_as_utf16, u); + + assert_eq!(u_as_string, s); + assert_eq!(String::from_utf16_lossy(&u), s); + + assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s); + assert_eq!(u_as_string.utf16_units().collect::>(), u); + } +} + +#[test] +fn test_utf16_invalid() { + // completely positive cases tested above. + // lead + eof + assert!(String::from_utf16(&[0xD800]).is_err()); + // lead + lead + assert!(String::from_utf16(&[0xD800, 0xD800]).is_err()); + + // isolated trail + assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err()); + + // general + assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err()); +} + +#[test] +fn test_from_utf16_lossy() { + // completely positive cases tested above. + // lead + eof + assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from_str("\u{FFFD}")); + // lead + lead + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), + String::from_str("\u{FFFD}\u{FFFD}")); + + // isolated trail + assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from_str("a\u{FFFD}")); + + // general + assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), + String::from_str("\u{FFFD}𐒋\u{FFFD}")); +} + +#[test] +fn test_push_bytes() { + let mut s = String::from_str("ABC"); + unsafe { + let mv = s.as_mut_vec(); + mv.push_all(&[b'D']); + } + assert_eq!(s, "ABCD"); +} + +#[test] +fn test_push_str() { + let mut s = String::new(); + s.push_str(""); + assert_eq!(&s[0..], ""); + s.push_str("abc"); + assert_eq!(&s[0..], "abc"); + s.push_str("ประเทศไทย中华Việt Nam"); + assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam"); +} + +#[test] +fn test_push() { + let mut data = String::from_str("ประเทศไทย中"); + data.push('华'); + data.push('b'); // 1 byte + data.push('¢'); // 2 byte + data.push('€'); // 3 byte + data.push('𤭢'); // 4 byte + assert_eq!(data, "ประเทศไทย中华b¢€𤭢"); +} + +#[test] +fn test_pop() { + let mut data = String::from_str("ประเทศไทย中华b¢€𤭢"); + assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes + assert_eq!(data.pop().unwrap(), '€'); // 3 bytes + assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes + assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes + assert_eq!(data.pop().unwrap(), '华'); + assert_eq!(data, "ประเทศไทย中"); +} + +#[test] +fn test_str_truncate() { + let mut s = String::from_str("12345"); + s.truncate(5); + assert_eq!(s, "12345"); + s.truncate(3); + assert_eq!(s, "123"); + s.truncate(0); + assert_eq!(s, ""); + + let mut s = String::from_str("12345"); + let p = s.as_ptr(); + s.truncate(3); + s.push_str("6"); + let p_ = s.as_ptr(); + assert_eq!(p_, p); +} + +#[test] +#[should_panic] +fn test_str_truncate_invalid_len() { + let mut s = String::from_str("12345"); + s.truncate(6); +} + +#[test] +#[should_panic] +fn test_str_truncate_split_codepoint() { + let mut s = String::from_str("\u{FC}"); // ü + s.truncate(1); +} + +#[test] +fn test_str_clear() { + let mut s = String::from_str("12345"); + s.clear(); + assert_eq!(s.len(), 0); + assert_eq!(s, ""); +} + +#[test] +fn test_str_add() { + let a = String::from_str("12345"); + let b = a + "2"; + let b = b + "2"; + assert_eq!(b.len(), 7); + assert_eq!(b, "1234522"); +} + +#[test] +fn remove() { + let mut s = "ศไทย中华Việt Nam; foobar".to_string();; + assert_eq!(s.remove(0), 'ศ'); + assert_eq!(s.len(), 33); + assert_eq!(s, "ไทย中华Việt Nam; foobar"); + assert_eq!(s.remove(17), 'ệ'); + assert_eq!(s, "ไทย中华Vit Nam; foobar"); +} + +#[test] #[should_panic] +fn remove_bad() { + "ศ".to_string().remove(1); +} + +#[test] +fn insert() { + let mut s = "foobar".to_string(); + s.insert(0, 'ệ'); + assert_eq!(s, "ệfoobar"); + s.insert(6, 'ย'); + assert_eq!(s, "ệfooยbar"); +} + +#[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); } +#[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); } + +#[test] +fn test_slicing() { + let s = "foobar".to_string(); + assert_eq!("foobar", &s[..]); + assert_eq!("foo", &s[..3]); + assert_eq!("bar", &s[3..]); + assert_eq!("oob", &s[1..4]); +} + +#[test] +fn test_simple_types() { + assert_eq!(1.to_string(), "1"); + assert_eq!((-1).to_string(), "-1"); + assert_eq!(200.to_string(), "200"); + assert_eq!(2.to_string(), "2"); + assert_eq!(true.to_string(), "true"); + assert_eq!(false.to_string(), "false"); + assert_eq!(("hi".to_string()).to_string(), "hi"); +} + +#[test] +fn test_vectors() { + let x: Vec = vec![]; + assert_eq!(format!("{:?}", x), "[]"); + assert_eq!(format!("{:?}", vec![1]), "[1]"); + assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); + assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == + "[[], [1], [1, 1]]"); +} + +#[test] +fn test_from_iterator() { + let s = "ศไทย中华Việt Nam".to_string(); + let t = "ศไทย中华"; + let u = "Việt Nam"; + + let a: String = s.chars().collect(); + assert_eq!(s, a); + + let mut b = t.to_string(); + b.extend(u.chars()); + assert_eq!(s, b); + + let c: String = vec![t, u].into_iter().collect(); + assert_eq!(s, c); + + let mut d = t.to_string(); + d.extend(vec![u].into_iter()); + assert_eq!(s, d); +} + +#[bench] +fn bench_with_capacity(b: &mut Bencher) { + b.iter(|| { + String::with_capacity(100) + }); +} + +#[bench] +fn bench_push_str(b: &mut Bencher) { + let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; + b.iter(|| { + let mut r = String::new(); + r.push_str(s); + }); +} + +const REPETITIONS: u64 = 10_000; + +#[bench] +fn bench_push_str_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push_str("a") + } + }); +} + +#[bench] +fn bench_push_char_one_byte(b: &mut Bencher) { + b.bytes = REPETITIONS; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('a') + } + }); +} + +#[bench] +fn bench_push_char_two_bytes(b: &mut Bencher) { + b.bytes = REPETITIONS * 2; + b.iter(|| { + let mut r = String::new(); + for _ in 0..REPETITIONS { + r.push('â') + } + }); +} + +#[bench] +fn from_utf8_lossy_100_ascii(b: &mut Bencher) { + let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { + let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); + assert_eq!(100, s.len()); + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_invalid(b: &mut Bencher) { + let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + b.iter(|| { + let _ = String::from_utf8_lossy(s); + }); +} + +#[bench] +fn from_utf8_lossy_100_invalid(b: &mut Bencher) { + let s = repeat(0xf5).take(100).collect::>(); + b.iter(|| { + let _ = String::from_utf8_lossy(&s); + }); +} + +#[bench] +fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { + let s = "Hello there, the quick brown fox jumped over the lazy dog! \ + Lorem ipsum dolor sit amet, consectetur. "; + // ensure our operation produces an exact-size string before we benchmark it + let mut r = String::with_capacity(s.len()); + r.push_str(s); + assert_eq!(r.len(), r.capacity()); + b.iter(|| { + let mut r = String::with_capacity(s.len()); + r.push_str(s); + r.shrink_to_fit(); + r + }); +} diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs new file mode 100644 index 0000000000..2923bea982 --- /dev/null +++ b/src/libcollectionstest/vec.rs @@ -0,0 +1,994 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter::{FromIterator, repeat}; +use std::mem::size_of; +use std::vec::as_vec; + +use test::Bencher; + +struct DropCounter<'a> { + count: &'a mut u32 +} + +#[unsafe_destructor] +impl<'a> Drop for DropCounter<'a> { + fn drop(&mut self) { + *self.count += 1; + } +} + +#[test] +fn test_as_vec() { + let xs = [1u8, 2u8, 3u8]; + assert_eq!(&**as_vec(&xs), xs); +} + +#[test] +fn test_as_vec_dtor() { + let (mut count_x, mut count_y) = (0, 0); + { + let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }]; + assert_eq!(as_vec(xs).len(), 2); + } + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); +} + +#[test] +fn test_small_vec_struct() { + assert!(size_of::>() == size_of::() * 3); +} + +#[test] +fn test_double_drop() { + struct TwoVec { + x: Vec, + y: Vec + } + + let (mut count_x, mut count_y) = (0, 0); + { + let mut tv = TwoVec { + x: Vec::new(), + y: Vec::new() + }; + tv.x.push(DropCounter {count: &mut count_x}); + tv.y.push(DropCounter {count: &mut count_y}); + + // If Vec had a drop flag, here is where it would be zeroed. + // Instead, it should rely on its internal state to prevent + // doing anything significant when dropped multiple times. + drop(tv.x); + + // Here tv goes out of scope, tv.y should be dropped, but not tv.x. + } + + assert_eq!(count_x, 1); + assert_eq!(count_y, 1); +} + +#[test] +fn test_reserve() { + let mut v = Vec::new(); + assert_eq!(v.capacity(), 0); + + v.reserve(2); + assert!(v.capacity() >= 2); + + for i in 0..16 { + v.push(i); + } + + assert!(v.capacity() >= 16); + v.reserve(16); + assert!(v.capacity() >= 32); + + v.push(16); + + v.reserve(16); + assert!(v.capacity() >= 33) +} + +#[test] +fn test_extend() { + let mut v = Vec::new(); + let mut w = Vec::new(); + + v.extend(0..3); + for i in 0..3 { w.push(i) } + + assert_eq!(v, w); + + v.extend(3..10); + for i in 3..10 { w.push(i) } + + assert_eq!(v, w); +} + +#[test] +fn test_slice_from_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let slice = &mut values[2 ..]; + assert!(slice == [3, 4, 5]); + for p in slice { + *p += 2; + } + } + + assert!(values == [1, 2, 5, 6, 7]); +} + +#[test] +fn test_slice_to_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let slice = &mut values[.. 2]; + assert!(slice == [1, 2]); + for p in slice { + *p += 1; + } + } + + assert!(values == [2, 3, 3, 4, 5]); +} + +#[test] +fn test_split_at_mut() { + let mut values = vec![1, 2, 3, 4, 5]; + { + let (left, right) = values.split_at_mut(2); + { + let left: &[_] = left; + assert!(&left[..left.len()] == &[1, 2]); + } + for p in left { + *p += 1; + } + + { + let right: &[_] = right; + assert!(&right[..right.len()] == &[3, 4, 5]); + } + for p in right { + *p += 2; + } + } + + assert_eq!(values, [2, 3, 5, 6, 7]); +} + +#[test] +fn test_clone() { + let v: Vec = vec![]; + let w = vec!(1, 2, 3); + + assert_eq!(v, v.clone()); + + let z = w.clone(); + assert_eq!(w, z); + // they should be disjoint in memory. + assert!(w.as_ptr() != z.as_ptr()) +} + +#[test] +fn test_clone_from() { + let mut v = vec!(); + let three: Vec> = vec!(box 1, box 2, box 3); + let two: Vec> = vec!(box 4, box 5); + // zero, long + v.clone_from(&three); + assert_eq!(v, three); + + // equal + v.clone_from(&three); + assert_eq!(v, three); + + // long, short + v.clone_from(&two); + assert_eq!(v, two); + + // short, long + v.clone_from(&three); + assert_eq!(v, three) +} + +#[test] +fn test_retain() { + let mut vec = vec![1, 2, 3, 4]; + vec.retain(|&x| x % 2 == 0); + assert_eq!(vec, [2, 4]); +} + +#[test] +fn zero_sized_values() { + let mut v = Vec::new(); + assert_eq!(v.len(), 0); + v.push(()); + assert_eq!(v.len(), 1); + v.push(()); + assert_eq!(v.len(), 2); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), Some(())); + assert_eq!(v.pop(), None); + + assert_eq!(v.iter().count(), 0); + v.push(()); + assert_eq!(v.iter().count(), 1); + v.push(()); + assert_eq!(v.iter().count(), 2); + + for &() in &v {} + + assert_eq!(v.iter_mut().count(), 2); + v.push(()); + assert_eq!(v.iter_mut().count(), 3); + v.push(()); + assert_eq!(v.iter_mut().count(), 4); + + for &mut () in &mut v {} + unsafe { v.set_len(0); } + assert_eq!(v.iter_mut().count(), 0); +} + +#[test] +fn test_partition() { + assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); + assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); +} + +#[test] +fn test_zip_unzip() { + let z1 = vec![(1, 4), (2, 5), (3, 6)]; + + let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip(); + + assert_eq!((1, 4), (left[0], right[0])); + assert_eq!((2, 5), (left[1], right[1])); + assert_eq!((3, 6), (left[2], right[2])); +} + +#[test] +fn test_unsafe_ptrs() { + unsafe { + // Test on-stack copy-from-buf. + let a = [1, 2, 3]; + let ptr = a.as_ptr(); + let b = Vec::from_raw_buf(ptr, 3); + assert_eq!(b, [1, 2, 3]); + + // Test on-heap copy-from-buf. + let c = vec![1, 2, 3, 4, 5]; + let ptr = c.as_ptr(); + let d = Vec::from_raw_buf(ptr, 5); + assert_eq!(d, [1, 2, 3, 4, 5]); + } +} + +#[test] +fn test_vec_truncate_drop() { + static mut drops: u32 = 0; + struct Elem(i32); + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; + assert_eq!(unsafe { drops }, 0); + v.truncate(3); + assert_eq!(unsafe { drops }, 2); + v.truncate(0); + assert_eq!(unsafe { drops }, 5); +} + +#[test] +#[should_panic] +fn test_vec_truncate_fail() { + struct BadElem(i32); + impl Drop for BadElem { + fn drop(&mut self) { + let BadElem(ref mut x) = *self; + if *x == 0xbadbeef { + panic!("BadElem panic: 0xbadbeef") + } + } + } + + let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; + v.truncate(0); +} + +#[test] +fn test_index() { + let vec = vec![1, 2, 3]; + assert!(vec[1] == 2); +} + +#[test] +#[should_panic] +fn test_index_out_of_bounds() { + let vec = vec![1, 2, 3]; + let _ = vec[3]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_1() { + let x = vec![1, 2, 3, 4, 5]; + &x[-1..]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_2() { + let x = vec![1, 2, 3, 4, 5]; + &x[..6]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_3() { + let x = vec![1, 2, 3, 4, 5]; + &x[-1..4]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_4() { + let x = vec![1, 2, 3, 4, 5]; + &x[1..6]; +} + +#[test] +#[should_panic] +fn test_slice_out_of_bounds_5() { + let x = vec![1, 2, 3, 4, 5]; + &x[3..2]; +} + +#[test] +#[should_panic] +fn test_swap_remove_empty() { + let mut vec= Vec::::new(); + vec.swap_remove(0); +} + +#[test] +fn test_move_iter_unwrap() { + let mut vec = Vec::with_capacity(7); + vec.push(1); + vec.push(2); + let ptr = vec.as_ptr(); + vec = vec.into_iter().into_inner(); + assert_eq!(vec.as_ptr(), ptr); + assert_eq!(vec.capacity(), 7); + assert_eq!(vec.len(), 0); +} + +#[test] +#[should_panic] +fn test_map_in_place_incompatible_types_fail() { + let v = vec![0, 1, 2]; + v.map_in_place(|_| ()); +} + +#[test] +fn test_map_in_place() { + let v = vec![0, 1, 2]; + assert_eq!(v.map_in_place(|i: u32| i as i32 - 1), [-1, 0, 1]); +} + +#[test] +fn test_map_in_place_zero_sized() { + let v = vec![(), ()]; + #[derive(PartialEq, Debug)] + struct ZeroSized; + assert_eq!(v.map_in_place(|_| ZeroSized), [ZeroSized, ZeroSized]); +} + +#[test] +fn test_map_in_place_zero_drop_count() { + use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + + #[derive(Clone, PartialEq, Debug)] + struct Nothing; + impl Drop for Nothing { fn drop(&mut self) { } } + + #[derive(Clone, PartialEq, Debug)] + struct ZeroSized; + impl Drop for ZeroSized { + fn drop(&mut self) { + DROP_COUNTER.fetch_add(1, Ordering::Relaxed); + } + } + const NUM_ELEMENTS: usize = 2; + static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + + let v = repeat(Nothing).take(NUM_ELEMENTS).collect::>(); + + DROP_COUNTER.store(0, Ordering::Relaxed); + + let v = v.map_in_place(|_| ZeroSized); + assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), 0); + drop(v); + assert_eq!(DROP_COUNTER.load(Ordering::Relaxed), NUM_ELEMENTS); +} + +#[test] +fn test_move_items() { + let vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec { + vec2.push(i); + } + assert_eq!(vec2, [1, 2, 3]); +} + +#[test] +fn test_move_items_reverse() { + let vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.into_iter().rev() { + vec2.push(i); + } + assert_eq!(vec2, [3, 2, 1]); +} + +#[test] +fn test_move_items_zero_sized() { + let vec = vec![(), (), ()]; + let mut vec2 = vec![]; + for i in vec { + vec2.push(i); + } + assert_eq!(vec2, [(), (), ()]); +} + +#[test] +fn test_drain_items() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.drain() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [ 1, 2, 3 ]); +} + +#[test] +fn test_drain_items_reverse() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![]; + for i in vec.drain().rev() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [3, 2, 1]); +} + +#[test] +fn test_drain_items_zero_sized() { + let mut vec = vec![(), (), ()]; + let mut vec2 = vec![]; + for i in vec.drain() { + vec2.push(i); + } + assert_eq!(vec, []); + assert_eq!(vec2, [(), (), ()]); +} + +#[test] +fn test_into_boxed_slice() { + let xs = vec![1, 2, 3]; + let ys = xs.into_boxed_slice(); + assert_eq!(&*ys, [1, 2, 3]); +} + +#[test] +fn test_append() { + let mut vec = vec![1, 2, 3]; + let mut vec2 = vec![4, 5, 6]; + vec.append(&mut vec2); + assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + assert_eq!(vec2, []); +} + +#[test] +fn test_split_off() { + let mut vec = vec![1, 2, 3, 4, 5, 6]; + let vec2 = vec.split_off(4); + assert_eq!(vec, [1, 2, 3, 4]); + assert_eq!(vec2, [5, 6]); +} + +#[bench] +fn bench_new(b: &mut Bencher) { + b.iter(|| { + let v: Vec = Vec::new(); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), 0); + }) +} + +fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let v: Vec = Vec::with_capacity(src_len); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), src_len); + }) +} + +#[bench] +fn bench_with_capacity_0000(b: &mut Bencher) { + do_bench_with_capacity(b, 0) +} + +#[bench] +fn bench_with_capacity_0010(b: &mut Bencher) { + do_bench_with_capacity(b, 10) +} + +#[bench] +fn bench_with_capacity_0100(b: &mut Bencher) { + do_bench_with_capacity(b, 100) +} + +#[bench] +fn bench_with_capacity_1000(b: &mut Bencher) { + do_bench_with_capacity(b, 1000) +} + +fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let dst = (0..src_len).collect::>(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }) +} + +#[bench] +fn bench_from_fn_0000(b: &mut Bencher) { + do_bench_from_fn(b, 0) +} + +#[bench] +fn bench_from_fn_0010(b: &mut Bencher) { + do_bench_from_fn(b, 10) +} + +#[bench] +fn bench_from_fn_0100(b: &mut Bencher) { + do_bench_from_fn(b, 100) +} + +#[bench] +fn bench_from_fn_1000(b: &mut Bencher) { + do_bench_from_fn(b, 1000) +} + +fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec = repeat(5).take(src_len).collect(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().all(|x| *x == 5)); + }) +} + +#[bench] +fn bench_from_elem_0000(b: &mut Bencher) { + do_bench_from_elem(b, 0) +} + +#[bench] +fn bench_from_elem_0010(b: &mut Bencher) { + do_bench_from_elem(b, 10) +} + +#[bench] +fn bench_from_elem_0100(b: &mut Bencher) { + do_bench_from_elem(b, 100) +} + +#[bench] +fn bench_from_elem_1000(b: &mut Bencher) { + do_bench_from_elem(b, 1000) +} + +fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst = src.clone()[..].to_vec(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_from_slice_0000(b: &mut Bencher) { + do_bench_from_slice(b, 0) +} + +#[bench] +fn bench_from_slice_0010(b: &mut Bencher) { + do_bench_from_slice(b, 10) +} + +#[bench] +fn bench_from_slice_0100(b: &mut Bencher) { + do_bench_from_slice(b, 100) +} + +#[bench] +fn bench_from_slice_1000(b: &mut Bencher) { + do_bench_from_slice(b, 1000) +} + +fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { + let src: Vec<_> = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst: Vec<_> = FromIterator::from_iter(src.clone().into_iter()); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_from_iter_0000(b: &mut Bencher) { + do_bench_from_iter(b, 0) +} + +#[bench] +fn bench_from_iter_0010(b: &mut Bencher) { + do_bench_from_iter(b, 10) +} + +#[bench] +fn bench_from_iter_0100(b: &mut Bencher) { + do_bench_from_iter(b, 100) +} + +#[bench] +fn bench_from_iter_1000(b: &mut Bencher) { + do_bench_from_iter(b, 1000) +} + +fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone().into_iter()); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_extend_0000_0000(b: &mut Bencher) { + do_bench_extend(b, 0, 0) +} + +#[bench] +fn bench_extend_0000_0010(b: &mut Bencher) { + do_bench_extend(b, 0, 10) +} + +#[bench] +fn bench_extend_0000_0100(b: &mut Bencher) { + do_bench_extend(b, 0, 100) +} + +#[bench] +fn bench_extend_0000_1000(b: &mut Bencher) { + do_bench_extend(b, 0, 1000) +} + +#[bench] +fn bench_extend_0010_0010(b: &mut Bencher) { + do_bench_extend(b, 10, 10) +} + +#[bench] +fn bench_extend_0100_0100(b: &mut Bencher) { + do_bench_extend(b, 100, 100) +} + +#[bench] +fn bench_extend_1000_1000(b: &mut Bencher) { + do_bench_extend(b, 1000, 1000) +} + +fn do_bench_push_all(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.push_all(&src); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_push_all_0000_0000(b: &mut Bencher) { + do_bench_push_all(b, 0, 0) +} + +#[bench] +fn bench_push_all_0000_0010(b: &mut Bencher) { + do_bench_push_all(b, 0, 10) +} + +#[bench] +fn bench_push_all_0000_0100(b: &mut Bencher) { + do_bench_push_all(b, 0, 100) +} + +#[bench] +fn bench_push_all_0000_1000(b: &mut Bencher) { + do_bench_push_all(b, 0, 1000) +} + +#[bench] +fn bench_push_all_0010_0010(b: &mut Bencher) { + do_bench_push_all(b, 10, 10) +} + +#[bench] +fn bench_push_all_0100_0100(b: &mut Bencher) { + do_bench_push_all(b, 100, 100) +} + +#[bench] +fn bench_push_all_1000_1000(b: &mut Bencher) { + do_bench_push_all(b, 1000, 1000) +} + +fn do_bench_push_all_move(b: &mut Bencher, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..dst_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let mut dst = dst.clone(); + dst.extend(src.clone().into_iter()); + assert_eq!(dst.len(), dst_len + src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_push_all_move_0000_0000(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 0) +} + +#[bench] +fn bench_push_all_move_0000_0010(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 10) +} + +#[bench] +fn bench_push_all_move_0000_0100(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 100) +} + +#[bench] +fn bench_push_all_move_0000_1000(b: &mut Bencher) { + do_bench_push_all_move(b, 0, 1000) +} + +#[bench] +fn bench_push_all_move_0010_0010(b: &mut Bencher) { + do_bench_push_all_move(b, 10, 10) +} + +#[bench] +fn bench_push_all_move_0100_0100(b: &mut Bencher) { + do_bench_push_all_move(b, 100, 100) +} + +#[bench] +fn bench_push_all_move_1000_1000(b: &mut Bencher) { + do_bench_push_all_move(b, 1000, 1000) +} + +fn do_bench_clone(b: &mut Bencher, src_len: usize) { + let src: Vec = FromIterator::from_iter(0..src_len); + + b.bytes = src_len as u64; + + b.iter(|| { + let dst = src.clone(); + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| i == *x)); + }); +} + +#[bench] +fn bench_clone_0000(b: &mut Bencher) { + do_bench_clone(b, 0) +} + +#[bench] +fn bench_clone_0010(b: &mut Bencher) { + do_bench_clone(b, 10) +} + +#[bench] +fn bench_clone_0100(b: &mut Bencher) { + do_bench_clone(b, 100) +} + +#[bench] +fn bench_clone_1000(b: &mut Bencher) { + do_bench_clone(b, 1000) +} + +fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { + let dst: Vec<_> = FromIterator::from_iter(0..src_len); + let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); + + b.bytes = (times * src_len) as u64; + + b.iter(|| { + let mut dst = dst.clone(); + + for _ in 0..times { + dst.clone_from(&src); + + assert_eq!(dst.len(), src_len); + assert!(dst.iter().enumerate().all(|(i, x)| dst_len + i == *x)); + } + }); +} + +#[bench] +fn bench_clone_from_01_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 0) +} + +#[bench] +fn bench_clone_from_01_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 10) +} + +#[bench] +fn bench_clone_from_01_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 100) +} + +#[bench] +fn bench_clone_from_01_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 0, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 10) +} + +#[bench] +fn bench_clone_from_01_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 100) +} + +#[bench] +fn bench_clone_from_01_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 100) +} + +#[bench] +fn bench_clone_from_01_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 1000) +} + +#[bench] +fn bench_clone_from_01_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 1, 10, 0) +} + +#[bench] +fn bench_clone_from_01_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 1, 100, 10) +} + +#[bench] +fn bench_clone_from_01_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 1, 1000, 100) +} + +#[bench] +fn bench_clone_from_10_0000_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 0) +} + +#[bench] +fn bench_clone_from_10_0000_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 10) +} + +#[bench] +fn bench_clone_from_10_0000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 100) +} + +#[bench] +fn bench_clone_from_10_0000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 0, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 10) +} + +#[bench] +fn bench_clone_from_10_0100_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 100) +} + +#[bench] +fn bench_clone_from_10_1000_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 100) +} + +#[bench] +fn bench_clone_from_10_0100_1000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 1000) +} + +#[bench] +fn bench_clone_from_10_0010_0000(b: &mut Bencher) { + do_bench_clone_from(b, 10, 10, 0) +} + +#[bench] +fn bench_clone_from_10_0100_0010(b: &mut Bencher) { + do_bench_clone_from(b, 10, 100, 10) +} + +#[bench] +fn bench_clone_from_10_1000_0100(b: &mut Bencher) { + do_bench_clone_from(b, 10, 1000, 100) +} diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs new file mode 100644 index 0000000000..12323286f6 --- /dev/null +++ b/src/libcollectionstest/vec_deque.rs @@ -0,0 +1,887 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::VecDeque; +use std::fmt::Debug; +use std::hash::{SipHasher, self}; + +use test; + +use self::Taggy::*; +use self::Taggypar::*; + +#[test] +fn test_simple() { + let mut d = VecDeque::new(); + assert_eq!(d.len(), 0); + d.push_front(17); + d.push_front(42); + d.push_back(137); + assert_eq!(d.len(), 3); + d.push_back(137); + assert_eq!(d.len(), 4); + assert_eq!(*d.front().unwrap(), 42); + assert_eq!(*d.back().unwrap(), 137); + let mut i = d.pop_front(); + assert_eq!(i, Some(42)); + i = d.pop_back(); + assert_eq!(i, Some(137)); + i = d.pop_back(); + assert_eq!(i, Some(137)); + i = d.pop_back(); + assert_eq!(i, Some(17)); + assert_eq!(d.len(), 0); + d.push_back(3); + assert_eq!(d.len(), 1); + d.push_front(2); + assert_eq!(d.len(), 2); + d.push_back(4); + assert_eq!(d.len(), 3); + d.push_front(1); + assert_eq!(d.len(), 4); + debug!("{}", d[0]); + debug!("{}", d[1]); + debug!("{}", d[2]); + debug!("{}", d[3]); + assert_eq!(d[0], 1); + assert_eq!(d[1], 2); + assert_eq!(d[2], 3); + assert_eq!(d[3], 4); +} + +#[cfg(test)] +fn test_parameterized(a: T, b: T, c: T, d: T) { + let mut deq = VecDeque::new(); + assert_eq!(deq.len(), 0); + deq.push_front(a.clone()); + deq.push_front(b.clone()); + deq.push_back(c.clone()); + assert_eq!(deq.len(), 3); + deq.push_back(d.clone()); + assert_eq!(deq.len(), 4); + assert_eq!((*deq.front().unwrap()).clone(), b.clone()); + assert_eq!((*deq.back().unwrap()).clone(), d.clone()); + assert_eq!(deq.pop_front().unwrap(), b.clone()); + assert_eq!(deq.pop_back().unwrap(), d.clone()); + assert_eq!(deq.pop_back().unwrap(), c.clone()); + assert_eq!(deq.pop_back().unwrap(), a.clone()); + assert_eq!(deq.len(), 0); + deq.push_back(c.clone()); + assert_eq!(deq.len(), 1); + deq.push_front(b.clone()); + assert_eq!(deq.len(), 2); + deq.push_back(d.clone()); + assert_eq!(deq.len(), 3); + deq.push_front(a.clone()); + assert_eq!(deq.len(), 4); + assert_eq!(deq[0].clone(), a.clone()); + assert_eq!(deq[1].clone(), b.clone()); + assert_eq!(deq[2].clone(), c.clone()); + assert_eq!(deq[3].clone(), d.clone()); +} + +#[test] +fn test_push_front_grow() { + let mut deq = VecDeque::new(); + for i in 0..66 { + deq.push_front(i); + } + assert_eq!(deq.len(), 66); + + for i in 0..66 { + assert_eq!(deq[i], 65 - i); + } + + let mut deq = VecDeque::new(); + for i in 0..66 { + deq.push_back(i); + } + + for i in 0..66 { + assert_eq!(deq[i], i); + } +} + +#[test] +fn test_index() { + let mut deq = VecDeque::new(); + for i in 1..4 { + deq.push_front(i); + } + assert_eq!(deq[1], 2); +} + +#[test] +#[should_panic] +fn test_index_out_of_bounds() { + let mut deq = VecDeque::new(); + for i in 1..4 { + deq.push_front(i); + } + deq[3]; +} + +#[bench] +fn bench_new(b: &mut test::Bencher) { + b.iter(|| { + let ring: VecDeque = VecDeque::new(); + test::black_box(ring); + }) +} + +#[bench] +fn bench_grow_1025(b: &mut test::Bencher) { + b.iter(|| { + let mut deq = VecDeque::new(); + for i in 0..1025 { + deq.push_front(i); + } + test::black_box(deq); + }) +} + +#[bench] +fn bench_iter_1000(b: &mut test::Bencher) { + let ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for &i in &ring { + sum += i; + } + test::black_box(sum); + }) +} + +#[bench] +fn bench_mut_iter_1000(b: &mut test::Bencher) { + let mut ring: VecDeque<_> = (0..1000).collect(); + + b.iter(|| { + let mut sum = 0; + for i in &mut ring { + sum += *i; + } + test::black_box(sum); + }) +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggy { + One(i32), + Two(i32, i32), + Three(i32, i32, i32), +} + +#[derive(Clone, PartialEq, Debug)] +enum Taggypar { + Onepar(T), + Twopar(T, T), + Threepar(T, T, T), +} + +#[derive(Clone, PartialEq, Debug)] +struct RecCy { + x: i32, + y: i32, + t: Taggy +} + +#[test] +fn test_param_int() { + test_parameterized::(5, 72, 64, 175); +} + +#[test] +fn test_param_taggy() { + test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); +} + +#[test] +fn test_param_taggypar() { + test_parameterized::>(Onepar::(1), + Twopar::(1, 2), + Threepar::(1, 2, 3), + Twopar::(17, 42)); +} + +#[test] +fn test_param_reccy() { + let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; + let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; + let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; + let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; + test_parameterized::(reccy1, reccy2, reccy3, reccy4); +} + +#[test] +fn test_with_capacity() { + let mut d = VecDeque::with_capacity(0); + d.push_back(1); + assert_eq!(d.len(), 1); + let mut d = VecDeque::with_capacity(50); + d.push_back(1); + assert_eq!(d.len(), 1); +} + +#[test] +fn test_with_capacity_non_power_two() { + let mut d3 = VecDeque::with_capacity(3); + d3.push_back(1); + + // X = None, | = lo + // [|1, X, X] + assert_eq!(d3.pop_front(), Some(1)); + // [X, |X, X] + assert_eq!(d3.front(), None); + + // [X, |3, X] + d3.push_back(3); + // [X, |3, 6] + d3.push_back(6); + // [X, X, |6] + assert_eq!(d3.pop_front(), Some(3)); + + // Pushing the lo past half way point to trigger + // the 'B' scenario for growth + // [9, X, |6] + d3.push_back(9); + // [9, 12, |6] + d3.push_back(12); + + d3.push_back(15); + // There used to be a bug here about how the + // VecDeque made growth assumptions about the + // underlying Vec which didn't hold and lead + // to corruption. + // (Vec grows to next power of two) + //good- [9, 12, 15, X, X, X, X, |6] + //bug- [15, 12, X, X, X, |6, X, X] + assert_eq!(d3.pop_front(), Some(6)); + + // Which leads us to the following state which + // would be a failure case. + //bug- [15, 12, X, X, X, X, |X, X] + assert_eq!(d3.front(), Some(&9)); +} + +#[test] +fn test_reserve_exact() { + let mut d = VecDeque::new(); + d.push_back(0); + d.reserve_exact(50); + assert!(d.capacity() >= 51); +} + +#[test] +fn test_reserve() { + let mut d = VecDeque::new(); + d.push_back(0); + d.reserve(50); + assert!(d.capacity() >= 51); +} + +#[test] +fn test_swap() { + let mut d: VecDeque<_> = (0..5).collect(); + d.pop_front(); + d.swap(0, 3); + assert_eq!(d.iter().cloned().collect::>(), [4, 2, 3, 1]); +} + +#[test] +fn test_iter() { + let mut d = VecDeque::new(); + assert_eq!(d.iter().next(), None); + assert_eq!(d.iter().size_hint(), (0, Some(0))); + + for i in 0..5 { + d.push_back(i); + } + { + let b: &[_] = &[&0,&1,&2,&3,&4]; + assert_eq!(d.iter().collect::>(), b); + } + + for i in 6..9 { + d.push_front(i); + } + { + let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; + assert_eq!(d.iter().collect::>(), b); + } + + let mut it = d.iter(); + let mut len = d.len(); + loop { + match it.next() { + None => break, + _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } + } + } +} + +#[test] +fn test_rev_iter() { + let mut d = VecDeque::new(); + assert_eq!(d.iter().rev().next(), None); + + for i in 0..5 { + d.push_back(i); + } + { + let b: &[_] = &[&4,&3,&2,&1,&0]; + assert_eq!(d.iter().rev().collect::>(), b); + } + + for i in 6..9 { + d.push_front(i); + } + let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; + assert_eq!(d.iter().rev().collect::>(), b); +} + +#[test] +fn test_mut_rev_iter_wrap() { + let mut d = VecDeque::with_capacity(3); + assert!(d.iter_mut().rev().next().is_none()); + + d.push_back(1); + d.push_back(2); + d.push_back(3); + assert_eq!(d.pop_front(), Some(1)); + d.push_back(4); + + assert_eq!(d.iter_mut().rev().map(|x| *x).collect::>(), + vec![4, 3, 2]); +} + +#[test] +fn test_mut_iter() { + let mut d = VecDeque::new(); + assert!(d.iter_mut().next().is_none()); + + for i in 0..3 { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().enumerate() { + assert_eq!(*elt, 2 - i); + *elt = i; + } + + { + let mut it = d.iter_mut(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } +} + +#[test] +fn test_mut_rev_iter() { + let mut d = VecDeque::new(); + assert!(d.iter_mut().rev().next().is_none()); + + for i in 0..3 { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().rev().enumerate() { + assert_eq!(*elt, i); + *elt = i; + } + + { + let mut it = d.iter_mut().rev(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } +} + +#[test] +fn test_into_iter() { + + // Empty iter + { + let d: VecDeque = VecDeque::new(); + let mut iter = d.into_iter(); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + // simple iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + + let b = vec![0,1,2,3,4]; + assert_eq!(d.into_iter().collect::>(), b); + } + + // wrapped iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + let b = vec![8,7,6,0,1,2,3,4]; + assert_eq!(d.into_iter().collect::>(), b); + } + + // partially used + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + let mut it = d.into_iter(); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } +} + +#[test] +fn test_drain() { + + // Empty iter + { + let mut d: VecDeque = VecDeque::new(); + + { + let mut iter = d.drain(); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert!(d.is_empty()); + } + + // simple iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + + assert_eq!(d.drain().collect::>(), [0, 1, 2, 3, 4]); + assert!(d.is_empty()); + } + + // wrapped iter + { + let mut d = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + assert_eq!(d.drain().collect::>(), [8,7,6,0,1,2,3,4]); + assert!(d.is_empty()); + } + + // partially used + { + let mut d: VecDeque<_> = VecDeque::new(); + for i in 0..5 { + d.push_back(i); + } + for i in 6..9 { + d.push_front(i); + } + + { + let mut it = d.drain(); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } + assert!(d.is_empty()); + } +} + +#[test] +fn test_from_iter() { + use std::iter; + + let v = vec!(1,2,3,4,5,6,7); + let deq: VecDeque<_> = v.iter().cloned().collect(); + let u: Vec<_> = deq.iter().cloned().collect(); + assert_eq!(u, v); + + let seq = (0..).step_by(2).take(256); + let deq: VecDeque<_> = seq.collect(); + for (i, &x) in deq.iter().enumerate() { + assert_eq!(2*i, x); + } + assert_eq!(deq.len(), 256); +} + +#[test] +fn test_clone() { + let mut d = VecDeque::new(); + d.push_front(17); + d.push_front(42); + d.push_back(137); + d.push_back(137); + assert_eq!(d.len(), 4); + let mut e = d.clone(); + assert_eq!(e.len(), 4); + while !d.is_empty() { + assert_eq!(d.pop_back(), e.pop_back()); + } + assert_eq!(d.len(), 0); + assert_eq!(e.len(), 0); +} + +#[test] +fn test_eq() { + let mut d = VecDeque::new(); + assert!(d == VecDeque::with_capacity(0)); + d.push_front(137); + d.push_front(17); + d.push_front(42); + d.push_back(137); + let mut e = VecDeque::with_capacity(0); + e.push_back(42); + e.push_back(17); + e.push_back(137); + e.push_back(137); + assert!(&e == &d); + e.pop_back(); + e.push_back(0); + assert!(e != d); + e.clear(); + assert!(e == VecDeque::new()); +} + +#[test] +fn test_hash() { + let mut x = VecDeque::new(); + let mut y = VecDeque::new(); + + x.push_back(1); + x.push_back(2); + x.push_back(3); + + y.push_back(0); + y.push_back(1); + y.pop_front(); + y.push_back(2); + y.push_back(3); + + assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_ord() { + let x = VecDeque::new(); + let mut y = VecDeque::new(); + y.push_back(1); + y.push_back(2); + y.push_back(3); + assert!(x < y); + assert!(y > x); + assert!(x <= x); + assert!(x >= x); +} + +#[test] +fn test_show() { + let ringbuf: VecDeque<_> = (0..10).collect(); + assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter() + .cloned() + .collect(); + assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); +} + +#[test] +fn test_drop() { + static mut drops: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + drop(ring); + + assert_eq!(unsafe {drops}, 4); +} + +#[test] +fn test_drop_with_pop() { + static mut drops: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + + drop(ring.pop_back()); + drop(ring.pop_front()); + assert_eq!(unsafe {drops}, 2); + + drop(ring); + assert_eq!(unsafe {drops}, 4); +} + +#[test] +fn test_drop_clear() { + static mut drops: i32 = 0; + struct Elem; + impl Drop for Elem { + fn drop(&mut self) { + unsafe { drops += 1; } + } + } + + let mut ring = VecDeque::new(); + ring.push_back(Elem); + ring.push_front(Elem); + ring.push_back(Elem); + ring.push_front(Elem); + ring.clear(); + assert_eq!(unsafe {drops}, 4); + + drop(ring); + assert_eq!(unsafe {drops}, 4); +} + +#[test] +fn test_reserve_grow() { + // test growth path A + // [T o o H] -> [T o o H . . . . ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } + + // test growth path B + // [H T o o] -> [. T o o H . . . ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..1 { + ring.push_back(i); + assert_eq!(ring.pop_front(), Some(i)); + } + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } + + // test growth path C + // [o o H T] -> [o o H . . . . T ] + let mut ring = VecDeque::with_capacity(4); + for i in 0..3 { + ring.push_back(i); + assert_eq!(ring.pop_front(), Some(i)); + } + for i in 0..3 { + ring.push_back(i); + } + ring.reserve(7); + for i in 0..3 { + assert_eq!(ring.pop_front(), Some(i)); + } +} + +#[test] +fn test_get() { + let mut ring = VecDeque::new(); + ring.push_back(0); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), None); + + ring.push_back(1); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), Some(&1)); + assert_eq!(ring.get(2), None); + + ring.push_back(2); + assert_eq!(ring.get(0), Some(&0)); + assert_eq!(ring.get(1), Some(&1)); + assert_eq!(ring.get(2), Some(&2)); + assert_eq!(ring.get(3), None); + + assert_eq!(ring.pop_front(), Some(0)); + assert_eq!(ring.get(0), Some(&1)); + assert_eq!(ring.get(1), Some(&2)); + assert_eq!(ring.get(2), None); + + assert_eq!(ring.pop_front(), Some(1)); + assert_eq!(ring.get(0), Some(&2)); + assert_eq!(ring.get(1), None); + + assert_eq!(ring.pop_front(), Some(2)); + assert_eq!(ring.get(0), None); + assert_eq!(ring.get(1), None); +} + +#[test] +fn test_get_mut() { + let mut ring = VecDeque::new(); + for i in 0..3 { + ring.push_back(i); + } + + match ring.get_mut(1) { + Some(x) => *x = -1, + None => () + }; + + assert_eq!(ring.get_mut(0), Some(&mut 0)); + assert_eq!(ring.get_mut(1), Some(&mut -1)); + assert_eq!(ring.get_mut(2), Some(&mut 2)); + assert_eq!(ring.get_mut(3), None); + + assert_eq!(ring.pop_front(), Some(0)); + assert_eq!(ring.get_mut(0), Some(&mut -1)); + assert_eq!(ring.get_mut(1), Some(&mut 2)); + assert_eq!(ring.get_mut(2), None); +} + +#[test] +fn test_front() { + let mut ring = VecDeque::new(); + ring.push_back(10); + ring.push_back(20); + assert_eq!(ring.front(), Some(&10)); + ring.pop_front(); + assert_eq!(ring.front(), Some(&20)); + ring.pop_front(); + assert_eq!(ring.front(), None); +} + +#[test] +fn test_as_slices() { + let mut ring: VecDeque = VecDeque::with_capacity(127); + let cap = ring.capacity() as i32; + let first = cap/2; + let last = cap - first; + for i in 0..first { + ring.push_back(i); + + let (left, right) = ring.as_slices(); + let expected: Vec<_> = (0..i+1).collect(); + assert_eq!(left, &expected[..]); + assert_eq!(right, []); + } + + for j in -last..0 { + ring.push_front(j); + let (left, right) = ring.as_slices(); + let expected_left: Vec<_> = (-last..j+1).rev().collect(); + let expected_right: Vec<_> = (0..first).collect(); + assert_eq!(left, &expected_left[..]); + assert_eq!(right, &expected_right[..]); + } + + assert_eq!(ring.len() as i32, cap); + assert_eq!(ring.capacity() as i32, cap); +} + +#[test] +fn test_as_mut_slices() { + let mut ring: VecDeque = VecDeque::with_capacity(127); + let cap = ring.capacity() as i32; + let first = cap/2; + let last = cap - first; + for i in 0..first { + ring.push_back(i); + + let (left, right) = ring.as_mut_slices(); + let expected: Vec<_> = (0..i+1).collect(); + assert_eq!(left, &expected[..]); + assert_eq!(right, []); + } + + for j in -last..0 { + ring.push_front(j); + let (left, right) = ring.as_mut_slices(); + let expected_left: Vec<_> = (-last..j+1).rev().collect(); + let expected_right: Vec<_> = (0..first).collect(); + assert_eq!(left, &expected_left[..]); + assert_eq!(right, &expected_right[..]); + } + + assert_eq!(ring.len() as i32, cap); + assert_eq!(ring.capacity() as i32, cap); +} + +#[test] +fn test_append() { + let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); + let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); + + // normal append + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::>(), []); + + // append nothing to something + a.append(&mut b); + assert_eq!(a.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(b.iter().cloned().collect::>(), []); + + // append something to nothing + b.append(&mut a); + assert_eq!(b.iter().cloned().collect::>(), [1, 2, 3, 4, 5, 6]); + assert_eq!(a.iter().cloned().collect::>(), []); +} diff --git a/src/libcollectionstest/vec_map.rs b/src/libcollectionstest/vec_map.rs new file mode 100644 index 0000000000..112b4c03e2 --- /dev/null +++ b/src/libcollectionstest/vec_map.rs @@ -0,0 +1,510 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::VecMap; +use std::collections::vec_map::Entry::{Occupied, Vacant}; +use std::hash::{SipHasher, hash}; + +#[test] +fn test_get_mut() { + let mut m = VecMap::new(); + assert!(m.insert(1, 12).is_none()); + assert!(m.insert(2, 8).is_none()); + assert!(m.insert(5, 14).is_none()); + let new = 100; + match m.get_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.get(&5), Some(&new)); +} + +#[test] +fn test_len() { + let mut map = VecMap::new(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert!(map.insert(5, 20).is_none()); + assert_eq!(map.len(), 1); + assert!(!map.is_empty()); + assert!(map.insert(11, 12).is_none()); + assert_eq!(map.len(), 2); + assert!(!map.is_empty()); + assert!(map.insert(14, 22).is_none()); + assert_eq!(map.len(), 3); + assert!(!map.is_empty()); +} + +#[test] +fn test_clear() { + let mut map = VecMap::new(); + assert!(map.insert(5, 20).is_none()); + assert!(map.insert(11, 12).is_none()); + assert!(map.insert(14, 22).is_none()); + map.clear(); + assert!(map.is_empty()); + assert!(map.get(&5).is_none()); + assert!(map.get(&11).is_none()); + assert!(map.get(&14).is_none()); +} + +#[test] +fn test_insert() { + let mut m = VecMap::new(); + assert_eq!(m.insert(1, 2), None); + assert_eq!(m.insert(1, 3), Some(2)); + assert_eq!(m.insert(1, 4), Some(3)); +} + +#[test] +fn test_remove() { + let mut m = VecMap::new(); + m.insert(1, 2); + assert_eq!(m.remove(&1), Some(2)); + assert_eq!(m.remove(&1), None); +} + +#[test] +fn test_keys() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let keys: Vec<_> = map.keys().collect(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); +} + +#[test] +fn test_values() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let values: Vec<_> = map.values().cloned().collect(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); +} + +#[test] +fn test_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + let mut it = m.iter(); + assert_eq!(it.size_hint(), (0, Some(11))); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.size_hint(), (0, Some(10))); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.size_hint(), (0, Some(9))); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.size_hint(), (0, Some(7))); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.size_hint(), (0, Some(4))); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); +} + +#[test] +fn test_iterator_size_hints() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + assert_eq!(m.iter().size_hint(), (0, Some(11))); + assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); +} + +#[test] +fn test_mut_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + for (k, v) in &mut m { + *v += k as isize; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); +} + +#[test] +fn test_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + let mut it = m.iter().rev(); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.next().unwrap(), (0, &1)); + assert!(it.next().is_none()); +} + +#[test] +fn test_mut_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1).is_none()); + assert!(m.insert(1, 2).is_none()); + assert!(m.insert(3, 5).is_none()); + assert!(m.insert(6, 10).is_none()); + assert!(m.insert(10, 11).is_none()); + + for (k, v) in m.iter_mut().rev() { + *v += k as isize; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); +} + +#[test] +fn test_move_iter() { + let mut m: VecMap> = VecMap::new(); + m.insert(1, box 2); + let mut called = false; + for (k, v) in m { + assert!(!called); + called = true; + assert_eq!(k, 1); + assert_eq!(v, box 2); + } + assert!(called); +} + +#[test] +fn test_drain_iterator() { + let mut map = VecMap::new(); + map.insert(1, "a"); + map.insert(3, "c"); + map.insert(2, "b"); + + let vec: Vec<_> = map.drain().collect(); + + assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]); + assert_eq!(map.len(), 0); +} + +#[test] +fn test_append() { + let mut a = VecMap::new(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + + let mut b = VecMap::new(); + b.insert(3, "d"); // Overwrite element from a + b.insert(4, "e"); + b.insert(5, "f"); + + a.append(&mut b); + + assert_eq!(a.len(), 5); + assert_eq!(b.len(), 0); + // Capacity shouldn't change for possible reuse + assert!(b.capacity() >= 4); + + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + assert_eq!(a[3], "d"); + assert_eq!(a[4], "e"); + assert_eq!(a[5], "f"); +} + +#[test] +fn test_split_off() { + // Split within the key range + let mut a = VecMap::new(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(3); + + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); + + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + + assert_eq!(b[3], "c"); + assert_eq!(b[4], "d"); + + // Split at 0 + a.clear(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(0); + + assert_eq!(a.len(), 0); + assert_eq!(b.len(), 4); + assert_eq!(b[1], "a"); + assert_eq!(b[2], "b"); + assert_eq!(b[3], "c"); + assert_eq!(b[4], "d"); + + // Split behind max_key + a.clear(); + a.insert(1, "a"); + a.insert(2, "b"); + a.insert(3, "c"); + a.insert(4, "d"); + + let b = a.split_off(5); + + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 0); + assert_eq!(a[1], "a"); + assert_eq!(a[2], "b"); + assert_eq!(a[3], "c"); + assert_eq!(a[4], "d"); +} + +#[test] +fn test_show() { + let mut map = VecMap::new(); + let empty = VecMap::::new(); + + map.insert(1, 2); + map.insert(3, 4); + + let map_str = format!("{:?}", map); + assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); + assert_eq!(format!("{:?}", empty), "{}"); +} + +#[test] +fn test_clone() { + let mut a = VecMap::new(); + + a.insert(1, 'x'); + a.insert(4, 'y'); + a.insert(6, 'z'); + + assert!(a.clone() == a); +} + +#[test] +fn test_eq() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a == b); + assert!(a.insert(0, 5).is_none()); + assert!(a != b); + assert!(b.insert(0, 4).is_none()); + assert!(a != b); + assert!(a.insert(5, 19).is_none()); + assert!(a != b); + assert!(!b.insert(0, 5).is_none()); + assert!(a != b); + assert!(b.insert(5, 19).is_none()); + assert!(a == b); + + a = VecMap::new(); + b = VecMap::with_capacity(1); + assert!(a == b); +} + +#[test] +fn test_lt() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2, 5).is_none()); + assert!(a < b); + assert!(a.insert(2, 7).is_none()); + assert!(!(a < b) && b < a); + assert!(b.insert(1, 0).is_none()); + assert!(b < a); + assert!(a.insert(0, 6).is_none()); + assert!(a < b); + assert!(a.insert(6, 2).is_none()); + assert!(a < b && !(b < a)); +} + +#[test] +fn test_ord() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1, 1).is_none()); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2, 2).is_none()); + assert!(b > a && b >= a); + assert!(a < b && a <= b); +} + +#[test] +fn test_hash() { + let mut x = VecMap::new(); + let mut y = VecMap::new(); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); + + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); + + x.insert(1000, 'd'); + x.remove(&1000); + + assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y)); +} + +#[test] +fn test_from_iter() { + let xs = vec![(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; + + let map: VecMap<_> = xs.iter().cloned().collect(); + + for &(k, v) in &xs { + assert_eq!(map.get(&k), Some(&v)); + } +} + +#[test] +fn test_index() { + let mut map = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + assert_eq!(map[3], 4); +} + +#[test] +#[should_panic] +fn test_index_nonexistent() { + let mut map = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + map[4]; +} + +#[test] +fn test_entry(){ + let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: VecMap<_> = xs.iter().cloned().collect(); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.insert(100), 10); + } + } + assert_eq!(map.get(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + *v *= 10; + } + } + assert_eq!(map.get(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.remove(), 30); + } + } + assert_eq!(map.get(&3), None); + assert_eq!(map.len(), 5); + + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.insert(1000), 1000); + } + } + assert_eq!(map.get(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); +} + +mod bench { + use std::collections::VecMap; + + map_insert_rand_bench!{insert_rand_100, 100, VecMap} + map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap} + + map_insert_seq_bench!{insert_seq_100, 100, VecMap} + map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap} + + map_find_rand_bench!{find_rand_100, 100, VecMap} + map_find_rand_bench!{find_rand_10_000, 10_000, VecMap} + + map_find_seq_bench!{find_seq_100, 100, VecMap} + map_find_seq_bench!{find_seq_10_000, 10_000, VecMap} +} diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 462b6771b4..320fdd50b3 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -55,7 +55,7 @@ //! } //! //! // This function wants to log its parameter out prior to doing work with it. -//! fn do_work(value: &T) { +//! fn do_work(value: &T) { //! log(value); //! // ...do some other work //! } @@ -71,30 +71,34 @@ #![stable(feature = "rust1", since = "1.0.0")] +use fmt; +use marker::Send; use mem::transmute; use option::Option::{self, Some, None}; use raw::TraitObject; use intrinsics; -use marker::Sized; +use marker::{Reflect, Sized}; /////////////////////////////////////////////////////////////////////////////// // Any trait /////////////////////////////////////////////////////////////////////////////// -/// The `Any` trait is implemented by all `'static` types, and can be used for -/// dynamic typing +/// A type to emulate dynamic typing. See the [module-level documentation][mod] for more details. /// -/// Every type with no non-`'static` references implements `Any`, so `Any` can -/// be used as a trait object to emulate the effects dynamic typing. +/// Every type with no non-`'static` references implements `Any`. +/// +/// [mod]: ../index.html #[stable(feature = "rust1", since = "1.0.0")] -pub trait Any: 'static { +pub trait Any: Reflect + 'static { /// Get the `TypeId` of `self` #[unstable(feature = "core", reason = "this method will likely be replaced by an associated static")] fn get_type_id(&self) -> TypeId; } -impl Any for T { +impl Any for T + where T: Reflect + 'static +{ fn get_type_id(&self) -> TypeId { TypeId::of::() } } @@ -102,11 +106,18 @@ impl Any for T { // Extension methods for Any trait objects. /////////////////////////////////////////////////////////////////////////////// +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Any { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Any") + } +} + impl Any { /// Returns true if the boxed type is the same as `T` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is(&self) -> bool { + pub fn is(&self) -> bool { // Get TypeId of the type this function is instantiated with let t = TypeId::of::(); @@ -121,7 +132,7 @@ impl Any { /// `None` if it isn't. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn downcast_ref(&self) -> Option<&T> { + pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -139,7 +150,7 @@ impl Any { /// `None` if it isn't. #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn downcast_mut(&mut self) -> Option<&mut T> { + pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { // Get the raw representation of the trait object @@ -154,6 +165,30 @@ impl Any { } } +impl Any+Send { + /// Forwards to the method defined on the type `Any`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is(&self) -> bool { + Any::is::(self) + } + + /// Forwards to the method defined on the type `Any`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + Any::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `Any`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + Any::downcast_mut::(self) + } +} + + /////////////////////////////////////////////////////////////////////////////// // TypeID and its methods /////////////////////////////////////////////////////////////////////////////// @@ -175,9 +210,8 @@ pub struct TypeId { impl TypeId { /// Returns the `TypeId` of the type this generic function has been /// instantiated with - #[unstable(feature = "core", - reason = "may grow a `Reflect` bound soon via marker traits")] - pub fn of() -> TypeId { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn of() -> TypeId { TypeId { t: unsafe { intrinsics::type_id::() }, } diff --git a/src/libcore/array.rs b/src/libcore/array.rs index afb5d95c9f..91301ee558 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -14,20 +14,64 @@ #![unstable(feature = "core")] // not yet reviewed +#![doc(primitive = "array")] + use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; +use convert::{AsRef, AsMut}; use fmt; use hash::{Hash, self}; use iter::IntoIterator; -use marker::Copy; -use ops::Deref; +use marker::{Copy, Sized}; use option::Option; use slice::{Iter, IterMut, SliceExt}; +/// Utility trait implemented only on arrays of fixed size +/// +/// This trait can be used to implement other traits on fixed-size arrays +/// without causing much metadata bloat. +#[unstable(feature = "core")] +pub trait FixedSizeArray { + /// Converts the array to immutable slice + fn as_slice(&self) -> &[T]; + /// Converts the array to mutable slice + fn as_mut_slice(&mut self) -> &mut [T]; +} + // macro for implementing n-ary tuple functions and operations macro_rules! array_impls { ($($N:expr)+) => { $( + #[unstable(feature = "core")] + impl FixedSizeArray for [T; $N] { + #[inline] + fn as_slice(&self) -> &[T] { + &self[..] + } + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + &mut self[..] + } + } + + #[unstable(feature = "array_as_ref", + reason = "should ideally be implemented for all fixed-sized arrays")] + impl AsRef<[T]> for [T; $N] { + #[inline] + fn as_ref(&self) -> &[T] { + &self[..] + } + } + + #[unstable(feature = "array_as_ref", + reason = "should ideally be implemented for all fixed-sized arrays")] + impl AsMut<[T]> for [T; $N] { + #[inline] + fn as_mut(&mut self) -> &mut [T] { + &mut self[..] + } + } + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for [T; $N] { fn clone(&self) -> [T; $N] { @@ -35,13 +79,6 @@ macro_rules! array_impls { } } - #[cfg(stage0)] - impl> Hash for [T; $N] { - fn hash(&self, state: &mut S) { - Hash::hash(&self[..], state) - } - } - #[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for [T; $N] { fn hash(&self, state: &mut H) { @@ -76,47 +113,13 @@ macro_rules! array_impls { } } - #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq<[B; $N]> for [A; $N] where A: PartialEq { - #[inline] - fn eq(&self, other: &[B; $N]) -> bool { - &self[..] == &other[..] - } - #[inline] - fn ne(&self, other: &[B; $N]) -> bool { - &self[..] != &other[..] - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, A, B, Rhs> PartialEq for [A; $N] where - A: PartialEq, - Rhs: Deref, - { - #[inline(always)] - fn eq(&self, other: &Rhs) -> bool { - PartialEq::eq(&self[..], &**other) - } - #[inline(always)] - fn ne(&self, other: &Rhs) -> bool { - PartialEq::ne(&self[..], &**other) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where - A: PartialEq, - Lhs: Deref - { - #[inline(always)] - fn eq(&self, other: &[B; $N]) -> bool { - PartialEq::eq(&**self, &other[..]) - } - #[inline(always)] - fn ne(&self, other: &[B; $N]) -> bool { - PartialEq::ne(&**self, &other[..]) - } - } + // NOTE: some less important impls are omitted to reduce code bloat + __impl_slice_eq1! { [A; $N], [B; $N] } + __impl_slice_eq2! { [A; $N], [B] } + __impl_slice_eq2! { [A; $N], &'b [B] } + __impl_slice_eq2! { [A; $N], &'b mut [B] } + // __impl_slice_eq2! { [A; $N], &'b [B; $N] } + // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] } #[stable(feature = "rust1", since = "1.0.0")] impl Eq for [T; $N] { } diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 6afe5b2257..ed35e09549 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -15,7 +15,7 @@ //! types. //! //! This module defines atomic versions of a select number of primitive -//! types, including `AtomicBool`, `AtomicIsize`, `AtomicUsize`, and `AtomicOption`. +//! types, including `AtomicBool`, `AtomicIsize`, and `AtomicUsize`. //! Atomic types present operations that, when used correctly, synchronize //! updates between threads. //! @@ -122,7 +122,7 @@ unsafe impl Sync for AtomicPtr {} /// Rust's memory orderings are [the same as /// C++'s](http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync). #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Ordering { /// No ordering constraints, only atomic operations. #[stable(feature = "rust1", since = "1.0.0")] @@ -161,7 +161,7 @@ pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize { v: UnsafeCell { value: 0, } }; // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly -const UINT_TRUE: usize = -1; +const UINT_TRUE: usize = !0; impl AtomicBool { /// Creates a new `AtomicBool`. @@ -252,7 +252,8 @@ impl AtomicBool { /// Stores a value into the bool if the current value is the same as the expected value. /// - /// If the return value is equal to `old` then the value was updated. + /// The return value is always the previous value. If it is equal to `old`, then the value was + /// updated. /// /// `swap` also takes an `Ordering` argument which describes the memory ordering of this /// operation. @@ -489,7 +490,8 @@ impl AtomicIsize { /// Stores a value into the isize if the current value is the same as the expected value. /// - /// If the return value is equal to `old` then the value was updated. + /// The return value is always the previous value. If it is equal to `old`, then the value was + /// updated. /// /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of /// this operation. @@ -676,7 +678,8 @@ impl AtomicUsize { /// Stores a value into the usize if the current value is the same as the expected value. /// - /// If the return value is equal to `old` then the value was updated. + /// The return value is always the previous value. If it is equal to `old`, then the value was + /// updated. /// /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of /// this operation. @@ -873,7 +876,8 @@ impl AtomicPtr { /// Stores a value into the pointer if the current value is the same as the expected value. /// - /// If the return value is equal to `old` then the value was updated. + /// The return value is always the previous value. If it is equal to `old`, then the value was + /// updated. /// /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of /// this operation. @@ -1058,142 +1062,3 @@ pub fn fence(order: Ordering) { } } } - -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "renamed to AtomicIsize")] -#[allow(missing_docs)] -pub struct AtomicInt { - v: UnsafeCell, -} - -unsafe impl Sync for AtomicInt {} - -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "renamed to AtomicUsize")] -#[allow(missing_docs)] -pub struct AtomicUint { - v: UnsafeCell, -} - -unsafe impl Sync for AtomicUint {} - -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use ATOMIC_ISIZE_INIT instead")] -#[allow(missing_docs, deprecated)] -pub const ATOMIC_INT_INIT: AtomicInt = - AtomicInt { v: UnsafeCell { value: 0 } }; -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use ATOMIC_USIZE_INIT instead")] -#[allow(missing_docs, deprecated)] -pub const ATOMIC_UINT_INIT: AtomicUint = - AtomicUint { v: UnsafeCell { value: 0, } }; - -#[allow(missing_docs, deprecated)] -impl AtomicInt { - #[inline] - pub fn new(v: int) -> AtomicInt { - AtomicInt {v: UnsafeCell::new(v)} - } - - #[inline] - pub fn load(&self, order: Ordering) -> int { - unsafe { atomic_load(self.v.get(), order) } - } - - #[inline] - pub fn store(&self, val: int, order: Ordering) { - unsafe { atomic_store(self.v.get(), val, order); } - } - - #[inline] - pub fn swap(&self, val: int, order: Ordering) -> int { - unsafe { atomic_swap(self.v.get(), val, order) } - } - - #[inline] - pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int { - unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } - } - - #[inline] - pub fn fetch_add(&self, val: int, order: Ordering) -> int { - unsafe { atomic_add(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_sub(&self, val: int, order: Ordering) -> int { - unsafe { atomic_sub(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_and(&self, val: int, order: Ordering) -> int { - unsafe { atomic_and(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_or(&self, val: int, order: Ordering) -> int { - unsafe { atomic_or(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_xor(&self, val: int, order: Ordering) -> int { - unsafe { atomic_xor(self.v.get(), val, order) } - } -} - -#[allow(missing_docs, deprecated)] -impl AtomicUint { - #[inline] - pub fn new(v: uint) -> AtomicUint { - AtomicUint { v: UnsafeCell::new(v) } - } - - #[inline] - pub fn load(&self, order: Ordering) -> uint { - unsafe { atomic_load(self.v.get(), order) } - } - - #[inline] - pub fn store(&self, val: uint, order: Ordering) { - unsafe { atomic_store(self.v.get(), val, order); } - } - - #[inline] - pub fn swap(&self, val: uint, order: Ordering) -> uint { - unsafe { atomic_swap(self.v.get(), val, order) } - } - - #[inline] - pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint { - unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } - } - - #[inline] - pub fn fetch_add(&self, val: uint, order: Ordering) -> uint { - unsafe { atomic_add(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint { - unsafe { atomic_sub(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_and(&self, val: uint, order: Ordering) -> uint { - unsafe { atomic_and(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_or(&self, val: uint, order: Ordering) -> uint { - unsafe { atomic_or(self.v.get(), val, order) } - } - - #[inline] - pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint { - unsafe { atomic_xor(self.v.get(), val, order) } - } -} diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index eb138e6142..76e09eedbd 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -144,7 +144,7 @@ use clone::Clone; use cmp::PartialEq; use default::Default; -use marker::{Copy, Send}; +use marker::{Copy, Send, Sync}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{None, Some}; @@ -168,6 +168,7 @@ impl Cell { /// let c = Cell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn new(value: T) -> Cell { Cell { value: UnsafeCell::new(value), @@ -219,6 +220,7 @@ impl Cell { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::cell::Cell; /// /// let c = Cell::new(5); @@ -237,6 +239,7 @@ unsafe impl Send for Cell where T: Send {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Cell { + #[inline] fn clone(&self) -> Cell { Cell::new(self.get()) } @@ -245,6 +248,7 @@ impl Clone for Cell { #[stable(feature = "rust1", since = "1.0.0")] impl Default for Cell { #[stable(feature = "rust1", since = "1.0.0")] + #[inline] fn default() -> Cell { Cell::new(Default::default()) } @@ -252,6 +256,7 @@ impl Default for Cell { #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Cell { + #[inline] fn eq(&self, other: &Cell) -> bool { self.get() == other.get() } @@ -282,7 +287,7 @@ pub enum BorrowState { // (will not outgrow its range since `usize` is the size of the address space) type BorrowFlag = usize; const UNUSED: BorrowFlag = 0; -const WRITING: BorrowFlag = -1; +const WRITING: BorrowFlag = !0; impl RefCell { /// Creates a new `RefCell` containing `value`. @@ -295,6 +300,7 @@ impl RefCell { /// let c = RefCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn new(value: T) -> RefCell { RefCell { value: UnsafeCell::new(value), @@ -314,6 +320,7 @@ impl RefCell { /// let five = c.into_inner(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn into_inner(self) -> T { // Since this function takes `self` (the `RefCell`) by value, the // compiler statically verifies that it is not currently borrowed. @@ -327,6 +334,7 @@ impl RefCell { /// The returned value can be dispatched on to determine if a call to /// `borrow` or `borrow_mut` would succeed. #[unstable(feature = "std_misc")] + #[inline] pub fn borrow_state(&self) -> BorrowState { match self.borrow.get() { WRITING => BorrowState::Writing, @@ -335,22 +343,6 @@ impl RefCell { } } - /// Attempts to immutably borrow the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// Returns `None` if the value is currently mutably borrowed. - #[unstable(feature = "core", reason = "may be renamed or removed")] - #[deprecated(since = "1.0.0", - reason = "dispatch on `cell.borrow_state()` instead")] - pub fn try_borrow<'a>(&'a self) -> Option> { - match BorrowRef::new(&self.borrow) { - Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }), - None => None, - } - } - /// Immutably borrows the wrapped value. /// /// The borrow lasts until the returned `Ref` exits scope. Multiple @@ -387,6 +379,7 @@ impl RefCell { /// assert!(result.is_err()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn borrow<'a>(&'a self) -> Ref<'a, T> { match BorrowRef::new(&self.borrow) { Some(b) => Ref { @@ -397,22 +390,6 @@ impl RefCell { } } - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// Returns `None` if the value is currently borrowed. - #[unstable(feature = "core", reason = "may be renamed or removed")] - #[deprecated(since = "1.0.0", - reason = "dispatch on `cell.borrow_state()` instead")] - pub fn try_borrow_mut<'a>(&'a self) -> Option> { - match BorrowRefMut::new(&self.borrow) { - Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }), - None => None, - } - } - /// Mutably borrows the wrapped value. /// /// The borrow lasts until the returned `RefMut` exits scope. The value @@ -448,6 +425,7 @@ impl RefCell { /// assert!(result.is_err()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { match BorrowRefMut::new(&self.borrow) { Some(b) => RefMut { @@ -475,6 +453,7 @@ unsafe impl Send for RefCell where T: Send {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for RefCell { + #[inline] fn clone(&self) -> RefCell { RefCell::new(self.borrow().clone()) } @@ -483,6 +462,7 @@ impl Clone for RefCell { #[stable(feature = "rust1", since = "1.0.0")] impl Default for RefCell { #[stable(feature = "rust1", since = "1.0.0")] + #[inline] fn default() -> RefCell { RefCell::new(Default::default()) } @@ -490,6 +470,7 @@ impl Default for RefCell { #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for RefCell { + #[inline] fn eq(&self, other: &RefCell) -> bool { *self.borrow() == *other.borrow() } @@ -500,6 +481,7 @@ struct BorrowRef<'b> { } impl<'b> BorrowRef<'b> { + #[inline] fn new(borrow: &'b Cell) -> Option> { match borrow.get() { WRITING => None, @@ -513,6 +495,7 @@ impl<'b> BorrowRef<'b> { #[unsafe_destructor] impl<'b> Drop for BorrowRef<'b> { + #[inline] fn drop(&mut self) { let borrow = self._borrow.get(); debug_assert!(borrow != WRITING && borrow != UNUSED); @@ -521,6 +504,7 @@ impl<'b> Drop for BorrowRef<'b> { } impl<'b> Clone for BorrowRef<'b> { + #[inline] fn clone(&self) -> BorrowRef<'b> { // Since this Ref exists, we know the borrow flag // is not set to WRITING. @@ -561,6 +545,7 @@ impl<'b, T> Deref for Ref<'b, T> { /// use of `r.borrow().clone()` to clone the contents of a `RefCell`. #[unstable(feature = "core", reason = "likely to be moved to a method, pending language changes")] +#[inline] pub fn clone_ref<'b, T:Clone>(orig: &Ref<'b, T>) -> Ref<'b, T> { Ref { _value: orig._value, @@ -574,6 +559,7 @@ struct BorrowRefMut<'b> { #[unsafe_destructor] impl<'b> Drop for BorrowRefMut<'b> { + #[inline] fn drop(&mut self) { let borrow = self._borrow.get(); debug_assert!(borrow == WRITING); @@ -582,6 +568,7 @@ impl<'b> Drop for BorrowRefMut<'b> { } impl<'b> BorrowRefMut<'b> { + #[inline] fn new(borrow: &'b Cell) -> Option> { match borrow.get() { UNUSED => { @@ -631,9 +618,6 @@ impl<'b, T> DerefMut for RefMut<'b, T> { /// /// Types like `Cell` and `RefCell` use this type to wrap their internal data. /// -/// `UnsafeCell` doesn't opt-out from any marker traits, instead, types with an `UnsafeCell` -/// interior are expected to opt-out from those traits themselves. -/// /// # Examples /// /// ``` @@ -660,6 +644,8 @@ pub struct UnsafeCell { pub value: T, } +impl !Sync for UnsafeCell {} + impl UnsafeCell { /// Construct a new instance of `UnsafeCell` which will wrap the specified /// value. @@ -675,6 +661,7 @@ impl UnsafeCell { /// let uc = UnsafeCell::new(5); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn new(value: T) -> UnsafeCell { UnsafeCell { value: value } } @@ -692,7 +679,11 @@ impl UnsafeCell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self) -> *mut T { &self.value as *const T as *mut T } + pub fn get(&self) -> *mut T { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] + &self.value as *const T as *mut T + } /// Unwraps the value /// diff --git a/src/libcore/char.rs b/src/libcore/char.rs index c45fac1bc9..010415b364 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -22,13 +22,13 @@ use option::Option; use slice::SliceExt; // UTF-8 ranges and tags for encoding characters -static TAG_CONT: u8 = 0b1000_0000u8; -static TAG_TWO_B: u8 = 0b1100_0000u8; -static TAG_THREE_B: u8 = 0b1110_0000u8; -static TAG_FOUR_B: u8 = 0b1111_0000u8; -static MAX_ONE_B: u32 = 0x80u32; -static MAX_TWO_B: u32 = 0x800u32; -static MAX_THREE_B: u32 = 0x10000u32; +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; /* Lu Uppercase_Letter an uppercase letter @@ -118,7 +118,7 @@ pub fn from_u32(i: u32) -> Option { /// assert_eq!(c, Some('4')); /// ``` #[inline] -#[unstable(feature = "core", reason = "pending integer conventions")] +#[stable(feature = "rust1", since = "1.0.0")] pub fn from_digit(num: u32, radix: u32) -> Option { if radix > 36 { panic!("from_digit: radix is too high (maximum 36)"); @@ -136,230 +136,25 @@ pub fn from_digit(num: u32, radix: u32) -> Option { } } -/// Basic `char` manipulations. -#[stable(feature = "rust1", since = "1.0.0")] +// NB: the stabilization and documentation for this trait is in +// unicode/char.rs, not here +#[allow(missing_docs)] // docs in libunicode/u_char.rs 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. - /// - /// # Examples - /// - /// ``` - /// let c = '1'; - /// - /// assert!(c.is_digit(10)); - /// - /// assert!('f'.is_digit(16)); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] fn is_digit(self, radix: u32) -> 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]. - /// - /// # Examples - /// - /// ``` - /// let c = '1'; - /// - /// assert_eq!(c.to_digit(10), Some(1)); - /// - /// assert_eq!('f'.to_digit(16), Some(15)); - /// ``` - #[unstable(feature = "core", - reason = "pending integer conventions")] fn to_digit(self, radix: u32) -> Option; - - /// 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. - /// - /// # Examples - /// - /// ``` - /// for i in '❤'.escape_unicode() { - /// println!("{}", i); - /// } - /// ``` - /// - /// This prints: - /// - /// ```text - /// \ - /// u - /// { - /// 2 - /// 7 - /// 6 - /// 4 - /// } - /// ``` - /// - /// Collecting into a `String`: - /// - /// ``` - /// let heart: String = '❤'.escape_unicode().collect(); - /// - /// assert_eq!(heart, r"\u{2764}"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] fn escape_unicode(self) -> 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`. - /// - /// # Examples - /// - /// ``` - /// for i in '"'.escape_default() { - /// println!("{}", i); - /// } - /// ``` - /// - /// This prints: - /// - /// ```text - /// \ - /// " - /// ``` - /// - /// Collecting into a `String`: - /// - /// ``` - /// let quote: String = '"'.escape_default().collect(); - /// - /// assert_eq!(quote, "\\\""); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] fn escape_default(self) -> EscapeDefault; - - /// Returns the number of bytes this character would need if encoded in UTF-8. - /// - /// # Examples - /// - /// ``` - /// let n = 'ß'.len_utf8(); - /// - /// assert_eq!(n, 2); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] fn len_utf8(self) -> usize; - - /// Returns the number of bytes this character would need if encoded in UTF-16. - /// - /// # Examples - /// - /// ``` - /// let n = 'ß'.len_utf16(); - /// - /// assert_eq!(n, 1); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] fn len_utf16(self) -> usize; - - /// 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. - /// - /// # Examples - /// - /// In both of these examples, 'ß' takes two bytes to encode. - /// - /// ``` - /// let mut b = [0; 2]; - /// - /// let result = 'ß'.encode_utf8(&mut b); - /// - /// assert_eq!(result, Some(2)); - /// ``` - /// - /// A buffer that's too small: - /// - /// ``` - /// let mut b = [0; 1]; - /// - /// let result = 'ß'.encode_utf8(&mut b); - /// - /// assert_eq!(result, None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] fn encode_utf8(self, dst: &mut [u8]) -> Option; - - /// 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. - /// - /// # Examples - /// - /// In both of these examples, 'ß' takes one byte to encode. - /// - /// ``` - /// let mut b = [0; 1]; - /// - /// let result = 'ß'.encode_utf16(&mut b); - /// - /// assert_eq!(result, Some(1)); - /// ``` - /// - /// A buffer that's too small: - /// - /// ``` - /// let mut b = [0; 0]; - /// - /// let result = 'ß'.encode_utf8(&mut b); - /// - /// assert_eq!(result, None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] fn encode_utf16(self, dst: &mut [u16]) -> Option; } -#[stable(feature = "rust1", since = "1.0.0")] impl CharExt for char { - #[unstable(feature = "core", - reason = "pending integer conventions")] fn is_digit(self, radix: u32) -> bool { self.to_digit(radix).is_some() } - #[unstable(feature = "core", - reason = "pending integer conventions")] fn to_digit(self, radix: u32) -> Option { if radix > 36 { panic!("to_digit: radix is too high (maximum 36)"); @@ -374,12 +169,10 @@ impl CharExt for char { else { None } } - #[stable(feature = "rust1", since = "1.0.0")] fn escape_unicode(self) -> EscapeUnicode { EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash } } - #[stable(feature = "rust1", since = "1.0.0")] fn escape_default(self) -> EscapeDefault { let init_state = match self { '\t' => EscapeDefaultState::Backslash('t'), @@ -395,34 +188,31 @@ impl CharExt for char { } #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn len_utf8(self) -> usize { let code = self as u32; - match () { - _ if code < MAX_ONE_B => 1, - _ if code < MAX_TWO_B => 2, - _ if code < MAX_THREE_B => 3, - _ => 4, + if code < MAX_ONE_B { + 1 + } else if code < MAX_TWO_B { + 2 + } else if code < MAX_THREE_B { + 3 + } else { + 4 } } #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn len_utf16(self) -> usize { let ch = self as u32; - if (ch & 0xFFFF_u32) == ch { 1 } else { 2 } + if (ch & 0xFFFF) == ch { 1 } else { 2 } } #[inline] - #[unstable(feature = "core", - reason = "pending decision about Iterator/Writer/Reader")] fn encode_utf8(self, dst: &mut [u8]) -> Option { encode_utf8_raw(self as u32, dst) } #[inline] - #[unstable(feature = "core", - reason = "pending decision about Iterator/Writer/Reader")] fn encode_utf16(self, dst: &mut [u16]) -> Option { encode_utf16_raw(self as u32, dst) } @@ -434,26 +224,25 @@ impl CharExt for char { /// If the buffer is not large enough, nothing will be written into it /// and a `None` will be returned. #[inline] -#[unstable(feature = "core")] pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option { // Marked #[inline] to allow llvm optimizing it away if code < MAX_ONE_B && dst.len() >= 1 { dst[0] = code as u8; Some(1) } else if code < MAX_TWO_B && dst.len() >= 2 { - dst[0] = (code >> 6 & 0x1F_u32) as u8 | TAG_TWO_B; - dst[1] = (code & 0x3F_u32) as u8 | TAG_CONT; + dst[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + dst[1] = (code & 0x3F) as u8 | TAG_CONT; Some(2) } else if code < MAX_THREE_B && dst.len() >= 3 { - dst[0] = (code >> 12 & 0x0F_u32) as u8 | TAG_THREE_B; - dst[1] = (code >> 6 & 0x3F_u32) as u8 | TAG_CONT; - dst[2] = (code & 0x3F_u32) as u8 | TAG_CONT; + dst[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + dst[1] = (code >> 6 & 0x3F) as u8 | TAG_CONT; + dst[2] = (code & 0x3F) as u8 | TAG_CONT; Some(3) } else if dst.len() >= 4 { - dst[0] = (code >> 18 & 0x07_u32) as u8 | TAG_FOUR_B; - dst[1] = (code >> 12 & 0x3F_u32) as u8 | TAG_CONT; - dst[2] = (code >> 6 & 0x3F_u32) as u8 | TAG_CONT; - dst[3] = (code & 0x3F_u32) as u8 | TAG_CONT; + dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + dst[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; + dst[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; + dst[3] = (code & 0x3F) as u8 | TAG_CONT; Some(4) } else { None @@ -466,18 +255,17 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> Option { /// If the buffer is not large enough, nothing will be written into it /// and a `None` will be returned. #[inline] -#[unstable(feature = "core")] pub fn encode_utf16_raw(mut ch: u32, dst: &mut [u16]) -> Option { // Marked #[inline] to allow llvm optimizing it away - if (ch & 0xFFFF_u32) == ch && dst.len() >= 1 { + if (ch & 0xFFFF) == ch && dst.len() >= 1 { // The BMP falls through (assuming non-surrogate, as it should) dst[0] = ch as u16; Some(1) } else if dst.len() >= 2 { // Supplementary planes break into surrogates. - ch -= 0x1_0000_u32; - dst[0] = 0xD800_u16 | ((ch >> 10) as u16); - dst[1] = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); + ch -= 0x1_0000; + dst[0] = 0xD800 | ((ch >> 10) as u16); + dst[1] = 0xDC00 | ((ch as u16) & 0x3FF); Some(2) } else { None @@ -494,7 +282,6 @@ pub struct EscapeUnicode { } #[derive(Clone)] -#[unstable(feature = "core")] enum EscapeUnicodeState { Backslash, Type, @@ -556,7 +343,6 @@ pub struct EscapeDefault { } #[derive(Clone)] -#[unstable(feature = "core")] enum EscapeDefaultState { Backslash(char), Char(char), diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 058eff121e..85e5bde485 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -27,6 +27,14 @@ use marker::Sized; #[stable(feature = "rust1", since = "1.0.0")] pub trait Clone : Sized { /// Returns a copy of the value. + /// + /// # Examples + /// + /// ``` + /// let hello = "Hello"; // &str implements Clone + /// + /// assert_eq!("Hello", hello.clone()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn clone(&self) -> Self; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index b37bad5f75..efe1179621 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -19,8 +19,7 @@ //! could do the following: //! //! ``` -//! use core::num::SignedInt; -//! +//! # #![feature(core)] //! struct FuzzyNum { //! num: i32, //! } @@ -65,7 +64,6 @@ use option::Option::{self, Some, None}; /// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`. #[lang="eq"] #[stable(feature = "rust1", since = "1.0.0")] -#[old_orphan_check] pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used by `==`. #[stable(feature = "rust1", since = "1.0.0")] @@ -361,6 +359,8 @@ pub trait PartialOrd: PartialEq { /// Compare and return the minimum of two values. /// +/// Returns the first argument if the comparison determines them to be equal. +/// /// # Examples /// /// ``` @@ -372,11 +372,13 @@ pub trait PartialOrd: PartialEq { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn min(v1: T, v2: T) -> T { - if v1 < v2 { v1 } else { v2 } + if v1 <= v2 { v1 } else { v2 } } /// Compare and return the maximum of two values. /// +/// Returns the second argument if the comparison determines them to be equal. +/// /// # Examples /// /// ``` @@ -388,7 +390,7 @@ pub fn min(v1: T, v2: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn max(v1: T, v2: T) -> T { - if v1 > v2 { v1 } else { v2 } + if v2 >= v1 { v2 } else { v1 } } /// Compare and return the minimum of two values if there is one. @@ -398,6 +400,7 @@ pub fn max(v1: T, v2: T) -> T { /// # Examples /// /// ``` +/// # #![feature(core)] /// use std::cmp; /// /// assert_eq!(Some(1), cmp::partial_min(1, 2)); @@ -407,6 +410,7 @@ pub fn max(v1: T, v2: T) -> T { /// When comparison is impossible: /// /// ``` +/// # #![feature(core)] /// use std::cmp; /// /// let result = cmp::partial_min(std::f64::NAN, 1.0); @@ -424,11 +428,12 @@ pub fn partial_min(v1: T, v2: T) -> Option { /// Compare and return the maximum of two values if there is one. /// -/// Returns the first argument if the comparison determines them to be equal. +/// Returns the second argument if the comparison determines them to be equal. /// /// # Examples /// /// ``` +/// # #![feature(core)] /// use std::cmp; /// /// assert_eq!(Some(2), cmp::partial_max(1, 2)); @@ -438,6 +443,7 @@ pub fn partial_min(v1: T, v2: T) -> Option { /// When comparison is impossible: /// /// ``` +/// # #![feature(core)] /// use std::cmp; /// /// let result = cmp::partial_max(std::f64::NAN, 1.0); @@ -447,8 +453,8 @@ pub fn partial_min(v1: T, v2: T) -> Option { #[unstable(feature = "core")] pub fn partial_max(v1: T, v2: T) -> Option { match v1.partial_cmp(&v2) { - Some(Less) => Some(v2), - Some(Equal) | Some(Greater) => Some(v1), + Some(Equal) | Some(Less) => Some(v2), + Some(Greater) => Some(v1), None => None } } diff --git a/src/libcore/cmp_macros.rs b/src/libcore/cmp_macros.rs new file mode 100644 index 0000000000..95dab3d165 --- /dev/null +++ b/src/libcore/cmp_macros.rs @@ -0,0 +1,47 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Utility macros for implementing PartialEq on slice-like types + +#![doc(hidden)] + +#[macro_export] +macro_rules! __impl_slice_eq1 { + ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq1! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq { + #[inline] + fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] } + #[inline] + fn ne(&self, other: &$Rhs) -> bool { &self[..] != &other[..] } + } + } +} + +#[macro_export] +macro_rules! __impl_slice_eq2 { + ($Lhs: ty, $Rhs: ty) => { + __impl_slice_eq2! { $Lhs, $Rhs, Sized } + }; + ($Lhs: ty, $Rhs: ty, $Bound: ident) => { + __impl_slice_eq1!($Lhs, $Rhs, $Bound); + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq { + #[inline] + fn eq(&self, other: &$Lhs) -> bool { &self[..] == &other[..] } + #[inline] + fn ne(&self, other: &$Lhs) -> bool { &self[..] != &other[..] } + } + } +} diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs new file mode 100644 index 0000000000..4a99f1a756 --- /dev/null +++ b/src/libcore/convert.rs @@ -0,0 +1,135 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits for conversions between types. +//! +//! The traits in this module provide a general way to talk about +//! conversions from one type to another. They follow the standard +//! Rust conventions of `as`/`to`/`into`/`from`. + +#![stable(feature = "rust1", since = "1.0.0")] + +use marker::Sized; + +/// A cheap, reference-to-reference conversion. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait AsRef { + /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_ref(&self) -> &T; +} + +/// A cheap, mutable reference-to-mutable reference conversion. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait AsMut { + /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_mut(&mut self) -> &mut T; +} + +/// A conversion that consumes `self`, which may or may not be +/// expensive. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Into: Sized { + /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] + fn into(self) -> T; +} + +/// Construct `Self` via a conversion. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait From { + /// Perform the conversion. + #[stable(feature = "rust1", since = "1.0.0")] + fn from(T) -> Self; +} + +//////////////////////////////////////////////////////////////////////////////// +// GENERIC IMPLS +//////////////////////////////////////////////////////////////////////////////// + +// As lifts over & +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a T where T: AsRef { + fn as_ref(&self) -> &U { + >::as_ref(*self) + } +} + +// As lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized, U: ?Sized> AsRef for &'a mut T where T: AsRef { + fn as_ref(&self) -> &U { + >::as_ref(*self) + } +} + +// FIXME (#23442): replace the above impls for &/&mut with the following more general one: +// // As lifts over Deref +// impl AsRef for D where D::Target: AsRef { +// fn as_ref(&self) -> &U { +// self.deref().as_ref() +// } +// } + +// AsMut lifts over &mut +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized, U: ?Sized> AsMut for &'a mut T where T: AsMut { + fn as_mut(&mut self) -> &mut U { + (*self).as_mut() + } +} + +// FIXME (#23442): replace the above impl for &mut with the following more general one: +// // AsMut lifts over DerefMut +// impl AsMut for D where D::Target: AsMut { +// fn as_mut(&mut self) -> &mut U { +// self.deref_mut().as_mut() +// } +// } + +// From implies Into +#[stable(feature = "rust1", since = "1.0.0")] +impl Into for T where U: From { + fn into(self) -> U { + U::from(self) + } +} + +// From (and thus Into) is reflexive +#[stable(feature = "rust1", since = "1.0.0")] +impl From for T { + fn from(t: T) -> T { t } +} + +//////////////////////////////////////////////////////////////////////////////// +// CONCRETE IMPLS +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for [T] { + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsMut<[T]> for [T] { + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for str { + fn as_ref(&self) -> &str { + self + } +} diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 7f46d9cbe5..910cf805f3 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -164,4 +164,3 @@ default_impl! { i64, 0 } default_impl! { f32, 0.0f32 } default_impl! { f64, 0.0f64 } - diff --git a/src/libcore/error.rs b/src/libcore/error.rs deleted file mode 100644 index 161f6c7892..0000000000 --- a/src/libcore/error.rs +++ /dev/null @@ -1,112 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Traits for working with Errors. -//! -//! # The `Error` trait -//! -//! `Error` is a trait representing the basic expectations for error values, -//! i.e. values of type `E` in `Result`. At a minimum, errors must provide -//! a description, but they may optionally provide additional detail (via -//! `Display`) and cause chain information: -//! -//! ``` -//! use std::fmt::Display; -//! -//! trait Error: Display { -//! fn description(&self) -> &str; -//! -//! fn cause(&self) -> Option<&Error> { None } -//! } -//! ``` -//! -//! The `cause` method is generally used when errors cross "abstraction -//! boundaries", i.e. when a one module must report an error that is "caused" -//! by an error from a lower-level module. This setup makes it possible for the -//! high-level module to provide its own errors that do not commit to any -//! particular implementation, but also reveal some of its implementation for -//! debugging via `cause` chains. -//! -//! # The `FromError` trait -//! -//! `FromError` is a simple trait that expresses conversions between different -//! error types. To provide maximum flexibility, it does not require either of -//! the types to actually implement the `Error` trait, although this will be the -//! common case. -//! -//! The main use of this trait is in the `try!` macro, which uses it to -//! automatically convert a given error to the error specified in a function's -//! return type. -//! -//! For example, -//! -//! ``` -//! use std::error::FromError; -//! use std::old_io::{File, IoError}; -//! use std::os::{MemoryMap, MapError}; -//! use std::old_path::Path; -//! -//! enum MyError { -//! Io(IoError), -//! Map(MapError) -//! } -//! -//! impl FromError for MyError { -//! fn from_error(err: IoError) -> MyError { -//! MyError::Io(err) -//! } -//! } -//! -//! impl FromError for MyError { -//! fn from_error(err: MapError) -> MyError { -//! MyError::Map(err) -//! } -//! } -//! -//! #[allow(unused_variables)] -//! fn open_and_map() -> Result<(), MyError> { -//! let f = try!(File::open(&Path::new("foo.txt"))); -//! let m = try!(MemoryMap::new(0, &[])); -//! // do something interesting here... -//! Ok(()) -//! } -//! ``` - -#![stable(feature = "rust1", since = "1.0.0")] - -use prelude::*; -use fmt::Display; - -/// Base functionality for all errors in Rust. -#[unstable(feature = "core", - reason = "the exact API of this trait may change")] -pub trait Error: Display { - /// A short description of the error; usually a static string. - fn description(&self) -> &str; - - /// The lower-level cause of this error, if any. - fn cause(&self) -> Option<&Error> { None } -} - -/// A trait for types that can be converted from a given error type `E`. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait FromError { - /// Perform the conversion. - #[stable(feature = "rust1", since = "1.0.0")] - fn from_error(err: E) -> Self; -} - -// Any type is convertable from itself -#[stable(feature = "rust1", since = "1.0.0")] -impl FromError for E { - fn from_error(err: E) -> E { - err - } -} diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs deleted file mode 100644 index 562a597ccc..0000000000 --- a/src/libcore/finally.rs +++ /dev/null @@ -1,110 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The Finally trait provides a method, `finally` on -//! stack closures that emulates Java-style try/finally blocks. -//! -//! Using the `finally` method is sometimes convenient, but the type rules -//! prohibit any shared, mutable state between the "try" case and the -//! "finally" case. For advanced cases, the `try_finally` function can -//! also be used. See that function for more details. -//! -//! # Example -//! -//! ``` -//! # #![feature(unboxed_closures)] -//! -//! use std::finally::Finally; -//! -//! (|| { -//! // ... -//! }).finally(|| { -//! // this code is always run -//! }) -//! ``` - -#![unstable(feature = "core")] -#![deprecated(since = "1.0.0", - reason = "It is unclear if this module is more robust than implementing \ - Drop on a custom type, and this module is being removed with no \ - replacement. Use a custom Drop implementation to regain existing \ - functionality.")] -#![allow(deprecated)] - -use ops::{Drop, FnMut, FnOnce}; - -/// A trait for executing a destructor unconditionally after a block of code, -/// regardless of whether the blocked fails. -pub trait Finally { - /// Executes this object, unconditionally running `dtor` after this block of - /// code has run. - fn finally(&mut self, dtor: F) -> T where F: FnMut(); -} - -impl Finally for F where F: FnMut() -> T { - fn finally(&mut self, mut dtor: G) -> T where G: FnMut() { - try_finally(&mut (), self, |_, f| (*f)(), |_| dtor()) - } -} - -/// The most general form of the `finally` functions. The function -/// `try_fn` will be invoked first; whether or not it panics, the -/// function `finally_fn` will be invoked next. The two parameters -/// `mutate` and `drop` are used to thread state through the two -/// closures. `mutate` is used for any shared, mutable state that both -/// closures require access to; `drop` is used for any state that the -/// `try_fn` requires ownership of. -/// -/// **WARNING:** While shared, mutable state between the try and finally -/// function is often necessary, one must be very careful; the `try` -/// function could have panicked at any point, so the values of the shared -/// state may be inconsistent. -/// -/// # Example -/// -/// ``` -/// use std::finally::try_finally; -/// -/// struct State<'a> { buffer: &'a mut [u8], len: usize } -/// # let mut buf = []; -/// let mut state = State { buffer: &mut buf, len: 0 }; -/// try_finally( -/// &mut state, (), -/// |state, ()| { -/// // use state.buffer, state.len -/// }, -/// |state| { -/// // use state.buffer, state.len to cleanup -/// }) -/// ``` -pub fn try_finally(mutate: &mut T, drop: U, try_fn: F, finally_fn: G) -> R where - F: FnOnce(&mut T, U) -> R, - G: FnMut(&mut T), -{ - let f = Finallyalizer { - mutate: mutate, - dtor: finally_fn, - }; - try_fn(&mut *f.mutate, drop) -} - -struct Finallyalizer<'a, A:'a, F> where F: FnMut(&mut A) { - mutate: &'a mut A, - dtor: F, -} - -#[unsafe_destructor] -impl<'a, A, F> Drop for Finallyalizer<'a, A, F> where F: FnMut(&mut A) { - #[inline] - fn drop(&mut self) { - (self.dtor)(self.mutate); - } -} - diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs new file mode 100644 index 0000000000..f61a7f2d30 --- /dev/null +++ b/src/libcore/fmt/builders.rs @@ -0,0 +1,333 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use fmt::{self, Write, FlagV1}; + +struct PadAdapter<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + on_newline: bool, +} + +impl<'a, 'b: 'a> PadAdapter<'a, 'b> { + fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> { + PadAdapter { + fmt: fmt, + on_newline: false, + } + } +} + +impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { + fn write_str(&mut self, mut s: &str) -> fmt::Result { + while !s.is_empty() { + if self.on_newline { + try!(self.fmt.write_str(" ")); + } + + let split = match s.find('\n') { + Some(pos) => { + self.on_newline = true; + pos + 1 + } + None => { + self.on_newline = false; + s.len() + } + }; + try!(self.fmt.write_str(&s[..split])); + s = &s[split..]; + } + + Ok(()) + } +} + +/// A struct to help with `fmt::Debug` implementations. +/// +/// Constructed by the `Formatter::debug_struct` method. +#[must_use] +pub struct DebugStruct<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) + -> DebugStruct<'a, 'b> { + let result = fmt.write_str(name); + DebugStruct { + fmt: fmt, + result: result, + has_fields: false, + } +} + +impl<'a, 'b: 'a> DebugStruct<'a, 'b> { + /// Adds a new field to the generated struct output. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn field(mut self, name: &str, value: &fmt::Debug) -> DebugStruct<'a, 'b> { + self.result = self.result.and_then(|_| { + let prefix = if self.has_fields { + "," + } else { + " {" + }; + + if self.is_pretty() { + let mut writer = PadAdapter::new(self.fmt); + fmt::write(&mut writer, format_args!("{}\n{}: {:#?}", prefix, name, value)) + } else { + write!(self.fmt, "{} {}: {:?}", prefix, name, value) + } + }); + + self.has_fields = true; + self + } + + /// Consumes the `DebugStruct`, finishing output and returning any error + /// encountered. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn finish(mut self) -> fmt::Result { + if self.has_fields { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + self.fmt.write_str("\n}") + } else { + self.fmt.write_str(" }") + } + }); + } + self.result + } + + fn is_pretty(&self) -> bool { + self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + } +} + +/// A struct to help with `fmt::Debug` implementations. +/// +/// Constructed by the `Formatter::debug_tuple` method. +#[must_use] +pub struct DebugTuple<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> { + let result = fmt.write_str(name); + DebugTuple { + fmt: fmt, + result: result, + has_fields: false, + } +} + +impl<'a, 'b: 'a> DebugTuple<'a, 'b> { + /// Adds a new field to the generated tuple struct output. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn field(mut self, value: &fmt::Debug) -> DebugTuple<'a, 'b> { + self.result = self.result.and_then(|_| { + let (prefix, space) = if self.has_fields { + (",", " ") + } else { + ("(", "") + }; + + if self.is_pretty() { + let mut writer = PadAdapter::new(self.fmt); + fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, value)) + } else { + write!(self.fmt, "{}{}{:?}", prefix, space, value) + } + }); + + self.has_fields = true; + self + } + + /// Consumes the `DebugTuple`, finishing output and returning any error + /// encountered. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn finish(mut self) -> fmt::Result { + if self.has_fields { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + self.fmt.write_str("\n)") + } else { + self.fmt.write_str(")") + } + }); + } + self.result + } + + fn is_pretty(&self) -> bool { + self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + } +} + +struct DebugInner<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +impl<'a, 'b: 'a> DebugInner<'a, 'b> { + fn entry(&mut self, entry: &fmt::Debug) { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + let mut writer = PadAdapter::new(self.fmt); + let prefix = if self.has_fields { "," } else { "" }; + fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry)) + } else { + let prefix = if self.has_fields { ", " } else { "" }; + write!(self.fmt, "{}{:?}", prefix, entry) + } + }); + + self.has_fields = true; + } + + pub fn finish(&mut self) { + let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" }; + self.result = self.result.and_then(|_| self.fmt.write_str(prefix)); + } + + fn is_pretty(&self) -> bool { + self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + } +} + +/// A struct to help with `fmt::Debug` implementations. +/// +/// Constructed by the `Formatter::debug_set` method. +#[must_use] +pub struct DebugSet<'a, 'b: 'a> { + inner: DebugInner<'a, 'b>, +} + +pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { + let result = write!(fmt, "{{"); + DebugSet { + inner: DebugInner { + fmt: fmt, + result: result, + has_fields: false, + } + } +} + +impl<'a, 'b: 'a> DebugSet<'a, 'b> { + /// Adds a new entry to the set output. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn entry(mut self, entry: &fmt::Debug) -> DebugSet<'a, 'b> { + self.inner.entry(entry); + self + } + + /// Consumes the `DebugSet`, finishing output and returning any error + /// encountered. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn finish(mut self) -> fmt::Result { + self.inner.finish(); + self.inner.result.and_then(|_| self.inner.fmt.write_str("}")) + } +} + +/// A struct to help with `fmt::Debug` implementations. +/// +/// Constructed by the `Formatter::debug_list` method. +#[must_use] +pub struct DebugList<'a, 'b: 'a> { + inner: DebugInner<'a, 'b>, +} + +pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { + let result = write!(fmt, "["); + DebugList { + inner: DebugInner { + fmt: fmt, + result: result, + has_fields: false, + } + } +} + +impl<'a, 'b: 'a> DebugList<'a, 'b> { + /// Adds a new entry to the set output. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn entry(mut self, entry: &fmt::Debug) -> DebugList<'a, 'b> { + self.inner.entry(entry); + self + } + + /// Consumes the `DebugSet`, finishing output and returning any error + /// encountered. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn finish(mut self) -> fmt::Result { + self.inner.finish(); + self.inner.result.and_then(|_| self.inner.fmt.write_str("]")) + } +} + +/// A struct to help with `fmt::Debug` implementations. +/// +/// Constructed by the `Formatter::debug_map` method. +#[must_use] +pub struct DebugMap<'a, 'b: 'a> { + fmt: &'a mut fmt::Formatter<'b>, + result: fmt::Result, + has_fields: bool, +} + +pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { + let result = write!(fmt, "{{"); + DebugMap { + fmt: fmt, + result: result, + has_fields: false, + } +} + +impl<'a, 'b: 'a> DebugMap<'a, 'b> { + /// Adds a new entry to the map output. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn entry(mut self, key: &fmt::Debug, value: &fmt::Debug) -> DebugMap<'a, 'b> { + self.result = self.result.and_then(|_| { + if self.is_pretty() { + let mut writer = PadAdapter::new(self.fmt); + let prefix = if self.has_fields { "," } else { "" }; + fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value)) + } else { + let prefix = if self.has_fields { ", " } else { "" }; + write!(self.fmt, "{}{:?}: {:?}", prefix, key, value) + } + }); + + self.has_fields = true; + self + } + + /// Consumes the `DebugMap`, finishing output and returning any error + /// encountered. + #[unstable(feature = "debug_builders", reason = "method was just created")] + pub fn finish(self) -> fmt::Result { + let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" }; + self.result.and_then(|_| write!(self.fmt, "{}}}", prefix)) + } + + fn is_pretty(&self) -> bool { + self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0 + } +} diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 7f7264a046..6a5943265c 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -17,7 +17,7 @@ pub use self::SignFormat::*; use char; use char::CharExt; use fmt; -use iter::IteratorExt; +use iter::Iterator; use num::{cast, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnOnce; @@ -40,10 +40,10 @@ pub enum ExponentFormat { pub enum SignificantDigits { /// At most the given number of digits will be printed, truncating any /// trailing zeroes. - DigMax(uint), + DigMax(usize), /// Precisely the given number of digits will be printed. - DigExact(uint) + DigExact(usize) } /// How to emit the sign of a number. @@ -53,7 +53,7 @@ pub enum SignFormat { SignNeg } -static DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11; +const DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11; /// Converts a number to its string representation as a byte vector. /// This is meant to be a common base implementation for all numeric string @@ -123,13 +123,13 @@ pub fn float_to_str_bytes_common( // For an f64 the exponent is in the range of [-1022, 1023] for base 2, so // we may have up to that many digits. Give ourselves some extra wiggle room // otherwise as well. - let mut buf = [0u8; 1536]; + let mut buf = [0; 1536]; let mut end = 0; - let radix_gen: T = cast(radix as int).unwrap(); + let radix_gen: T = cast(radix as isize).unwrap(); let (num, exp) = match exp_format { - ExpNone => (num, 0i32), - ExpDec if num == _0 => (num, 0i32), + ExpNone => (num, 0), + ExpDec if num == _0 => (num, 0), ExpDec => { let (exp, exp_base) = match exp_format { ExpDec => (num.abs().log10().floor(), cast::(10.0f64).unwrap()), @@ -156,7 +156,7 @@ pub fn float_to_str_bytes_common( deccum = deccum / radix_gen; deccum = deccum.trunc(); - let c = char::from_digit(current_digit.to_int().unwrap() as u32, radix); + let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix); buf[end] = c.unwrap() as u8; end += 1; @@ -211,7 +211,7 @@ pub fn float_to_str_bytes_common( // See note in first loop. let current_digit = deccum.trunc().abs(); - let c = char::from_digit(current_digit.to_int().unwrap() as u32, + let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix); buf[end] = c.unwrap() as u8; end += 1; @@ -235,32 +235,32 @@ pub fn float_to_str_bytes_common( let extra_digit = ascii2value(buf[end - 1]); end -= 1; if extra_digit >= radix / 2 { // -> need to round - let mut i: int = end as int - 1; + let mut i: isize = end as isize - 1; loop { // If reached left end of number, have to // insert additional digit: if i < 0 - || buf[i as uint] == b'-' - || buf[i as uint] == b'+' { - for j in (i as uint + 1..end).rev() { + || buf[i as usize] == b'-' + || buf[i as usize] == b'+' { + for j in (i as usize + 1..end).rev() { buf[j + 1] = buf[j]; } - buf[(i + 1) as uint] = value2ascii(1); + buf[(i + 1) as usize] = value2ascii(1); end += 1; break; } // Skip the '.' - if buf[i as uint] == b'.' { i -= 1; continue; } + if buf[i as usize] == b'.' { i -= 1; continue; } // Either increment the digit, // or set to 0 if max and carry the 1. - let current_digit = ascii2value(buf[i as uint]); + let current_digit = ascii2value(buf[i as usize]); if current_digit < (radix - 1) { - buf[i as uint] = value2ascii(current_digit+1); + buf[i as usize] = value2ascii(current_digit+1); break; } else { - buf[i as uint] = value2ascii(0); + buf[i as usize] = value2ascii(0); i -= 1; } } @@ -311,13 +311,13 @@ pub fn float_to_str_bytes_common( struct Filler<'a> { buf: &'a mut [u8], - end: &'a mut uint, + end: &'a mut usize, } impl<'a> fmt::Write for Filler<'a> { fn write_str(&mut self, s: &str) -> fmt::Result { - slice::bytes::copy_memory(&mut self.buf[(*self.end)..], - s.as_bytes()); + slice::bytes::copy_memory(s.as_bytes(), + &mut self.buf[(*self.end)..]); *self.end += s.len(); Ok(()) } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a2c1bbc033..be80432766 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -12,10 +12,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -use any; use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; use char::CharExt; -use iter::{Iterator, IteratorExt}; +use clone::Clone; +use iter::Iterator; use marker::{Copy, PhantomData, Sized}; use mem; use option::Option; @@ -32,8 +32,11 @@ pub use self::num::radix; pub use self::num::Radix; pub use self::num::RadixFmt; +pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap}; + mod num; mod float; +mod builders; #[stable(feature = "rust1", since = "1.0.0")] #[doc(hidden)] @@ -51,7 +54,7 @@ pub type Result = result::Result<(), Error>; /// occurred. Any extra information must be arranged to be transmitted through /// some other means. #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub struct Error; /// A collection of methods that are required to format a message into a stream. @@ -110,11 +113,11 @@ pub trait Write { /// traits. #[stable(feature = "rust1", since = "1.0.0")] pub struct Formatter<'a> { - flags: uint, + flags: u32, fill: char, align: rt::v1::Alignment, - width: Option, - precision: Option, + width: Option, + precision: Option, buf: &'a mut (Write+'a), curarg: slice::Iter<'a, ArgumentV1<'a>>, @@ -138,9 +141,15 @@ pub struct ArgumentV1<'a> { formatter: fn(&Void, &mut Formatter) -> Result, } +impl<'a> Clone for ArgumentV1<'a> { + fn clone(&self) -> ArgumentV1<'a> { + *self + } +} + impl<'a> ArgumentV1<'a> { #[inline(never)] - fn show_uint(x: &uint, f: &mut Formatter) -> Result { + fn show_usize(x: &usize, f: &mut Formatter) -> Result { Display::fmt(x, f) } @@ -158,13 +167,13 @@ impl<'a> ArgumentV1<'a> { #[doc(hidden)] #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_uint(x: &uint) -> ArgumentV1 { - ArgumentV1::new(x, ArgumentV1::show_uint) + pub fn from_usize(x: &usize) -> ArgumentV1 { + ArgumentV1::new(x, ArgumentV1::show_usize) } - fn as_uint(&self) -> Option { - if self.formatter as uint == ArgumentV1::show_uint as uint { - Some(unsafe { *(self.value as *const _ as *const uint) }) + fn as_usize(&self) -> Option { + if self.formatter as usize == ArgumentV1::show_usize as usize { + Some(unsafe { *(self.value as *const _ as *const usize) }) } else { None } @@ -172,7 +181,7 @@ impl<'a> ArgumentV1<'a> { } // flags available in the v1 format of format_args -#[derive(Copy)] +#[derive(Copy, Clone)] #[allow(dead_code)] // SignMinus isn't currently used enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, } @@ -194,7 +203,7 @@ impl<'a> Arguments<'a> { /// The `pieces` array must be at least as long as `fmt` to construct /// a valid Arguments structure. Also, any `Count` within `fmt` that is /// `CountIsParam` or `CountIsNextParam` has to point to an argument - /// created with `argumentuint`. However, failing to do so doesn't cause + /// created with `argumentusize`. However, failing to do so doesn't cause /// unsafety, but will ignore invalid . #[doc(hidden)] #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -219,7 +228,7 @@ impl<'a> Arguments<'a> { /// macro validates the format string at compile-time so usage of the `write` /// and `format` functions can be safely performed. #[stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Arguments<'a> { // Format string pieces to print. pieces: &'a [&'a str], @@ -246,16 +255,6 @@ impl<'a> Display for Arguments<'a> { } } -/// Format trait for the `:?` format. Useful for debugging, all types -/// should implement this. -#[deprecated(since = "1.0.0", reason = "renamed to Debug")] -#[unstable(feature = "old_fmt")] -pub trait Show { - /// Formats the value using the given formatter. - #[stable(feature = "rust1", since = "1.0.0")] - fn fmt(&self, &mut Formatter) -> Result; -} - /// Format trait for the `:?` format. Useful for debugging, all types /// should implement this. #[stable(feature = "rust1", since = "1.0.0")] @@ -269,22 +268,6 @@ pub trait Debug { fn fmt(&self, &mut Formatter) -> Result; } -#[allow(deprecated)] -impl Debug for T { - #[allow(deprecated)] - fn fmt(&self, f: &mut Formatter) -> Result { Show::fmt(self, f) } -} - -/// When a value can be semantically expressed as a String, this trait may be -/// used. It corresponds to the default format, `{}`. -#[deprecated(since = "1.0.0", reason = "renamed to Display")] -#[unstable(feature = "old_fmt")] -pub trait String { - /// Formats the value using the given formatter. - #[stable(feature = "rust1", since = "1.0.0")] - fn fmt(&self, &mut Formatter) -> Result; -} - /// When a value can be semantically expressed as a String, this trait may be /// used. It corresponds to the default format, `{}`. #[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \ @@ -297,12 +280,6 @@ pub trait Display { fn fmt(&self, &mut Formatter) -> Result; } -#[allow(deprecated)] -impl Display for T { - #[allow(deprecated)] - fn fmt(&self, f: &mut Formatter) -> Result { String::fmt(self, f) } -} - /// Format trait for the `o` character #[stable(feature = "rust1", since = "1.0.0")] pub trait Octal { @@ -434,15 +411,15 @@ impl<'a> Formatter<'a> { (value.formatter)(value.value, self) } - fn getcount(&mut self, cnt: &rt::v1::Count) -> Option { + fn getcount(&mut self, cnt: &rt::v1::Count) -> Option { match *cnt { rt::v1::Count::Is(n) => Some(n), rt::v1::Count::Implied => None, rt::v1::Count::Param(i) => { - self.args[i].as_uint() + self.args[i].as_usize() } rt::v1::Count::NextParam => { - self.curarg.next().and_then(|arg| arg.as_uint()) + self.curarg.next().and_then(|arg| arg.as_usize()) } } } @@ -457,7 +434,7 @@ impl<'a> Formatter<'a> { /// # Arguments /// /// * is_positive - whether the original integer was positive or not. - /// * prefix - if the '#' character (FlagAlternate) is provided, this + /// * prefix - if the '#' character (Alternate) is provided, this /// is the prefix to put in front of the number. /// * buf - the byte array that the number has been formatted into /// @@ -476,12 +453,12 @@ impl<'a> Formatter<'a> { let mut sign = None; if !is_positive { sign = Some('-'); width += 1; - } else if self.flags & (1 << (FlagV1::SignPlus as uint)) != 0 { + } else if self.flags & (1 << (FlagV1::SignPlus as u32)) != 0 { sign = Some('+'); width += 1; } let mut prefixed = false; - if self.flags & (1 << (FlagV1::Alternate as uint)) != 0 { + if self.flags & (1 << (FlagV1::Alternate as u32)) != 0 { prefixed = true; width += prefix.char_len(); } @@ -511,7 +488,7 @@ impl<'a> Formatter<'a> { } // The sign and prefix goes before the padding if the fill character // is zero - Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as uint)) != 0 => { + Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 => { self.fill = '0'; try!(write_prefix(self)); self.with_padding(min - width, Alignment::Right, |f| { @@ -581,7 +558,7 @@ impl<'a> Formatter<'a> { /// Runs a callback, emitting the correct padding either before or /// afterwards depending on whether right or left alignment is requested. - fn with_padding(&mut self, padding: uint, default: Alignment, + fn with_padding(&mut self, padding: usize, default: Alignment, f: F) -> Result where F: FnOnce(&mut Formatter) -> Result, { @@ -597,7 +574,7 @@ impl<'a> Formatter<'a> { Alignment::Center => (padding / 2, (padding + 1) / 2), }; - let mut fill = [0u8; 4]; + let mut fill = [0; 4]; let len = self.fill.encode_utf8(&mut fill).unwrap_or(0); let fill = unsafe { str::from_utf8_unchecked(&fill[..len]) }; @@ -629,7 +606,7 @@ impl<'a> Formatter<'a> { /// Flags for formatting (packed version of rt::Flag) #[stable(feature = "rust1", since = "1.0.0")] - pub fn flags(&self) -> usize { self.flags } + pub fn flags(&self) -> u32 { self.flags } /// Character used as 'fill' whenever there is alignment #[unstable(feature = "core", reason = "method was just created")] @@ -641,11 +618,150 @@ impl<'a> Formatter<'a> { /// Optionally specified integer width that the output should be #[unstable(feature = "core", reason = "method was just created")] - pub fn width(&self) -> Option { self.width } + pub fn width(&self) -> Option { self.width } /// Optionally specified precision for numeric types #[unstable(feature = "core", reason = "method was just created")] - pub fn precision(&self) -> Option { self.precision } + pub fn precision(&self) -> Option { self.precision } + + /// Creates a `DebugStruct` builder designed to assist with creation of + /// `fmt::Debug` implementations for structs. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(debug_builders, core)] + /// use std::fmt; + /// + /// struct Foo { + /// bar: i32, + /// baz: String, + /// } + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fmt.debug_struct("Foo") + /// .field("bar", &self.bar) + /// .field("baz", &self.baz) + /// .finish() + /// } + /// } + /// + /// // prints "Foo { bar: 10, baz: "Hello World" }" + /// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }); + /// ``` + #[unstable(feature = "debug_builders", reason = "method was just created")] + #[inline] + pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> { + builders::debug_struct_new(self, name) + } + + /// Creates a `DebugTuple` builder designed to assist with creation of + /// `fmt::Debug` implementations for tuple structs. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(debug_builders, core)] + /// use std::fmt; + /// + /// struct Foo(i32, String); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// fmt.debug_tuple("Foo") + /// .field(&self.0) + /// .field(&self.1) + /// .finish() + /// } + /// } + /// + /// // prints "Foo(10, "Hello World")" + /// println!("{:?}", Foo(10, "Hello World".to_string())); + /// ``` + #[unstable(feature = "debug_builders", reason = "method was just created")] + #[inline] + pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> { + builders::debug_tuple_new(self, name) + } + + /// Creates a `DebugList` builder designed to assist with creation of + /// `fmt::Debug` implementations for list-like structures. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(debug_builders, core)] + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// self.0.iter().fold(fmt.debug_list(), |b, e| b.entry(e)).finish() + /// } + /// } + /// + /// // prints "[10, 11]" + /// println!("{:?}", Foo(vec![10, 11])); + /// ``` + #[unstable(feature = "debug_builders", reason = "method was just created")] + #[inline] + pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> { + builders::debug_list_new(self) + } + + /// Creates a `DebugSet` builder designed to assist with creation of + /// `fmt::Debug` implementations for set-like structures. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(debug_builders, core)] + /// use std::fmt; + /// + /// struct Foo(Vec); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// self.0.iter().fold(fmt.debug_set(), |b, e| b.entry(e)).finish() + /// } + /// } + /// + /// // prints "{10, 11}" + /// println!("{:?}", Foo(vec![10, 11])); + /// ``` + #[unstable(feature = "debug_builders", reason = "method was just created")] + #[inline] + pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> { + builders::debug_set_new(self) + } + + /// Creates a `DebugMap` builder designed to assist with creation of + /// `fmt::Debug` implementations for map-like structures. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(debug_builders, core)] + /// use std::fmt; + /// + /// struct Foo(Vec<(String, i32)>); + /// + /// impl fmt::Debug for Foo { + /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + /// self.0.iter().fold(fmt.debug_map(), |b, &(ref k, ref v)| b.entry(k, v)).finish() + /// } + /// } + /// + /// // prints "{"A": 10, "B": 11}" + /// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])); + /// ``` + #[unstable(feature = "debug_builders", reason = "method was just created")] + #[inline] + pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { + builders::debug_map_new(self) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -721,7 +837,7 @@ impl Debug for char { #[stable(feature = "rust1", since = "1.0.0")] impl Display for char { fn fmt(&self, f: &mut Formatter) -> Result { - let mut utf8 = [0u8; 4]; + let mut utf8 = [0; 4]; let amt = self.encode_utf8(&mut utf8).unwrap_or(0); let s: &str = unsafe { mem::transmute(&utf8[..amt]) }; Display::fmt(s, f) @@ -731,9 +847,9 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter) -> Result { - f.flags |= 1 << (FlagV1::Alternate as uint); - let ret = LowerHex::fmt(&(*self as uint), f); - f.flags &= !(1 << (FlagV1::Alternate as uint)); + f.flags |= 1 << (FlagV1::Alternate as u32); + let ret = LowerHex::fmt(&(*self as usize), f); + f.flags &= !(1 << (FlagV1::Alternate as u32)); ret } } @@ -741,6 +857,8 @@ impl Pointer for *const T { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *mut T { fn fmt(&self, f: &mut Formatter) -> Result { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] Pointer::fmt(&(*self as *const T), f) } } @@ -748,6 +866,8 @@ impl Pointer for *mut T { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Pointer for &'a T { fn fmt(&self, f: &mut Formatter) -> Result { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] Pointer::fmt(&(*self as *const T), f) } } @@ -755,6 +875,8 @@ impl<'a, T> Pointer for &'a T { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Pointer for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] Pointer::fmt(&(&**self as *const T), f) } } @@ -881,30 +1003,10 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Debug for &'a (any::Any+'a) { - fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Debug for [T] { fn fmt(&self, f: &mut Formatter) -> Result { - if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 { - try!(write!(f, "[")); - } - let mut is_first = true; - for x in self { - if is_first { - is_first = false; - } else { - try!(write!(f, ", ")); - } - try!(write!(f, "{:?}", *x)) - } - if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 { - try!(write!(f, "]")); - } - Ok(()) + self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish() } } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 1222126b5e..76c975902a 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -15,7 +15,7 @@ #![allow(unsigned_negation)] use fmt; -use iter::IteratorExt; +use iter::Iterator; use num::{Int, cast}; use slice::SliceExt; use str; @@ -33,12 +33,13 @@ trait GenericRadix { fn digit(&self, x: u8) -> u8; /// Format an integer using the radix using a formatter. + #[allow(deprecated)] // Int fn fmt_int(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result { // The radix can be as low as 2, so we need a buffer of at least 64 // characters for a base 2 number. let zero = Int::zero(); let is_positive = x >= zero; - let mut buf = [0u8; 64]; + let mut buf = [0; 64]; let mut curr = buf.len(); let base = cast(self.base()).unwrap(); if is_positive { @@ -84,7 +85,7 @@ struct LowerHex; /// A hexadecimal (base 16) radix, formatted with upper-case characters #[derive(Clone, PartialEq)] -pub struct UpperHex; +struct UpperHex; macro_rules! radix { ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => { @@ -138,14 +139,15 @@ impl GenericRadix for Radix { /// A helper type for formatting radixes. #[unstable(feature = "core", reason = "may be renamed or move to a different module")] -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct RadixFmt(T, R); /// Constructs a radix formatter in the range of `2..36`. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(core)] /// use std::fmt::radix; /// assert_eq!(format!("{}", radix(55, 36)), "1j".to_string()); /// ``` @@ -156,7 +158,7 @@ pub fn radix(x: T, base: u8) -> RadixFmt { } macro_rules! radix_fmt { - ($T:ty as $U:ty, $fmt:ident, $S:expr) => { + ($T:ty as $U:ty, $fmt:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for RadixFmt<$T, Radix> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -182,8 +184,8 @@ macro_rules! int_base { } } -macro_rules! show { - ($T:ident with $S:expr) => { +macro_rules! debug { + ($T:ident) => { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for $T { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -194,27 +196,24 @@ macro_rules! show { } macro_rules! integer { ($Int:ident, $Uint:ident) => { - integer! { $Int, $Uint, stringify!($Int), stringify!($Uint) } - }; - ($Int:ident, $Uint:ident, $SI:expr, $SU:expr) => { int_base! { Display for $Int as $Int -> Decimal } int_base! { Binary for $Int as $Uint -> Binary } int_base! { Octal for $Int as $Uint -> Octal } int_base! { LowerHex for $Int as $Uint -> LowerHex } int_base! { UpperHex for $Int as $Uint -> UpperHex } - radix_fmt! { $Int as $Int, fmt_int, $SI } - show! { $Int with $SI } + radix_fmt! { $Int as $Int, fmt_int } + debug! { $Int } int_base! { Display for $Uint as $Uint -> Decimal } int_base! { Binary for $Uint as $Uint -> Binary } int_base! { Octal for $Uint as $Uint -> Octal } int_base! { LowerHex for $Uint as $Uint -> LowerHex } int_base! { UpperHex for $Uint as $Uint -> UpperHex } - radix_fmt! { $Uint as $Uint, fmt_int, $SU } - show! { $Uint with $SU } + radix_fmt! { $Uint as $Uint, fmt_int } + debug! { $Uint } } } -integer! { int, uint, "i", "u" } +integer! { isize, usize } integer! { i8, u8 } integer! { i16, u16 } integer! { i32, u32 } diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 0c9bb6316e..d56ec6a74d 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -16,7 +16,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[derive(Copy)] +#[derive(Copy, Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Argument { #[stable(feature = "rust1", since = "1.0.0")] @@ -25,7 +25,7 @@ pub struct Argument { pub format: FormatSpec, } -#[derive(Copy)] +#[derive(Copy, Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct FormatSpec { #[stable(feature = "rust1", since = "1.0.0")] @@ -33,7 +33,7 @@ pub struct FormatSpec { #[stable(feature = "rust1", since = "1.0.0")] pub align: Alignment, #[stable(feature = "rust1", since = "1.0.0")] - pub flags: uint, + pub flags: u32, #[stable(feature = "rust1", since = "1.0.0")] pub precision: Count, #[stable(feature = "rust1", since = "1.0.0")] @@ -41,7 +41,7 @@ pub struct FormatSpec { } /// Possible alignments that can be requested as part of a formatting directive. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Alignment { /// Indication that contents should be left-aligned. @@ -58,7 +58,7 @@ pub enum Alignment { Unknown, } -#[derive(Copy)] +#[derive(Copy, Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Count { #[stable(feature = "rust1", since = "1.0.0")] @@ -71,7 +71,7 @@ pub enum Count { Implied, } -#[derive(Copy)] +#[derive(Copy, Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Position { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 2e83334b93..2375ae8965 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -16,11 +16,12 @@ //! # Examples //! //! ```rust +//! # #![feature(hash)] //! use std::hash::{hash, Hash, SipHasher}; //! //! #[derive(Hash)] //! struct Person { -//! id: uint, +//! id: u32, //! name: String, //! phone: u64, //! } @@ -35,10 +36,11 @@ //! the trait `Hash`: //! //! ```rust +//! # #![feature(hash)] //! use std::hash::{hash, Hash, Hasher, SipHasher}; //! //! struct Person { -//! id: uint, +//! id: u32, //! name: String, //! phone: u64, //! } @@ -70,10 +72,17 @@ mod sip; /// A hashable type. /// /// The `H` type parameter is an abstract hash state that is used by the `Hash` -/// to compute the hash. Specific implementations of this trait may specialize -/// for particular instances of `H` in order to be able to optimize the hashing -/// behavior. -#[cfg(not(stage0))] +/// to compute the hash. +/// +/// If you are also implementing `Eq`, there is an additional property that +/// is important: +/// +/// ```text +/// k1 == k2 -> hash(k1) == hash(k2) +/// ``` +/// +/// In other words, if two keys are equal, their hashes should also be equal. +/// `HashMap` and `HashSet` both rely on this behavior. #[stable(feature = "rust1", since = "1.0.0")] pub trait Hash { /// Feeds this value into the state given, updating the hasher as necessary. @@ -89,72 +98,40 @@ pub trait Hash { } } -/// A hashable type. -/// -/// The `H` type parameter is an abstract hash state that is used by the `Hash` -/// to compute the hash. Specific implementations of this trait may specialize -/// for particular instances of `H` in order to be able to optimize the hashing -/// behavior. -#[cfg(stage0)] -pub trait Hash { - /// Feeds this value into the state given, updating the hasher as necessary. - fn hash(&self, state: &mut H); -} - /// A trait which represents the ability to hash an arbitrary stream of bytes. #[stable(feature = "rust1", since = "1.0.0")] pub trait Hasher { - /// Result type of one run of hashing generated by this hasher. - #[cfg(stage0)] - type Output; - - /// Resets this hasher back to its initial state (as if it were just - /// created). - #[cfg(stage0)] - fn reset(&mut self); - - /// Completes a round of hashing, producing the output hash generated. - #[cfg(stage0)] - fn finish(&self) -> Self::Output; - /// Completes a round of hashing, producing the output hash generated. - #[cfg(not(stage0))] - #[unstable(feature = "hash", reason = "module was recently redesigned")] + #[stable(feature = "rust1", since = "1.0.0")] fn finish(&self) -> u64; /// Writes some data into this `Hasher` - #[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, bytes: &[u8]); /// Write a single `u8` into this hasher - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_u8(&mut self, i: u8) { self.write(&[i]) } /// Write a single `u16` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_u16(&mut self, i: u16) { self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) }) } /// Write a single `u32` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_u32(&mut self, i: u32) { self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) }) } /// Write a single `u64` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_u64(&mut self, i: u64) { self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) }) } /// Write a single `usize` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_usize(&mut self, i: usize) { @@ -166,58 +143,31 @@ pub trait Hasher { } /// Write a single `i8` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) } /// Write a single `i16` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) } /// Write a single `i32` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) } /// Write a single `i64` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) } /// Write a single `isize` into this hasher. - #[cfg(not(stage0))] #[inline] #[unstable(feature = "hash", reason = "module was recently redesigned")] fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) } } -/// A common bound on the `Hasher` parameter to `Hash` implementations in order -/// to generically hash an aggregate. -#[unstable(feature = "hash", - reason = "this trait will likely be replaced by io::Writer")] -#[allow(missing_docs)] -#[cfg(stage0)] -pub trait Writer { - fn write(&mut self, bytes: &[u8]); -} - -/// Hash a value with the default SipHasher algorithm (two initial keys of 0). -/// -/// The specified value will be hashed with this hasher and then the resulting -/// hash will be returned. -#[cfg(stage0)] -pub fn hash, H: Hasher + Default>(value: &T) -> H::Output { - let mut h: H = Default::default(); - value.hash(&mut h); - h.finish() -} - /// Hash a value with the default SipHasher algorithm (two initial keys of 0). /// /// The specified value will be hashed with this hasher and then the resulting /// hash will be returned. -#[cfg(not(stage0))] #[unstable(feature = "hash", reason = "module was recently redesigned")] pub fn hash(value: &T) -> u64 { let mut h: H = Default::default(); @@ -227,145 +177,6 @@ pub fn hash(value: &T) -> u64 { ////////////////////////////////////////////////////////////////////////////// -#[cfg(stage0)] -mod impls { - use prelude::*; - - use mem; - use num::Int; - use super::*; - - macro_rules! impl_hash { - ($ty:ident, $uty:ident) => { - impl Hash for $ty { - #[inline] - fn hash(&self, state: &mut S) { - let a: [u8; ::$ty::BYTES] = unsafe { - mem::transmute(*self) - }; - state.write(&a) - } - } - } - } - - impl_hash! { u8, u8 } - impl_hash! { u16, u16 } - impl_hash! { u32, u32 } - impl_hash! { u64, u64 } - impl_hash! { uint, uint } - impl_hash! { i8, u8 } - impl_hash! { i16, u16 } - impl_hash! { i32, u32 } - impl_hash! { i64, u64 } - impl_hash! { int, uint } - - impl Hash for bool { - #[inline] - fn hash(&self, state: &mut S) { - (*self as u8).hash(state); - } - } - - impl Hash for char { - #[inline] - fn hash(&self, state: &mut S) { - (*self as u32).hash(state); - } - } - - impl Hash for str { - #[inline] - fn hash(&self, state: &mut S) { - state.write(self.as_bytes()); - 0xffu8.hash(state) - } - } - - macro_rules! impl_hash_tuple { - () => ( - impl Hash for () { - #[inline] - fn hash(&self, _state: &mut S) {} - } - ); - - ( $($name:ident)+) => ( - impl),*> Hash for ($($name,)*) { - #[inline] - #[allow(non_snake_case)] - fn hash(&self, state: &mut S) { - match *self { - ($(ref $name,)*) => { - $( - $name.hash(state); - )* - } - } - } - } - ); - } - - impl_hash_tuple! {} - impl_hash_tuple! { A } - impl_hash_tuple! { A B } - impl_hash_tuple! { A B C } - impl_hash_tuple! { A B C D } - impl_hash_tuple! { A B C D E } - impl_hash_tuple! { A B C D E F } - impl_hash_tuple! { A B C D E F G } - impl_hash_tuple! { A B C D E F G H } - impl_hash_tuple! { A B C D E F G H I } - impl_hash_tuple! { A B C D E F G H I J } - impl_hash_tuple! { A B C D E F G H I J K } - impl_hash_tuple! { A B C D E F G H I J K L } - - impl> Hash for [T] { - #[inline] - fn hash(&self, state: &mut S) { - self.len().hash(state); - for elt in self { - elt.hash(state); - } - } - } - - - impl<'a, S: Hasher, T: ?Sized + Hash> Hash for &'a T { - #[inline] - fn hash(&self, state: &mut S) { - (**self).hash(state); - } - } - - impl<'a, S: Hasher, T: ?Sized + Hash> Hash for &'a mut T { - #[inline] - fn hash(&self, state: &mut S) { - (**self).hash(state); - } - } - - impl Hash for *const T { - #[inline] - fn hash(&self, state: &mut S) { - // NB: raw-pointer Hash does _not_ dereference - // to the target; it just gives you the pointer-bytes. - (*self as uint).hash(state); - } - } - - impl Hash for *mut T { - #[inline] - fn hash(&self, state: &mut S) { - // NB: raw-pointer Hash does _not_ dereference - // to the target; it just gives you the pointer-bytes. - (*self as uint).hash(state); - } - } -} - -#[cfg(not(stage0))] mod impls { use prelude::*; @@ -381,7 +192,9 @@ mod impls { } fn hash_slice(data: &[$ty], state: &mut H) { - let newlen = data.len() * ::$ty::BYTES; + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] + let newlen = data.len() * ::$ty::BYTES as usize; let ptr = data.as_ptr() as *const u8; state.write(unsafe { slice::from_raw_parts(ptr, newlen) }) } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index ce8917cc20..6820a7025f 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -12,12 +12,11 @@ //! An implementation of SipHash 2-4. +#![allow(deprecated)] // until the next snapshot for inherent wrapping ops + use prelude::*; use default::Default; - use super::Hasher; -#[cfg(stage0)] -use super::Writer; /// An implementation of SipHash 2-4. /// @@ -36,13 +35,13 @@ use super::Writer; pub struct SipHasher { k0: u64, k1: u64, - length: uint, // how many bytes we've processed + length: usize, // how many bytes we've processed v0: u64, // hash state v1: u64, v2: u64, v3: u64, tail: u64, // unprocessed bytes le - ntail: uint, // how many bytes in tail are valid + ntail: usize, // how many bytes in tail are valid } // sadly, these macro definitions can't appear later, @@ -62,7 +61,7 @@ macro_rules! u8to64_le { ($buf:expr, $i:expr, $len:expr) => ({ let mut t = 0; - let mut out = 0u64; + let mut out = 0; while t < $len { out |= ($buf[t+$i] as u64) << t*8; t += 1; @@ -73,17 +72,17 @@ macro_rules! u8to64_le { macro_rules! rotl { ($x:expr, $b:expr) => - (($x << $b) | ($x >> (64 - $b))) + (($x << $b) | ($x >> (64_i32.wrapping_sub($b)))) } macro_rules! compress { ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => ({ - $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0; + $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0; $v0 = rotl!($v0, 32); - $v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2; - $v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0; - $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2; + $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2; $v2 = rotl!($v2, 32); }) } @@ -115,11 +114,6 @@ impl SipHasher { state } - /// Returns the computed hash. - #[unstable(feature = "hash")] - #[deprecated(since = "1.0.0", reason = "renamed to finish")] - pub fn result(&self) -> u64 { self.finish() } - fn reset(&mut self) { self.length = 0; self.v0 = self.k0 ^ 0x736f6d6570736575; @@ -175,26 +169,9 @@ impl SipHasher { } } -#[cfg(stage0)] -impl Writer for SipHasher { - #[inline] - fn write(&mut self, msg: &[u8]) { - self.write(msg) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Hasher for SipHasher { - #[cfg(stage0)] - type Output = u64; - - #[cfg(stage0)] - fn reset(&mut self) { - self.reset(); - } - #[inline] - #[cfg(not(stage0))] fn write(&mut self, msg: &[u8]) { self.write(msg) } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b2ee959638..0e91eafce1 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -44,24 +44,6 @@ use marker::Sized; -pub type GlueFn = extern "Rust" fn(*const i8); - -#[lang="ty_desc"] -#[derive(Copy)] -pub struct TyDesc { - // sizeof(T) - pub size: usize, - - // alignof(T) - pub align: usize, - - // Called when a value of type `T` is no longer needed - pub drop_glue: GlueFn, - - // Name corresponding to the type - pub name: &'static str, -} - extern "rust-intrinsic" { // NB: These intrinsics take unsafe pointers because they mutate aliased @@ -196,21 +178,42 @@ extern "rust-intrinsic" { pub fn min_align_of() -> usize; pub fn pref_align_of() -> usize; - /// Get a static pointer to a type descriptor. - pub fn get_tydesc() -> *const TyDesc; + /// Gets a static string slice containing the name of a type. + pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever /// crate it is invoked in. pub fn type_id() -> u64; + /// Create a value initialized to so that its drop flag, + /// if any, says that it has been dropped. + /// + /// `init_dropped` is unsafe because it returns a datum with all + /// of its bytes set to the drop flag, which generally does not + /// correspond to a valid value. + /// + /// This intrinsic is likely to be deprecated in the future when + /// Rust moves to non-zeroing dynamic drop (and thus removes the + /// embedded drop flags that are being established by this + /// intrinsic). + pub fn init_dropped() -> T; + /// Create a value initialized to zero. /// /// `init` is unsafe because it returns a zeroed-out datum, - /// which is unsafe unless T is Copy. + /// which is unsafe unless T is `Copy`. Also, even if T is + /// `Copy`, an all-zero value may not correspond to any legitimate + /// state for the type in question. pub fn init() -> T; /// Create an uninitialized value. + /// + /// `uninit` is unsafe because there is no guarantee of what its + /// contents are. In particular its drop-flag may be set to any + /// state, which means it may claim either dropped or + /// undropped. In the general case one must use `ptr::write` to + /// initialize memory previous set to the result of `uninit`. pub fn uninit() -> T; /// Move a value out of scope without running drop glue. @@ -230,7 +233,7 @@ extern "rust-intrinsic" { /// use std::mem; /// /// let v: &[u8] = unsafe { mem::transmute("L") }; - /// assert!(v == [76u8]); + /// assert!(v == [76]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn transmute(e: T) -> U; @@ -241,7 +244,12 @@ extern "rust-intrinsic" { /// will trigger a compiler error. pub fn return_address() -> *const u8; - /// Returns `true` if a type requires drop glue. + /// Returns `true` if the actual type given as `T` requires drop + /// glue; returns `false` if the actual type provided for `T` + /// implements `Copy`. + /// + /// If the actual type neither requires drop glue nor implements + /// `Copy`, then may return `true` or `false`. pub fn needs_drop() -> bool; /// Returns `true` if a type is managed (will be allocated on the local heap) @@ -258,7 +266,7 @@ extern "rust-intrinsic" { /// Copies `count * size_of` bytes from `src` to `dst`. The source /// and destination may *not* overlap. /// - /// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`. + /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. /// /// # Safety /// @@ -274,6 +282,7 @@ extern "rust-intrinsic" { /// A safe swap function: /// /// ``` + /// # #![feature(core)] /// use std::mem; /// use std::ptr; /// @@ -283,9 +292,9 @@ extern "rust-intrinsic" { /// let mut t: T = mem::uninitialized(); /// /// // Perform the swap, `&mut` pointers never alias - /// ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); - /// ptr::copy_nonoverlapping_memory(x, &*y, 1); - /// ptr::copy_nonoverlapping_memory(y, &t, 1); + /// ptr::copy_nonoverlapping(x, &mut t, 1); + /// ptr::copy_nonoverlapping(y, x, 1); + /// ptr::copy_nonoverlapping(&t, y, 1); /// /// // y and t now point to the same thing, but we need to completely forget `tmp` /// // because it's no longer relevant. @@ -293,13 +302,19 @@ extern "rust-intrinsic" { /// } /// } /// ``` - #[unstable(feature = "core")] - pub fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: usize); + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(stage0))] + pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + + /// dox + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] + pub fn copy_nonoverlapping(dst: *mut T, src: *const T, count: usize); /// Copies `count * size_of` bytes from `src` to `dst`. The source /// and destination may overlap. /// - /// `copy_memory` is semantically equivalent to C's `memmove`. + /// `copy` is semantically equivalent to C's `memmove`. /// /// # Safety /// @@ -313,24 +328,30 @@ extern "rust-intrinsic" { /// Efficiently create a Rust vector from an unsafe buffer: /// /// ``` + /// # #![feature(core)] /// use std::ptr; /// - /// unsafe fn from_buf_raw(ptr: *const T, elts: uint) -> Vec { + /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { /// let mut dst = Vec::with_capacity(elts); /// dst.set_len(elts); - /// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts); + /// ptr::copy(ptr, dst.as_mut_ptr(), elts); /// dst /// } /// ``` /// - #[unstable(feature = "core")] - pub fn copy_memory(dst: *mut T, src: *const T, count: usize); + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(stage0))] + pub fn copy(src: *const T, dst: *mut T, count: usize); + + /// dox + #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] + pub fn copy(dst: *mut T, src: *const T, count: usize); /// Invokes memset on the specified pointer, setting `count * size_of::()` /// bytes of memory starting at `dst` to `c`. - #[unstable(feature = "core", - reason = "uncertain about naming and semantics")] - pub fn set_memory(dst: *mut T, val: u8, count: usize); + #[stable(feature = "rust1", since = "1.0.0")] + pub fn write_bytes(dst: *mut T, val: u8, count: usize); /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::()` and an alignment of @@ -541,4 +562,11 @@ extern "rust-intrinsic" { pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool); /// Performs checked `u64` multiplication. pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool); + + /// Returns (a + b) mod 2^N, where N is the width of N in bits. + pub fn overflowing_add(a: T, b: T) -> T; + /// Returns (a - b) mod 2^N, where N is the width of N in bits. + pub fn overflowing_sub(a: T, b: T) -> T; + /// Returns (a * b) mod 2^N, where N is the width of N in bits. + pub fn overflowing_mul(a: T, b: T) -> T; } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 8fb10b5b2d..42e90ec34d 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -12,47 +12,47 @@ //! //! # The `Iterator` trait //! -//! This module defines Rust's core iteration trait. The `Iterator` trait has one -//! unimplemented method, `next`. All other methods are derived through default -//! methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`. +//! This module defines Rust's core iteration trait. The `Iterator` trait has +//! one unimplemented method, `next`. All other methods are derived through +//! default methods to perform operations such as `zip`, `chain`, `enumerate`, +//! and `fold`. //! //! The goal of this module is to unify iteration across all containers in Rust. -//! An iterator can be considered as a state machine which is used to track which -//! element will be yielded next. +//! An iterator can be considered as a state machine which is used to track +//! which element will be yielded next. //! -//! There are various extensions also defined in this module to assist with various -//! types of iteration, such as the `DoubleEndedIterator` for iterating in reverse, -//! the `FromIterator` trait for creating a container from an iterator, and much -//! more. +//! There are various extensions also defined in this module to assist with +//! various types of iteration, such as the `DoubleEndedIterator` for iterating +//! in reverse, the `FromIterator` trait for creating a container from an +//! iterator, and much more. //! -//! ## Rust's `for` loop +//! # Rust's `for` loop //! -//! The special syntax used by rust's `for` loop is based around the `Iterator` -//! trait defined in this module. For loops can be viewed as a syntactical expansion -//! into a `loop`, for example, the `for` loop in this example is essentially -//! translated to the `loop` below. +//! The special syntax used by rust's `for` loop is based around the +//! `IntoIterator` trait defined in this module. `for` loops can be viewed as a +//! syntactical expansion into a `loop`, for example, the `for` loop in this +//! example is essentially translated to the `loop` below. //! //! ``` //! let values = vec![1, 2, 3]; //! -//! // "Syntactical sugar" taking advantage of an iterator -//! for &x in values.iter() { +//! for x in values { //! println!("{}", x); //! } //! //! // Rough translation of the iteration without a `for` iterator. -//! let mut it = values.iter(); +//! # let values = vec![1, 2, 3]; +//! let mut it = values.into_iter(); //! loop { //! match it.next() { -//! Some(&x) => { -//! println!("{}", x); -//! } -//! None => { break } +//! Some(x) => println!("{}", x), +//! None => break, //! } //! } //! ``` //! -//! This `for` loop syntax can be applied to any iterator over any type. +//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be applied to any +//! iterator over any type. #![stable(feature = "rust1", since = "1.0.0")] @@ -64,13 +64,14 @@ use cmp::Ord; use default::Default; use marker; use mem; -use num::{ToPrimitive, Int}; -use ops::{Add, Deref, FnMut}; -use option::Option; -use option::Option::{Some, None}; +use num::{Int, Zero, One}; +use ops::{self, Add, Sub, FnMut, RangeFrom}; +use option::Option::{self, Some, None}; use marker::Sized; use usize; +fn _assert_is_object_safe(_: &Iterator) {} + /// An interface for dealing with "external iterators". These types of iterators /// can be resumed at any time as all state is stored internally as opposed to /// being located on the call stack. @@ -83,77 +84,26 @@ use usize; /// else. #[lang="iterator"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \ - method"] +#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \ + `.iter()` or a similar method"] pub trait Iterator { + /// The type of the elements being iterated #[stable(feature = "rust1", since = "1.0.0")] type Item; - /// Advance the iterator and return the next value. Return `None` when the end is reached. + /// Advance the iterator and return the next value. Return `None` when the + /// end is reached. #[stable(feature = "rust1", since = "1.0.0")] fn next(&mut self) -> Option; /// Returns a lower and upper bound on the remaining length of the iterator. /// - /// An upper bound of `None` means either there is no known upper bound, or the upper bound - /// does not fit within a `usize`. + /// An upper bound of `None` means either there is no known upper bound, or + /// the upper bound does not fit within a `usize`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn size_hint(&self) -> (usize, Option) { (0, None) } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I { - type Item = I::Item; - fn next(&mut self) -> Option { (**self).next() } - fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } -} - -/// Conversion from an `Iterator` -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ - built from an iterator over elements of type `{A}`"] -pub trait FromIterator { - /// Build a container with elements from something iterable. - #[stable(feature = "rust1", since = "1.0.0")] - fn from_iter>(iterator: T) -> Self; -} - -/// Conversion into an `Iterator` -#[stable(feature = "rust1", since = "1.0.0")] -pub trait IntoIterator { - #[stable(feature = "rust1", since = "1.0.0")] - type Item; - - #[stable(feature = "rust1", since = "1.0.0")] - type IntoIter: Iterator; - - /// Consumes `Self` and returns an iterator over it - #[stable(feature = "rust1", since = "1.0.0")] - fn into_iter(self) -> Self::IntoIter; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for I { - type Item = I::Item; - type IntoIter = I; - - fn into_iter(self) -> I { - self - } -} - -/// A type growable from an `Iterator` implementation -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Extend { - /// Extend a container with the elements yielded by an arbitrary iterator - #[stable(feature = "rust1", since = "1.0.0")] - fn extend>(&mut self, iterable: T); -} -/// An extension trait providing numerous methods applicable to all iterators. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait IteratorExt: Iterator + Sized { /// Counts the number of elements in this iterator. /// /// # Examples @@ -164,12 +114,11 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn count(self) -> usize { + fn count(self) -> usize where Self: Sized { self.fold(0, |cnt, _x| cnt + 1) } - /// Loops through the entire iterator, returning the last element of the - /// iterator. + /// Loops through the entire iterator, returning the last element. /// /// # Examples /// @@ -179,7 +128,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn last(self) -> Option { + fn last(self) -> Option where Self: Sized { let mut last = None; for x in self { last = Some(x); } last @@ -198,7 +147,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn nth(&mut self, mut n: usize) -> Option { + fn nth(&mut self, mut n: usize) -> Option where Self: Sized { for x in self.by_ref() { if n == 0 { return Some(x) } n -= 1; @@ -223,7 +172,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn chain(self, other: U) -> Chain where - U: Iterator, + Self: Sized, U: Iterator, { Chain{a: self, b: other, flag: false} } @@ -242,9 +191,23 @@ pub trait IteratorExt: Iterator + Sized { /// assert_eq!(it.next().unwrap(), (&0, &1)); /// assert!(it.next().is_none()); /// ``` + /// + /// `zip` can provide similar functionality to `enumerate`: + /// + /// ``` + /// for pair in "foo".chars().enumerate() { + /// println!("{:?}", pair); + /// } + /// + /// for pair in (0..).zip("foo".chars()) { + /// println!("{:?}", pair); + /// } + /// ``` + /// + /// both produce the same output. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn zip(self, other: U) -> Zip { + fn zip(self, other: U) -> Zip where Self: Sized { Zip{a: self, b: other} } @@ -263,7 +226,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn map(self, f: F) -> Map where - F: FnMut(Self::Item) -> B, + Self: Sized, F: FnMut(Self::Item) -> B, { Map{iter: self, f: f} } @@ -283,7 +246,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn filter

(self, predicate: P) -> Filter where - P: FnMut(&Self::Item) -> bool, + Self: Sized, P: FnMut(&Self::Item) -> bool, { Filter{iter: self, predicate: predicate} } @@ -303,7 +266,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn filter_map(self, f: F) -> FilterMap where - F: FnMut(Self::Item) -> Option, + Self: Sized, F: FnMut(Self::Item) -> Option, { FilterMap { iter: self, f: f } } @@ -311,6 +274,10 @@ pub trait IteratorExt: Iterator + Sized { /// Creates an iterator that yields a pair of the value returned by this /// iterator plus the current index of iteration. /// + /// `enumerate` keeps its count as a `usize`. If you want to count by a + /// different sized integer, the `zip` function provides similar + /// functionality. + /// /// # Examples /// /// ``` @@ -322,7 +289,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn enumerate(self) -> Enumerate { + fn enumerate(self) -> Enumerate where Self: Sized { Enumerate{iter: self, count: 0} } @@ -332,6 +299,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// let xs = [100, 200, 300]; /// let mut it = xs.iter().cloned().peekable(); /// assert_eq!(*it.peek().unwrap(), 100); @@ -345,7 +313,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn peekable(self) -> Peekable { + fn peekable(self) -> Peekable where Self: Sized { Peekable{iter: self, peeked: None} } @@ -366,7 +334,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn skip_while

(self, predicate: P) -> SkipWhile where - P: FnMut(&Self::Item) -> bool, + Self: Sized, P: FnMut(&Self::Item) -> bool, { SkipWhile{iter: self, flag: false, predicate: predicate} } @@ -387,7 +355,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn take_while

(self, predicate: P) -> TakeWhile where - P: FnMut(&Self::Item) -> bool, + Self: Sized, P: FnMut(&Self::Item) -> bool, { TakeWhile{iter: self, flag: false, predicate: predicate} } @@ -406,7 +374,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn skip(self, n: usize) -> Skip { + fn skip(self, n: usize) -> Skip where Self: Sized { Skip{iter: self, n: n} } @@ -425,7 +393,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn take(self, n: usize) -> Take { + fn take(self, n: usize) -> Take where Self: Sized, { Take{iter: self, n: n} } @@ -452,7 +420,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn scan(self, initial_state: St, f: F) -> Scan - where F: FnMut(&mut St, Self::Item) -> Option, + where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option, { Scan{iter: self, f: f, state: initial_state} } @@ -463,9 +431,10 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// let xs = [2, 3]; /// let ys = [0, 1, 0, 1, 2]; - /// let it = xs.iter().flat_map(|&x| std::iter::count(0, 1).take(x)); + /// let it = xs.iter().flat_map(|&x| (0..).take(x)); /// // Check that `it` has the same elements as `ys` /// for (i, x) in it.enumerate() { /// assert_eq!(x, ys[i]); @@ -474,7 +443,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn flat_map(self, f: F) -> FlatMap - where U: Iterator, F: FnMut(Self::Item) -> U, + where Self: Sized, U: Iterator, F: FnMut(Self::Item) -> U, { FlatMap{iter: self, f: f, frontiter: None, backiter: None } } @@ -486,7 +455,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` - /// fn process>(it: U) -> isize { + /// fn process>(it: U) -> i32 { /// let mut it = it.fuse(); /// let mut sum = 0; /// for x in it.by_ref() { @@ -508,7 +477,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn fuse(self) -> Fuse { + fn fuse(self) -> Fuse where Self: Sized { Fuse{iter: self, done: false} } @@ -519,6 +488,7 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::iter::AdditiveIterator; /// /// let a = [1, 4, 2, 3, 8, 9, 6]; @@ -533,7 +503,7 @@ pub trait IteratorExt: Iterator + Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn inspect(self, f: F) -> Inspect where - F: FnMut(&Self::Item), + Self: Sized, F: FnMut(&Self::Item), { Inspect{iter: self, f: f} } @@ -553,7 +523,7 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(it.next() == Some(5)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn by_ref(&mut self) -> &mut Self { self } + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } /// Loops through the entire iterator, collecting all of the elements into /// a container implementing `FromIterator`. @@ -561,13 +531,13 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` - /// let a = [1, 2, 3, 4, 5]; - /// let b: Vec<_> = a.iter().cloned().collect(); - /// assert_eq!(a, b); + /// let expected = [1, 2, 3, 4, 5]; + /// let actual: Vec<_> = expected.iter().cloned().collect(); + /// assert_eq!(actual, expected); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn collect>(self) -> B { + fn collect>(self) -> B where Self: Sized { FromIterator::from_iter(self) } @@ -577,14 +547,15 @@ pub trait IteratorExt: Iterator + Sized { /// do not. /// /// ``` + /// # #![feature(core)] /// let vec = vec![1, 2, 3, 4]; /// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0); - /// assert_eq!(even, vec![2, 4]); - /// assert_eq!(odd, vec![1, 3]); + /// assert_eq!(even, [2, 4]); + /// assert_eq!(odd, [1, 3]); /// ``` - #[unstable(feature = "core", - reason = "recently added as part of collections reform")] + #[stable(feature = "rust1", since = "1.0.0")] fn partition(self, mut f: F) -> (B, B) where + Self: Sized, B: Default + Extend, F: FnMut(&Self::Item) -> bool { @@ -609,12 +580,12 @@ pub trait IteratorExt: Iterator + Sized { /// /// ``` /// let a = [1, 2, 3, 4, 5]; - /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); + /// assert!(a.iter().fold(0, |acc, &item| acc + item) == 15); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn fold(self, init: B, mut f: F) -> B where - F: FnMut(B, Self::Item) -> B, + Self: Sized, F: FnMut(B, Self::Item) -> B, { let mut accum = init; for x in self { @@ -634,27 +605,34 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn all(self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool { - for x in self { if !f(x) { return false; } } + fn all(&mut self, mut f: F) -> bool where + Self: Sized, F: FnMut(Self::Item) -> bool + { + for x in self.by_ref() { if !f(x) { return false; } } true } - /// Tests whether any element of an iterator satisfies the specified predicate. + /// Tests whether any element of an iterator satisfies the specified + /// predicate. /// /// Does not consume the iterator past the first found element. /// /// # Examples /// /// ``` + /// # #![feature(core)] /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert!(it.any(|x| *x == 3)); - /// assert_eq!(it.as_slice(), [4, 5]); + /// assert_eq!(&it[..], [4, 5]); /// /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn any(&mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool { + fn any(&mut self, mut f: F) -> bool where + Self: Sized, + F: FnMut(Self::Item) -> bool + { for x in self.by_ref() { if f(x) { return true; } } false } @@ -666,13 +644,15 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3); - /// assert_eq!(it.as_slice(), [4, 5]); + /// assert_eq!(&it[..], [4, 5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn find

(&mut self, mut predicate: P) -> Option where + Self: Sized, P: FnMut(&Self::Item) -> bool, { for x in self.by_ref() { @@ -688,13 +668,15 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter(); /// assert_eq!(it.position(|x| *x == 3).unwrap(), 2); - /// assert_eq!(it.as_slice(), [4, 5]); + /// assert_eq!(&it[..], [4, 5]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn position

(&mut self, mut predicate: P) -> Option where + Self: Sized, P: FnMut(Self::Item) -> bool, { let mut i = 0; @@ -716,20 +698,22 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// let a = [1, 2, 2, 4, 5]; /// let mut it = a.iter(); /// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2); - /// assert_eq!(it.as_slice(), [1, 2]); + /// assert_eq!(&it[..], [1, 2]); #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn rposition

(&mut self, mut predicate: P) -> Option where P: FnMut(Self::Item) -> bool, - Self: ExactSizeIterator + DoubleEndedIterator + Self: Sized + ExactSizeIterator + DoubleEndedIterator { - let mut i = self.len() - 1; + let mut i = self.len(); + while let Some(v) = self.next_back() { if predicate(v) { - return Some(i); + return Some(i - 1); } i -= 1; } @@ -738,6 +722,9 @@ pub trait IteratorExt: Iterator + Sized { /// Consumes the entire iterator to return the maximum element. /// + /// Returns the rightmost element if the comparison determines two elements + /// to be equally maximum. + /// /// # Examples /// /// ``` @@ -746,18 +733,21 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn max(self) -> Option where Self::Item: Ord + fn max(self) -> Option where Self: Sized, Self::Item: Ord { - self.fold(None, |max, x| { + self.fold(None, |max, y| { match max { - None => Some(x), - Some(y) => Some(cmp::max(x, y)) + None => Some(y), + Some(x) => Some(cmp::max(x, y)) } }) } /// Consumes the entire iterator to return the minimum element. /// + /// Returns the leftmost element if the comparison determines two elements + /// to be equally minimum. + /// /// # Examples /// /// ``` @@ -766,12 +756,12 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn min(self) -> Option where Self::Item: Ord + fn min(self) -> Option where Self: Sized, Self::Item: Ord { - self.fold(None, |min, x| { + self.fold(None, |min, y| { match min { - None => Some(x), - Some(y) => Some(cmp::min(x, y)) + None => Some(y), + Some(x) => Some(cmp::min(x, y)) } }) } @@ -787,14 +777,16 @@ pub trait IteratorExt: Iterator + Sized { /// element in the iterator and all elements are equal. /// /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons, - /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons. + /// and so is faster than calling `min` and `max` separately which does `2 * + /// n` comparisons. /// /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax}; /// - /// let a: [isize; 0] = []; + /// let a: [i32; 0] = []; /// assert_eq!(a.iter().min_max(), NoElements); /// /// let a = [1]; @@ -807,23 +799,24 @@ pub trait IteratorExt: Iterator + Sized { /// assert!(a.iter().min_max() == MinMax(&1, &1)); /// ``` #[unstable(feature = "core", reason = "return type may change")] - fn min_max(mut self) -> MinMaxResult where Self::Item: Ord + fn min_max(mut self) -> MinMaxResult where Self: Sized, Self::Item: Ord { let (mut min, mut max) = match self.next() { None => return NoElements, Some(x) => { match self.next() { None => return OneElement(x), - Some(y) => if x < y {(x, y)} else {(y,x)} + Some(y) => if x <= y {(x, y)} else {(y, x)} } } }; loop { - // `first` and `second` are the two next elements we want to look at. - // We first compare `first` and `second` (#1). The smaller one is then compared to - // current minimum (#2). The larger one is compared to current maximum (#3). This - // way we do 3 comparisons for 2 elements. + // `first` and `second` are the two next elements we want to look + // at. We first compare `first` and `second` (#1). The smaller one + // is then compared to current minimum (#2). The larger one is + // compared to current maximum (#3). This way we do 3 comparisons + // for 2 elements. let first = match self.next() { None => break, Some(x) => x @@ -832,19 +825,19 @@ pub trait IteratorExt: Iterator + Sized { None => { if first < min { min = first; - } else if first > max { + } else if first >= max { max = first; } break; } Some(x) => x }; - if first < second { - if first < min {min = first;} - if max < second {max = second;} + if first <= second { + if first < min { min = first } + if second >= max { max = second } } else { - if second < min {min = second;} - if max < first {max = first;} + if second < min { min = second } + if first >= max { max = first } } } @@ -854,28 +847,32 @@ pub trait IteratorExt: Iterator + Sized { /// Return the element that gives the maximum value from the /// specified function. /// + /// Returns the rightmost element if the comparison determines two elements + /// to be equally maximum. + /// /// # Examples /// /// ``` - /// use core::num::SignedInt; + /// # #![feature(core)] /// - /// let a = [-3, 0, 1, 5, -10]; + /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().max_by(|x| x.abs()).unwrap(), -10); /// ``` #[inline] #[unstable(feature = "core", reason = "may want to produce an Ordering directly; see #15311")] fn max_by(self, mut f: F) -> Option where + Self: Sized, F: FnMut(&Self::Item) -> B, { - self.fold(None, |max: Option<(Self::Item, B)>, x| { - let x_val = f(&x); + self.fold(None, |max: Option<(Self::Item, B)>, y| { + let y_val = f(&y); match max { - None => Some((x, x_val)), - Some((y, y_val)) => if x_val > y_val { - Some((x, x_val)) - } else { + None => Some((y, y_val)), + Some((x, x_val)) => if y_val >= x_val { Some((y, y_val)) + } else { + Some((x, x_val)) } } }).map(|(x, _)| x) @@ -884,25 +881,29 @@ pub trait IteratorExt: Iterator + Sized { /// Return the element that gives the minimum value from the /// specified function. /// + /// Returns the leftmost element if the comparison determines two elements + /// to be equally minimum. + /// /// # Examples /// /// ``` - /// use core::num::SignedInt; + /// # #![feature(core)] /// - /// let a = [-3, 0, 1, 5, -10]; + /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().min_by(|x| x.abs()).unwrap(), 0); /// ``` #[inline] #[unstable(feature = "core", reason = "may want to produce an Ordering directly; see #15311")] fn min_by(self, mut f: F) -> Option where + Self: Sized, F: FnMut(&Self::Item) -> B, { - self.fold(None, |min: Option<(Self::Item, B)>, x| { - let x_val = f(&x); + self.fold(None, |min: Option<(Self::Item, B)>, y| { + let y_val = f(&y); match min { - None => Some((x, x_val)), - Some((y, y_val)) => if x_val < y_val { + None => Some((y, y_val)), + Some((x, x_val)) => if x_val <= y_val { Some((x, x_val)) } else { Some((y, y_val)) @@ -925,7 +926,7 @@ pub trait IteratorExt: Iterator + Sized { /// `std::usize::MAX` elements of the original iterator. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn rev(self) -> Rev { + fn rev(self) -> Rev where Self: Sized { Rev{iter: self} } @@ -937,16 +938,17 @@ pub trait IteratorExt: Iterator + Sized { /// # Examples /// /// ``` + /// # #![feature(core)] /// let a = [(1, 2), (3, 4)]; /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip(); - /// assert_eq!([1, 3], left); - /// assert_eq!([2, 4], right); + /// assert_eq!(left, [1, 3]); + /// assert_eq!(right, [2, 4]); /// ``` - #[unstable(feature = "core", reason = "recent addition")] + #[stable(feature = "rust1", since = "1.0.0")] fn unzip(self) -> (FromA, FromB) where FromA: Default + Extend, FromB: Default + Extend, - Self: Iterator, + Self: Sized + Iterator, { struct SizeHint(usize, Option, marker::PhantomData); impl Iterator for SizeHint { @@ -973,12 +975,11 @@ pub trait IteratorExt: Iterator + Sized { (ts, us) } - /// Creates an iterator that clones the elements it yields. Useful for converting an - /// Iterator<&T> to an Iterator. - #[unstable(feature = "core", reason = "recent addition")] - fn cloned(self) -> Cloned where - Self::Item: Deref, - ::Output: Clone, + /// Creates an iterator that clones the elements it yields. Useful for + /// converting an Iterator<&T> to an Iterator. + #[stable(feature = "rust1", since = "1.0.0")] + fn cloned<'a, T: 'a>(self) -> Cloned + where Self: Sized + Iterator, T: Clone { Cloned { it: self } } @@ -996,7 +997,7 @@ pub trait IteratorExt: Iterator + Sized { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - fn cycle(self) -> Cycle where Self: Clone { + fn cycle(self) -> Cycle where Self: Sized + Clone { Cycle{orig: self.clone(), iter: self} } @@ -1004,7 +1005,7 @@ pub trait IteratorExt: Iterator + Sized { #[unstable(feature = "core", reason = "uncertain about placement or widespread use")] fn reverse_in_place<'a, T: 'a>(&mut self) where - Self: Iterator + DoubleEndedIterator + Self: Sized + Iterator + DoubleEndedIterator { loop { match (self.next(), self.next_back()) { @@ -1016,7 +1017,80 @@ pub trait IteratorExt: Iterator + Sized { } #[stable(feature = "rust1", since = "1.0.0")] -impl IteratorExt for I where I: Iterator {} +impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I { + type Item = I::Item; + fn next(&mut self) -> Option { (**self).next() } + fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } +} + +/// Conversion from an `Iterator` +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ + built from an iterator over elements of type `{A}`"] +pub trait FromIterator { + /// Build a container with elements from something iterable. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashSet; + /// use std::iter::FromIterator; + /// + /// let colors_vec = vec!["red", "red", "yellow", "blue"]; + /// let colors_set = HashSet::<&str>::from_iter(colors_vec); + /// assert_eq!(colors_set.len(), 3); + /// ``` + /// + /// `FromIterator` is more commonly used implicitly via the + /// `Iterator::collect` method: + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let colors_vec = vec!["red", "red", "yellow", "blue"]; + /// let colors_set = colors_vec.into_iter().collect::>(); + /// assert_eq!(colors_set.len(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + fn from_iter>(iterator: T) -> Self; +} + +/// Conversion into an `Iterator` +/// +/// Implementing this trait allows you to use your type with Rust's `for` loop. See +/// the [module level documentation](../index.html) for more details. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IntoIterator { + /// The type of the elements being iterated + #[stable(feature = "rust1", since = "1.0.0")] + type Item; + + /// A container for iterating over elements of type Item + #[stable(feature = "rust1", since = "1.0.0")] + type IntoIter: Iterator; + + /// Consumes `Self` and returns an iterator over it + #[stable(feature = "rust1", since = "1.0.0")] + fn into_iter(self) -> Self::IntoIter; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for I { + type Item = I::Item; + type IntoIter = I; + + fn into_iter(self) -> I { + self + } +} + +/// A type growable from an `Iterator` implementation +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Extend { + /// Extend a container with the elements yielded by an arbitrary iterator + #[stable(feature = "rust1", since = "1.0.0")] + fn extend>(&mut self, iterable: T); +} /// A range iterator able to yield elements from both ends /// @@ -1038,12 +1112,13 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { /// An object implementing random access indexing by `usize` /// -/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`. -/// Calling `next()` or `next_back()` on a `RandomAccessIterator` -/// reduces the indexable range accordingly. That is, `it.idx(1)` will become `it.idx(0)` -/// after `it.next()` is called. +/// A `RandomAccessIterator` should be either infinite or a +/// `DoubleEndedIterator`. Calling `next()` or `next_back()` on a +/// `RandomAccessIterator` reduces the indexable range accordingly. That is, +/// `it.idx(1)` will become `it.idx(0)` after `it.next()` is called. #[unstable(feature = "core", - reason = "not widely used, may be better decomposed into Index and ExactSizeIterator")] + reason = "not widely used, may be better decomposed into Index \ + and ExactSizeIterator")] pub trait RandomAccessIterator: Iterator { /// Return the number of indexable elements. At most `std::usize::MAX` /// elements are indexable, even if the iterator represents a longer range. @@ -1088,13 +1163,15 @@ impl ExactSizeIterator for Inspect where F: FnMut(&I::Item), {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Rev where I: ExactSizeIterator + DoubleEndedIterator {} +impl ExactSizeIterator for Rev + where I: ExactSizeIterator + DoubleEndedIterator {} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Map where F: FnMut(I::Item) -> B, {} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Zip where A: ExactSizeIterator, B: ExactSizeIterator {} +impl ExactSizeIterator for Zip + where A: ExactSizeIterator, B: ExactSizeIterator {} /// An double-ended iterator with the direction inverted #[derive(Clone)] @@ -1121,13 +1198,19 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Rev where I: DoubleEndedIterator + RandomAccessIterator { +impl RandomAccessIterator for Rev + where I: DoubleEndedIterator + RandomAccessIterator +{ #[inline] fn indexable(&self) -> usize { self.iter.indexable() } #[inline] fn idx(&mut self, index: usize) -> Option<::Item> { let amt = self.indexable(); - self.iter.idx(amt - index - 1) + if amt > index { + self.iter.idx(amt - index - 1) + } else { + None + } } } @@ -1140,9 +1223,10 @@ pub trait AdditiveIterator { /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::iter::AdditiveIterator; /// - /// let a = [1i32, 2, 3, 4, 5]; + /// let a = [1, 2, 3, 4, 5]; /// let mut it = a.iter().cloned(); /// assert!(it.sum() == 15); /// ``` @@ -1182,10 +1266,11 @@ pub trait MultiplicativeIterator { /// # Examples /// /// ``` - /// use std::iter::{count, MultiplicativeIterator}; + /// # #![feature(core)] + /// use std::iter::MultiplicativeIterator; /// /// fn factorial(n: usize) -> usize { - /// count(1, 1).take_while(|&i| i <= n).product() + /// (1..).take_while(|&i| i <= n).product() /// } /// assert!(factorial(0) == 1); /// assert!(factorial(1) == 1); @@ -1218,7 +1303,8 @@ impl_multiplicative! { usize, 1 } impl_multiplicative! { f32, 1.0 } impl_multiplicative! { f64, 1.0 } -/// `MinMaxResult` is an enum returned by `min_max`. See `IteratorOrdExt::min_max` for more detail. +/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for +/// more detail. #[derive(Clone, PartialEq, Debug)] #[unstable(feature = "core", reason = "unclear whether such a fine-grained result is widely useful")] @@ -1229,22 +1315,25 @@ pub enum MinMaxResult { /// Iterator with one element, so the minimum and maximum are the same OneElement(T), - /// More than one element in the iterator, the first element is not larger than the second + /// More than one element in the iterator, the first element is not larger + /// than the second MinMax(T, T) } impl MinMaxResult { - /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant - /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant - /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`, - /// performing this operation will make one clone of `x`. + /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` + /// has variant `None` if and only if the `MinMaxResult` has variant + /// `NoElements`. Otherwise variant `Some(x,y)` is returned where `x <= y`. + /// If `MinMaxResult` has variant `OneElement(x)`, performing this operation + /// will make one clone of `x`. /// /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::iter::MinMaxResult::{self, NoElements, OneElement, MinMax}; /// - /// let r: MinMaxResult = NoElements; + /// let r: MinMaxResult = NoElements; /// assert_eq!(r.into_option(), None); /// /// let r = OneElement(1); @@ -1272,10 +1361,8 @@ pub struct Cloned { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Cloned where - T: Clone, - D: Deref, - I: Iterator, +impl<'a, I, T: 'a> Iterator for Cloned + where I: Iterator, T: Clone { type Item = T; @@ -1289,10 +1376,8 @@ impl Iterator for Cloned where } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Cloned where - T: Clone, - D: Deref, - I: DoubleEndedIterator, +impl<'a, I, T: 'a> DoubleEndedIterator for Cloned + where I: DoubleEndedIterator, T: Clone { fn next_back(&mut self) -> Option { self.it.next_back().cloned() @@ -1300,17 +1385,13 @@ impl DoubleEndedIterator for Cloned where } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Cloned where - T: Clone, - D: Deref, - I: ExactSizeIterator, +impl<'a, I, T: 'a> ExactSizeIterator for Cloned + where I: ExactSizeIterator, T: Clone {} #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Cloned where - T: Clone, - D: Deref, - I: RandomAccessIterator +impl<'a, I, T: 'a> RandomAccessIterator for Cloned + where I: RandomAccessIterator, T: Clone { #[inline] fn indexable(&self) -> usize { @@ -1393,11 +1474,14 @@ pub struct Chain { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Chain where A: Iterator, B: Iterator { - type Item = T; +impl Iterator for Chain where + A: Iterator, + B: Iterator +{ + type Item = A::Item; #[inline] - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.flag { self.b.next() } else { @@ -1427,12 +1511,12 @@ impl Iterator for Chain where A: Iterator, B: Iterator DoubleEndedIterator for Chain where - A: DoubleEndedIterator, - B: DoubleEndedIterator, +impl DoubleEndedIterator for Chain where + A: DoubleEndedIterator, + B: DoubleEndedIterator, { #[inline] - fn next_back(&mut self) -> Option { + fn next_back(&mut self) -> Option { match self.b.next_back() { Some(x) => Some(x), None => self.a.next_back() @@ -1441,9 +1525,9 @@ impl DoubleEndedIterator for Chain where } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Chain where - A: RandomAccessIterator, - B: RandomAccessIterator, +impl RandomAccessIterator for Chain where + A: RandomAccessIterator, + B: RandomAccessIterator, { #[inline] fn indexable(&self) -> usize { @@ -1452,7 +1536,7 @@ impl RandomAccessIterator for Chain where } #[inline] - fn idx(&mut self, index: usize) -> Option { + fn idx(&mut self, index: usize) -> Option { let len = self.a.indexable(); if index < len { self.a.idx(index) @@ -1472,14 +1556,12 @@ pub struct Zip { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Zip where - A: Iterator, - B: Iterator, +impl Iterator for Zip where A: Iterator, B: Iterator { - type Item = (T, U); + type Item = (A::Item, B::Item); #[inline] - fn next(&mut self) -> Option<(T, U)> { + fn next(&mut self) -> Option<(A::Item, B::Item)> { match self.a.next() { None => None, Some(x) => match self.b.next() { @@ -1508,12 +1590,12 @@ impl Iterator for Zip where } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Zip where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator, +impl DoubleEndedIterator for Zip where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, { #[inline] - fn next_back(&mut self) -> Option<(T, U)> { + fn next_back(&mut self) -> Option<(A::Item, B::Item)> { let a_sz = self.a.len(); let b_sz = self.b.len(); if a_sz != b_sz { @@ -1533,9 +1615,9 @@ impl DoubleEndedIterator for Zip where } #[unstable(feature = "core", reason = "trait is experimental")] -impl RandomAccessIterator for Zip where - A: RandomAccessIterator, - B: RandomAccessIterator, +impl RandomAccessIterator for Zip where + A: RandomAccessIterator, + B: RandomAccessIterator { #[inline] fn indexable(&self) -> usize { @@ -1543,7 +1625,7 @@ impl RandomAccessIterator for Zip where } #[inline] - fn idx(&mut self, index: usize) -> Option<(T, U)> { + fn idx(&mut self, index: usize) -> Option<(A::Item, B::Item)> { match self.a.idx(index) { None => None, Some(x) => match self.b.idx(index) { @@ -1563,24 +1645,13 @@ pub struct Map { f: F, } -impl Map where F: FnMut(I::Item) -> B { - #[inline] - fn do_map(&mut self, elt: Option) -> Option { - match elt { - Some(a) => Some((self.f)(a)), - _ => None - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Map where F: FnMut(I::Item) -> B { type Item = B; #[inline] fn next(&mut self) -> Option { - let next = self.iter.next(); - self.do_map(next) + self.iter.next().map(|a| (self.f)(a)) } #[inline] @@ -1595,8 +1666,7 @@ impl DoubleEndedIterator for Map where { #[inline] fn next_back(&mut self) -> Option { - let next = self.iter.next_back(); - self.do_map(next) + self.iter.next_back().map(|a| (self.f)(a)) } } @@ -1611,8 +1681,7 @@ impl RandomAccessIterator for Map where #[inline] fn idx(&mut self, index: usize) -> Option { - let elt = self.iter.idx(index); - self.do_map(elt) + self.iter.idx(index).map(|a| (self.f)(a)) } } @@ -1634,8 +1703,6 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool for x in self.iter.by_ref() { if (self.predicate)(&x) { return Some(x); - } else { - continue } } None @@ -2061,12 +2128,14 @@ pub struct Scan { f: F, /// The current internal state to be passed to the closure next. + #[unstable(feature = "core")] pub state: St, } #[stable(feature = "rust1", since = "1.0.0")] -impl, St, F> Iterator for Scan where - F: FnMut(&mut St, A) -> Option, +impl Iterator for Scan where + I: Iterator, + F: FnMut(&mut St, I::Item) -> Option, { type Item = B; @@ -2301,11 +2370,12 @@ impl RandomAccessIterator for Inspect /// An iterator that passes mutable state to a closure and yields the result. /// -/// # Example: The Fibonacci Sequence +/// # Examples /// /// An iterator that yields sequential Fibonacci numbers, and stops on overflow. /// /// ``` +/// # #![feature(core)] /// use std::iter::Unfold; /// use std::num::Int; // For `.checked_add()` /// @@ -2338,6 +2408,7 @@ impl RandomAccessIterator for Inspect pub struct Unfold { f: F, /// Internal state that will be passed to the closure on the next iteration + #[unstable(feature = "core")] pub state: St, } @@ -2370,140 +2441,152 @@ impl Iterator for Unfold where F: FnMut(&mut St) -> Option { } } -/// An infinite iterator starting at `start` and advancing by `step` with each -/// iteration -#[derive(Clone)] -#[unstable(feature = "core", - reason = "may be renamed or replaced by range notation adapters")] -pub struct Counter { - /// The current state the counter is at (next value to be yielded) - state: A, - /// The amount that this iterator is stepping by - step: A, +/// Objects that can be stepped over in both directions. +/// +/// The `steps_between` function provides a way to efficiently compare +/// two `Step` objects. +#[unstable(feature = "step_trait", + reason = "likely to be replaced by finer-grained traits")] +pub trait Step: Ord { + /// Steps `self` if possible. + fn step(&self, by: &Self) -> Option; + + /// The number of steps between two step objects. + /// + /// `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(start: &Self, end: &Self, by: &Self) -> Option; } -/// Creates a new counter with the specified start/step -#[inline] -#[unstable(feature = "core", - reason = "may be renamed or replaced by range notation adapters")] -pub fn count(start: A, step: A) -> Counter { - Counter{state: start, step: step} +macro_rules! step_impl { + ($($t:ty)*) => ($( + impl Step for $t { + #[inline] + fn step(&self, by: &$t) -> Option<$t> { + (*self).checked_add(*by) + } + #[inline] + #[allow(trivial_numeric_casts)] + fn steps_between(start: &$t, end: &$t, by: &$t) -> Option { + if *start <= *end { + Some(((*end - *start) / *by) as usize) + } else { + Some(0) + } + } + } + )*) } -#[stable(feature = "rust1", since = "1.0.0")] -impl + Clone> Iterator for Counter { - type Item = A; +macro_rules! step_impl_no_between { + ($($t:ty)*) => ($( + impl Step for $t { + #[inline] + fn step(&self, by: &$t) -> Option<$t> { + (*self).checked_add(*by) + } + #[inline] + fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option { + None + } + } + )*) +} - #[inline] - fn next(&mut self) -> Option { - let result = self.state.clone(); - self.state = self.state.clone() + self.step.clone(); - Some(result) - } +step_impl!(usize u8 u16 u32 isize i8 i16 i32); +#[cfg(target_pointer_width = "64")] +step_impl!(u64 i64); +#[cfg(target_pointer_width = "32")] +step_impl_no_between!(u64 i64); - #[inline] - fn size_hint(&self) -> (usize, Option) { - (usize::MAX, None) // Too bad we can't specify an infinite lower bound - } +/// An adapter for stepping range iterators by a custom amount. +/// +/// The resulting iterator handles overflow by stopping. The `A` +/// parameter is the type being iterated over, while `R` is the range +/// type (usually one of `std::ops::{Range, RangeFrom}`. +#[derive(Clone)] +#[unstable(feature = "step_by", reason = "recent addition")] +pub struct StepBy { + step_by: A, + range: R, } -/// An iterator over the range [start, stop) -#[derive(Clone)] -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -pub struct Range { - state: A, - stop: A, - one: A, +impl RangeFrom { + /// Creates an iterator starting at the same point, but stepping by + /// the given amount at each iteration. + /// + /// # Examples + /// + /// ```ignore + /// for i in (0u8..).step_by(2) { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints all even `u8` values. + #[unstable(feature = "step_by", reason = "recent addition")] + pub fn step_by(self, by: A) -> StepBy { + StepBy { + step_by: by, + range: self + } + } } -/// Returns an iterator over the given range [start, stop) (that is, starting -/// at start (inclusive), and ending at stop (exclusive)). -/// -/// # Examples -/// -/// ``` -/// let array = [0, 1, 2, 3, 4]; -/// -/// for i in range(0, 5) { -/// println!("{}", i); -/// assert_eq!(i, array[i]); -/// } -/// ``` -#[inline] -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -pub fn range(start: A, stop: A) -> Range { - Range { - state: start, - stop: stop, - one: Int::one(), +#[allow(deprecated)] +impl ops::Range { + /// Creates an iterator with the same range, but stepping by the + /// given amount at each iteration. + /// + /// The resulting iterator handles overflow by stopping. + /// + /// # Examples + /// + /// ``` + /// # #![feature(step_by, core)] + /// for i in (0..10).step_by(2) { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// 0 + /// 2 + /// 4 + /// 6 + /// 8 + /// ``` + #[unstable(feature = "step_by", reason = "recent addition")] + pub fn step_by(self, by: A) -> StepBy { + StepBy { + step_by: by, + range: self + } } } -// FIXME: #10414: Unfortunate type bound -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -impl Iterator for Range { +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for StepBy> where + A: Clone, + for<'a> &'a A: Add<&'a A, Output = A> +{ type Item = A; #[inline] fn next(&mut self) -> Option { - if self.state < self.stop { - let result = self.state.clone(); - self.state = self.state + self.one; - Some(result) - } else { - None - } + let mut n = &self.range.start + &self.step_by; + mem::swap(&mut n, &mut self.range.start); + Some(n) } #[inline] fn size_hint(&self) -> (usize, Option) { - // This first checks if the elements are representable as i64. If they aren't, try u64 (to - // handle cases like range(huge, huger)). We don't use usize/isize because the difference of - // the i64/u64 might lie within their range. - let bound = match self.state.to_i64() { - Some(a) => { - let sz = self.stop.to_i64().map(|b| b.checked_sub(a)); - match sz { - Some(Some(bound)) => bound.to_uint(), - _ => None, - } - }, - None => match self.state.to_u64() { - Some(a) => { - let sz = self.stop.to_u64().map(|b| b.checked_sub(a)); - match sz { - Some(Some(bound)) => bound.to_uint(), - _ => None - } - }, - None => None - } - }; - - match bound { - Some(b) => (b, Some(b)), - // Standard fallback for unbounded/unrepresentable bounds - None => (0, None) - } - } -} - -/// `Int` is required to ensure the range will be the same regardless of -/// the direction it is consumed. -#[unstable(feature = "core", - reason = "will be replaced by range notation")] -impl DoubleEndedIterator for Range { - #[inline] - fn next_back(&mut self) -> Option { - if self.stop > self.state { - self.stop = self.stop - self.one; - Some(self.stop.clone()) - } else { - None - } + (usize::MAX, None) // Too bad we can't specify an infinite lower bound } } @@ -2512,7 +2595,7 @@ impl DoubleEndedIterator for Range { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] pub struct RangeInclusive { - range: Range, + range: ops::Range, done: bool, } @@ -2520,16 +2603,18 @@ pub struct RangeInclusive { #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { +pub fn range_inclusive(start: A, stop: A) -> RangeInclusive + where A: Step + One + Clone +{ RangeInclusive { - range: range(start, stop), + range: start..stop, done: false, } } #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -impl Iterator for RangeInclusive { +impl Iterator for RangeInclusive { type Item = A; #[inline] @@ -2537,9 +2622,9 @@ impl Iterator for RangeInclusive { match self.range.next() { Some(x) => Some(x), None => { - if !self.done && self.range.state == self.range.stop { + if !self.done && self.range.start == self.range.end { self.done = true; - Some(self.range.stop.clone()) + Some(self.range.end.clone()) } else { None } @@ -2565,56 +2650,47 @@ impl Iterator for RangeInclusive { #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] -impl DoubleEndedIterator for RangeInclusive { +impl DoubleEndedIterator for RangeInclusive + where A: Step + One + Clone, + for<'a> &'a A: Sub +{ #[inline] fn next_back(&mut self) -> Option { - if self.range.stop > self.range.state { - let result = self.range.stop.clone(); - self.range.stop = self.range.stop - self.range.one; + if self.range.end > self.range.start { + let result = self.range.end.clone(); + self.range.end = &self.range.end - &A::one(); Some(result) - } else if !self.done && self.range.state == self.range.stop { + } else if !self.done && self.range.start == self.range.end { self.done = true; - Some(self.range.stop.clone()) + Some(self.range.end.clone()) } else { None } } } -/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[derive(Clone)] -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -pub struct RangeStep { - state: A, - stop: A, - step: A, - rev: bool, -} - -/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[inline] -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -pub fn range_step(start: A, stop: A, step: A) -> RangeStep { - let rev = step < Int::zero(); - RangeStep{state: start, stop: stop, step: step, rev: rev} -} - -#[unstable(feature = "core", - reason = "likely to be replaced by range notation and adapters")] -impl Iterator for RangeStep { +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] +impl Iterator for StepBy> { type Item = A; #[inline] fn next(&mut self) -> Option { - if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) { - let result = self.state; - match self.state.checked_add(self.step) { - Some(x) => self.state = x, - None => self.state = self.stop.clone() + let rev = self.step_by < A::zero(); + if (rev && self.range.start > self.range.end) || + (!rev && self.range.start < self.range.end) + { + match self.range.start.step(&self.step_by) { + Some(mut n) => { + mem::swap(&mut self.range.start, &mut n); + Some(n) + }, + None => { + let mut n = self.range.end.clone(); + mem::swap(&mut self.range.start, &mut n); + Some(n) + } } - Some(result) } else { None } @@ -2633,10 +2709,35 @@ pub struct RangeStepInclusive { done: bool, } -/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. +/// Return an iterator over the range [start, stop] by `step`. +/// +/// It handles overflow by stopping. +/// +/// # Examples +/// +/// ``` +/// # #![feature(core)] +/// use std::iter::range_step_inclusive; +/// +/// for i in range_step_inclusive(0, 10, 2) { +/// println!("{}", i); +/// } +/// ``` +/// +/// This prints: +/// +/// ```text +/// 0 +/// 2 +/// 4 +/// 6 +/// 8 +/// 10 +/// ``` #[inline] #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[allow(deprecated)] pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive { let rev = step < Int::zero(); RangeStepInclusive { @@ -2650,6 +2751,7 @@ pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepIncl #[unstable(feature = "core", reason = "likely to be replaced by range notation and adapters")] +#[allow(deprecated)] impl Iterator for RangeStepInclusive { type Item = A; @@ -2672,20 +2774,30 @@ impl Iterator for RangeStepInclusive { macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl ExactSizeIterator for ::ops::Range<$t> { } + impl ExactSizeIterator for ops::Range<$t> { } )*) } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ::ops::Range { +#[allow(deprecated)] +impl Iterator for ops::Range { type Item = A; #[inline] fn next(&mut self) -> Option { if self.start < self.end { - let result = self.start; - self.start = self.start + Int::one(); - Some(result) + match self.start.step(&A::one()) { + Some(mut n) => { + mem::swap(&mut n, &mut self.start); + Some(n) + }, + None => { + let mut n = self.end.clone(); + mem::swap(&mut n, &mut self.start); + Some(n) + + } + } } else { None } @@ -2693,11 +2805,10 @@ impl Iterator for ::ops::Range { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.start >= self.end { - (0, Some(0)) + if let Some(hint) = Step::steps_between(&self.start, &self.end, &A::one()) { + (hint, Some(hint)) } else { - let length = (self.end - self.start).to_uint(); - (length.unwrap_or(0), length) + (0, None) } } } @@ -2707,12 +2818,15 @@ impl Iterator for ::ops::Range { range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ::ops::Range { +#[allow(deprecated)] +impl DoubleEndedIterator for ops::Range where + for<'a> &'a A: Sub<&'a A, Output = A> +{ #[inline] fn next_back(&mut self) -> Option { if self.start < self.end { - self.end = self.end - Int::one(); - Some(self.end) + self.end = &self.end - &A::one(); + Some(self.end.clone()) } else { None } @@ -2720,15 +2834,16 @@ impl DoubleEndedIterator for ::ops::Range { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ::ops::RangeFrom { +#[allow(deprecated)] +impl Iterator for ops::RangeFrom { type Item = A; #[inline] fn next(&mut self) -> Option { - let result = self.start; - self.start = self.start + Int::one(); - debug_assert!(result < self.start); - Some(result) + self.start.step(&A::one()).map(|mut n| { + mem::swap(&mut n, &mut self.start); + n + }) } } @@ -2825,10 +2940,10 @@ pub mod order { use super::Iterator; /// Compare `a` and `b` for equality using `Eq` - pub fn equals(mut a: T, mut b: S) -> bool where + pub fn equals(mut a: L, mut b: R) -> bool where A: Eq, - T: Iterator, - S: Iterator, + L: Iterator, + R: Iterator, { loop { match (a.next(), b.next()) { @@ -2840,10 +2955,10 @@ pub mod order { } /// Order `a` and `b` lexicographically using `Ord` - pub fn cmp(mut a: T, mut b: S) -> cmp::Ordering where + pub fn cmp(mut a: L, mut b: R) -> cmp::Ordering where A: Ord, - T: Iterator, - S: Iterator, + L: Iterator, + R: Iterator, { loop { match (a.next(), b.next()) { @@ -2859,10 +2974,8 @@ pub mod order { } /// Order `a` and `b` lexicographically using `PartialOrd` - pub fn partial_cmp(mut a: T, mut b: S) -> Option where - A: PartialOrd, - T: Iterator, - S: Iterator, + pub fn partial_cmp(mut a: L, mut b: R) -> Option where + L::Item: PartialOrd { loop { match (a.next(), b.next()) { @@ -2878,10 +2991,8 @@ pub mod order { } /// Compare `a` and `b` for equality (Using partial equality, `PartialEq`) - pub fn eq(mut a: L, mut b: R) -> bool where - A: PartialEq, - L: Iterator, - R: Iterator, + pub fn eq(mut a: L, mut b: R) -> bool where + L::Item: PartialEq, { loop { match (a.next(), b.next()) { @@ -2893,10 +3004,8 @@ pub mod order { } /// Compare `a` and `b` for nonequality (Using partial equality, `PartialEq`) - pub fn ne(mut a: L, mut b: R) -> bool where - A: PartialEq, - L: Iterator, - R: Iterator, + pub fn ne(mut a: L, mut b: R) -> bool where + L::Item: PartialEq, { loop { match (a.next(), b.next()) { @@ -2908,10 +3017,8 @@ pub mod order { } /// Return `a` < `b` lexicographically (Using partial order, `PartialOrd`) - pub fn lt(mut a: T, mut b: S) -> bool where - A: PartialOrd, - T: Iterator, - S: Iterator, + pub fn lt(mut a: L, mut b: R) -> bool where + L::Item: PartialOrd, { loop { match (a.next(), b.next()) { @@ -2924,10 +3031,8 @@ pub mod order { } /// Return `a` <= `b` lexicographically (Using partial order, `PartialOrd`) - pub fn le(mut a: T, mut b: S) -> bool where - A: PartialOrd, - T: Iterator, - S: Iterator, + pub fn le(mut a: L, mut b: R) -> bool where + L::Item: PartialOrd, { loop { match (a.next(), b.next()) { @@ -2940,10 +3045,8 @@ pub mod order { } /// Return `a` > `b` lexicographically (Using partial order, `PartialOrd`) - pub fn gt(mut a: T, mut b: S) -> bool where - A: PartialOrd, - T: Iterator, - S: Iterator, + pub fn gt(mut a: L, mut b: R) -> bool where + L::Item: PartialOrd, { loop { match (a.next(), b.next()) { @@ -2956,10 +3059,8 @@ pub mod order { } /// Return `a` >= `b` lexicographically (Using partial order, `PartialOrd`) - pub fn ge(mut a: T, mut b: S) -> bool where - A: PartialOrd, - T: Iterator, - S: Iterator, + pub fn ge(mut a: L, mut b: R) -> bool where + L::Item: PartialOrd, { loop { match (a.next(), b.next()) { diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 3c58480ff0..2189e2c3ad 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -35,11 +35,10 @@ //! often generated by LLVM. Additionally, this library can make explicit //! calls to these functions. Their signatures are the same as found in C. //! These functions are often provided by the system libc, but can also be -//! provided by `librlibc` which is distributed with the standard rust -//! distribution. +//! provided by the [rlibc crate](https://crates.io/crates/rlibc). //! //! * `rust_begin_unwind` - This function takes three arguments, a -//! `fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate +//! `fmt::Arguments`, a `&str`, and a `usize`. These three arguments dictate //! the panic message, the file at which panic was invoked, and the line. //! It is up to consumers of this core library to define this panic //! function; it is only required to never return. @@ -47,6 +46,8 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "core"] #![unstable(feature = "core")] #![staged_api] @@ -55,23 +56,31 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] +#![doc(test(no_crate_inject))] #![feature(no_std)] #![no_std] #![allow(raw_pointer_derive)] #![deny(missing_docs)] -#![feature(int_uint)] #![feature(intrinsics, lang_items)] #![feature(on_unimplemented)] #![feature(simd, unsafe_destructor)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(rustc_attrs)] +#![feature(optin_builtin_traits)] +#![feature(fundamental)] +#![feature(concat_idents)] +#![feature(reflect)] +#![feature(custom_attribute)] #[macro_use] mod macros; +#[macro_use] +mod cmp_macros; + #[path = "num/float_macros.rs"] #[macro_use] mod float_macros; @@ -84,14 +93,12 @@ mod int_macros; #[macro_use] mod uint_macros; -#[path = "num/int.rs"] pub mod int; #[path = "num/isize.rs"] pub mod isize; #[path = "num/i8.rs"] pub mod i8; #[path = "num/i16.rs"] pub mod i16; #[path = "num/i32.rs"] pub mod i32; #[path = "num/i64.rs"] pub mod i64; -#[path = "num/uint.rs"] pub mod uint; #[path = "num/usize.rs"] pub mod usize; #[path = "num/u8.rs"] pub mod u8; #[path = "num/u16.rs"] pub mod u16; @@ -121,15 +128,16 @@ pub mod ops; pub mod cmp; pub mod clone; pub mod default; +pub mod convert; /* Core types and methods on primitives */ pub mod any; +pub mod array; pub mod atomic; pub mod cell; pub mod char; pub mod panicking; -pub mod finally; pub mod iter; pub mod option; pub mod raw; @@ -139,7 +147,6 @@ pub mod slice; pub mod str; pub mod hash; pub mod fmt; -pub mod error; #[doc(primitive = "bool")] mod bool { @@ -147,7 +154,6 @@ mod bool { // note: does not need to be public mod tuple; -mod array; #[doc(hidden)] mod core { diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 943365d845..751bd7353e 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -15,7 +15,7 @@ macro_rules! panic { panic!("explicit panic") ); ($msg:expr) => ({ - static _MSG_FILE_LINE: (&'static str, &'static str, usize) = ($msg, file!(), line!()); + static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!()); ::core::panicking::panic(&_MSG_FILE_LINE) }); ($fmt:expr, $($arg:tt)*) => ({ @@ -23,7 +23,7 @@ macro_rules! panic { // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, usize) = (file!(), line!()); + static _FILE_LINE: (&'static str, u32) = (file!(), line!()); ::core::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE) }); } @@ -33,7 +33,7 @@ macro_rules! panic { /// This will invoke the `panic!` macro if the provided expression cannot be /// evaluated to `true` at runtime. /// -/// # Example +/// # Examples /// /// ``` /// // the panic message for these assertions is the stringified value of the @@ -66,12 +66,12 @@ macro_rules! assert { ); } -/// Asserts that two expressions are equal to each other, testing equality in -/// both directions. +/// Asserts that two expressions are equal to each other. /// -/// On panic, this macro will print the values of the expressions. +/// On panic, this macro will print the values of the expressions with their +/// debug representations. /// -/// # Example +/// # Examples /// /// ``` /// let a = 3; @@ -84,10 +84,8 @@ macro_rules! assert_eq { ($left:expr , $right:expr) => ({ match (&($left), &($right)) { (left_val, right_val) => { - // check both directions of equality.... - if !((*left_val == *right_val) && - (*right_val == *left_val)) { - panic!("assertion failed: `(left == right) && (right == left)` \ + if !(*left_val == *right_val) { + panic!("assertion failed: `(left == right)` \ (left: `{:?}`, right: `{:?}`)", *left_val, *right_val) } } @@ -100,12 +98,14 @@ macro_rules! assert_eq { /// This will invoke the `panic!` macro if the provided expression cannot be /// evaluated to `true` at runtime. /// -/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing -/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for -/// checks that are too expensive to be present in a release build but may be -/// helpful during development. +/// Unlike `assert!`, `debug_assert!` statements are only enabled in non +/// optimized builds by default. An optimized build will omit all +/// `debug_assert!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. /// -/// # Example +/// # Examples /// /// ``` /// // the panic message for these assertions is the stringified value of the @@ -125,7 +125,7 @@ macro_rules! assert_eq { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); }) + ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); }) } /// Asserts that two expressions are equal to each other, testing equality in @@ -133,12 +133,14 @@ macro_rules! debug_assert { /// /// On panic, this macro will print the values of the expressions. /// -/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by -/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!` -/// useful for checks that are too expensive to be present in a release build -/// but may be helpful during development. +/// Unlike `assert_eq!`, `debug_assert_eq!` statements are only enabled in non +/// optimized builds by default. An optimized build will omit all +/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the +/// compiler. This makes `debug_assert_eq!` useful for checks that are too +/// expensive to be present in a release build but may be helpful during +/// development. /// -/// # Example +/// # Examples /// /// ``` /// let a = 3; @@ -147,12 +149,12 @@ macro_rules! debug_assert { /// ``` #[macro_export] macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); }) + ($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); }) } /// Short circuiting evaluation on Err /// -/// `libstd` contains a more general `try!` macro that uses `FromError`. +/// `libstd` contains a more general `try!` macro that uses `From`. #[macro_export] macro_rules! try { ($e:expr) => ({ @@ -168,10 +170,11 @@ macro_rules! try { /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. /// See `std::fmt` for more information. /// -/// # Example +/// # Examples /// /// ``` /// # #![allow(unused_must_use)] +/// use std::io::Write; /// /// let mut w = Vec::new(); /// write!(&mut w, "test"); @@ -212,8 +215,8 @@ macro_rules! writeln { /// /// Match arms: /// -/// ```rust -/// fn foo(x: Option) { +/// ``` +/// fn foo(x: Option) { /// match x { /// Some(n) if n >= 0 => println!("Some(Non-negative)"), /// Some(n) if n < 0 => println!("Some(Negative)"), @@ -225,9 +228,10 @@ macro_rules! writeln { /// /// Iterators: /// -/// ```rust +/// ``` +/// # #![feature(core)] /// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3 -/// for i in std::iter::count(0_u32, 1) { +/// for i in 0.. { /// if 3*i < i { panic!("u32 overflow"); } /// if x < 3*i { return i-1; } /// } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d284eb3417..619f983aee 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -31,28 +31,25 @@ use option::Option; use hash::Hash; use hash::Hasher; -/// Types able to be transferred across thread boundaries. -#[unstable(feature = "core", - reason = "will be overhauled with new lifetime rules; see RFC 458")] -#[lang="send"] -#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] -#[cfg(stage0)] -pub unsafe trait Send: 'static { - // empty. -} /// Types able to be transferred across thread boundaries. #[stable(feature = "rust1", since = "1.0.0")] #[lang="send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] -#[cfg(not(stage0))] pub unsafe trait Send : MarkerTrait { // empty. } +unsafe impl Send for .. { } + +impl !Send for *const T { } +impl !Send for *mut T { } +impl !Send for Managed { } + /// Types with a constant size known at compile-time. #[stable(feature = "rust1", since = "1.0.0")] #[lang="sized"] #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] +#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable pub trait Sized : MarkerTrait { // Empty. } @@ -79,7 +76,7 @@ pub trait Sized : MarkerTrait { /// /// ``` /// // we can just derive a `Copy` implementation -/// #[derive(Debug, Copy)] +/// #[derive(Debug, Copy, Clone)] /// struct Foo; /// /// let x = Foo; @@ -128,7 +125,7 @@ pub trait Sized : MarkerTrait { /// There are two ways to implement `Copy` on your type: /// /// ``` -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct MyStruct; /// ``` /// @@ -137,6 +134,7 @@ pub trait Sized : MarkerTrait { /// ``` /// struct MyStruct; /// impl Copy for MyStruct {} +/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } } /// ``` /// /// There is a small difference between the two: the `derive` strategy will also place a `Copy` @@ -158,7 +156,7 @@ pub trait Sized : MarkerTrait { /// change: that second example would fail to compile if we made `Foo` non-`Copy`. #[stable(feature = "rust1", since = "1.0.0")] #[lang="copy"] -pub trait Copy : MarkerTrait { +pub trait Copy : Clone { // Empty. } @@ -199,14 +197,9 @@ pub trait Copy : MarkerTrait { /// the `sync` crate do ensure that any mutation cannot cause data /// races. Hence these types are `Sync`. /// -/// Users writing their own types with interior mutability (or anything -/// else that is not thread-safe) should use the `NoSync` marker type -/// (from `std::marker`) to ensure that the compiler doesn't -/// consider the user-defined type to be `Sync`. Any types with -/// interior mutability must also use the `std::cell::UnsafeCell` wrapper -/// around the value(s) which can be mutated when behind a `&` -/// reference; not doing this is undefined behaviour (for example, -/// `transmute`-ing from `&T` to `&mut T` is illegal). +/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the +/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined +/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal). #[stable(feature = "rust1", since = "1.0.0")] #[lang="sync"] #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] @@ -214,6 +207,12 @@ pub unsafe trait Sync : MarkerTrait { // Empty } +unsafe impl Sync for .. { } + +impl !Sync for *const T { } +impl !Sync for *mut T { } +impl !Sync for Managed { } + /// A type which is considered "not POD", meaning that it is not /// implicitly copyable. This is typically embedded in other types to /// ensure that they are never copied, even if they lack a destructor. @@ -233,13 +232,6 @@ pub struct Managed; macro_rules! impls{ ($t: ident) => ( - #[cfg(stage0)] - impl Hash for $t { - #[inline] - fn hash(&self, _: &mut S) { - } - } - #[cfg(not(stage0))] impl Hash for $t { #[inline] fn hash(&self, _: &mut H) { @@ -284,7 +276,14 @@ macro_rules! impls{ /// any methods, but instead is used to gate access to data. /// /// FIXME. Better documentation needed here! -pub trait MarkerTrait : PhantomFn { } +#[stable(feature = "rust1", since = "1.0.0")] +pub trait MarkerTrait : PhantomFn { } +// ~~~~~ <-- FIXME(#22806)? +// +// Marker trait has been made invariant so as to avoid inf recursion, +// but we should ideally solve the underlying problem. That's a bit +// complicated. + impl MarkerTrait for T { } /// `PhantomFn` is a marker trait for use with traits that contain @@ -296,7 +295,7 @@ impl MarkerTrait for T { } /// can extend `MarkerTrait`, which is equivalent to /// `PhantomFn`. /// -/// # Example +/// # Examples /// /// As an example, consider a trait with no methods like `Even`, meant /// to represent types that are "even": @@ -318,7 +317,7 @@ impl MarkerTrait for T { } /// /// Therefore, we can model a method like this as follows: /// -/// ```rust +/// ``` /// use std::marker::PhantomFn; /// trait Even : PhantomFn { } /// ``` @@ -326,7 +325,8 @@ impl MarkerTrait for T { } /// Another equivalent, but clearer, option would be to use /// `MarkerTrait`: /// -/// ```rust +/// ``` +/// # #![feature(core)] /// use std::marker::MarkerTrait; /// trait Even : MarkerTrait { } /// ``` @@ -348,40 +348,62 @@ impl MarkerTrait for T { } #[stable(feature = "rust1", since = "1.0.0")] pub trait PhantomFn { } -#[cfg(stage0)] // built into the trait matching system after stage0 -impl PhantomFn for U { } - -/// Specific to stage0. You should not be seeing these docs! -#[cfg(stage0)] -#[lang="covariant_type"] // only relevant to stage0 -pub struct PhantomData; - -/// `PhantomData` is a way to tell the compiler about fake fields. -/// Phantom data is required whenever type parameters are not used. -/// The idea is that if the compiler encounters a `PhantomData` -/// instance, it will behave *as if* an instance of the type `T` were -/// present for the purpose of various automatic analyses. +/// `PhantomData` allows you to describe that a type acts as if it stores a value of type `T`, +/// even though it does not. This allows you to inform the compiler about certain safety properties +/// of your code. /// -/// For example, embedding a `PhantomData` will inform the compiler +/// Though they both have scary names, `PhantomData` and "phantom types" are unrelated. 👻👻👻 +/// +/// # Examples +/// +/// When handling external resources over a foreign function interface, `PhantomData` can +/// prevent mismatches by enforcing types in the method implementations: +/// +/// ``` +/// # trait ResType { fn foo(&self); }; +/// # struct ParamType; +/// # mod foreign_lib { +/// # pub fn new(_: usize) -> *mut () { 42 as *mut () } +/// # pub fn do_stuff(_: *mut (), _: usize) {} +/// # } +/// # fn convert_params(_: ParamType) -> usize { 42 } +/// use std::marker::PhantomData; +/// use std::mem; +/// +/// struct ExternalResource { +/// resource_handle: *mut (), +/// resource_type: PhantomData, +/// } +/// +/// impl ExternalResource { +/// fn new() -> ExternalResource { +/// let size_of_res = mem::size_of::(); +/// ExternalResource { +/// resource_handle: foreign_lib::new(size_of_res), +/// resource_type: PhantomData, +/// } +/// } +/// +/// fn do_stuff(&self, param: ParamType) { +/// let foreign_params = convert_params(param); +/// foreign_lib::do_stuff(self.resource_handle, foreign_params); +/// } +/// } +/// ``` +/// +/// Another example: embedding a `PhantomData` will inform the compiler /// that one or more instances of the type `T` could be dropped when /// instances of the type itself is dropped, though that may not be /// apparent from the other structure of the type itself. This is /// commonly necessary if the structure is using an unsafe pointer /// like `*mut T` whose referent may be dropped when the type is /// dropped, as a `*mut T` is otherwise not treated as owned. -/// -/// FIXME. Better documentation and examples of common patterns needed -/// here! For now, please see [RFC 738][738] for more information. -/// -/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md -#[cfg(not(stage0))] #[lang="phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] pub struct PhantomData; impls! { PhantomData } -#[cfg(not(stage0))] mod impls { use super::{Send, Sync, Sized}; @@ -389,39 +411,41 @@ mod impls { unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {} } -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")] -#[lang="contravariant_lifetime"] -pub struct ContravariantLifetime<'a>; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="covariant_lifetime"] -pub struct CovariantLifetime<'a>; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] -#[lang="invariant_lifetime"] -pub struct InvariantLifetime<'a>; - -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="contravariant_type"] -pub struct ContravariantType; +/// A marker trait indicates a type that can be reflected over. This +/// trait is implemented for all types. Its purpose is to ensure that +/// when you write a generic function that will employ reflection, +/// that must be reflected (no pun intended) in the generic bounds of +/// that function. Here is an example: +/// +/// ``` +/// #![feature(core)] +/// use std::marker::Reflect; +/// use std::any::Any; +/// fn foo(x: &T) { +/// let any: &Any = x; +/// if any.is::() { println!("u32"); } +/// } +/// ``` +/// +/// Without the declaration `T:Reflect`, `foo` would not type check +/// (note: as a matter of style, it would be preferable to to write +/// `T:Any`, because `T:Any` implies `T:Reflect` and `T:'static`, but +/// we use `Reflect` here to show how it works). The `Reflect` bound +/// thus serves to alert `foo`'s caller to the fact that `foo` may +/// behave differently depending on whether `T=u32` or not. In +/// particular, thanks to the `Reflect` bound, callers know that a +/// function declared like `fn bar(...)` will always act in +/// precisely the same way no matter what type `T` is supplied, +/// because there are no bounds declared on `T`. (The ability for a +/// caller to reason about what a function may do based solely on what +/// generic bounds are declared is often called the ["parametricity +/// property"][1].) +/// +/// [1]: http://en.wikipedia.org/wiki/Parametricity +#[rustc_reflect_like] +#[unstable(feature = "core", reason = "requires RFC and more experience")] +pub trait Reflect : MarkerTrait { +} -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] -#[lang="covariant_type"] -#[cfg(not(stage0))] -pub struct CovariantType; +impl Reflect for .. { } -/// Old-style marker trait. Deprecated. -#[unstable(feature = "core", reason = "deprecated")] -#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] -#[lang="invariant_type"] -pub struct InvariantType; diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 740997b7a2..249beb6295 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -158,6 +158,27 @@ pub unsafe fn zeroed() -> T { intrinsics::init() } +/// Create a value initialized to an unspecified series of bytes. +/// +/// The byte sequence usually indicates that the value at the memory +/// in question has been dropped. Thus, *if* T carries a drop flag, +/// any associated destructor will not be run when the value falls out +/// of scope. +/// +/// Some code at one time used the `zeroed` function above to +/// accomplish this goal. +/// +/// This function is expected to be deprecated with the transition +/// to non-zeroing drop. +#[inline] +#[unstable(feature = "filling_drop")] +pub unsafe fn dropped() -> T { + #[inline(always)] + unsafe fn dropped_impl() -> T { intrinsics::init_dropped() } + + dropped_impl() +} + /// Create an uninitialized value. /// /// Care must be taken when using this function, if the type `T` has a destructor and the value @@ -203,9 +224,9 @@ pub fn swap(x: &mut T, y: &mut T) { let mut t: T = uninitialized(); // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping_memory(&mut t, &*x, 1); - ptr::copy_nonoverlapping_memory(x, &*y, 1); - ptr::copy_nonoverlapping_memory(y, &t, 1); + ptr::copy_nonoverlapping(&*x, &mut t, 1); + ptr::copy_nonoverlapping(&*y, x, 1); + ptr::copy_nonoverlapping(&t, y, 1); // y and t now point to the same thing, but we need to completely forget `t` // because it's no longer relevant. @@ -251,7 +272,7 @@ pub fn swap(x: &mut T, y: &mut T) { /// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from /// `self`, allowing it to be returned: /// -/// ```rust +/// ``` /// use std::mem; /// # struct Buffer { buf: Vec } /// impl Buffer { @@ -291,15 +312,52 @@ pub fn replace(dest: &mut T, mut src: T) -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn drop(_x: T) { } -/// Interprets `src` as `&U`, and then reads `src` without moving the contained value. +macro_rules! repeat_u8_as_u32 { + ($name:expr) => { (($name as u32) << 24 | + ($name as u32) << 16 | + ($name as u32) << 8 | + ($name as u32)) } +} +macro_rules! repeat_u8_as_u64 { + ($name:expr) => { ((repeat_u8_as_u32!($name) as u64) << 32 | + (repeat_u8_as_u32!($name) as u64)) } +} + +// NOTE: Keep synchronized with values used in librustc_trans::trans::adt. +// +// In particular, the POST_DROP_U8 marker must never equal the +// DTOR_NEEDED_U8 marker. +// +// For a while pnkfelix was using 0xc1 here. +// But having the sign bit set is a pain, so 0x1d is probably better. +// +// And of course, 0x00 brings back the old world of zero'ing on drop. +#[unstable(feature = "filling_drop")] +pub const POST_DROP_U8: u8 = 0x1d; +#[unstable(feature = "filling_drop")] +pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8); +#[unstable(feature = "filling_drop")] +pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8); + +#[cfg(target_pointer_width = "32")] +#[unstable(feature = "filling_drop")] +pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize; +#[cfg(target_pointer_width = "64")] +#[unstable(feature = "filling_drop")] +pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize; + +/// Interprets `src` as `&U`, and then reads `src` without moving the contained +/// value. /// -/// This function will unsafely assume the pointer `src` is valid for `sizeof(U)` bytes by -/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the -/// contained value instead of moving out of `src`. +/// This function will unsafely assume the pointer `src` is valid for +/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It +/// will also unsafely create a copy of the contained value instead of moving +/// out of `src`. /// -/// It is not a compile-time error if `T` and `U` have different sizes, but it is highly encouraged -/// to only invoke this function where `T` and `U` have the same size. This function triggers -/// undefined behavior if `U` is larger than `T`. +/// It is not a compile-time error if `T` and `U` have different sizes, but it +/// is highly encouraged to only invoke this function where `T` and `U` have the +/// same size. This function triggers undefined behavior if `U` is larger than +/// `T`. /// /// # Examples /// @@ -313,6 +371,8 @@ pub fn drop(_x: T) { } #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn transmute_copy(src: &T) -> U { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] ptr::read(src as *const T as *const U) } diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index b542c9d47f..12b45a766b 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -22,13 +22,13 @@ use num::Float; use num::FpCategory as Fp; use option::Option; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const RADIX: uint = 2; +#[stable(feature = "rust1", since = "1.0.0")] +pub const RADIX: u32 = 2; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MANTISSA_DIGITS: uint = 24; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const DIGITS: uint = 6; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MANTISSA_DIGITS: u32 = 24; +#[stable(feature = "rust1", since = "1.0.0")] +pub const DIGITS: u32 = 6; #[stable(feature = "rust1", since = "1.0.0")] pub const EPSILON: f32 = 1.19209290e-07_f32; @@ -56,15 +56,15 @@ pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32; #[stable(feature = "rust1", since = "1.0.0")] pub const MAX: f32 = 3.40282347e+38_f32; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MIN_EXP: int = -125; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MAX_EXP: int = 128; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MIN_EXP: i32 = -125; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MAX_EXP: i32 = 128; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MIN_10_EXP: int = -37; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MAX_10_EXP: int = 38; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MIN_10_EXP: i32 = -37; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MAX_10_EXP: i32 = 38; #[stable(feature = "rust1", since = "1.0.0")] pub const NAN: f32 = 0.0_f32/0.0_f32; @@ -73,61 +73,89 @@ pub const INFINITY: f32 = 1.0_f32/0.0_f32; #[stable(feature = "rust1", since = "1.0.0")] pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32; -/// Various useful constants. -#[unstable(feature = "core", - reason = "naming scheme needs to be revisited")] +/// Basic mathematial constants. +#[stable(feature = "rust1", since = "1.0.0")] pub mod consts { // FIXME: replace with mathematical constants from cmath. /// Archimedes' constant + #[stable(feature = "rust1", since = "1.0.0")] pub const PI: f32 = 3.14159265358979323846264338327950288_f32; /// pi * 2.0 + #[unstable(feature = "core", reason = "unclear naming convention/usefulness")] pub const PI_2: f32 = 6.28318530717958647692528676655900576_f32; /// pi/2.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32; /// pi/3.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32; /// pi/4.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32; /// pi/6.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32; /// pi/8.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32; /// 1.0/pi + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32; /// 2.0/pi + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32; /// 2.0/sqrt(pi) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32; + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")] pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32; /// sqrt(2.0) + #[stable(feature = "rust1", since = "1.0.0")] + pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32; + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")] pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32; /// 1.0/sqrt(2.0) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")] pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32; /// Euler's number + #[stable(feature = "rust1", since = "1.0.0")] pub const E: f32 = 2.71828182845904523536028747135266250_f32; /// log2(e) + #[stable(feature = "rust1", since = "1.0.0")] pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32; /// log10(e) + #[stable(feature = "rust1", since = "1.0.0")] pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32; /// ln(2.0) + #[stable(feature = "rust1", since = "1.0.0")] pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32; /// ln(10.0) + #[stable(feature = "rust1", since = "1.0.0")] pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; } @@ -193,12 +221,12 @@ impl Float for f32 { #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn mantissa_digits(_: Option) -> uint { MANTISSA_DIGITS } + fn mantissa_digits(_: Option) -> usize { MANTISSA_DIGITS as usize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn digits(_: Option) -> uint { DIGITS } + fn digits(_: Option) -> usize { DIGITS as usize } #[inline] #[unstable(feature = "core")] @@ -208,22 +236,22 @@ impl Float for f32 { #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn min_exp(_: Option) -> int { MIN_EXP } + fn min_exp(_: Option) -> isize { MIN_EXP as isize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn max_exp(_: Option) -> int { MAX_EXP } + fn max_exp(_: Option) -> isize { MAX_EXP as isize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn min_10_exp(_: Option) -> int { MIN_10_EXP } + fn min_10_exp(_: Option) -> isize { MIN_10_EXP as isize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn max_10_exp(_: Option) -> int { MAX_10_EXP } + fn max_10_exp(_: Option) -> isize { MAX_10_EXP as isize } #[inline] #[unstable(feature = "core")] @@ -281,8 +309,9 @@ impl Float for f32 { /// The fractional part of the number, satisfying: /// - /// ```rust - /// use core::num::Float; + /// ``` + /// # #![feature(core)] + /// use std::num::Float; /// /// let x = 1.65f32; /// assert!(x == x.trunc() + x.fract()) diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 2aae710754..058acedd9c 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -22,16 +22,13 @@ use num::Float; use num::FpCategory as Fp; use option::Option; -// FIXME(#5527): These constants should be deprecated once associated -// constants are implemented in favour of referencing the respective -// members of `Bounded` and `Float`. - -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const RADIX: uint = 2; +#[stable(feature = "rust1", since = "1.0.0")] +pub const RADIX: u32 = 2; -pub const MANTISSA_DIGITS: uint = 53; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const DIGITS: uint = 15; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MANTISSA_DIGITS: u32 = 53; +#[stable(feature = "rust1", since = "1.0.0")] +pub const DIGITS: u32 = 15; #[stable(feature = "rust1", since = "1.0.0")] pub const EPSILON: f64 = 2.2204460492503131e-16_f64; @@ -59,15 +56,15 @@ pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64; #[stable(feature = "rust1", since = "1.0.0")] pub const MAX: f64 = 1.7976931348623157e+308_f64; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MIN_EXP: int = -1021; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MAX_EXP: int = 1024; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MIN_EXP: i32 = -1021; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MAX_EXP: i32 = 1024; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MIN_10_EXP: int = -307; -#[unstable(feature = "core", reason = "pending integer conventions")] -pub const MAX_10_EXP: int = 308; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MIN_10_EXP: i32 = -307; +#[stable(feature = "rust1", since = "1.0.0")] +pub const MAX_10_EXP: i32 = 308; #[stable(feature = "rust1", since = "1.0.0")] pub const NAN: f64 = 0.0_f64/0.0_f64; @@ -76,65 +73,89 @@ pub const INFINITY: f64 = 1.0_f64/0.0_f64; #[stable(feature = "rust1", since = "1.0.0")] pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64; -/// Various useful constants. -#[unstable(feature = "core", - reason = "naming scheme needs to be revisited")] +/// Basic mathematial constants. +#[stable(feature = "rust1", since = "1.0.0")] pub mod consts { // FIXME: replace with mathematical constants from cmath. - // FIXME(#5527): These constants should be deprecated once associated - // constants are implemented in favour of referencing the respective members - // of `Float`. - /// Archimedes' constant + #[stable(feature = "rust1", since = "1.0.0")] pub const PI: f64 = 3.14159265358979323846264338327950288_f64; /// pi * 2.0 + #[unstable(feature = "core", reason = "unclear naming convention/usefulness")] pub const PI_2: f64 = 6.28318530717958647692528676655900576_f64; /// pi/2.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64; /// pi/3.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_3: f64 = 1.04719755119659774615421446109316763_f64; /// pi/4.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_4: f64 = 0.785398163397448309615660845819875721_f64; /// pi/6.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_6: f64 = 0.52359877559829887307710723054658381_f64; /// pi/8.0 + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_PI_8: f64 = 0.39269908169872415480783042290993786_f64; /// 1.0/pi + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64; /// 2.0/pi + #[stable(feature = "rust1", since = "1.0.0")] pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64; /// 2.0/sqrt(pi) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64; + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")] pub const FRAC_2_SQRTPI: f64 = 1.12837916709551257389615890312154517_f64; /// sqrt(2.0) + #[stable(feature = "rust1", since = "1.0.0")] + pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64; + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")] pub const SQRT2: f64 = 1.41421356237309504880168872420969808_f64; /// 1.0/sqrt(2.0) + #[stable(feature = "rust1", since = "1.0.0")] + pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")] pub const FRAC_1_SQRT2: f64 = 0.707106781186547524400844362104849039_f64; /// Euler's number + #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; /// log2(e) + #[stable(feature = "rust1", since = "1.0.0")] pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64; /// log10(e) + #[stable(feature = "rust1", since = "1.0.0")] pub const LOG10_E: f64 = 0.434294481903251827651128918916605082_f64; /// ln(2.0) + #[stable(feature = "rust1", since = "1.0.0")] pub const LN_2: f64 = 0.693147180559945309417232121458176568_f64; /// ln(10.0) + #[stable(feature = "rust1", since = "1.0.0")] pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; } @@ -200,12 +221,12 @@ impl Float for f64 { #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn mantissa_digits(_: Option) -> uint { MANTISSA_DIGITS } + fn mantissa_digits(_: Option) -> usize { MANTISSA_DIGITS as usize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn digits(_: Option) -> uint { DIGITS } + fn digits(_: Option) -> usize { DIGITS as usize } #[inline] #[unstable(feature = "core")] @@ -215,22 +236,22 @@ impl Float for f64 { #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn min_exp(_: Option) -> int { MIN_EXP } + fn min_exp(_: Option) -> isize { MIN_EXP as isize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn max_exp(_: Option) -> int { MAX_EXP } + fn max_exp(_: Option) -> isize { MAX_EXP as isize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn min_10_exp(_: Option) -> int { MIN_10_EXP } + fn min_10_exp(_: Option) -> isize { MIN_10_EXP as isize } #[inline] #[unstable(feature = "core")] #[deprecated(since = "1.0.0")] - fn max_10_exp(_: Option) -> int { MAX_10_EXP } + fn max_10_exp(_: Option) -> isize { MAX_10_EXP as isize } #[inline] #[unstable(feature = "core")] @@ -288,8 +309,9 @@ impl Float for f64 { /// The fractional part of the number, satisfying: /// - /// ```rust - /// use core::num::Float; + /// ``` + /// # #![feature(core)] + /// use std::num::Float; /// /// let x = 1.65f64; /// assert!(x == x.trunc() + x.fract()) diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs index 20300d29fa..b3adef53da 100644 --- a/src/libcore/num/float_macros.rs +++ b/src/libcore/num/float_macros.rs @@ -18,4 +18,3 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } - diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs deleted file mode 100644 index 2132b9516a..0000000000 --- a/src/libcore/num/int.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Deprecated: replaced by `isize`. -//! -//! The rollout of the new type will gradually take place over the -//! alpha cycle along with the development of clearer conventions -//! around integer types. - -#![unstable(feature = "core")] -#![deprecated(since = "1.0.0", reason = "replaced by isize")] - -#[cfg(target_pointer_width = "32")] int_module! { int, 32 } -#[cfg(target_pointer_width = "64")] int_module! { int, 64 } diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 954c8a08e6..fe0d6d13c4 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -15,11 +15,11 @@ macro_rules! int_module { ($T:ty, $bits:expr) => ( // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of // calling the `mem::size_of` function. #[unstable(feature = "core")] -pub const BITS : uint = $bits; +pub const BITS : u32 = $bits; // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of // calling the `mem::size_of` function. #[unstable(feature = "core")] -pub const BYTES : uint = ($bits / 8); +pub const BYTES : u32 = ($bits / 8); // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of // calling the `Bounded::min_value` function. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 7612469c80..28e0bcf13d 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -15,13 +15,14 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] +use self::wrapping::{OverflowingOps, WrappingOps}; + use char::CharExt; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord}; -use error::Error; use fmt; use intrinsics; -use iter::IteratorExt; +use iter::Iterator; use marker::Copy; use mem::size_of; use ops::{Add, Sub, Mul, Div, Rem, Neg}; @@ -30,8 +31,66 @@ use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; use str::{FromStr, StrExt}; +/// Provides intentionally-wrapped arithmetic on `T`. +/// +/// Operations like `+` on `u32` values is intended to never overflow, +/// and in some debug configurations overflow is detected and results +/// in a panic. While most arithmetic falls into this category, some +/// code explicitly expects and relies upon modular arithmetic (e.g., +/// hashing). +/// +/// Wrapping arithmetic can be achieved either through methods like +/// `wrapping_add`, or through the `Wrapping` type, which says that +/// all standard arithmetic operations on the underlying value are +/// intended to have wrapping semantics. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] +pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); + +#[unstable(feature = "core", reason = "may be removed or relocated")] +pub mod wrapping; + +/// Types that have a "zero" value. +/// +/// This trait is intended for use in conjunction with `Add`, as an identity: +/// `x + T::zero() == x`. +#[unstable(feature = "zero_one", + reason = "unsure of placement, wants to use associated constants")] +pub trait Zero { + /// The "zero" (usually, additive identity) for this type. + fn zero() -> Self; +} + +/// Types that have a "one" value. +/// +/// This trait is intended for use in conjunction with `Mul`, as an identity: +/// `x * T::one() == x`. +#[unstable(feature = "zero_one", + reason = "unsure of placement, wants to use associated constants")] +pub trait One { + /// The "one" (usually, multiplicative identity) for this type. + fn one() -> Self; +} + +macro_rules! zero_one_impl { + ($($t:ty)*) => ($( + impl Zero for $t { + #[inline] + fn zero() -> $t { 0 } + } + impl One for $t { + #[inline] + fn one() -> $t { 1 } + } + )*) +} +zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } + /// A built-in signed or unsigned integer. #[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", + reason = "replaced by inherent methods; for generics, use rust-lang/num")] +#[allow(deprecated)] pub trait Int : Copy + Clone + NumCast @@ -46,8 +105,10 @@ pub trait Int + BitAnd + BitOr + BitXor - + Shl - + Shr + + Shl + + Shr + + WrappingOps + + OverflowingOps { /// Returns the `0` value of this integer type. // FIXME (#5527): Should be an associated constant @@ -75,9 +136,10 @@ pub trait Int /// Returns the number of ones in the binary representation of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// let n = 0b01001100u8; @@ -86,13 +148,14 @@ pub trait Int /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] - fn count_ones(self) -> uint; + fn count_ones(self) -> u32; /// Returns the number of zeros in the binary representation of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// let n = 0b01001100u8; @@ -102,16 +165,17 @@ pub trait Int #[unstable(feature = "core", reason = "pending integer conventions")] #[inline] - fn count_zeros(self) -> uint { + fn count_zeros(self) -> u32 { (!self).count_ones() } /// Returns the number of leading zeros in the binary representation /// of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// let n = 0b0101000u16; @@ -120,14 +184,15 @@ pub trait Int /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] - fn leading_zeros(self) -> uint; + fn leading_zeros(self) -> u32; /// Returns the number of trailing zeros in the binary representation /// of `self`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// let n = 0b0101000u16; @@ -136,14 +201,15 @@ pub trait Int /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] - fn trailing_zeros(self) -> uint; + fn trailing_zeros(self) -> u32; /// Shifts the bits to the left by a specified amount amount, `n`, wrapping /// the truncated bits to the end of the resulting integer. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -153,14 +219,15 @@ pub trait Int /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] - fn rotate_left(self, n: uint) -> Self; + fn rotate_left(self, n: u32) -> Self; /// Shifts the bits to the right by a specified amount amount, `n`, wrapping /// the truncated bits to the beginning of the resulting integer. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -170,13 +237,13 @@ pub trait Int /// ``` #[unstable(feature = "core", reason = "pending integer conventions")] - fn rotate_right(self, n: uint) -> Self; + fn rotate_right(self, n: u32) -> Self; /// Reverses the byte order of the integer. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -191,9 +258,9 @@ pub trait Int /// /// On big endian this is a no-op. On little endian the bytes are swapped. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -214,9 +281,9 @@ pub trait Int /// /// On little endian this is a no-op. On big endian the bytes are swapped. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -237,9 +304,9 @@ pub trait Int /// /// On big endian this is a no-op. On little endian the bytes are swapped. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -260,9 +327,9 @@ pub trait Int /// /// On little endian this is a no-op. On big endian the bytes are swapped. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// let n = 0x0123456789ABCDEFu64; @@ -282,9 +349,9 @@ pub trait Int /// Checked integer addition. Computes `self + other`, returning `None` if /// overflow occurred. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// assert_eq!(5u16.checked_add(65530), Some(65535)); @@ -296,9 +363,9 @@ pub trait Int /// Checked integer subtraction. Computes `self - other`, returning `None` /// if underflow occurred. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// assert_eq!((-127i8).checked_sub(1), Some(-128)); @@ -310,9 +377,9 @@ pub trait Int /// Checked integer multiplication. Computes `self * other`, returning /// `None` if underflow or overflow occurred. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// assert_eq!(5u8.checked_mul(51), Some(255)); @@ -324,9 +391,9 @@ pub trait Int /// Checked integer division. Computes `self / other`, returning `None` if /// `other == 0` or the operation results in underflow or overflow. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::num::Int; /// /// assert_eq!((-127i8).checked_div(-1), Some(127)); @@ -338,6 +405,16 @@ pub trait Int /// Saturating integer addition. Computes `self + other`, saturating at /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// ``` + /// use std::num::Int; + /// + /// assert_eq!(5u16.saturating_add(65534), 65535); + /// assert_eq!((-5i16).saturating_add(-32767), -32768); + /// assert_eq!(100u32.saturating_add(4294967294), 4294967295); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] fn saturating_add(self, other: Self) -> Self { @@ -350,6 +427,16 @@ pub trait Int /// Saturating integer subtraction. Computes `self - other`, saturating at /// the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// ``` + /// use std::num::Int; + /// + /// assert_eq!(5u16.saturating_sub(65534), 0); + /// assert_eq!(5i16.saturating_sub(-32767), 32767); + /// assert_eq!(100u32.saturating_sub(4294967294), 0); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] fn saturating_sub(self, other: Self) -> Self { @@ -362,9 +449,10 @@ pub trait Int /// Raises self to the power of `exp`, using exponentiation by squaring. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(core)] /// use std::num::Int; /// /// assert_eq!(2.pow(4), 16); @@ -372,14 +460,27 @@ pub trait Int #[unstable(feature = "core", reason = "pending integer conventions")] #[inline] - fn pow(self, mut exp: uint) -> Self { + fn pow(self, mut exp: u32) -> Self { let mut base = self; let mut acc: Self = Int::one(); + + let mut prev_base = self; + let mut base_oflo = false; while exp > 0 { if (exp & 1) == 1 { - acc = acc * base; + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } } - base = base * base; + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; exp /= 2; } acc @@ -403,6 +504,7 @@ macro_rules! uint_impl { $sub_with_overflow:path, $mul_with_overflow:path) => { #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] impl Int for $T { #[inline] fn zero() -> $T { 0 } @@ -414,33 +516,41 @@ macro_rules! uint_impl { fn min_value() -> $T { 0 } #[inline] - fn max_value() -> $T { -1 } + fn max_value() -> $T { !0 } #[inline] - fn count_ones(self) -> uint { unsafe { $ctpop(self as $ActualT) as uint } } + fn count_ones(self) -> u32 { + unsafe { $ctpop(self as $ActualT) as u32 } + } #[inline] - fn leading_zeros(self) -> uint { unsafe { $ctlz(self as $ActualT) as uint } } + fn leading_zeros(self) -> u32 { + unsafe { $ctlz(self as $ActualT) as u32 } + } #[inline] - fn trailing_zeros(self) -> uint { unsafe { $cttz(self as $ActualT) as uint } } + fn trailing_zeros(self) -> u32 { + unsafe { $cttz(self as $ActualT) as u32 } + } #[inline] - fn rotate_left(self, n: uint) -> $T { + fn rotate_left(self, n: u32) -> $T { // Protect against undefined behaviour for over-long bit shifts let n = n % $BITS; (self << n) | (self >> (($BITS - n) % $BITS)) } #[inline] - fn rotate_right(self, n: uint) -> $T { + fn rotate_right(self, n: u32) -> $T { // Protect against undefined behaviour for over-long bit shifts let n = n % $BITS; (self >> n) | (self << (($BITS - n) % $BITS)) } #[inline] - fn swap_bytes(self) -> $T { unsafe { $bswap(self as $ActualT) as $T } } + fn swap_bytes(self) -> $T { + unsafe { $bswap(self as $ActualT) as $T } + } #[inline] fn checked_add(self, other: $T) -> Option<$T> { @@ -509,7 +619,7 @@ uint_impl! { u64 = u64, 64, intrinsics::u64_mul_with_overflow } #[cfg(target_pointer_width = "32")] -uint_impl! { uint = u32, 32, +uint_impl! { usize = u32, 32, intrinsics::ctpop32, intrinsics::ctlz32, intrinsics::cttz32, @@ -519,7 +629,7 @@ uint_impl! { uint = u32, 32, intrinsics::u32_mul_with_overflow } #[cfg(target_pointer_width = "64")] -uint_impl! { uint = u64, 64, +uint_impl! { usize = u64, 64, intrinsics::ctpop64, intrinsics::ctlz64, intrinsics::cttz64, @@ -534,6 +644,7 @@ macro_rules! int_impl { $sub_with_overflow:path, $mul_with_overflow:path) => { #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] impl Int for $T { #[inline] fn zero() -> $T { 0 } @@ -548,22 +659,32 @@ macro_rules! int_impl { fn max_value() -> $T { let min: $T = Int::min_value(); !min } #[inline] - fn count_ones(self) -> uint { (self as $UnsignedT).count_ones() } + fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } #[inline] - fn leading_zeros(self) -> uint { (self as $UnsignedT).leading_zeros() } + fn leading_zeros(self) -> u32 { + (self as $UnsignedT).leading_zeros() + } #[inline] - fn trailing_zeros(self) -> uint { (self as $UnsignedT).trailing_zeros() } + fn trailing_zeros(self) -> u32 { + (self as $UnsignedT).trailing_zeros() + } #[inline] - fn rotate_left(self, n: uint) -> $T { (self as $UnsignedT).rotate_left(n) as $T } + fn rotate_left(self, n: u32) -> $T { + (self as $UnsignedT).rotate_left(n) as $T + } #[inline] - fn rotate_right(self, n: uint) -> $T { (self as $UnsignedT).rotate_right(n) as $T } + fn rotate_right(self, n: u32) -> $T { + (self as $UnsignedT).rotate_right(n) as $T + } #[inline] - fn swap_bytes(self) -> $T { (self as $UnsignedT).swap_bytes() as $T } + fn swap_bytes(self) -> $T { + (self as $UnsignedT).swap_bytes() as $T + } #[inline] fn checked_add(self, other: $T) -> Option<$T> { @@ -614,19 +735,22 @@ int_impl! { i64 = i64, u64, 64, intrinsics::i64_mul_with_overflow } #[cfg(target_pointer_width = "32")] -int_impl! { int = i32, u32, 32, +int_impl! { isize = i32, u32, 32, intrinsics::i32_add_with_overflow, intrinsics::i32_sub_with_overflow, intrinsics::i32_mul_with_overflow } #[cfg(target_pointer_width = "64")] -int_impl! { int = i64, u64, 64, +int_impl! { isize = i64, u64, 64, intrinsics::i64_add_with_overflow, intrinsics::i64_sub_with_overflow, intrinsics::i64_mul_with_overflow } /// A built-in two's complement integer. #[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", + reason = "replaced by inherent methods; for generics, use rust-lang/num")] +#[allow(deprecated)] pub trait SignedInt : Int + Neg @@ -658,6 +782,7 @@ pub trait SignedInt macro_rules! signed_int_impl { ($T:ty) => { #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] impl SignedInt for $T { #[inline] fn abs(self) -> $T { @@ -686,64 +811,1084 @@ signed_int_impl! { i8 } signed_int_impl! { i16 } signed_int_impl! { i32 } signed_int_impl! { i64 } -signed_int_impl! { int } +signed_int_impl! { isize } -/// A built-in unsigned integer. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait UnsignedInt: Int { - /// Returns `true` iff `self == 2^k` for some `k`. - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn is_power_of_two(self) -> bool { - (self - Int::one()) & self == Int::zero() && !(self == Int::zero()) - } +// `Int` + `SignedInt` implemented for signed integers +macro_rules! int_impl { + ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the smallest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn min_value() -> $T { + (-1 as $T) << ($BITS - 1) + } - /// Returns the smallest power of two greater than or equal to `self`. - /// Unspecified behavior on overflow. - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - fn next_power_of_two(self) -> Self { - let bits = size_of::() * 8; - let one: Self = Int::one(); - one << ((bits - (self - one).leading_zeros()) % bits) + /// Returns the largest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn max_value() -> $T { + let min: $T = Int::min_value(); !min + } + + /// Convert a string slice in a given base to an integer. + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * src - A string slice + /// * radix - The base to use. Must lie in the range [2 .. 36] + /// + /// # Return value + /// + /// `None` if the string did not represent a valid number. + /// Otherwise, `Some(n)` where `n` is the integer represented + /// by `src`. + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] + pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> { + ::from_str_radix(src, radix) + } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn leading_zeros(self) -> u32 { + (self as $UnsignedT).leading_zeros() + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trailing_zeros(self) -> u32 { + (self as $UnsignedT).trailing_zeros() + } + + /// Shifts the bits to the left by a specified amount amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { + (self as $UnsignedT).rotate_left(n) as $T + } + + /// Shifts the bits to the right by a specified amount amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { + (self as $UnsignedT).rotate_right(n) as $T + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { + (self as $UnsignedT).swap_bytes() as $T + } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` + /// if overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning + /// `None` if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` + /// if `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_div(-1), Some(127)); + /// assert_eq!((-128i8).checked_div(-1), None); + /// assert_eq!((1i8).checked_div(0), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + -1 if self == <$T>::min_value() + => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T as Zero>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating + /// at the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T as Zero>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Wrapping (modular) addition. Computes `self + other`, + /// wrapping around at the boundary of the type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn wrapping_add(self, rhs: $T) -> $T { + unsafe { + intrinsics::overflowing_add(self, rhs) + } + } + + /// Wrapping (modular) subtraction. Computes `self - other`, + /// wrapping around at the boundary of the type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn wrapping_sub(self, rhs: $T) -> $T { + unsafe { + intrinsics::overflowing_sub(self, rhs) + } + } + + /// Wrapping (modular) multiplication. Computes `self * + /// other`, wrapping around at the boundary of the type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn wrapping_mul(self, rhs: $T) -> $T { + unsafe { + intrinsics::overflowing_mul(self, rhs) + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T as One>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Computes the absolute value of `self`. `Int::min_value()` will be + /// returned if the number is `Int::min_value()`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> $T { + if self.is_negative() { -self } else { self } + } + + /// Returns a number representing sign of `self`. + /// + /// - `0` if the number is zero + /// - `1` if the number is positive + /// - `-1` if the number is negative + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> $T { + match self { + n if n > 0 => 1, + 0 => 0, + _ => -1, + } + } + + /// Returns `true` if `self` is positive and `false` if the number + /// is zero or negative. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_positive(self) -> bool { self > 0 } + + /// Returns `true` if `self` is negative and `false` if the number + /// is zero or positive. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_negative(self) -> bool { self < 0 } } +} - /// Returns the smallest power of two greater than or equal to `n`. If the - /// next power of two is greater than the type's maximum value, `None` is - /// returned, otherwise the power of two is wrapped in `Some`. - #[stable(feature = "rust1", since = "1.0.0")] - fn checked_next_power_of_two(self) -> Option { - let npot = self.next_power_of_two(); - if npot >= self { - Some(npot) - } else { - None +#[lang = "i8"] +impl i8 { + int_impl! { i8 = i8, u8, 8, + intrinsics::i8_add_with_overflow, + intrinsics::i8_sub_with_overflow, + intrinsics::i8_mul_with_overflow } +} + +#[lang = "i16"] +impl i16 { + int_impl! { i16 = i16, u16, 16, + intrinsics::i16_add_with_overflow, + intrinsics::i16_sub_with_overflow, + intrinsics::i16_mul_with_overflow } +} + +#[lang = "i32"] +impl i32 { + int_impl! { i32 = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } +} + +#[lang = "i64"] +impl i64 { + int_impl! { i64 = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } +} + +#[cfg(target_pointer_width = "32")] +#[lang = "isize"] +impl isize { + int_impl! { isize = i32, u32, 32, + intrinsics::i32_add_with_overflow, + intrinsics::i32_sub_with_overflow, + intrinsics::i32_mul_with_overflow } +} + +#[cfg(target_pointer_width = "64")] +#[lang = "isize"] +impl isize { + int_impl! { isize = i64, u64, 64, + intrinsics::i64_add_with_overflow, + intrinsics::i64_sub_with_overflow, + intrinsics::i64_mul_with_overflow } +} + +// `Int` + `UnsignedInt` implemented for signed integers +macro_rules! uint_impl { + ($T:ty = $ActualT:ty, $BITS:expr, + $ctpop:path, + $ctlz:path, + $cttz:path, + $bswap:path, + $add_with_overflow:path, + $sub_with_overflow:path, + $mul_with_overflow:path) => { + /// Returns the smallest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn min_value() -> $T { 0 } + + /// Returns the largest value that can be represented by this integer type. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn max_value() -> $T { !0 } + + /// Convert a string slice in a given base to an integer. + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * src - A string slice + /// * radix - The base to use. Must lie in the range [2 .. 36] + /// + /// # Return value + /// + /// `None` if the string did not represent a valid number. + /// Otherwise, `Some(n)` where `n` is the integer represented + /// by `src`. + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] + pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> { + ::from_str_radix(src, radix) + } + + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_ones(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn count_ones(self) -> u32 { + unsafe { $ctpop(self as $ActualT) as u32 } + } + + /// Returns the number of zeros in the binary representation of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b01001100u8; + /// + /// assert_eq!(n.count_zeros(), 5); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn count_zeros(self) -> u32 { + (!self).count_ones() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.leading_zeros(), 10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn leading_zeros(self) -> u32 { + unsafe { $ctlz(self as $ActualT) as u32 } + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0b0101000u16; + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trailing_zeros(self) -> u32 { + unsafe { $cttz(self as $ActualT) as u32 } + } + + /// Shifts the bits to the left by a specified amount amount, `n`, + /// wrapping the truncated bits to the end of the resulting integer. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0x3456789ABCDEF012u64; + /// + /// assert_eq!(n.rotate_left(12), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rotate_left(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self << n) | (self >> (($BITS - n) % $BITS)) + } + + /// Shifts the bits to the right by a specified amount amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xDEF0123456789ABCu64; + /// + /// assert_eq!(n.rotate_right(12), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn rotate_right(self, n: u32) -> $T { + // Protect against undefined behaviour for over-long bit shifts + let n = n % $BITS; + (self >> n) | (self << (($BITS - n) % $BITS)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// let m = 0xEFCDAB8967452301u64; + /// + /// assert_eq!(n.swap_bytes(), m); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn swap_bytes(self) -> $T { + unsafe { $bswap(self as $ActualT) as $T } + } + + /// Convert an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Int::from_be(n), n) + /// } else { + /// assert_eq!(Int::from_be(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_be(x: $T) -> $T { + if cfg!(target_endian = "big") { x } else { x.swap_bytes() } + } + + /// Convert an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Int::from_le(n), n) + /// } else { + /// assert_eq!(Int::from_le(n), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn from_le(x: $T) -> $T { + if cfg!(target_endian = "little") { x } else { x.swap_bytes() } + } + + /// Convert `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n) + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_be(self) -> $T { // or not to be? + if cfg!(target_endian = "big") { self } else { self.swap_bytes() } + } + + /// Convert `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// let n = 0x0123456789ABCDEFu64; + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n) + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_le(self) -> $T { + if cfg!(target_endian = "little") { self } else { self.swap_bytes() } + } + + /// Checked integer addition. Computes `self + other`, returning `None` + /// if overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u16.checked_add(65530), Some(65535)); + /// assert_eq!(6u16.checked_add(65530), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_add(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $add_with_overflow, self, other) + } + + /// Checked integer subtraction. Computes `self - other`, returning + /// `None` if underflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_sub(1), Some(-128)); + /// assert_eq!((-128i8).checked_sub(1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_sub(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $sub_with_overflow, self, other) + } + + /// Checked integer multiplication. Computes `self * other`, returning + /// `None` if underflow or overflow occurred. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!(5u8.checked_mul(51), Some(255)); + /// assert_eq!(5u8.checked_mul(52), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_mul(self, other: $T) -> Option<$T> { + checked_op!($T, $ActualT, $mul_with_overflow, self, other) + } + + /// Checked integer division. Computes `self / other`, returning `None` + /// if `other == 0` or the operation results in underflow or overflow. + /// + /// # Examples + /// + /// ```rust + /// use std::num::Int; + /// + /// assert_eq!((-127i8).checked_div(-1), Some(127)); + /// assert_eq!((-128i8).checked_div(-1), None); + /// assert_eq!((1i8).checked_div(0), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn checked_div(self, v: $T) -> Option<$T> { + match v { + 0 => None, + v => Some(self / v), + } + } + + /// Saturating integer addition. Computes `self + other`, saturating at + /// the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_add(self, other: $T) -> $T { + match self.checked_add(other) { + Some(x) => x, + None if other >= <$T as Zero>::zero() => <$T>::max_value(), + None => <$T>::min_value(), + } + } + + /// Saturating integer subtraction. Computes `self - other`, saturating + /// at the numeric bounds instead of overflowing. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn saturating_sub(self, other: $T) -> $T { + match self.checked_sub(other) { + Some(x) => x, + None if other >= <$T as Zero>::zero() => <$T>::min_value(), + None => <$T>::max_value(), + } + } + + /// Wrapping (modular) addition. Computes `self + other`, + /// wrapping around at the boundary of the type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn wrapping_add(self, rhs: $T) -> $T { + unsafe { + intrinsics::overflowing_add(self, rhs) + } + } + + /// Wrapping (modular) subtraction. Computes `self - other`, + /// wrapping around at the boundary of the type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn wrapping_sub(self, rhs: $T) -> $T { + unsafe { + intrinsics::overflowing_sub(self, rhs) + } + } + + /// Wrapping (modular) multiplication. Computes `self * + /// other`, wrapping around at the boundary of the type. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn wrapping_mul(self, rhs: $T) -> $T { + unsafe { + intrinsics::overflowing_mul(self, rhs) + } + } + + /// Raises self to the power of `exp`, using exponentiation by squaring. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(core)] + /// use std::num::Int; + /// + /// assert_eq!(2.pow(4), 16); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn pow(self, mut exp: u32) -> $T { + let mut base = self; + let mut acc = <$T as One>::one(); + + let mut prev_base = self; + let mut base_oflo = false; + while exp > 0 { + if (exp & 1) == 1 { + if base_oflo { + // ensure overflow occurs in the same manner it + // would have otherwise (i.e. signal any exception + // it would have otherwise). + acc = acc * (prev_base * prev_base); + } else { + acc = acc * base; + } + } + prev_base = base; + let (new_base, new_base_oflo) = base.overflowing_mul(base); + base = new_base; + base_oflo = new_base_oflo; + exp /= 2; + } + acc + } + + /// Returns `true` iff `self == 2^k` for some `k`. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_power_of_two(self) -> bool { + (self.wrapping_sub(<$T as One>::one())) & self == <$T as Zero>::zero() && + !(self == <$T as Zero>::zero()) + } + + /// Returns the smallest power of two greater than or equal to `self`. + /// Unspecified behavior on overflow. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn next_power_of_two(self) -> $T { + let bits = size_of::<$T>() * 8; + let one: $T = <$T as One>::one(); + one << ((bits - self.wrapping_sub(one).leading_zeros() as usize) % bits) + } + + /// Returns the smallest power of two greater than or equal to `n`. If + /// the next power of two is greater than the type's maximum value, + /// `None` is returned, otherwise the power of two is wrapped in `Some`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn checked_next_power_of_two(self) -> Option<$T> { + let npot = self.next_power_of_two(); + if npot >= self { + Some(npot) + } else { + None + } } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl UnsignedInt for uint {} +#[lang = "u8"] +impl u8 { + uint_impl! { u8 = u8, 8, + intrinsics::ctpop8, + intrinsics::ctlz8, + intrinsics::cttz8, + bswap8, + intrinsics::u8_add_with_overflow, + intrinsics::u8_sub_with_overflow, + intrinsics::u8_mul_with_overflow } +} -#[stable(feature = "rust1", since = "1.0.0")] -impl UnsignedInt for u8 {} +#[lang = "u16"] +impl u16 { + uint_impl! { u16 = u16, 16, + intrinsics::ctpop16, + intrinsics::ctlz16, + intrinsics::cttz16, + intrinsics::bswap16, + intrinsics::u16_add_with_overflow, + intrinsics::u16_sub_with_overflow, + intrinsics::u16_mul_with_overflow } +} -#[stable(feature = "rust1", since = "1.0.0")] -impl UnsignedInt for u16 {} +#[lang = "u32"] +impl u32 { + uint_impl! { u32 = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } +} -#[stable(feature = "rust1", since = "1.0.0")] -impl UnsignedInt for u32 {} -#[stable(feature = "rust1", since = "1.0.0")] -impl UnsignedInt for u64 {} +#[lang = "u64"] +impl u64 { + uint_impl! { u64 = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } +} + +#[cfg(target_pointer_width = "32")] +#[lang = "usize"] +impl usize { + uint_impl! { usize = u32, 32, + intrinsics::ctpop32, + intrinsics::ctlz32, + intrinsics::cttz32, + intrinsics::bswap32, + intrinsics::u32_add_with_overflow, + intrinsics::u32_sub_with_overflow, + intrinsics::u32_mul_with_overflow } +} + +#[cfg(target_pointer_width = "64")] +#[lang = "usize"] +impl usize { + uint_impl! { usize = u64, 64, + intrinsics::ctpop64, + intrinsics::ctlz64, + intrinsics::cttz64, + intrinsics::bswap64, + intrinsics::u64_add_with_overflow, + intrinsics::u64_sub_with_overflow, + intrinsics::u64_mul_with_overflow } +} /// A generic trait for converting a value to a number. #[unstable(feature = "core", reason = "trait is likely to be removed")] pub trait ToPrimitive { - /// Converts the value of `self` to an `int`. + /// Converts the value of `self` to an `isize`. #[inline] - fn to_int(&self) -> Option { - self.to_i64().and_then(|x| x.to_int()) + #[unstable(feature = "core")] + #[deprecated(since = "1.0.0", reason = "use to_isize")] + fn to_int(&self) -> Option { + self.to_i64().and_then(|x| x.to_isize()) + } + + /// Converts the value of `self` to an `isize`. + #[inline] + fn to_isize(&self) -> Option { + self.to_i64().and_then(|x| x.to_isize()) } /// Converts the value of `self` to an `i8`. @@ -767,10 +1912,18 @@ pub trait ToPrimitive { /// Converts the value of `self` to an `i64`. fn to_i64(&self) -> Option; - /// Converts the value of `self` to an `uint`. + /// Converts the value of `self` to an `usize`. + #[inline] + #[unstable(feature = "core")] + #[deprecated(since = "1.0.0", reason = "use to_usize")] + fn to_uint(&self) -> Option { + self.to_u64().and_then(|x| x.to_usize()) + } + + /// Converts the value of `self` to a `usize`. #[inline] - fn to_uint(&self) -> Option { - self.to_u64().and_then(|x| x.to_uint()) + fn to_usize(&self) -> Option { + self.to_u64().and_then(|x| x.to_usize()) } /// Converts the value of `self` to an `u8`. @@ -845,7 +1998,9 @@ macro_rules! impl_to_primitive_int { ($T:ty) => ( impl ToPrimitive for $T { #[inline] - fn to_int(&self) -> Option { impl_to_primitive_int_to_int!($T, int, *self) } + fn to_int(&self) -> Option { impl_to_primitive_int_to_int!($T, isize, *self) } + #[inline] + fn to_isize(&self) -> Option { impl_to_primitive_int_to_int!($T, isize, *self) } #[inline] fn to_i8(&self) -> Option { impl_to_primitive_int_to_int!($T, i8, *self) } #[inline] @@ -856,7 +2011,9 @@ macro_rules! impl_to_primitive_int { fn to_i64(&self) -> Option { impl_to_primitive_int_to_int!($T, i64, *self) } #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, uint, *self) } + fn to_uint(&self) -> Option { impl_to_primitive_int_to_uint!($T, usize, *self) } + #[inline] + fn to_usize(&self) -> Option { impl_to_primitive_int_to_uint!($T, usize, *self) } #[inline] fn to_u8(&self) -> Option { impl_to_primitive_int_to_uint!($T, u8, *self) } #[inline] @@ -874,7 +2031,7 @@ macro_rules! impl_to_primitive_int { ) } -impl_to_primitive_int! { int } +impl_to_primitive_int! { isize } impl_to_primitive_int! { i8 } impl_to_primitive_int! { i16 } impl_to_primitive_int! { i32 } @@ -915,7 +2072,9 @@ macro_rules! impl_to_primitive_uint { ($T:ty) => ( impl ToPrimitive for $T { #[inline] - fn to_int(&self) -> Option { impl_to_primitive_uint_to_int!(int, *self) } + fn to_int(&self) -> Option { impl_to_primitive_uint_to_int!(isize, *self) } + #[inline] + fn to_isize(&self) -> Option { impl_to_primitive_uint_to_int!(isize, *self) } #[inline] fn to_i8(&self) -> Option { impl_to_primitive_uint_to_int!(i8, *self) } #[inline] @@ -926,7 +2085,11 @@ macro_rules! impl_to_primitive_uint { fn to_i64(&self) -> Option { impl_to_primitive_uint_to_int!(i64, *self) } #[inline] - fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, uint, *self) } + fn to_uint(&self) -> Option { impl_to_primitive_uint_to_uint!($T, usize, *self) } + #[inline] + fn to_usize(&self) -> Option { + impl_to_primitive_uint_to_uint!($T, usize, *self) + } #[inline] fn to_u8(&self) -> Option { impl_to_primitive_uint_to_uint!($T, u8, *self) } #[inline] @@ -944,7 +2107,7 @@ macro_rules! impl_to_primitive_uint { ) } -impl_to_primitive_uint! { uint } +impl_to_primitive_uint! { usize } impl_to_primitive_uint! { u8 } impl_to_primitive_uint! { u16 } impl_to_primitive_uint! { u32 } @@ -970,7 +2133,9 @@ macro_rules! impl_to_primitive_float { ($T:ident) => ( impl ToPrimitive for $T { #[inline] - fn to_int(&self) -> Option { Some(*self as int) } + fn to_int(&self) -> Option { Some(*self as isize) } + #[inline] + fn to_isize(&self) -> Option { Some(*self as isize) } #[inline] fn to_i8(&self) -> Option { Some(*self as i8) } #[inline] @@ -981,7 +2146,9 @@ macro_rules! impl_to_primitive_float { fn to_i64(&self) -> Option { Some(*self as i64) } #[inline] - fn to_uint(&self) -> Option { Some(*self as uint) } + fn to_uint(&self) -> Option { Some(*self as usize) } + #[inline] + fn to_usize(&self) -> Option { Some(*self as usize) } #[inline] fn to_u8(&self) -> Option { Some(*self as u8) } #[inline] @@ -1005,10 +2172,19 @@ impl_to_primitive_float! { f64 } /// A generic trait for converting a number to a value. #[unstable(feature = "core", reason = "trait is likely to be removed")] pub trait FromPrimitive : ::marker::Sized { - /// Convert an `int` to return an optional value of this type. If the + /// Convert an `isize` to return an optional value of this type. If the + /// value cannot be represented by this value, the `None` is returned. + #[inline] + #[unstable(feature = "core")] + #[deprecated(since = "1.0.0", reason = "use from_isize")] + fn from_int(n: isize) -> Option { + FromPrimitive::from_i64(n as i64) + } + + /// Convert an `isize` to return an optional value of this type. If the /// value cannot be represented by this value, the `None` is returned. #[inline] - fn from_int(n: int) -> Option { + fn from_isize(n: isize) -> Option { FromPrimitive::from_i64(n as i64) } @@ -1037,10 +2213,19 @@ pub trait FromPrimitive : ::marker::Sized { /// type cannot be represented by this value, the `None` is returned. fn from_i64(n: i64) -> Option; - /// Convert an `uint` to return an optional value of this type. If the + /// Convert an `usize` to return an optional value of this type. If the /// type cannot be represented by this value, the `None` is returned. #[inline] - fn from_uint(n: uint) -> Option { + #[unstable(feature = "core")] + #[deprecated(since = "1.0.0", reason = "use from_usize")] + fn from_uint(n: usize) -> Option { + FromPrimitive::from_u64(n as u64) + } + + /// Convert a `usize` to return an optional value of this type. If the + /// type cannot be represented by this value, the `None` is returned. + #[inline] + fn from_usize(n: usize) -> Option { FromPrimitive::from_u64(n as u64) } @@ -1086,8 +2271,15 @@ pub trait FromPrimitive : ::marker::Sized { /// A utility function that just calls `FromPrimitive::from_int`. #[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_int(n: int) -> Option { - FromPrimitive::from_int(n) +#[deprecated(since = "1.0.0", reason = "use from_isize")] +pub fn from_int(n: isize) -> Option { + FromPrimitive::from_isize(n) +} + +/// A utility function that just calls `FromPrimitive::from_isize`. +#[unstable(feature = "core", reason = "likely to be removed")] +pub fn from_isize(n: isize) -> Option { + FromPrimitive::from_isize(n) } /// A utility function that just calls `FromPrimitive::from_i8`. @@ -1116,8 +2308,15 @@ pub fn from_i64(n: i64) -> Option { /// A utility function that just calls `FromPrimitive::from_uint`. #[unstable(feature = "core", reason = "likely to be removed")] -pub fn from_uint(n: uint) -> Option { - FromPrimitive::from_uint(n) +#[deprecated(since = "1.0.0", reason = "use from_uint")] +pub fn from_uint(n: usize) -> Option { + FromPrimitive::from_usize(n) +} + +/// A utility function that just calls `FromPrimitive::from_usize`. +#[unstable(feature = "core", reason = "likely to be removed")] +pub fn from_usize(n: usize) -> Option { + FromPrimitive::from_usize(n) } /// A utility function that just calls `FromPrimitive::from_u8`. @@ -1158,14 +2357,15 @@ pub fn from_f64(n: f64) -> Option { macro_rules! impl_from_primitive { ($T:ty, $to_ty:ident) => ( + #[allow(deprecated)] impl FromPrimitive for $T { - #[inline] fn from_int(n: int) -> Option<$T> { n.$to_ty() } + #[inline] fn from_int(n: isize) -> Option<$T> { n.$to_ty() } #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() } #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() } #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() } #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() } - #[inline] fn from_uint(n: uint) -> Option<$T> { n.$to_ty() } + #[inline] fn from_uint(n: usize) -> Option<$T> { n.$to_ty() } #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() } #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() } #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() } @@ -1177,12 +2377,12 @@ macro_rules! impl_from_primitive { ) } -impl_from_primitive! { int, to_int } +impl_from_primitive! { isize, to_int } impl_from_primitive! { i8, to_i8 } impl_from_primitive! { i16, to_i16 } impl_from_primitive! { i32, to_i32 } impl_from_primitive! { i64, to_i64 } -impl_from_primitive! { uint, to_uint } +impl_from_primitive! { usize, to_uint } impl_from_primitive! { u8, to_u8 } impl_from_primitive! { u16, to_u16 } impl_from_primitive! { u32, to_u32 } @@ -1192,9 +2392,10 @@ impl_from_primitive! { f64, to_f64 } /// Cast from one machine scalar to another. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(core)] /// use std::num; /// /// let twenty: f32 = num::cast(0x14).unwrap(); @@ -1219,6 +2420,7 @@ macro_rules! impl_num_cast { ($T:ty, $conv:ident) => ( impl NumCast for $T { #[inline] + #[allow(deprecated)] fn from(n: N) -> Option<$T> { // `$conv` could be generated using `concat_idents!`, but that // macro seems to be broken at the moment @@ -1232,28 +2434,37 @@ impl_num_cast! { u8, to_u8 } impl_num_cast! { u16, to_u16 } impl_num_cast! { u32, to_u32 } impl_num_cast! { u64, to_u64 } -impl_num_cast! { uint, to_uint } +impl_num_cast! { usize, to_uint } impl_num_cast! { i8, to_i8 } impl_num_cast! { i16, to_i16 } impl_num_cast! { i32, to_i32 } impl_num_cast! { i64, to_i64 } -impl_num_cast! { int, to_int } +impl_num_cast! { isize, to_int } impl_num_cast! { f32, to_f32 } impl_num_cast! { f64, to_f64 } /// Used for representing the classification of floating point numbers -#[derive(Copy, PartialEq, Debug)] -#[unstable(feature = "core", reason = "may be renamed")] +#[derive(Copy, Clone, PartialEq, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum FpCategory { /// "Not a Number", often obtained by dividing by zero + #[stable(feature = "rust1", since = "1.0.0")] Nan, + /// Positive or negative infinity + #[stable(feature = "rust1", since = "1.0.0")] Infinite , + /// Positive or negative zero + #[stable(feature = "rust1", since = "1.0.0")] Zero, + /// De-normalized floating point representation (less precise than `Normal`) + #[stable(feature = "rust1", since = "1.0.0")] Subnormal, + /// A regular floating point number + #[stable(feature = "rust1", since = "1.0.0")] Normal, } @@ -1297,12 +2508,12 @@ pub trait Float #[deprecated(since = "1.0.0", reason = "use `std::f32::MANTISSA_DIGITS` or \ `std::f64::MANTISSA_DIGITS` as appropriate")] - fn mantissa_digits(unused_self: Option) -> uint; + fn mantissa_digits(unused_self: Option) -> usize; /// Returns the number of base-10 digits of precision that this type supports. #[unstable(feature = "core")] #[deprecated(since = "1.0.0", reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] - fn digits(unused_self: Option) -> uint; + fn digits(unused_self: Option) -> usize; /// Returns the difference between 1.0 and the smallest representable number larger than 1.0. #[unstable(feature = "core")] #[deprecated(since = "1.0.0", @@ -1312,22 +2523,22 @@ pub trait Float #[unstable(feature = "core")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] - fn min_exp(unused_self: Option) -> int; + fn min_exp(unused_self: Option) -> isize; /// Returns the maximum binary exponent that this type can represent. #[unstable(feature = "core")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] - fn max_exp(unused_self: Option) -> int; + fn max_exp(unused_self: Option) -> isize; /// Returns the minimum base-10 exponent that this type can represent. #[unstable(feature = "core")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] - fn min_10_exp(unused_self: Option) -> int; + fn min_10_exp(unused_self: Option) -> isize; /// Returns the maximum base-10 exponent that this type can represent. #[unstable(feature = "core")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] - fn max_10_exp(unused_self: Option) -> int; + fn max_10_exp(unused_self: Option) -> isize; /// Returns the smallest finite value that this type can represent. #[unstable(feature = "core")] #[deprecated(since = "1.0.0", @@ -1430,13 +2641,24 @@ pub trait Float /// A generic trait for converting a string with a radix (base) to a value #[unstable(feature = "core", reason = "needs reevaluation")] +#[deprecated(since = "1.0.0", + reason = "moved to inherent methods; use e.g. i32::from_str_radix")] pub trait FromStrRadix { + #[unstable(feature = "core", reason = "needs reevaluation")] + #[deprecated(since = "1.0.0", reason = "moved to inherent methods")] type Err; + + #[unstable(feature = "core", reason = "needs reevaluation")] + #[deprecated(since = "1.0.0", + reason = "moved to inherent methods; use e.g. i32::from_str_radix")] + #[allow(deprecated)] fn from_str_radix(str: &str, radix: u32) -> Result; } -/// A utility function that just calls FromStrRadix::from_str_radix. +/// A utility function that just calls `FromStrRadix::from_str_radix`. #[unstable(feature = "core", reason = "needs reevaluation")] +#[deprecated(since = "1.0.0", reason = "use e.g. i32::from_str_radix")] +#[allow(deprecated)] pub fn from_str_radix(str: &str, radix: u32) -> Result { FromStrRadix::from_str_radix(str, radix) @@ -1474,12 +2696,14 @@ macro_rules! from_str_radix_float_impl { /// `None` if the string did not represent a valid number. Otherwise, /// `Some(n)` where `n` is the floating-point number represented by `src`. #[inline] + #[allow(deprecated)] fn from_str(src: &str) -> Result<$T, ParseFloatError> { from_str_radix(src, 10) } } #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] impl FromStrRadix for $T { type Err = ParseFloatError; @@ -1530,7 +2754,7 @@ macro_rules! from_str_radix_float_impl { let mut prev_sig = sig; let mut cs = src.chars().enumerate(); // Exponent prefix and exponent index offset - let mut exp_info = None::<(char, uint)>; + let mut exp_info = None::<(char, usize)>; // Parse the integer part of the significand for (i, c) in cs.by_ref() { @@ -1541,9 +2765,9 @@ macro_rules! from_str_radix_float_impl { // add/subtract current digit depending on sign if is_positive { - sig = sig + ((digit as int) as $T); + sig = sig + ((digit as isize) as $T); } else { - sig = sig - ((digit as int) as $T); + sig = sig - ((digit as isize) as $T); } // Detect overflow by comparing to last value, except @@ -1624,9 +2848,9 @@ macro_rules! from_str_radix_float_impl { // Parse the exponent as decimal integer let src = &src[offset..]; let (is_positive, exp) = match src.slice_shift_char() { - Some(('-', src)) => (false, src.parse::()), - Some(('+', src)) => (true, src.parse::()), - Some((_, _)) => (true, src.parse::()), + Some(('-', src)) => (false, src.parse::()), + Some(('+', src)) => (true, src.parse::()), + Some((_, _)) => (true, src.parse::()), None => return Err(PFE { kind: Invalid }), }; @@ -1650,6 +2874,7 @@ from_str_radix_float_impl! { f64 } macro_rules! from_str_radix_int_impl { ($T:ty) => { #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] impl FromStr for $T { type Err = ParseIntError; #[inline] @@ -1659,6 +2884,7 @@ macro_rules! from_str_radix_int_impl { } #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] impl FromStrRadix for $T { type Err = ParseIntError; fn from_str_radix(src: &str, radix: u32) @@ -1672,6 +2898,7 @@ macro_rules! from_str_radix_int_impl { let is_signed_ty = (0 as $T) > Int::min_value(); match src.slice_shift_char() { + Some(('-', "")) => Err(PIE { kind: Empty }), Some(('-', src)) if is_signed_ty => { // The number is negative let mut result = 0; @@ -1716,12 +2943,12 @@ macro_rules! from_str_radix_int_impl { } } } -from_str_radix_int_impl! { int } +from_str_radix_int_impl! { isize } from_str_radix_int_impl! { i8 } from_str_radix_int_impl! { i16 } from_str_radix_int_impl! { i32 } from_str_radix_int_impl! { i64 } -from_str_radix_int_impl! { uint } +from_str_radix_int_impl! { usize } from_str_radix_int_impl! { u8 } from_str_radix_int_impl! { u16 } from_str_radix_int_impl! { u32 } @@ -1740,16 +2967,9 @@ enum IntErrorKind { Underflow, } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for ParseIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseIntError { - fn description(&self) -> &str { +impl ParseIntError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", IntErrorKind::InvalidDigit => "invalid digit found in string", @@ -1759,6 +2979,13 @@ impl Error for ParseIntError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseIntError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + /// An error which can be returned when parsing a float. #[derive(Debug, Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] @@ -1770,19 +2997,19 @@ enum FloatErrorKind { Invalid, } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for ParseFloatError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseFloatError { - fn description(&self) -> &str { +impl ParseFloatError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { match self.kind { FloatErrorKind::Empty => "cannot parse float from empty string", FloatErrorKind::Invalid => "invalid float literal", } } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseFloatError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 06502be54a..d0c4885ad0 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -13,13 +13,13 @@ macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => ( #[unstable(feature = "core")] -pub const BITS : uint = $bits; +pub const BITS : u32 = $bits; #[unstable(feature = "core")] -pub const BYTES : uint = ($bits / 8); +pub const BYTES : u32 = ($bits / 8); #[stable(feature = "rust1", since = "1.0.0")] pub const MIN: $T = 0 as $T; #[stable(feature = "rust1", since = "1.0.0")] -pub const MAX: $T = 0 as $T - 1 as $T; +pub const MAX: $T = !0 as $T; ) } diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs new file mode 100644 index 0000000000..28276d0bf0 --- /dev/null +++ b/src/libcore/num/wrapping.rs @@ -0,0 +1,488 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(missing_docs)] +#![allow(deprecated)] + +use super::Wrapping; + +use ops::*; + +use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul}; + +use intrinsics::{i8_add_with_overflow, u8_add_with_overflow}; +use intrinsics::{i16_add_with_overflow, u16_add_with_overflow}; +use intrinsics::{i32_add_with_overflow, u32_add_with_overflow}; +use intrinsics::{i64_add_with_overflow, u64_add_with_overflow}; +use intrinsics::{i8_sub_with_overflow, u8_sub_with_overflow}; +use intrinsics::{i16_sub_with_overflow, u16_sub_with_overflow}; +use intrinsics::{i32_sub_with_overflow, u32_sub_with_overflow}; +use intrinsics::{i64_sub_with_overflow, u64_sub_with_overflow}; +use intrinsics::{i8_mul_with_overflow, u8_mul_with_overflow}; +use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow}; +use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow}; +use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow}; + +use ::{i8,i16,i32,i64}; + +#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")] +#[deprecated(since = "1.0.0", reason = "moved to inherent methods")] +pub trait WrappingOps { + fn wrapping_add(self, rhs: Self) -> Self; + fn wrapping_sub(self, rhs: Self) -> Self; + fn wrapping_mul(self, rhs: Self) -> Self; +} + +#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")] +pub trait OverflowingOps { + fn overflowing_add(self, rhs: Self) -> (Self, bool); + fn overflowing_sub(self, rhs: Self) -> (Self, bool); + fn overflowing_mul(self, rhs: Self) -> (Self, bool); + + fn overflowing_div(self, rhs: Self) -> (Self, bool); + fn overflowing_rem(self, rhs: Self) -> (Self, bool); + + fn overflowing_shl(self, rhs: u32) -> (Self, bool); + fn overflowing_shr(self, rhs: u32) -> (Self, bool); +} + +macro_rules! sh_impl { + ($t:ty, $f:ty) => ( + #[stable(feature = "rust1", since = "1.0.0")] + impl Shl<$f> for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn shl(self, other: $f) -> Wrapping<$t> { + Wrapping(self.0 << other) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Shr<$f> for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn shr(self, other: $f) -> Wrapping<$t> { + Wrapping(self.0 >> other) + } + } + ) +} + +// FIXME (#23545): uncomment the remaining impls +macro_rules! sh_impl_all { + ($($t:ty)*) => ($( + // sh_impl! { $t, u8 } + // sh_impl! { $t, u16 } + // sh_impl! { $t, u32 } + // sh_impl! { $t, u64 } + sh_impl! { $t, usize } + + // sh_impl! { $t, i8 } + // sh_impl! { $t, i16 } + // sh_impl! { $t, i32 } + // sh_impl! { $t, i64 } + // sh_impl! { $t, isize } + )*) +} + +sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } + +macro_rules! wrapping_impl { + ($($t:ty)*) => ($( + impl WrappingOps for $t { + #[inline(always)] + fn wrapping_add(self, rhs: $t) -> $t { + unsafe { + overflowing_add(self, rhs) + } + } + #[inline(always)] + fn wrapping_sub(self, rhs: $t) -> $t { + unsafe { + overflowing_sub(self, rhs) + } + } + #[inline(always)] + fn wrapping_mul(self, rhs: $t) -> $t { + unsafe { + overflowing_mul(self, rhs) + } + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Add for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn add(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_add(other.0)) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Sub for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn sub(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_sub(other.0)) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Mul for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn mul(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0.wrapping_mul(other.0)) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Not for Wrapping<$t> { + type Output = Wrapping<$t>; + + fn not(self) -> Wrapping<$t> { + Wrapping(!self.0) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl BitXor for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn bitxor(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0 ^ other.0) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl BitOr for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn bitor(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0 | other.0) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl BitAnd for Wrapping<$t> { + type Output = Wrapping<$t>; + + #[inline(always)] + fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> { + Wrapping(self.0 & other.0) + } + } + )*) +} + +wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } + +mod shift_max { + #![allow(non_upper_case_globals)] + + pub const i8: u32 = (1 << 3) - 1; + pub const i16: u32 = (1 << 4) - 1; + pub const i32: u32 = (1 << 5) - 1; + pub const i64: u32 = (1 << 6) - 1; + + pub const u8: u32 = i8; + pub const u16: u32 = i16; + pub const u32: u32 = i32; + pub const u64: u32 = i64; +} + +macro_rules! signed_overflowing_impl { + ($($t:ident)*) => ($( + impl OverflowingOps for $t { + #[inline(always)] + fn overflowing_add(self, rhs: $t) -> ($t, bool) { + unsafe { + concat_idents!($t, _add_with_overflow)(self, rhs) + } + } + #[inline(always)] + fn overflowing_sub(self, rhs: $t) -> ($t, bool) { + unsafe { + concat_idents!($t, _sub_with_overflow)(self, rhs) + } + } + #[inline(always)] + fn overflowing_mul(self, rhs: $t) -> ($t, bool) { + unsafe { + concat_idents!($t, _mul_with_overflow)(self, rhs) + } + } + + #[inline(always)] + fn overflowing_div(self, rhs: $t) -> ($t, bool) { + if self == $t::MIN && rhs == -1 { + (1, true) + } else { + (self/rhs, false) + } + } + #[inline(always)] + fn overflowing_rem(self, rhs: $t) -> ($t, bool) { + if self == $t::MIN && rhs == -1 { + (0, true) + } else { + (self % rhs, false) + } + } + + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> ($t, bool) { + (self << (rhs & self::shift_max::$t), + (rhs > self::shift_max::$t)) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> ($t, bool) { + (self >> (rhs & self::shift_max::$t), + (rhs > self::shift_max::$t)) + } + } + )*) +} + +macro_rules! unsigned_overflowing_impl { + ($($t:ident)*) => ($( + impl OverflowingOps for $t { + #[inline(always)] + fn overflowing_add(self, rhs: $t) -> ($t, bool) { + unsafe { + concat_idents!($t, _add_with_overflow)(self, rhs) + } + } + #[inline(always)] + fn overflowing_sub(self, rhs: $t) -> ($t, bool) { + unsafe { + concat_idents!($t, _sub_with_overflow)(self, rhs) + } + } + #[inline(always)] + fn overflowing_mul(self, rhs: $t) -> ($t, bool) { + unsafe { + concat_idents!($t, _mul_with_overflow)(self, rhs) + } + } + + #[inline(always)] + fn overflowing_div(self, rhs: $t) -> ($t, bool) { + (self/rhs, false) + } + #[inline(always)] + fn overflowing_rem(self, rhs: $t) -> ($t, bool) { + (self % rhs, false) + } + + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> ($t, bool) { + (self << (rhs & self::shift_max::$t), + (rhs > self::shift_max::$t)) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> ($t, bool) { + (self >> (rhs & self::shift_max::$t), + (rhs > self::shift_max::$t)) + } + } + )*) +} + +signed_overflowing_impl! { i8 i16 i32 i64 } +unsigned_overflowing_impl! { u8 u16 u32 u64 } + +#[cfg(target_pointer_width = "64")] +impl OverflowingOps for usize { + #[inline(always)] + fn overflowing_add(self, rhs: usize) -> (usize, bool) { + unsafe { + let res = u64_add_with_overflow(self as u64, rhs as u64); + (res.0 as usize, res.1) + } + } + #[inline(always)] + fn overflowing_sub(self, rhs: usize) -> (usize, bool) { + unsafe { + let res = u64_sub_with_overflow(self as u64, rhs as u64); + (res.0 as usize, res.1) + } + } + #[inline(always)] + fn overflowing_mul(self, rhs: usize) -> (usize, bool) { + unsafe { + let res = u64_mul_with_overflow(self as u64, rhs as u64); + (res.0 as usize, res.1) + } + } + #[inline(always)] + fn overflowing_div(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_div(rhs as u64); + (r as usize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_rem(rhs as u64); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_shl(rhs); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u64).overflowing_shr(rhs); + (r as usize, f) + } +} + +#[cfg(target_pointer_width = "32")] +impl OverflowingOps for usize { + #[inline(always)] + fn overflowing_add(self, rhs: usize) -> (usize, bool) { + unsafe { + let res = u32_add_with_overflow(self as u32, rhs as u32); + (res.0 as usize, res.1) + } + } + #[inline(always)] + fn overflowing_sub(self, rhs: usize) -> (usize, bool) { + unsafe { + let res = u32_sub_with_overflow(self as u32, rhs as u32); + (res.0 as usize, res.1) + } + } + #[inline(always)] + fn overflowing_mul(self, rhs: usize) -> (usize, bool) { + unsafe { + let res = u32_mul_with_overflow(self as u32, rhs as u32); + (res.0 as usize, res.1) + } + } + #[inline(always)] + fn overflowing_div(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_div(rhs as u32); + (r as usize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: usize) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_rem(rhs as u32); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_shl(rhs); + (r as usize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (usize, bool) { + let (r, f) = (self as u32).overflowing_shr(rhs); + (r as usize, f) + } +} + +#[cfg(target_pointer_width = "64")] +impl OverflowingOps for isize { + #[inline(always)] + fn overflowing_add(self, rhs: isize) -> (isize, bool) { + unsafe { + let res = i64_add_with_overflow(self as i64, rhs as i64); + (res.0 as isize, res.1) + } + } + #[inline(always)] + fn overflowing_sub(self, rhs: isize) -> (isize, bool) { + unsafe { + let res = i64_sub_with_overflow(self as i64, rhs as i64); + (res.0 as isize, res.1) + } + } + #[inline(always)] + fn overflowing_mul(self, rhs: isize) -> (isize, bool) { + unsafe { + let res = i64_mul_with_overflow(self as i64, rhs as i64); + (res.0 as isize, res.1) + } + } + #[inline(always)] + fn overflowing_div(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_div(rhs as i64); + (r as isize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_rem(rhs as i64); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_shl(rhs); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i64).overflowing_shr(rhs); + (r as isize, f) + } +} + +#[cfg(target_pointer_width = "32")] +impl OverflowingOps for isize { + #[inline(always)] + fn overflowing_add(self, rhs: isize) -> (isize, bool) { + unsafe { + let res = i32_add_with_overflow(self as i32, rhs as i32); + (res.0 as isize, res.1) + } + } + #[inline(always)] + fn overflowing_sub(self, rhs: isize) -> (isize, bool) { + unsafe { + let res = i32_sub_with_overflow(self as i32, rhs as i32); + (res.0 as isize, res.1) + } + } + #[inline(always)] + fn overflowing_mul(self, rhs: isize) -> (isize, bool) { + unsafe { + let res = i32_mul_with_overflow(self as i32, rhs as i32); + (res.0 as isize, res.1) + } + } + #[inline(always)] + fn overflowing_div(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_div(rhs as i32); + (r as isize, f) + } + #[inline(always)] + fn overflowing_rem(self, rhs: isize) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_rem(rhs as i32); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shl(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_shl(rhs); + (r as isize, f) + } + #[inline(always)] + fn overflowing_shr(self, rhs: u32) -> (isize, bool) { + let (r, f) = (self as i32).overflowing_shr(rhs); + (r as isize, f) + } +} diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index fbd7f840da..faf305c6a1 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -27,7 +27,7 @@ //! idea to have both `T` and `&T` implement the traits `Add` and `Add<&T>` //! so that generic code can be written without unnecessary cloning. //! -//! # Example +//! # Examples //! //! This example creates a `Point` struct that implements `Add` and `Sub`, and then //! demonstrates adding and subtracting two `Point`s. @@ -73,12 +73,12 @@ use fmt; /// The `Drop` trait is used to run some code when a value goes out of scope. This /// is sometimes called a 'destructor'. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Drop`. The `drop` method is called when `_x` goes /// out of scope, and therefore `main` prints `Dropping!`. /// -/// ```rust +/// ``` /// struct HasDrop; /// /// impl Drop for HasDrop { @@ -157,15 +157,15 @@ macro_rules! forward_ref_binop { /// The `Add` trait is used to specify the functionality of `+`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up /// calling `add`, and therefore, `main` prints `Adding!`. /// -/// ```rust +/// ``` /// use std::ops::Add; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Add for Foo { @@ -184,6 +184,7 @@ macro_rules! forward_ref_binop { #[lang="add"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Add { + /// The resulting type after applying the `+` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -210,15 +211,15 @@ add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// The `Sub` trait is used to specify the functionality of `-`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up /// calling `sub`, and therefore, `main` prints `Subtracting!`. /// -/// ```rust +/// ``` /// use std::ops::Sub; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Sub for Foo { @@ -237,6 +238,7 @@ add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } #[lang="sub"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Sub { + /// The resulting type after applying the `-` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -263,15 +265,15 @@ sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// The `Mul` trait is used to specify the functionality of `*`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up /// calling `mul`, and therefore, `main` prints `Multiplying!`. /// -/// ```rust +/// ``` /// use std::ops::Mul; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Mul for Foo { @@ -290,6 +292,7 @@ sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } #[lang="mul"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Mul { + /// The resulting type after applying the `*` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -316,7 +319,7 @@ mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// The `Div` trait is used to specify the functionality of `/`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up /// calling `div`, and therefore, `main` prints `Dividing!`. @@ -324,7 +327,7 @@ mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// ``` /// use std::ops::Div; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Div for Foo { @@ -343,6 +346,7 @@ mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } #[lang="div"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Div { + /// The resulting type after applying the `/` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -369,7 +373,7 @@ div_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// The `Rem` trait is used to specify the functionality of `%`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up /// calling `rem`, and therefore, `main` prints `Remainder-ing!`. @@ -377,7 +381,7 @@ div_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } /// ``` /// use std::ops::Rem; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Rem for Foo { @@ -396,6 +400,7 @@ div_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 } #[lang="rem"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Rem { + /// The resulting type after applying the `%` operator #[stable(feature = "rust1", since = "1.0.0")] type Output = Self; @@ -441,7 +446,7 @@ rem_float_impl! { f64, fmod } /// The `Neg` trait is used to specify the functionality of unary `-`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling /// `neg`, and therefore, `main` prints `Negating!`. @@ -449,7 +454,7 @@ rem_float_impl! { f64, fmod } /// ``` /// use std::ops::Neg; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Neg for Foo { @@ -468,6 +473,7 @@ rem_float_impl! { f64, fmod } #[lang="neg"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Neg { + /// The resulting type after applying the `-` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -476,48 +482,44 @@ pub trait Neg { fn neg(self) -> Self::Output; } -macro_rules! neg_impl { - ($($t:ty)*) => ($( + + +macro_rules! neg_impl_core { + ($id:ident => $body:expr, $($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] + #[allow(unsigned_negation)] impl Neg for $t { #[stable(feature = "rust1", since = "1.0.0")] type Output = $t; #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn neg(self) -> $t { -self } + fn neg(self) -> $t { let $id = self; $body } } forward_ref_unop! { impl Neg, neg for $t } )*) } -macro_rules! neg_uint_impl { - ($t:ty, $t_signed:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl Neg for $t { - type Output = $t; - - #[inline] - fn neg(self) -> $t { -(self as $t_signed) as $t } - } - - forward_ref_unop! { impl Neg, neg for $t } - } +macro_rules! neg_impl_numeric { + ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} } } -neg_impl! { isize i8 i16 i32 i64 f32 f64 } - -neg_uint_impl! { usize, isize } -neg_uint_impl! { u8, i8 } -neg_uint_impl! { u16, i16 } -neg_uint_impl! { u32, i32 } -neg_uint_impl! { u64, i64 } +macro_rules! neg_impl_unsigned { + ($($t:ty)*) => { + neg_impl_core!{ x => { + #[cfg(stage0)] + use ::num::wrapping::WrappingOps; + !x.wrapping_add(1) + }, $($t)*} } +} +// neg_impl_unsigned! { usize u8 u16 u32 u64 } +neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 } /// The `Not` trait is used to specify the functionality of unary `!`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Not`. When `!Foo` happens, it ends up calling /// `not`, and therefore, `main` prints `Not-ing!`. @@ -525,7 +527,7 @@ neg_uint_impl! { u64, i64 } /// ``` /// use std::ops::Not; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Not for Foo { @@ -544,6 +546,7 @@ neg_uint_impl! { u64, i64 } #[lang="not"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Not { + /// The resulting type after applying the `!` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -570,7 +573,7 @@ not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// The `BitAnd` trait is used to specify the functionality of `&`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up /// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. @@ -578,7 +581,7 @@ not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// ``` /// use std::ops::BitAnd; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl BitAnd for Foo { @@ -597,6 +600,7 @@ not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } #[lang="bitand"] #[stable(feature = "rust1", since = "1.0.0")] pub trait BitAnd { + /// The resulting type after applying the `&` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -623,7 +627,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// The `BitOr` trait is used to specify the functionality of `|`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up /// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. @@ -631,7 +635,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// ``` /// use std::ops::BitOr; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl BitOr for Foo { @@ -650,6 +654,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } #[lang="bitor"] #[stable(feature = "rust1", since = "1.0.0")] pub trait BitOr { + /// The resulting type after applying the `|` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -676,7 +681,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// The `BitXor` trait is used to specify the functionality of `^`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up /// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`. @@ -684,7 +689,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// ``` /// use std::ops::BitXor; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl BitXor for Foo { @@ -703,6 +708,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } #[lang="bitxor"] #[stable(feature = "rust1", since = "1.0.0")] pub trait BitXor { + /// The resulting type after applying the `^` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -729,7 +735,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// The `Shl` trait is used to specify the functionality of `<<`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up /// calling `shl`, and therefore, `main` prints `Shifting left!`. @@ -737,7 +743,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// ``` /// use std::ops::Shl; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Shl for Foo { @@ -756,6 +762,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } #[lang="shl"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Shl { + /// The resulting type after applying the `<<` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -800,7 +807,7 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// The `Shr` trait is used to specify the functionality of `>>`. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up /// calling `shr`, and therefore, `main` prints `Shifting right!`. @@ -808,7 +815,7 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// ``` /// use std::ops::Shr; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// /// impl Shr for Foo { @@ -827,6 +834,7 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } #[lang="shr"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Shr { + /// The resulting type after applying the `>>` operator #[stable(feature = "rust1", since = "1.0.0")] type Output; @@ -871,7 +879,7 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// The `Index` trait is used to specify the functionality of indexing operations /// like `arr[idx]` when used in an immutable context. /// -/// # Example +/// # Examples /// /// A trivial implementation of `Index`. When `Foo[Bar]` happens, it ends up /// calling `index`, and therefore, `main` prints `Indexing!`. @@ -879,14 +887,14 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// ``` /// use std::ops::Index; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// struct Bar; /// /// impl Index for Foo { /// type Output = Foo; /// -/// fn index<'a>(&'a self, _index: &Bar) -> &'a Foo { +/// fn index<'a>(&'a self, _index: Bar) -> &'a Foo { /// println!("Indexing!"); /// self /// } @@ -900,17 +908,19 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Index { + /// The returned type after indexing + #[stable(feature = "rust1", since = "1.0.0")] type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation #[stable(feature = "rust1", since = "1.0.0")] - fn index<'a>(&'a self, index: &Idx) -> &'a Self::Output; + fn index<'a>(&'a self, index: Idx) -> &'a Self::Output; } /// The `IndexMut` trait is used to specify the functionality of indexing /// operations like `arr[idx]`, when used in a mutable context. /// -/// # Example +/// # Examples /// /// A trivial implementation of `IndexMut`. When `Foo[Bar]` happens, it ends up /// calling `index_mut`, and therefore, `main` prints `Indexing!`. @@ -918,20 +928,20 @@ pub trait Index { /// ``` /// use std::ops::{Index, IndexMut}; /// -/// #[derive(Copy)] +/// #[derive(Copy, Clone)] /// struct Foo; /// struct Bar; /// /// impl Index for Foo { /// type Output = Foo; /// -/// fn index<'a>(&'a self, _index: &Bar) -> &'a Foo { +/// fn index<'a>(&'a self, _index: Bar) -> &'a Foo { /// self /// } /// } /// /// impl IndexMut for Foo { -/// fn index_mut<'a>(&'a mut self, _index: &Bar) -> &'a mut Foo { +/// fn index_mut<'a>(&'a mut self, _index: Bar) -> &'a mut Foo { /// println!("Indexing!"); /// self /// } @@ -947,7 +957,7 @@ pub trait Index { pub trait IndexMut: Index { /// The method for the indexing (`Foo[Bar]`) operation #[stable(feature = "rust1", since = "1.0.0")] - fn index_mut<'a>(&'a mut self, index: &Idx) -> &'a mut Self::Output; + fn index_mut<'a>(&'a mut self, index: Idx) -> &'a mut Self::Output; } /// An unbounded range. @@ -969,8 +979,10 @@ impl fmt::Debug for RangeFull { #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] pub start: Idx, /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] pub end: Idx, } @@ -987,11 +999,10 @@ impl fmt::Debug for Range { #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). + #[stable(feature = "rust1", since = "1.0.0")] pub start: Idx, } - - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for RangeFrom { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { @@ -1005,6 +1016,7 @@ impl fmt::Debug for RangeFrom { #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeTo { /// The upper bound of the range (exclusive). + #[stable(feature = "rust1", since = "1.0.0")] pub end: Idx, } @@ -1015,11 +1027,10 @@ impl fmt::Debug for RangeTo { } } - /// The `Deref` trait is used to specify the functionality of dereferencing /// operations like `*v`. /// -/// # Example +/// # Examples /// /// A struct with a single field which is accessible via dereferencing the /// struct. @@ -1047,6 +1058,7 @@ impl fmt::Debug for RangeTo { #[lang="deref"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Deref { + /// The resulting type after dereferencing #[stable(feature = "rust1", since = "1.0.0")] type Target: ?Sized; @@ -1072,7 +1084,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// The `DerefMut` trait is used to specify the functionality of dereferencing /// mutably like `*v = 1;` /// -/// # Example +/// # Examples /// /// A struct with a single field which is modifiable via dereferencing the /// struct. @@ -1121,9 +1133,8 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T { #[lang="fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] -pub trait Fn { - type Output; - +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait Fn : FnMut { /// This is called when the call operator is used. extern "rust-call" fn call(&self, args: Args) -> Self::Output; } @@ -1132,9 +1143,8 @@ pub trait Fn { #[lang="fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] -pub trait FnMut { - type Output; - +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnMut : FnOnce { /// This is called when the call operator is used. extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } @@ -1143,29 +1153,60 @@ pub trait FnMut { #[lang="fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` pub trait FnOnce { + /// The returned type after the call operator is used. type Output; /// This is called when the call operator is used. extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } -impl FnMut for F - where F : Fn -{ - type Output = >::Output; +#[cfg(not(stage0))] +mod impls { + use marker::Sized; + use super::{Fn, FnMut, FnOnce}; - extern "rust-call" fn call_mut(&mut self, args: A) -> >::Output { - self.call(args) + impl<'a,A,F:?Sized> Fn for &'a F + where F : Fn + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } } -} -impl FnOnce for F - where F : FnMut -{ - type Output = >::Output; + impl<'a,A,F:?Sized> FnMut for &'a F + where F : Fn + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + impl<'a,A,F:?Sized> FnOnce for &'a F + where F : Fn + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } - extern "rust-call" fn call_once(mut self, args: A) -> >::Output { - self.call_mut(args) + impl<'a,A,F:?Sized> FnMut for &'a mut F + where F : FnMut + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + impl<'a,A,F:?Sized> FnOnce for &'a mut F + where F : FnMut + { + type Output = F::Output; + extern "rust-call" fn call_once(mut self, args: A) -> F::Output { + (*self).call_mut(args) + } } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index abfef72a5d..6db7c9bd99 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -148,13 +148,12 @@ use self::Option::*; use clone::Clone; use cmp::{Eq, Ord}; use default::Default; -use iter::{ExactSizeIterator}; -use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, IntoIterator}; +use iter::ExactSizeIterator; +use iter::{Iterator, DoubleEndedIterator, FromIterator, IntoIterator}; use mem; -use ops::{Deref, FnOnce}; +use ops::FnOnce; use result::Result::{Ok, Err}; use result::Result; -use slice::AsSlice; use slice; // Note that this is not a lang item per se, but it has a hidden dependency on @@ -185,7 +184,7 @@ impl Option { /// Returns `true` if the option is a `Some` value /// - /// # Example + /// # Examples /// /// ``` /// let x: Option = Some(2); @@ -205,7 +204,7 @@ impl Option { /// Returns `true` if the option is a `None` value /// - /// # Example + /// # Examples /// /// ``` /// let x: Option = Some(2); @@ -226,7 +225,7 @@ impl Option { /// Convert from `Option` to `Option<&T>` /// - /// # Example + /// # Examples /// /// Convert an `Option` into an `Option`, preserving the original. /// The `map` method takes the `self` argument by value, consuming the original, @@ -251,7 +250,7 @@ impl Option { /// Convert from `Option` to `Option<&mut T>` /// - /// # Example + /// # Examples /// /// ``` /// let mut x = Some(2); @@ -272,9 +271,10 @@ impl Option { /// Convert from `Option` to `&mut [T]` (without copying) /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// let mut x = Some("Diamonds"); /// { /// let v = x.as_mut_slice(); @@ -311,14 +311,14 @@ impl Option { /// Panics if the value is a `None` with a custom panic message provided by /// `msg`. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some("value"); /// assert_eq!(x.expect("the world is ending"), "value"); /// ``` /// - /// ```{.should_fail} + /// ```{.should_panic} /// let x: Option<&str> = None; /// x.expect("the world is ending"); // panics with `world is ending` /// ``` @@ -331,7 +331,7 @@ impl Option { } } - /// Returns the inner `T` of a `Some(T)`. + /// Moves the value `v` out of the `Option` if it is `Some(v)`. /// /// # Panics /// @@ -343,14 +343,14 @@ impl Option { /// Instead, prefer to use pattern matching and handle the `None` /// case explicitly. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some("air"); /// assert_eq!(x.unwrap(), "air"); /// ``` /// - /// ```{.should_fail} + /// ```{.should_panic} /// let x: Option<&str> = None; /// assert_eq!(x.unwrap(), "air"); // fails /// ``` @@ -365,7 +365,7 @@ impl Option { /// Returns the contained value or a default. /// - /// # Example + /// # Examples /// /// ``` /// assert_eq!(Some("car").unwrap_or("bike"), "car"); @@ -382,10 +382,10 @@ impl Option { /// Returns the contained value or computes it from a closure. /// - /// # Example + /// # Examples /// /// ``` - /// let k = 10i32; + /// let k = 10; /// assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4); /// assert_eq!(None.unwrap_or_else(|| 2 * k), 20); /// ``` @@ -404,7 +404,7 @@ impl Option { /// Maps an `Option` to `Option` by applying a function to a contained value /// - /// # Example + /// # Examples /// /// Convert an `Option` into an `Option`, consuming the original: /// @@ -424,7 +424,7 @@ impl Option { /// Applies a function to the contained value or returns a default. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some("foo"); @@ -444,7 +444,7 @@ impl Option { /// Applies a function to the contained value or computes a default. /// - /// # Example + /// # Examples /// /// ``` /// let k = 21; @@ -467,9 +467,10 @@ impl Option { /// Transforms the `Option` into a `Result`, mapping `Some(v)` to /// `Ok(v)` and `None` to `Err(err)`. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// let x = Some("foo"); /// assert_eq!(x.ok_or(0), Ok("foo")); /// @@ -477,7 +478,7 @@ impl Option { /// assert_eq!(x.ok_or(0), Err(0)); /// ``` #[inline] - #[unstable(feature = "core")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn ok_or(self, err: E) -> Result { match self { Some(v) => Ok(v), @@ -488,9 +489,10 @@ impl Option { /// Transforms the `Option` into a `Result`, mapping `Some(v)` to /// `Ok(v)` and `None` to `Err(err())`. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// let x = Some("foo"); /// assert_eq!(x.ok_or_else(|| 0), Ok("foo")); /// @@ -498,7 +500,7 @@ impl Option { /// assert_eq!(x.ok_or_else(|| 0), Err(0)); /// ``` #[inline] - #[unstable(feature = "core")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn ok_or_else E>(self, err: F) -> Result { match self { Some(v) => Ok(v), @@ -512,7 +514,7 @@ impl Option { /// Returns an iterator over the possibly contained value. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some(4); @@ -529,9 +531,10 @@ impl Option { /// Returns a mutable iterator over the possibly contained value. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// let mut x = Some(4); /// match x.iter_mut().next() { /// Some(&mut ref mut v) => *v = 42, @@ -543,20 +546,19 @@ impl Option { /// assert_eq!(x.iter_mut().next(), None); /// ``` #[inline] - #[unstable(feature = "core", - reason = "waiting for iterator conventions")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut { IterMut { inner: Item { opt: self.as_mut() } } } /// Returns a consuming iterator over the possibly contained value. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some("string"); /// let v: Vec<&str> = x.into_iter().collect(); - /// assert_eq!(v, vec!["string"]); + /// assert_eq!(v, ["string"]); /// /// let x = None; /// let v: Vec<&str> = x.into_iter().collect(); @@ -574,7 +576,7 @@ impl Option { /// Returns `None` if the option is `None`, otherwise returns `optb`. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some(2); @@ -607,7 +609,7 @@ impl Option { /// /// Some languages call this operation flatmap. /// - /// # Example + /// # Examples /// /// ``` /// fn sq(x: u32) -> Option { Some(x * x) } @@ -629,7 +631,7 @@ impl Option { /// Returns the option if it contains a value, otherwise returns `optb`. /// - /// # Example + /// # Examples /// /// ``` /// let x = Some(2); @@ -660,7 +662,7 @@ impl Option { /// Returns the option if it contains a value, otherwise calls `f` and /// returns the result. /// - /// # Example + /// # Examples /// /// ``` /// fn nobody() -> Option<&'static str> { None } @@ -685,7 +687,7 @@ impl Option { /// Takes the value out of the option, leaving a `None` in its place. /// - /// # Example + /// # Examples /// /// ``` /// let mut x = Some(2); @@ -701,15 +703,26 @@ impl Option { pub fn take(&mut self) -> Option { mem::replace(self, None) } + + /// Convert from `Option` to `&[T]` (without copying) + #[inline] + #[unstable(feature = "as_slice", since = "unsure of the utility here")] + pub fn as_slice<'a>(&'a self) -> &'a [T] { + match *self { + Some(ref x) => slice::ref_slice(x), + None => { + let result: &[_] = &[]; + result + } + } + } } -impl<'a, T: Clone, D: Deref> Option { - /// Maps an Option to an Option by dereffing and cloning the contents of the Option. - /// Useful for converting an Option<&T> to an Option. - #[unstable(feature = "core", - reason = "recently added as part of collections reform")] +impl<'a, T: Clone> Option<&'a T> { + /// Maps an Option<&T> to an Option by cloning the contents of the Option. + #[stable(feature = "rust1", since = "1.0.0")] pub fn cloned(self) -> Option { - self.map(|t| t.deref().clone()) + self.map(|t| t.clone()) } } @@ -720,7 +733,7 @@ impl Option { /// value, otherwise if `None`, returns the default value for that /// type. /// - /// # Example + /// # Examples /// /// Convert a string to an integer, turning poorly-formed strings /// into 0 (the default value for integers). `parse` converts @@ -750,22 +763,6 @@ impl Option { // Trait implementations ///////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "core", - reason = "waiting on the stability of the trait itself")] -impl AsSlice for Option { - /// Convert from `Option` to `&[T]` (without copying) - #[inline] - fn as_slice<'a>(&'a self) -> &'a [T] { - match *self { - Some(ref x) => slice::ref_slice(x), - None => { - let result: &[_] = &[]; - result - } - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Default for Option { #[inline] @@ -897,7 +894,7 @@ impl> FromIterator> for Option { /// Here is an example which increments every integer in a vector, /// checking for overflow: /// - /// ```rust + /// ``` /// use std::u16; /// /// let v = vec!(1, 2); diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 61b4284e1d..d6e00df1fd 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -16,7 +16,7 @@ //! interface for panicking is: //! //! ```ignore -//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, uint)) -> !; +//! fn panic_impl(fmt: fmt::Arguments, &(&'static str, usize)) -> !; //! ``` //! //! This definition allows for panicking with any general message, but it does not @@ -34,26 +34,32 @@ use fmt; #[cold] #[inline(never)] // this is the slow path, always #[lang="panic"] -pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! { +pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { + // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially + // reduce size overhead. The format_args! macro uses str's Display trait to + // write expr, which calls Formatter::pad, which must accommodate string + // truncation and padding (even though none is used here). Using + // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the + // output binary, saving up to a few kilobytes. let (expr, file, line) = *expr_file_line; - panic_fmt(format_args!("{}", expr), &(file, line)) + panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line)) } #[cold] #[inline(never)] #[lang="panic_bounds_check"] -fn panic_bounds_check(file_line: &(&'static str, uint), - index: uint, len: uint) -> ! { +fn panic_bounds_check(file_line: &(&'static str, u32), + index: usize, len: usize) -> ! { panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}", len, index), file_line) } #[cold] #[inline(never)] -pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! { +pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! { #[allow(improper_ctypes)] extern { #[lang = "panic_fmt"] - fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !; + fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: usize) -> !; } let (file, line) = *file_line; - unsafe { panic_impl(fmt, file, line) } + unsafe { panic_impl(fmt, file, line as usize) } } diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index f4b1a0633d..e60bc49408 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -29,7 +29,6 @@ pub use marker::{Copy, Send, Sized, Sync}; pub use ops::{Drop, Fn, FnMut, FnOnce}; // Reexported functions -pub use iter::range; pub use mem::drop; // Reexported types and traits @@ -37,11 +36,12 @@ pub use mem::drop; pub use char::CharExt; pub use clone::Clone; pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; -pub use iter::{Extend, IteratorExt}; -pub use iter::{Iterator, DoubleEndedIterator}; -pub use iter::{ExactSizeIterator}; +pub use convert::{AsRef, AsMut, Into, From}; +pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator}; pub use option::Option::{self, Some, None}; -pub use ptr::{PtrExt, MutPtrExt}; pub use result::Result::{self, Ok, Err}; -pub use slice::{AsSlice, SliceExt}; -pub use str::{Str, StrExt}; +pub use slice::SliceExt; +pub use str::StrExt; + +#[allow(deprecated)] pub use slice::AsSlice; +#[allow(deprecated)] pub use str::Str; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 16b84dcf18..ff51e25fcb 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -15,12 +15,9 @@ //! Working with unsafe pointers in Rust is uncommon, //! typically limited to a few patterns. //! -//! Use the [`null` function](fn.null.html) to create null pointers, -//! the [`is_null`](trait.PtrExt.html#tymethod.is_null) -//! methods of the [`PtrExt` trait](trait.PtrExt.html) to check for null. -//! The `PtrExt` trait is imported by the prelude, so `is_null` etc. -//! work everywhere. The `PtrExt` also defines the `offset` method, -//! for pointer math. +//! Use the [`null` function](fn.null.html) to create null pointers, and +//! the `is_null` method of the `*const T` type to check for null. +//! The `*const T` type also defines the `offset` method, for pointer math. //! //! # Common ways to create unsafe pointers //! @@ -33,31 +30,35 @@ //! let my_speed_ptr: *mut i32 = &mut my_speed; //! ``` //! +//! To get a pointer to a boxed value, dereference the box: +//! +//! ``` +//! let my_num: Box = Box::new(10); +//! let my_num_ptr: *const i32 = &*my_num; +//! let mut my_speed: Box = Box::new(88); +//! let my_speed_ptr: *mut i32 = &mut *my_speed; +//! ``` +//! //! This does not take ownership of the original allocation //! and requires no resource management later, //! but you must not use the pointer after its lifetime. //! -//! ## 2. Transmute an owned box (`Box`). +//! ## 2. Consume a box (`Box`). //! -//! The `transmute` function takes, by value, whatever it's given -//! and returns it as whatever type is requested, as long as the -//! types are the same size. Because `Box` and `*mut T` have the same -//! representation they can be trivially, -//! though unsafely, transformed from one type to the other. +//! The `into_raw` function consumes a box and returns +//! the raw pointer. It doesn't destroy `T` or deallocate any memory. //! //! ``` -//! use std::mem; +//! # #![feature(alloc)] +//! use std::boxed; //! //! unsafe { -//! let my_num: Box = Box::new(10); -//! let my_num: *const i32 = mem::transmute(my_num); //! let my_speed: Box = Box::new(88); -//! let my_speed: *mut i32 = mem::transmute(my_speed); +//! let my_speed: *mut i32 = boxed::into_raw(my_speed); //! //! // By taking ownership of the original `Box` though -//! // we are obligated to transmute it back later to be destroyed. -//! drop(mem::transmute::<_, Box>(my_speed)); -//! drop(mem::transmute::<_, Box>(my_num)); +//! // we are obligated to put it together later to be destroyed. +//! drop(Box::from_raw(my_speed)); //! } //! ``` //! @@ -67,6 +68,7 @@ //! ## 3. Get it from C. //! //! ``` +//! # #![feature(libc)] //! extern crate libc; //! //! use std::mem; @@ -101,16 +103,31 @@ use cmp::Ordering::{self, Less, Equal, Greater}; // FIXME #19649: intrinsic docs don't render, so these have no docs :( -#[unstable(feature = "core")] -pub use intrinsics::copy_nonoverlapping_memory; +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +pub use intrinsics::copy_nonoverlapping; -#[unstable(feature = "core")] -pub use intrinsics::copy_memory; +/// dox +#[cfg(stage0)] +#[stable(feature = "rust1", since = "1.0.0")] +pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { + intrinsics::copy_nonoverlapping(dst, src, count) +} -#[unstable(feature = "core", - reason = "uncertain about naming and semantics")] -pub use intrinsics::set_memory; +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +pub use intrinsics::copy; +/// dox +#[cfg(stage0)] +#[stable(feature = "rust1", since = "1.0.0")] +pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { + intrinsics::copy(dst, src, count) +} + + +#[stable(feature = "rust1", since = "1.0.0")] +pub use intrinsics::write_bytes; /// Creates a null raw pointer. /// @@ -140,20 +157,6 @@ pub fn null() -> *const T { 0 as *const T } #[stable(feature = "rust1", since = "1.0.0")] pub fn null_mut() -> *mut T { 0 as *mut T } -/// Zeroes out `count * size_of::` bytes of memory at `dst`. `count` may be -/// `0`. -/// -/// # Safety -/// -/// Beyond accepting a raw pointer, this is unsafe because it will not drop the -/// contents of `dst`, and may be used to create invalid instances of `T`. -#[inline] -#[unstable(feature = "core", - reason = "may play a larger role in std::ptr future extensions")] -pub unsafe fn zero_memory(dst: *mut T, count: usize) { - set_memory(dst, 0, count); -} - /// Swaps the values at two mutable locations of the same type, without /// deinitialising either. They may overlap, unlike `mem::swap` which is /// otherwise equivalent. @@ -166,12 +169,11 @@ pub unsafe fn zero_memory(dst: *mut T, count: usize) { pub unsafe fn swap(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with let mut tmp: T = mem::uninitialized(); - let t: *mut T = &mut tmp; // Perform the swap - copy_nonoverlapping_memory(t, &*x, 1); - copy_memory(x, &*y, 1); // `x` and `y` may overlap - copy_nonoverlapping_memory(y, &*t, 1); + copy_nonoverlapping(x, &mut tmp, 1); + copy(y, x, 1); // `x` and `y` may overlap + copy_nonoverlapping(&tmp, y, 1); // y and t now point to the same thing, but we need to completely forget `tmp` // because it's no longer relevant. @@ -207,7 +209,7 @@ pub unsafe fn replace(dest: *mut T, mut src: T) -> T { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read(src: *const T) -> T { let mut tmp: T = mem::uninitialized(); - copy_nonoverlapping_memory(&mut tmp, src, 1); + copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -224,7 +226,22 @@ pub unsafe fn read_and_zero(dest: *mut T) -> T { let tmp = read(&*dest); // Now zero out `dest`: - zero_memory(dest, 1); + write_bytes(dest, 0, 1); + + tmp +} + +/// Variant of read_and_zero that writes the specific drop-flag byte +/// (which may be more appropriate than zero). +#[inline(always)] +#[unstable(feature = "core", + reason = "may play a larger role in std::ptr future extensions")] +pub unsafe fn read_and_drop(dest: *mut T) -> T { + // Copy the data out from `dest`: + let tmp = read(&*dest); + + // Now mark `dest` as dropped: + write_bytes(dest, mem::POST_DROP_U8, 1); tmp } @@ -246,14 +263,15 @@ pub unsafe fn write(dst: *mut T, src: T) { intrinsics::move_val_init(&mut *dst, src) } -/// Methods on raw pointers #[stable(feature = "rust1", since = "1.0.0")] -pub trait PtrExt: Sized { - type Target; - +#[lang = "const_ptr"] +impl *const T { /// Returns true if the pointer is null. #[stable(feature = "rust1", since = "1.0.0")] - fn is_null(self) -> bool; + #[inline] + pub fn is_null(self) -> bool where T: Sized { + self == 0 as *const T + } /// Returns `None` if the pointer is null, or else returns a reference to /// the value wrapped in `Some`. @@ -267,7 +285,14 @@ pub trait PtrExt: Sized { #[unstable(feature = "core", reason = "Option is not clearly the right return type, and we may want \ to tie the return lifetime to a borrow of the raw pointer")] - unsafe fn as_ref<'a>(&self) -> Option<&'a Self::Target>; + #[inline] + pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized { + if self.is_null() { + None + } else { + Some(&**self) + } + } /// Calculates the offset from a pointer. `count` is in units of T; e.g. a /// `count` of 3 represents a pointer offset of `3 * sizeof::()` bytes. @@ -278,90 +303,69 @@ pub trait PtrExt: Sized { /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether /// the pointer is used. #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn offset(self, count: isize) -> Self; + #[inline] + pub unsafe fn offset(self, count: isize) -> *const T where T: Sized { + intrinsics::offset(self, count) + } } -/// Methods on mutable raw pointers #[stable(feature = "rust1", since = "1.0.0")] -pub trait MutPtrExt { - type Target; +#[lang = "mut_ptr"] +impl *mut T { + /// Returns true if the pointer is null. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_null(self) -> bool where T: Sized { + self == 0 as *mut T + } - /// Returns `None` if the pointer is null, or else returns a mutable - /// reference to the value wrapped in `Some`. + /// Returns `None` if the pointer is null, or else returns a reference to + /// the value wrapped in `Some`. /// /// # Safety /// - /// As with `as_ref`, this is unsafe because it cannot verify the validity - /// of the returned pointer. + /// While this method and its mutable counterpart are useful for + /// null-safety, it is important to note that this is still an unsafe + /// operation because the returned value could be pointing to invalid + /// memory. #[unstable(feature = "core", reason = "Option is not clearly the right return type, and we may want \ to tie the return lifetime to a borrow of the raw pointer")] - unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PtrExt for *const T { - type Target = T; - - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - fn is_null(self) -> bool { self == 0 as *const T } - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) - } - - #[inline] - #[unstable(feature = "core", - reason = "return value does not necessarily convey all possible \ - information")] - unsafe fn as_ref<'a>(&self) -> Option<&'a T> { + pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized { if self.is_null() { None } else { Some(&**self) } } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PtrExt for *mut T { - type Target = T; - #[inline] + /// Calculates the offset from a pointer. `count` is in units of T; e.g. a + /// `count` of 3 represents a pointer offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The offset must be in-bounds of the object, or one-byte-past-the-end. + /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether + /// the pointer is used. #[stable(feature = "rust1", since = "1.0.0")] - fn is_null(self) -> bool { self == 0 as *mut T } - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn offset(self, count: isize) -> *mut T { + pub unsafe fn offset(self, count: isize) -> *mut T where T: Sized { intrinsics::offset(self, count) as *mut T } - #[inline] + /// Returns `None` if the pointer is null, or else returns a mutable + /// reference to the value wrapped in `Some`. + /// + /// # Safety + /// + /// As with `as_ref`, this is unsafe because it cannot verify the validity + /// of the returned pointer. #[unstable(feature = "core", reason = "return value does not necessarily convey all possible \ information")] - unsafe fn as_ref<'a>(&self) -> Option<&'a T> { - if self.is_null() { - None - } else { - Some(&**self) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl MutPtrExt for *mut T { - type Target = T; - #[inline] - #[unstable(feature = "core", - reason = "return value does not necessarily convey all possible \ - information")] - unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> { + pub unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> where T: Sized { if self.is_null() { None } else { @@ -372,33 +376,25 @@ impl MutPtrExt for *mut T { // Equality for pointers #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for *const T { +impl PartialEq for *const T { #[inline] - fn eq(&self, other: &*const T) -> bool { - *self == *other - } - #[inline] - fn ne(&self, other: &*const T) -> bool { !self.eq(other) } + fn eq(&self, other: &*const T) -> bool { *self == *other } } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for *const T {} +impl Eq for *const T {} #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for *mut T { - #[inline] - fn eq(&self, other: &*mut T) -> bool { - *self == *other - } +impl PartialEq for *mut T { #[inline] - fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } + fn eq(&self, other: &*mut T) -> bool { *self == *other } } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for *mut T {} +impl Eq for *mut T {} #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for *const T { +impl Clone for *const T { #[inline] fn clone(&self) -> *const T { *self @@ -406,7 +402,7 @@ impl Clone for *const T { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for *mut T { +impl Clone for *mut T { #[inline] fn clone(&self) -> *mut T { *self @@ -450,7 +446,7 @@ mod externfnpointers { // Comparison for pointers #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for *const T { +impl Ord for *const T { #[inline] fn cmp(&self, other: &*const T) -> Ordering { if self < other { @@ -464,7 +460,7 @@ impl Ord for *const T { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for *const T { +impl PartialOrd for *const T { #[inline] fn partial_cmp(&self, other: &*const T) -> Option { Some(self.cmp(other)) @@ -484,7 +480,7 @@ impl PartialOrd for *const T { } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for *mut T { +impl Ord for *mut T { #[inline] fn cmp(&self, other: &*mut T) -> Ordering { if self < other { @@ -498,7 +494,7 @@ impl Ord for *mut T { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for *mut T { +impl PartialOrd for *mut T { #[inline] fn partial_cmp(&self, other: &*mut T) -> Option { Some(self.cmp(other)) @@ -525,8 +521,8 @@ impl PartialOrd for *mut T { /// modified without a unique path to the `Unique` reference. Useful /// for building abstractions like `Vec` or `Box`, which /// internally use raw pointers to manage the memory that they own. -#[unstable(feature = "core", reason = "recently added to this module")] -pub struct Unique { +#[unstable(feature = "unique")] +pub struct Unique { pointer: NonZero<*const T>, _marker: PhantomData, } @@ -535,39 +531,37 @@ pub struct Unique { /// reference is unaliased. Note that this aliasing invariant is /// unenforced by the type system; the abstraction using the /// `Unique` must enforce it. -#[unstable(feature = "core", reason = "recently added to this module")] +#[unstable(feature = "unique")] unsafe impl Send for Unique { } /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they /// reference is unaliased. Note that this aliasing invariant is /// unenforced by the type system; the abstraction using the /// `Unique` must enforce it. -#[unstable(feature = "core", reason = "recently added to this module")] +#[unstable(feature = "unique")] unsafe impl Sync for Unique { } -impl Unique { +impl Unique { /// Create a new `Unique`. - #[unstable(feature = "core", - reason = "recently added to this module")] + #[unstable(feature = "unique")] pub unsafe fn new(ptr: *mut T) -> Unique { - Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData } + Unique { pointer: NonZero::new(ptr), _marker: PhantomData } } /// Dereference the content. - #[unstable(feature = "core", - reason = "recently added to this module")] + #[unstable(feature = "unique")] pub unsafe fn get(&self) -> &T { &**self.pointer } /// Mutably dereference the content. - #[unstable(feature = "core", - reason = "recently added to this module")] + #[unstable(feature = "unique")] pub unsafe fn get_mut(&mut self) -> &mut T { &mut ***self } } +#[unstable(feature = "unique")] impl Deref for Unique { type Target = *mut T; diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 5cc210df5b..ded52ff077 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -18,6 +18,7 @@ //! //! Their definition should always match the ABI defined in `rustc::back::abi`. +use clone::Clone; use marker::Copy; use mem; @@ -48,6 +49,7 @@ use mem; /// # Examples /// /// ``` +/// # #![feature(core)] /// use std::raw::{self, Repr}; /// /// let slice: &[u16] = &[1, 2, 3, 4]; @@ -62,17 +64,8 @@ pub struct Slice { } impl Copy for Slice {} - -/// The representation of an old closure. -#[repr(C)] -#[derive(Copy)] -#[unstable(feature = "core")] -#[deprecated(reason = "unboxed new closures do not have a universal representation; \ - `&Fn` (etc) trait objects should use `TraitObject` instead", - since= "1.0.0")] -pub struct Closure { - pub code: *mut (), - pub env: *mut (), +impl Clone for Slice { + fn clone(&self) -> Slice { *self } } /// The representation of a trait object like `&SomeTrait`. @@ -105,6 +98,7 @@ pub struct Closure { /// # Examples /// /// ``` +/// # #![feature(core)] /// use std::mem; /// use std::raw; /// @@ -146,7 +140,7 @@ pub struct Closure { /// assert_eq!(synthesized.bar(), 457); /// ``` #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct TraitObject { pub data: *mut (), pub vtable: *mut (), diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 23e936a75d..eff04dd590 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -60,25 +60,25 @@ //! that make working with it more succinct. //! //! ``` -//! let good_result: Result = Ok(10); -//! let bad_result: Result = Err(10); +//! let good_result: Result = Ok(10); +//! let bad_result: Result = Err(10); //! //! // The `is_ok` and `is_err` methods do what they say. //! assert!(good_result.is_ok() && !good_result.is_err()); //! assert!(bad_result.is_err() && !bad_result.is_ok()); //! //! // `map` consumes the `Result` and produces another. -//! let good_result: Result = good_result.map(|i| i + 1); -//! let bad_result: Result = bad_result.map(|i| i - 1); +//! let good_result: Result = good_result.map(|i| i + 1); +//! let bad_result: Result = bad_result.map(|i| i - 1); //! //! // Use `and_then` to continue the computation. -//! let good_result: Result = good_result.and_then(|i| Ok(i == 11)); +//! let good_result: Result = good_result.and_then(|i| Ok(i == 11)); //! //! // Use `or_else` to handle the error. -//! let bad_result: Result = bad_result.or_else(|i| Ok(11)); +//! let bad_result: Result = bad_result.or_else(|i| Ok(11)); //! //! // Consume the result and return the contents with `unwrap`. -//! let final_awesome_result = good_result.ok().unwrap(); +//! let final_awesome_result = good_result.unwrap(); //! ``` //! //! # Results must be used @@ -92,9 +92,10 @@ //! useful value. //! //! Consider the `write_line` method defined for I/O types -//! by the [`Writer`](../io/trait.Writer.html) trait: +//! by the [`Writer`](../old_io/trait.Writer.html) trait: //! //! ``` +//! # #![feature(old_io)] //! use std::old_io::IoError; //! //! trait Writer { @@ -110,7 +111,9 @@ //! something like this: //! //! ```{.ignore} -//! use std::old_io::{File, Open, Write}; +//! # #![feature(old_io)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! // If `write_line` errors, then we'll never know, because the return @@ -128,7 +131,9 @@ //! a marginally useful message indicating why: //! //! ```{.no_run} -//! use std::old_io::{File, Open, Write}; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! file.write_line("important message").ok().expect("failed to write message"); @@ -138,7 +143,9 @@ //! You might also simply assert success: //! //! ```{.no_run} -//! # use std::old_io::{File, Open, Write}; +//! # #![feature(old_io, old_path)] +//! # use std::old_io::*; +//! # use std::old_path::Path; //! //! # let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! assert!(file.write_line("important message").is_ok()); @@ -148,7 +155,9 @@ //! Or propagate the error up the call stack with `try!`: //! //! ``` -//! # use std::old_io::{File, Open, Write, IoError}; +//! # #![feature(old_io, old_path)] +//! # use std::old_io::*; +//! # use std::old_path::Path; //! fn write_message() -> Result<(), IoError> { //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write); //! try!(file.write_line("important message")); @@ -167,44 +176,48 @@ //! It replaces this: //! //! ``` -//! use std::old_io::{File, Open, Write, IoError}; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! struct Info { //! name: String, -//! age: int, -//! rating: int +//! age: i32, +//! rating: i32, //! } //! //! fn write_info(info: &Info) -> Result<(), IoError> { //! let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write); //! // Early return on error -//! if let Err(e) = file.write_line(format!("name: {}", info.name).as_slice()) { +//! if let Err(e) = file.write_line(&format!("name: {}", info.name)) { //! return Err(e) //! } -//! if let Err(e) = file.write_line(format!("age: {}", info.age).as_slice()) { +//! if let Err(e) = file.write_line(&format!("age: {}", info.age)) { //! return Err(e) //! } -//! return file.write_line(format!("rating: {}", info.rating).as_slice()); +//! return file.write_line(&format!("rating: {}", info.rating)); //! } //! ``` //! //! With this: //! //! ``` -//! use std::old_io::{File, Open, Write, IoError}; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! struct Info { //! name: String, -//! age: int, -//! rating: int +//! age: i32, +//! rating: i32, //! } //! //! fn write_info(info: &Info) -> Result<(), IoError> { //! let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write); //! // Early return on error -//! try!(file.write_line(format!("name: {}", info.name).as_slice())); -//! try!(file.write_line(format!("age: {}", info.age).as_slice())); -//! try!(file.write_line(format!("rating: {}", info.rating).as_slice())); +//! try!(file.write_line(&format!("name: {}", info.name))); +//! try!(file.write_line(&format!("age: {}", info.age))); +//! try!(file.write_line(&format!("rating: {}", info.rating))); //! return Ok(()); //! } //! ``` @@ -230,10 +243,10 @@ use self::Result::{Ok, Err}; use clone::Clone; use fmt; -use iter::{Iterator, IteratorExt, DoubleEndedIterator, - FromIterator, ExactSizeIterator, IntoIterator}; +use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator}; use ops::{FnMut, FnOnce}; use option::Option::{self, None, Some}; +#[allow(deprecated)] use slice::AsSlice; use slice; @@ -265,13 +278,13 @@ impl Result { /// Returns true if the result is `Ok` /// - /// # Example + /// # Examples /// /// ``` - /// let x: Result = Ok(-3); + /// let x: Result = Ok(-3); /// assert_eq!(x.is_ok(), true); /// - /// let x: Result = Err("Some error message"); + /// let x: Result = Err("Some error message"); /// assert_eq!(x.is_ok(), false); /// ``` #[inline] @@ -285,13 +298,13 @@ impl Result { /// Returns true if the result is `Err` /// - /// # Example + /// # Examples /// /// ``` - /// let x: Result = Ok(-3); + /// let x: Result = Ok(-3); /// assert_eq!(x.is_err(), false); /// - /// let x: Result = Err("Some error message"); + /// let x: Result = Err("Some error message"); /// assert_eq!(x.is_err(), true); /// ``` #[inline] @@ -309,7 +322,7 @@ impl Result { /// Converts `self` into an `Option`, consuming `self`, /// and discarding the error, if any. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(2); @@ -330,9 +343,9 @@ impl Result { /// Convert from `Result` to `Option` /// /// Converts `self` into an `Option`, consuming `self`, - /// and discarding the value, if any. + /// and discarding the success value, if any. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(2); @@ -378,18 +391,18 @@ impl Result { /// Convert from `Result` to `Result<&mut T, &mut E>` /// /// ``` - /// fn mutate(r: &mut Result) { + /// fn mutate(r: &mut Result) { /// match r.as_mut() { /// Ok(&mut ref mut v) => *v = 42, /// Err(&mut ref mut e) => *e = 0, /// } /// } /// - /// let mut x: Result = Ok(2); + /// let mut x: Result = Ok(2); /// mutate(&mut x); /// assert_eq!(x.unwrap(), 42); /// - /// let mut x: Result = Err(13); + /// let mut x: Result = Err(13); /// mutate(&mut x); /// assert_eq!(x.unwrap_err(), 0); /// ``` @@ -402,9 +415,24 @@ impl Result { } } + /// Convert from `Result` to `&[T]` (without copying) + #[inline] + #[unstable(feature = "as_slice", since = "unsure of the utility here")] + pub fn as_slice(&self) -> &[T] { + match *self { + Ok(ref x) => slice::ref_slice(x), + Err(_) => { + // work around lack of implicit coercion from fixed-size array to slice + let emp: &[_] = &[]; + emp + } + } + } + /// Convert from `Result` to `&mut [T]` (without copying) /// /// ``` + /// # #![feature(core)] /// let mut x: Result<&str, u32> = Ok("Gold"); /// { /// let v = x.as_mut_slice(); @@ -440,26 +468,28 @@ impl Result { /// /// This function can be used to compose the results of two functions. /// - /// # Example + /// # Examples /// /// Sum the lines of a buffer by mapping strings to numbers, /// ignoring I/O and parse errors: /// /// ``` - /// use std::old_io::IoResult; + /// # #![feature(old_io)] + /// use std::old_io::*; /// - /// let mut buffer = &mut b"1\n2\n3\n4\n"; + /// let mut buffer: &[u8] = b"1\n2\n3\n4\n"; + /// let mut buffer = &mut buffer; /// /// let mut sum = 0; /// /// while !buffer.is_empty() { /// let line: IoResult = buffer.read_line(); /// // Convert the string line to a number using `map` and `from_str` - /// let val: IoResult = line.map(|line| { - /// line.trim_right().parse::().unwrap_or(0) + /// let val: IoResult = line.map(|line| { + /// line.trim_right().parse::().unwrap_or(0) /// }); /// // Add the value if there were no errors, otherwise add 0 - /// sum += val.ok().unwrap_or(0); + /// sum += val.unwrap_or(0); /// } /// /// assert!(sum == 10); @@ -479,7 +509,7 @@ impl Result { /// This function can be used to pass through a successful result while handling /// an error. /// - /// # Example + /// # Examples /// /// ``` /// fn stringify(x: u32) -> String { format!("error code: {}", x) } @@ -505,7 +535,7 @@ impl Result { /// Returns an iterator over the possibly contained value. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(7); @@ -522,7 +552,7 @@ impl Result { /// Returns a mutable iterator over the possibly contained value. /// - /// # Example + /// # Examples /// /// ``` /// let mut x: Result = Ok(7); @@ -543,16 +573,16 @@ impl Result { /// Returns a consuming iterator over the possibly contained value. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(5); /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, vec![5]); + /// assert_eq!(v, [5]); /// /// let x: Result = Err("nothing!"); /// let v: Vec = x.into_iter().collect(); - /// assert_eq!(v, vec![]); + /// assert_eq!(v, []); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -566,7 +596,7 @@ impl Result { /// Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(2); @@ -598,7 +628,7 @@ impl Result { /// /// This function can be used for control flow based on result values. /// - /// # Example + /// # Examples /// /// ``` /// fn sq(x: u32) -> Result { Ok(x * x) } @@ -620,7 +650,7 @@ impl Result { /// Returns `res` if the result is `Err`, otherwise returns the `Ok` value of `self`. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(2); @@ -641,9 +671,9 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or(self, res: Result) -> Result { + pub fn or(self, res: Result) -> Result { match self { - Ok(_) => self, + Ok(v) => Ok(v), Err(_) => res, } } @@ -652,7 +682,7 @@ impl Result { /// /// This function can be used for control flow based on result values. /// - /// # Example + /// # Examples /// /// ``` /// fn sq(x: u32) -> Result { Ok(x * x) } @@ -675,7 +705,7 @@ impl Result { /// Unwraps a result, yielding the content of an `Ok`. /// Else it returns `optb`. /// - /// # Example + /// # Examples /// /// ``` /// let optb = 2; @@ -697,7 +727,7 @@ impl Result { /// Unwraps a result, yielding the content of an `Ok`. /// If the value is an `Err` then it calls `op` with its value. /// - /// # Example + /// # Examples /// /// ``` /// fn count(x: &str) -> usize { x.len() } @@ -724,14 +754,14 @@ impl Result { /// Panics if the value is an `Err`, with a custom panic message provided /// by the `Err`'s value. /// - /// # Example + /// # Examples /// /// ``` /// let x: Result = Ok(2); /// assert_eq!(x.unwrap(), 2); /// ``` /// - /// ```{.should_fail} + /// ```{.should_panic} /// let x: Result = Err("emergency failure"); /// x.unwrap(); // panics with `emergency failure` /// ``` @@ -755,9 +785,9 @@ impl Result { /// Panics if the value is an `Ok`, with a custom panic message provided /// by the `Ok`'s value. /// - /// # Example + /// # Examples /// - /// ```{.should_fail} + /// ```{.should_panic} /// let x: Result = Ok(2); /// x.unwrap_err(); // panics with `2` /// ``` @@ -781,10 +811,14 @@ impl Result { // Trait implementations ///////////////////////////////////////////////////////////////////////////// +#[unstable(feature = "core", + reason = "waiting on the stability of the trait itself")] +#[deprecated(since = "1.0.0", + reason = "use inherent method instead")] +#[allow(deprecated)] impl AsSlice for Result { /// Convert from `Result` to `&[T]` (without copying) #[inline] - #[stable(feature = "rust1", since = "1.0.0")] fn as_slice<'a>(&'a self) -> &'a [T] { match *self { Ok(ref x) => slice::ref_slice(x), @@ -896,7 +930,7 @@ impl> FromIterator> for Result { /// Here is an example which increments every integer in a vector, /// checking for overflow: /// - /// ```rust + /// ``` /// use std::u32; /// /// let v = vec!(1, 2); diff --git a/src/libcore/simd.rs b/src/libcore/simd.rs index 0058971faf..7b55ba49a0 100644 --- a/src/libcore/simd.rs +++ b/src/libcore/simd.rs @@ -19,7 +19,7 @@ //! provided beyond this module. //! //! ```rust -//! +//! # #![feature(core)] //! fn main() { //! use std::simd::f32x4; //! let a = f32x4(40.0, 41.0, 42.0, 43.0); @@ -38,7 +38,7 @@ #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct i8x16(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, @@ -47,26 +47,26 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8, #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct i16x8(pub i16, pub i16, pub i16, pub i16, pub i16, pub i16, pub i16, pub i16); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct i32x4(pub i32, pub i32, pub i32, pub i32); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct i64x2(pub i64, pub i64); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct u8x16(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, @@ -75,31 +75,31 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8, #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct u16x8(pub u16, pub u16, pub u16, pub u16, pub u16, pub u16, pub u16, pub u16); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct u32x4(pub u32, pub u32, pub u32, pub u32); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct u64x2(pub u64, pub u64); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct f32x4(pub f32, pub f32, pub f32, pub f32); #[unstable(feature = "core")] #[simd] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct f64x2(pub f64, pub f64); diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index a86da53b37..70e60adf64 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -40,6 +40,7 @@ use cmp::{Ordering, PartialEq, PartialOrd, Eq, Ord}; use cmp::Ordering::{Less, Equal, Greater}; use cmp; use default::Default; +use intrinsics::assume; use iter::*; use ops::{FnMut, self, Index}; use ops::RangeFull; @@ -48,10 +49,9 @@ use option::Option::{None, Some}; use result::Result; use result::Result::{Ok, Err}; use ptr; -use ptr::PtrExt; use mem; use mem::size_of; -use marker::{Sized, self}; +use marker::{Send, Sized, Sync, self}; use raw::Repr; // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module. use raw::Slice as RawSlice; @@ -88,7 +88,6 @@ pub trait SliceExt { fn len(&self) -> usize; fn is_empty(&self) -> bool { self.len() == 0 } fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>; - fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item]; fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>; fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>; fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item]; @@ -137,6 +136,7 @@ impl SliceExt for [T] { fn iter<'a>(&'a self) -> Iter<'a, T> { unsafe { let p = self.as_ptr(); + assume(!p.is_null()); if mem::size_of::() == 0 { Iter {ptr: p, end: (p as usize + self.len()) as *const T, @@ -259,16 +259,13 @@ impl SliceExt for [T] { if index < self.len() { Some(&mut self[index]) } else { None } } - #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { self } - #[inline] fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { unsafe { let self2: &mut [T] = mem::transmute_copy(&self); - (ops::IndexMut::index_mut(self, &ops::RangeTo { end: mid } ), - ops::IndexMut::index_mut(self2, &ops::RangeFrom { start: mid } )) + (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ), + ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } )) } } @@ -276,6 +273,7 @@ impl SliceExt for [T] { fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> { unsafe { let p = self.as_mut_ptr(); + assume(!p.is_null()); if mem::size_of::() == 0 { IterMut {ptr: p, end: (p as usize + self.len()) as *mut T, @@ -348,6 +346,7 @@ impl SliceExt for [T] { ChunksMut { v: self, chunk_size: chunk_size } } + #[inline] fn swap(&mut self, a: usize, b: usize) { unsafe { // Can't take two mutable loans from one vector, so instead just cast @@ -492,7 +491,7 @@ impl SliceExt for [T] { impl ops::Index for [T] { type Output = T; - fn index(&self, &index: &usize) -> &T { + fn index(&self, index: usize) -> &T { assert!(index < self.len()); unsafe { mem::transmute(self.repr().data.offset(index as isize)) } @@ -501,7 +500,8 @@ impl ops::Index for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut for [T] { - fn index_mut(&mut self, &index: &usize) -> &mut T { + #[inline] + fn index_mut(&mut self, index: usize) -> &mut T { assert!(index < self.len()); unsafe { mem::transmute(self.repr().data.offset(index as isize)) } @@ -511,39 +511,43 @@ impl ops::IndexMut for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for [T] { type Output = [T]; + #[inline] - fn index(&self, index: &ops::Range) -> &[T] { + fn index(&self, index: ops::Range) -> &[T] { assert!(index.start <= index.end); assert!(index.end <= self.len()); unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(index.start as isize), - len: index.end - index.start - }) + from_raw_parts ( + self.as_ptr().offset(index.start as isize), + index.end - index.start + ) } } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for [T] { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeTo) -> &[T] { - self.index(&ops::Range{ start: 0, end: index.end }) + fn index(&self, index: ops::RangeTo) -> &[T] { + self.index(ops::Range{ start: 0, end: index.end }) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for [T] { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeFrom) -> &[T] { - self.index(&ops::Range{ start: index.start, end: self.len() }) + fn index(&self, index: ops::RangeFrom) -> &[T] { + self.index(ops::Range{ start: index.start, end: self.len() }) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for [T] { type Output = [T]; + #[inline] - fn index(&self, _index: &RangeFull) -> &[T] { + fn index(&self, _index: RangeFull) -> &[T] { self } } @@ -551,36 +555,36 @@ impl ops::Index for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for [T] { #[inline] - fn index_mut(&mut self, index: &ops::Range) -> &mut [T] { + fn index_mut(&mut self, index: ops::Range) -> &mut [T] { assert!(index.start <= index.end); assert!(index.end <= self.len()); unsafe { - transmute(RawSlice { - data: self.as_ptr().offset(index.start as isize), - len: index.end - index.start - }) + from_raw_parts_mut( + self.as_mut_ptr().offset(index.start as isize), + index.end - index.start + ) } } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for [T] { #[inline] - fn index_mut(&mut self, index: &ops::RangeTo) -> &mut [T] { - self.index_mut(&ops::Range{ start: 0, end: index.end }) + fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { + self.index_mut(ops::Range{ start: 0, end: index.end }) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut> for [T] { #[inline] - fn index_mut(&mut self, index: &ops::RangeFrom) -> &mut [T] { + fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { let len = self.len(); - self.index_mut(&ops::Range{ start: index.start, end: len }) + self.index_mut(ops::Range{ start: index.start, end: len }) } } #[stable(feature = "rust1", since = "1.0.0")] impl ops::IndexMut for [T] { #[inline] - fn index_mut(&mut self, _index: &RangeFull) -> &mut [T] { + fn index_mut(&mut self, _index: RangeFull) -> &mut [T] { self } } @@ -593,24 +597,29 @@ impl ops::IndexMut for [T] { /// Data that is viewable as a slice. #[unstable(feature = "core", reason = "will be replaced by slice syntax")] +#[deprecated(since = "1.0.0", + reason = "use std::convert::AsRef<[T]> instead")] pub trait AsSlice { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a [T]; } #[unstable(feature = "core", reason = "trait is experimental")] +#[allow(deprecated)] impl AsSlice for [T] { #[inline(always)] fn as_slice<'a>(&'a self) -> &'a [T] { self } } #[unstable(feature = "core", reason = "trait is experimental")] +#[allow(deprecated)] impl<'a, T, U: ?Sized + AsSlice> AsSlice for &'a U { #[inline(always)] fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } } #[unstable(feature = "core", reason = "trait is experimental")] +#[allow(deprecated)] impl<'a, T, U: ?Sized + AsSlice> AsSlice for &'a mut U { #[inline(always)] fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) } @@ -657,6 +666,8 @@ macro_rules! iterator { fn next(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks unsafe { + ::intrinsics::assume(!self.ptr.is_null()); + ::intrinsics::assume(!self.end.is_null()); if self.ptr == self.end { None } else { @@ -693,6 +704,8 @@ macro_rules! iterator { fn next_back(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks unsafe { + ::intrinsics::assume(!self.ptr.is_null()); + ::intrinsics::assume(!self.end.is_null()); if self.end == self.ptr { None } else { @@ -723,7 +736,21 @@ macro_rules! make_slice { diff / mem::size_of::<$t>() }; unsafe { - transmute::<_, $result>(RawSlice { data: $start, len: len }) + from_raw_parts($start, len) + } + }} +} + +macro_rules! make_mut_slice { + ($t: ty => $result: ty: $start: expr, $end: expr) => {{ + let diff = $end as usize - $start as usize; + let len = if mem::size_of::() == 0 { + diff + } else { + diff / mem::size_of::<$t>() + }; + unsafe { + from_raw_parts_mut($start, len) } }} } @@ -736,11 +763,15 @@ pub struct Iter<'a, T: 'a> { _marker: marker::PhantomData<&'a T>, } +unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {} +unsafe impl<'a, T: Sync> Send for Iter<'a, T> {} + #[unstable(feature = "core")] impl<'a, T> ops::Index> for Iter<'a, T> { type Output = [T]; + #[inline] - fn index(&self, index: &ops::Range) -> &[T] { + fn index(&self, index: ops::Range) -> &[T] { self.as_slice().index(index) } } @@ -748,8 +779,9 @@ impl<'a, T> ops::Index> for Iter<'a, T> { #[unstable(feature = "core")] impl<'a, T> ops::Index> for Iter<'a, T> { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeTo) -> &[T] { + fn index(&self, index: ops::RangeTo) -> &[T] { self.as_slice().index(index) } } @@ -757,8 +789,9 @@ impl<'a, T> ops::Index> for Iter<'a, T> { #[unstable(feature = "core")] impl<'a, T> ops::Index> for Iter<'a, T> { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeFrom) -> &[T] { + fn index(&self, index: ops::RangeFrom) -> &[T] { self.as_slice().index(index) } } @@ -766,8 +799,9 @@ impl<'a, T> ops::Index> for Iter<'a, T> { #[unstable(feature = "core")] impl<'a, T> ops::Index for Iter<'a, T> { type Output = [T]; + #[inline] - fn index(&self, _index: &RangeFull) -> &[T] { + fn index(&self, _index: RangeFull) -> &[T] { self.as_slice() } } @@ -826,36 +860,42 @@ pub struct IterMut<'a, T: 'a> { _marker: marker::PhantomData<&'a mut T>, } +unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {} +unsafe impl<'a, T: Send> Send for IterMut<'a, T> {} #[unstable(feature = "core")] impl<'a, T> ops::Index> for IterMut<'a, T> { type Output = [T]; + #[inline] - fn index(&self, index: &ops::Range) -> &[T] { - self.index(&RangeFull).index(index) + fn index(&self, index: ops::Range) -> &[T] { + self.index(RangeFull).index(index) } } #[unstable(feature = "core")] impl<'a, T> ops::Index> for IterMut<'a, T> { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeTo) -> &[T] { - self.index(&RangeFull).index(index) + fn index(&self, index: ops::RangeTo) -> &[T] { + self.index(RangeFull).index(index) } } #[unstable(feature = "core")] impl<'a, T> ops::Index> for IterMut<'a, T> { type Output = [T]; + #[inline] - fn index(&self, index: &ops::RangeFrom) -> &[T] { - self.index(&RangeFull).index(index) + fn index(&self, index: ops::RangeFrom) -> &[T] { + self.index(RangeFull).index(index) } } #[unstable(feature = "core")] impl<'a, T> ops::Index for IterMut<'a, T> { type Output = [T]; + #[inline] - fn index(&self, _index: &RangeFull) -> &[T] { + fn index(&self, _index: RangeFull) -> &[T] { make_slice!(T => &[T]: self.ptr, self.end) } } @@ -863,29 +903,32 @@ impl<'a, T> ops::Index for IterMut<'a, T> { #[unstable(feature = "core")] impl<'a, T> ops::IndexMut> for IterMut<'a, T> { #[inline] - fn index_mut(&mut self, index: &ops::Range) -> &mut [T] { - self.index_mut(&RangeFull).index_mut(index) + fn index_mut(&mut self, index: ops::Range) -> &mut [T] { + self.index_mut(RangeFull).index_mut(index) } } #[unstable(feature = "core")] impl<'a, T> ops::IndexMut> for IterMut<'a, T> { + #[inline] - fn index_mut(&mut self, index: &ops::RangeTo) -> &mut [T] { - self.index_mut(&RangeFull).index_mut(index) + fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { + self.index_mut(RangeFull).index_mut(index) } } #[unstable(feature = "core")] impl<'a, T> ops::IndexMut> for IterMut<'a, T> { + #[inline] - fn index_mut(&mut self, index: &ops::RangeFrom) -> &mut [T] { - self.index_mut(&RangeFull).index_mut(index) + fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { + self.index_mut(RangeFull).index_mut(index) } } #[unstable(feature = "core")] impl<'a, T> ops::IndexMut for IterMut<'a, T> { + #[inline] - fn index_mut(&mut self, _index: &RangeFull) -> &mut [T] { - make_slice!(T => &mut [T]: self.ptr, self.end) + fn index_mut(&mut self, _index: RangeFull) -> &mut [T] { + make_mut_slice!(T => &mut [T]: self.ptr, self.end) } } @@ -899,7 +942,7 @@ impl<'a, T> IterMut<'a, T> { /// restricted lifetimes that do not consume the iterator. #[unstable(feature = "core")] pub fn into_slice(self) -> &'a mut [T] { - make_slice!(T => &'a mut [T]: self.ptr, self.end) + make_mut_slice!(T => &'a mut [T]: self.ptr, self.end) } } @@ -1083,18 +1126,20 @@ impl> Iterator for GenericSplitN { #[inline] fn next(&mut self) -> Option { - if self.count == 0 { - self.iter.finish() - } else { - self.count -= 1; - if self.invert { self.iter.next_back() } else { self.iter.next() } + match self.count { + 0 => None, + 1 => { self.count -= 1; self.iter.finish() } + _ => { + self.count -= 1; + if self.invert {self.iter.next_back()} else {self.iter.next()} + } } } #[inline] fn size_hint(&self) -> (usize, Option) { let (lower, upper_opt) = self.iter.size_hint(); - (lower, upper_opt.map(|upper| cmp::min(self.count + 1, upper))) + (lower, upper_opt.map(|upper| cmp::min(self.count, upper))) } } @@ -1155,13 +1200,23 @@ forward_iterator! { SplitNMut: T, &'a mut [T] } forward_iterator! { RSplitNMut: T, &'a mut [T] } /// An iterator over overlapping subslices of length `size`. -#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Windows<'a, T:'a> { v: &'a [T], size: usize } +// FIXME(#19839) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Clone for Windows<'a, T> { + fn clone(&self) -> Windows<'a, T> { + Windows { + v: self.v, + size: self.size, + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Windows<'a, T> { type Item = &'a [T]; @@ -1227,13 +1282,23 @@ impl<'a, T> RandomAccessIterator for Windows<'a, T> { /// /// When the slice len is not evenly divided by the chunk size, the last slice /// of the iteration will be the remainder. -#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Chunks<'a, T:'a> { v: &'a [T], size: usize } +// FIXME(#19839) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> Clone for Chunks<'a, T> { + fn clone(&self) -> Chunks<'a, T> { + Chunks { + v: self.v, + size: self.size, + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Chunks<'a, T> { type Item = &'a [T]; @@ -1371,7 +1436,7 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} #[unstable(feature = "core")] pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { unsafe { - transmute(RawSlice { data: s, len: 1 }) + from_raw_parts(s, 1) } } @@ -1379,8 +1444,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] { #[unstable(feature = "core")] pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { unsafe { - let ptr: *const A = transmute(s); - transmute(RawSlice { data: ptr, len: 1 }) + from_raw_parts_mut(s, 1) } } @@ -1400,9 +1464,9 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { /// function taking the lifetime of a host value for the slice, or by explicit /// annotation. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::slice; /// /// // manifest a slice out of thin air! @@ -1413,7 +1477,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { /// } /// ``` #[inline] -#[unstable(feature = "core")] +#[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] { transmute(RawSlice { data: p, len: len }) } @@ -1425,58 +1489,11 @@ pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: usize) -> &'a [T] { /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. #[inline] -#[unstable(feature = "core")] +#[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { transmute(RawSlice { data: p, len: len }) } -/// Forms a slice from a pointer and a length. -/// -/// The pointer given is actually a reference to the base of the slice. This -/// reference is used to give a concrete lifetime to tie the returned slice to. -/// Typically this should indicate that the slice is valid for as long as the -/// pointer itself is valid. -/// -/// The `len` argument is the number of **elements**, not the number of bytes. -/// -/// This function is unsafe as there is no guarantee that the given pointer is -/// valid for `len` elements, nor whether the lifetime provided is a suitable -/// lifetime for the returned slice. -/// -/// # Example -/// -/// ```rust -/// use std::slice; -/// -/// // manifest a slice out of thin air! -/// let ptr = 0x1234 as *const usize; -/// let amt = 10; -/// unsafe { -/// let slice = slice::from_raw_buf(&ptr, amt); -/// } -/// ``` -#[inline] -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use from_raw_parts")] -pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: usize) -> &'a [T] { - transmute(RawSlice { data: *p, len: len }) -} - -/// Performs the same functionality as `from_raw_buf`, except that a mutable -/// slice is returned. -/// -/// This function is unsafe for the same reasons as `from_raw_buf`, as well as -/// not being able to provide a non-aliasing guarantee of the returned mutable -/// slice. -#[inline] -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "use from_raw_parts_mut")] -pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: usize) -> &'a mut [T] { - transmute(RawSlice { data: *p, len: len }) -} - // // Submodules // @@ -1496,7 +1513,7 @@ pub mod bytes { impl MutableByteVector for [u8] { #[inline] fn set_memory(&mut self, value: u8) { - unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) }; + unsafe { ptr::write_bytes(self.as_mut_ptr(), value, self.len()) }; } } @@ -1504,15 +1521,15 @@ pub mod bytes { /// /// Panics if the length of `dst` is less than the length of `src`. #[inline] - pub fn copy_memory(dst: &mut [u8], src: &[u8]) { + pub fn copy_memory(src: &[u8], dst: &mut [u8]) { let len_src = src.len(); assert!(dst.len() >= len_src); // `dst` is unaliasable, so we know statically it doesn't overlap // with `src`. unsafe { - ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), - src.as_ptr(), - len_src); + ptr::copy_nonoverlapping(src.as_ptr(), + dst.as_mut_ptr(), + len_src); } } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index eec997b9f1..dbb365c4e2 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -16,26 +16,29 @@ #![doc(primitive = "str")] -use self::Searcher::{Naive, TwoWay, TwoWayLong}; +use self::OldSearcher::{TwoWay, TwoWayLong}; +use char::CharExt; use clone::Clone; use cmp::{self, Eq}; use default::Default; -use error::Error; use fmt; use iter::ExactSizeIterator; -use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator}; +use iter::{Map, Iterator, DoubleEndedIterator}; use marker::Sized; use mem; -use num::Int; -use ops::{Fn, FnMut}; +use ops::{Fn, FnMut, FnOnce}; use option::Option::{self, None, Some}; -use ptr::PtrExt; use raw::{Repr, Slice}; use result::Result::{self, Ok, Err}; use slice::{self, SliceExt}; use usize; +pub use self::pattern::Pattern; +pub use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep}; + +mod pattern; + macro_rules! delegate_iter { (exact $te:ty : $ti:ty) => { delegate_iter!{$te : $ti} @@ -70,7 +73,7 @@ macro_rules! delegate_iter { }; (pattern $te:ty : $ti:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, P: CharEq> Iterator for $ti { + impl<'a, P: Pattern<'a>> Iterator for $ti { type Item = $te; #[inline] @@ -83,7 +86,8 @@ macro_rules! delegate_iter { } } #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, P: CharEq> DoubleEndedIterator for $ti { + impl<'a, P: Pattern<'a>> DoubleEndedIterator for $ti + where P::Searcher: DoubleEndedSearcher<'a> { #[inline] fn next_back(&mut self) -> Option<$te> { self.0.next_back() @@ -92,7 +96,8 @@ macro_rules! delegate_iter { }; (pattern forward $te:ty : $ti:ty) => { #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, P: CharEq> Iterator for $ti { + impl<'a, P: Pattern<'a>> Iterator for $ti + where P::Searcher: DoubleEndedSearcher<'a> { type Item = $te; #[inline] @@ -104,7 +109,24 @@ macro_rules! delegate_iter { self.0.size_hint() } } - } + }; + (pattern reverse $te:ty : $ti:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, P: Pattern<'a>> Iterator for $ti + where P::Searcher: ReverseSearcher<'a> + { + type Item = $te; + + #[inline] + fn next(&mut self) -> Option<$te> { + self.0.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + }; } /// A trait to abstract the idea of creating a new instance of a type from a @@ -127,12 +149,22 @@ impl FromStr for bool { /// Parse a `bool` from a string. /// - /// Yields an `Option`, because `s` may or may not actually be - /// parseable. + /// Yields a `Result`, because `s` may or may not + /// actually be parseable. /// /// # Examples /// - /// ```rust + /// ``` + /// use std::str::FromStr; + /// + /// assert_eq!(FromStr::from_str("true"), Ok(true)); + /// assert_eq!(FromStr::from_str("false"), Ok(false)); + /// assert!(::from_str("not even a boolean").is_err()); + /// ``` + /// + /// Note, in many cases, the `.parse()` method on `str` is more proper. + /// + /// ``` /// assert_eq!("true".parse(), Ok(true)); /// assert_eq!("false".parse(), Ok(false)); /// assert!("not even a boolean".parse::().is_err()); @@ -159,11 +191,6 @@ impl fmt::Display for ParseBoolError { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseBoolError { - fn description(&self) -> &str { "failed to parse bool" } -} - /* Section: Creating a string */ @@ -208,81 +235,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { mem::transmute(v) } -/// Constructs a static string slice from a given raw pointer. -/// -/// This function will read memory starting at `s` until it finds a 0, and then -/// transmute the memory up to that point as a string slice, returning the -/// corresponding `&'static str` value. -/// -/// This function is unsafe because the caller must ensure the C string itself -/// has the static lifetime and that the memory `s` is valid up to and including -/// the first null byte. -/// -/// # Panics -/// -/// This function will panic if the string pointed to by `s` is not valid UTF-8. -#[unstable(feature = "core")] -#[deprecated(since = "1.0.0", - reason = "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 = 0; - while *s.offset(len as isize) != 0 { - len += 1; - } - let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len }); - from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data") -} - -/// Something that can be used to compare against a character -#[unstable(feature = "core", - reason = "definition may change as pattern-related methods are stabilized")] -pub trait CharEq { - /// Determine if the splitter should split at the given character - fn matches(&mut self, char) -> bool; - /// Indicate if this is only concerned about ASCII characters, - /// which can allow for a faster implementation. - fn only_ascii(&self) -> bool; -} - -impl CharEq for char { - #[inline] - fn matches(&mut self, c: char) -> bool { *self == c } - - #[inline] - fn only_ascii(&self) -> bool { (*self as u32) < 128 } -} - -impl CharEq for F where F: FnMut(char) -> bool { - #[inline] - fn matches(&mut self, c: char) -> bool { (*self)(c) } - - #[inline] - fn only_ascii(&self) -> bool { false } -} - -impl<'a> CharEq for &'a [char] { - #[inline] - fn matches(&mut self, c: char) -> bool { - self.iter().any(|&m| { let mut m = m; m.matches(c) }) - } - - #[inline] - fn only_ascii(&self) -> bool { - self.iter().all(|m| m.only_ascii()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for Utf8Error { - fn description(&self) -> &str { - match *self { - Utf8Error::TooShort => "invalid utf-8: not enough bytes", - Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Utf8Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -310,21 +262,20 @@ pub struct Chars<'a> { iter: slice::Iter<'a, u8> } -// Return the initial codepoint accumulator for the first byte. -// The first byte is special, only want bottom 5 bits for width 2, 4 bits -// for width 3, and 3 bits for width 4 -macro_rules! utf8_first_byte { - ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32) -} +/// Return the initial codepoint accumulator for the first byte. +/// The first byte is special, only want bottom 5 bits for width 2, 4 bits +/// for width 3, and 3 bits for width 4. +#[inline] +fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 } -// return the value of $ch updated with continuation byte $byte -macro_rules! utf8_acc_cont_byte { - ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & CONT_MASK) as u32) -} +/// Return the value of `ch` updated with continuation byte `byte`. +#[inline] +fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 } -macro_rules! utf8_is_cont_byte { - ($byte:expr) => (($byte & !CONT_MASK) == TAG_CONT_U8) -} +/// Checks whether the byte is a UTF-8 continuation byte (i.e. starts with the +/// bits `10`). +#[inline] +fn utf8_is_cont_byte(byte: u8) -> bool { (byte & !CONT_MASK) == TAG_CONT_U8 } #[inline] fn unwrap_or_0(opt: Option<&u8>) -> u8 { @@ -337,6 +288,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 { /// Reads the next code point out of a byte iterator (assuming a /// UTF-8-like encoding). #[unstable(feature = "core")] +#[inline] pub fn next_code_point(bytes: &mut slice::Iter) -> Option { // Decode UTF-8 let x = match bytes.next() { @@ -348,26 +300,58 @@ pub fn next_code_point(bytes: &mut slice::Iter) -> Option { // Multibyte case follows // Decode from a byte combination out of: [[[x y] z] w] // NOTE: Performance is sensitive to the exact formulation here - let init = utf8_first_byte!(x, 2); + let init = utf8_first_byte(x, 2); let y = unwrap_or_0(bytes.next()); - let mut ch = utf8_acc_cont_byte!(init, y); + let mut ch = utf8_acc_cont_byte(init, y); if x >= 0xE0 { // [[x y z] w] case // 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid let z = unwrap_or_0(bytes.next()); - let y_z = utf8_acc_cont_byte!((y & CONT_MASK) as u32, z); + let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z); ch = init << 12 | y_z; if x >= 0xF0 { // [x y z w] case // use only the lower 3 bits of `init` let w = unwrap_or_0(bytes.next()); - ch = (init & 7) << 18 | utf8_acc_cont_byte!(y_z, w); + ch = (init & 7) << 18 | utf8_acc_cont_byte(y_z, w); } } Some(ch) } +/// Reads the last code point out of a byte iterator (assuming a +/// UTF-8-like encoding). +#[unstable(feature = "core")] +#[inline] +pub fn next_code_point_reverse(bytes: &mut slice::Iter) -> Option { + // Decode UTF-8 + let w = match bytes.next_back() { + None => return None, + Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32), + Some(&back_byte) => back_byte, + }; + + // Multibyte case follows + // Decode from a byte combination out of: [x [y [z w]]] + let mut ch; + let z = unwrap_or_0(bytes.next_back()); + ch = utf8_first_byte(z, 2); + if utf8_is_cont_byte(z) { + let y = unwrap_or_0(bytes.next_back()); + ch = utf8_first_byte(y, 3); + if utf8_is_cont_byte(y) { + let x = unwrap_or_0(bytes.next_back()); + ch = utf8_first_byte(x, 4); + ch = utf8_acc_cont_byte(ch, y); + } + ch = utf8_acc_cont_byte(ch, z); + } + ch = utf8_acc_cont_byte(ch, w); + + Some(ch) +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Chars<'a> { type Item = char; @@ -385,7 +369,10 @@ impl<'a> Iterator for Chars<'a> { #[inline] fn size_hint(&self) -> (usize, Option) { let (len, _) = self.iter.size_hint(); - (len.saturating_add(3) / 4, Some(len)) + // `(len + 3)` can't overflow, because we know that the `slice::Iter` + // belongs to a slice in memory which has a maximum length of + // `isize::MAX` (that's well below `usize::MAX`). + ((len + 3) / 4, Some(len)) } } @@ -393,33 +380,12 @@ impl<'a> Iterator for Chars<'a> { impl<'a> DoubleEndedIterator for Chars<'a> { #[inline] fn next_back(&mut self) -> Option { - let w = match self.iter.next_back() { - None => return None, - Some(&back_byte) if back_byte < 128 => return Some(back_byte as char), - Some(&back_byte) => back_byte, - }; - - // Multibyte case follows - // Decode from a byte combination out of: [x [y [z w]]] - let mut ch; - let z = unwrap_or_0(self.iter.next_back()); - ch = utf8_first_byte!(z, 2); - if utf8_is_cont_byte!(z) { - let y = unwrap_or_0(self.iter.next_back()); - ch = utf8_first_byte!(y, 3); - if utf8_is_cont_byte!(y) { - let x = unwrap_or_0(self.iter.next_back()); - ch = utf8_first_byte!(x, 4); - ch = utf8_acc_cont_byte!(ch, y); + next_code_point_reverse(&mut self.iter).map(|ch| { + // str invariant says `ch` is a valid Unicode Scalar Value + unsafe { + mem::transmute(ch) } - ch = utf8_acc_cont_byte!(ch, z); - } - ch = utf8_acc_cont_byte!(ch, w); - - // str invariant says `ch` is a valid Unicode Scalar Value - unsafe { - Some(mem::transmute(ch)) - } + }) } } @@ -474,7 +440,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> { /// External iterator for a string's bytes. /// Use with the `std::iter` module. /// -/// Created with `StrExt::bytes` +/// Created with `str::bytes` #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct Bytes<'a>(Map, BytesDeref>); @@ -486,34 +452,65 @@ delegate_iter!{exact u8 : Bytes<'a>} struct BytesDeref; impl<'a> Fn<(&'a u8,)> for BytesDeref { - type Output = u8; - #[inline] extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 { *ptr } } +impl<'a> FnMut<(&'a u8,)> for BytesDeref { + #[inline] + extern "rust-call" fn call_mut(&mut self, (ptr,): (&'a u8,)) -> u8 { + Fn::call(&*self, (ptr,)) + } +} + +impl<'a> FnOnce<(&'a u8,)> for BytesDeref { + type Output = u8; + + #[inline] + extern "rust-call" fn call_once(self, (ptr,): (&'a u8,)) -> u8 { + Fn::call(&self, (ptr,)) + } +} + /// An iterator over the substrings of a string, separated by `sep`. -#[derive(Clone)] -struct CharSplits<'a, Sep> { +struct CharSplits<'a, P: Pattern<'a>> { /// The slice remaining to be iterated - string: &'a str, - sep: Sep, + start: usize, + end: usize, + matcher: P::Searcher, /// Whether an empty string at the end is allowed allow_trailing_empty: bool, - only_ascii: bool, finished: bool, } /// An iterator over the substrings of a string, separated by `sep`, /// splitting at most `count` times. -#[derive(Clone)] -struct CharSplitsN<'a, Sep> { - iter: CharSplits<'a, Sep>, +struct CharSplitsN<'a, P: Pattern<'a>> { + iter: CharSplits<'a, P>, + /// The number of items remaining + count: usize, +} + +/// An iterator over the substrings of a string, separated by a +/// pattern, in reverse order. +struct RCharSplits<'a, P: Pattern<'a>> { + /// The slice remaining to be iterated + start: usize, + end: usize, + matcher: P::Searcher, + /// Whether an empty string at the end of iteration is allowed + allow_final_empty: bool, + finished: bool, +} + +/// An iterator over the substrings of a string, separated by a +/// pattern, splitting at most `count` times, in reverse order. +struct RCharSplitsN<'a, P: Pattern<'a>> { + iter: RCharSplits<'a, P>, /// The number of splits remaining count: usize, - invert: bool, } /// An iterator over the lines of a string, separated by `\n`. @@ -528,12 +525,15 @@ pub struct LinesAny<'a> { inner: Map, fn(&str) -> &str>, } -impl<'a, Sep> CharSplits<'a, Sep> { +impl<'a, P: Pattern<'a>> CharSplits<'a, P> { #[inline] fn get_end(&mut self) -> Option<&'a str> { - if !self.finished && (self.allow_trailing_empty || self.string.len() > 0) { + if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) { self.finished = true; - Some(self.string) + unsafe { + let string = self.matcher.haystack().slice_unchecked(self.start, self.end); + Some(string) + } } else { None } @@ -541,33 +541,18 @@ impl<'a, Sep> CharSplits<'a, Sep> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> { +impl<'a, P: Pattern<'a>> Iterator for CharSplits<'a, P> { type Item = &'a str; #[inline] fn next(&mut self) -> Option<&'a str> { if self.finished { return None } - let mut next_split = None; - if self.only_ascii { - for (idx, byte) in self.string.bytes().enumerate() { - if self.sep.matches(byte as char) && byte < 128u8 { - next_split = Some((idx, idx + 1)); - break; - } - } - } else { - for (idx, ch) in self.string.char_indices() { - if self.sep.matches(ch) { - next_split = Some((idx, self.string.char_range_at(idx).next)); - break; - } - } - } - match next_split { + let haystack = self.matcher.haystack(); + match self.matcher.next_match() { Some((a, b)) => unsafe { - let elt = self.string.slice_unchecked(0, a); - self.string = self.string.slice_unchecked(b, self.string.len()); + let elt = haystack.slice_unchecked(self.start, a); + self.start = b; Some(elt) }, None => self.get_end(), @@ -576,7 +561,8 @@ impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> { +impl<'a, P: Pattern<'a>> DoubleEndedIterator for CharSplits<'a, P> +where P::Searcher: DoubleEndedSearcher<'a> { #[inline] fn next_back(&mut self) -> Option<&'a str> { if self.finished { return None } @@ -588,73 +574,86 @@ impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> { _ => if self.finished { return None } } } - let len = self.string.len(); - let mut next_split = None; - - if self.only_ascii { - for (idx, byte) in self.string.bytes().enumerate().rev() { - if self.sep.matches(byte as char) && byte < 128u8 { - next_split = Some((idx, idx + 1)); - break; - } - } - } else { - for (idx, ch) in self.string.char_indices().rev() { - if self.sep.matches(ch) { - next_split = Some((idx, self.string.char_range_at(idx).next)); - break; - } - } - } - match next_split { + + let haystack = self.matcher.haystack(); + match self.matcher.next_match_back() { Some((a, b)) => unsafe { - let elt = self.string.slice_unchecked(b, len); - self.string = self.string.slice_unchecked(0, a); + let elt = haystack.slice_unchecked(b, self.end); + self.end = a; Some(elt) }, - None => { self.finished = true; Some(self.string) } + None => unsafe { + self.finished = true; + Some(haystack.slice_unchecked(self.start, self.end)) + }, } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> { +impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P> { type Item = &'a str; #[inline] fn next(&mut self) -> Option<&'a str> { - if self.count != 0 { - self.count -= 1; - if self.invert { self.iter.next_back() } else { self.iter.next() } - } else { - self.iter.get_end() + match self.count { + 0 => None, + 1 => { self.count = 0; self.iter.get_end() } + _ => { self.count -= 1; self.iter.next() } } } } -/// The internal state of an iterator that searches for matches of a substring -/// within a larger string using naive search -#[derive(Clone)] -struct NaiveSearcher { - position: usize +impl<'a, P: Pattern<'a>> RCharSplits<'a, P> { + #[inline] + fn get_remainder(&mut self) -> Option<&'a str> { + if !self.finished && (self.allow_final_empty || self.end - self.start > 0) { + self.finished = true; + unsafe { + let string = self.matcher.haystack().slice_unchecked(self.start, self.end); + Some(string) + } + } else { + None + } + } } -impl NaiveSearcher { - fn new() -> NaiveSearcher { - NaiveSearcher { position: 0 } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, P: Pattern<'a>> Iterator for RCharSplits<'a, P> + where P::Searcher: ReverseSearcher<'a> +{ + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + if self.finished { return None } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match_back() { + Some((a, b)) => unsafe { + let elt = haystack.slice_unchecked(b, self.end); + self.end = a; + Some(elt) + }, + None => self.get_remainder(), + } } +} - fn next(&mut self, haystack: &[u8], needle: &[u8]) -> Option<(usize, usize)> { - while self.position + needle.len() <= haystack.len() { - if &haystack[self.position .. self.position + needle.len()] == needle { - let match_pos = self.position; - self.position += needle.len(); // add 1 for all matches - return Some((match_pos, match_pos + needle.len())); - } else { - self.position += 1; - } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, P: Pattern<'a>> Iterator for RCharSplitsN<'a, P> + where P::Searcher: ReverseSearcher<'a> +{ + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + match self.count { + 0 => None, + 1 => { self.count -= 1; self.iter.get_remainder() } + _ => { self.count -= 1; self.iter.next() } } - None } } @@ -743,6 +742,7 @@ struct TwoWaySearcher { */ impl TwoWaySearcher { + #[allow(dead_code)] fn new(needle: &[u8]) -> TwoWaySearcher { let (crit_pos_false, period_false) = TwoWaySearcher::maximal_suffix(needle, false); let (crit_pos_true, period_true) = TwoWaySearcher::maximal_suffix(needle, true); @@ -852,8 +852,10 @@ impl TwoWaySearcher { // Specifically, returns (i, p), where i is the starting index of v in some // critical factorization (u, v) and p = period(v) #[inline] + #[allow(dead_code)] + #[allow(deprecated)] fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) { - let mut left = -1; // Corresponds to i in the paper + let mut left: usize = !0; // Corresponds to i in the paper let mut right = 0; // Corresponds to j in the paper let mut offset = 1; // Corresponds to k in the paper let mut period = 1; // Corresponds to p in the paper @@ -862,17 +864,17 @@ impl TwoWaySearcher { let a; let b; if reversed { - a = arr[left + offset]; + a = arr[left.wrapping_add(offset)]; b = arr[right + offset]; } else { a = arr[right + offset]; - b = arr[left + offset]; + b = arr[left.wrapping_add(offset)]; } if a < b { // Suffix is smaller, period is entire prefix so far. right += offset; offset = 1; - period = right - left; + period = right.wrapping_sub(left); } else if a == b { // Advance through repetition of the current period. if offset == period { @@ -889,27 +891,33 @@ impl TwoWaySearcher { period = 1; } } - (left + 1, period) + (left.wrapping_add(1), period) } } /// The internal state of an iterator that searches for matches of a substring /// within a larger string using a dynamically chosen search algorithm #[derive(Clone)] -enum Searcher { - Naive(NaiveSearcher), +// NB: This is kept around for convenience because +// it is planned to be used again in the future +enum OldSearcher { TwoWay(TwoWaySearcher), - TwoWayLong(TwoWaySearcher) + TwoWayLong(TwoWaySearcher), } -impl Searcher { - fn new(haystack: &[u8], needle: &[u8]) -> Searcher { +impl OldSearcher { + #[allow(dead_code)] + fn new(haystack: &[u8], needle: &[u8]) -> OldSearcher { + if needle.len() == 0 { + // Handle specially + unimplemented!() // FIXME: Tune this. // FIXME(#16715): This unsigned integer addition will probably not // overflow because that would mean that the memory almost solely // consists of the needle. Needs #16715 to be formally fixed. - if needle.len() + 20 > haystack.len() { - Naive(NaiveSearcher::new()) + } else if needle.len() + 20 > haystack.len() { + // Use naive searcher + unimplemented!() } else { let searcher = TwoWaySearcher::new(needle); if searcher.memory == usize::MAX { // If the period is long @@ -921,67 +929,45 @@ impl Searcher { } } -/// An iterator over the start and end indices of the matches of a -/// substring within a larger string #[derive(Clone)] -#[unstable(feature = "core", reason = "type may be removed")] -pub struct MatchIndices<'a> { +// NB: This is kept around for convenience because +// it is planned to be used again in the future +struct OldMatchIndices<'a, 'b> { // constants haystack: &'a str, - needle: &'a str, - searcher: Searcher + needle: &'b str, + searcher: OldSearcher } -/// An iterator over the substrings of a string separated by a given -/// search string -#[derive(Clone)] +// FIXME: #21637 Prevents a Clone impl +/// An iterator over the start and end indices of the matches of a +/// substring within a larger string #[unstable(feature = "core", reason = "type may be removed")] -pub struct SplitStr<'a> { - it: MatchIndices<'a>, - last_end: usize, - finished: bool -} +pub struct MatchIndices<'a, P: Pattern<'a>>(P::Searcher); #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Iterator for MatchIndices<'a> { +impl<'a, P: Pattern<'a>> Iterator for MatchIndices<'a, P> { type Item = (usize, usize); #[inline] fn next(&mut self) -> Option<(usize, usize)> { - match self.searcher { - Naive(ref mut searcher) - => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes()), - TwoWay(ref mut searcher) - => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), false), - TwoWayLong(ref mut searcher) - => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), true) - } + self.0.next_match() } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Iterator for SplitStr<'a> { - type Item = &'a str; - +impl<'a, 'b> OldMatchIndices<'a, 'b> { #[inline] - fn next(&mut self) -> Option<&'a str> { - if self.finished { return None; } - - match self.it.next() { - Some((from, to)) => { - let ret = Some(&self.it.haystack[self.last_end .. from]); - self.last_end = to; - ret - } - None => { - self.finished = true; - Some(&self.it.haystack[self.last_end .. self.it.haystack.len()]) - } + #[allow(dead_code)] + fn next(&mut self) -> Option<(usize, usize)> { + match self.searcher { + TwoWay(ref mut searcher) + => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), false), + TwoWayLong(ref mut searcher) + => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), true), } } } - /* Section: Comparing strings */ @@ -1051,7 +1037,7 @@ fn run_utf8_validation_iterator(iter: &mut slice::Iter) // ASCII characters are always valid, so only large // bytes need more examination. if first >= 128 { - let w = UTF8_CHAR_WIDTH[first as usize] as usize; + let w = UTF8_CHAR_WIDTH[first as usize]; let second = next!(); // 2-byte encoding is for codepoints \u{0080} to \u{07ff} // first C2 80 last DF BF @@ -1119,9 +1105,11 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [ /// Struct that contains a `char` and the index of the first byte of /// the next `char` in a string. This can be used as a data structure /// for iterating over the UTF-8 bytes of a string. -#[derive(Copy)] -#[unstable(feature = "core", - reason = "naming is uncertain with container conventions")] +#[derive(Copy, Clone)] +#[unstable(feature = "str_char", + reason = "existence of this struct is uncertain as it is frequently \ + able to be replaced with char.len_utf8() and/or \ + char/char_indices iterators")] pub struct CharRange { /// Current `char` pub ch: char, @@ -1130,9 +1118,9 @@ pub struct CharRange { } /// Mask of the value bits of a continuation byte -const CONT_MASK: u8 = 0b0011_1111u8; +const CONT_MASK: u8 = 0b0011_1111; /// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte -const TAG_CONT_U8: u8 = 0b1000_0000u8; +const TAG_CONT_U8: u8 = 0b1000_0000; /* Section: Trait implementations @@ -1141,7 +1129,7 @@ Section: Trait implementations mod traits { use cmp::{Ordering, Ord, PartialEq, PartialOrd, Eq}; use cmp::Ordering::{Less, Equal, Greater}; - use iter::IteratorExt; + use iter::Iterator; use option::Option; use option::Option::Some; use ops; @@ -1192,9 +1180,9 @@ mod traits { /// Panics when `begin` and `end` do not point to valid characters /// or point beyond the last character of the string. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let s = "Löwe 老虎 Léopard"; /// assert_eq!(&s[0 .. 1], "L"); /// @@ -1214,7 +1202,7 @@ mod traits { impl ops::Index> for str { type Output = str; #[inline] - fn index(&self, index: &ops::Range) -> &str { + fn index(&self, index: ops::Range) -> &str { // is_char_boundary checks that the index is in [0, .len()] if index.start <= index.end && self.is_char_boundary(index.start) && @@ -1236,8 +1224,9 @@ mod traits { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for str { type Output = str; + #[inline] - fn index(&self, index: &ops::RangeTo) -> &str { + fn index(&self, index: ops::RangeTo) -> &str { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(index.end) { unsafe { self.slice_unchecked(0, index.end) } @@ -1256,8 +1245,9 @@ mod traits { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index> for str { type Output = str; + #[inline] - fn index(&self, index: &ops::RangeFrom) -> &str { + fn index(&self, index: ops::RangeFrom) -> &str { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(index.start) { unsafe { self.slice_unchecked(index.start, self.len()) } @@ -1270,8 +1260,9 @@ mod traits { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for str { type Output = str; + #[inline] - fn index(&self, _index: &ops::RangeFull) -> &str { + fn index(&self, _index: ops::RangeFull) -> &str { self } } @@ -1282,45 +1273,49 @@ mod traits { reason = "Instead of taking this bound generically, this trait will be \ replaced with one of slicing syntax (&foo[..]), deref coercions, or \ a more generic conversion trait")] +#[deprecated(since = "1.0.0", + reason = "use std::convert::AsRef instead")] pub trait Str { /// Work with `self` as a slice. fn as_slice<'a>(&'a self) -> &'a str; } +#[allow(deprecated)] impl Str for str { #[inline] fn as_slice<'a>(&'a self) -> &'a str { self } } +#[allow(deprecated)] impl<'a, S: ?Sized> Str for &'a S where S: Str { #[inline] fn as_slice(&self) -> &str { Str::as_slice(*self) } } -/// Return type of `StrExt::split` -#[derive(Clone)] +/// Return type of `str::split` #[stable(feature = "rust1", since = "1.0.0")] -pub struct Split<'a, P>(CharSplits<'a, P>); +pub struct Split<'a, P: Pattern<'a>>(CharSplits<'a, P>); delegate_iter!{pattern &'a str : Split<'a, P>} -/// Return type of `StrExt::split_terminator` -#[derive(Clone)] -#[unstable(feature = "core", - reason = "might get removed in favour of a constructor method on Split")] -pub struct SplitTerminator<'a, P>(CharSplits<'a, P>); +/// Return type of `str::split_terminator` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SplitTerminator<'a, P: Pattern<'a>>(CharSplits<'a, P>); delegate_iter!{pattern &'a str : SplitTerminator<'a, P>} -/// Return type of `StrExt::splitn` -#[derive(Clone)] +/// Return type of `str::splitn` #[stable(feature = "rust1", since = "1.0.0")] -pub struct SplitN<'a, P>(CharSplitsN<'a, P>); +pub struct SplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>); delegate_iter!{pattern forward &'a str : SplitN<'a, P>} -/// Return type of `StrExt::rsplitn` -#[derive(Clone)] +/// Return type of `str::rsplit` #[stable(feature = "rust1", since = "1.0.0")] -pub struct RSplitN<'a, P>(CharSplitsN<'a, P>); -delegate_iter!{pattern forward &'a str : RSplitN<'a, P>} +pub struct RSplit<'a, P: Pattern<'a>>(RCharSplits<'a, P>); +delegate_iter!{pattern reverse &'a str : RSplit<'a, P>} + +/// Return type of `str::rsplitn` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct RSplitN<'a, P: Pattern<'a>>(RCharSplitsN<'a, P>); +delegate_iter!{pattern reverse &'a str : RSplitN<'a, P>} /// Methods for string slices #[allow(missing_docs)] @@ -1328,36 +1323,42 @@ pub trait StrExt { // NB there are no docs here are they're all located on the StrExt trait in // libcollections, not here. - fn contains(&self, pat: &str) -> bool; - fn contains_char(&self, pat: P) -> bool; + fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool; + fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool; fn chars<'a>(&'a self) -> Chars<'a>; fn bytes<'a>(&'a self) -> Bytes<'a>; fn char_indices<'a>(&'a self) -> CharIndices<'a>; - fn split<'a, P: CharEq>(&'a self, pat: P) -> Split<'a, P>; - fn splitn<'a, P: CharEq>(&'a self, count: usize, pat: P) -> SplitN<'a, P>; - fn split_terminator<'a, P: CharEq>(&'a self, pat: P) -> SplitTerminator<'a, P>; - fn rsplitn<'a, P: CharEq>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>; - fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a>; - fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a>; + fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P>; + fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P>; + fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P>; + fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a>; + fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> + where P::Searcher: ReverseSearcher<'a>; + fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P>; fn lines<'a>(&'a self) -> Lines<'a>; fn lines_any<'a>(&'a self) -> LinesAny<'a>; fn char_len(&self) -> usize; fn slice_chars<'a>(&'a self, begin: usize, end: usize) -> &'a str; unsafe fn slice_unchecked<'a>(&'a self, begin: usize, end: usize) -> &'a str; - fn starts_with(&self, pat: &str) -> bool; - fn ends_with(&self, pat: &str) -> bool; - fn trim_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str; - fn trim_left_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str; - fn trim_right_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str; + fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool; + fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a>; + fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a>; + fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str; + fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a>; fn is_char_boundary(&self, index: usize) -> bool; fn char_range_at(&self, start: usize) -> CharRange; fn char_range_at_reverse(&self, start: usize) -> CharRange; fn char_at(&self, i: usize) -> char; fn char_at_reverse(&self, i: usize) -> char; fn as_bytes<'a>(&'a self) -> &'a [u8]; - fn find(&self, pat: P) -> Option; - fn rfind(&self, pat: P) -> Option; - fn find_str(&self, pat: &str) -> Option; + fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option; + fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option + where P::Searcher: ReverseSearcher<'a>; + fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option; fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>; fn subslice_offset(&self, inner: &str) -> usize; fn as_ptr(&self) -> *const u8; @@ -1375,13 +1376,13 @@ fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! { impl StrExt for str { #[inline] - fn contains(&self, needle: &str) -> bool { - self.find_str(needle).is_some() + fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + pat.is_contained_in(self) } #[inline] - fn contains_char(&self, pat: P) -> bool { - self.find(pat).is_some() + fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + pat.is_contained_in(self) } #[inline] @@ -1400,27 +1401,26 @@ impl StrExt for str { } #[inline] - fn split(&self, pat: P) -> Split

{ + fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { Split(CharSplits { - string: self, - only_ascii: pat.only_ascii(), - sep: pat, + start: 0, + end: self.len(), + matcher: pat.into_searcher(self), allow_trailing_empty: true, finished: false, }) } #[inline] - fn splitn(&self, count: usize, pat: P) -> SplitN

{ + fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { SplitN(CharSplitsN { iter: self.split(pat).0, count: count, - invert: false, }) } #[inline] - fn split_terminator(&self, pat: P) -> SplitTerminator

{ + fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> { SplitTerminator(CharSplits { allow_trailing_empty: false, ..self.split(pat).0 @@ -1428,31 +1428,31 @@ impl StrExt for str { } #[inline] - fn rsplitn(&self, count: usize, pat: P) -> RSplitN

{ - RSplitN(CharSplitsN { - iter: self.split(pat).0, - count: count, - invert: true, + fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + RSplit(RCharSplits { + start: 0, + end: self.len(), + matcher: pat.into_searcher(self), + allow_final_empty: true, + finished: false, }) } #[inline] - fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a> { - assert!(!sep.is_empty()); - MatchIndices { - haystack: self, - needle: sep, - searcher: Searcher::new(self.as_bytes(), sep.as_bytes()) - } + fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> + where P::Searcher: ReverseSearcher<'a> + { + RSplitN(RCharSplitsN { + iter: self.rsplit(pat).0, + count: count, + }) } #[inline] - fn split_str<'a>(&'a self, sep: &'a str) -> SplitStr<'a> { - SplitStr { - it: self.match_indices(sep), - last_end: 0, - finished: false - } + fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { + MatchIndices(pat.into_searcher(self)) } #[inline] @@ -1506,48 +1506,63 @@ impl StrExt for str { } #[inline] - fn starts_with(&self, needle: &str) -> bool { - let n = needle.len(); - self.len() >= n && needle.as_bytes() == &self.as_bytes()[..n] + fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool { + pat.is_prefix_of(self) } #[inline] - fn ends_with(&self, needle: &str) -> bool { - let (m, n) = (self.len(), needle.len()); - m >= n && needle.as_bytes() == &self.as_bytes()[m-n..] + fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool + where P::Searcher: ReverseSearcher<'a> + { + pat.is_suffix_of(self) } #[inline] - fn trim_matches(&self, mut pat: P) -> &str { - let cur = match self.find(|c: char| !pat.matches(c)) { - None => "", - Some(i) => unsafe { self.slice_unchecked(i, self.len()) } - }; - match cur.rfind(|c: char| !pat.matches(c)) { - None => "", - Some(i) => { - let right = cur.char_range_at(i).next; - unsafe { cur.slice_unchecked(0, right) } - } + fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: DoubleEndedSearcher<'a> + { + let mut i = 0; + let mut j = 0; + let mut matcher = pat.into_searcher(self); + if let Some((a, b)) = matcher.next_reject() { + i = a; + j = b; // Rember earliest known match, correct it below if + // last match is different + } + if let Some((_, b)) = matcher.next_reject_back() { + j = b; + } + unsafe { + // Searcher is known to return valid indices + self.slice_unchecked(i, j) } } #[inline] - fn trim_left_matches(&self, mut pat: P) -> &str { - match self.find(|c: char| !pat.matches(c)) { - None => "", - Some(first) => unsafe { self.slice_unchecked(first, self.len()) } + fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str { + let mut i = self.len(); + let mut matcher = pat.into_searcher(self); + if let Some((a, _)) = matcher.next_reject() { + i = a; + } + unsafe { + // Searcher is known to return valid indices + self.slice_unchecked(i, self.len()) } } #[inline] - fn trim_right_matches(&self, mut pat: P) -> &str { - match self.rfind(|c: char| !pat.matches(c)) { - None => "", - Some(last) => { - let next = self.char_range_at(last).next; - unsafe { self.slice_unchecked(0, next) } - } + fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str + where P::Searcher: ReverseSearcher<'a> + { + let mut j = 0; + let mut matcher = pat.into_searcher(self); + if let Some((_, b)) = matcher.next_reject_back() { + j = b; + } + unsafe { + // Searcher is known to return valid indices + self.slice_unchecked(0, j) } } @@ -1556,7 +1571,7 @@ impl StrExt for str { if index == self.len() { return true; } match self.as_bytes().get(index) { None => false, - Some(&b) => b < 128u8 || b >= 192u8, + Some(&b) => b < 128 || b >= 192, } } @@ -1582,14 +1597,14 @@ impl StrExt for str { i -= 1; } - let mut val = s.as_bytes()[i] as u32; - let w = UTF8_CHAR_WIDTH[val as usize] as usize; - assert!((w != 0)); + let first= s.as_bytes()[i]; + let w = UTF8_CHAR_WIDTH[first as usize]; + assert!(w != 0); - val = utf8_first_byte!(val, w); - val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]); - if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); } - if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); } + let mut val = utf8_first_byte(first, w as u32); + val = utf8_acc_cont_byte(val, s.as_bytes()[i + 1]); + if w > 2 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 2]); } + if w > 3 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 3]); } return CharRange {ch: unsafe { mem::transmute(val) }, next: i}; } @@ -1612,36 +1627,18 @@ impl StrExt for str { unsafe { mem::transmute(self) } } - fn find(&self, mut pat: P) -> Option { - if pat.only_ascii() { - self.bytes().position(|b| pat.matches(b as char)) - } else { - for (index, c) in self.char_indices() { - if pat.matches(c) { return Some(index); } - } - None - } + fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { + pat.into_searcher(self).next_match().map(|(i, _)| i) } - fn rfind(&self, mut pat: P) -> Option { - if pat.only_ascii() { - self.bytes().rposition(|b| pat.matches(b as char)) - } else { - for (index, c) in self.char_indices().rev() { - if pat.matches(c) { return Some(index); } - } - None - } + fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option + where P::Searcher: ReverseSearcher<'a> + { + pat.into_searcher(self).next_match_back().map(|(i, _)| i) } - fn find_str(&self, needle: &str) -> Option { - if needle.is_empty() { - Some(0) - } else { - self.match_indices(needle) - .next() - .map(|(start, _end)| start) - } + fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option { + self.find(pat) } #[inline] @@ -1649,8 +1646,8 @@ impl StrExt for str { if self.is_empty() { None } else { - let CharRange {ch, next} = self.char_range_at(0); - let next_s = unsafe { self.slice_unchecked(next, self.len()) }; + let ch = self.char_at(0); + let next_s = unsafe { self.slice_unchecked(ch.len_utf8(), self.len()) }; Some((ch, next_s)) } } @@ -1686,22 +1683,22 @@ impl StrExt for str { #[inline] #[unstable(feature = "core")] pub fn char_range_at_raw(bytes: &[u8], i: usize) -> (u32, usize) { - if bytes[i] < 128u8 { + if bytes[i] < 128 { return (bytes[i] as u32, i + 1); } // Multibyte case is a fn to allow char_range_at to inline cleanly fn multibyte_char_range_at(bytes: &[u8], i: usize) -> (u32, usize) { - let mut val = bytes[i] as u32; - let w = UTF8_CHAR_WIDTH[val as usize] as usize; - assert!((w != 0)); + let first = bytes[i]; + let w = UTF8_CHAR_WIDTH[first as usize]; + assert!(w != 0); - val = utf8_first_byte!(val, w); - val = utf8_acc_cont_byte!(val, bytes[i + 1]); - if w > 2 { val = utf8_acc_cont_byte!(val, bytes[i + 2]); } - if w > 3 { val = utf8_acc_cont_byte!(val, bytes[i + 3]); } + let mut val = utf8_first_byte(first, w as u32); + val = utf8_acc_cont_byte(val, bytes[i + 1]); + if w > 2 { val = utf8_acc_cont_byte(val, bytes[i + 2]); } + if w > 3 { val = utf8_acc_cont_byte(val, bytes[i + 3]); } - return (val, i + w); + return (val, i + w as usize); } multibyte_char_range_at(bytes, i) diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs new file mode 100644 index 0000000000..922ab2c14a --- /dev/null +++ b/src/libcore/str/pattern.rs @@ -0,0 +1,571 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; + +// Pattern + +/// A string pattern. +/// +/// A `Pattern<'a>` expresses that the implementing type +/// can be used as a string pattern for searching in a `&'a str`. +/// +/// For example, both `'a'` and `"aa"` are patterns that +/// would match at index `1` in the string `"baaaab"`. +/// +/// The trait itself acts as a builder for an associated +/// `Searcher` type, which does the actual work of finding +/// occurrences of the pattern in a string. +pub trait Pattern<'a>: Sized { + /// Associated searcher for this pattern + type Searcher: Searcher<'a>; + + /// Construct the associated searcher from + /// `self` and the `haystack` to search in. + fn into_searcher(self, haystack: &'a str) -> Self::Searcher; + + /// Check whether the pattern matches anywhere in the haystack + #[inline] + fn is_contained_in(self, haystack: &'a str) -> bool { + self.into_searcher(haystack).next_match().is_some() + } + + /// Check whether the pattern matches at the front of the haystack + #[inline] + fn is_prefix_of(self, haystack: &'a str) -> bool { + match self.into_searcher(haystack).next() { + SearchStep::Match(0, _) => true, + _ => false, + } + } + + /// Check whether the pattern matches at the back of the haystack + #[inline] + fn is_suffix_of(self, haystack: &'a str) -> bool + where Self::Searcher: ReverseSearcher<'a> + { + match self.into_searcher(haystack).next_back() { + SearchStep::Match(_, j) if haystack.len() == j => true, + _ => false, + } + } +} + +// Searcher + +/// Result of calling `Searcher::next()` or `ReverseSearcher::next_back()`. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum SearchStep { + /// Expresses that a match of the pattern has been found at + /// `haystack[a..b]`. + Match(usize, usize), + /// Expresses that `haystack[a..b]` has been rejected as a possible match + /// of the pattern. + /// + /// Note that there might be more than one `Reject` between two `Match`es, + /// there is no requirement for them to be combined into one. + Reject(usize, usize), + /// Expresses that every byte of the haystack has been visted, ending + /// the iteration. + Done +} + +/// A searcher for a string pattern. +/// +/// This trait provides methods for searching for non-overlapping +/// matches of a pattern starting from the front (left) of a string. +/// +/// It will be implemented by associated `Searcher` +/// types of the `Pattern` trait. +/// +/// The trait is marked unsafe because the indices returned by the +/// `next()` methods are required to lie on valid utf8 boundaries in +/// the haystack. This enables consumers of this trait to +/// slice the haystack without additional runtime checks. +pub unsafe trait Searcher<'a> { + /// Getter for the underlaying string to be searched in + /// + /// Will always return the same `&str` + fn haystack(&self) -> &'a str; + + /// Performs the next search step starting from the front. + /// + /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern. + /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the + /// pattern, even partially. + /// - Returns `Done` if every byte of the haystack has been visited + /// + /// The stream of `Match` and `Reject` values up to a `Done` + /// will contain index ranges that are adjacent, non-overlapping, + /// covering the whole haystack, and laying on utf8 boundaries. + /// + /// A `Match` result needs to contain the whole matched pattern, + /// however `Reject` results may be split up into arbitrary + /// many adjacent fragments. Both ranges may have zero length. + /// + /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"` + /// might produce the stream + /// `[Reject(0, 1), Reject(1, 2), Match(2, 5), Reject(5, 8)]` + fn next(&mut self) -> SearchStep; + + /// Find the next `Match` result. See `next()` + #[inline] + fn next_match(&mut self) -> Option<(usize, usize)> { + loop { + match self.next() { + SearchStep::Match(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } + + /// Find the next `Reject` result. See `next()` + #[inline] + fn next_reject(&mut self) -> Option<(usize, usize)> { + loop { + match self.next() { + SearchStep::Reject(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } +} + +/// A reverse searcher for a string pattern. +/// +/// This trait provides methods for searching for non-overlapping +/// matches of a pattern starting from the back (right) of a string. +/// +/// It will be implemented by associated `Searcher` +/// types of the `Pattern` trait if the pattern supports searching +/// for it from the back. +/// +/// The index ranges returned by this trait are not required +/// to exactly match those of the forward search in reverse. +/// +/// For the reason why this trait is marked unsafe, see them +/// parent trait `Searcher`. +pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { + /// Performs the next search step starting from the back. + /// + /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern. + /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the + /// pattern, even partially. + /// - Returns `Done` if every byte of the haystack has been visited + /// + /// The stream of `Match` and `Reject` values up to a `Done` + /// will contain index ranges that are adjacent, non-overlapping, + /// covering the whole haystack, and laying on utf8 boundaries. + /// + /// A `Match` result needs to contain the whole matched pattern, + /// however `Reject` results may be split up into arbitrary + /// many adjacent fragments. Both ranges may have zero length. + /// + /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"` + /// might produce the stream + /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]` + fn next_back(&mut self) -> SearchStep; + + /// Find the next `Match` result. See `next_back()` + #[inline] + fn next_match_back(&mut self) -> Option<(usize, usize)>{ + loop { + match self.next_back() { + SearchStep::Match(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } + + /// Find the next `Reject` result. See `next_back()` + #[inline] + fn next_reject_back(&mut self) -> Option<(usize, usize)>{ + loop { + match self.next_back() { + SearchStep::Reject(a, b) => return Some((a, b)), + SearchStep::Done => return None, + _ => continue, + } + } + } +} + +/// A marker trait to express that a `ReverseSearcher` +/// can be used for a `DoubleEndedIterator` implementation. +/// +/// For this, the impl of `Searcher` and `ReverseSearcher` need +/// to follow these conditions: +/// +/// - All results of `next()` need to be identical +/// to the results of `next_back()` in reverse order. +/// - `next()` and `next_back()` need to behave as +/// the two ends of a range of values, that is they +/// can not "walk past each other". +/// +/// # Examples +/// +/// `char::Searcher` is a `DoubleEndedSearcher` because searching for a +/// `char` only requires looking at one at a time, which behaves the same +/// from both ends. +/// +/// `(&str)::Searcher` is not a `DoubleEndedSearcher` because +/// the pattern `"aa"` in the haystack `"aaa"` matches as either +/// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched. +pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {} + +// Impl for a CharEq wrapper + +#[doc(hidden)] +trait CharEq { + fn matches(&mut self, char) -> bool; + fn only_ascii(&self) -> bool; +} + +impl CharEq for char { + #[inline] + fn matches(&mut self, c: char) -> bool { *self == c } + + #[inline] + fn only_ascii(&self) -> bool { (*self as u32) < 128 } +} + +impl CharEq for F where F: FnMut(char) -> bool { + #[inline] + fn matches(&mut self, c: char) -> bool { (*self)(c) } + + #[inline] + fn only_ascii(&self) -> bool { false } +} + +impl<'a> CharEq for &'a [char] { + #[inline] + fn matches(&mut self, c: char) -> bool { + self.iter().any(|&m| { let mut m = m; m.matches(c) }) + } + + #[inline] + fn only_ascii(&self) -> bool { + self.iter().all(|m| m.only_ascii()) + } +} + +struct CharEqPattern(C); + +struct CharEqSearcher<'a, C: CharEq> { + char_eq: C, + haystack: &'a str, + char_indices: super::CharIndices<'a>, + #[allow(dead_code)] + ascii_only: bool, +} + +impl<'a, C: CharEq> Pattern<'a> for CharEqPattern { + type Searcher = CharEqSearcher<'a, C>; + + #[inline] + fn into_searcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> { + CharEqSearcher { + ascii_only: self.0.only_ascii(), + haystack: haystack, + char_eq: self.0, + char_indices: haystack.char_indices(), + } + } +} + +unsafe impl<'a, C: CharEq> Searcher<'a> for CharEqSearcher<'a, C> { + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } + + #[inline] + fn next(&mut self) -> SearchStep { + let s = &mut self.char_indices; + // Compare lengths of the internal byte slice iterator + // to find length of current char + let (pre_len, _) = s.iter.iter.size_hint(); + if let Some((i, c)) = s.next() { + let (len, _) = s.iter.iter.size_hint(); + let char_len = pre_len - len; + if self.char_eq.matches(c) { + return SearchStep::Match(i, i + char_len); + } else { + return SearchStep::Reject(i, i + char_len); + } + } + SearchStep::Done + } +} + +unsafe impl<'a, C: CharEq> ReverseSearcher<'a> for CharEqSearcher<'a, C> { + #[inline] + fn next_back(&mut self) -> SearchStep { + let s = &mut self.char_indices; + // Compare lengths of the internal byte slice iterator + // to find length of current char + let (pre_len, _) = s.iter.iter.size_hint(); + if let Some((i, c)) = s.next_back() { + let (len, _) = s.iter.iter.size_hint(); + let char_len = pre_len - len; + if self.char_eq.matches(c) { + return SearchStep::Match(i, i + char_len); + } else { + return SearchStep::Reject(i, i + char_len); + } + } + SearchStep::Done + } +} + +impl<'a, C: CharEq> DoubleEndedSearcher<'a> for CharEqSearcher<'a, C> {} + +// Impl for &str + +// Todo: Optimize the naive implementation here + +#[derive(Clone)] +struct StrSearcher<'a, 'b> { + haystack: &'a str, + needle: &'b str, + start: usize, + end: usize, + done: bool, +} + +/// Non-allocating substring search. +/// +/// Will handle the pattern `""` as returning empty matches at each utf8 +/// boundary. +impl<'a, 'b> Pattern<'a> for &'b str { + type Searcher = StrSearcher<'a, 'b>; + + #[inline] + fn into_searcher(self, haystack: &'a str) -> StrSearcher<'a, 'b> { + StrSearcher { + haystack: haystack, + needle: self, + start: 0, + end: haystack.len(), + done: false, + } + } +} + +unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> { + #[inline] + fn haystack(&self) -> &'a str { + self.haystack + } + + #[inline] + fn next(&mut self) -> SearchStep { + str_search_step(self, + |m: &mut StrSearcher| { + // Forward step for empty needle + let current_start = m.start; + if !m.done { + m.start = m.haystack.char_range_at(current_start).next; + } + SearchStep::Match(current_start, current_start) + }, + |m: &mut StrSearcher| { + // Forward step for nonempty needle + let current_start = m.start; + // Compare byte window because this might break utf8 boundaries + let possible_match = &m.haystack.as_bytes()[m.start .. m.start + m.needle.len()]; + if possible_match == m.needle.as_bytes() { + m.start += m.needle.len(); + SearchStep::Match(current_start, m.start) + } else { + // Skip a char + let haystack_suffix = &m.haystack[m.start..]; + m.start += haystack_suffix.chars().next().unwrap().len_utf8(); + SearchStep::Reject(current_start, m.start) + } + }) + } +} + +unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> { + #[inline] + fn next_back(&mut self) -> SearchStep { + str_search_step(self, + |m: &mut StrSearcher| { + // Backward step for empty needle + let current_end = m.end; + if !m.done { + m.end = m.haystack.char_range_at_reverse(current_end).next; + } + SearchStep::Match(current_end, current_end) + }, + |m: &mut StrSearcher| { + // Backward step for nonempty needle + let current_end = m.end; + // Compare byte window because this might break utf8 boundaries + let possible_match = &m.haystack.as_bytes()[m.end - m.needle.len() .. m.end]; + if possible_match == m.needle.as_bytes() { + m.end -= m.needle.len(); + SearchStep::Match(m.end, current_end) + } else { + // Skip a char + let haystack_prefix = &m.haystack[..m.end]; + m.end -= haystack_prefix.chars().rev().next().unwrap().len_utf8(); + SearchStep::Reject(m.end, current_end) + } + }) + } +} + +// Helper function for encapsulating the common control flow +// of doing a search step from the front or doing a search step from the back +fn str_search_step(mut m: &mut StrSearcher, + empty_needle_step: F, + nonempty_needle_step: G) -> SearchStep + where F: FnOnce(&mut StrSearcher) -> SearchStep, + G: FnOnce(&mut StrSearcher) -> SearchStep +{ + if m.done { + SearchStep::Done + } else if m.needle.len() == 0 && m.start <= m.end { + // Case for needle == "" + if m.start == m.end { + m.done = true; + } + empty_needle_step(&mut m) + } else if m.start + m.needle.len() <= m.end { + // Case for needle != "" + nonempty_needle_step(&mut m) + } else if m.start < m.end { + // Remaining slice shorter than needle, reject it + m.done = true; + SearchStep::Reject(m.start, m.end) + } else { + m.done = true; + SearchStep::Done + } +} + +macro_rules! char_eq_pattern_impl { + ($wrapper:ty, $wrapper_ident:ident) => { + fn into_searcher(self, haystack: &'a str) -> $wrapper { + $wrapper_ident(CharEqPattern(self).into_searcher(haystack)) + } + #[inline] + fn is_contained_in(self, haystack: &'a str) -> bool { + CharEqPattern(self).is_contained_in(haystack) + } + #[inline] + fn is_prefix_of(self, haystack: &'a str) -> bool { + CharEqPattern(self).is_prefix_of(haystack) + } + #[inline] + fn is_suffix_of(self, haystack: &'a str) -> bool + where $wrapper: ReverseSearcher<'a> + { + CharEqPattern(self).is_suffix_of(haystack) + } + } +} + +// Pattern for char + +impl<'a> Pattern<'a> for char { + type Searcher = CharSearcher<'a>; + char_eq_pattern_impl!(CharSearcher<'a>, CharSearcher); +} + +pub struct CharSearcher<'a>(CharEqSearcher<'a, char>); + +unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { + #[inline] + fn haystack(&self) -> &'a str { self.0.haystack() } + #[inline] + fn next(&mut self) -> SearchStep { self.0.next() } +} +unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { + #[inline] + fn next_back(&mut self) -> SearchStep { self.0.next_back() } +} +impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {} + +// Pattern for &[char] + +impl<'a, 'b> Pattern<'a> for &'b [char] { + type Searcher = CharSliceSearcher<'a, 'b>; + char_eq_pattern_impl!(CharSliceSearcher<'a, 'b>, CharSliceSearcher); +} + +pub struct CharSliceSearcher<'a, 'b>(CharEqSearcher<'a, &'b [char]>); + +unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> { + #[inline] + fn haystack(&self) -> &'a str { self.0.haystack() } + #[inline] + fn next(&mut self) -> SearchStep { self.0.next() } +} +unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> { + #[inline] + fn next_back(&mut self) -> SearchStep { self.0.next_back() } +} +impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {} + +// Pattern for predicates + +impl<'a, F: FnMut(char) -> bool> Pattern<'a> for F { + type Searcher = CharPredSearcher<'a, F>; + char_eq_pattern_impl!(CharPredSearcher<'a, F>, CharPredSearcher); +} + +pub struct CharPredSearcher<'a, F: FnMut(char) -> bool>(CharEqSearcher<'a, F>); + +unsafe impl<'a, F> Searcher<'a> for CharPredSearcher<'a, F> + where F: FnMut(char) -> bool +{ + #[inline] + fn haystack(&self) -> &'a str { self.0.haystack() } + #[inline] + fn next(&mut self) -> SearchStep { self.0.next() } +} +unsafe impl<'a, F> ReverseSearcher<'a> for CharPredSearcher<'a, F> + where F: FnMut(char) -> bool +{ + #[inline] + fn next_back(&mut self) -> SearchStep { self.0.next_back() } +} +impl<'a, F> DoubleEndedSearcher<'a> for CharPredSearcher<'a, F> + where F: FnMut(char) -> bool +{} + +// Pattern for &&str + +impl<'a, 'b> Pattern<'a> for &'b &'b str { + type Searcher = <&'b str as Pattern<'a>>::Searcher; + #[inline] + fn into_searcher(self, haystack: &'a str) + -> <&'b str as Pattern<'a>>::Searcher { + (*self).into_searcher(haystack) + } + #[inline] + fn is_contained_in(self, haystack: &'a str) -> bool { + (*self).is_contained_in(haystack) + } + #[inline] + fn is_prefix_of(self, haystack: &'a str) -> bool { + (*self).is_prefix_of(haystack) + } + #[inline] + fn is_suffix_of(self, haystack: &'a str) -> bool { + (*self).is_suffix_of(haystack) + } +} diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 72b2d5dc18..ba6a7c4a5f 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -10,18 +10,12 @@ //! Operations on tuples //! -//! To access a single element of a tuple one can use the following -//! methods: +//! To access a single element of a tuple one can use the `.0` +//! field access syntax. //! -//! * `valN` - returns a value of _N_-th element -//! * `refN` - returns a reference to _N_-th element -//! * `mutN` - returns a mutable reference to _N_-th element -//! -//! Indexing starts from zero, so `val0` returns first value, `val1` -//! returns second value, and so on. In general, a tuple with _S_ -//! elements provides aforementioned methods suffixed with numbers -//! from `0` to `S-1`. Traits which contain these methods are -//! implemented for tuples with up to 12 elements. +//! Indexing starts from zero, so `.0` returns first value, `.1` +//! returns second value, and so on. In general, a tuple with *N* +//! elements has field accessors from 0 to *N* - 1. //! //! If every type inside a tuple implements one of the following //! traits, then a tuple itself also implements it. @@ -52,7 +46,7 @@ macro_rules! e { macro_rules! tuple_impls { ($( $Tuple:ident { - $(($valN:ident, $refN:ident, $mutN:ident, $idx:tt) -> $T:ident)+ + $(($idx:tt) -> $T:ident)+ } )+) => { $( @@ -156,105 +150,105 @@ macro_rules! lexical_cmp { tuple_impls! { Tuple1 { - (val0, ref0, mut0, 0) -> A + (0) -> A } Tuple2 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B + (0) -> A + (1) -> B } Tuple3 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C + (0) -> A + (1) -> B + (2) -> C } Tuple4 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D + (0) -> A + (1) -> B + (2) -> C + (3) -> D } Tuple5 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E } Tuple6 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F } Tuple7 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G } Tuple8 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H } Tuple9 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I } Tuple10 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I - (val9, ref9, mut9, 9) -> J + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I + (9) -> J } Tuple11 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I - (val9, ref9, mut9, 9) -> J - (val10, ref10, mut10, 10) -> K + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I + (9) -> J + (10) -> K } Tuple12 { - (val0, ref0, mut0, 0) -> A - (val1, ref1, mut1, 1) -> B - (val2, ref2, mut2, 2) -> C - (val3, ref3, mut3, 3) -> D - (val4, ref4, mut4, 4) -> E - (val5, ref5, mut5, 5) -> F - (val6, ref6, mut6, 6) -> G - (val7, ref7, mut7, 7) -> H - (val8, ref8, mut8, 8) -> I - (val9, ref9, mut9, 9) -> J - (val10, ref10, mut10, 10) -> K - (val11, ref11, mut11, 11) -> L + (0) -> A + (1) -> B + (2) -> C + (3) -> D + (4) -> E + (5) -> F + (6) -> G + (7) -> H + (8) -> I + (9) -> J + (10) -> K + (11) -> L } } diff --git a/src/libcoretest/any.rs b/src/libcoretest/any.rs index 8b5e46f85f..eeaaa3e217 100644 --- a/src/libcoretest/any.rs +++ b/src/libcoretest/any.rs @@ -37,9 +37,9 @@ fn any_referenced() { fn any_owning() { let (a, b, c) = (box 5_usize as Box, box TEST as Box, box Test as Box); - assert!(a.is::()); - assert!(!b.is::()); - assert!(!c.is::()); + assert!(a.is::()); + assert!(!b.is::()); + assert!(!c.is::()); assert!(!a.is::<&'static str>()); assert!(b.is::<&'static str>()); @@ -54,7 +54,7 @@ fn any_owning() { fn any_downcast_ref() { let a = &5_usize as &Any; - match a.downcast_ref::() { + match a.downcast_ref::() { Some(&5) => {} x => panic!("Unexpected value {:?}", x) } @@ -68,13 +68,13 @@ fn any_downcast_ref() { #[test] fn any_downcast_mut() { let mut a = 5_usize; - let mut b = box 7_usize; + let mut b: Box<_> = box 7_usize; let a_r = &mut a as &mut Any; - let tmp: &mut uint = &mut *b; + let tmp: &mut usize = &mut *b; let b_r = tmp as &mut Any; - match a_r.downcast_mut::() { + match a_r.downcast_mut::() { Some(x) => { assert_eq!(*x, 5); *x = 612; @@ -82,7 +82,7 @@ fn any_downcast_mut() { x => panic!("Unexpected value {:?}", x) } - match b_r.downcast_mut::() { + match b_r.downcast_mut::() { Some(x) => { assert_eq!(*x, 7); *x = 413; @@ -100,12 +100,12 @@ fn any_downcast_mut() { x => panic!("Unexpected value {:?}", x) } - match a_r.downcast_mut::() { + match a_r.downcast_mut::() { Some(&mut 612) => {} x => panic!("Unexpected value {:?}", x) } - match b_r.downcast_mut::() { + match b_r.downcast_mut::() { Some(&mut 413) => {} x => panic!("Unexpected value {:?}", x) } @@ -115,8 +115,8 @@ fn any_downcast_mut() { fn any_fixed_vec() { let test = [0_usize; 8]; let test = &test as &Any; - assert!(test.is::<[uint; 8]>()); - assert!(!test.is::<[uint; 10]>()); + assert!(test.is::<[usize; 8]>()); + assert!(!test.is::<[usize; 10]>()); } @@ -126,6 +126,6 @@ fn bench_downcast_ref(b: &mut Bencher) { let mut x = 0; let mut y = &mut x as &mut Any; test::black_box(&mut y); - test::black_box(y.downcast_ref::() == Some(&0)); + test::black_box(y.downcast_ref::() == Some(&0)); }); } diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index 317ef3a570..85dd103900 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -59,7 +59,6 @@ fn double_imm_borrow() { fn no_mut_then_imm_borrow() { let x = RefCell::new(0); let _b1 = x.borrow_mut(); - assert!(x.try_borrow().is_none()); assert_eq!(x.borrow_state(), BorrowState::Writing); } @@ -67,7 +66,6 @@ fn no_mut_then_imm_borrow() { fn no_imm_then_borrow_mut() { let x = RefCell::new(0); let _b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); assert_eq!(x.borrow_state(), BorrowState::Reading); } @@ -76,7 +74,6 @@ fn no_double_borrow_mut() { let x = RefCell::new(0); assert_eq!(x.borrow_state(), BorrowState::Unused); let _b1 = x.borrow_mut(); - assert!(x.try_borrow_mut().is_none()); assert_eq!(x.borrow_state(), BorrowState::Writing); } @@ -105,11 +102,11 @@ fn double_borrow_single_release_no_borrow_mut() { { let _b2 = x.borrow(); } - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } #[test] -#[should_fail] +#[should_panic] fn discard_doesnt_unborrow() { let x = RefCell::new(0); let _b = x.borrow(); @@ -122,31 +119,31 @@ fn clone_ref_updates_flag() { let x = RefCell::new(0); { let b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); { let _b2 = clone_ref(&b1); - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } - assert!(x.try_borrow_mut().is_none()); + assert_eq!(x.borrow_state(), BorrowState::Reading); } - assert!(x.try_borrow_mut().is_some()); + assert_eq!(x.borrow_state(), BorrowState::Unused); } #[test] fn as_unsafe_cell() { - let c1: Cell = Cell::new(0); + let c1: Cell = Cell::new(0); c1.set(1); assert_eq!(1, unsafe { *c1.as_unsafe_cell().get() }); - let c2: Cell = Cell::new(0); + let c2: Cell = Cell::new(0); unsafe { *c2.as_unsafe_cell().get() = 1; } assert_eq!(1, c2.get()); - let r1: RefCell = RefCell::new(0); + let r1: RefCell = RefCell::new(0); *r1.borrow_mut() = 1; assert_eq!(1, unsafe { *r1.as_unsafe_cell().get() }); - let r2: RefCell = RefCell::new(0); + let r2: RefCell = RefCell::new(0); unsafe { *r2.as_unsafe_cell().get() = 1; } assert_eq!(1, *r2.borrow()); } diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs index 32dc6440b1..65e941d160 100644 --- a/src/libcoretest/char.rs +++ b/src/libcoretest/char.rs @@ -57,35 +57,47 @@ fn test_to_digit() { #[test] fn test_to_lowercase() { - assert_eq!('A'.to_lowercase(), 'a'); - assert_eq!('Ö'.to_lowercase(), 'ö'); - assert_eq!('ß'.to_lowercase(), 'ß'); - assert_eq!('Ü'.to_lowercase(), 'ü'); - assert_eq!('💩'.to_lowercase(), '💩'); - assert_eq!('Σ'.to_lowercase(), 'σ'); - assert_eq!('Τ'.to_lowercase(), 'τ'); - assert_eq!('Ι'.to_lowercase(), 'ι'); - assert_eq!('Γ'.to_lowercase(), 'γ'); - assert_eq!('Μ'.to_lowercase(), 'μ'); - assert_eq!('Α'.to_lowercase(), 'α'); - assert_eq!('Σ'.to_lowercase(), 'σ'); + fn lower(c: char) -> char { + let mut it = c.to_lowercase(); + let c = it.next().unwrap(); + assert!(it.next().is_none()); + c + } + assert_eq!(lower('A'), 'a'); + assert_eq!(lower('Ö'), 'ö'); + assert_eq!(lower('ß'), 'ß'); + assert_eq!(lower('Ü'), 'ü'); + assert_eq!(lower('💩'), '💩'); + assert_eq!(lower('Σ'), 'σ'); + assert_eq!(lower('Τ'), 'τ'); + assert_eq!(lower('Ι'), 'ι'); + assert_eq!(lower('Γ'), 'γ'); + assert_eq!(lower('Μ'), 'μ'); + assert_eq!(lower('Α'), 'α'); + assert_eq!(lower('Σ'), 'σ'); } #[test] fn test_to_uppercase() { - assert_eq!('a'.to_uppercase(), 'A'); - assert_eq!('ö'.to_uppercase(), 'Ö'); - assert_eq!('ß'.to_uppercase(), 'ß'); // not ẞ: Latin capital letter sharp s - assert_eq!('ü'.to_uppercase(), 'Ü'); - assert_eq!('💩'.to_uppercase(), '💩'); - - assert_eq!('σ'.to_uppercase(), 'Σ'); - assert_eq!('τ'.to_uppercase(), 'Τ'); - assert_eq!('ι'.to_uppercase(), 'Ι'); - assert_eq!('γ'.to_uppercase(), 'Γ'); - assert_eq!('μ'.to_uppercase(), 'Μ'); - assert_eq!('α'.to_uppercase(), 'Α'); - assert_eq!('ς'.to_uppercase(), 'Σ'); + fn upper(c: char) -> char { + let mut it = c.to_uppercase(); + let c = it.next().unwrap(); + assert!(it.next().is_none()); + c + } + assert_eq!(upper('a'), 'A'); + assert_eq!(upper('ö'), 'Ö'); + assert_eq!(upper('ß'), 'ß'); // not ẞ: Latin capital letter sharp s + assert_eq!(upper('ü'), 'Ü'); + assert_eq!(upper('💩'), '💩'); + + assert_eq!(upper('σ'), 'Σ'); + assert_eq!(upper('τ'), 'Τ'); + assert_eq!(upper('ι'), 'Ι'); + assert_eq!(upper('γ'), 'Γ'); + assert_eq!(upper('μ'), 'Μ'); + assert_eq!(upper('α'), 'Α'); + assert_eq!(upper('ς'), 'Σ'); } #[test] @@ -165,7 +177,7 @@ fn test_escape_unicode() { #[test] fn test_encode_utf8() { fn check(input: char, expect: &[u8]) { - let mut buf = [0u8; 4]; + let mut buf = [0; 4]; let n = input.encode_utf8(&mut buf).unwrap_or(0); assert_eq!(&buf[..n], expect); } @@ -179,7 +191,7 @@ fn test_encode_utf8() { #[test] fn test_encode_utf16() { fn check(input: char, expect: &[u16]) { - let mut buf = [0u16; 2]; + let mut buf = [0; 2]; let n = input.encode_utf16(&mut buf).unwrap_or(0); assert_eq!(&buf[..n], expect); } diff --git a/src/libcoretest/cmp.rs b/src/libcoretest/cmp.rs index 2e5c6fe5a2..9ed1508c3e 100644 --- a/src/libcoretest/cmp.rs +++ b/src/libcoretest/cmp.rs @@ -114,7 +114,7 @@ fn test_user_defined_eq() { // Our type. struct SketchyNum { - num : int + num : isize } // Our implementation of `PartialEq` to support `==` and `!=`. diff --git a/src/libcoretest/finally.rs b/src/libcoretest/finally.rs deleted file mode 100644 index 55fcb84985..0000000000 --- a/src/libcoretest/finally.rs +++ /dev/null @@ -1,62 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(deprecated)] - -use core::finally::{try_finally, Finally}; -use std::thread; - -#[test] -fn test_success() { - let mut i = 0; - try_finally( - &mut i, (), - |i, ()| { - *i = 10; - }, - |i| { - assert!(!thread::panicking()); - assert_eq!(*i, 10); - *i = 20; - }); - assert_eq!(i, 20); -} - -#[test] -#[should_fail] -fn test_fail() { - let mut i = 0; - try_finally( - &mut i, (), - |i, ()| { - *i = 10; - panic!(); - }, - |i| { - assert!(thread::panicking()); - assert_eq!(*i, 10); - }) -} - -#[test] -fn test_retval() { - let mut closure = || 10; - // FIXME(#16640) `: i32` annotation shouldn't be necessary - let i: i32 = closure.finally(|| { }); - assert_eq!(i, 10); -} - -#[test] -fn test_compact() { - fn do_some_fallible_work() {} - fn but_always_run_this_function() { } - let mut f = do_some_fallible_work; - f.finally(but_always_run_this_function); -} diff --git a/src/libcoretest/fmt/builders.rs b/src/libcoretest/fmt/builders.rs new file mode 100644 index 0000000000..885ee3f9c3 --- /dev/null +++ b/src/libcoretest/fmt/builders.rs @@ -0,0 +1,498 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod debug_struct { + use std::fmt; + + #[test] + fn test_empty() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Foo").finish() + } + } + + assert_eq!("Foo", format!("{:?}", Foo)); + assert_eq!("Foo", format!("{:#?}", Foo)); + } + + #[test] + fn test_single() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Foo") + .field("bar", &true) + .finish() + } + } + + assert_eq!("Foo { bar: true }", format!("{:?}", Foo)); + assert_eq!( +"Foo { + bar: true +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Foo") + .field("bar", &true) + .field("baz", &format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + assert_eq!("Foo { bar: true, baz: 10/20 }", format!("{:?}", Foo)); + assert_eq!( +"Foo { + bar: true, + baz: 10/20 +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Foo") + .field("bar", &true) + .field("baz", &format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Bar") + .field("foo", &Foo) + .field("hello", &"world") + .finish() + } + } + + assert_eq!("Bar { foo: Foo { bar: true, baz: 10/20 }, hello: \"world\" }", + format!("{:?}", Bar)); + assert_eq!( +"Bar { + foo: Foo { + bar: true, + baz: 10/20 + }, + hello: \"world\" +}", + format!("{:#?}", Bar)); + } +} + +mod debug_tuple { + use std::fmt; + + #[test] + fn test_empty() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Foo").finish() + } + } + + assert_eq!("Foo", format!("{:?}", Foo)); + assert_eq!("Foo", format!("{:#?}", Foo)); + } + + #[test] + fn test_single() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .finish() + } + } + + assert_eq!("Foo(true)", format!("{:?}", Foo)); + assert_eq!( +"Foo( + true +)", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .field(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + assert_eq!("Foo(true, 10/20)", format!("{:?}", Foo)); + assert_eq!( +"Foo( + true, + 10/20 +)", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Foo") + .field(&true) + .field(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("Bar") + .field(&Foo) + .field(&"world") + .finish() + } + } + + assert_eq!("Bar(Foo(true, 10/20), \"world\")", + format!("{:?}", Bar)); + assert_eq!( +"Bar( + Foo( + true, + 10/20 + ), + \"world\" +)", + format!("{:#?}", Bar)); + } +} + +mod debug_map { + use std::fmt; + + #[test] + fn test_empty() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_map().finish() + } + } + + assert_eq!("{}", format!("{:?}", Foo)); + assert_eq!("{}", format!("{:#?}", Foo)); + } + + #[test] + fn test_single() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .finish() + } + } + + assert_eq!("{\"bar\": true}", format!("{:?}", Foo)); + assert_eq!( +"{ + \"bar\": true +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .entry(&10i32, &format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + assert_eq!("{\"bar\": true, 10: 10/20}", format!("{:?}", Foo)); + assert_eq!( +"{ + \"bar\": true, + 10: 10/20 +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_map() + .entry(&"bar", &true) + .entry(&10i32, &format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_map() + .entry(&"foo", &Foo) + .entry(&Foo, &"world") + .finish() + } + } + + assert_eq!("{\"foo\": {\"bar\": true, 10: 10/20}, \ + {\"bar\": true, 10: 10/20}: \"world\"}", + format!("{:?}", Bar)); + assert_eq!( +"{ + \"foo\": { + \"bar\": true, + 10: 10/20 + }, + { + \"bar\": true, + 10: 10/20 + }: \"world\" +}", + format!("{:#?}", Bar)); + } +} + +mod debug_set { + use std::fmt; + + #[test] + fn test_empty() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_set().finish() + } + } + + assert_eq!("{}", format!("{:?}", Foo)); + assert_eq!("{}", format!("{:#?}", Foo)); + } + + #[test] + fn test_single() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .finish() + } + } + + assert_eq!("{true}", format!("{:?}", Foo)); + assert_eq!( +"{ + true +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .entry(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + assert_eq!("{true, 10/20}", format!("{:?}", Foo)); + assert_eq!( +"{ + true, + 10/20 +}", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_set() + .entry(&true) + .entry(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_set() + .entry(&Foo) + .entry(&"world") + .finish() + } + } + + assert_eq!("{{true, 10/20}, \"world\"}", + format!("{:?}", Bar)); + assert_eq!( +"{ + { + true, + 10/20 + }, + \"world\" +}", + format!("{:#?}", Bar)); + } +} + +mod debug_list { + use std::fmt; + + #[test] + fn test_empty() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list().finish() + } + } + + assert_eq!("[]", format!("{:?}", Foo)); + assert_eq!("[]", format!("{:#?}", Foo)); + } + + #[test] + fn test_single() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .finish() + } + } + + assert_eq!("[true]", format!("{:?}", Foo)); + assert_eq!( +"[ + true +]", + format!("{:#?}", Foo)); + } + + #[test] + fn test_multiple() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + assert_eq!("[true, 10/20]", format!("{:?}", Foo)); + assert_eq!( +"[ + true, + 10/20 +]", + format!("{:#?}", Foo)); + } + + #[test] + fn test_nested() { + struct Foo; + + impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&true) + .entry(&format_args!("{}/{}", 10i32, 20i32)) + .finish() + } + } + + struct Bar; + + impl fmt::Debug for Bar { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_list() + .entry(&Foo) + .entry(&"world") + .finish() + } + } + + assert_eq!("[[true, 10/20], \"world\"]", + format!("{:?}", Bar)); + assert_eq!( +"[ + [ + true, + 10/20 + ], + \"world\" +]", + format!("{:#?}", Bar)); + } +} diff --git a/src/libcoretest/fmt/mod.rs b/src/libcoretest/fmt/mod.rs index e779201444..cdb9c38f02 100644 --- a/src/libcoretest/fmt/mod.rs +++ b/src/libcoretest/fmt/mod.rs @@ -9,6 +9,7 @@ // except according to those terms. mod num; +mod builders; #[test] fn test_format_flags() { diff --git a/src/libcoretest/fmt/num.rs b/src/libcoretest/fmt/num.rs index bc8461b0b9..ba12ff306e 100644 --- a/src/libcoretest/fmt/num.rs +++ b/src/libcoretest/fmt/num.rs @@ -125,14 +125,14 @@ fn test_format_int_flags() { assert!(format!("{:>8x}", 10) == " a"); assert!(format!("{:#08x}", 10) == "0x00000a"); assert!(format!("{:08}", -10) == "-0000010"); - assert!(format!("{:x}", -1u8) == "ff"); - assert!(format!("{:X}", -1u8) == "FF"); - assert!(format!("{:b}", -1u8) == "11111111"); - assert!(format!("{:o}", -1u8) == "377"); - assert!(format!("{:#x}", -1u8) == "0xff"); - assert!(format!("{:#X}", -1u8) == "0xFF"); - assert!(format!("{:#b}", -1u8) == "0b11111111"); - assert!(format!("{:#o}", -1u8) == "0o377"); + assert!(format!("{:x}", !0u8) == "ff"); + assert!(format!("{:X}", !0u8) == "FF"); + assert!(format!("{:b}", !0u8) == "11111111"); + assert!(format!("{:o}", !0u8) == "377"); + assert!(format!("{:#x}", !0u8) == "0xff"); + assert!(format!("{:#X}", !0u8) == "0xFF"); + assert!(format!("{:#b}", !0u8) == "0b11111111"); + assert!(format!("{:#o}", !0u8) == "0o377"); } #[test] @@ -161,7 +161,7 @@ fn test_format_radix() { } #[test] -#[should_fail] +#[should_panic] fn test_radix_base_too_large() { let _ = radix(55, 37); } @@ -170,42 +170,42 @@ mod u32 { use test::Bencher; use core::fmt::radix; use std::rand::{weak_rng, Rng}; - use std::old_io::util::NullWriter; + use std::io::{Write, sink}; #[bench] fn format_bin(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:b}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:b}", rng.gen::()) }) } #[bench] fn format_oct(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:o}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:o}", rng.gen::()) }) } #[bench] fn format_dec(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{}", rng.gen::()) }) } #[bench] fn format_hex(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:x}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:x}", rng.gen::()) }) } #[bench] fn format_show(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:?}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:?}", rng.gen::()) }) } #[bench] fn format_base_36(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{}", radix(rng.gen::(), 36)) }) + b.iter(|| { write!(&mut sink(), "{}", radix(rng.gen::(), 36)) }) } } @@ -213,41 +213,41 @@ mod i32 { use test::Bencher; use core::fmt::radix; use std::rand::{weak_rng, Rng}; - use std::old_io::util::NullWriter; + use std::io::{Write, sink}; #[bench] fn format_bin(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:b}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:b}", rng.gen::()) }) } #[bench] fn format_oct(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:o}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:o}", rng.gen::()) }) } #[bench] fn format_dec(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{}", rng.gen::()) }) } #[bench] fn format_hex(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:x}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:x}", rng.gen::()) }) } #[bench] fn format_show(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{:?}", rng.gen::()) }) + b.iter(|| { write!(&mut sink(), "{:?}", rng.gen::()) }) } #[bench] fn format_base_36(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { write!(&mut NullWriter, "{}", radix(rng.gen::(), 36)) }) + b.iter(|| { write!(&mut sink(), "{}", radix(rng.gen::(), 36)) }) } } diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index 9b6af182f7..5c11f0196a 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -62,9 +62,10 @@ fn test_writer_hasher() { // FIXME (#18283) Enable test //let s: Box = box "a"; //assert_eq!(hasher.hash(& s), 97 + 0xFF); - let cs: &[u8] = &[1u8, 2u8, 3u8]; + let cs: &[u8] = &[1, 2, 3]; assert_eq!(hash(& cs), 9); - let cs: Box<[u8]> = box [1u8, 2u8, 3u8]; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let cs: Box<[u8]> = Box::new([1, 2, 3]); assert_eq!(hash(& cs), 9); // FIXME (#18248) Add tests for hashing Rc and Rc<[T]> @@ -85,7 +86,7 @@ struct CustomHasher { output: u64 } impl Hasher for CustomHasher { fn finish(&self) -> u64 { self.output } - fn write(&mut self, data: &[u8]) { panic!() } + fn write(&mut self, _: &[u8]) { panic!() } fn write_u64(&mut self, data: u64) { self.output = data; } } diff --git a/src/libcoretest/hash/sip.rs b/src/libcoretest/hash/sip.rs index 248cad32ef..8289d06d04 100644 --- a/src/libcoretest/hash/sip.rs +++ b/src/libcoretest/hash/sip.rs @@ -100,8 +100,8 @@ fn test_siphash() { [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ] ]; - let k0 = 0x_07_06_05_04_03_02_01_00_u64; - let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64; + let k0 = 0x_07_06_05_04_03_02_01_00; + let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; let mut buf = Vec::new(); let mut t = 0; let mut state_inc = SipState::new_with_keys(k0, k1); @@ -230,8 +230,8 @@ fn test_hash_no_concat_alias() { assert!(s != t && t != u); assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u)); - let v: (&[u8], &[u8], &[u8]) = (&[1u8], &[0u8, 0], &[0u8]); - let w: (&[u8], &[u8], &[u8]) = (&[1u8, 0, 0, 0], &[], &[]); + let v: (&[u8], &[u8], &[u8]) = (&[1], &[0, 0], &[0]); + let w: (&[u8], &[u8], &[u8]) = (&[1, 0, 0, 0], &[], &[]); assert!(v != w); assert!(hash(&v) != hash(&w)); diff --git a/src/libcoretest/intrinsics.rs b/src/libcoretest/intrinsics.rs index b836f5f3f6..c99fb8c197 100644 --- a/src/libcoretest/intrinsics.rs +++ b/src/libcoretest/intrinsics.rs @@ -28,4 +28,3 @@ fn test_typeid_unsized_types() { assert_eq!(TypeId::of::(), TypeId::of::()); assert!(TypeId::of::() != TypeId::of::()); } - diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 39a590c730..af80d347f0 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -12,14 +12,14 @@ use core::iter::*; use core::iter::order::*; use core::iter::MinMaxResult::*; use core::num::SignedInt; -use core::uint; +use core::usize; use core::cmp; use test::Bencher; #[test] fn test_lt() { - let empty: [int; 0] = []; + let empty: [isize; 0] = []; let xs = [1,2,3]; let ys = [1,2,0]; @@ -72,9 +72,9 @@ fn test_multi_iter() { #[test] fn test_counter_from_iter() { - let it = count(0, 5).take(10); - let xs: Vec = FromIterator::from_iter(it); - assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); + let it = (0..).step_by(5).take(10); + let xs: Vec = FromIterator::from_iter(it); + assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); } #[test] @@ -82,7 +82,7 @@ fn test_iterator_chain() { let xs = [0, 1, 2, 3, 4, 5]; let ys = [30, 40, 50, 60]; let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; - let mut it = xs.iter().chain(ys.iter()); + let it = xs.iter().chain(ys.iter()); let mut i = 0; for &x in it { assert_eq!(x, expected[i]); @@ -90,8 +90,8 @@ fn test_iterator_chain() { } assert_eq!(i, expected.len()); - let ys = count(30, 10).take(4); - let mut it = xs.iter().cloned().chain(ys); + let ys = (30..).step_by(10).take(4); + let it = xs.iter().cloned().chain(ys); let mut i = 0; for x in it { assert_eq!(x, expected[i]); @@ -102,15 +102,15 @@ fn test_iterator_chain() { #[test] fn test_filter_map() { - let it = count(0, 1).take(10) + let it = (0..).step_by(1).take(10) .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None }); - assert!(it.collect::>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]); + assert_eq!(it.collect::>(), [0*0, 2*2, 4*4, 6*6, 8*8]); } #[test] fn test_iterator_enumerate() { let xs = [0, 1, 2, 3, 4, 5]; - let mut it = xs.iter().enumerate(); + let it = xs.iter().enumerate(); for (i, &x) in it { assert_eq!(i, x); } @@ -152,7 +152,7 @@ fn test_iterator_peekable() { fn test_iterator_take_while() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; let ys = [0, 1, 2, 3, 5, 13]; - let mut it = xs.iter().take_while(|&x| *x < 15); + let it = xs.iter().take_while(|&x| *x < 15); let mut i = 0; for x in it { assert_eq!(*x, ys[i]); @@ -165,7 +165,7 @@ fn test_iterator_take_while() { fn test_iterator_skip_while() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19]; let ys = [15, 16, 17, 19]; - let mut it = xs.iter().skip_while(|&x| *x < 15); + let it = xs.iter().skip_while(|&x| *x < 15); let mut i = 0; for x in it { assert_eq!(*x, ys[i]); @@ -224,14 +224,14 @@ fn test_iterator_take_short() { #[test] fn test_iterator_scan() { // test the type inference - fn add(old: &mut int, new: &uint) -> Option { - *old += *new as int; + fn add(old: &mut isize, new: &usize) -> Option { + *old += *new as isize; Some(*old as f64) } let xs = [0, 1, 2, 3, 4]; let ys = [0f64, 1.0, 3.0, 6.0, 10.0]; - let mut it = xs.iter().scan(0, add); + let it = xs.iter().scan(0, add); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -244,7 +244,7 @@ fn test_iterator_scan() { fn test_iterator_flat_map() { let xs = [0, 3, 6]; let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8]; - let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3)); + let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3)); let mut i = 0; for x in it { assert_eq!(x, ys[i]); @@ -261,7 +261,7 @@ fn test_inspect() { let ys = xs.iter() .cloned() .inspect(|_| n += 1) - .collect::>(); + .collect::>(); assert_eq!(n, xs.len()); assert_eq!(&xs[..], &ys[..]); @@ -269,7 +269,7 @@ fn test_inspect() { #[test] fn test_unfoldr() { - fn count(st: &mut uint) -> Option { + fn count(st: &mut usize) -> Option { if *st < 10 { let ret = Some(*st); *st += 1; @@ -279,7 +279,7 @@ fn test_unfoldr() { } } - let mut it = Unfold::new(0, count); + let it = Unfold::new(0, count); let mut i = 0; for counted in it { assert_eq!(counted, i); @@ -291,13 +291,13 @@ fn test_unfoldr() { #[test] fn test_cycle() { let cycle_len = 3; - let it = count(0, 1).take(cycle_len).cycle(); - assert_eq!(it.size_hint(), (uint::MAX, None)); + let it = (0..).step_by(1).take(cycle_len).cycle(); + assert_eq!(it.size_hint(), (usize::MAX, None)); for (i, x) in it.take(100).enumerate() { assert_eq!(i % cycle_len, x); } - let mut it = count(0, 1).take(0).cycle(); + let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); } @@ -360,24 +360,24 @@ fn test_iterator_min() { #[test] fn test_iterator_size_hint() { - let c = count(0, 1); + let c = (0..).step_by(1); let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let v2 = &[10, 11, 12]; let vi = v.iter(); - assert_eq!(c.size_hint(), (uint::MAX, None)); + assert_eq!(c.size_hint(), (usize::MAX, None)); assert_eq!(vi.clone().size_hint(), (10, Some(10))); assert_eq!(c.clone().take(5).size_hint(), (5, Some(5))); assert_eq!(c.clone().skip(5).size_hint().1, None); assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None)); assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.clone().enumerate().size_hint(), (uint::MAX, None)); - assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (uint::MAX, None)); + assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None)); + assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None)); assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10))); assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None)); assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None)); - assert_eq!(c.clone().map(|_| 0).size_hint(), (uint::MAX, None)); + assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None)); assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5))); @@ -398,13 +398,14 @@ fn test_iterator_size_hint() { #[test] fn test_collect() { let a = vec![1, 2, 3, 4, 5]; - let b: Vec = a.iter().cloned().collect(); + let b: Vec = a.iter().cloned().collect(); assert!(a == b); } #[test] fn test_all() { - let v: Box<[int]> = box [1, 2, 3, 4, 5]; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]); assert!(v.iter().all(|&x| x < 10)); assert!(!v.iter().all(|&x| x % 2 == 0)); assert!(!v.iter().all(|&x| x > 100)); @@ -413,7 +414,8 @@ fn test_all() { #[test] fn test_any() { - let v: Box<[int]> = box [1, 2, 3, 4, 5]; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let v: Box<[isize]> = Box::new([1, 2, 3, 4, 5]); assert!(v.iter().any(|&x| x < 10)); assert!(v.iter().any(|&x| x % 2 == 0)); assert!(!v.iter().any(|&x| x > 100)); @@ -422,7 +424,7 @@ fn test_any() { #[test] fn test_find() { - let v: &[int] = &[1, 3, 9, 27, 103, 14, 11]; + let v: &[isize] = &[1, 3, 9, 27, 103, 14, 11]; assert_eq!(*v.iter().find(|&&x| x & 1 == 0).unwrap(), 14); assert_eq!(*v.iter().find(|&&x| x % 3 == 0).unwrap(), 3); assert!(v.iter().find(|&&x| x % 12 == 0).is_none()); @@ -446,13 +448,13 @@ fn test_count() { #[test] fn test_max_by() { - let xs: &[int] = &[-3, 0, 1, 5, -10]; + let xs: &[isize] = &[-3, 0, 1, 5, -10]; assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10); } #[test] fn test_min_by() { - let xs: &[int] = &[-3, 0, 1, 5, -10]; + let xs: &[isize] = &[-3, 0, 1, 5, -10]; assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0); } @@ -471,7 +473,7 @@ fn test_rev() { let mut it = xs.iter(); it.next(); it.next(); - assert!(it.rev().cloned().collect::>() == + assert!(it.rev().cloned().collect::>() == vec![16, 14, 12, 10, 8, 6]); } @@ -570,8 +572,8 @@ fn test_double_ended_chain() { #[test] fn test_rposition() { - fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } - fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } + fn f(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'b' } + fn g(xy: &(isize, char)) -> bool { let (_x, y) = *xy; y == 'd' } let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; assert_eq!(v.iter().rposition(f), Some(3)); @@ -579,10 +581,11 @@ fn test_rposition() { } #[test] -#[should_fail] +#[should_panic] fn test_rposition_panic() { - let v = [(box 0, box 0), (box 0, box 0), - (box 0, box 0), (box 0, box 0)]; + let v: [(Box<_>, Box<_>); 4] = + [(box 0, box 0), (box 0, box 0), + (box 0, box 0), (box 0, box 0)]; let mut i = 0; v.iter().rposition(|_elt| { if i == 2 { @@ -595,7 +598,7 @@ fn test_rposition_panic() { #[cfg(test)] -fn check_randacc_iter(a: T, len: uint) where +fn check_randacc_iter(a: T, len: usize) where A: PartialEq, T: Clone + RandomAccessIterator + Iterator, { @@ -681,7 +684,7 @@ fn test_random_access_zip() { #[test] fn test_random_access_take() { let xs = [1, 2, 3, 4, 5]; - let empty: &[int] = &[]; + let empty: &[isize] = &[]; check_randacc_iter(xs.iter().take(3), 3); check_randacc_iter(xs.iter().take(20), xs.len()); check_randacc_iter(xs.iter().take(0), 0); @@ -691,7 +694,7 @@ fn test_random_access_take() { #[test] fn test_random_access_skip() { let xs = [1, 2, 3, 4, 5]; - let empty: &[int] = &[]; + let empty: &[isize] = &[]; check_randacc_iter(xs.iter().skip(2), xs.len() - 2); check_randacc_iter(empty.iter().skip(2), 0); } @@ -723,19 +726,19 @@ fn test_random_access_map() { #[test] fn test_random_access_cycle() { let xs = [1, 2, 3, 4, 5]; - let empty: &[int] = &[]; + let empty: &[isize] = &[]; check_randacc_iter(xs.iter().cycle().take(27), 27); check_randacc_iter(empty.iter().cycle(), 0); } #[test] fn test_double_ended_range() { - assert!((11..14).rev().collect::>() == vec![13, 12, 11]); + assert_eq!((11..14).rev().collect::>(), [13, 12, 11]); for _ in (10..0).rev() { panic!("unreachable"); } - assert!((11..14).rev().collect::>() == vec![13, 12, 11]); + assert_eq!((11..14).rev().collect::>(), [13, 12, 11]); for _ in (10..0).rev() { panic!("unreachable"); } @@ -743,62 +746,51 @@ fn test_double_ended_range() { #[test] fn test_range() { - assert!((0..5).collect::>() == vec![0, 1, 2, 3, 4]); - assert!((-10..-1).collect::>() == - vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); - assert!((0..5).rev().collect::>() == vec![4, 3, 2, 1, 0]); + assert_eq!((0..5).collect::>(), [0, 1, 2, 3, 4]); + assert_eq!((-10..-1).collect::>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]); + assert_eq!((0..5).rev().collect::>(), [4, 3, 2, 1, 0]); assert_eq!((200..-5).count(), 0); assert_eq!((200..-5).rev().count(), 0); assert_eq!((200..200).count(), 0); assert_eq!((200..200).rev().count(), 0); assert_eq!((0..100).size_hint(), (100, Some(100))); - // this test is only meaningful when sizeof uint < sizeof u64 - assert_eq!((uint::MAX - 1..uint::MAX).size_hint(), (1, Some(1))); + // this test is only meaningful when sizeof usize < sizeof u64 + assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1))); assert_eq!((-10..-1).size_hint(), (9, Some(9))); assert_eq!((-1..-10).size_hint(), (0, Some(0))); } #[test] fn test_range_inclusive() { - assert!(range_inclusive(0, 5).collect::>() == + assert!(range_inclusive(0, 5).collect::>() == vec![0, 1, 2, 3, 4, 5]); - assert!(range_inclusive(0, 5).rev().collect::>() == + assert!(range_inclusive(0, 5).rev().collect::>() == vec![5, 4, 3, 2, 1, 0]); assert_eq!(range_inclusive(200, -5).count(), 0); assert_eq!(range_inclusive(200, -5).rev().count(), 0); - assert!(range_inclusive(200, 200).collect::>() == vec![200]); - assert!(range_inclusive(200, 200).rev().collect::>() == vec![200]); + assert_eq!(range_inclusive(200, 200).collect::>(), [200]); + assert_eq!(range_inclusive(200, 200).rev().collect::>(), [200]); } #[test] fn test_range_step() { - assert!(range_step(0, 20, 5).collect::>() == - vec![0, 5, 10, 15]); - assert!(range_step(20, 0, -5).collect::>() == - vec![20, 15, 10, 5]); - assert!(range_step(20, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(range_step(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(range_step(200, -5, 1).collect::>() == vec![]); - assert!(range_step(200, 200, 1).collect::>() == vec![]); + assert_eq!((0..20).step_by(5).collect::>(), [0, 5, 10, 15]); + assert_eq!((20..0).step_by(-5).collect::>(), [20, 15, 10, 5]); + assert_eq!((20..0).step_by(-6).collect::>(), [20, 14, 8, 2]); + assert_eq!((200..255).step_by(50).collect::>(), [200, 250]); + assert_eq!((200..-5).step_by(1).collect::>(), []); + assert_eq!((200..200).step_by(1).collect::>(), []); } #[test] fn test_range_step_inclusive() { - assert!(range_step_inclusive(0, 20, 5).collect::>() == - vec![0, 5, 10, 15, 20]); - assert!(range_step_inclusive(20, 0, -5).collect::>() == - vec![20, 15, 10, 5, 0]); - assert!(range_step_inclusive(20, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(range_step_inclusive(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(range_step_inclusive(200, -5, 1).collect::>() == - vec![]); - assert!(range_step_inclusive(200, 200, 1).collect::>() == - vec![200]); + assert_eq!(range_step_inclusive(0, 20, 5).collect::>(), [0, 5, 10, 15, 20]); + assert_eq!(range_step_inclusive(20, 0, -5).collect::>(), [20, 15, 10, 5, 0]); + assert_eq!(range_step_inclusive(20, 0, -6).collect::>(), [20, 14, 8, 2]); + assert_eq!(range_step_inclusive(200, 255, 50).collect::>(), [200, 250]); + assert_eq!(range_step_inclusive(200, -5, 1).collect::>(), []); + assert_eq!(range_step_inclusive(200, 200, 1).collect::>(), [200]); } #[test] @@ -819,7 +811,7 @@ fn test_peekable_is_empty() { #[test] fn test_min_max() { - let v: [int; 0] = []; + let v: [isize; 0] = []; assert_eq!(v.iter().min_max(), NoElements); let v = [1]; @@ -837,7 +829,7 @@ fn test_min_max() { #[test] fn test_min_max_result() { - let r: MinMaxResult = NoElements; + let r: MinMaxResult = NoElements; assert_eq!(r.into_option(), None); let r = OneElement(1); @@ -884,7 +876,7 @@ fn test_fuse() { #[bench] fn bench_rposition(b: &mut Bencher) { - let it: Vec = (0..300).collect(); + let it: Vec = (0..300).collect(); b.iter(|| { it.iter().rposition(|&x| x <= 150); }); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 2dfd81f32c..7ae0dcbb5f 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -8,10 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![feature(box_syntax)] #![feature(int_uint)] #![feature(unboxed_closures)] #![feature(unsafe_destructor)] +#![feature(core)] +#![feature(test)] +#![feature(rand)] +#![feature(unicode)] +#![feature(std_misc)] +#![feature(libc)] +#![feature(hash)] +#![feature(io)] +#![feature(collections)] +#![feature(debug_builders)] +#![feature(unique)] +#![feature(step_by)] +#![feature(slice_patterns)] #![allow(deprecated)] // rand extern crate core; @@ -24,7 +39,6 @@ mod atomic; mod cell; mod char; mod cmp; -mod finally; mod fmt; mod hash; mod iter; diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 5aeb330b78..5bc08376d2 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -21,15 +21,15 @@ fn size_of_basic() { #[test] #[cfg(target_pointer_width = "32")] fn size_of_32() { - assert_eq!(size_of::(), 4); - assert_eq!(size_of::<*const uint>(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::<*const usize>(), 4); } #[test] #[cfg(target_pointer_width = "64")] fn size_of_64() { - assert_eq!(size_of::(), 8); - assert_eq!(size_of::<*const uint>(), 8); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::<*const usize>(), 8); } #[test] @@ -50,15 +50,15 @@ fn align_of_basic() { #[test] #[cfg(target_pointer_width = "32")] fn align_of_32() { - assert_eq!(align_of::(), 4); - assert_eq!(align_of::<*const uint>(), 4); + assert_eq!(align_of::(), 4); + assert_eq!(align_of::<*const usize>(), 4); } #[test] #[cfg(target_pointer_width = "64")] fn align_of_64() { - assert_eq!(align_of::(), 8); - assert_eq!(align_of::<*const uint>(), 8); + assert_eq!(align_of::(), 8); + assert_eq!(align_of::<*const usize>(), 8); } #[test] @@ -93,17 +93,17 @@ fn test_transmute_copy() { #[test] fn test_transmute() { trait Foo { fn dummy(&self) { } } - impl Foo for int {} + impl Foo for isize {} - let a = box 100 as Box; + let a = box 100isize as Box; unsafe { let x: ::core::raw::TraitObject = transmute(a); - assert!(*(x.data as *const int) == 100); + assert!(*(x.data as *const isize) == 100); let _x: Box = transmute(x); } unsafe { - assert!(vec![76u8] == transmute::<_, Vec>("L".to_string())); + assert_eq!(transmute::<_, Vec>("L".to_string()), [76]); } } @@ -112,15 +112,15 @@ fn test_transmute() { // Static/dynamic method dispatch struct Struct { - field: int + field: isize } trait Trait { - fn method(&self) -> int; + fn method(&self) -> isize; } impl Trait for Struct { - fn method(&self) -> int { + fn method(&self) -> isize { self.field } } diff --git a/src/libcoretest/nonzero.rs b/src/libcoretest/nonzero.rs index be4c83d23e..7a367ddeec 100644 --- a/src/libcoretest/nonzero.rs +++ b/src/libcoretest/nonzero.rs @@ -43,7 +43,7 @@ fn test_match_on_nonzero_option() { #[test] fn test_match_option_empty_vec() { - let a: Option> = Some(vec![]); + let a: Option> = Some(vec![]); match a { None => panic!("unexpected None while matching on Some(vec![])"), _ => {} @@ -54,7 +54,7 @@ fn test_match_option_empty_vec() { fn test_match_option_vec() { let a = Some(vec![1, 2, 3, 4]); match a { - Some(v) => assert_eq!(v, vec![1, 2, 3, 4]), + Some(v) => assert_eq!(v, [1, 2, 3, 4]), None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])") } } diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index f5657d939b..fa41167cae 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -12,7 +12,7 @@ macro_rules! int_module { ($T:ty, $T_i:ident) => ( #[cfg(test)] mod tests { use core::$T_i::*; - use core::int; + use core::isize; use core::num::{FromStrRadix, Int, SignedInt}; use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr}; use num; @@ -70,12 +70,12 @@ mod tests { assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not()); } - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; - static _0: $T = 0; - static _1: $T = !0; + const _0: $T = 0; + const _1: $T = !0; #[test] fn test_count_ones() { @@ -153,7 +153,7 @@ mod tests { fn test_signed_checked_div() { assert!(10.checked_div(2) == Some(5)); assert!(5.checked_div(0) == None); - assert!(int::MIN.checked_div(-1) == None); + assert!(isize::MIN.checked_div(-1) == None); } #[test] @@ -201,6 +201,17 @@ mod tests { assert_eq!(FromStrRadix::from_str_radix("Z", 35).ok(), None::<$T>); assert_eq!(FromStrRadix::from_str_radix("-9", 2).ok(), None::<$T>); } + + #[test] + fn test_pow() { + let mut r = 2 as $T; + + assert_eq!(r.pow(2u32), 4 as $T); + assert_eq!(r.pow(0u32), 1 as $T); + r = -2 as $T; + assert_eq!(r.pow(2u32), 4 as $T); + assert_eq!(r.pow(3u32), -8 as $T); + } } )} diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 2c6efc0040..9087b87f64 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -21,7 +21,6 @@ mod i8; mod i16; mod i32; mod i64; -mod int; #[macro_use] mod uint_macros; @@ -30,7 +29,6 @@ mod u8; mod u16; mod u32; mod u64; -mod uint; /// Helper function for testing numeric operations pub fn test_num(ten: T, two: T) where @@ -90,36 +88,41 @@ mod test { #[test] fn test_int_from_str_overflow() { - let mut i8_val: i8 = 127_i8; + let mut i8_val: i8 = 127; assert_eq!("127".parse::().ok(), Some(i8_val)); assert_eq!("128".parse::().ok(), None); - i8_val += 1 as i8; + i8_val = i8_val.wrapping_add(1); assert_eq!("-128".parse::().ok(), Some(i8_val)); assert_eq!("-129".parse::().ok(), None); - let mut i16_val: i16 = 32_767_i16; + let mut i16_val: i16 = 32_767; assert_eq!("32767".parse::().ok(), Some(i16_val)); assert_eq!("32768".parse::().ok(), None); - i16_val += 1 as i16; + i16_val = i16_val.wrapping_add(1); assert_eq!("-32768".parse::().ok(), Some(i16_val)); assert_eq!("-32769".parse::().ok(), None); - let mut i32_val: i32 = 2_147_483_647_i32; + let mut i32_val: i32 = 2_147_483_647; assert_eq!("2147483647".parse::().ok(), Some(i32_val)); assert_eq!("2147483648".parse::().ok(), None); - i32_val += 1 as i32; + i32_val = i32_val.wrapping_add(1); assert_eq!("-2147483648".parse::().ok(), Some(i32_val)); assert_eq!("-2147483649".parse::().ok(), None); - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + let mut i64_val: i64 = 9_223_372_036_854_775_807; assert_eq!("9223372036854775807".parse::().ok(), Some(i64_val)); assert_eq!("9223372036854775808".parse::().ok(), None); - i64_val += 1 as i64; + i64_val = i64_val.wrapping_add(1); assert_eq!("-9223372036854775808".parse::().ok(), Some(i64_val)); assert_eq!("-9223372036854775809".parse::().ok(), None); } + + #[test] + fn test_int_from_minus_sign() { + assert_eq!("-".parse::().ok(), None); + } } diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index 5c6efc857f..e3eff6e751 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -20,7 +20,7 @@ mod tests { fn test_overflows() { assert!(MAX > 0); assert!(MIN <= 0); - assert!(MIN + MAX + 1 == 0); + assert!((MIN + MAX).wrapping_add(1) == 0); } #[test] @@ -38,12 +38,12 @@ mod tests { assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); } - static A: $T = 0b0101100; - static B: $T = 0b0100001; - static C: $T = 0b1111001; + const A: $T = 0b0101100; + const B: $T = 0b0100001; + const C: $T = 0b1111001; - static _0: $T = 0; - static _1: $T = !0; + const _0: $T = 0; + const _1: $T = !0; #[test] fn test_count_ones() { diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs index 0183e6a93c..33674a3abd 100644 --- a/src/libcoretest/ops.rs +++ b/src/libcoretest/ops.rs @@ -14,7 +14,7 @@ use core::ops::{Range, RangeFull, RangeFrom, RangeTo}; // Overhead of dtors struct HasDtor { - _x: int + _x: isize } impl Drop for HasDtor { diff --git a/src/libcoretest/option.rs b/src/libcoretest/option.rs index 860bd40e21..569142c0d7 100644 --- a/src/libcoretest/option.rs +++ b/src/libcoretest/option.rs @@ -16,11 +16,11 @@ use core::clone::Clone; #[test] fn test_get_ptr() { unsafe { - let x = box 0; - let addr_x: *const int = mem::transmute(&*x); + let x: Box<_> = box 0; + let addr_x: *const isize = mem::transmute(&*x); let opt = Some(x); let y = opt.unwrap(); - let addr_y: *const int = mem::transmute(&*y); + let addr_y: *const isize = mem::transmute(&*y); assert_eq!(addr_x, addr_y); } } @@ -41,7 +41,7 @@ fn test_get_resource() { use core::cell::RefCell; struct R { - i: Rc>, + i: Rc>, } #[unsafe_destructor] @@ -53,7 +53,7 @@ fn test_get_resource() { } } - fn r(i: Rc>) -> R { + fn r(i: Rc>) -> R { R { i: i } @@ -80,7 +80,7 @@ fn test_option_dance() { assert!(y.is_none()); } -#[test] #[should_fail] +#[test] #[should_panic] fn test_option_too_much_dance() { let mut y = Some(marker::NoCopy); let _y2 = y.take().unwrap(); @@ -89,44 +89,44 @@ fn test_option_too_much_dance() { #[test] fn test_and() { - let x: Option = Some(1); + let x: Option = Some(1); assert_eq!(x.and(Some(2)), Some(2)); - assert_eq!(x.and(None::), None); + assert_eq!(x.and(None::), None); - let x: Option = None; + let x: Option = None; assert_eq!(x.and(Some(2)), None); - assert_eq!(x.and(None::), None); + assert_eq!(x.and(None::), None); } #[test] fn test_and_then() { - let x: Option = Some(1); + let x: Option = Some(1); assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); - assert_eq!(x.and_then(|_| None::), None); + assert_eq!(x.and_then(|_| None::), None); - let x: Option = None; + let x: Option = None; assert_eq!(x.and_then(|x| Some(x + 1)), None); - assert_eq!(x.and_then(|_| None::), None); + assert_eq!(x.and_then(|_| None::), None); } #[test] fn test_or() { - let x: Option = Some(1); + let x: Option = Some(1); assert_eq!(x.or(Some(2)), Some(1)); assert_eq!(x.or(None), Some(1)); - let x: Option = None; + let x: Option = None; assert_eq!(x.or(Some(2)), Some(2)); assert_eq!(x.or(None), None); } #[test] fn test_or_else() { - let x: Option = Some(1); + let x: Option = Some(1); assert_eq!(x.or_else(|| Some(2)), Some(1)); assert_eq!(x.or_else(|| None), Some(1)); - let x: Option = None; + let x: Option = None; assert_eq!(x.or_else(|| Some(2)), Some(2)); assert_eq!(x.or_else(|| None), None); } @@ -139,14 +139,14 @@ fn test_unwrap() { } #[test] -#[should_fail] +#[should_panic] fn test_unwrap_panic1() { - let x: Option = None; + let x: Option = None; x.unwrap(); } #[test] -#[should_fail] +#[should_panic] fn test_unwrap_panic2() { let x: Option = None; x.unwrap(); @@ -154,19 +154,19 @@ fn test_unwrap_panic2() { #[test] fn test_unwrap_or() { - let x: Option = Some(1); + let x: Option = Some(1); assert_eq!(x.unwrap_or(2), 1); - let x: Option = None; + let x: Option = None; assert_eq!(x.unwrap_or(2), 2); } #[test] fn test_unwrap_or_else() { - let x: Option = Some(1); + let x: Option = Some(1); assert_eq!(x.unwrap_or_else(|| 2), 1); - let x: Option = None; + let x: Option = None; assert_eq!(x.unwrap_or_else(|| 2), 2); } @@ -223,13 +223,13 @@ fn test_ord() { /* FIXME(#20575) #[test] fn test_collect() { - let v: Option> = (0..0).map(|_| Some(0)).collect(); + let v: Option> = (0..0).map(|_| Some(0)).collect(); assert!(v == Some(vec![])); - let v: Option> = (0..3).map(|x| Some(x)).collect(); + let v: Option> = (0..3).map(|x| Some(x)).collect(); assert!(v == Some(vec![0, 1, 2])); - let v: Option> = (0..3).map(|x| { + let v: Option> = (0..3).map(|x| { if x > 1 { None } else { Some(x) } }).collect(); assert!(v == None); @@ -258,9 +258,6 @@ fn test_cloned() { assert_eq!(opt_none.clone(), None); assert_eq!(opt_none.cloned(), None); - // Mutable refs work - assert_eq!(opt_mut_ref.cloned(), Some(2u32)); - // Immutable ref works assert_eq!(opt_ref.clone(), Some(&val1)); assert_eq!(opt_ref.cloned(), Some(1u32)); diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs index 57456bfb1a..8f1017c50a 100644 --- a/src/libcoretest/ptr.rs +++ b/src/libcoretest/ptr.rs @@ -16,12 +16,12 @@ use std::iter::repeat; fn test() { unsafe { struct Pair { - fst: int, - snd: int + fst: isize, + snd: isize }; let mut p = Pair {fst: 10, snd: 20}; let pptr: *mut Pair = &mut p; - let iptr: *mut int = mem::transmute(pptr); + let iptr: *mut isize = mem::transmute(pptr); assert_eq!(*iptr, 10); *iptr = 30; assert_eq!(*iptr, 30); @@ -35,18 +35,15 @@ fn test() { let v0 = vec![32000u16, 32001u16, 32002u16]; let mut v1 = vec![0u16, 0u16, 0u16]; - copy_memory(v1.as_mut_ptr().offset(1), - v0.as_ptr().offset(1), 1); + copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1); assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16)); - copy_memory(v1.as_mut_ptr(), - v0.as_ptr().offset(2), 1); + copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1); assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16)); - copy_memory(v1.as_mut_ptr().offset(2), - v0.as_ptr(), 1); + copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1); assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16)); @@ -55,13 +52,13 @@ fn test() { #[test] fn test_is_null() { - let p: *const int = null(); + let p: *const isize = null(); assert!(p.is_null()); let q = unsafe { p.offset(1) }; assert!(!q.is_null()); - let mp: *mut int = null_mut(); + let mp: *mut isize = null_mut(); assert!(mp.is_null()); let mq = unsafe { mp.offset(1) }; @@ -71,22 +68,22 @@ fn test_is_null() { #[test] fn test_as_ref() { unsafe { - let p: *const int = null(); + let p: *const isize = null(); assert_eq!(p.as_ref(), None); - let q: *const int = &2; + let q: *const isize = &2; assert_eq!(q.as_ref().unwrap(), &2); - let p: *mut int = null_mut(); + let p: *mut isize = null_mut(); assert_eq!(p.as_ref(), None); - let q: *mut int = &mut 2; + let q: *mut isize = &mut 2; assert_eq!(q.as_ref().unwrap(), &2); // Lifetime inference - let u = 2; + let u = 2isize; { - let p: *const int = &u as *const _; + let p = &u as *const isize; assert_eq!(p.as_ref().unwrap(), &2); } } @@ -95,16 +92,16 @@ fn test_as_ref() { #[test] fn test_as_mut() { unsafe { - let p: *mut int = null_mut(); + let p: *mut isize = null_mut(); assert!(p.as_mut() == None); - let q: *mut int = &mut 2; + let q: *mut isize = &mut 2; assert!(q.as_mut().unwrap() == &mut 2); // Lifetime inference - let mut u = 2; + let mut u = 2isize; { - let p: *mut int = &mut u as *mut _; + let p = &mut u as *mut isize; assert!(p.as_mut().unwrap() == &mut 2); } } @@ -139,12 +136,12 @@ fn test_ptr_addition() { fn test_ptr_subtraction() { unsafe { let xs = vec![0,1,2,3,4,5,6,7,8,9]; - let mut idx = 9i8; + let mut idx = 9; let ptr = xs.as_ptr(); - while idx >= 0i8 { - assert_eq!(*(ptr.offset(idx as int)), idx as int); - idx = idx - 1i8; + while idx >= 0 { + assert_eq!(*(ptr.offset(idx as isize)), idx as isize); + idx = idx - 1; } let mut xs_mut = xs; @@ -156,7 +153,7 @@ fn test_ptr_subtraction() { m_ptr = m_ptr.offset(-1); } - assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]); + assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]); } } @@ -164,15 +161,15 @@ fn test_ptr_subtraction() { fn test_set_memory() { let mut xs = [0u8; 20]; let ptr = xs.as_mut_ptr(); - unsafe { set_memory(ptr, 5u8, xs.len()); } + unsafe { write_bytes(ptr, 5u8, xs.len()); } assert!(xs == [5u8; 20]); } #[test] fn test_unsized_unique() { - let xs: &mut [_] = &mut [1, 2, 3]; - let ptr = unsafe { Unique::new(xs as *mut [_]) }; + let xs: &mut [i32] = &mut [1, 2, 3]; + let ptr = unsafe { Unique::new(xs as *mut [i32]) }; let ys = unsafe { &mut **ptr }; - let zs: &mut [_] = &mut [1, 2, 3]; + let zs: &mut [i32] = &mut [1, 2, 3]; assert!(ys == zs); } diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs index ab7b5101e7..ac8c2b953a 100644 --- a/src/libcoretest/result.rs +++ b/src/libcoretest/result.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn op1() -> Result { Ok(666) } -pub fn op2() -> Result { Err("sadface") } +pub fn op1() -> Result { Ok(666) } +pub fn op2() -> Result { Err("sadface") } #[test] pub fn test_and() { @@ -24,74 +24,74 @@ pub fn test_and() { #[test] pub fn test_and_then() { - assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); - assert_eq!(op1().and_then(|_| Err::("bad")).unwrap_err(), + assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); + assert_eq!(op1().and_then(|_| Err::("bad")).unwrap_err(), "bad"); - assert_eq!(op2().and_then(|i| Ok::(i + 1)).unwrap_err(), + assert_eq!(op2().and_then(|i| Ok::(i + 1)).unwrap_err(), "sadface"); - assert_eq!(op2().and_then(|_| Err::("bad")).unwrap_err(), + assert_eq!(op2().and_then(|_| Err::("bad")).unwrap_err(), "sadface"); } #[test] pub fn test_or() { - assert_eq!(op1().or(Ok(667)).unwrap(), 666); + assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666); assert_eq!(op1().or(Err("bad")).unwrap(), 666); - assert_eq!(op2().or(Ok(667)).unwrap(), 667); + assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667); assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad"); } #[test] pub fn test_or_else() { - assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), 666); - assert_eq!(op1().or_else(|e| Err::(e)).unwrap(), 666); + assert_eq!(op1().or_else(|_| Ok::(667)).unwrap(), 666); + assert_eq!(op1().or_else(|e| Err::(e)).unwrap(), 666); - assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), 667); - assert_eq!(op2().or_else(|e| Err::(e)).unwrap_err(), + assert_eq!(op2().or_else(|_| Ok::(667)).unwrap(), 667); + assert_eq!(op2().or_else(|e| Err::(e)).unwrap_err(), "sadface"); } #[test] pub fn test_impl_map() { - assert!(Ok::(1).map(|x| x + 1) == Ok(2)); - assert!(Err::(1).map(|x| x + 1) == Err(1)); + assert!(Ok::(1).map(|x| x + 1) == Ok(2)); + assert!(Err::(1).map(|x| x + 1) == Err(1)); } #[test] pub fn test_impl_map_err() { - assert!(Ok::(1).map_err(|x| x + 1) == Ok(1)); - assert!(Err::(1).map_err(|x| x + 1) == Err(2)); + assert!(Ok::(1).map_err(|x| x + 1) == Ok(1)); + assert!(Err::(1).map_err(|x| x + 1) == Err(2)); } /* FIXME(#20575) #[test] fn test_collect() { - let v: Result, ()> = (0..0).map(|_| Ok::(0)).collect(); + let v: Result, ()> = (0..0).map(|_| Ok::(0)).collect(); assert!(v == Ok(vec![])); - let v: Result, ()> = (0..3).map(|x| Ok::(x)).collect(); + let v: Result, ()> = (0..3).map(|x| Ok::(x)).collect(); assert!(v == Ok(vec![0, 1, 2])); - let v: Result, int> = (0..3).map(|x| { + let v: Result, isize> = (0..3).map(|x| { if x > 1 { Err(x) } else { Ok(x) } }).collect(); assert!(v == Err(2)); // test that it does not take more elements than it needs - let mut functions: [Box Result<(), int>>; 3] = + let mut functions: [Box Result<(), isize>>; 3] = [box || Ok(()), box || Err(1), box || panic!()]; - let v: Result, int> = functions.iter_mut().map(|f| (*f)()).collect(); + let v: Result, isize> = functions.iter_mut().map(|f| (*f)()).collect(); assert!(v == Err(1)); } */ #[test] pub fn test_fmt_default() { - let ok: Result = Ok(100); - let err: Result = Err("Err"); + let ok: Result = Ok(100); + let err: Result = Err("Err"); let s = format!("{:?}", ok); assert_eq!(s, "Ok(100)"); @@ -101,8 +101,8 @@ pub fn test_fmt_default() { #[test] pub fn test_unwrap_or() { - let ok: Result = Ok(100); - let ok_err: Result = Err("Err"); + let ok: Result = Ok(100); + let ok_err: Result = Err("Err"); assert_eq!(ok.unwrap_or(50), 100); assert_eq!(ok_err.unwrap_or(50), 50); @@ -110,7 +110,7 @@ pub fn test_unwrap_or() { #[test] pub fn test_unwrap_or_else() { - fn handler(msg: &'static str) -> int { + fn handler(msg: &'static str) -> isize { if msg == "I got this." { 50 } else { @@ -118,17 +118,17 @@ pub fn test_unwrap_or_else() { } } - let ok: Result = Ok(100); - let ok_err: Result = Err("I got this."); + let ok: Result = Ok(100); + let ok_err: Result = Err("I got this."); assert_eq!(ok.unwrap_or_else(handler), 100); assert_eq!(ok_err.unwrap_or_else(handler), 50); } #[test] -#[should_fail] +#[should_panic] pub fn test_unwrap_or_else_panic() { - fn handler(msg: &'static str) -> int { + fn handler(msg: &'static str) -> isize { if msg == "I got this." { 50 } else { @@ -136,6 +136,6 @@ pub fn test_unwrap_or_else_panic() { } } - let bad_err: Result = Err("Unrecoverable mess."); - let _ : int = bad_err.unwrap_or_else(handler); + let bad_err: Result = Err("Unrecoverable mess."); + let _ : isize = bad_err.unwrap_or_else(handler); } diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs index 46c7730cc6..fe73b3b440 100644 --- a/src/libcoretest/slice.rs +++ b/src/libcoretest/slice.rs @@ -59,16 +59,16 @@ fn iterator_to_slice() { let mut iter = data.iter_mut(); assert_eq!(&iter[..], &other_data[..]); // mutability: - assert!(&mut iter[] == other_data); + assert!(&mut iter[..] == other_data); iter.next(); assert_eq!(&iter[..], &other_data[1..]); - assert!(&mut iter[] == &mut other_data[1..]); + assert!(&mut iter[..] == &mut other_data[1..]); iter.next_back(); assert_eq!(&iter[..], &other_data[1..2]); - assert!(&mut iter[] == &mut other_data[1..2]); + assert!(&mut iter[..] == &mut other_data[1..2]); let s = iter.into_slice(); assert!(s == &mut other_data[1..2]); diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index 375564c39b..5fce527d97 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[test] +fn test_pattern_deref_forward() { + let data = "aabcdaa"; + assert!(data.contains("bcd")); + assert!(data.contains(&"bcd")); + assert!(data.contains(&"bcd".to_string())); +} + +#[test] +fn test_empty_match_indices() { + let data = "aä中!"; + let vec: Vec<_> = data.match_indices("").collect(); + assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]); +} + #[test] fn test_bool_from_str() { assert_eq!("true".parse().ok(), Some(true)); @@ -18,7 +33,7 @@ fn test_bool_from_str() { fn check_contains_all_substrings(s: &str) { assert!(s.contains("")); for i in 0..s.len() { - for j in range(i+1, s.len() + 1) { + for j in i+1..s.len() + 1 { assert!(s.contains(&s[i..j])); } } @@ -50,22 +65,22 @@ fn test_strslice_contains() { fn test_rsplitn_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - let mut split: Vec<&str> = data.rsplitn(3, ' ').collect(); + let mut split: Vec<&str> = data.rsplitn(4, ' ').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); - let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect(); + let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); // Unicode - let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect(); + let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); - let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect(); + let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect(); split.reverse(); - assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); } #[test] @@ -73,33 +88,33 @@ fn test_split_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; let split: Vec<&str> = data.split(' ').collect(); - assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); let mut rsplit: Vec<&str> = data.split(' ').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); let split: Vec<&str> = data.split(|c: char| c == ' ').collect(); - assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); + assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); // Unicode let split: Vec<&str> = data.split('ä').collect(); - assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); let mut rsplit: Vec<&str> = data.split('ä').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); let split: Vec<&str> = data.split(|c: char| c == 'ä').collect(); - assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect(); rsplit.reverse(); - assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); + assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); } #[test] @@ -108,16 +123,263 @@ fn test_rev_split_char_iterator_no_trailing() { let mut split: Vec<&str> = data.split('\n').rev().collect(); split.reverse(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); let mut split: Vec<&str> = data.split_terminator('\n').rev().collect(); split.reverse(); - assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]); + assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); } #[test] fn test_utf16_code_units() { use unicode::str::Utf16Encoder; assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::>(), - vec![0xE9, 0xD83D, 0xDCA9]) + [0xE9, 0xD83D, 0xDCA9]) +} + +#[test] +fn starts_with_in_unicode() { + assert!(!"├── Cargo.toml".starts_with("# ")); +} + +#[test] +fn starts_short_long() { + assert!(!"".starts_with("##")); + assert!(!"##".starts_with("####")); + assert!("####".starts_with("##")); + assert!(!"##ä".starts_with("####")); + assert!("####ä".starts_with("##")); + assert!(!"##".starts_with("####ä")); + assert!("##ä##".starts_with("##ä")); + + assert!("".starts_with("")); + assert!("ä".starts_with("")); + assert!("#ä".starts_with("")); + assert!("##ä".starts_with("")); + assert!("ä###".starts_with("")); + assert!("#ä##".starts_with("")); + assert!("##ä#".starts_with("")); +} + +#[test] +fn contains_weird_cases() { + assert!("* \t".contains(' ')); + assert!(!"* \t".contains('?')); + assert!(!"* \t".contains('\u{1F4A9}')); +} + +#[test] +fn trim_ws() { + assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()), + "a \t "); + assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()), + " \t a"); + assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), + "a"); + assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()), + ""); + assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()), + ""); + assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), + ""); +} + +mod pattern { + use std::str::Pattern; + use std::str::{Searcher, ReverseSearcher}; + use std::str::SearchStep::{self, Match, Reject, Done}; + + macro_rules! make_test { + ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => { + mod $name { + use std::str::SearchStep::{Match, Reject}; + use super::{cmp_search_to_vec}; + #[test] + fn fwd() { + cmp_search_to_vec(false, $p, $h, vec![$($e),*]); + } + #[test] + fn bwd() { + cmp_search_to_vec(true, $p, $h, vec![$($e),*]); + } + } + } + } + + fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str, + right: Vec) + where P::Searcher: ReverseSearcher<'a> + { + let mut searcher = pat.into_searcher(haystack); + let mut v = vec![]; + loop { + match if !rev {searcher.next()} else {searcher.next_back()} { + Match(a, b) => v.push(Match(a, b)), + Reject(a, b) => v.push(Reject(a, b)), + Done => break, + } + } + if rev { + v.reverse(); + } + assert_eq!(v, right); + } + + make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [ + Reject(0, 1), + Match (1, 3), + Reject(3, 4), + Match (4, 6), + Reject(6, 7), + ]); + make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [ + Match(0, 0), + Match(1, 1), + Match(2, 2), + Match(3, 3), + Match(4, 4), + Match(5, 5), + Match(6, 6), + Match(7, 7), + ]); + make_test!(str_searcher_mulibyte_haystack, " ", "├──", [ + Reject(0, 3), + Reject(3, 6), + Reject(6, 9), + ]); + make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [ + Match(0, 0), + Match(3, 3), + Match(6, 6), + Match(9, 9), + ]); + make_test!(str_searcher_empty_needle_empty_haystack, "", "", [ + Match(0, 0), + ]); + make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [ + ]); + make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [ + Reject(0, 1), + Match (1, 2), + Match (2, 3), + Reject(3, 4), + Match (4, 5), + Match (5, 6), + Reject(6, 7), + ]); + make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [ + Reject(0, 3), + Reject(3, 6), + Reject(6, 9), + ]); + make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [ + Reject(0, 1), + Reject(1, 2), + Reject(2, 3), + ]); + +} + +mod bench { + macro_rules! make_test_inner { + ($s:ident, $code:expr, $name:ident, $str:expr) => { + #[bench] + fn $name(bencher: &mut Bencher) { + let mut $s = $str; + black_box(&mut $s); + bencher.iter(|| $code); + } + } + } + + macro_rules! make_test { + ($name:ident, $s:ident, $code:expr) => { + mod $name { + use test::Bencher; + use test::black_box; + + // Short strings: 65 bytes each + make_test_inner!($s, $code, short_ascii, + "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!"); + make_test_inner!($s, $code, short_mixed, + "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!"); + make_test_inner!($s, $code, short_pile_of_poo, + "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!"); + make_test_inner!($s, $code, long_lorem_ipsum,"\ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \ +ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \ +eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \ +sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \ +tempus vel, gravida nec quam. + +In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ +sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ +diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ +lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ +eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ +interdum. Curabitur ut nisi justo. + +Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ +mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ +lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ +est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ +felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ +ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ +feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ +Aliquam sit amet placerat lorem. + +Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ +mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ +Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ +lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ +suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ +cursus accumsan. + +Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ +feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ +vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ +leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ +malesuada sollicitudin quam eu fermentum!"); + } + } + } + + make_test!(chars_count, s, s.chars().count()); + + make_test!(contains_bang_str, s, s.contains("!")); + make_test!(contains_bang_char, s, s.contains('!')); + + make_test!(match_indices_a_str, s, s.match_indices("a").count()); + + make_test!(split_a_str, s, s.split("a").count()); + + make_test!(trim_ascii_char, s, { + use std::ascii::AsciiExt; + s.trim_matches(|c: char| c.is_ascii()) + }); + make_test!(trim_left_ascii_char, s, { + use std::ascii::AsciiExt; + s.trim_left_matches(|c: char| c.is_ascii()) + }); + make_test!(trim_right_ascii_char, s, { + use std::ascii::AsciiExt; + s.trim_right_matches(|c: char| c.is_ascii()) + }); + + make_test!(find_underscore_char, s, s.find('_')); + make_test!(rfind_underscore_char, s, s.rfind('_')); + make_test!(find_underscore_str, s, s.find("_")); + + make_test!(find_zzz_char, s, s.find('\u{1F4A4}')); + make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}')); + make_test!(find_zzz_str, s, s.find("\u{1F4A4}")); + + make_test!(split_space_char, s, s.split(' ').count()); + make_test!(split_terminator_space_char, s, s.split_terminator(' ').count()); + + make_test!(splitn_space_char, s, s.splitn(10, ' ').count()); + make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count()); + + make_test!(split_space_str, s, s.split(" ").count()); + make_test!(split_ad_str, s, s.split("ad").count()); } diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 24660b3f39..63d1fe968f 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -14,6 +14,8 @@ //! [def]: https://en.wikipedia.org/wiki/DEFLATE //! [mz]: https://code.google.com/p/miniz/ +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "flate"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -23,23 +25,43 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(core)] -#![feature(int_uint)] #![feature(libc)] #![feature(staged_api)] +#![feature(unique)] +#![cfg_attr(test, feature(rustc_private, rand, collections))] #[cfg(test)] #[macro_use] extern crate log; extern crate libc; use libc::{c_void, size_t, c_int}; +use std::fmt; use std::ops::Deref; use std::ptr::Unique; use std::slice; +#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Error { + _unused: (), +} + +impl Error { + fn new() -> Error { + Error { + _unused: (), + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "decompression error".fmt(f) + } +} + pub struct Bytes { ptr: Unique, - len: uint, + len: usize, } impl Deref for Bytes { @@ -72,59 +94,60 @@ extern { -> *mut c_void; } -static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal" -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 +const LZ_NORM: c_int = 0x80; // LZ with 128 probes, "normal" +const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum +const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum -fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { +fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes { unsafe { - let mut outsz : size_t = 0; + let mut outsz: size_t = 0; let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, bytes.len() as size_t, &mut outsz, flags); - if !res.is_null() { - let res = Unique::new(res as *mut u8); - Some(Bytes { ptr: res, len: outsz as uint }) - } else { - None + assert!(!res.is_null()); + Bytes { + ptr: Unique::new(res as *mut u8), + len: outsz as usize, } } } /// Compress a buffer, without writing any sort of header on the output. -pub fn deflate_bytes(bytes: &[u8]) -> Option { +pub fn deflate_bytes(bytes: &[u8]) -> 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 { +pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes { deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER) } -fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { +fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result { unsafe { - let mut outsz : size_t = 0; + let mut outsz: size_t = 0; let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _, bytes.len() as size_t, &mut outsz, flags); if !res.is_null() { - let res = Unique::new(res as *mut u8); - Some(Bytes { ptr: res, len: outsz as uint }) + Ok(Bytes { + ptr: Unique::new(res as *mut u8), + len: outsz as usize, + }) } else { - None + Err(Error::new()) } } } /// Decompress a buffer, without parsing any sort of header on the input. -pub fn inflate_bytes(bytes: &[u8]) -> Option { +pub fn inflate_bytes(bytes: &[u8]) -> Result { inflate_bytes_internal(bytes, 0) } /// Decompress a buffer that starts with a zlib header. -pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option { +pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result { inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER) } @@ -138,7 +161,7 @@ mod tests { #[test] fn test_flate_round_trip() { let mut r = rand::thread_rng(); - let mut words = vec!(); + let mut words = vec![]; for _ in 0..20 { let range = r.gen_range(1, 10); let v = r.gen_iter::().take(range).collect::>(); @@ -151,8 +174,8 @@ mod tests { } debug!("de/inflate of {} bytes of random word-sequences", input.len()); - let cmp = deflate_bytes(&input).expect("deflation failed"); - let out = inflate_bytes(&cmp).expect("inflation failed"); + let cmp = deflate_bytes(&input); + let out = inflate_bytes(&cmp).unwrap(); debug!("{} bytes deflated to {} ({:.1}% size)", input.len(), cmp.len(), 100.0 * ((cmp.len() as f64) / (input.len() as f64))); @@ -162,9 +185,9 @@ mod tests { #[test] fn test_zlib_flate() { - let bytes = vec!(1, 2, 3, 4, 5); - let deflated = deflate_bytes(&bytes).expect("deflation failed"); - let inflated = inflate_bytes(&deflated).expect("inflation failed"); + let bytes = vec![1, 2, 3, 4, 5]; + let deflated = deflate_bytes(&bytes); + let inflated = inflate_bytes(&deflated).unwrap(); assert_eq!(&*inflated, &*bytes); } } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index be77622ac1..4cf93ab264 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -14,6 +14,8 @@ //! Parsing does not happen at runtime: structures of `std::fmt::rt` are //! generated instead. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "fmt_macros"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -24,7 +26,6 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(int_uint)] #![feature(staged_api)] #![feature(unicode)] @@ -39,7 +40,7 @@ use std::string; /// A piece is a portion of the format string which represents the next part /// to emit. These are emitted as a stream by the `Parser` class. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum Piece<'a> { /// A literal string which should directly be emitted String(&'a str), @@ -49,7 +50,7 @@ pub enum Piece<'a> { } /// Representation of an argument specification. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub struct Argument<'a> { /// Where to find this argument pub position: Position<'a>, @@ -58,14 +59,14 @@ pub struct Argument<'a> { } /// Specification for the formatting of an argument in the format string. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub struct FormatSpec<'a> { /// Optionally specified character to fill alignment with pub fill: Option, /// Optionally specified alignment pub align: Alignment, /// Packed version of various flags provided - pub flags: uint, + pub flags: u32, /// The integer precision to use pub precision: Count<'a>, /// The string width requested for the resulting format @@ -77,18 +78,18 @@ pub struct FormatSpec<'a> { } /// Enum describing where an argument for a format can be located. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum Position<'a> { /// The argument will be in the next position. This is the default. ArgumentNext, /// The argument is located at a specific index. - ArgumentIs(uint), + ArgumentIs(usize), /// The argument has a name. ArgumentNamed(&'a str), } /// Enum of alignments which are supported. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum Alignment { /// The value will be aligned to the left. AlignLeft, @@ -102,7 +103,7 @@ pub enum Alignment { /// Various flags which can be applied to format strings. The meaning of these /// flags is defined by the formatters themselves. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum Flag { /// A `+` will be used to denote positive numbers. FlagSignPlus, @@ -118,14 +119,14 @@ pub enum Flag { /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum Count<'a> { /// The count is specified explicitly. - CountIs(uint), + CountIs(usize), /// The count is specified by the argument with the given name. CountIsName(&'a str), /// The count is specified by the argument at the given index. - CountIsParam(uint), + CountIsParam(usize), /// The count is specified by the next parameter. CountIsNextParam, /// The count is implied and cannot be explicitly specified. @@ -237,7 +238,7 @@ impl<'a> Parser<'a> { /// Parses all of a string which is to be considered a "raw literal" in a /// format string. This is everything outside of the braces. - fn string(&mut self, start: uint) -> &'a str { + fn string(&mut self, start: usize) -> &'a str { loop { // we may not consume the character, so clone the iterator match self.cur.clone().next() { @@ -314,13 +315,13 @@ impl<'a> Parser<'a> { } // Sign flags if self.consume('+') { - spec.flags |= 1 << (FlagSignPlus as uint); + spec.flags |= 1 << (FlagSignPlus as u32); } else if self.consume('-') { - spec.flags |= 1 << (FlagSignMinus as uint); + spec.flags |= 1 << (FlagSignMinus as u32); } // Alternate marker if self.consume('#') { - spec.flags |= 1 << (FlagAlternate as uint); + spec.flags |= 1 << (FlagAlternate as u32); } // Width and precision let mut havewidth = false; @@ -333,7 +334,7 @@ impl<'a> Parser<'a> { spec.width = CountIsParam(0); havewidth = true; } else { - spec.flags |= 1 << (FlagSignAwareZeroPad as uint); + spec.flags |= 1 << (FlagSignAwareZeroPad as u32); } } if !havewidth { @@ -413,7 +414,7 @@ impl<'a> Parser<'a> { /// Optionally parses an integer at the current position. This doesn't deal /// with overflow at all, it's just accumulating digits. - fn integer(&mut self) -> Option { + fn integer(&mut self) -> Option { let mut cur = 0; let mut found = false; loop { @@ -445,7 +446,7 @@ mod tests { fn same(fmt: &'static str, p: &[Piece<'static>]) { let parser = Parser::new(fmt); - assert!(p == parser.collect::>>()); + assert!(parser.collect::>>() == p); } fn fmtdflt() -> FormatSpec<'static> { @@ -617,7 +618,7 @@ mod tests { format: FormatSpec { fill: None, align: AlignUnknown, - flags: (1 << FlagSignMinus as uint), + flags: (1 << FlagSignMinus as u32), precision: CountImplied, width: CountImplied, ty: "", @@ -628,7 +629,7 @@ mod tests { format: FormatSpec { fill: None, align: AlignUnknown, - flags: (1 << FlagSignPlus as uint) | (1 << FlagAlternate as uint), + flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32), precision: CountImplied, width: CountImplied, ty: "", diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index fdd7f7395c..5c10641e85 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -46,7 +46,7 @@ //! //! fn print_usage(program: &str, opts: &[OptGroup]) { //! let brief = format!("Usage: {} [options]", program); -//! print!("{}", usage(brief.as_slice(), opts)); +//! print!("{}", usage(brief, opts)); //! } //! //! fn main() { @@ -63,20 +63,23 @@ //! Err(f) => { panic!(f.to_string()) } //! }; //! if matches.opt_present("h") { -//! print_usage(program.as_slice(), opts); +//! print_usage(program, opts); //! return; //! } //! let output = matches.opt_str("o"); //! let input = if !matches.free.is_empty() { //! matches.free[0].clone() //! } else { -//! print_usage(program.as_slice(), opts); +//! print_usage(program, opts); //! return; //! }; -//! do_work(input.as_slice(), output); +//! do_work(input, output); //! } //! ``` + +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "getopts"] #![unstable(feature = "rustc_private", reason = "use the crates.io `getopts` library instead")] @@ -89,10 +92,9 @@ html_playground_url = "http://play.rust-lang.org/")] #![deny(missing_docs)] -#![feature(collections)] -#![feature(int_uint)] #![feature(staged_api)] #![feature(str_words)] +#![feature(str_char)] #![cfg_attr(test, feature(rustc_private))] #[cfg(test)] #[macro_use] extern crate log; @@ -211,7 +213,7 @@ pub enum Fail { } /// The type of failure that occurred. -#[derive(Copy, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[allow(missing_docs)] pub enum FailType { ArgumentMissing_, @@ -308,7 +310,7 @@ impl Matches { } /// Returns the number of times an option was matched. - pub fn opt_count(&self, nm: &str) -> uint { + pub fn opt_count(&self, nm: &str) -> usize { self.opt_vals(nm).len() } @@ -386,7 +388,7 @@ fn is_arg(arg: &str) -> bool { arg.len() > 1 && arg.as_bytes()[0] == b'-' } -fn find_opt(opts: &[Opt], nm: Name) -> Option { +fn find_opt(opts: &[Opt], nm: Name) -> Option { // Search main options. let pos = opts.iter().position(|opt| opt.name == nm); if pos.is_some() { @@ -584,7 +586,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { let opts: Vec = optgrps.iter().map(|x| x.long_to_short()).collect(); let n_opts = opts.len(); - fn f(_x: uint) -> Vec { return Vec::new(); } + fn f(_x: usize) -> Vec { return Vec::new(); } let mut vals: Vec<_> = (0..n_opts).map(f).collect(); let mut free: Vec = Vec::new(); @@ -616,8 +618,8 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { let mut j = 1; names = Vec::new(); while j < curlen { - let range = cur.char_range_at(j); - let opt = Short(range.ch); + let ch = cur.char_at(j); + let opt = Short(ch); /* In a series of potential options (eg. -aheJ), if we see one which takes an argument, we assume all @@ -638,12 +640,13 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { No => false }; - if arg_follows && range.next < curlen { - i_arg = Some((&cur[range.next..curlen]).to_string()); + let next = j + ch.len_utf8(); + if arg_follows && next < curlen { + i_arg = Some((&cur[next..curlen]).to_string()); break; } - j = range.next; + j = next; } } let mut name_pos = 0; @@ -784,7 +787,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // FIXME: #5516 should be graphemes not codepoints // wrapped description - row.push_str(&desc_rows.connect(&desc_sep[..])[]); + row.push_str(&desc_rows.connect(&desc_sep[..])); row }); @@ -840,18 +843,18 @@ pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String { line } -#[derive(Copy)] +#[derive(Copy, Clone)] enum SplitWithinState { A, // leading whitespace, initial state B, // words C, // internal and trailing whitespace } -#[derive(Copy)] +#[derive(Copy, Clone)] enum Whitespace { Ws, // current char is whitespace Cr // current char is not whitespace } -#[derive(Copy)] +#[derive(Copy, Clone)] enum LengthLimit { UnderLim, // current char makes current substring still fit in limit OverLim // current char makes current substring no longer fit in limit @@ -869,7 +872,7 @@ enum LengthLimit { /// /// Panics during iteration if the string contains a non-whitespace /// sequence longer than the limit. -fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where +fn each_split_within(ss: &str, lim: usize, mut it: F) -> bool where F: FnMut(&str) -> bool { // Just for fun, let's write this as a state machine: @@ -888,7 +891,7 @@ fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where lim = fake_i; } - let mut machine = |cont: &mut bool, (i, c): (uint, char)| -> bool { + let mut machine = |cont: &mut bool, (i, c): (usize, char)| -> bool { let whitespace = if c.is_whitespace() { Ws } else { Cr }; let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim }; @@ -950,7 +953,7 @@ fn each_split_within(ss: &str, lim: uint, mut it: F) -> bool where #[test] fn test_split_within() { - fn t(s: &str, i: uint, u: &[String]) { + fn t(s: &str, i: usize, u: &[String]) { let mut v = Vec::new(); each_split_within(s, i, |s| { v.push(s.to_string()); true }); assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); @@ -963,7 +966,7 @@ fn test_split_within() { "little lamb".to_string(), "Little lamb".to_string() ]); - t("\nMary had a little lamb\nLittle lamb\n", ::std::uint::MAX, + t("\nMary had a little lamb\nLittle lamb\n", ::std::usize::MAX, &["Mary had a little lamb\nLittle lamb".to_string()]); } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index acd52c752e..95b78e1cbf 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -37,7 +37,7 @@ //! Each node label is derived directly from the int representing the node, //! while the edge labels are all empty strings. //! -//! This example also illustrates how to use `CowVec` to return +//! This example also illustrates how to use `Cow<[T]>` to return //! an owned vector or a borrowed slice as appropriate: we construct the //! node vector from scratch, but borrow the edge list (rather than //! constructing a copy of all the edges from scratch). @@ -47,14 +47,16 @@ //! which is cyclic. //! //! ```rust +//! # #![feature(rustc_private, core, into_cow)] //! use std::borrow::IntoCow; +//! use std::io::Write; //! use graphviz as dot; //! -//! type Nd = int; -//! type Ed = (int,int); +//! type Nd = isize; +//! type Ed = (isize,isize); //! struct Edges(Vec); //! -//! pub fn render_to(output: &mut W) { +//! pub fn render_to(output: &mut W) { //! let edges = Edges(vec!((0,1), (0,2), (1,3), (2,3), (3,4), (4,4))); //! dot::render(&edges, output).unwrap() //! } @@ -82,7 +84,7 @@ //! //! fn edges(&'a self) -> dot::Edges<'a,Ed> { //! let &Edges(ref edges) = self; -//! edges.as_slice().into_cow() +//! (&edges[..]).into_cow() //! } //! //! fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s } @@ -94,10 +96,10 @@ //! ``` //! //! ```no_run -//! # pub fn render_to(output: &mut W) { unimplemented!() } +//! # pub fn render_to(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::old_io::File; -//! let mut f = File::create(&Path::new("example1.dot")); +//! use std::fs::File; +//! let mut f = File::create("example1.dot").unwrap(); //! render_to(&mut f) //! } //! ``` @@ -131,7 +133,7 @@ //! direct reference to the `(source,target)` pair stored in the graph's //! internal vector (rather than passing around a copy of the pair //! itself). Note that this implies that `fn edges(&'a self)` must -//! construct a fresh `Vec<&'a (uint,uint)>` from the `Vec<(uint,uint)>` +//! construct a fresh `Vec<&'a (usize,usize)>` from the `Vec<(usize,usize)>` //! edges stored in `self`. //! //! Since both the set of nodes and the set of edges are always @@ -147,14 +149,16 @@ //! entity `&sube`). //! //! ```rust +//! # #![feature(rustc_private, core, into_cow)] //! use std::borrow::IntoCow; +//! use std::io::Write; //! use graphviz as dot; //! -//! type Nd = uint; -//! type Ed<'a> = &'a (uint, uint); -//! struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } +//! type Nd = usize; +//! type Ed<'a> = &'a (usize, usize); +//! struct Graph { nodes: Vec<&'static str>, edges: Vec<(usize,usize)> } //! -//! pub fn render_to(output: &mut W) { +//! pub fn render_to(output: &mut W) { //! let nodes = vec!("{x,y}","{x}","{y}","{}"); //! let edges = vec!((0,1), (0,2), (1,3), (2,3)); //! let graph = Graph { nodes: nodes, edges: edges }; @@ -186,10 +190,10 @@ //! ``` //! //! ```no_run -//! # pub fn render_to(output: &mut W) { unimplemented!() } +//! # pub fn render_to(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::old_io::File; -//! let mut f = File::create(&Path::new("example2.dot")); +//! use std::fs::File; +//! let mut f = File::create("example2.dot").unwrap(); //! render_to(&mut f) //! } //! ``` @@ -203,14 +207,16 @@ //! Hasse-diagram for the subsets of the set `{x, y}`. //! //! ```rust +//! # #![feature(rustc_private, core, into_cow)] //! use std::borrow::IntoCow; +//! use std::io::Write; //! use graphviz as dot; //! -//! type Nd<'a> = (uint, &'a str); +//! type Nd<'a> = (usize, &'a str); //! type Ed<'a> = (Nd<'a>, Nd<'a>); -//! struct Graph { nodes: Vec<&'static str>, edges: Vec<(uint,uint)> } +//! struct Graph { nodes: Vec<&'static str>, edges: Vec<(usize,usize)> } //! -//! pub fn render_to(output: &mut W) { +//! pub fn render_to(output: &mut W) { //! let nodes = vec!("{x,y}","{x}","{y}","{}"); //! let edges = vec!((0,1), (0,2), (1,3), (2,3)); //! let graph = Graph { nodes: nodes, edges: edges }; @@ -225,7 +231,7 @@ //! } //! fn node_label<'b>(&'b self, n: &Nd<'b>) -> dot::LabelText<'b> { //! let &(i, _) = n; -//! dot::LabelText::LabelStr(self.nodes[i].as_slice().into_cow()) +//! dot::LabelText::LabelStr(self.nodes[i].into_cow()) //! } //! fn edge_label<'b>(&'b self, _: &Ed<'b>) -> dot::LabelText<'b> { //! dot::LabelText::LabelStr("⊆".into_cow()) @@ -234,12 +240,12 @@ //! //! impl<'a> dot::GraphWalk<'a, Nd<'a>, Ed<'a>> for Graph { //! fn nodes(&'a self) -> dot::Nodes<'a,Nd<'a>> { -//! self.nodes.iter().map(|s|s.as_slice()).enumerate().collect() +//! self.nodes.iter().map(|s| &s[..]).enumerate().collect() //! } //! fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { //! self.edges.iter() -//! .map(|&(i,j)|((i, self.nodes[i].as_slice()), -//! (j, self.nodes[j].as_slice()))) +//! .map(|&(i,j)|((i, &self.nodes[i][..]), +//! (j, &self.nodes[j][..]))) //! .collect() //! } //! fn source(&self, e: &Ed<'a>) -> Nd<'a> { let &(s,_) = e; s } @@ -250,10 +256,10 @@ //! ``` //! //! ```no_run -//! # pub fn render_to(output: &mut W) { unimplemented!() } +//! # pub fn render_to(output: &mut W) { unimplemented!() } //! pub fn main() { -//! use std::old_io::File; -//! let mut f = File::create(&Path::new("example3.dot")); +//! use std::fs::File; +//! let mut f = File::create("example3.dot").unwrap(); //! render_to(&mut f) //! } //! ``` @@ -264,6 +270,8 @@ //! //! * [DOT language](http://www.graphviz.org/doc/info/lang.html) +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "graphviz"] #![unstable(feature = "rustc_private")] #![feature(staged_api)] @@ -273,14 +281,14 @@ #![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(int_uint)] #![feature(collections)] -#![feature(old_io)] +#![feature(into_cow)] use self::LabelText::*; use std::borrow::{IntoCow, Cow}; -use std::old_io; +use std::io::prelude::*; +use std::io; /// The text for a graphviz label on a node or edge. pub enum LabelText<'a> { @@ -376,7 +384,7 @@ impl<'a> Id<'a> { is_letter_or_underscore(c) || in_range('0', c, '9') } fn in_range(low: char, c: char, high: char) -> bool { - low as uint <= c as uint && c as uint <= high as uint + low as usize <= c as usize && c as usize <= high as usize } } @@ -463,7 +471,7 @@ impl<'a> LabelText<'a> { fn pre_escaped_content(self) -> Cow<'a, str> { match self { EscStr(s) => s, - LabelStr(s) => if s.contains_char('\\') { + LabelStr(s) => if s.contains('\\') { (&*s).escape_default().into_cow() } else { s @@ -502,7 +510,7 @@ pub type Edges<'a,E> = Cow<'a,[E]>; /// that is bound by the self lifetime `'a`. /// /// The `nodes` and `edges` method each return instantiations of -/// `CowVec` to leave implementers the freedom to create +/// `Cow<[T]>` to leave implementers the freedom to create /// entirely new vectors or to pass back slices into internally owned /// vectors. pub trait GraphWalk<'a, N, E> { @@ -516,7 +524,7 @@ pub trait GraphWalk<'a, N, E> { fn target(&'a self, edge: &E) -> N; } -#[derive(Copy, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum RenderOption { NoEdgeLabels, NoNodeLabels, @@ -527,26 +535,26 @@ pub fn default_options() -> Vec { vec![] } /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Simple wrapper around `render_opts` that passes a default set of options.) -pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( +pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Write>( g: &'a G, - w: &mut W) -> old_io::IoResult<()> { + w: &mut W) -> io::Result<()> { render_opts(g, w, &[]) } /// Renders directed graph `g` into the writer `w` in DOT syntax. /// (Main entry point for the library.) -pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>( +pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Write>( g: &'a G, w: &mut W, - options: &[RenderOption]) -> old_io::IoResult<()> + options: &[RenderOption]) -> io::Result<()> { - fn writeln(w: &mut W, arg: &[&str]) -> old_io::IoResult<()> { - for &s in arg { try!(w.write_str(s)); } - w.write_char('\n') + fn writeln(w: &mut W, arg: &[&str]) -> io::Result<()> { + for &s in arg { try!(w.write_all(s.as_bytes())); } + write!(w, "\n") } - fn indent(w: &mut W) -> old_io::IoResult<()> { - w.write_str(" ") + fn indent(w: &mut W) -> io::Result<()> { + w.write_all(b" ") } try!(writeln(w, &["digraph ", g.graph_id().as_slice(), " {"])); @@ -587,17 +595,18 @@ mod tests { use self::NodeLabels::*; use super::{Id, Labeller, Nodes, Edges, GraphWalk, render}; use super::LabelText::{self, LabelStr, EscStr}; - use std::old_io::IoResult; + use std::io; + use std::io::prelude::*; use std::borrow::IntoCow; use std::iter::repeat; /// each node is an index in a vector in the graph. - type Node = uint; + type Node = usize; struct Edge { - from: uint, to: uint, label: &'static str + from: usize, to: usize, label: &'static str } - fn edge(from: uint, to: uint, label: &'static str) -> Edge { + fn edge(from: usize, to: usize, label: &'static str) -> Edge { Edge { from: from, to: to, label: label } } @@ -627,7 +636,7 @@ mod tests { enum NodeLabels { AllNodesLabelled(Vec), - UnlabelledNodes(uint), + UnlabelledNodes(usize), SomeNodesLabelled(Vec>), } @@ -736,10 +745,12 @@ mod tests { } } - fn test_input(g: LabelledGraph) -> IoResult { + fn test_input(g: LabelledGraph) -> io::Result { let mut writer = Vec::new(); render(&g, &mut writer).unwrap(); - (&mut &*writer).read_to_string() + let mut s = String::new(); + try!(Read::read_to_string(&mut &*writer, &mut s)); + Ok(s) } // All of the tests use raw-strings as the format for the expected outputs, @@ -851,9 +862,10 @@ r#"digraph hasse_diagram { edge(1, 3, ";"), edge(2, 3, ";" ))); render(&g, &mut writer).unwrap(); - let r = (&mut &*writer).read_to_string(); + let mut r = String::new(); + Read::read_to_string(&mut &*writer, &mut r).unwrap(); - assert_eq!(r.unwrap(), + assert_eq!(r, r#"digraph syntax_tree { N0[label="if test {\l branch1\l} else {\l branch2\l}\lafterward\l"]; N1[label="branch1"]; diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 383108a3bc..44d689059d 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "libc"] #![crate_type = "rlib"] -#![cfg_attr(not(feature = "cargo-build"), - unstable(feature = "libc"))] -#![cfg_attr(not(feature = "cargo-build"), feature(staged_api))] +#![cfg_attr(not(feature = "cargo-build"), unstable(feature = "libc"))] +#![cfg_attr(not(feature = "cargo-build"), feature(staged_api, core, no_std))] #![cfg_attr(not(feature = "cargo-build"), staged_api)] -#![cfg_attr(not(feature = "cargo-build"), feature(core))] -#![feature(no_std)] -#![no_std] +#![cfg_attr(not(feature = "cargo-build"), no_std)] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", @@ -76,7 +75,8 @@ //! one from Berkeley after the lawsuits died down and the CSRG dissolved. #![allow(bad_style, raw_pointer_derive)] -#[cfg(feature = "cargo-build")] extern crate "std" as core; +#![cfg_attr(target_os = "nacl", allow(unused_imports))] +#[cfg(feature = "cargo-build")] extern crate std as core; #[cfg(not(feature = "cargo-build"))] extern crate core; #[cfg(test)] extern crate std; @@ -86,78 +86,33 @@ // you can write more-platform-agnostic code if you stick to just these // symbols. -pub use types::common::c95::{FILE, c_void, fpos_t}; -pub use types::common::c99::{int8_t, int16_t, int32_t, int64_t}; -pub use types::common::c99::{uint8_t, uint16_t, uint32_t, uint64_t}; -pub use types::common::posix88::{DIR, dirent_t}; -pub use types::os::common::posix01::{timeval}; -pub use types::os::common::bsd44::{addrinfo, in_addr, in6_addr, sockaddr_storage}; -pub use types::os::common::bsd44::{ip_mreq, ip6_mreq, sockaddr, sockaddr_un}; -pub use types::os::common::bsd44::{sa_family_t, sockaddr_in, sockaddr_in6, socklen_t}; -pub use types::os::arch::c95::{c_char, c_double, c_float, c_int, c_uint}; -pub use types::os::arch::c95::{c_long, c_short, c_uchar, c_ulong, wchar_t}; -pub use types::os::arch::c95::{c_ushort, clock_t, ptrdiff_t, c_schar}; -pub use types::os::arch::c95::{size_t, time_t, suseconds_t}; -pub use types::os::arch::c99::{c_longlong, c_ulonglong}; -pub use types::os::arch::c99::{intptr_t, uintptr_t}; -pub use types::os::arch::c99::{intmax_t, uintmax_t}; -pub use types::os::arch::posix88::{dev_t, ino_t, mode_t}; -pub use types::os::arch::posix88::{off_t, pid_t, ssize_t}; - -pub use consts::os::c95::{_IOFBF, _IOLBF, _IONBF, BUFSIZ, EOF}; -pub use consts::os::c95::{EXIT_FAILURE, EXIT_SUCCESS}; -pub use consts::os::c95::{FILENAME_MAX, FOPEN_MAX, L_tmpnam}; -pub use consts::os::c95::{RAND_MAX, SEEK_CUR, SEEK_END}; -pub use consts::os::c95::{SEEK_SET, TMP_MAX}; -pub use consts::os::posix88::{F_OK, O_APPEND, O_CREAT, O_EXCL}; -pub use consts::os::posix88::{O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY}; -pub use consts::os::posix88::{R_OK, S_IEXEC, S_IFBLK, S_IFCHR}; -pub use consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG, S_IFLNK}; -pub use consts::os::posix88::{S_IREAD, S_IRUSR, S_IRWXU, S_IWUSR}; -pub use consts::os::posix88::{STDERR_FILENO, STDIN_FILENO, S_IXUSR}; -pub use consts::os::posix88::{STDOUT_FILENO, W_OK, X_OK}; -pub use consts::os::bsd44::{AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW}; -pub use consts::os::bsd44::{IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, TCP_NODELAY}; -pub use consts::os::bsd44::{SOL_SOCKET, SO_KEEPALIVE, SO_ERROR}; -pub use consts::os::bsd44::{SO_REUSEADDR, SO_BROADCAST, SHUT_WR, IP_MULTICAST_LOOP}; -pub use consts::os::bsd44::{IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP}; -pub use consts::os::bsd44::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP}; -pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL, IP_HDRINCL, SHUT_RD}; -pub use consts::os::extra::{IPPROTO_RAW}; - -pub use funcs::c95::ctype::{isalnum, isalpha, iscntrl, isdigit}; -pub use funcs::c95::ctype::{islower, isprint, ispunct, isspace}; -pub use funcs::c95::ctype::{isupper, isxdigit, tolower, toupper}; - -pub use funcs::c95::stdio::{fclose, feof, ferror, fflush, fgetc}; -pub use funcs::c95::stdio::{fgetpos, fgets, fopen, fputc, fputs}; -pub use funcs::c95::stdio::{fread, freopen, fseek, fsetpos, ftell}; -pub use funcs::c95::stdio::{fwrite, perror, puts, remove, rename, rewind}; -pub use funcs::c95::stdio::{setbuf, setvbuf, tmpfile, ungetc}; - -pub use funcs::c95::stdlib::{abs, atof, atoi, calloc, exit, _exit, atexit}; -pub use funcs::c95::stdlib::{free, getenv, labs, malloc, rand}; -pub use funcs::c95::stdlib::{realloc, srand, strtod, strtol}; -pub use funcs::c95::stdlib::{strtoul, system}; - -pub use funcs::c95::string::{memchr, memcmp}; -pub use funcs::c95::string::{strcat, strchr, strcmp}; -pub use funcs::c95::string::{strcoll, strcpy, strcspn, strerror}; -pub use funcs::c95::string::{strlen, strncat, strncmp, strncpy}; -pub use funcs::c95::string::{strpbrk, strrchr, strspn, strstr}; -pub use funcs::c95::string::{strtok, strxfrm}; - -pub use funcs::posix88::fcntl::{open, creat}; -pub use funcs::posix88::stat_::{chmod, fstat, mkdir, stat}; -pub use funcs::posix88::stdio::{fdopen, fileno, pclose, popen}; -pub use funcs::posix88::unistd::{access, chdir, close, dup, dup2}; -pub use funcs::posix88::unistd::{execv, execve, execvp, getcwd}; -pub use funcs::posix88::unistd::{getpid, isatty, lseek, pipe, read}; -pub use funcs::posix88::unistd::{rmdir, unlink, write}; - -pub use funcs::bsd43::{socket, setsockopt, bind, send, recv, recvfrom}; -pub use funcs::bsd43::{listen, sendto, accept, connect, getpeername, getsockname}; -pub use funcs::bsd43::{shutdown}; +pub use types::common::c95::*; +pub use types::common::c99::*; +pub use types::common::posix88::*; +pub use types::os::common::posix01::*; +pub use types::os::common::bsd44::*; +pub use types::os::arch::c95::*; +pub use types::os::arch::c99::*; +pub use types::os::arch::posix88::*; +pub use types::os::arch::posix01::*; +pub use types::os::arch::extra::*; + +pub use consts::os::c95::*; +pub use consts::os::posix88::*; +pub use consts::os::posix01::*; +pub use consts::os::bsd44::*; +pub use consts::os::extra::*; + +pub use funcs::c95::ctype::*; +pub use funcs::c95::stdio::*; +pub use funcs::c95::stdlib::*; +pub use funcs::c95::string::*; +pub use funcs::posix88::fcntl::*; +pub use funcs::posix88::stat_::*; +pub use funcs::posix88::stdio::*; +pub use funcs::posix88::unistd::*; + +pub use funcs::bsd43::*; // But we also reexport most everything // if you're interested in writing platform-specific code. @@ -169,148 +124,44 @@ pub use funcs::bsd43::{shutdown}; // // So the following exports don't follow any particular plan. -#[cfg(unix)] pub use consts::os::sysconf::{_SC_PAGESIZE}; -#[cfg(unix)] pub use consts::os::posix88::{PROT_READ, PROT_WRITE, PROT_EXEC}; -#[cfg(unix)] pub use consts::os::posix88::{MAP_FIXED, MAP_FILE, MAP_ANON, MAP_PRIVATE, MAP_FAILED}; -#[cfg(unix)] pub use consts::os::posix88::{EACCES, EBADF, EINVAL, ENODEV, ENOMEM}; -#[cfg(unix)] pub use consts::os::posix88::{ECONNREFUSED, ECONNRESET, EPERM, EPIPE}; -#[cfg(unix)] pub use consts::os::posix88::{ENOTCONN, ECONNABORTED, EADDRNOTAVAIL, EINTR}; -#[cfg(unix)] pub use consts::os::posix88::{EADDRINUSE, ENOENT, EISDIR, EAGAIN, EWOULDBLOCK}; -#[cfg(unix)] pub use consts::os::posix88::{ECANCELED, SIGINT, EINPROGRESS}; -#[cfg(unix)] pub use consts::os::posix88::{ENOSYS, ENOTTY, ETIMEDOUT, EMFILE}; -#[cfg(unix)] pub use consts::os::posix88::{SIGTERM, SIGKILL, SIGPIPE, PROT_NONE}; -#[cfg(unix)] pub use consts::os::posix01::{SIG_IGN, F_GETFL, F_SETFL}; -#[cfg(unix)] pub use consts::os::bsd44::{AF_UNIX}; -#[cfg(unix)] pub use consts::os::extra::{O_NONBLOCK}; - -#[cfg(unix)] pub use types::os::common::posix01::{pthread_t, timespec, timezone}; - -#[cfg(unix)] pub use types::os::arch::posix88::{uid_t, gid_t}; -#[cfg(unix)] pub use types::os::arch::posix01::{pthread_attr_t}; -#[cfg(unix)] pub use types::os::arch::posix01::{stat, utimbuf}; -#[cfg(unix)] pub use types::os::common::bsd44::{ifaddrs}; -#[cfg(unix)] pub use funcs::posix88::unistd::{sysconf, setgid, setsid, setuid, pread, pwrite}; -#[cfg(unix)] pub use funcs::posix88::unistd::{getgid, getuid, getsid}; -#[cfg(unix)] pub use funcs::posix88::unistd::{_PC_NAME_MAX, utime, nanosleep, pathconf, link}; -#[cfg(unix)] pub use funcs::posix88::unistd::{chown}; -#[cfg(unix)] pub use funcs::posix88::mman::{mmap, munmap, mprotect}; -#[cfg(unix)] pub use funcs::posix88::dirent::{opendir, readdir_r, closedir}; -#[cfg(unix)] pub use funcs::posix88::fcntl::{fcntl}; -#[cfg(unix)] pub use funcs::posix88::net::{if_nametoindex}; -#[cfg(unix)] pub use funcs::posix01::stat_::{lstat}; -#[cfg(unix)] pub use funcs::posix01::unistd::{fsync, ftruncate}; -#[cfg(unix)] pub use funcs::posix01::unistd::{readlink, symlink}; -#[cfg(unix)] pub use funcs::bsd43::{getifaddrs, freeifaddrs}; - -#[cfg(windows)] pub use consts::os::c95::{WSAECONNREFUSED, WSAECONNRESET, WSAEACCES}; -#[cfg(windows)] pub use consts::os::c95::{WSAEWOULDBLOCK, WSAENOTCONN, WSAECONNABORTED}; -#[cfg(windows)] pub use consts::os::c95::{WSAEADDRNOTAVAIL, WSAEADDRINUSE, WSAEINTR}; -#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS, WSAEINVAL, WSAEMFILE}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_INSUFFICIENT_BUFFER}; -#[cfg(windows)] pub use consts::os::extra::{O_BINARY, O_NOINHERIT, PAGE_NOACCESS}; -#[cfg(windows)] pub use consts::os::extra::{PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE}; -#[cfg(windows)] pub use consts::os::extra::{PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}; -#[cfg(windows)] pub use consts::os::extra::{MEM_COMMIT, MEM_RESERVE, MEM_RELEASE}; -#[cfg(windows)] pub use consts::os::extra::{FILE_MAP_READ, FILE_MAP_WRITE, FILE_MAP_EXECUTE}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_ALREADY_EXISTS, ERROR_NO_DATA}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_NAME}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_BROKEN_PIPE, ERROR_INVALID_FUNCTION}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_CALL_NOT_IMPLEMENTED}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_NOTHING_TO_TERMINATE}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_INVALID_HANDLE}; -#[cfg(windows)] pub use consts::os::extra::{TRUE, FALSE, INFINITE}; -#[cfg(windows)] pub use consts::os::extra::{PROCESS_TERMINATE, PROCESS_QUERY_INFORMATION}; -#[cfg(windows)] pub use consts::os::extra::{STILL_ACTIVE, DETACHED_PROCESS}; -#[cfg(windows)] pub use consts::os::extra::{CREATE_NEW_PROCESS_GROUP, CREATE_UNICODE_ENVIRONMENT}; -#[cfg(windows)] pub use consts::os::extra::{FILE_BEGIN, FILE_END, FILE_CURRENT}; -#[cfg(windows)] pub use consts::os::extra::{FILE_GENERIC_READ, FILE_GENERIC_WRITE}; -#[cfg(windows)] pub use consts::os::extra::{FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE}; -#[cfg(windows)] pub use consts::os::extra::{TRUNCATE_EXISTING, CREATE_ALWAYS, OPEN_EXISTING}; -#[cfg(windows)] pub use consts::os::extra::{CREATE_NEW, FILE_APPEND_DATA, FILE_WRITE_DATA}; -#[cfg(windows)] pub use consts::os::extra::{OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL}; -#[cfg(windows)] pub use consts::os::extra::{FILE_FLAG_BACKUP_SEMANTICS, INVALID_HANDLE_VALUE}; -#[cfg(windows)] pub use consts::os::extra::{MOVEFILE_REPLACE_EXISTING}; -#[cfg(windows)] pub use consts::os::extra::{GENERIC_READ, GENERIC_WRITE}; -#[cfg(windows)] pub use consts::os::extra::{VOLUME_NAME_DOS}; -#[cfg(windows)] pub use consts::os::extra::{PIPE_ACCESS_DUPLEX, FILE_FLAG_FIRST_PIPE_INSTANCE}; -#[cfg(windows)] pub use consts::os::extra::{FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE}; -#[cfg(windows)] pub use consts::os::extra::{PIPE_READMODE_BYTE, PIPE_WAIT}; -#[cfg(windows)] pub use consts::os::extra::{PIPE_UNLIMITED_INSTANCES, ERROR_ACCESS_DENIED}; -#[cfg(windows)] pub use consts::os::extra::{FILE_WRITE_ATTRIBUTES, FILE_READ_ATTRIBUTES}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_BUSY, ERROR_IO_PENDING}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED, WAIT_OBJECT_0}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_NOT_FOUND}; -#[cfg(windows)] pub use consts::os::extra::{ERROR_OPERATION_ABORTED}; -#[cfg(windows)] pub use consts::os::extra::{FIONBIO}; -#[cfg(windows)] pub use types::os::common::bsd44::{SOCKET}; -#[cfg(windows)] pub use types::os::common::posix01::{stat, utimbuf}; -#[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES}; -#[cfg(windows)] pub use types::os::arch::extra::{LPCSTR, WORD, DWORD, BYTE, FILETIME}; -#[cfg(windows)] pub use types::os::arch::extra::{LARGE_INTEGER, LPVOID, LONG}; -#[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED, LPCWSTR}; -#[cfg(windows)] pub use types::os::arch::extra::{LPOVERLAPPED, SIZE_T, LPDWORD}; -#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES, WIN32_FIND_DATAW}; -#[cfg(windows)] pub use funcs::c95::string::{wcslen}; -#[cfg(windows)] pub use funcs::posix88::stat_::{wstat, wutime, wchmod, wrmdir}; -#[cfg(windows)] pub use funcs::bsd43::{closesocket}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetCurrentDirectoryW, GetLastError}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetEnvironmentVariableW, SetEnvironmentVariableW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetModuleFileNameW, SetCurrentDirectoryW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetSystemInfo, VirtualAlloc, VirtualFree}; -#[cfg(windows)] pub use funcs::extra::kernel32::{CreateFileMappingW, MapViewOfFile}; -#[cfg(windows)] pub use funcs::extra::kernel32::{UnmapViewOfFile, CloseHandle}; -#[cfg(windows)] pub use funcs::extra::kernel32::{WaitForSingleObject, GetSystemTimeAsFileTime}; -#[cfg(windows)] pub use funcs::extra::kernel32::{QueryPerformanceCounter}; -#[cfg(windows)] pub use funcs::extra::kernel32::{QueryPerformanceFrequency}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetExitCodeProcess, TerminateProcess}; -#[cfg(windows)] pub use funcs::extra::kernel32::{ReadFile, WriteFile, SetFilePointerEx}; -#[cfg(windows)] pub use funcs::extra::kernel32::{SetEndOfFile, CreateFileW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{CreateDirectoryW, FindFirstFileW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{FindNextFileW, FindClose, DeleteFileW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{CreateHardLinkW, CreateEventW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{FlushFileBuffers, CreateNamedPipeW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{SetNamedPipeHandleState, WaitNamedPipeW}; -#[cfg(windows)] pub use funcs::extra::kernel32::{GetOverlappedResult, ConnectNamedPipe}; -#[cfg(windows)] pub use funcs::extra::kernel32::{DisconnectNamedPipe, OpenProcess}; -#[cfg(windows)] pub use funcs::extra::kernel32::{MoveFileExW, VirtualProtect}; -#[cfg(windows)] pub use funcs::extra::kernel32::{RemoveDirectoryW}; -#[cfg(windows)] pub use funcs::extra::msvcrt::{get_osfhandle, open_osfhandle}; -#[cfg(windows)] pub use funcs::extra::winsock::{ioctlsocket}; - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd"))] -pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC}; - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use funcs::posix01::unistd::{fdatasync}; -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use types::os::arch::extra::{sockaddr_ll}; -#[cfg(any(target_os = "linux", target_os = "android"))] -pub use consts::os::extra::{AF_PACKET}; - -#[cfg(all(unix, not(any(target_os = "freebsd", target_os = "openbsd"))))] -pub use consts::os::extra::{MAP_STACK}; - -#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] -pub use consts::os::bsd44::{TCP_KEEPIDLE}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub use consts::os::bsd44::{TCP_KEEPALIVE}; -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub use consts::os::extra::{F_FULLFSYNC}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub use types::os::arch::extra::{mach_timebase_info}; - - -#[cfg(not(windows))] +#[cfg(unix)] pub use consts::os::sysconf::*; + +#[cfg(unix)] pub use funcs::posix88::mman::*; +#[cfg(unix)] pub use funcs::posix88::dirent::*; +#[cfg(unix)] pub use funcs::posix88::net::*; +#[cfg(unix)] pub use funcs::posix01::stat_::*; +#[cfg(unix)] pub use funcs::posix01::unistd::*; +#[cfg(unix)] pub use funcs::posix01::resource::*; + + +#[cfg(windows)] pub use funcs::extra::kernel32::*; +#[cfg(windows)] pub use funcs::extra::winsock::*; +#[cfg(windows)] pub use funcs::extra::msvcrt::*; + +// On NaCl, these libraries are static. Thus it would be a Bad Idea to link them +// in when creating a test crate. +#[cfg(not(any(windows, all(target_os = "nacl", test))))] #[link(name = "c")] #[link(name = "m")] extern {} +// libnacl provides functions that require a trip through the IRT to work. +// ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip +// to the kernel. +#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))] +#[link(name = "nacl", kind = "static")] +extern {} + +// pnaclmm provides a number of functions that the toolchain's Clang emits calls +// to when codegening atomic ops. All the functions within wrap various atomic +// operations. +// Yes, it could be linked by rustc explicitly, however by linking it here +// instead we save a bit of time where bins are involved (by not running the +// optimizations on the whole pnaclmm foreach binary built). +#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))] +#[link(name = "pnaclmm", kind = "static")] +extern {} + pub mod types { // Types tend to vary *per architecture* so we pull their definitions out @@ -361,7 +212,7 @@ pub mod types { // Standard types that are scalar but vary by OS and arch. - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] pub mod os { pub mod common { pub mod posix01 { @@ -369,10 +220,14 @@ pub mod types { use types::os::arch::c95::{c_char, c_ulong, size_t, time_t, suseconds_t, c_long}; + #[cfg(not(target_os = "nacl"))] pub type pthread_t = c_ulong; + #[cfg(target_os = "nacl")] + pub type pthread_t = *mut c_void; + pub type rlim_t = u64; #[repr(C)] - #[derive(Copy)] pub struct glob_t { + #[derive(Copy, Clone)] pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, @@ -385,21 +240,56 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct timeval { + #[derive(Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - #[derive(Copy)] pub struct timespec { + #[derive(Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - #[derive(Copy)] pub enum timezone {} + pub enum timezone {} pub type sighandler_t = size_t; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, + } + } + + pub mod bsd43 { + use types::os::common::posix01::timeval; + use types::os::arch::c95::c_long; + // This is also specified in POSIX 2001, but only has two fields. All implementors + // implement BSD 4.3 version. + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rusage { + pub ru_utime: timeval, + pub ru_stime: timeval, + pub ru_maxrss: c_long, + pub ru_ixrss: c_long, + pub ru_idrss: c_long, + pub ru_isrss: c_long, + pub ru_minflt: c_long, + pub ru_majflt: c_long, + pub ru_nswap: c_long, + pub ru_inblock: c_long, + pub ru_oublock: c_long, + pub ru_msgsnd: c_long, + pub ru_msgrcv: c_long, + pub ru_nsignals: c_long, + pub ru_nvcsw: c_long, + pub ru_nivcsw: c_long + } } + pub mod bsd44 { use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; @@ -409,29 +299,35 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - #[derive(Copy)] pub struct sockaddr { + #[derive(Copy, Clone)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8; 14], } #[repr(C)] #[derive(Copy)] pub struct sockaddr_storage { pub ss_family: sa_family_t, - pub __ss_align: i64, - pub __ss_pad2: [u8; 112], + pub __ss_align: isize, + #[cfg(target_pointer_width = "32")] + pub __ss_pad2: [u8; 128 - 2 * 4], + #[cfg(target_pointer_width = "64")] + pub __ss_pad2: [u8; 128 - 2 * 8], + } + impl ::core::clone::Clone for sockaddr_storage { + fn clone(&self) -> sockaddr_storage { *self } } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in { + #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8; 8], } #[repr(C)] - #[derive(Copy)] pub struct in_addr { + #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in6 { + #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, @@ -439,21 +335,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - #[derive(Copy)] pub struct in6_addr { + #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u16; 8] } #[repr(C)] - #[derive(Copy)] pub struct ip_mreq { + #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - #[derive(Copy)] pub struct ip6_mreq { + #[derive(Copy, Clone)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - #[derive(Copy)] pub struct addrinfo { + #[derive(Copy, Clone)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -466,10 +362,10 @@ pub mod types { #[cfg(target_os = "linux")] pub ai_canonname: *mut c_char, - #[cfg(target_os = "android")] + #[cfg(any(target_os = "android", target_os = "nacl"))] pub ai_canonname: *mut c_char, - #[cfg(target_os = "android")] + #[cfg(any(target_os = "android", target_os = "nacl"))] pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, @@ -479,9 +375,12 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char; 108] } + impl ::core::clone::Clone for sockaddr_un { + fn clone(&self) -> sockaddr_un { *self } + } #[repr(C)] - #[derive(Copy)] pub struct ifaddrs { + #[derive(Copy, Clone)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -498,7 +397,8 @@ pub mod types { target_arch = "arm", target_arch = "mips", target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "powerpc", + target_arch = "le32"))] pub mod arch { pub mod c95 { pub type c_char = i8; @@ -530,7 +430,9 @@ pub mod types { #[cfg(any(target_arch = "x86", target_arch = "mips", target_arch = "mipsel", - target_arch = "powerpc"))] + target_arch = "powerpc", + target_arch = "le32", + all(target_arch = "arm", not(target_os = "android"))))] pub mod posix88 { pub type off_t = i32; pub type dev_t = u64; @@ -542,7 +444,7 @@ pub mod types { pub type mode_t = u32; pub type ssize_t = i32; } - #[cfg(target_arch = "arm")] + #[cfg(all(target_arch = "arm", target_os = "android"))] pub mod posix88 { pub type off_t = i32; pub type dev_t = u32; @@ -555,7 +457,9 @@ pub mod types { pub type ssize_t = i32; } #[cfg(any(target_arch = "x86", - target_arch = "powerpc"))] + target_arch = "le32", + target_arch = "powerpc", + all(target_arch = "arm", not(target_os = "android"))))] pub mod posix01 { use types::os::arch::c95::{c_short, c_long, time_t}; use types::os::arch::posix88::{dev_t, gid_t, ino_t}; @@ -567,7 +471,7 @@ pub mod types { pub type blkcnt_t = i32; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub __pad1: c_short, pub st_ino: ino_t, @@ -591,17 +495,17 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - #[derive(Copy)] pub struct pthread_attr_t { + #[derive(Copy, Clone)] pub struct pthread_attr_t { pub __size: [u32; 9] } } - #[cfg(target_arch = "arm")] + #[cfg(all(target_arch = "arm", target_os = "android"))] pub mod posix01 { use types::os::arch::c95::{c_uchar, c_uint, c_ulong, time_t}; use types::os::arch::c99::{c_longlong, c_ulonglong}; @@ -612,7 +516,7 @@ pub mod types { pub type blkcnt_t = u32; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: c_ulonglong, pub __pad0: [c_uchar; 4], pub __st_ino: ino_t, @@ -635,13 +539,13 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - #[derive(Copy)] pub struct pthread_attr_t { + #[derive(Copy, Clone)] pub struct pthread_attr_t { pub __size: [u32; 9] } } @@ -658,7 +562,7 @@ pub mod types { pub type blkcnt_t = i32; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: c_ulong, pub st_pad1: [c_long; 3], pub st_ino: ino_t, @@ -682,13 +586,13 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - #[derive(Copy)] pub struct pthread_attr_t { + #[derive(Copy, Clone)] pub struct pthread_attr_t { pub __size: [u32; 9] } } @@ -697,7 +601,7 @@ pub mod types { pub mod extra { use types::os::arch::c95::{c_ushort, c_int, c_uchar}; #[repr(C)] - #[derive(Copy)] pub struct sockaddr_ll { + #[derive(Copy, Clone)] pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, pub sll_ifindex: c_int, @@ -769,7 +673,7 @@ pub mod types { pub type blkcnt_t = i64; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_nlink: nlink_t, @@ -791,13 +695,13 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - #[derive(Copy)] pub struct pthread_attr_t { + #[derive(Copy, Clone)] pub struct pthread_attr_t { pub __size: [u64; 7] } } @@ -813,7 +717,7 @@ pub mod types { pub type blkcnt_t = i64; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, @@ -836,13 +740,13 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } #[repr(C)] - #[derive(Copy)] pub struct pthread_attr_t { + #[derive(Copy, Clone)] pub struct pthread_attr_t { pub __size: [u64; 8] } } @@ -852,7 +756,7 @@ pub mod types { } pub mod extra { use types::os::arch::c95::{c_ushort, c_int, c_uchar}; - #[derive(Copy)] pub struct sockaddr_ll { + #[derive(Copy, Clone)] pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, pub sll_ifindex: c_int, @@ -876,9 +780,10 @@ pub mod types { use types::os::arch::c99::{uintptr_t}; pub type pthread_t = uintptr_t; + pub type rlim_t = i64; #[repr(C)] - #[derive(Copy)] pub struct glob_t { + #[derive(Copy, Clone)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: size_t, pub gl_offs: size_t, @@ -895,21 +800,54 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct timeval { + #[derive(Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - #[derive(Copy)] pub struct timespec { + #[derive(Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - #[derive(Copy)] pub enum timezone {} + pub enum timezone {} pub type sighandler_t = size_t; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, + } } + + pub mod bsd43 { + use types::os::common::posix01::timeval; + use types::os::arch::c95::c_long; + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rusage { + pub ru_utime: timeval, + pub ru_stime: timeval, + pub ru_maxrss: c_long, + pub ru_ixrss: c_long, + pub ru_idrss: c_long, + pub ru_isrss: c_long, + pub ru_minflt: c_long, + pub ru_majflt: c_long, + pub ru_nswap: c_long, + pub ru_inblock: c_long, + pub ru_oublock: c_long, + pub ru_msgsnd: c_long, + pub ru_msgrcv: c_long, + pub ru_nsignals: c_long, + pub ru_nvcsw: c_long, + pub ru_nivcsw: c_long + } + } + pub mod bsd44 { use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; @@ -919,13 +857,13 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - #[derive(Copy)] pub struct sockaddr { + #[derive(Copy, Clone)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8; 14], } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_storage { + #[derive(Copy, Clone)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, pub __ss_pad1: [u8; 6], @@ -933,7 +871,7 @@ pub mod types { pub __ss_pad2: [u8; 112], } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in { + #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, @@ -941,11 +879,11 @@ pub mod types { pub sin_zero: [u8; 8], } #[repr(C)] - #[derive(Copy)] pub struct in_addr { + #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in6 { + #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -954,21 +892,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - #[derive(Copy)] pub struct in6_addr { + #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u16; 8] } #[repr(C)] - #[derive(Copy)] pub struct ip_mreq { + #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - #[derive(Copy)] pub struct ip6_mreq { + #[derive(Copy, Clone)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - #[derive(Copy)] pub struct addrinfo { + #[derive(Copy, Clone)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -979,13 +917,13 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_un { + #[derive(Copy, Clone)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104] } #[repr(C)] - #[derive(Copy)] pub struct ifaddrs { + #[derive(Copy, Clone)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -1052,7 +990,7 @@ pub mod types { pub type blkcnt_t = i64; pub type fflags_t = u32; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, @@ -1078,7 +1016,7 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -1104,9 +1042,10 @@ pub mod types { use types::os::arch::c99::{uintptr_t}; pub type pthread_t = uintptr_t; + pub type rlim_t = i64; #[repr(C)] - #[derive(Copy)] pub struct glob_t { + #[derive(Copy, Clone)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: size_t, pub gl_offs: size_t, @@ -1123,21 +1062,54 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct timeval { + #[derive(Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - #[derive(Copy)] pub struct timespec { + #[derive(Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - #[derive(Copy)] pub enum timezone {} + pub enum timezone {} pub type sighandler_t = size_t; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, + } } + + pub mod bsd43 { + use types::os::common::posix01::timeval; + use types::os::arch::c95::c_long; + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rusage { + pub ru_utime: timeval, + pub ru_stime: timeval, + pub ru_maxrss: c_long, + pub ru_ixrss: c_long, + pub ru_idrss: c_long, + pub ru_isrss: c_long, + pub ru_minflt: c_long, + pub ru_majflt: c_long, + pub ru_nswap: c_long, + pub ru_inblock: c_long, + pub ru_oublock: c_long, + pub ru_msgsnd: c_long, + pub ru_msgrcv: c_long, + pub ru_nsignals: c_long, + pub ru_nvcsw: c_long, + pub ru_nivcsw: c_long + } + } + pub mod bsd44 { use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; @@ -1147,13 +1119,13 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - #[derive(Copy)] pub struct sockaddr { + #[derive(Copy, Clone)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8; 14], } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_storage { + #[derive(Copy, Clone)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, pub __ss_pad1: [u8; 6], @@ -1161,7 +1133,7 @@ pub mod types { pub __ss_pad2: [u8; 112], } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in { + #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, @@ -1169,11 +1141,11 @@ pub mod types { pub sin_zero: [u8; 8], } #[repr(C)] - #[derive(Copy)] pub struct in_addr { + #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in6 { + #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -1182,21 +1154,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - #[derive(Copy)] pub struct in6_addr { + #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u16; 8] } #[repr(C)] - #[derive(Copy)] pub struct ip_mreq { + #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - #[derive(Copy)] pub struct ip6_mreq { + #[derive(Copy, Clone)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - #[derive(Copy)] pub struct addrinfo { + #[derive(Copy, Clone)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -1207,13 +1179,13 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_un { + #[derive(Copy, Clone)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104] } #[repr(C)] - #[derive(Copy)] pub struct ifaddrs { + #[derive(Copy, Clone)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -1258,7 +1230,6 @@ pub mod types { pub mod posix88 { pub type off_t = i64; pub type dev_t = u32; - pub type ino_t = u32; pub type pid_t = i32; pub type uid_t = u32; pub type gid_t = u32; @@ -1281,7 +1252,7 @@ pub mod types { pub type fflags_t = u32; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_ino: ino_t, pub st_nlink: nlink_t, pub st_dev: dev_t, @@ -1306,7 +1277,7 @@ pub mod types { pub st_qspare2: int64_t, } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -1322,7 +1293,7 @@ pub mod types { } } - #[cfg(target_os = "openbsd")] + #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] pub mod os { pub mod common { pub mod posix01 { @@ -1332,9 +1303,28 @@ pub mod types { use types::os::arch::c99::{uintptr_t}; pub type pthread_t = uintptr_t; + pub type rlim_t = u64; + + #[cfg(target_os = "bitrig")] + #[repr(C)] + #[derive(Copy, Clone)] pub struct glob_t { + pub gl_pathc: c_int, + pub gl_matchc: c_int, + pub gl_offs: c_int, + pub gl_flags: c_int, + pub gl_pathv: *mut *mut c_char, + pub __unused1: *mut c_void, + pub __unused2: *mut c_void, + pub __unused3: *mut c_void, + pub __unused4: *mut c_void, + pub __unused5: *mut c_void, + pub __unused6: *mut c_void, + pub __unused7: *mut c_void, + } + #[cfg(target_os = "openbsd")] #[repr(C)] - #[derive(Copy)] pub struct glob_t { + #[derive(Copy, Clone)] pub struct glob_t { pub gl_pathc: c_int, pub __unused1: c_int, pub gl_offs: c_int, @@ -1352,21 +1342,54 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct timeval { + #[derive(Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - #[derive(Copy)] pub struct timespec { + #[derive(Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - #[derive(Copy)] pub enum timezone {} + pub enum timezone {} pub type sighandler_t = size_t; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, + } } + + pub mod bsd43 { + use types::os::common::posix01::timeval; + use types::os::arch::c95::c_long; + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rusage { + pub ru_utime: timeval, + pub ru_stime: timeval, + pub ru_maxrss: c_long, + pub ru_ixrss: c_long, + pub ru_idrss: c_long, + pub ru_isrss: c_long, + pub ru_minflt: c_long, + pub ru_majflt: c_long, + pub ru_nswap: c_long, + pub ru_inblock: c_long, + pub ru_oublock: c_long, + pub ru_msgsnd: c_long, + pub ru_msgrcv: c_long, + pub ru_nsignals: c_long, + pub ru_nvcsw: c_long, + pub ru_nivcsw: c_long + } + } + pub mod bsd44 { use types::common::c95::{c_void}; use types::os::arch::c95::{c_char, c_int, c_uint}; @@ -1376,13 +1399,13 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - #[derive(Copy)] pub struct sockaddr { + #[derive(Copy, Clone)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8; 14], } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_storage { + #[derive(Copy, Clone)] pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, pub __ss_pad1: [u8; 6], @@ -1390,7 +1413,7 @@ pub mod types { pub __ss_pad3: [u8; 240], } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in { + #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, @@ -1398,11 +1421,11 @@ pub mod types { pub sin_zero: [u8; 8], } #[repr(C)] - #[derive(Copy)] pub struct in_addr { + #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in6 { + #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -1411,21 +1434,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - #[derive(Copy)] pub struct in6_addr { + #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u16; 8] } #[repr(C)] - #[derive(Copy)] pub struct ip_mreq { + #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - #[derive(Copy)] pub struct ip6_mreq { + #[derive(Copy, Clone)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - #[derive(Copy)] pub struct addrinfo { + #[derive(Copy, Clone)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -1436,13 +1459,13 @@ pub mod types { pub ai_next: *mut addrinfo, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_un { + #[derive(Copy, Clone)] pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104] } #[repr(C)] - #[derive(Copy)] pub struct ifaddrs { + #[derive(Copy, Clone)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -1451,7 +1474,6 @@ pub mod types { pub ifa_dstaddr: *mut sockaddr, pub ifa_data: *mut c_void } - } } @@ -1485,15 +1507,15 @@ pub mod types { pub type uintmax_t = u64; } pub mod posix88 { + use types::os::arch::c95::{c_long}; pub type off_t = i64; - pub type dev_t = u32; - pub type ino_t = u64; + pub type dev_t = i32; pub type pid_t = i32; pub type uid_t = u32; pub type gid_t = u32; pub type useconds_t = u32; pub type mode_t = u32; - pub type ssize_t = i64; + pub type ssize_t = c_long; } pub mod posix01 { use types::common::c95::{c_void}; @@ -1503,14 +1525,14 @@ pub mod types { use types::os::arch::posix88::{mode_t, off_t}; use types::os::arch::posix88::{uid_t}; - pub type nlink_t = u32; + pub type nlink_t = uint32_t; pub type blksize_t = uint32_t; pub type ino_t = uint64_t; pub type blkcnt_t = i64; pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_mode: mode_t, pub st_dev: dev_t, pub st_ino: ino_t, @@ -1533,7 +1555,7 @@ pub mod types { pub st_birthtime_nsec: c_long, } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -1560,7 +1582,7 @@ pub mod types { // pub Note: this is the struct called stat64 in Windows. Not stat, // nor stati64. #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: u16, @@ -1576,24 +1598,24 @@ pub mod types { // note that this is called utimbuf64 in Windows #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time64_t, pub modtime: time64_t, } #[repr(C)] - #[derive(Copy)] pub struct timeval { + #[derive(Copy, Clone)] pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, } #[repr(C)] - #[derive(Copy)] pub struct timespec { + #[derive(Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - #[derive(Copy)] pub enum timezone {} + pub enum timezone {} } pub mod bsd44 { @@ -1606,7 +1628,7 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - #[derive(Copy)] pub struct sockaddr { + #[derive(Copy, Clone)] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8; 14], } @@ -1617,19 +1639,22 @@ pub mod types { pub __ss_align: i64, pub __ss_pad2: [u8; 112], } + impl ::core::clone::Clone for sockaddr_storage { + fn clone(&self) -> sockaddr_storage { *self } + } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in { + #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8; 8], } #[repr(C)] - #[derive(Copy)] pub struct in_addr { + #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in6 { + #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, @@ -1637,21 +1662,21 @@ pub mod types { pub sin6_scope_id: u32, } #[repr(C)] - #[derive(Copy)] pub struct in6_addr { + #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u16; 8] } #[repr(C)] - #[derive(Copy)] pub struct ip_mreq { + #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - #[derive(Copy)] pub struct ip6_mreq { + #[derive(Copy, Clone)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - #[derive(Copy)] pub struct addrinfo { + #[derive(Copy, Clone)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -1666,6 +1691,9 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char; 108] } + impl ::core::clone::Clone for sockaddr_un { + fn clone(&self) -> sockaddr_un { *self } + } } } @@ -1791,7 +1819,7 @@ pub mod types { pub type LPCH = *mut CHAR; #[repr(C)] - #[derive(Copy)] pub struct SECURITY_ATTRIBUTES { + #[derive(Copy, Clone)] pub struct SECURITY_ATTRIBUTES { pub nLength: DWORD, pub lpSecurityDescriptor: LPVOID, pub bInheritHandle: BOOL, @@ -1815,7 +1843,7 @@ pub mod types { pub type int64 = i64; #[repr(C)] - #[derive(Copy)] pub struct STARTUPINFO { + #[derive(Copy, Clone)] pub struct STARTUPINFO { pub cb: DWORD, pub lpReserved: LPWSTR, pub lpDesktop: LPWSTR, @@ -1838,7 +1866,7 @@ pub mod types { pub type LPSTARTUPINFO = *mut STARTUPINFO; #[repr(C)] - #[derive(Copy)] pub struct PROCESS_INFORMATION { + #[derive(Copy, Clone)] pub struct PROCESS_INFORMATION { pub hProcess: HANDLE, pub hThread: HANDLE, pub dwProcessId: DWORD, @@ -1847,7 +1875,7 @@ pub mod types { pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; #[repr(C)] - #[derive(Copy)] pub struct SYSTEM_INFO { + #[derive(Copy, Clone)] pub struct SYSTEM_INFO { pub wProcessorArchitecture: WORD, pub wReserved: WORD, pub dwPageSize: DWORD, @@ -1863,7 +1891,7 @@ pub mod types { pub type LPSYSTEM_INFO = *mut SYSTEM_INFO; #[repr(C)] - #[derive(Copy)] pub struct MEMORY_BASIC_INFORMATION { + #[derive(Copy, Clone)] pub struct MEMORY_BASIC_INFORMATION { pub BaseAddress: LPVOID, pub AllocationBase: LPVOID, pub AllocationProtect: DWORD, @@ -1875,7 +1903,7 @@ pub mod types { pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION; #[repr(C)] - #[derive(Copy)] pub struct OVERLAPPED { + #[derive(Copy, Clone)] pub struct OVERLAPPED { pub Internal: *mut c_ulong, pub InternalHigh: *mut c_ulong, pub Offset: DWORD, @@ -1886,7 +1914,7 @@ pub mod types { pub type LPOVERLAPPED = *mut OVERLAPPED; #[repr(C)] - #[derive(Copy)] pub struct FILETIME { + #[derive(Copy, Clone)] pub struct FILETIME { pub dwLowDateTime: DWORD, pub dwHighDateTime: DWORD, } @@ -1894,7 +1922,7 @@ pub mod types { pub type LPFILETIME = *mut FILETIME; #[repr(C)] - #[derive(Copy)] pub struct GUID { + #[derive(Copy, Clone)] pub struct GUID { pub Data1: DWORD, pub Data2: WORD, pub Data3: WORD, @@ -1902,7 +1930,7 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct WSAPROTOCOLCHAIN { + #[derive(Copy, Clone)] pub struct WSAPROTOCOLCHAIN { pub ChainLen: c_int, pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize], } @@ -1932,6 +1960,9 @@ pub mod types { pub dwProviderReserved: DWORD, pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1], } + impl ::core::clone::Clone for WSAPROTOCOL_INFO { + fn clone(&self) -> WSAPROTOCOL_INFO { *self } + } pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; @@ -1950,6 +1981,9 @@ pub mod types { pub cFileName: [wchar_t; 260], // #define MAX_PATH 260 pub cAlternateFileName: [wchar_t; 14], } + impl ::core::clone::Clone for WIN32_FIND_DATAW { + fn clone(&self) -> WIN32_FIND_DATAW { *self } + } pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW; } @@ -1966,9 +2000,10 @@ pub mod types { use types::os::arch::c99::{uintptr_t}; pub type pthread_t = uintptr_t; + pub type rlim_t = u64; #[repr(C)] - #[derive(Copy)] pub struct glob_t { + #[derive(Copy, Clone)] pub struct glob_t { pub gl_pathc: size_t, pub __unused1: c_int, pub gl_offs: size_t, @@ -1985,20 +2020,52 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct timeval { + #[derive(Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] - #[derive(Copy)] pub struct timespec { + #[derive(Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } - #[derive(Copy)] pub enum timezone {} + pub enum timezone {} pub type sighandler_t = size_t; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, + } + } + + pub mod bsd43 { + use types::os::common::posix01::timeval; + use types::os::arch::c95::c_long; + #[repr(C)] + #[derive(Copy, Clone)] + pub struct rusage { + pub ru_utime: timeval, + pub ru_stime: timeval, + pub ru_maxrss: c_long, + pub ru_ixrss: c_long, + pub ru_idrss: c_long, + pub ru_isrss: c_long, + pub ru_minflt: c_long, + pub ru_majflt: c_long, + pub ru_nswap: c_long, + pub ru_inblock: c_long, + pub ru_oublock: c_long, + pub ru_msgsnd: c_long, + pub ru_msgrcv: c_long, + pub ru_nsignals: c_long, + pub ru_nvcsw: c_long, + pub ru_nivcsw: c_long + } } pub mod bsd44 { @@ -2010,7 +2077,7 @@ pub mod types { pub type in_port_t = u16; pub type in_addr_t = u32; #[repr(C)] - #[derive(Copy)] pub struct sockaddr { + #[derive(Copy, Clone)] pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8; 14], @@ -2024,9 +2091,12 @@ pub mod types { pub __ss_align: i64, pub __ss_pad2: [u8; 112], } + impl ::core::clone::Clone for sockaddr_storage { + fn clone(&self) -> sockaddr_storage { *self } + } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in { + #[derive(Copy, Clone)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, @@ -2035,12 +2105,12 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct in_addr { + #[derive(Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[repr(C)] - #[derive(Copy)] pub struct sockaddr_in6 { + #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, @@ -2050,24 +2120,24 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct in6_addr { + #[derive(Copy, Clone)] pub struct in6_addr { pub s6_addr: [u16; 8] } #[repr(C)] - #[derive(Copy)] pub struct ip_mreq { + #[derive(Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(C)] - #[derive(Copy)] pub struct ip6_mreq { + #[derive(Copy, Clone)] pub struct ip6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } #[repr(C)] - #[derive(Copy)] pub struct addrinfo { + #[derive(Copy, Clone)] pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, @@ -2084,9 +2154,12 @@ pub mod types { pub sun_family: sa_family_t, pub sun_path: [c_char; 104] } + impl ::core::clone::Clone for sockaddr_un { + fn clone(&self) -> sockaddr_un { *self } + } #[repr(C)] - #[derive(Copy)] pub struct ifaddrs { + #[derive(Copy, Clone)] pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, @@ -2151,7 +2224,7 @@ pub mod types { pub type blkcnt_t = i64; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, pub st_nlink: nlink_t, @@ -2177,7 +2250,7 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -2187,6 +2260,9 @@ pub mod types { pub __sig: c_long, pub __opaque: [c_char; 36] } + impl ::core::clone::Clone for pthread_attr_t { + fn clone(&self) -> pthread_attr_t { *self } + } } pub mod posix08 { } @@ -2194,7 +2270,7 @@ pub mod types { } pub mod extra { #[repr(C)] - #[derive(Copy)] pub struct mach_timebase_info { + #[derive(Copy, Clone)] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, } @@ -2257,7 +2333,7 @@ pub mod types { pub type blkcnt_t = i64; #[repr(C)] - #[derive(Copy)] pub struct stat { + #[derive(Copy, Clone)] pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, pub st_nlink: nlink_t, @@ -2283,7 +2359,7 @@ pub mod types { } #[repr(C)] - #[derive(Copy)] pub struct utimbuf { + #[derive(Copy, Clone)] pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } @@ -2293,6 +2369,9 @@ pub mod types { pub __sig: c_long, pub __opaque: [c_char; 56] } + impl ::core::clone::Clone for pthread_attr_t { + fn clone(&self) -> pthread_attr_t { *self } + } } pub mod posix08 { } @@ -2300,7 +2379,7 @@ pub mod types { } pub mod extra { #[repr(C)] - #[derive(Copy)] pub struct mach_timebase_info { + #[derive(Copy, Clone)] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, } @@ -2330,11 +2409,11 @@ pub mod consts { pub const _IOFBF : c_int = 0; pub const _IONBF : c_int = 4; pub const _IOLBF : c_int = 64; - pub const BUFSIZ : c_uint = 512_u32; - pub const FOPEN_MAX : c_uint = 20_u32; - pub const FILENAME_MAX : c_uint = 260_u32; - pub const L_tmpnam : c_uint = 16_u32; - pub const TMP_MAX : c_uint = 32767_u32; + pub const BUFSIZ : c_uint = 512; + pub const FOPEN_MAX : c_uint = 20; + pub const FILENAME_MAX : c_uint = 260; + pub const L_tmpnam : c_uint = 16; + pub const TMP_MAX : c_uint = 32767; pub const WSAEINTR: c_int = 10004; pub const WSAEBADF: c_int = 10009; @@ -2393,6 +2472,7 @@ pub mod consts { } pub mod posix88 { use types::os::arch::c95::c_int; + use types::os::arch::posix88::mode_t; pub const O_RDONLY : c_int = 0; pub const O_WRONLY : c_int = 1; @@ -2415,6 +2495,14 @@ pub mod consts { pub const S_IXUSR : c_int = 64; pub const S_IWUSR : c_int = 128; pub const S_IRUSR : c_int = 256; + pub const S_IRWXG : mode_t = 56; + pub const S_IXGRP : mode_t = 8; + pub const S_IWGRP : mode_t = 16; + pub const S_IRGRP : mode_t = 32; + pub const S_IRWXO : mode_t = 7; + pub const S_IXOTH : mode_t = 1; + pub const S_IWOTH : mode_t = 2; + pub const S_IROTH : mode_t = 4; pub const F_OK : c_int = 0; pub const R_OK : c_int = 4; pub const W_OK : c_int = 2; @@ -2449,10 +2537,24 @@ pub mod consts { pub const TCP_NODELAY: c_int = 0x0001; pub const SOL_SOCKET: c_int = 0xffff; - pub const SO_KEEPALIVE: c_int = 8; - pub const SO_BROADCAST: c_int = 32; - pub const SO_REUSEADDR: c_int = 4; + + pub const SO_DEBUG: c_int = 0x0001; + pub const SO_ACCEPTCONN: c_int = 0x0002; + pub const SO_REUSEADDR: c_int = 0x0004; + pub const SO_KEEPALIVE: c_int = 0x0008; + pub const SO_DONTROUTE: c_int = 0x0010; + pub const SO_BROADCAST: c_int = 0x0020; + pub const SO_USELOOPBACK: c_int = 0x0040; + pub const SO_LINGER: c_int = 0x0080; + pub const SO_OOBINLINE: c_int = 0x0100; + pub const SO_SNDBUF: c_int = 0x1001; + pub const SO_RCVBUF: c_int = 0x1002; + pub const SO_SNDLOWAT: c_int = 0x1003; + pub const SO_RCVLOWAT: c_int = 0x1004; + pub const SO_SNDTIMEO: c_int = 0x1005; + pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; + pub const SO_TYPE: c_int = 0x1008; pub const IFF_LOOPBACK: c_int = 4; @@ -2461,7 +2563,7 @@ pub mod consts { pub const SHUT_RDWR: c_int = 2; } pub mod extra { - use SOCKET; + use types::os::common::bsd44::SOCKET; use types::os::arch::c95::{c_int, c_long}; use types::os::arch::extra::{WORD, DWORD, BOOL, HANDLE}; @@ -2492,7 +2594,7 @@ pub mod consts { pub const ERROR_IO_PENDING: c_int = 997; pub const ERROR_FILE_INVALID : c_int = 1006; pub const ERROR_NOT_FOUND: c_int = 1168; - pub const INVALID_HANDLE_VALUE: HANDLE = -1 as HANDLE; + pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; pub const DELETE : DWORD = 0x00010000; pub const READ_CONTROL : DWORD = 0x00020000; @@ -2530,12 +2632,12 @@ pub mod consts { pub const WAIT_ABANDONED : DWORD = 0x00000080; pub const WAIT_OBJECT_0 : DWORD = 0x00000000; pub const WAIT_TIMEOUT : DWORD = 0x00000102; - pub const WAIT_FAILED : DWORD = -1; + pub const WAIT_FAILED : DWORD = !0; pub const DUPLICATE_CLOSE_SOURCE : DWORD = 0x00000001; pub const DUPLICATE_SAME_ACCESS : DWORD = 0x00000002; - pub const INFINITE : DWORD = -1; + pub const INFINITE : DWORD = !0; pub const STILL_ACTIVE : DWORD = 259; pub const MEM_COMMIT : DWORD = 0x00001000; @@ -2696,7 +2798,7 @@ pub mod consts { } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] pub mod os { pub mod c95 { use types::os::arch::c95::{c_int, c_uint}; @@ -2711,11 +2813,11 @@ pub mod consts { pub const _IOFBF : c_int = 0; pub const _IONBF : c_int = 2; pub const _IOLBF : c_int = 1; - pub const BUFSIZ : c_uint = 8192_u32; - pub const FOPEN_MAX : c_uint = 16_u32; - pub const FILENAME_MAX : c_uint = 4096_u32; - pub const L_tmpnam : c_uint = 20_u32; - pub const TMP_MAX : c_uint = 238328_u32; + pub const BUFSIZ : c_uint = 8192; + pub const FOPEN_MAX : c_uint = 16; + pub const FILENAME_MAX : c_uint = 4096; + pub const L_tmpnam : c_uint = 20; + pub const TMP_MAX : c_uint = 238328; } pub mod c99 { } @@ -2723,6 +2825,7 @@ pub mod consts { target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", + target_arch = "le32", target_arch = "powerpc"))] pub mod posix88 { use types::os::arch::c95::c_int; @@ -2750,6 +2853,14 @@ pub mod consts { pub const S_IXUSR : mode_t = 64; pub const S_IWUSR : mode_t = 128; pub const S_IRUSR : mode_t = 256; + pub const S_IRWXG : mode_t = 56; + pub const S_IXGRP : mode_t = 8; + pub const S_IWGRP : mode_t = 16; + pub const S_IRGRP : mode_t = 32; + pub const S_IRWXO : mode_t = 7; + pub const S_IXOTH : mode_t = 1; + pub const S_IWOTH : mode_t = 2; + pub const S_IROTH : mode_t = 4; pub const F_OK : c_int = 0; pub const R_OK : c_int = 4; pub const W_OK : c_int = 2; @@ -2784,7 +2895,7 @@ pub mod consts { pub const MAP_FIXED : c_int = 0x0010; pub const MAP_ANON : c_int = 0x0020; - pub const MAP_FAILED : *mut c_void = -1 as *mut c_void; + pub const MAP_FAILED : *mut c_void = !0 as *mut c_void; pub const MCL_CURRENT : c_int = 0x0001; pub const MCL_FUTURE : c_int = 0x0002; @@ -2963,6 +3074,14 @@ pub mod consts { pub const S_IXUSR : mode_t = 64; pub const S_IWUSR : mode_t = 128; pub const S_IRUSR : mode_t = 256; + pub const S_IRWXG : mode_t = 56; + pub const S_IXGRP : mode_t = 8; + pub const S_IWGRP : mode_t = 16; + pub const S_IRGRP : mode_t = 32; + pub const S_IRWXO : mode_t = 7; + pub const S_IXOTH : mode_t = 1; + pub const S_IWOTH : mode_t = 2; + pub const S_IROTH : mode_t = 4; pub const F_OK : c_int = 0; pub const R_OK : c_int = 4; pub const W_OK : c_int = 2; @@ -3146,8 +3265,10 @@ pub mod consts { pub const EDQUOT: c_int = 1133; } + #[cfg(not(target_os = "nacl"))] pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + use types::os::common::posix01::rlim_t; pub const F_DUPFD : c_int = 0; pub const F_GETFD : c_int = 1; @@ -3156,7 +3277,6 @@ pub mod consts { pub const F_SETFL : c_int = 4; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_ERR : c_int = 1 << 0; @@ -3227,6 +3347,126 @@ pub mod consts { pub const CLOCK_REALTIME: c_int = 0; pub const CLOCK_MONOTONIC: c_int = 1; + + pub const RLIMIT_CPU: c_int = 0; + pub const RLIMIT_FSIZE: c_int = 1; + pub const RLIMIT_DATA: c_int = 2; + pub const RLIMIT_STACK: c_int = 3; + pub const RLIMIT_CORE: c_int = 4; + pub const RLIMIT_RSS: c_int = 5; + pub const RLIMIT_NOFILE: c_int = 7; + pub const RLIMIT_AS: c_int = 9; + pub const RLIMIT_NPROC: c_int = 6; + pub const RLIMIT_MEMLOCK: c_int = 8; + pub const RLIMIT_LOCKS: c_int = 10; + pub const RLIMIT_SIGPENDING: c_int = 11; + pub const RLIMIT_MSGQUEUE: c_int = 12; + pub const RLIMIT_NICE: c_int = 13; + pub const RLIMIT_RTPRIO: c_int = 14; + pub const RLIMIT_RTTIME: c_int = 15; + pub const RLIMIT_NLIMITS: c_int = 16; + pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff; + pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; + pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; + + pub const RUSAGE_SELF: c_int = 0; + pub const RUSAGE_CHILDREN: c_int = -1; + pub const RUSAGE_THREAD: c_int = 1; + } + #[cfg(target_os = "nacl")] + pub mod posix01 { + use types::os::arch::c95::{c_int, size_t}; + use types::os::common::posix01::rlim_t; + + pub const F_DUPFD : c_int = 0; + pub const F_GETFD : c_int = 1; + pub const F_SETFD : c_int = 2; + pub const F_GETFL : c_int = 3; + pub const F_SETFL : c_int = 4; + + pub const SIGTRAP : c_int = 5; + pub const SIG_IGN: size_t = 1; + + pub const GLOB_ERR : c_int = 1 << 0; + pub const GLOB_MARK : c_int = 1 << 1; + pub const GLOB_NOSORT : c_int = 1 << 2; + pub const GLOB_DOOFFS : c_int = 1 << 3; + pub const GLOB_NOCHECK : c_int = 1 << 4; + pub const GLOB_APPEND : c_int = 1 << 5; + pub const GLOB_NOESCAPE : c_int = 1 << 6; + + pub const GLOB_NOSPACE : c_int = 1; + pub const GLOB_ABORTED : c_int = 2; + pub const GLOB_NOMATCH : c_int = 3; + + pub const POSIX_MADV_NORMAL : c_int = 0; + pub const POSIX_MADV_RANDOM : c_int = 1; + pub const POSIX_MADV_SEQUENTIAL : c_int = 2; + pub const POSIX_MADV_WILLNEED : c_int = 3; + pub const POSIX_MADV_DONTNEED : c_int = 4; + + pub const _SC_MQ_PRIO_MAX : c_int = 28; + pub const _SC_IOV_MAX : c_int = 60; + pub const _SC_GETGR_R_SIZE_MAX : c_int = 69; + pub const _SC_GETPW_R_SIZE_MAX : c_int = 70; + pub const _SC_LOGIN_NAME_MAX : c_int = 71; + pub const _SC_TTY_NAME_MAX : c_int = 72; + pub const _SC_THREADS : c_int = 67; + pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 68; + pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 73; + pub const _SC_THREAD_KEYS_MAX : c_int = 74; + pub const _SC_THREAD_STACK_MIN : c_int = 75; + pub const _SC_THREAD_THREADS_MAX : c_int = 76; + pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77; + pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78; + pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 79; + pub const _SC_THREAD_PRIO_INHERIT : c_int = 80; + pub const _SC_THREAD_PRIO_PROTECT : c_int = 81; + pub const _SC_THREAD_PROCESS_SHARED : c_int = 82; + pub const _SC_ATEXIT_MAX : c_int = 87; + pub const _SC_XOPEN_VERSION : c_int = 89; + pub const _SC_XOPEN_XCU_VERSION : c_int = 90; + pub const _SC_XOPEN_UNIX : c_int = 91; + pub const _SC_XOPEN_CRYPT : c_int = 92; + pub const _SC_XOPEN_ENH_I18N : c_int = 93; + pub const _SC_XOPEN_SHM : c_int = 94; + pub const _SC_XOPEN_LEGACY : c_int = 129; + pub const _SC_XOPEN_REALTIME : c_int = 130; + pub const _SC_XOPEN_REALTIME_THREADS : c_int = 131; + + pub const PTHREAD_CREATE_JOINABLE: c_int = 1; + pub const PTHREAD_CREATE_DETACHED: c_int = 0; + + pub const PTHREAD_STACK_MIN: size_t = 1024; + + pub const CLOCK_REALTIME: c_int = 0; + pub const CLOCK_MONOTONIC: c_int = 1; + + pub const RLIMIT_CPU: c_int = 0; + pub const RLIMIT_FSIZE: c_int = 1; + pub const RLIMIT_DATA: c_int = 2; + pub const RLIMIT_STACK: c_int = 3; + pub const RLIMIT_CORE: c_int = 4; + pub const RLIMIT_RSS: c_int = 5; + pub const RLIMIT_NOFILE: c_int = 7; + pub const RLIMIT_AS: c_int = 9; + pub const RLIMIT_NPROC: c_int = 6; + pub const RLIMIT_MEMLOCK: c_int = 8; + pub const RLIMIT_LOCKS: c_int = 10; + pub const RLIMIT_SIGPENDING: c_int = 11; + pub const RLIMIT_MSGQUEUE: c_int = 12; + pub const RLIMIT_NICE: c_int = 13; + pub const RLIMIT_RTPRIO: c_int = 14; + pub const RLIMIT_RTTIME: c_int = 15; + pub const RLIMIT_NLIMITS: c_int = 16; + + pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff; + pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; + pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; + + pub const RUSAGE_SELF: c_int = 0; + pub const RUSAGE_CHILDREN: c_int = -1; + pub const RUSAGE_THREAD: c_int = 1; } pub mod posix08 { } @@ -3234,6 +3474,7 @@ pub mod consts { target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64", + target_arch = "le32", target_arch = "powerpc"))] pub mod bsd44 { use types::os::arch::c95::c_int; @@ -3272,10 +3513,24 @@ pub mod consts { pub const TCP_NODELAY: c_int = 1; pub const SOL_SOCKET: c_int = 1; - pub const SO_KEEPALIVE: c_int = 9; - pub const SO_BROADCAST: c_int = 6; + + pub const SO_DEBUG: c_int = 1; pub const SO_REUSEADDR: c_int = 2; + pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; + pub const SO_DONTROUTE: c_int = 5; + pub const SO_BROADCAST: c_int = 6; + pub const SO_SNDBUF: c_int = 7; + pub const SO_RCVBUF: c_int = 8; + pub const SO_KEEPALIVE: c_int = 9; + pub const SO_OOBINLINE: c_int = 10; + pub const SO_LINGER: c_int = 13; + pub const SO_REUSEPORT: c_int = 15; + pub const SO_RCVLOWAT: c_int = 18; + pub const SO_SNDLOWAT: c_int = 19; + pub const SO_RCVTIMEO: c_int = 20; + pub const SO_SNDTIMEO: c_int = 21; + pub const SO_ACCEPTCONN: c_int = 30; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; @@ -3318,10 +3573,24 @@ pub mod consts { pub const TCP_NODELAY: c_int = 1; pub const SOL_SOCKET: c_int = 65535; - pub const SO_KEEPALIVE: c_int = 8; - pub const SO_BROADCAST: c_int = 32; - pub const SO_REUSEADDR: c_int = 4; - pub const SO_ERROR: c_int = 4103; + + pub const SO_DEBUG: c_int = 0x0001; + pub const SO_REUSEADDR: c_int = 0x0004; + pub const SO_KEEPALIVE: c_int = 0x0008; + pub const SO_DONTROUTE: c_int = 0x0010; + pub const SO_BROADCAST: c_int = 0x0020; + pub const SO_LINGER: c_int = 0x0080; + pub const SO_OOBINLINE: c_int = 0x100; + pub const SO_REUSEPORT: c_int = 0x0200; + pub const SO_SNDBUF: c_int = 0x1001; + pub const SO_RCVBUF: c_int = 0x1002; + pub const SO_SNDLOWAT: c_int = 0x1003; + pub const SO_RCVLOWAT: c_int = 0x1004; + pub const SO_SNDTIMEO: c_int = 0x1005; + pub const SO_RCVTIMEO: c_int = 0x1006; + pub const SO_ERROR: c_int = 0x1007; + pub const SO_TYPE: c_int = 0x1008; + pub const SO_ACCEPTCONN: c_int = 0x1009; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; @@ -3331,6 +3600,7 @@ pub mod consts { target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", + target_arch = "le32", target_arch = "powerpc"))] pub mod extra { use types::os::arch::c95::c_int; @@ -3353,7 +3623,7 @@ pub mod consts { pub const MAP_DENYWRITE : c_int = 0x0800; pub const MAP_EXECUTABLE : c_int = 0x01000; pub const MAP_LOCKED : c_int = 0x02000; - pub const MAP_NONRESERVE : c_int = 0x04000; + pub const MAP_NORESERVE : c_int = 0x04000; pub const MAP_POPULATE : c_int = 0x08000; pub const MAP_NONBLOCK : c_int = 0x010000; pub const MAP_STACK : c_int = 0x020000; @@ -3380,7 +3650,7 @@ pub mod consts { pub const MAP_DENYWRITE : c_int = 0x02000; pub const MAP_EXECUTABLE : c_int = 0x04000; pub const MAP_LOCKED : c_int = 0x08000; - pub const MAP_NONRESERVE : c_int = 0x0400; + pub const MAP_NORESERVE : c_int = 0x0400; pub const MAP_POPULATE : c_int = 0x010000; pub const MAP_NONBLOCK : c_int = 0x020000; pub const MAP_STACK : c_int = 0x040000; @@ -3446,6 +3716,14 @@ pub mod consts { pub const _SC_XBS5_ILP32_OFFBIG : c_int = 126; pub const _SC_XBS5_LPBIG_OFFBIG : c_int = 128; } + #[cfg(target_os = "nacl")] + pub mod sysconf { + use types::os::arch::c95::c_int; + + pub static _SC_SENDMSG_MAX_SIZE : c_int = 0; + pub static _SC_NPROCESSORS_ONLN : c_int = 1; + pub static _SC_PAGESIZE : c_int = 2; + } #[cfg(target_os = "android")] pub mod sysconf { use types::os::arch::c95::c_int; @@ -3498,11 +3776,11 @@ pub mod consts { pub const _IOFBF : c_int = 0; pub const _IONBF : c_int = 2; pub const _IOLBF : c_int = 1; - pub const BUFSIZ : c_uint = 1024_u32; - pub const FOPEN_MAX : c_uint = 20_u32; - pub const FILENAME_MAX : c_uint = 1024_u32; - pub const L_tmpnam : c_uint = 1024_u32; - pub const TMP_MAX : c_uint = 308915776_u32; + pub const BUFSIZ : c_uint = 1024; + pub const FOPEN_MAX : c_uint = 20; + pub const FILENAME_MAX : c_uint = 1024; + pub const L_tmpnam : c_uint = 1024; + pub const TMP_MAX : c_uint = 308915776; } pub mod c99 { } @@ -3532,6 +3810,14 @@ pub mod consts { pub const S_IXUSR : mode_t = 64; pub const S_IWUSR : mode_t = 128; pub const S_IRUSR : mode_t = 256; + pub const S_IRWXG : mode_t = 56; + pub const S_IXGRP : mode_t = 8; + pub const S_IWGRP : mode_t = 16; + pub const S_IRGRP : mode_t = 32; + pub const S_IRWXO : mode_t = 7; + pub const S_IXOTH : mode_t = 1; + pub const S_IWOTH : mode_t = 2; + pub const S_IROTH : mode_t = 4; pub const F_OK : c_int = 0; pub const R_OK : c_int = 4; pub const W_OK : c_int = 2; @@ -3679,6 +3965,7 @@ pub mod consts { } pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + use types::os::common::posix01::rlim_t; pub const F_DUPFD : c_int = 0; pub const F_GETFD : c_int = 1; @@ -3687,7 +3974,6 @@ pub mod consts { pub const F_SETFL : c_int = 4; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_APPEND : c_int = 0x0001; @@ -3755,6 +4041,29 @@ pub mod consts { pub const CLOCK_REALTIME: c_int = 0; pub const CLOCK_MONOTONIC: c_int = 4; + + pub const RLIMIT_CPU: c_int = 0; + pub const RLIMIT_FSIZE: c_int = 1; + pub const RLIMIT_DATA: c_int = 2; + pub const RLIMIT_STACK: c_int = 3; + pub const RLIMIT_CORE: c_int = 4; + pub const RLIMIT_RSS: c_int = 5; + pub const RLIMIT_MEMLOCK: c_int = 6; + pub const RLIMIT_NPROC: c_int = 7; + pub const RLIMIT_NOFILE: c_int = 8; + pub const RLIMIT_SBSIZE: c_int = 9; + pub const RLIMIT_VMEM: c_int = 10; + pub const RLIMIT_AS: c_int = RLIMIT_VMEM; + pub const RLIMIT_NPTS: c_int = 11; + pub const RLIMIT_SWAP: c_int = 12; + pub const RLIMIT_KQUEUES: c_int = 13; + + pub const RLIM_NLIMITS: rlim_t = 14; + pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; + + pub const RUSAGE_SELF: c_int = 0; + pub const RUSAGE_CHILDREN: c_int = -1; + pub const RUSAGE_THREAD: c_int = 1; } pub mod posix08 { } @@ -3801,10 +4110,24 @@ pub mod consts { pub const TCP_NODELAY: c_int = 1; pub const TCP_KEEPIDLE: c_int = 256; pub const SOL_SOCKET: c_int = 0xffff; + pub const SO_DEBUG: c_int = 0x01; + pub const SO_ACCEPTCONN: c_int = 0x0002; + pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; + pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_REUSEADDR: c_int = 0x0004; + pub const SO_USELOOPBACK: c_int = 0x0040; + pub const SO_LINGER: c_int = 0x0080; + pub const SO_OOBINLINE: c_int = 0x0100; + pub const SO_REUSEPORT: c_int = 0x0200; + pub const SO_SNDBUF: c_int = 0x1001; + pub const SO_RCVBUF: c_int = 0x1002; + pub const SO_SNDLOWAT: c_int = 0x1003; + pub const SO_RCVLOWAT: c_int = 0x1004; + pub const SO_SNDTIMEO: c_int = 0x1005; + pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; + pub const SO_TYPE: c_int = 0x1008; pub const IFF_LOOPBACK: c_int = 0x8; @@ -3892,7 +4215,7 @@ pub mod consts { } } - #[cfg(target_os = "openbsd")] + #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] pub mod os { pub mod c95 { use types::os::arch::c95::{c_int, c_uint}; @@ -3907,11 +4230,11 @@ pub mod consts { pub const _IOFBF : c_int = 0; pub const _IONBF : c_int = 2; pub const _IOLBF : c_int = 1; - pub const BUFSIZ : c_uint = 1024_u32; - pub const FOPEN_MAX : c_uint = 20_u32; - pub const FILENAME_MAX : c_uint = 1024_u32; - pub const L_tmpnam : c_uint = 1024_u32; - pub const TMP_MAX : c_uint = 308915776_u32; + pub const BUFSIZ : c_uint = 1024; + pub const FOPEN_MAX : c_uint = 20; + pub const FILENAME_MAX : c_uint = 1024; + pub const L_tmpnam : c_uint = 1024; + pub const TMP_MAX : c_uint = 308915776; } pub mod c99 { } @@ -3941,6 +4264,14 @@ pub mod consts { pub const S_IXUSR : mode_t = 64; pub const S_IWUSR : mode_t = 128; pub const S_IRUSR : mode_t = 256; + pub const S_IRWXG : mode_t = 56; + pub const S_IXGRP : mode_t = 8; + pub const S_IWGRP : mode_t = 16; + pub const S_IRGRP : mode_t = 32; + pub const S_IRWXO : mode_t = 7; + pub const S_IXOTH : mode_t = 1; + pub const S_IWOTH : mode_t = 2; + pub const S_IROTH : mode_t = 4; pub const F_OK : c_int = 0; pub const R_OK : c_int = 4; pub const W_OK : c_int = 2; @@ -3980,11 +4311,11 @@ pub mod consts { pub const MCL_CURRENT : c_int = 0x0001; pub const MCL_FUTURE : c_int = 0x0002; - pub const MS_SYNC : c_int = 0x0002; // changed pub const MS_ASYNC : c_int = 0x0001; - pub const MS_INVALIDATE : c_int = 0x0004; // changed + pub const MS_SYNC : c_int = 0x0002; + pub const MS_INVALIDATE : c_int = 0x0004; - pub const EPERM : c_int = 1; // not checked + pub const EPERM : c_int = 1; pub const ENOENT : c_int = 2; pub const ESRCH : c_int = 3; pub const EINTR : c_int = 4; @@ -4066,37 +4397,35 @@ pub mod consts { pub const EFTYPE : c_int = 79; pub const EAUTH : c_int = 80; pub const ENEEDAUTH : c_int = 81; - pub const EIDRM : c_int = 82; - pub const ENOMSG : c_int = 83; - pub const EOVERFLOW : c_int = 84; - pub const ECANCELED : c_int = 85; - pub const EILSEQ : c_int = 86; - pub const ENOATTR : c_int = 87; - pub const EDOOFUS : c_int = 88; - pub const EBADMSG : c_int = 89; - pub const EMULTIHOP : c_int = 90; - pub const ENOLINK : c_int = 91; - pub const EPROTO : c_int = 92; - pub const ENOMEDIUM : c_int = 93; - pub const EUNUSED94 : c_int = 94; - pub const EUNUSED95 : c_int = 95; - pub const EUNUSED96 : c_int = 96; - pub const EUNUSED97 : c_int = 97; - pub const EUNUSED98 : c_int = 98; - pub const EASYNC : c_int = 99; - pub const ELAST : c_int = 99; + pub const EIPSEC : c_int = 82; + pub const ENOATTR : c_int = 83; + pub const EILSEQ : c_int = 84; + pub const ENOMEDIUM : c_int = 85; + pub const EMEDIUMTYPE : c_int = 86; + pub const EOVERFLOW : c_int = 87; + pub const ECANCELED : c_int = 88; + pub const EIDRM : c_int = 89; + pub const ENOMSG : c_int = 90; + pub const ENOTSUP : c_int = 91; + pub const ELAST : c_int = 91; // must be equal to largest errno } pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + use types::os::common::posix01::rlim_t; pub const F_DUPFD : c_int = 0; pub const F_GETFD : c_int = 1; pub const F_SETFD : c_int = 2; pub const F_GETFL : c_int = 3; pub const F_SETFL : c_int = 4; + pub const F_GETOWN : c_int = 5; + pub const F_SETOWN : c_int = 6; + pub const F_GETLK : c_int = 7; + pub const F_SETLK : c_int = 8; + pub const F_SETLKW : c_int = 9; + pub const F_DUPFD_CLOEXEC : c_int = 10; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_APPEND : c_int = 0x0001; @@ -4105,11 +4434,12 @@ pub mod consts { pub const GLOB_MARK : c_int = 0x0008; pub const GLOB_NOCHECK : c_int = 0x0010; pub const GLOB_NOSORT : c_int = 0x0020; - pub const GLOB_NOESCAPE : c_int = 0x1000; // changed + pub const GLOB_NOESCAPE : c_int = 0x1000; pub const GLOB_NOSPACE : c_int = -1; pub const GLOB_ABORTED : c_int = -2; pub const GLOB_NOMATCH : c_int = -3; + pub const GLOB_NOSYS : c_int = -4; pub const POSIX_MADV_NORMAL : c_int = 0; pub const POSIX_MADV_RANDOM : c_int = 1; @@ -4117,7 +4447,7 @@ pub mod consts { pub const POSIX_MADV_WILLNEED : c_int = 3; pub const POSIX_MADV_DONTNEED : c_int = 4; - pub const _SC_IOV_MAX : c_int = 51; // all changed... + pub const _SC_IOV_MAX : c_int = 51; pub const _SC_GETGR_R_SIZE_MAX : c_int = 100; pub const _SC_GETPW_R_SIZE_MAX : c_int = 101; pub const _SC_LOGIN_NAME_MAX : c_int = 102; @@ -4144,14 +4474,32 @@ pub mod consts { pub const _SC_XOPEN_SHM : c_int = 30; pub const _SC_XOPEN_UNIX : c_int = 123; pub const _SC_XOPEN_VERSION : c_int = 125; - //pub const _SC_XOPEN_XCU_VERSION : c_int = ; - pub const PTHREAD_CREATE_JOINABLE: c_int = 0; - pub const PTHREAD_CREATE_DETACHED: c_int = 1; - pub const PTHREAD_STACK_MIN: size_t = 2048; - - pub const CLOCK_REALTIME: c_int = 0; - pub const CLOCK_MONOTONIC: c_int = 3; + pub const PTHREAD_CREATE_JOINABLE : c_int = 0; + pub const PTHREAD_CREATE_DETACHED : c_int = 1; + pub const PTHREAD_STACK_MIN : size_t = 2048; + + pub const CLOCK_REALTIME : c_int = 0; + pub const CLOCK_MONOTONIC : c_int = 3; + + pub const RLIMIT_CPU: c_int = 0; + pub const RLIMIT_FSIZE: c_int = 1; + pub const RLIMIT_DATA: c_int = 2; + pub const RLIMIT_STACK: c_int = 3; + pub const RLIMIT_CORE: c_int = 4; + pub const RLIMIT_RSS: c_int = 5; + pub const RLIMIT_MEMLOCK: c_int = 6; + pub const RLIMIT_NPROC: c_int = 7; + pub const RLIMIT_NOFILE: c_int = 8; + pub const RLIM_NLIMITS: c_int = 9; + + pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; + pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; + pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; + + pub const RUSAGE_SELF: c_int = 0; + pub const RUSAGE_CHILDREN: c_int = -1; + pub const RUSAGE_THREAD: c_int = 1; } pub mod posix08 { } @@ -4163,23 +4511,11 @@ pub mod consts { pub const MADV_SEQUENTIAL : c_int = 2; pub const MADV_WILLNEED : c_int = 3; pub const MADV_DONTNEED : c_int = 4; - pub const MADV_FREE : c_int = 6; // changed - //pub const MADV_NOSYNC : c_int = ; - //pub const MADV_AUTOSYNC : c_int = ; - //pub const MADV_NOCORE : c_int = ; - //pub const MADV_CORE : c_int = ; - //pub const MADV_PROTECT : c_int = ; - - //pub const MINCORE_INCORE : c_int = ; - //pub const MINCORE_REFERENCED : c_int = ; - //pub const MINCORE_MODIFIED : c_int = ; - //pub const MINCORE_REFERENCED_OTHER : c_int = ; - //pub const MINCORE_MODIFIED_OTHER : c_int = ; - //pub const MINCORE_SUPER : c_int = ; + pub const MADV_FREE : c_int = 6; - pub const AF_INET: c_int = 2; - pub const AF_INET6: c_int = 24; // changed pub const AF_UNIX: c_int = 1; + pub const AF_INET: c_int = 2; + pub const AF_INET6: c_int = 24; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; @@ -4192,18 +4528,29 @@ pub mod consts { pub const IP_HDRINCL: c_int = 2; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; - // don't exist, keep same as IP_ADD_MEMBERSHIP - pub const IPV6_ADD_MEMBERSHIP: c_int = 12; - // don't exist, keep same as IP_DROP_MEMBERSHIP - pub const IPV6_DROP_MEMBERSHIP: c_int = 13; + pub const IPV6_ADD_MEMBERSHIP: c_int = 12; // don't exist + pub const IPV6_DROP_MEMBERSHIP: c_int = 13; // don't exist - pub const TCP_NODELAY: c_int = 1; - //pub const TCP_KEEPIDLE: c_int = ; + pub const TCP_NODELAY: c_int = 0x01; pub const SOL_SOCKET: c_int = 0xffff; + pub const SO_DEBUG: c_int = 0x01; + pub const SO_ACCEPTCONN: c_int = 0x0002; + pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; + pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_REUSEADDR: c_int = 0x0004; + pub const SO_USELOOPBACK: c_int = 0x0040; + pub const SO_LINGER: c_int = 0x0080; + pub const SO_OOBINLINE: c_int = 0x0100; + pub const SO_REUSEPORT: c_int = 0x0200; + pub const SO_SNDBUF: c_int = 0x1001; + pub const SO_RCVBUF: c_int = 0x1002; + pub const SO_SNDLOWAT: c_int = 0x1003; + pub const SO_RCVLOWAT: c_int = 0x1004; + pub const SO_SNDTIMEO: c_int = 0x1005; + pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; + pub const SO_TYPE: c_int = 0x1008; pub const IFF_LOOPBACK: c_int = 0x8; @@ -4214,20 +4561,21 @@ pub mod consts { pub mod extra { use types::os::arch::c95::c_int; + pub const O_DSYNC : c_int = 128; // same as SYNC pub const O_SYNC : c_int = 128; pub const O_NONBLOCK : c_int = 4; - pub const CTL_KERN: c_int = 1; - pub const KERN_PROC: c_int = 66; + pub const CTL_KERN : c_int = 1; + pub const KERN_PROC : c_int = 66; pub const MAP_COPY : c_int = 0x0002; - pub const MAP_RENAME : c_int = 0x0000; // changed - pub const MAP_NORESERVE : c_int = 0x0000; // changed - pub const MAP_HASSEMAPHORE : c_int = 0x0000; // changed - //pub const MAP_STACK : c_int = ; - //pub const MAP_NOSYNC : c_int = ; - //pub const MAP_NOCORE : c_int = ; + pub const MAP_RENAME : c_int = 0x0000; + pub const MAP_NORESERVE : c_int = 0x0000; + pub const MAP_NOEXTEND : c_int = 0x0000; + pub const MAP_HASSEMAPHORE : c_int = 0x0000; pub const IPPROTO_RAW : c_int = 255; + + pub const PATH_MAX: c_int = 1024; } pub mod sysconf { use types::os::arch::c95::c_int; @@ -4259,31 +4607,31 @@ pub mod consts { pub const _SC_2_UPE : c_int = 25; pub const _SC_STREAM_MAX : c_int = 26; pub const _SC_TZNAME_MAX : c_int = 27; - pub const _SC_ASYNCHRONOUS_IO : c_int = 45; // changed... + pub const _SC_PAGESIZE : c_int = 28; + pub const _SC_FSYNC : c_int = 29; + pub const _SC_SEM_NSEMS_MAX : c_int = 31; + pub const _SC_SEM_VALUE_MAX : c_int = 32; + pub const _SC_AIO_LISTIO_MAX : c_int = 42; + pub const _SC_AIO_MAX : c_int = 43; + pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44; + pub const _SC_ASYNCHRONOUS_IO : c_int = 45; + pub const _SC_DELAYTIMER_MAX : c_int = 50; pub const _SC_MAPPED_FILES : c_int = 53; pub const _SC_MEMLOCK : c_int = 54; pub const _SC_MEMLOCK_RANGE : c_int = 55; pub const _SC_MEMORY_PROTECTION : c_int = 56; pub const _SC_MESSAGE_PASSING : c_int = 57; + pub const _SC_MQ_OPEN_MAX : c_int = 58; pub const _SC_PRIORITIZED_IO : c_int = 60; pub const _SC_PRIORITY_SCHEDULING : c_int = 61; pub const _SC_REALTIME_SIGNALS : c_int = 64; + pub const _SC_RTSIG_MAX : c_int = 66; pub const _SC_SEMAPHORES : c_int = 67; - pub const _SC_FSYNC : c_int = 29; pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 68; - pub const _SC_SYNCHRONIZED_IO : c_int = 75; - pub const _SC_TIMERS : c_int = 94; // ...changed - pub const _SC_AIO_LISTIO_MAX : c_int = 42; - pub const _SC_AIO_MAX : c_int = 43; - pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44; - pub const _SC_DELAYTIMER_MAX : c_int = 50; // changed... - pub const _SC_MQ_OPEN_MAX : c_int = 58; - pub const _SC_PAGESIZE : c_int = 28; - pub const _SC_RTSIG_MAX : c_int = 66; - pub const _SC_SEM_NSEMS_MAX : c_int = 31; - pub const _SC_SEM_VALUE_MAX : c_int = 32; pub const _SC_SIGQUEUE_MAX : c_int = 70; + pub const _SC_SYNCHRONIZED_IO : c_int = 75; pub const _SC_TIMER_MAX : c_int = 93; + pub const _SC_TIMERS : c_int = 94; } } @@ -4302,11 +4650,11 @@ pub mod consts { pub const _IOFBF : c_int = 0; pub const _IONBF : c_int = 2; pub const _IOLBF : c_int = 1; - pub const BUFSIZ : c_uint = 1024_u32; - pub const FOPEN_MAX : c_uint = 20_u32; - pub const FILENAME_MAX : c_uint = 1024_u32; - pub const L_tmpnam : c_uint = 1024_u32; - pub const TMP_MAX : c_uint = 308915776_u32; + pub const BUFSIZ : c_uint = 1024; + pub const FOPEN_MAX : c_uint = 20; + pub const FILENAME_MAX : c_uint = 1024; + pub const L_tmpnam : c_uint = 1024; + pub const TMP_MAX : c_uint = 308915776; } pub mod c99 { } @@ -4336,6 +4684,14 @@ pub mod consts { pub const S_IXUSR : mode_t = 64; pub const S_IWUSR : mode_t = 128; pub const S_IRUSR : mode_t = 256; + pub const S_IRWXG : mode_t = 56; + pub const S_IXGRP : mode_t = 8; + pub const S_IWGRP : mode_t = 16; + pub const S_IRGRP : mode_t = 32; + pub const S_IRWXO : mode_t = 7; + pub const S_IXOTH : mode_t = 1; + pub const S_IWOTH : mode_t = 2; + pub const S_IROTH : mode_t = 4; pub const F_OK : c_int = 0; pub const R_OK : c_int = 4; pub const W_OK : c_int = 2; @@ -4370,7 +4726,7 @@ pub mod consts { pub const MAP_FIXED : c_int = 0x0010; pub const MAP_ANON : c_int = 0x1000; - pub const MAP_FAILED : *mut c_void = -1 as *mut c_void; + pub const MAP_FAILED : *mut c_void = !0 as *mut c_void; pub const MCL_CURRENT : c_int = 0x0001; pub const MCL_FUTURE : c_int = 0x0002; @@ -4493,6 +4849,7 @@ pub mod consts { } pub mod posix01 { use types::os::arch::c95::{c_int, size_t}; + use types::os::common::posix01::rlim_t; pub const F_DUPFD : c_int = 0; pub const F_GETFD : c_int = 1; @@ -4501,7 +4858,6 @@ pub mod consts { pub const F_SETFL : c_int = 4; pub const SIGTRAP : c_int = 5; - pub const SIGPIPE: c_int = 13; pub const SIG_IGN: size_t = 1; pub const GLOB_APPEND : c_int = 0x0001; @@ -4554,6 +4910,24 @@ pub mod consts { pub const PTHREAD_CREATE_JOINABLE: c_int = 1; pub const PTHREAD_CREATE_DETACHED: c_int = 2; pub const PTHREAD_STACK_MIN: size_t = 8192; + + pub const RLIMIT_CPU: c_int = 0; + pub const RLIMIT_FSIZE: c_int = 1; + pub const RLIMIT_DATA: c_int = 2; + pub const RLIMIT_STACK: c_int = 3; + pub const RLIMIT_CORE: c_int = 4; + pub const RLIMIT_AS: c_int = 5; + pub const RLIMIT_MEMLOCK: c_int = 6; + pub const RLIMIT_NPROC: c_int = 7; + pub const RLIMIT_NOFILE: c_int = 8; + pub const RLIM_NLIMITS: c_int = 9; + pub const _RLIMIT_POSIX_FLAG: c_int = 0x1000; + + pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff; + + pub const RUSAGE_SELF: c_int = 0; + pub const RUSAGE_CHILDREN: c_int = -1; + pub const RUSAGE_THREAD: c_int = 1; } pub mod posix08 { } @@ -4598,10 +4972,25 @@ pub mod consts { pub const TCP_NODELAY: c_int = 0x01; pub const TCP_KEEPALIVE: c_int = 0x10; pub const SOL_SOCKET: c_int = 0xffff; + + pub const SO_DEBUG: c_int = 0x01; + pub const SO_ACCEPTCONN: c_int = 0x0002; + pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; + pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; - pub const SO_REUSEADDR: c_int = 0x0004; + pub const SO_USELOOPBACK: c_int = 0x0040; + pub const SO_LINGER: c_int = 0x0080; + pub const SO_OOBINLINE: c_int = 0x0100; + pub const SO_REUSEPORT: c_int = 0x0200; + pub const SO_SNDBUF: c_int = 0x1001; + pub const SO_RCVBUF: c_int = 0x1002; + pub const SO_SNDLOWAT: c_int = 0x1003; + pub const SO_RCVLOWAT: c_int = 0x1004; + pub const SO_SNDTIMEO: c_int = 0x1005; + pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; + pub const SO_TYPE: c_int = 0x1008; pub const IFF_LOOPBACK: c_int = 0x8; @@ -4627,6 +5016,15 @@ pub mod consts { pub const MAP_STACK : c_int = 0; pub const IPPROTO_RAW : c_int = 255; + + pub const SO_NREAD: c_int = 0x1020; + pub const SO_NKE: c_int = 0x1021; + pub const SO_NOSIGPIPE: c_int = 0x1022; + pub const SO_NOADDRERR: c_int = 0x1023; + pub const SO_NWRITE: c_int = 0x1024; + pub const SO_DONTTRUNC: c_int = 0x2000; + pub const SO_WANTMORE: c_int = 0x4000; + pub const SO_WANTOOBFLAG: c_int = 0x8000; } pub mod sysconf { use types::os::arch::c95::c_int; @@ -4809,7 +5207,7 @@ pub mod funcs { /// /// # Examples /// - /// ```no_run + /// ```no_run,ignore /// extern crate libc; /// /// fn main() { @@ -5005,7 +5403,9 @@ pub mod funcs { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", - target_os = "openbsd"))] + target_os = "bitrig", + target_os = "openbsd", + target_os = "nacl"))] pub mod posix88 { pub mod stat_ { use types::os::arch::c95::{c_char, c_int}; @@ -5019,9 +5419,11 @@ pub mod funcs { #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd", target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -5029,14 +5431,17 @@ pub mod funcs { pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; + #[cfg(not(target_os = "nacl"))] pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd", target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -5062,9 +5467,36 @@ pub mod funcs { use types::os::arch::c95::{c_char, c_int}; use types::os::arch::posix88::mode_t; + mod open_shim { + extern { + #[cfg(any(target_os = "macos", + target_os = "ios"))] + pub fn open(path: *const ::c_char, oflag: ::c_int, ...) + -> ::c_int; + + #[cfg(not(any(target_os = "macos", + target_os = "ios")))] + pub fn open(path: *const ::c_char, oflag: ::c_int, mode: ::mode_t) + -> ::c_int; + } + } + + #[cfg(any(target_os = "macos", + target_os = "ios"))] + #[inline] + pub unsafe extern fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { + use types::os::arch::c95::c_uint; + open_shim::open(path, oflag, mode as c_uint) + } + + #[cfg(not(any(target_os = "macos", + target_os = "ios")))] + #[inline] + pub unsafe extern fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { + open_shim::open(path, oflag, mode) + } + extern { - pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) - -> c_int; pub fn creat(path: *const c_char, mode: mode_t) -> c_int; pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; } @@ -5108,6 +5540,7 @@ pub mod funcs { pub const _PC_NAME_MAX: c_int = 4; + #[cfg(not(target_os = "nacl"))] extern { pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn alarm(seconds: c_uint) -> c_uint; @@ -5129,7 +5562,7 @@ pub mod funcs { pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; - pub fn getgid() -> gid_t ; + pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; pub fn getlogin() -> *mut c_char; @@ -5170,6 +5603,57 @@ pub mod funcs { offset: off_t) -> ssize_t; pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; } + #[cfg(target_os = "nacl")] + extern { + pub fn access(path: *const c_char, amode: c_int) -> c_int; + pub fn chdir(dir: *const c_char) -> c_int; + pub fn chown(path: *const c_char, uid: uid_t, + gid: gid_t) -> c_int; + pub fn close(fd: c_int) -> c_int; + pub fn dup(fd: c_int) -> c_int; + pub fn dup2(src: c_int, dst: c_int) -> c_int; + pub fn execv(prog: *const c_char, + argv: *mut *const c_char) -> c_int; + pub fn execve(prog: *const c_char, argv: *mut *const c_char, + envp: *mut *const c_char) + -> c_int; + pub fn execvp(c: *const c_char, + argv: *mut *const c_char) -> c_int; + pub fn fork() -> pid_t; + pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; + pub fn getegid() -> gid_t; + pub fn geteuid() -> uid_t; + pub fn getgid() -> gid_t; + pub fn getlogin() -> *mut c_char; + pub fn getopt(argc: c_int, argv: *mut *const c_char, + optstr: *const c_char) -> c_int; + pub fn getuid() -> uid_t; + pub fn getsid(pid: pid_t) -> pid_t; + pub fn isatty(fd: c_int) -> c_int; + pub fn link(src: *const c_char, dst: *const c_char) -> c_int; + pub fn lseek(fd: c_int, offset: off_t, whence: c_int) + -> off_t; + pub fn pipe(fds: *mut c_int) -> c_int; + pub fn read(fd: c_int, buf: *mut c_void, count: size_t) + -> ssize_t; + pub fn rmdir(path: *const c_char) -> c_int; + pub fn setgid(gid: gid_t) -> c_int; + pub fn setuid(uid: uid_t) -> c_int; + pub fn sleep(secs: c_uint) -> c_uint; + pub fn usleep(secs: c_uint) -> c_int; + pub fn nanosleep(rqtp: *const timespec, + rmtp: *mut timespec) -> c_int; + pub fn sysconf(name: c_int) -> c_long; + pub fn ttyname(fd: c_int) -> *mut c_char; + pub fn unlink(c: *const c_char) -> c_int; + pub fn write(fd: c_int, buf: *const c_void, count: size_t) + -> ssize_t; + pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, + offset: off_t) -> ssize_t; + pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, + offset: off_t) -> ssize_t; + pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; + } } pub mod signal { @@ -5186,12 +5670,24 @@ pub mod funcs { use types::os::arch::c95::{size_t, c_int, c_char}; use types::os::arch::posix88::{mode_t, off_t}; + #[cfg(not(target_os = "nacl"))] extern { pub fn mlock(addr: *const c_void, len: size_t) -> c_int; pub fn munlock(addr: *const c_void, len: size_t) -> c_int; pub fn mlockall(flags: c_int) -> c_int; pub fn munlockall() -> c_int; + pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) + -> c_int; + + pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) + -> c_int; + pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) + -> c_int; + pub fn shm_unlink(name: *const c_char) -> c_int; + } + + extern { pub fn mmap(addr: *mut c_void, len: size_t, prot: c_int, @@ -5201,14 +5697,6 @@ pub mod funcs { -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; - pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) - -> c_int; - - pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) - -> c_int; - pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) - -> c_int; - pub fn shm_unlink(name: *const c_char) -> c_int; } } @@ -5228,7 +5716,9 @@ pub mod funcs { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", - target_os = "openbsd"))] + target_os = "bitrig", + target_os = "openbsd", + target_os = "nacl"))] pub mod posix01 { pub mod stat_ { use types::os::arch::c95::{c_char, c_int}; @@ -5238,9 +5728,11 @@ pub mod funcs { #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd", target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -5312,6 +5804,7 @@ pub mod funcs { use types::common::c95::{c_void}; use types::os::arch::c95::{c_int, size_t}; + #[cfg(not(target_os = "nacl"))] extern { pub fn posix_madvise(addr: *mut c_void, len: size_t, @@ -5319,6 +5812,18 @@ pub mod funcs { -> c_int; } } + + pub mod resource { + use types::os::arch::c95::c_int; + use types::os::common::posix01::rlimit; + use types::os::common::bsd43::rusage; + extern { + pub fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int; + pub fn setrlimit(resource: c_int, rlim: *const rlimit) -> c_int; + pub fn getrusage(resource: c_int, usage: *mut rusage) -> c_int; + + } + } } #[cfg(target_os = "windows")] @@ -5347,7 +5852,9 @@ pub mod funcs { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", - target_os = "openbsd"))] + target_os = "bitrig", + target_os = "openbsd", + target_os = "nacl"))] pub mod posix08 { pub mod unistd { } @@ -5434,6 +5941,7 @@ pub mod funcs { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub mod bsd44 { use types::common::c95::{c_void}; @@ -5463,10 +5971,11 @@ pub mod funcs { -> c_int; pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int; + pub fn realpath(pathname: *const c_char, resolved: *mut c_char) + -> *mut c_char; } } - #[cfg(any(target_os = "linux", target_os = "android"))] pub mod bsd44 { use types::common::c95::{c_void}; @@ -5483,6 +5992,13 @@ pub mod funcs { } } + #[cfg(target_os = "nacl")] + pub mod bsd44 { + use types::os::arch::c95::c_int; + extern { + pub fn getdtablesize() -> c_int; + } + } #[cfg(target_os = "windows")] pub mod bsd44 { @@ -5500,11 +6016,12 @@ pub mod funcs { #[cfg(any(target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub mod extra { } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))] pub mod extra { } diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index c2c7f20ce9..453d087196 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -155,6 +155,8 @@ //! they're turned off (just a load and an integer comparison). This also means that //! if logging is disabled, none of the components of the log will be executed. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "log"] #![unstable(feature = "rustc_private", reason = "use the crates.io `log` library instead")] @@ -167,24 +169,22 @@ html_playground_url = "http://play.rust-lang.org/")] #![deny(missing_docs)] +#![feature(alloc)] #![feature(staged_api)] #![feature(box_syntax)] -#![feature(int_uint)] #![feature(core)] -#![feature(old_io)] #![feature(std_misc)] -#![feature(env)] +use std::boxed; use std::cell::RefCell; use std::fmt; -use std::old_io::LineBufferedWriter; -use std::old_io; +use std::io::{self, Stderr}; +use std::io::prelude::*; use std::mem; use std::env; -use std::ptr; use std::rt; use std::slice; -use std::sync::{Once, ONCE_INIT}; +use std::sync::{Once, ONCE_INIT, StaticMutex, MUTEX_INIT}; use directive::LOG_LEVEL_NAMES; @@ -200,16 +200,18 @@ pub const MAX_LOG_LEVEL: u32 = 255; /// The default logging level of a crate if no other is specified. const DEFAULT_LOG_LEVEL: u32 = 1; +static LOCK: StaticMutex = MUTEX_INIT; + /// An unsafe constant that is the maximum logging level of any module /// specified. This is the first line of defense to determining whether a /// logging statement should be run. static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL; -static mut DIRECTIVES: *const Vec = - 0 as *const Vec; +static mut DIRECTIVES: *mut Vec = + 0 as *mut Vec; /// Optional filter. -static mut FILTER: *const String = 0 as *const _; +static mut FILTER: *mut String = 0 as *mut _; /// Debug log level pub const DEBUG: u32 = 4; @@ -234,18 +236,16 @@ pub trait Logger { fn log(&mut self, record: &LogRecord); } -struct DefaultLogger { - handle: LineBufferedWriter, -} +struct DefaultLogger { handle: Stderr } /// Wraps the log level with fmt implementations. -#[derive(Copy, PartialEq, PartialOrd, Debug)] +#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct LogLevel(pub u32); impl fmt::Display for LogLevel { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let LogLevel(level) = *self; - match LOG_LEVEL_NAMES.get(level as uint - 1) { + match LOG_LEVEL_NAMES.get(level as usize - 1) { Some(ref name) => fmt::Display::fmt(name, fmt), None => fmt::Display::fmt(&level, fmt) } @@ -286,18 +286,27 @@ impl Drop for DefaultLogger { pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { // Test the literal string from args against the current filter, if there // is one. - match unsafe { FILTER.as_ref() } { - Some(filter) if !args.to_string().contains(&filter[..]) => return, - _ => {} + unsafe { + let _g = LOCK.lock(); + match FILTER as usize { + 0 => {} + 1 => panic!("cannot log after main thread has exited"), + n => { + let filter = mem::transmute::<_, &String>(n); + if !args.to_string().contains(&filter[..]) { + return + } + } + } } // Completely remove the local logger from TLS in case anyone attempts to // frob the slot while we're doing the logging. This will destroy any logger // set during logging. - let mut logger = LOCAL_LOGGER.with(|s| { + let mut logger: Box = LOCAL_LOGGER.with(|s| { s.borrow_mut().take() }).unwrap_or_else(|| { - box DefaultLogger { handle: old_io::stderr() } as Box + box DefaultLogger { handle: io::stderr() } }); logger.log(&LogRecord { level: LogLevel(level), @@ -342,15 +351,15 @@ pub struct LogRecord<'a> { pub file: &'a str, /// The line number of where the LogRecord originated. - pub line: uint, + pub line: u32, } #[doc(hidden)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct LogLocation { pub module_path: &'static str, pub file: &'static str, - pub line: uint, + pub line: u32, } /// Tests whether a given module's name is enabled for a particular level of @@ -370,9 +379,15 @@ pub fn mod_enabled(level: u32, module: &str) -> bool { // This assertion should never get tripped unless we're in an at_exit // handler after logging has been torn down and a logging attempt was made. - assert!(unsafe { !DIRECTIVES.is_null() }); - enabled(level, module, unsafe { (*DIRECTIVES).iter() }) + let _g = LOCK.lock(); + unsafe { + assert!(DIRECTIVES as usize != 0); + assert!(DIRECTIVES as usize != 1, + "cannot log after the main thread has exited"); + + enabled(level, module, (*DIRECTIVES).iter()) + } } fn enabled(level: u32, @@ -419,23 +434,23 @@ fn init() { assert!(FILTER.is_null()); match filter { - Some(f) => FILTER = mem::transmute(box f), + Some(f) => FILTER = boxed::into_raw(box f), None => {} } assert!(DIRECTIVES.is_null()); - DIRECTIVES = mem::transmute(box directives); + DIRECTIVES = boxed::into_raw(box directives); // Schedule the cleanup for the globals for when the runtime exits. - rt::at_exit(move || { + let _ = rt::at_exit(move || { + let _g = LOCK.lock(); assert!(!DIRECTIVES.is_null()); - let _directives: Box> = - mem::transmute(DIRECTIVES); - DIRECTIVES = ptr::null(); + let _directives = Box::from_raw(DIRECTIVES); + DIRECTIVES = 1 as *mut _; if !FILTER.is_null() { - let _filter: Box = mem::transmute(FILTER); - FILTER = 0 as *const _; + let _filter = Box::from_raw(FILTER); + FILTER = 1 as *mut _; } }); } diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs index 4a9a9bd406..80eb160103 100644 --- a/src/liblog/macros.rs +++ b/src/liblog/macros.rs @@ -16,7 +16,7 @@ /// format!-based argument list. See documentation in `std::fmt` for details on /// how to use the syntax. /// -/// # Example +/// # Examples /// /// ``` /// #[macro_use] extern crate log; @@ -64,7 +64,7 @@ macro_rules! log { /// A convenience macro for logging at the error log level. /// -/// # Example +/// # Examples /// /// ``` /// #[macro_use] extern crate log; @@ -89,7 +89,7 @@ macro_rules! error { /// A convenience macro for logging at the warning log level. /// -/// # Example +/// # Examples /// /// ``` /// #[macro_use] extern crate log; @@ -113,7 +113,7 @@ macro_rules! warn { /// A convenience macro for logging at the info log level. /// -/// # Example +/// # Examples /// /// ``` /// #[macro_use] extern crate log; @@ -139,7 +139,7 @@ macro_rules! info { /// be omitted at compile time by passing `--cfg ndebug` to the compiler. If /// this option is not passed, then debug statements will be compiled. /// -/// # Example +/// # Examples /// /// ``` /// #[macro_use] extern crate log; @@ -157,12 +157,12 @@ macro_rules! info { /// ``` #[macro_export] macro_rules! debug { - ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(::log::DEBUG, $($arg)*) }) + ($($arg:tt)*) => (if cfg!(debug_assertions) { log!(::log::DEBUG, $($arg)*) }) } /// A macro to test whether a log level is enabled for the current module. /// -/// # Example +/// # Examples /// /// ``` /// #[macro_use] extern crate log; @@ -192,9 +192,8 @@ macro_rules! debug { macro_rules! log_enabled { ($lvl:expr) => ({ let lvl = $lvl; - (lvl != ::log::DEBUG || cfg!(not(ndebug))) && + (lvl != ::log::DEBUG || cfg!(debug_assertions)) && lvl <= ::log::log_level() && ::log::mod_enabled(lvl, module_path!()) }) } - diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index 2673649f34..44187a4fc9 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -12,11 +12,12 @@ use core::prelude::*; use core::num::Int; +use core::num::wrapping::WrappingOps; use {Rng, SeedableRng, Rand}; -const KEY_WORDS : uint = 8; // 8 words for the 256-bit key -const STATE_WORDS : uint = 16; -const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of this writing +const KEY_WORDS : usize = 8; // 8 words for the 256-bit key +const STATE_WORDS : usize = 16; +const CHACHA_ROUNDS: usize = 20; // Cryptographically secure from 8 upwards as of this writing /// A random number generator that uses the ChaCha20 algorithm [1]. /// @@ -31,7 +32,7 @@ const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of pub struct ChaChaRng { buffer: [u32; STATE_WORDS], // Internal buffer of output state: [u32; STATE_WORDS], // Initial state - index: uint, // Index into state + index: usize, // Index into state } static EMPTY: ChaChaRng = ChaChaRng { @@ -43,10 +44,10 @@ static EMPTY: ChaChaRng = ChaChaRng { macro_rules! quarter_round{ ($a: expr, $b: expr, $c: expr, $d: expr) => {{ - $a += $b; $d ^= $a; $d = $d.rotate_left(16); - $c += $d; $b ^= $c; $b = $b.rotate_left(12); - $a += $b; $d ^= $a; $d = $d.rotate_left( 8); - $c += $d; $b ^= $c; $b = $b.rotate_left( 7); + $a = $a.wrapping_add($b); $d = $d ^ $a; $d = $d.rotate_left(16); + $c = $c.wrapping_add($d); $b = $b ^ $c; $b = $b.rotate_left(12); + $a = $a.wrapping_add($b); $d = $d ^ $a; $d = $d.rotate_left( 8); + $c = $c.wrapping_add($d); $b = $b ^ $c; $b = $b.rotate_left( 7); }} } @@ -74,7 +75,7 @@ fn core(output: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) { } for i in 0..STATE_WORDS { - output[i] += input[i]; + output[i] = output[i].wrapping_add(input[i]); } } @@ -172,7 +173,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { fn reseed(&mut self, seed: &'a [u32]) { // reset state - self.init(&[0u32; KEY_WORDS]); + self.init(&[0; KEY_WORDS]); // set key in place let key = &mut self.state[4 .. 4+KEY_WORDS]; for (k, s) in key.iter_mut().zip(seed.iter()) { @@ -197,7 +198,7 @@ impl Rand for ChaChaRng { for word in &mut key { *word = other.gen(); } - SeedableRng::from_seed(key.as_slice()) + SeedableRng::from_seed(&key[..]) } } @@ -244,7 +245,7 @@ mod test { fn test_rng_true_values() { // Test vectors 1 and 2 from // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04 - let seed : &[_] = &[0u32; 8]; + let seed : &[_] = &[0; 8]; let mut ra: ChaChaRng = SeedableRng::from_seed(seed); let v = (0..16).map(|_| ra.next_u32()).collect::>(); @@ -284,7 +285,7 @@ mod test { #[test] fn test_rng_clone() { - let seed : &[_] = &[0u32; 8]; + let seed : &[_] = &[0; 8]; let mut rng: ChaChaRng = SeedableRng::from_seed(seed); let mut clone = rng.clone(); for _ in 0..16 { diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index e4927902cb..2ba3164e1b 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -29,7 +29,7 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; /// Generate Normal Random /// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield /// College, Oxford -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Exp1(pub f64); // This could be done via `-rng.gen::().ln()` but that is slower. @@ -57,9 +57,10 @@ impl Rand for Exp1 { /// This distribution has density function: `f(x) = lambda * /// exp(-lambda * x)` for `x > 0`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{Exp, IndependentSample}; /// @@ -67,7 +68,7 @@ impl Rand for Exp1 { /// let v = exp.ind_sample(&mut rand::thread_rng()); /// println!("{} is from a Exp(2) distribution", v); /// ``` -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Exp { /// `lambda` stored as `1/lambda`, since this is what we scale by. lambda_inverse: f64 @@ -109,12 +110,12 @@ mod test { } } #[test] - #[should_fail] + #[should_panic] fn test_exp_invalid_lambda_zero() { Exp::new(0.0); } #[test] - #[should_fail] + #[should_panic] fn test_exp_invalid_lambda_neg() { Exp::new(-10.0); } diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 38eba0cfc7..d04e83e84f 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -37,9 +37,10 @@ use super::{IndependentSample, Sample, Exp}; /// == 1`, and using the boosting technique described in [1] for /// `shape < 1`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{IndependentSample, Gamma}; /// @@ -184,9 +185,10 @@ impl IndependentSample for GammaLargeShape { /// `k`, this uses the equivalent characterisation `χ²(k) = Gamma(k/2, /// 2)`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{ChiSquared, IndependentSample}; /// @@ -241,9 +243,10 @@ impl IndependentSample for ChiSquared { /// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) / /// (χ²(n)/n)`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{FisherF, IndependentSample}; /// @@ -285,9 +288,10 @@ impl IndependentSample for FisherF { /// The Student t distribution, `t(nu)`, where `nu` is the degrees of /// freedom. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{StudentT, IndependentSample}; /// @@ -356,7 +360,7 @@ mod test { } } #[test] - #[should_fail] + #[should_panic] fn test_chi_squared_invalid_dof() { ChiSquared::new(-1.0); } diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 5a85552dc3..432081063c 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -17,8 +17,6 @@ //! internally. The `IndependentSample` trait is for generating values //! that do not need to record state. -#![unstable(feature = "rand")] - use core::prelude::*; use core::num::{Float, Int}; use core::marker::PhantomData; @@ -78,7 +76,7 @@ impl IndependentSample for RandSample { /// A value with a particular weight for use with `WeightedChoice`. pub struct Weighted { /// The numerical weight of this item - pub weight: uint, + pub weight: usize, /// The actual item which is being weighted pub item: T, } @@ -90,19 +88,20 @@ pub struct Weighted { /// /// The `Clone` restriction is a limitation of the `Sample` and /// `IndependentSample` traits. Note that `&T` is (cheaply) `Clone` for -/// all `T`, as is `uint`, so one can store references or indices into +/// all `T`, as is `usize`, so one can store references or indices into /// another vector. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{Weighted, WeightedChoice, IndependentSample}; /// /// let mut items = vec!(Weighted { weight: 2, item: 'a' }, /// Weighted { weight: 4, item: 'b' }, /// Weighted { weight: 1, item: 'c' }); -/// let wc = WeightedChoice::new(items.as_mut_slice()); +/// let wc = WeightedChoice::new(&mut items[..]); /// let mut rng = rand::thread_rng(); /// for _ in 0..16 { /// // on average prints 'a' 4 times, 'b' 8 and 'c' twice. @@ -111,7 +110,7 @@ pub struct Weighted { /// ``` pub struct WeightedChoice<'a, T:'a> { items: &'a mut [Weighted], - weight_range: Range + weight_range: Range } impl<'a, T: Clone> WeightedChoice<'a, T> { @@ -120,12 +119,12 @@ impl<'a, T: Clone> WeightedChoice<'a, T> { /// Panics if: /// - `v` is empty /// - the total weight is 0 - /// - the total weight is larger than a `uint` can contain. + /// - the total weight is larger than a `usize` can contain. pub fn new(items: &'a mut [Weighted]) -> WeightedChoice<'a, T> { // strictly speaking, this is subsumed by the total weight == 0 case assert!(!items.is_empty(), "WeightedChoice::new called with no items"); - let mut running_total = 0; + let mut running_total = 0_usize; // we convert the list from individual weights to cumulative // weights so we can binary search. This *could* drop elements @@ -134,7 +133,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> { running_total = match running_total.checked_add(item.weight) { Some(n) => n, None => panic!("WeightedChoice::new called with a total weight \ - larger than a uint can contain") + larger than a usize can contain") }; item.weight = running_total; @@ -223,7 +222,7 @@ fn ziggurat( mut pdf: P, mut zero_case: Z) -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 { - static SCALE: f64 = (1u64 << 53) as f64; + const SCALE: f64 = (1u64 << 53) as f64; loop { // reimplement the f64 generation as an optimisation suggested // by the Doornik paper: we have a lot of precision-space @@ -239,7 +238,7 @@ fn ziggurat( // this may be slower than it would be otherwise.) // FIXME: investigate/optimise for the above. let bits: u64 = rng.gen(); - let i = (bits & 0xff) as uint; + let i = (bits & 0xff) as usize; let f = (bits >> 11) as f64 / SCALE; // u is either U(-1, 1) or U(0, 1) depending on if this is a @@ -257,7 +256,7 @@ fn ziggurat( return zero_case(rng, u); } // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1 - if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen() < pdf(x) { + if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen::() < pdf(x) { return x; } } @@ -271,7 +270,7 @@ mod tests { use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample}; #[derive(PartialEq, Debug)] - struct ConstRand(uint); + struct ConstRand(usize); impl Rand for ConstRand { fn rand(_: &mut R) -> ConstRand { ConstRand(0) @@ -351,18 +350,18 @@ mod tests { [50, 51, 52, 53, 54, 55, 56]); } - #[test] #[should_fail] + #[test] #[should_panic] fn test_weighted_choice_no_items() { - WeightedChoice::::new(&mut []); + WeightedChoice::::new(&mut []); } - #[test] #[should_fail] + #[test] #[should_panic] fn test_weighted_choice_zero_weight() { WeightedChoice::new(&mut [Weighted { weight: 0, item: 0}, Weighted { weight: 0, item: 1}]); } - #[test] #[should_fail] + #[test] #[should_panic] fn test_weighted_choice_weight_overflows() { - let x = (-1) as uint / 2; // x + x + 2 is the overflow + let x = (!0) as usize / 2; // x + x + 2 is the overflow WeightedChoice::new(&mut [Weighted { weight: x, item: 0 }, Weighted { weight: 1, item: 1 }, Weighted { weight: x, item: 2 }, diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index 83f202742d..fa41c3edfe 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -28,7 +28,7 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample}; /// Generate Normal Random /// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield /// College, Oxford -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct StandardNormal(pub f64); impl Rand for StandardNormal { @@ -73,9 +73,10 @@ impl Rand for StandardNormal { /// This uses the ZIGNOR variant of the Ziggurat method, see /// `StandardNormal` for more details. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{Normal, IndependentSample}; /// @@ -84,7 +85,7 @@ impl Rand for StandardNormal { /// let v = normal.ind_sample(&mut rand::thread_rng()); /// println!("{} is from a N(2, 9) distribution", v) /// ``` -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Normal { mean: f64, std_dev: f64, @@ -121,9 +122,10 @@ impl IndependentSample for Normal { /// If `X` is log-normal distributed, then `ln(X)` is `N(mean, /// std_dev**2)` distributed. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::distributions::{LogNormal, IndependentSample}; /// @@ -132,7 +134,7 @@ impl IndependentSample for Normal { /// let v = log_normal.ind_sample(&mut rand::thread_rng()); /// println!("{} is from an ln N(2, 9) distribution", v) /// ``` -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct LogNormal { norm: Normal } @@ -175,7 +177,7 @@ mod tests { } } #[test] - #[should_fail] + #[should_panic] fn test_normal_invalid_sd() { Normal::new(10.0, -1.0); } @@ -191,7 +193,7 @@ mod tests { } } #[test] - #[should_fail] + #[should_panic] fn test_log_normal_invalid_sd() { LogNormal::new(10.0, -1.0); } diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index 6eb1d68a08..347d494259 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -12,8 +12,9 @@ // this is surprisingly complicated to be both generic & correct -use core::prelude::{PartialOrd}; +use core::prelude::PartialOrd; use core::num::Int; +use core::num::wrapping::WrappingOps; use Rng; use distributions::{Sample, IndependentSample}; @@ -22,8 +23,8 @@ use distributions::{Sample, IndependentSample}; /// /// This gives a uniform distribution (assuming the RNG used to sample /// it is itself uniform & the `SampleRange` implementation for the -/// given type is correct), even for edge cases like `low = 0u8`, -/// `high = 170u8`, for which a naive modulo operation would return +/// given type is correct), even for edge cases like `low = 0`, +/// `high = 170`, for which a naive modulo operation would return /// numbers less than 85 with double the probability to those greater /// than 85. /// @@ -32,9 +33,10 @@ use distributions::{Sample, IndependentSample}; /// primitive integer types satisfy this property, and the float types /// normally satisfy it, but rounding may mean `high` can occur. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand::distributions::{IndependentSample, Range}; /// /// fn main() { @@ -97,7 +99,7 @@ macro_rules! integer_impl { // bijection. fn construct_range(low: $ty, high: $ty) -> Range<$ty> { - let range = high as $unsigned - low as $unsigned; + let range = (high as $unsigned).wrapping_sub(low as $unsigned); let unsigned_max: $unsigned = Int::max_value(); // this is the largest number that fits into $unsigned @@ -122,7 +124,7 @@ macro_rules! integer_impl { // be uniformly distributed) if v < r.accept_zone as $unsigned { // and return it, with some adjustments - return r.low + (v % r.range as $unsigned) as $ty; + return r.low.wrapping_add((v % r.range as $unsigned) as $ty); } } } @@ -134,12 +136,12 @@ integer_impl! { i8, u8 } integer_impl! { i16, u16 } integer_impl! { i32, u32 } integer_impl! { i64, u64 } -integer_impl! { int, uint } +integer_impl! { isize, usize } integer_impl! { u8, u8 } integer_impl! { u16, u16 } integer_impl! { u32, u32 } integer_impl! { u64, u64 } -integer_impl! { uint, uint } +integer_impl! { usize, usize } macro_rules! float_impl { ($ty:ty) => { @@ -152,7 +154,7 @@ macro_rules! float_impl { } } fn sample_range(r: &Range<$ty>, rng: &mut R) -> $ty { - r.low + r.range * rng.gen() + r.low + r.range * rng.gen::<$ty>() } } } @@ -168,12 +170,12 @@ mod tests { use distributions::{Sample, IndependentSample}; use super::Range as Range; - #[should_fail] + #[should_panic] #[test] fn test_range_bad_limits_equal() { Range::new(10, 10); } - #[should_fail] + #[should_panic] #[test] fn test_range_bad_limits_flipped() { Range::new(10, 5); @@ -200,8 +202,8 @@ mod tests { )* }} } - t!(i8, i16, i32, i64, int, - u8, u16, u32, u64, uint) + t!(i8, i16, i32, i64, isize, + u8, u16, u32, u64, usize) } #[test] diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 701749ff34..a7f7889783 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -10,15 +10,21 @@ //! The ISAAC random number generator. +#![allow(non_camel_case_types)] + use core::prelude::*; use core::slice; -use core::iter::{range_step, repeat}; +use core::iter::repeat; +use core::num::Wrapping as w; use {Rng, SeedableRng, Rand}; -const RAND_SIZE_LEN: u32 = 8; -const RAND_SIZE: u32 = 1 << (RAND_SIZE_LEN as uint); -const RAND_SIZE_UINT: uint = 1 << (RAND_SIZE_LEN as uint); +type w32 = w; +type w64 = w; + +const RAND_SIZE_LEN: usize = 8; +const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN; +const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN; /// A random number generator that uses the ISAAC algorithm[1]. /// @@ -32,18 +38,18 @@ const RAND_SIZE_UINT: uint = 1 << (RAND_SIZE_LEN as uint); #[derive(Copy)] pub struct IsaacRng { cnt: u32, - rsl: [u32; RAND_SIZE_UINT], - mem: [u32; RAND_SIZE_UINT], - a: u32, - b: u32, - c: u32 + rsl: [w32; RAND_SIZE_USIZE], + mem: [w32; RAND_SIZE_USIZE], + a: w32, + b: w32, + c: w32, } static EMPTY: IsaacRng = IsaacRng { cnt: 0, - rsl: [0; RAND_SIZE_UINT], - mem: [0; RAND_SIZE_UINT], - a: 0, b: 0, c: 0 + rsl: [w(0); RAND_SIZE_USIZE], + mem: [w(0); RAND_SIZE_USIZE], + a: w(0), b: w(0), c: w(0), }; impl IsaacRng { @@ -60,7 +66,7 @@ impl IsaacRng { /// of `rsl` as a seed, otherwise construct one algorithmically (not /// randomly). fn init(&mut self, use_rsl: bool) { - let mut a = 0x9e3779b9; + let mut a = w(0x9e3779b9); let mut b = a; let mut c = a; let mut d = a; @@ -71,14 +77,14 @@ impl IsaacRng { macro_rules! mix { () => {{ - a^=b<<11; d+=a; b+=c; - b^=c>>2; e+=b; c+=d; - c^=d<<8; f+=c; d+=e; - d^=e>>16; g+=d; e+=f; - e^=f<<10; h+=e; f+=g; - f^=g>>4; a+=f; g+=h; - g^=h<<8; b+=g; h+=a; - h^=a>>9; c+=h; a+=b; + a=a^(b<<11); d=d+a; b=b+c; + b=b^(c>>2); e=e+b; c=c+d; + c=c^(d<<8); f=f+c; d=d+e; + d=d^(e>>16); g=g+d; e=e+f; + e=e^(f<<10); h=h+e; f=f+g; + f=f^(g>>4); a=a+f; g=g+h; + g=g^(h<<8); b=b+g; h=h+a; + h=h^(a>>9); c=c+h; a=a+b; }} } @@ -89,11 +95,11 @@ impl IsaacRng { if use_rsl { macro_rules! memloop { ($arr:expr) => {{ - for i in range_step(0, RAND_SIZE as uint, 8) { - a+=$arr[i ]; b+=$arr[i+1]; - c+=$arr[i+2]; d+=$arr[i+3]; - e+=$arr[i+4]; f+=$arr[i+5]; - g+=$arr[i+6]; h+=$arr[i+7]; + for i in (0..RAND_SIZE_USIZE).step_by(8) { + a=a+$arr[i ]; b=b+$arr[i+1]; + c=c+$arr[i+2]; d=d+$arr[i+3]; + e=e+$arr[i+4]; f=f+$arr[i+5]; + g=g+$arr[i+6]; h=h+$arr[i+7]; mix!(); self.mem[i ]=a; self.mem[i+1]=b; self.mem[i+2]=c; self.mem[i+3]=d; @@ -106,7 +112,7 @@ impl IsaacRng { memloop!(self.rsl); memloop!(self.mem); } else { - for i in range_step(0, RAND_SIZE as uint, 8) { + for i in (0..RAND_SIZE_USIZE).step_by(8) { mix!(); self.mem[i ]=a; self.mem[i+1]=b; self.mem[i+2]=c; self.mem[i+3]=d; @@ -122,31 +128,31 @@ impl IsaacRng { #[inline] #[allow(unsigned_negation)] fn isaac(&mut self) { - self.c += 1; + self.c = self.c + w(1); // abbreviations let mut a = self.a; let mut b = self.b + self.c; - static MIDPOINT: uint = (RAND_SIZE / 2) as uint; + const MIDPOINT: usize = RAND_SIZE_USIZE / 2; macro_rules! ind { - ($x:expr) => ( self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))] ) + ($x:expr) => (self.mem[($x >> 2).0 as usize & (RAND_SIZE_USIZE - 1)] ) } let r = [(0, MIDPOINT), (MIDPOINT, 0)]; - for &(mr_offset, m2_offset) in &r { + for &(mr_offset, m2_offset) in r.iter() { macro_rules! rngstepp { ($j:expr, $shift:expr) => {{ let base = $j; - let mix = a << $shift as uint; + let mix = a << $shift; let x = self.mem[base + mr_offset]; a = (a ^ mix) + self.mem[base + m2_offset]; let y = ind!(x) + a + b; self.mem[base + mr_offset] = y; - b = ind!(y >> RAND_SIZE_LEN as uint) + x; + b = ind!(y >> RAND_SIZE_LEN) + x; self.rsl[base + mr_offset] = b; }} } @@ -154,19 +160,19 @@ impl IsaacRng { macro_rules! rngstepn { ($j:expr, $shift:expr) => {{ let base = $j; - let mix = a >> $shift as uint; + let mix = a >> $shift; let x = self.mem[base + mr_offset]; a = (a ^ mix) + self.mem[base + m2_offset]; let y = ind!(x) + a + b; self.mem[base + mr_offset] = y; - b = ind!(y >> RAND_SIZE_LEN as uint) + x; + b = ind!(y >> RAND_SIZE_LEN) + x; self.rsl[base + mr_offset] = b; }} } - for i in range_step(0, MIDPOINT, 4) { + for i in (0..MIDPOINT).step_by(4) { rngstepp!(i + 0, 13); rngstepn!(i + 1, 6); rngstepp!(i + 2, 2); @@ -207,7 +213,7 @@ impl Rng for IsaacRng { // (the % is cheaply telling the optimiser that we're always // in bounds, without unsafe. NB. this is a power of two, so // it optimises to a bitwise mask). - self.rsl[(self.cnt % RAND_SIZE) as uint] + self.rsl[(self.cnt % RAND_SIZE) as usize].0 } } @@ -215,15 +221,15 @@ impl<'a> SeedableRng<&'a [u32]> for IsaacRng { fn reseed(&mut self, seed: &'a [u32]) { // make the seed into [seed[0], seed[1], ..., seed[seed.len() // - 1], 0, 0, ...], to fill rng.rsl. - let seed_iter = seed.iter().cloned().chain(repeat(0u32)); + let seed_iter = seed.iter().cloned().chain(repeat(0)); for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) { - *rsl_elem = seed_elem; + *rsl_elem = w(seed_elem); } self.cnt = 0; - self.a = 0; - self.b = 0; - self.c = 0; + self.a = w(0); + self.b = w(0); + self.c = w(0); self.init(true); } @@ -246,21 +252,21 @@ impl Rand for IsaacRng { unsafe { let ptr = ret.rsl.as_mut_ptr() as *mut u8; - let slice = slice::from_raw_parts_mut(ptr, (RAND_SIZE * 4) as uint); + let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_USIZE * 4); other.fill_bytes(slice); } ret.cnt = 0; - ret.a = 0; - ret.b = 0; - ret.c = 0; + ret.a = w(0); + ret.b = w(0); + ret.c = w(0); ret.init(true); return ret; } } -const RAND_SIZE_64_LEN: uint = 8; -const RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN; +const RAND_SIZE_64_LEN: usize = 8; +const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN; /// A random number generator that uses ISAAC-64[1], the 64-bit /// variant of the ISAAC algorithm. @@ -274,19 +280,19 @@ const RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN; /// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html) #[derive(Copy)] pub struct Isaac64Rng { - cnt: uint, - rsl: [u64; RAND_SIZE_64], - mem: [u64; RAND_SIZE_64], - a: u64, - b: u64, - c: u64, + cnt: usize, + rsl: [w64; RAND_SIZE_64], + mem: [w64; RAND_SIZE_64], + a: w64, + b: w64, + c: w64, } static EMPTY_64: Isaac64Rng = Isaac64Rng { cnt: 0, - rsl: [0; RAND_SIZE_64], - mem: [0; RAND_SIZE_64], - a: 0, b: 0, c: 0, + rsl: [w(0); RAND_SIZE_64], + mem: [w(0); RAND_SIZE_64], + a: w(0), b: w(0), c: w(0), }; impl Isaac64Rng { @@ -304,7 +310,7 @@ impl Isaac64Rng { fn init(&mut self, use_rsl: bool) { macro_rules! init { ($var:ident) => ( - let mut $var = 0x9e3779b97f4a7c13; + let mut $var = w(0x9e3779b97f4a7c13); ) } init!(a); init!(b); init!(c); init!(d); @@ -312,14 +318,14 @@ impl Isaac64Rng { macro_rules! mix { () => {{ - a-=e; f^=h>>9; h+=a; - b-=f; g^=a<<9; a+=b; - c-=g; h^=b>>23; b+=c; - d-=h; a^=c<<15; c+=d; - e-=a; b^=d>>14; d+=e; - f-=b; c^=e<<20; e+=f; - g-=c; d^=f>>17; f+=g; - h-=d; e^=g<<14; g+=h; + a=a-e; f=f^(h>>9); h=h+a; + b=b-f; g=g^(a<<9); a=a+b; + c=c-g; h=h^(b>>23); b=b+c; + d=d-h; a=a^(c<<15); c=c+d; + e=e-a; b=b^(d>>14); d=d+e; + f=f-b; c=c^(e<<20); e=e+f; + g=g-c; d=d^(f>>17); f=f+g; + h=h-d; e=e^(g<<14); g=g+h; }} } @@ -331,10 +337,10 @@ impl Isaac64Rng { macro_rules! memloop { ($arr:expr) => {{ for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) { - a+=$arr[i ]; b+=$arr[i+1]; - c+=$arr[i+2]; d+=$arr[i+3]; - e+=$arr[i+4]; f+=$arr[i+5]; - g+=$arr[i+6]; h+=$arr[i+7]; + a=a+$arr[i ]; b=b+$arr[i+1]; + c=c+$arr[i+2]; d=d+$arr[i+3]; + e=e+$arr[i+4]; f=f+$arr[i+5]; + g=g+$arr[i+6]; h=h+$arr[i+7]; mix!(); self.mem[i ]=a; self.mem[i+1]=b; self.mem[i+2]=c; self.mem[i+3]=d; @@ -361,25 +367,25 @@ impl Isaac64Rng { /// Refills the output buffer (`self.rsl`) fn isaac64(&mut self) { - self.c += 1; + self.c = self.c + w(1); // abbreviations let mut a = self.a; let mut b = self.b + self.c; - const MIDPOINT: uint = RAND_SIZE_64 / 2; - const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)]; + const MIDPOINT: usize = RAND_SIZE_64 / 2; + const MP_VEC: [(usize, usize); 2] = [(0,MIDPOINT), (MIDPOINT, 0)]; macro_rules! ind { ($x:expr) => { - *self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1)) + *self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1)) } } - for &(mr_offset, m2_offset) in &MP_VEC { + for &(mr_offset, m2_offset) in MP_VEC.iter() { for base in (0..MIDPOINT / 4).map(|i| i * 4) { macro_rules! rngstepp { ($j:expr, $shift:expr) => {{ let base = base + $j; - let mix = a ^ (a << $shift as uint); + let mix = a ^ (a << $shift); let mix = if $j == 0 {!mix} else {mix}; unsafe { @@ -397,7 +403,7 @@ impl Isaac64Rng { macro_rules! rngstepn { ($j:expr, $shift:expr) => {{ let base = base + $j; - let mix = a ^ (a >> $shift as uint); + let mix = a ^ (a >> $shift); let mix = if $j == 0 {!mix} else {mix}; unsafe { @@ -450,7 +456,7 @@ impl Rng for Isaac64Rng { // See corresponding location in IsaacRng.next_u32 for // explanation. debug_assert!(self.cnt < RAND_SIZE_64); - self.rsl[(self.cnt % RAND_SIZE_64) as uint] + self.rsl[(self.cnt % RAND_SIZE_64) as usize].0 } } @@ -458,15 +464,15 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng { fn reseed(&mut self, seed: &'a [u64]) { // make the seed into [seed[0], seed[1], ..., seed[seed.len() // - 1], 0, 0, ...], to fill rng.rsl. - let seed_iter = seed.iter().cloned().chain(repeat(0u64)); + let seed_iter = seed.iter().cloned().chain(repeat(0)); for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) { - *rsl_elem = seed_elem; + *rsl_elem = w(seed_elem); } self.cnt = 0; - self.a = 0; - self.b = 0; - self.c = 0; + self.a = w(0); + self.b = w(0); + self.c = w(0); self.init(true); } @@ -489,13 +495,13 @@ impl Rand for Isaac64Rng { unsafe { let ptr = ret.rsl.as_mut_ptr() as *mut u8; - let slice = slice::from_raw_parts_mut(ptr, (RAND_SIZE_64 * 8) as uint); + let slice = slice::from_raw_parts_mut(ptr, RAND_SIZE_64 * 8); other.fill_bytes(slice); } ret.cnt = 0; - ret.a = 0; - ret.b = 0; - ret.c = 0; + ret.a = w(0); + ret.b = w(0); + ret.c = w(0); ret.init(true); return ret; @@ -514,16 +520,16 @@ mod test { #[test] fn test_rng_32_rand_seeded() { let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut ra: IsaacRng = SeedableRng::from_seed(&*s); - let mut rb: IsaacRng = SeedableRng::from_seed(&*s); + let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]); + let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]); assert!(order::equals(ra.gen_ascii_chars().take(100), rb.gen_ascii_chars().take(100))); } #[test] fn test_rng_64_rand_seeded() { let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut ra: Isaac64Rng = SeedableRng::from_seed(&*s); - let mut rb: Isaac64Rng = SeedableRng::from_seed(&*s); + let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]); + let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]); assert!(order::equals(ra.gen_ascii_chars().take(100), rb.gen_ascii_chars().take(100))); } @@ -548,7 +554,7 @@ mod test { #[test] fn test_rng_32_reseed() { let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut r: IsaacRng = SeedableRng::from_seed(&*s); + let mut r: IsaacRng = SeedableRng::from_seed(&s[..]); let string1: String = r.gen_ascii_chars().take(100).collect(); r.reseed(&s); @@ -559,7 +565,7 @@ mod test { #[test] fn test_rng_64_reseed() { let s = ::test::rng().gen_iter::().take(256).collect::>(); - let mut r: Isaac64Rng = SeedableRng::from_seed(&*s); + let mut r: Isaac64Rng = SeedableRng::from_seed(&s[..]); let string1: String = r.gen_ascii_chars().take(100).collect(); r.reseed(&s); diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 7588bf7c51..15d3d981eb 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -16,22 +16,26 @@ //! is not recommended to use this library directly, but rather the official //! interface through `std::rand`. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rand"] #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(int_uint)] #![feature(no_std)] #![no_std] #![unstable(feature = "rand")] #![feature(staged_api)] #![staged_api] #![feature(core)] +#![feature(step_by)] #![deprecated(reason = "use the crates.io `rand` library instead", since = "1.0.0-alpha")] +#![cfg_attr(test, feature(test, rand, rustc_private))] + #![allow(deprecated)] #[macro_use] @@ -50,7 +54,7 @@ use distributions::{Range, IndependentSample}; use distributions::range::SampleRange; #[cfg(test)] -static RAND_BENCH_N: u64 = 100; +const RAND_BENCH_N: u64 = 100; pub mod distributions; pub mod isaac; @@ -95,8 +99,8 @@ pub trait Rng : Sized { /// See `Closed01` for the closed interval `[0,1]`, and /// `Open01` for the open interval `(0,1)`. fn next_f32(&mut self) -> f32 { - const MANTISSA_BITS: uint = 24; - const IGNORED_BITS: uint = 8; + const MANTISSA_BITS: usize = 24; + const IGNORED_BITS: usize = 8; const SCALE: f32 = (1u64 << MANTISSA_BITS) as f32; // using any more than `MANTISSA_BITS` bits will @@ -117,8 +121,8 @@ pub trait Rng : Sized { /// See `Closed01` for the closed interval `[0,1]`, and /// `Open01` for the open interval `(0,1)`. fn next_f64(&mut self) -> f64 { - const MANTISSA_BITS: uint = 53; - const IGNORED_BITS: uint = 11; + const MANTISSA_BITS: usize = 53; + const IGNORED_BITS: usize = 11; const SCALE: f64 = (1u64 << MANTISSA_BITS) as f64; (self.next_u64() >> IGNORED_BITS) as f64 / SCALE @@ -142,14 +146,15 @@ pub trait Rng : Sized { /// (e.g. reading past the end of a file that is being used as the /// source of randomness). /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand, core)] /// use std::rand::{thread_rng, Rng}; /// - /// let mut v = [0u8; 13579]; + /// let mut v = [0; 13579]; /// thread_rng().fill_bytes(&mut v); - /// println!("{:?}", v.as_slice()); + /// println!("{:?}", &v[..]); /// ``` fn fill_bytes(&mut self, dest: &mut [u8]) { // this could, in theory, be done by transmuting dest to a @@ -177,13 +182,14 @@ pub trait Rng : Sized { /// Return a random value of a `Rand` type. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand)] /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); - /// let x: uint = rng.gen(); + /// let x: usize = rng.gen(); /// println!("{}", x); /// println!("{:?}", rng.gen::<(f64, bool)>()); /// ``` @@ -195,13 +201,14 @@ pub trait Rng : Sized { /// Return an iterator that will yield an infinite number of randomly /// generated items. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(rand)] /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); - /// let x = rng.gen_iter::().take(10).collect::>(); + /// let x = rng.gen_iter::().take(10).collect::>(); /// println!("{:?}", x); /// println!("{:?}", rng.gen_iter::<(f64, bool)>().take(5) /// .collect::>()); @@ -222,13 +229,14 @@ pub trait Rng : Sized { /// /// Panics if `low >= high`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand)] /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); - /// let n: uint = rng.gen_range(0, 10); + /// let n: usize = rng.gen_range(0, 10); /// println!("{}", n); /// let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64); /// println!("{}", m); @@ -240,23 +248,25 @@ pub trait Rng : Sized { /// Return a bool with a 1 in n chance of true /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand)] /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// println!("{}", rng.gen_weighted_bool(3)); /// ``` - fn gen_weighted_bool(&mut self, n: uint) -> bool { + fn gen_weighted_bool(&mut self, n: usize) -> bool { n <= 1 || self.gen_range(0, n) == 0 } /// Return an iterator of random characters from the set A-Z,a-z,0-9. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand)] /// use std::rand::{thread_rng, Rng}; /// /// let s: String = thread_rng().gen_ascii_chars().take(10).collect(); @@ -270,9 +280,10 @@ pub trait Rng : Sized { /// /// Return `None` if `values` is empty. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(rand)] /// use std::rand::{thread_rng, Rng}; /// /// let choices = [1, 2, 4, 8, 16, 32]; @@ -290,17 +301,18 @@ pub trait Rng : Sized { /// Shuffle a mutable slice in place. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand, core)] /// use std::rand::{thread_rng, Rng}; /// /// let mut rng = thread_rng(); /// let mut y = [1, 2, 3]; /// rng.shuffle(&mut y); - /// println!("{:?}", y.as_slice()); + /// println!("{:?}", y); /// rng.shuffle(&mut y); - /// println!("{:?}", y.as_slice()); + /// println!("{:?}", y); /// ``` fn shuffle(&mut self, values: &mut [T]) { let mut i = values.len(); @@ -340,7 +352,7 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> { type Item = char; fn next(&mut self) -> Option { - static GEN_ASCII_STR_CHARSET: &'static [u8] = + const GEN_ASCII_STR_CHARSET: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789"; @@ -353,9 +365,10 @@ impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> { pub trait SeedableRng: Rng { /// Reseed an RNG with the given seed. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand)] /// use std::rand::{Rng, SeedableRng, StdRng}; /// /// let seed: &[_] = &[1, 2, 3, 4]; @@ -368,9 +381,10 @@ pub trait SeedableRng: Rng { /// Create a new RNG with the given seed. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rand)] /// use std::rand::{Rng, SeedableRng, StdRng}; /// /// let seed: &[_] = &[1, 2, 3, 4]; @@ -473,8 +487,10 @@ impl Rand for XorShiftRng { /// `Rand` implementation for `f32` and `f64` for the half-open /// `[0,1)`. /// -/// # Example -/// ```rust +/// # Examples +/// +/// ``` +/// # #![feature(rand)] /// use std::rand::{random, Open01}; /// /// let Open01(val) = random::>(); @@ -489,9 +505,10 @@ pub struct Open01(pub F); /// `Rand` implementation of `f32` and `f64` for the half-open /// `[0,1)`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand::{random, Closed01}; /// /// let Closed01(val) = random::>(); diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs index d5c5d50046..e2a5276cc7 100644 --- a/src/librand/rand_impls.rs +++ b/src/librand/rand_impls.rs @@ -12,18 +12,18 @@ use core::prelude::*; use core::char; -use core::int; -use core::uint; +use core::isize; +use core::usize; use {Rand,Rng}; -impl Rand for int { +impl Rand for isize { #[inline] - fn rand(rng: &mut R) -> int { - if int::BITS == 32 { - rng.gen::() as int + fn rand(rng: &mut R) -> isize { + if isize::BITS == 32 { + rng.gen::() as isize } else { - rng.gen::() as int + rng.gen::() as isize } } } @@ -56,13 +56,13 @@ impl Rand for i64 { } } -impl Rand for uint { +impl Rand for usize { #[inline] - fn rand(rng: &mut R) -> uint { - if uint::BITS == 32 { - rng.gen::() as uint + fn rand(rng: &mut R) -> usize { + if usize::BITS == 32 { + rng.gen::() as usize } else { - rng.gen::() as uint + rng.gen::() as usize } } } @@ -141,7 +141,7 @@ impl Rand for char { #[inline] fn rand(rng: &mut R) -> char { // a char is 21 bits - static CHAR_MASK: u32 = 0x001f_ffff; + const CHAR_MASK: u32 = 0x001f_ffff; loop { // Rejection sampling. About 0.2% of numbers with at most // 21-bits are invalid codepoints (surrogates), so this @@ -214,7 +214,6 @@ impl Rand for Option { #[cfg(test)] mod tests { - use std::prelude::v1::*; use std::rand::{Rng, thread_rng, Open01, Closed01}; struct ConstantRng(u64); diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index f4d3e975b7..98d1bbf5af 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -18,14 +18,14 @@ use core::default::Default; /// How many bytes of entropy the underling RNG is allowed to generate /// before it is reseeded. -static DEFAULT_GENERATION_THRESHOLD: uint = 32 * 1024; +const DEFAULT_GENERATION_THRESHOLD: usize = 32 * 1024; /// A wrapper around any RNG which reseeds the underlying RNG after it /// has generated a certain number of random bytes. pub struct ReseedingRng { rng: R, - generation_threshold: uint, - bytes_generated: uint, + generation_threshold: usize, + bytes_generated: usize, /// Controls the behaviour when reseeding the RNG. pub reseeder: Rsdr, } @@ -38,7 +38,7 @@ impl> ReseedingRng { /// * `rng`: the random number generator to use. /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG. /// * `reseeder`: the reseeding object to use. - pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng { + pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng { ReseedingRng { rng: rng, generation_threshold: generation_threshold, @@ -100,9 +100,10 @@ impl, Rsdr: Reseeder + Default> /// Something that can be used to reseed an RNG via `ReseedingRng`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand::{Rng, SeedableRng, StdRng}; /// use std::rand::reseeding::{Reseeder, ReseedingRng}; /// @@ -133,12 +134,8 @@ pub trait Reseeder { /// Reseed an RNG using a `Default` instance. This reseeds by /// replacing the RNG with the result of a `Default::default` call. -#[derive(Copy)] -pub struct ReseedWithDefault { __hack: [u8; 0] } -// FIXME(#21721) used to be an unit struct but that can cause -// certain LLVM versions to abort during optimizations. -#[allow(non_upper_case_globals)] -pub const ReseedWithDefault: ReseedWithDefault = ReseedWithDefault { __hack: [] }; +#[derive(Copy, Clone)] +pub struct ReseedWithDefault; impl Reseeder for ReseedWithDefault { fn reseed(&mut self, rng: &mut R) { @@ -216,10 +213,10 @@ mod test { assert_eq!(string1, string2); } - static FILL_BYTES_V_LEN: uint = 13579; + const FILL_BYTES_V_LEN: usize = 13579; #[test] fn test_rng_fill_bytes() { - let mut v = repeat(0u8).take(FILL_BYTES_V_LEN).collect::>(); + let mut v = repeat(0).take(FILL_BYTES_V_LEN).collect::>(); ::test::rng().fill_bytes(&mut v); // Sanity test: if we've gotten here, `fill_bytes` has not infinitely diff --git a/src/librbml/io.rs b/src/librbml/io.rs deleted file mode 100644 index 230fda11ab..0000000000 --- a/src/librbml/io.rs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::old_io::{IoError, IoResult, SeekStyle}; -use std::old_io; -use std::slice; -use std::iter::repeat; - -static BUF_CAPACITY: uint = 128; - -fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult { - // compute offset as signed and clamp to prevent overflow - let pos = match seek { - old_io::SeekSet => 0, - old_io::SeekEnd => end, - old_io::SeekCur => cur, - } as i64; - - if offset + pos < 0 { - Err(IoError { - kind: old_io::InvalidInput, - desc: "invalid seek to a negative offset", - detail: None - }) - } else { - Ok((offset + pos) as u64) - } -} - -/// Writes to an owned, growable byte vector that supports seeking. -/// -/// # Example -/// -/// ```rust -/// # #![allow(unused_must_use)] -/// use rbml::io::SeekableMemWriter; -/// -/// let mut w = SeekableMemWriter::new(); -/// w.write(&[0, 1, 2]); -/// -/// assert_eq!(w.unwrap(), vec!(0, 1, 2)); -/// ``` -pub struct SeekableMemWriter { - buf: Vec, - pos: uint, -} - -impl SeekableMemWriter { - /// Create a new `SeekableMemWriter`. - #[inline] - pub fn new() -> SeekableMemWriter { - SeekableMemWriter::with_capacity(BUF_CAPACITY) - } - /// Create a new `SeekableMemWriter`, allocating at least `n` bytes for - /// the internal buffer. - #[inline] - pub fn with_capacity(n: uint) -> SeekableMemWriter { - SeekableMemWriter { buf: Vec::with_capacity(n), pos: 0 } - } - - /// Acquires an immutable reference to the underlying buffer of this - /// `SeekableMemWriter`. - /// - /// No method is exposed for acquiring a mutable reference to the buffer - /// because it could corrupt the state of this `MemWriter`. - #[inline] - pub fn get_ref<'a>(&'a self) -> &'a [u8] { &self.buf } - - /// Unwraps this `SeekableMemWriter`, returning the underlying buffer - #[inline] - pub fn unwrap(self) -> Vec { self.buf } -} - -impl Writer for SeekableMemWriter { - #[inline] - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - if self.pos == self.buf.len() { - self.buf.push_all(buf) - } else { - // Make sure the internal buffer is as least as big as where we - // currently are - let difference = self.pos as i64 - self.buf.len() as i64; - if difference > 0 { - self.buf.extend(repeat(0).take(difference as uint)); - } - - // Figure out what bytes will be used to overwrite what's currently - // there (left), and what will be appended on the end (right) - let cap = self.buf.len() - self.pos; - let (left, right) = if cap <= buf.len() { - (&buf[..cap], &buf[cap..]) - } else { - let result: (_, &[_]) = (buf, &[]); - result - }; - - // Do the necessary writes - if left.len() > 0 { - slice::bytes::copy_memory(&mut self.buf[self.pos..], left); - } - if right.len() > 0 { - self.buf.push_all(right); - } - } - - // Bump us forward - self.pos += buf.len(); - Ok(()) - } -} - -impl Seek for SeekableMemWriter { - #[inline] - fn tell(&self) -> IoResult { Ok(self.pos as u64) } - - #[inline] - fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { - let new = try!(combine(style, self.pos, self.buf.len(), pos)); - self.pos = new as uint; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - extern crate test; - use super::SeekableMemWriter; - use std::old_io; - use std::iter::repeat; - use test::Bencher; - - #[test] - fn test_seekable_mem_writer() { - let mut writer = SeekableMemWriter::new(); - assert_eq!(writer.tell(), Ok(0)); - writer.write(&[0]).unwrap(); - assert_eq!(writer.tell(), Ok(1)); - writer.write(&[1, 2, 3]).unwrap(); - writer.write(&[4, 5, 6, 7]).unwrap(); - assert_eq!(writer.tell(), Ok(8)); - let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; - assert_eq!(writer.get_ref(), b); - - writer.seek(0, old_io::SeekSet).unwrap(); - assert_eq!(writer.tell(), Ok(0)); - writer.write(&[3, 4]).unwrap(); - let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; - assert_eq!(writer.get_ref(), b); - - writer.seek(1, old_io::SeekCur).unwrap(); - writer.write(&[0, 1]).unwrap(); - let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; - assert_eq!(writer.get_ref(), b); - - writer.seek(-1, old_io::SeekEnd).unwrap(); - writer.write(&[1, 2]).unwrap(); - let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; - assert_eq!(writer.get_ref(), b); - - writer.seek(1, old_io::SeekEnd).unwrap(); - writer.write(&[1]).unwrap(); - let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; - assert_eq!(writer.get_ref(), b); - } - - #[test] - fn seek_past_end() { - let mut r = SeekableMemWriter::new(); - r.seek(10, old_io::SeekSet).unwrap(); - assert!(r.write(&[3]).is_ok()); - } - - #[test] - fn seek_before_0() { - let mut r = SeekableMemWriter::new(); - assert!(r.seek(-1, old_io::SeekSet).is_err()); - } - - fn do_bench_seekable_mem_writer(b: &mut Bencher, times: uint, len: uint) { - let src: Vec = repeat(5).take(len).collect(); - - b.bytes = (times * len) as u64; - b.iter(|| { - let mut wr = SeekableMemWriter::new(); - for _ in 0..times { - wr.write(&src).unwrap(); - } - - let v = wr.unwrap(); - assert_eq!(v.len(), times * len); - assert!(v.iter().all(|x| *x == 5)); - }); - } - - #[bench] - fn bench_seekable_mem_writer_001_0000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 0) - } - - #[bench] - fn bench_seekable_mem_writer_001_0010(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 10) - } - - #[bench] - fn bench_seekable_mem_writer_001_0100(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 100) - } - - #[bench] - fn bench_seekable_mem_writer_001_1000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 1, 1000) - } - - #[bench] - fn bench_seekable_mem_writer_100_0000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 0) - } - - #[bench] - fn bench_seekable_mem_writer_100_0010(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 10) - } - - #[bench] - fn bench_seekable_mem_writer_100_0100(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 100) - } - - #[bench] - fn bench_seekable_mem_writer_100_1000(b: &mut Bencher) { - do_bench_seekable_mem_writer(b, 100, 1000) - } -} diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 4af322089d..e2875ac8ca 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,13 +8,111 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Really Bad Markup Language (rbml) is a temporary measure until we migrate -//! the rust object metadata to a better serialization format. It is not -//! intended to be used by users. +//! Really Bad Markup Language (rbml) is an internal serialization format of rustc. +//! This is not intended to be used by users. //! -//! It is loosely based on the Extensible Binary Markup Language (ebml): -//! http://www.matroska.org/technical/specs/rfc/index.html +//! Originally based on the Extensible Binary Markup Language +//! (ebml; http://www.matroska.org/technical/specs/rfc/index.html), +//! it is now a separate format tuned for the rust object metadata. +//! +//! # Encoding +//! +//! RBML document consists of the tag, length and data. +//! The encoded data can contain multiple RBML documents concatenated. +//! +//! **Tags** are a hint for the following data. +//! Tags are a number from 0x000 to 0xfff, where 0xf0 through 0xff is reserved. +//! Tags less than 0xf0 are encoded in one literal byte. +//! Tags greater than 0xff are encoded in two big-endian bytes, +//! where the tag number is ORed with 0xf000. (E.g. tag 0x123 = `f1 23`) +//! +//! **Lengths** encode the length of the following data. +//! It is a variable-length unsigned isize, and one of the following forms: +//! +//! - `80` through `fe` for lengths up to 0x7e; +//! - `40 ff` through `7f ff` for lengths up to 0x3fff; +//! - `20 40 00` through `3f ff ff` for lengths up to 0x1fffff; +//! - `10 20 00 00` through `1f ff ff ff` for lengths up to 0xfffffff. +//! +//! The "overlong" form is allowed so that the length can be encoded +//! without the prior knowledge of the encoded data. +//! For example, the length 0 can be represented either by `80`, `40 00`, +//! `20 00 00` or `10 00 00 00`. +//! The encoder tries to minimize the length if possible. +//! Also, some predefined tags listed below are so commonly used that +//! their lengths are omitted ("implicit length"). +//! +//! **Data** can be either binary bytes or zero or more nested RBML documents. +//! Nested documents cannot overflow, and should be entirely contained +//! within a parent document. +//! +//! # Predefined Tags +//! +//! Most RBML tags are defined by the application. +//! (For the rust object metadata, see also `rustc::metadata::common`.) +//! RBML itself does define a set of predefined tags however, +//! intended for the auto-serialization implementation. +//! +//! Predefined tags with an implicit length: +//! +//! - `U8` (`00`): 1-byte unsigned integer. +//! - `U16` (`01`): 2-byte big endian unsigned integer. +//! - `U32` (`02`): 4-byte big endian unsigned integer. +//! - `U64` (`03`): 8-byte big endian unsigned integer. +//! Any of `U*` tags can be used to encode primitive unsigned integer types, +//! as long as it is no greater than the actual size. +//! For example, `u8` can only be represented via the `U8` tag. +//! +//! - `I8` (`04`): 1-byte signed integer. +//! - `I16` (`05`): 2-byte big endian signed integer. +//! - `I32` (`06`): 4-byte big endian signed integer. +//! - `I64` (`07`): 8-byte big endian signed integer. +//! Similar to `U*` tags. Always uses two's complement encoding. +//! +//! - `Bool` (`08`): 1-byte boolean value, `00` for false and `01` for true. +//! +//! - `Char` (`09`): 4-byte big endian Unicode scalar value. +//! Surrogate pairs or out-of-bound values are invalid. +//! +//! - `F32` (`0a`): 4-byte big endian unsigned integer representing +//! IEEE 754 binary32 floating-point format. +//! - `F64` (`0b`): 8-byte big endian unsigned integer representing +//! IEEE 754 binary64 floating-point format. +//! +//! - `Sub8` (`0c`): 1-byte unsigned integer for supplementary information. +//! - `Sub32` (`0d`): 4-byte unsigned integer for supplementary information. +//! Those two tags normally occur as the first subdocument of certain tags, +//! namely `Enum`, `Vec` and `Map`, to provide a variant or size information. +//! They can be used interchangeably. +//! +//! Predefined tags with an explicit length: +//! +//! - `Str` (`10`): A UTF-8-encoded string. +//! +//! - `Enum` (`11`): An enum. +//! The first subdocument should be `Sub*` tags with a variant ID. +//! Subsequent subdocuments, if any, encode variant arguments. +//! +//! - `Vec` (`12`): A vector (sequence). +//! - `VecElt` (`13`): A vector element. +//! The first subdocument should be `Sub*` tags with the number of elements. +//! Subsequent subdocuments should be `VecElt` tag per each element. +//! +//! - `Map` (`14`): A map (associated array). +//! - `MapKey` (`15`): A key part of the map entry. +//! - `MapVal` (`16`): A value part of the map entry. +//! The first subdocument should be `Sub*` tags with the number of entries. +//! Subsequent subdocuments should be an alternating sequence of +//! `MapKey` and `MapVal` tags per each entry. +//! +//! - `Opaque` (`17`): An opaque, custom-format tag. +//! Used to wrap ordinary custom tags or data in the auto-serialized context. +//! Rustc typically uses this to encode type informations. +//! +//! First 0x20 tags are reserved by RBML; custom tags start at 0x20. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rbml"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -25,13 +123,12 @@ html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] -#![feature(collections)] #![feature(core)] -#![feature(int_uint)] -#![feature(old_io)] #![feature(rustc_private)] #![feature(staged_api)] +#![cfg_attr(test, feature(test))] + extern crate serialize; #[macro_use] extern crate log; @@ -43,14 +140,12 @@ pub use self::Error::*; use std::str; use std::fmt; -pub mod io; - /// Common data structures #[derive(Clone, Copy)] pub struct Doc<'a> { pub data: &'a [u8], - pub start: uint, - pub end: uint, + pub start: usize, + pub end: usize, } impl<'doc> Doc<'doc> { @@ -58,10 +153,14 @@ impl<'doc> Doc<'doc> { Doc { data: data, start: 0, end: data.len() } } - pub fn get<'a>(&'a self, tag: uint) -> Doc<'a> { + pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> { reader::get_doc(*self, tag) } + pub fn is_empty(&self) -> bool { + self.start == self.end + } + pub fn as_str_slice<'a>(&'a self) -> &'a str { str::from_utf8(&self.data[self.start..self.end]).unwrap() } @@ -72,49 +171,59 @@ impl<'doc> Doc<'doc> { } pub struct TaggedDoc<'a> { - tag: uint, + tag: usize, pub doc: Doc<'a>, } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum EbmlEncoderTag { - EsUint, // 0 - EsU64, // 1 - EsU32, // 2 - EsU16, // 3 - EsU8, // 4 - EsInt, // 5 - EsI64, // 6 - EsI32, // 7 - EsI16, // 8 - EsI8, // 9 - EsBool, // 10 - EsChar, // 11 - EsStr, // 12 - EsF64, // 13 - EsF32, // 14 - EsFloat, // 15 - EsEnum, // 16 - EsEnumVid, // 17 - EsEnumBody, // 18 - EsVec, // 19 - EsVecLen, // 20 - EsVecElt, // 21 - EsMap, // 22 - EsMapLen, // 23 - EsMapKey, // 24 - EsMapVal, // 25 - - EsOpaque, - - EsLabel, // Used only when debugging + // tags 00..1f are reserved for auto-serialization. + // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded. + + EsU8 = 0x00, // + 1 byte + EsU16 = 0x01, // + 2 bytes + EsU32 = 0x02, // + 4 bytes + EsU64 = 0x03, // + 8 bytes + EsI8 = 0x04, // + 1 byte + EsI16 = 0x05, // + 2 bytes + EsI32 = 0x06, // + 4 bytes + EsI64 = 0x07, // + 8 bytes + EsBool = 0x08, // + 1 byte + EsChar = 0x09, // + 4 bytes + EsF32 = 0x0a, // + 4 bytes + EsF64 = 0x0b, // + 8 bytes + EsSub8 = 0x0c, // + 1 byte + EsSub32 = 0x0d, // + 4 bytes + // 0x0e and 0x0f are reserved + + EsStr = 0x10, + EsEnum = 0x11, // encodes the variant id as the first EsSub* + EsVec = 0x12, // encodes the # of elements as the first EsSub* + EsVecElt = 0x13, + EsMap = 0x14, // encodes the # of pairs as the first EsSub* + EsMapKey = 0x15, + EsMapVal = 0x16, + EsOpaque = 0x17, } +const NUM_TAGS: usize = 0x1000; +const NUM_IMPLICIT_TAGS: usize = 0x0e; + +static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [ + 1, 2, 4, 8, // EsU* + 1, 2, 4, 8, // ESI* + 1, // EsBool + 4, // EsChar + 4, 8, // EsF* + 1, 4, // EsSub* +]; + #[derive(Debug)] pub enum Error { - IntTooBig(uint), + IntTooBig(usize), + InvalidTag(usize), Expected(String), - IoError(std::old_io::IoError), + IoError(std::io::Error), ApplicationError(String) } @@ -130,19 +239,16 @@ pub mod reader { use std::char; use std::isize; - use std::old_io::extensions::u64_from_be_bytes; use std::mem::transmute; - use std::num::Int; - use std::option::Option; - use std::option::Option::{None, Some}; + use std::slice::bytes; use serialize; - use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, - EsMapLen, EsMapKey, EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, + use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32, + EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, - EsEnumBody, EsUint, EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc, - Error, IntTooBig, Expected }; + EsOpaque, EbmlEncoderTag, Doc, TaggedDoc, + Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN }; pub type DecodeResult = Result; // rbml reading @@ -159,60 +265,76 @@ pub mod reader { ) } - #[derive(Copy)] + #[derive(Copy, Clone)] pub struct Res { - pub val: uint, - pub next: uint + pub val: usize, + pub next: usize + } + + pub fn tag_at(data: &[u8], start: usize) -> DecodeResult { + let v = data[start] as usize; + if v < 0xf0 { + Ok(Res { val: v, next: start + 1 }) + } else if v > 0xf0 { + Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as usize, next: start + 2 }) + } else { + // every tag starting with byte 0xf0 is an overlong form, which is prohibited. + Err(InvalidTag(v)) + } } #[inline(never)] - fn vuint_at_slow(data: &[u8], start: uint) -> DecodeResult { + fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult { let a = data[start]; - if a & 0x80u8 != 0u8 { - return Ok(Res {val: (a & 0x7fu8) as uint, next: start + 1}); + if a & 0x80 != 0 { + return Ok(Res {val: (a & 0x7f) as usize, next: start + 1}); } - if a & 0x40u8 != 0u8 { - return Ok(Res {val: ((a & 0x3fu8) as uint) << 8 | - (data[start + 1] as uint), + if a & 0x40 != 0 { + return Ok(Res {val: ((a & 0x3f) as usize) << 8 | + (data[start + 1] as usize), next: start + 2}); } - if a & 0x20u8 != 0u8 { - return Ok(Res {val: ((a & 0x1fu8) as uint) << 16 | - (data[start + 1] as uint) << 8 | - (data[start + 2] as uint), + if a & 0x20 != 0 { + return Ok(Res {val: ((a & 0x1f) as usize) << 16 | + (data[start + 1] as usize) << 8 | + (data[start + 2] as usize), next: start + 3}); } - if a & 0x10u8 != 0u8 { - return Ok(Res {val: ((a & 0x0fu8) as uint) << 24 | - (data[start + 1] as uint) << 16 | - (data[start + 2] as uint) << 8 | - (data[start + 3] as uint), + if a & 0x10 != 0 { + return Ok(Res {val: ((a & 0x0f) as usize) << 24 | + (data[start + 1] as usize) << 16 | + (data[start + 2] as usize) << 8 | + (data[start + 3] as usize), next: start + 4}); } - Err(IntTooBig(a as uint)) + Err(IntTooBig(a as usize)) } - pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult { + pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult { if data.len() - start < 4 { return vuint_at_slow(data, start); } - // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/ - // The Element IDs are parsed by reading a big endian u32 positioned at data[start]. - // Using the four most significant bits of the u32 we lookup in the table below how the - // element ID should be derived from it. + // Lookup table for parsing EBML Element IDs as per + // http://ebml.sourceforge.net/specs/ The Element IDs are parsed by + // reading a big endian u32 positioned at data[start]. Using the four + // most significant bits of the u32 we lookup in the table below how + // the element ID should be derived from it. // - // The table stores tuples (shift, mask) where shift is the number the u32 should be right - // shifted with and mask is the value the right shifted value should be masked with. - // If for example the most significant bit is set this means it's a class A ID and the u32 - // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at - // index 0x8 - 0xF (four bit numbers where the most significant bit is set). + // The table stores tuples (shift, mask) where shift is the number the + // u32 should be right shifted with and mask is the value the right + // shifted value should be masked with. If for example the most + // significant bit is set this means it's a class A ID and the u32 + // should be right shifted with 24 and masked with 0x7f. Therefore we + // store (24, 0x7f) at index 0x8 - 0xF (four bit numbers where the most + // significant bit is set). // - // By storing the number of shifts and masks in a table instead of checking in order if - // the most significant bit is set, the second most significant bit is set etc. we can - // replace up to three "and+branch" with a single table lookup which gives us a measured + // By storing the number of shifts and masks in a table instead of + // checking in order if the most significant bit is set, the second + // most significant bit is set etc. we can replace up to three + // "and+branch" with a single table lookup which gives us a measured // speedup of around 2x on x86_64. - static SHIFT_MASK_TABLE: [(uint, u32); 16] = [ + static SHIFT_MASK_TABLE: [(usize, u32); 16] = [ (0, 0x0), (0, 0x0fffffff), (8, 0x1fffff), (8, 0x1fffff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), @@ -221,21 +343,29 @@ pub mod reader { ]; unsafe { - let ptr = data.as_ptr().offset(start as int) as *const u32; - let val = Int::from_be(*ptr); + let ptr = data.as_ptr().offset(start as isize) as *const u32; + let val = u32::from_be(*ptr); - let i = (val >> 28) as uint; + let i = (val >> 28) as usize; let (shift, mask) = SHIFT_MASK_TABLE[i]; Ok(Res { - val: ((val >> shift) & mask) as uint, - next: start + (((32 - shift) >> 3) as uint) + val: ((val >> shift) & mask) as usize, + next: start + ((32 - shift) >> 3), }) } } - pub fn doc_at<'a>(data: &'a [u8], start: uint) -> DecodeResult> { - let elt_tag = try!(vuint_at(data, start)); - let elt_size = try!(vuint_at(data, elt_tag.next)); + pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult { + if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 { + Ok(Res { val: TAG_IMPLICIT_LEN[tag.val] as usize, next: tag.next }) + } else { + vuint_at(data, tag.next) + } + } + + pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult> { + let elt_tag = try!(tag_at(data, start)); + let elt_size = try!(tag_len_at(data, elt_tag)); let end = elt_size.next + elt_size.val; Ok(TaggedDoc { tag: elt_tag.val, @@ -243,11 +373,11 @@ pub mod reader { }) } - pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: uint) -> Option> { + pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { let mut pos = d.start; while pos < d.end { - let elt_tag = try_or!(vuint_at(d.data, pos), None); - let elt_size = try_or!(vuint_at(d.data, elt_tag.next), None); + let elt_tag = try_or!(tag_at(d.data, pos), None); + let elt_size = try_or!(tag_len_at(d.data, elt_tag), None); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { return Some(Doc { data: d.data, start: elt_size.next, @@ -257,7 +387,7 @@ pub mod reader { None } - pub fn get_doc<'a>(d: Doc<'a>, tg: uint) -> Doc<'a> { + pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> { match maybe_get_doc(d, tg) { Some(d) => d, None => { @@ -268,12 +398,12 @@ pub mod reader { } pub fn docs(d: Doc, mut it: F) -> bool where - F: FnMut(uint, Doc) -> bool, + F: FnMut(usize, Doc) -> bool, { let mut pos = d.start; while pos < d.end { - let elt_tag = try_or!(vuint_at(d.data, pos), false); - let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false); + let elt_tag = try_or!(tag_at(d.data, pos), false); + let elt_size = try_or!(tag_len_at(d.data, elt_tag), false); pos = elt_size.next + elt_size.val; let doc = Doc { data: d.data, start: elt_size.next, end: pos }; if !it(elt_tag.val, doc) { @@ -283,13 +413,13 @@ pub mod reader { return true; } - pub fn tagged_docs(d: Doc, tg: uint, mut it: F) -> bool where + pub fn tagged_docs(d: Doc, tg: usize, mut it: F) -> bool where F: FnMut(Doc) -> bool, { let mut pos = d.start; while pos < d.end { - let elt_tag = try_or!(vuint_at(d.data, pos), false); - let elt_size = try_or!(vuint_at(d.data, elt_tag.next), false); + let elt_tag = try_or!(tag_at(d.data, pos), false); + let elt_size = try_or!(tag_len_at(d.data, elt_tag), false); pos = elt_size.next + elt_size.val; if elt_tag.val == tg { let doc = Doc { data: d.data, start: elt_size.next, @@ -316,17 +446,23 @@ pub mod reader { pub fn doc_as_u16(d: Doc) -> u16 { assert_eq!(d.end, d.start + 2); - u64_from_be_bytes(d.data, d.start, 2) as u16 + let mut b = [0; 2]; + bytes::copy_memory(&d.data[d.start..d.end], &mut b); + unsafe { (*(b.as_ptr() as *const u16)).to_be() } } pub fn doc_as_u32(d: Doc) -> u32 { assert_eq!(d.end, d.start + 4); - u64_from_be_bytes(d.data, d.start, 4) as u32 + let mut b = [0; 4]; + bytes::copy_memory(&d.data[d.start..d.end], &mut b); + unsafe { (*(b.as_ptr() as *const u32)).to_be() } } pub fn doc_as_u64(d: Doc) -> u64 { assert_eq!(d.end, d.start + 8); - u64_from_be_bytes(d.data, d.start, 8) + let mut b = [0; 8]; + bytes::copy_memory(&d.data[d.start..d.end], &mut b); + unsafe { (*(b.as_ptr() as *const u64)).to_be() } } pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } @@ -336,7 +472,7 @@ pub mod reader { pub struct Decoder<'a> { parent: Doc<'a>, - pos: uint, + pos: usize, } impl<'doc> Decoder<'doc> { @@ -347,23 +483,6 @@ pub mod reader { } } - fn _check_label(&mut self, lbl: &str) -> DecodeResult<()> { - if self.pos < self.parent.end { - let TaggedDoc { tag: r_tag, doc: r_doc } = - try!(doc_at(self.parent.data, self.pos)); - - if r_tag == (EsLabel as uint) { - self.pos = r_doc.end; - let str = r_doc.as_str_slice(); - if lbl != str { - return Err(Expected(format!("Expected label {:?} but \ - found {:?}", lbl, str))); - } - } - } - Ok(()) - } - fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult> { debug!(". next_doc(exp_tag={:?})", exp_tag); if self.pos >= self.parent.end { @@ -379,7 +498,7 @@ pub mod reader { r_tag, r_doc.start, r_doc.end); - if r_tag != (exp_tag as uint) { + if r_tag != (exp_tag as usize) { return Err(Expected(format!("expected EBML doc with tag {:?} but \ found tag {:?}", exp_tag, r_tag))); } @@ -406,10 +525,66 @@ pub mod reader { Ok(r) } - fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult { - let r = doc_as_u32(try!(self.next_doc(exp_tag))); - debug!("_next_uint exp_tag={:?} result={:?}", exp_tag, r); - Ok(r as uint) + fn _next_sub(&mut self) -> DecodeResult { + // empty vector/map optimization + if self.parent.is_empty() { + return Ok(0); + } + + let TaggedDoc { tag: r_tag, doc: r_doc } = + try!(doc_at(self.parent.data, self.pos)); + let r = if r_tag == (EsSub8 as usize) { + doc_as_u8(r_doc) as usize + } else if r_tag == (EsSub32 as usize) { + doc_as_u32(r_doc) as usize + } else { + return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \ + found tag {:?}", EsSub8, EsSub32, r_tag))); + }; + if r_doc.end > self.parent.end { + return Err(Expected(format!("invalid EBML, child extends to \ + {:#x}, parent to {:#x}", + r_doc.end, self.parent.end))); + } + self.pos = r_doc.end; + debug!("_next_sub result={:?}", r); + Ok(r) + } + + // variable-length unsigned integer with different tags. + // `first_tag` should be a tag for u8 or i8. + // `last_tag` should be the largest allowed integer tag with the matching signedness. + // all tags between them should be valid, in the order of u8, u16, u32 and u64. + fn _next_int(&mut self, + first_tag: EbmlEncoderTag, + last_tag: EbmlEncoderTag) -> DecodeResult { + if self.pos >= self.parent.end { + return Err(Expected(format!("no more documents in \ + current node!"))); + } + + let TaggedDoc { tag: r_tag, doc: r_doc } = + try!(doc_at(self.parent.data, self.pos)); + let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize { + match r_tag - first_tag as usize { + 0 => doc_as_u8(r_doc) as u64, + 1 => doc_as_u16(r_doc) as u64, + 2 => doc_as_u32(r_doc) as u64, + 3 => doc_as_u64(r_doc), + _ => unreachable!(), + } + } else { + return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \ + found tag {:?}", first_tag, last_tag, r_tag))); + }; + if r_doc.end > self.parent.end { + return Err(Expected(format!("invalid EBML, child extends to \ + {:#x}, parent to {:#x}", + r_doc.end, self.parent.end))); + } + self.pos = r_doc.end; + debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r); + Ok(r) } pub fn read_opaque(&mut self, op: F) -> DecodeResult where @@ -433,38 +608,30 @@ pub mod reader { type Error = Error; fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) } - fn read_u64(&mut self) -> DecodeResult { Ok(doc_as_u64(try!(self.next_doc(EsU64)))) } - fn read_u32(&mut self) -> DecodeResult { Ok(doc_as_u32(try!(self.next_doc(EsU32)))) } - fn read_u16(&mut self) -> DecodeResult { Ok(doc_as_u16(try!(self.next_doc(EsU16)))) } - fn read_u8 (&mut self) -> DecodeResult { Ok(doc_as_u8 (try!(self.next_doc(EsU8 )))) } - fn read_uint(&mut self) -> DecodeResult { - let v = doc_as_u64(try!(self.next_doc(EsUint))); + fn read_u64(&mut self) -> DecodeResult { self._next_int(EsU8, EsU64) } + fn read_u32(&mut self) -> DecodeResult { Ok(try!(self._next_int(EsU8, EsU32)) as u32) } + fn read_u16(&mut self) -> DecodeResult { Ok(try!(self._next_int(EsU8, EsU16)) as u16) } + fn read_u8(&mut self) -> DecodeResult { Ok(doc_as_u8(try!(self.next_doc(EsU8)))) } + fn read_uint(&mut self) -> DecodeResult { + let v = try!(self._next_int(EsU8, EsU64)); if v > (::std::usize::MAX as u64) { - Err(IntTooBig(v as uint)) + Err(IntTooBig(v as usize)) } else { - Ok(v as uint) + Ok(v as usize) } } - fn read_i64(&mut self) -> DecodeResult { - Ok(doc_as_u64(try!(self.next_doc(EsI64))) as i64) - } - fn read_i32(&mut self) -> DecodeResult { - Ok(doc_as_u32(try!(self.next_doc(EsI32))) as i32) - } - fn read_i16(&mut self) -> DecodeResult { - Ok(doc_as_u16(try!(self.next_doc(EsI16))) as i16) - } - fn read_i8 (&mut self) -> DecodeResult { - Ok(doc_as_u8(try!(self.next_doc(EsI8 ))) as i8) - } - fn read_int(&mut self) -> DecodeResult { - let v = doc_as_u64(try!(self.next_doc(EsInt))) as i64; + fn read_i64(&mut self) -> DecodeResult { Ok(try!(self._next_int(EsI8, EsI64)) as i64) } + fn read_i32(&mut self) -> DecodeResult { Ok(try!(self._next_int(EsI8, EsI32)) as i32) } + fn read_i16(&mut self) -> DecodeResult { Ok(try!(self._next_int(EsI8, EsI16)) as i16) } + fn read_i8(&mut self) -> DecodeResult { Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8) } + fn read_int(&mut self) -> DecodeResult { + let v = try!(self._next_int(EsI8, EsI64)) as i64; if v > (isize::MAX as i64) || v < (isize::MIN as i64) { debug!("FIXME \\#6122: Removing this makes this function miscompile"); - Err(IntTooBig(v as uint)) + Err(IntTooBig(v as usize)) } else { - Ok(v as int) + Ok(v as isize) } } @@ -492,7 +659,6 @@ pub mod reader { F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_enum({})", name); - try!(self._check_label(name)); let doc = try!(self.next_doc(EsEnum)); @@ -509,26 +675,16 @@ pub mod reader { fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult, + where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult, { debug!("read_enum_variant()"); - let idx = try!(self._next_uint(EsEnumVid)); + let idx = try!(self._next_sub()); 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) + f(self, idx) } - fn read_enum_variant_arg(&mut self, idx: uint, f: F) -> DecodeResult where + fn read_enum_variant_arg(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_enum_variant_arg(idx={})", idx); @@ -537,28 +693,18 @@ pub mod reader { fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult, + where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult, { debug!("read_enum_struct_variant()"); - let idx = try!(self._next_uint(EsEnumVid)); + let idx = try!(self._next_sub()); 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) + f(self, idx) } fn read_enum_struct_variant_field(&mut self, name: &str, - idx: uint, + idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, @@ -567,22 +713,21 @@ pub mod reader { f(self) } - fn read_struct(&mut self, name: &str, _: uint, f: F) -> DecodeResult where + fn read_struct(&mut self, name: &str, _: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_struct(name={})", name); f(self) } - fn read_struct_field(&mut self, name: &str, idx: uint, f: F) -> DecodeResult where + fn read_struct_field(&mut self, name: &str, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_struct_field(name={}, idx={})", name, idx); - try!(self._check_label(name)); f(self) } - fn read_tuple(&mut self, tuple_len: uint, f: F) -> DecodeResult where + fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_tuple()"); @@ -596,14 +741,14 @@ pub mod reader { }) } - fn read_tuple_arg(&mut self, idx: uint, f: F) -> DecodeResult where + fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_tuple_arg(idx={})", idx); self.read_seq_elt(idx, f) } - fn read_tuple_struct(&mut self, name: &str, len: uint, f: F) -> DecodeResult where + fn read_tuple_struct(&mut self, name: &str, len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_tuple_struct(name={})", name); @@ -611,7 +756,7 @@ pub mod reader { } fn read_tuple_struct_arg(&mut self, - idx: uint, + idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, @@ -638,17 +783,17 @@ pub mod reader { } fn read_seq(&mut self, f: F) -> DecodeResult where - F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult, + F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult, { debug!("read_seq()"); self.push_doc(EsVec, move |d| { - let len = try!(d._next_uint(EsVecLen)); + let len = try!(d._next_sub()); debug!(" len={}", len); f(d, len) }) } - fn read_seq_elt(&mut self, idx: uint, f: F) -> DecodeResult where + fn read_seq_elt(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_seq_elt(idx={})", idx); @@ -656,24 +801,24 @@ pub mod reader { } fn read_map(&mut self, f: F) -> DecodeResult where - F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult, + F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult, { debug!("read_map()"); self.push_doc(EsMap, move |d| { - let len = try!(d._next_uint(EsMapLen)); + let len = try!(d._next_sub()); debug!(" len={}", len); f(d, len) }) } - fn read_map_elt_key(&mut self, idx: uint, f: F) -> DecodeResult where + fn read_map_elt_key(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_map_elt_key(idx={})", idx); self.push_doc(EsMapKey, f) } - fn read_map_elt_val(&mut self, idx: uint, f: F) -> DecodeResult where + fn read_map_elt_val(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult, { debug!("read_map_elt_val(idx={})", idx); @@ -687,97 +832,126 @@ pub mod reader { } pub mod writer { - use std::clone::Clone; - use std::old_io::extensions::u64_to_be_bytes; - use std::old_io::{Writer, Seek}; - use std::old_io; use std::mem; + use std::io::prelude::*; + use std::io::{self, SeekFrom, Cursor}; + use std::slice::bytes; + use std::num::ToPrimitive; - use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, - EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8, - EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint, - EsOpaque, EsLabel, EbmlEncoderTag }; + use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, + EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, + EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, + EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS }; use serialize; - pub type EncodeResult = old_io::IoResult<()>; + pub type EncodeResult = io::Result<()>; // rbml writing - pub struct Encoder<'a, W:'a> { - pub writer: &'a mut W, - size_positions: Vec, + pub struct Encoder<'a> { + pub writer: &'a mut Cursor>, + size_positions: Vec, + relax_limit: u64, // do not move encoded bytes before this position } - fn write_sized_vuint(w: &mut W, n: uint, size: uint) -> EncodeResult { + fn write_tag(w: &mut W, n: usize) -> EncodeResult { + if n < 0xf0 { + w.write_all(&[n as u8]) + } else if 0x100 <= n && n < NUM_TAGS { + w.write_all(&[0xf0 | (n >> 8) as u8, n as u8]) + } else { + Err(io::Error::new(io::ErrorKind::Other, + &format!("invalid tag: {}", n)[..])) + } + } + + fn write_sized_vuint(w: &mut W, n: usize, size: usize) -> EncodeResult { match size { - 1 => w.write_all(&[0x80u8 | (n as u8)]), - 2 => w.write_all(&[0x40u8 | ((n >> 8) as u8), n as u8]), - 3 => w.write_all(&[0x20u8 | ((n >> 16) as u8), (n >> 8) as u8, + 1 => w.write_all(&[0x80 | (n as u8)]), + 2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]), + 3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8, n as u8]), - 4 => w.write_all(&[0x10u8 | ((n >> 24) as u8), (n >> 16) as u8, + 4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]), - _ => Err(old_io::IoError { - kind: old_io::OtherIoError, - desc: "int too big", - detail: Some(format!("{}", n)) - }) + _ => Err(io::Error::new(io::ErrorKind::Other, + &format!("isize too big: {}", n)[..])) } } - fn write_vuint(w: &mut W, n: uint) -> EncodeResult { + fn write_vuint(w: &mut W, n: usize) -> EncodeResult { if n < 0x7f { return write_sized_vuint(w, n, 1); } if n < 0x4000 { return write_sized_vuint(w, n, 2); } if n < 0x200000 { return write_sized_vuint(w, n, 3); } if n < 0x10000000 { return write_sized_vuint(w, n, 4); } - Err(old_io::IoError { - kind: old_io::OtherIoError, - desc: "int too big", - detail: Some(format!("{}", n)) - }) + Err(io::Error::new(io::ErrorKind::Other, + &format!("isize too big: {}", n)[..])) } - impl<'a, W: Writer + Seek> Encoder<'a, W> { - pub fn new(w: &'a mut W) -> Encoder<'a, W> { + impl<'a> Encoder<'a> { + pub fn new(w: &'a mut Cursor>) -> Encoder<'a> { Encoder { writer: w, size_positions: vec!(), + relax_limit: 0, } } /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME. - pub unsafe fn unsafe_clone(&self) -> Encoder<'a, W> { + pub unsafe fn unsafe_clone(&self) -> Encoder<'a> { Encoder { writer: mem::transmute_copy(&self.writer), size_positions: self.size_positions.clone(), + relax_limit: self.relax_limit, } } - pub fn start_tag(&mut self, tag_id: uint) -> EncodeResult { + pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult { debug!("Start tag {:?}", tag_id); + assert!(tag_id >= NUM_IMPLICIT_TAGS); // Write the enum ID: - try!(write_vuint(self.writer, tag_id)); + try!(write_tag(self.writer, tag_id)); // Write a placeholder four-byte size. - self.size_positions.push(try!(self.writer.tell()) as uint); - let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8]; + let cur_pos = try!(self.writer.seek(SeekFrom::Current(0))); + self.size_positions.push(cur_pos); + let zeroes: &[u8] = &[0, 0, 0, 0]; self.writer.write_all(zeroes) } pub fn end_tag(&mut self) -> EncodeResult { let last_size_pos = self.size_positions.pop().unwrap(); - let cur_pos = try!(self.writer.tell()); - try!(self.writer.seek(last_size_pos as i64, old_io::SeekSet)); - let size = cur_pos as uint - last_size_pos - 4; - try!(write_sized_vuint(self.writer, size, 4)); - let r = try!(self.writer.seek(cur_pos as i64, old_io::SeekSet)); + let cur_pos = try!(self.writer.seek(SeekFrom::Current(0))); + try!(self.writer.seek(SeekFrom::Start(last_size_pos))); + let size = (cur_pos - last_size_pos - 4) as usize; + + // relax the size encoding for small tags (bigger tags are costly to move). + // we should never try to move the stable positions, however. + const RELAX_MAX_SIZE: usize = 0x100; + if size <= RELAX_MAX_SIZE && last_size_pos >= self.relax_limit { + // we can't alter the buffer in place, so have a temporary buffer + let mut buf = [0u8; RELAX_MAX_SIZE]; + { + let last_size_pos = last_size_pos as usize; + let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as usize]; + bytes::copy_memory(data, &mut buf); + } + + // overwrite the size and data and continue + try!(write_vuint(self.writer, size)); + try!(self.writer.write_all(&buf[..size])); + } else { + // overwrite the size with an overlong encoding and skip past the data + try!(write_sized_vuint(self.writer, size, 4)); + try!(self.writer.seek(SeekFrom::Start(cur_pos))); + } debug!("End tag (size = {:?})", size); - Ok(r) + Ok(()) } - pub fn wr_tag(&mut self, tag_id: uint, blk: F) -> EncodeResult where + pub fn wr_tag(&mut self, tag_id: usize, blk: F) -> EncodeResult where F: FnOnce() -> EncodeResult, { try!(self.start_tag(tag_id)); @@ -785,60 +959,93 @@ pub mod writer { self.end_tag() } - pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) -> EncodeResult { - try!(write_vuint(self.writer, tag_id)); + pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { + assert!(tag_id >= NUM_IMPLICIT_TAGS); + try!(write_tag(self.writer, tag_id)); try!(write_vuint(self.writer, b.len())); self.writer.write_all(b) } - pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) -> EncodeResult { - u64_to_be_bytes(v, 8, |v| { - self.wr_tagged_bytes(tag_id, v) - }) + pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { + let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_bytes(tag_id, &bytes) } - pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) -> EncodeResult{ - u64_to_be_bytes(v as u64, 4, |v| { - self.wr_tagged_bytes(tag_id, v) - }) + pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult{ + let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_bytes(tag_id, &bytes) } - pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) -> EncodeResult { - u64_to_be_bytes(v as u64, 2, |v| { - self.wr_tagged_bytes(tag_id, v) - }) + pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { + let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_bytes(tag_id, &bytes) } - pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) -> EncodeResult { + pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { self.wr_tagged_bytes(tag_id, &[v]) } - pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) -> EncodeResult { - u64_to_be_bytes(v as u64, 8, |v| { - self.wr_tagged_bytes(tag_id, v) - }) + pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { + self.wr_tagged_u64(tag_id, v as u64) } - pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) -> EncodeResult { - u64_to_be_bytes(v as u64, 4, |v| { - self.wr_tagged_bytes(tag_id, v) - }) + pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { + self.wr_tagged_u32(tag_id, v as u32) } - pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) -> EncodeResult { - u64_to_be_bytes(v as u64, 2, |v| { - self.wr_tagged_bytes(tag_id, v) - }) + pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { + self.wr_tagged_u16(tag_id, v as u16) } - pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) -> EncodeResult { + pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { self.wr_tagged_bytes(tag_id, &[v as u8]) } - pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) -> EncodeResult { + pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult { self.wr_tagged_bytes(tag_id, v.as_bytes()) } + // for auto-serialization + fn wr_tagged_raw_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult { + try!(write_tag(self.writer, tag_id)); + self.writer.write_all(b) + } + + fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult { + let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_raw_bytes(tag_id, &bytes) + } + + fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult{ + let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_raw_bytes(tag_id, &bytes) + } + + fn wr_tagged_raw_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult { + let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) }; + self.wr_tagged_raw_bytes(tag_id, &bytes) + } + + fn wr_tagged_raw_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult { + self.wr_tagged_raw_bytes(tag_id, &[v]) + } + + fn wr_tagged_raw_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult { + self.wr_tagged_raw_u64(tag_id, v as u64) + } + + fn wr_tagged_raw_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult { + self.wr_tagged_raw_u32(tag_id, v as u32) + } + + fn wr_tagged_raw_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult { + self.wr_tagged_raw_u16(tag_id, v as u16) + } + + fn wr_tagged_raw_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult { + self.wr_tagged_raw_bytes(tag_id, &[v as u8]) + } + pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult { debug!("Write {:?} bytes", b.len()); self.writer.write_all(b) @@ -848,188 +1055,198 @@ pub mod writer { debug!("Write str: {:?}", s); self.writer.write_all(s.as_bytes()) } - } - - // FIXME (#2743): optionally perform "relaxations" on end_tag to more - // efficiently encode sizes; this is a fixed point iteration - // Set to true to generate more debugging in EBML code. - // Totally lame approach. - #[cfg(not(ndebug))] - static DEBUG: bool = true; - #[cfg(ndebug)] - static DEBUG: bool = false; - - impl<'a, W: Writer + Seek> Encoder<'a, W> { - // used internally to emit things like the vector length and so on - fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) -> EncodeResult { - assert!(v <= 0xFFFF_FFFF); - self.wr_tagged_u32(t as uint, v as u32) + /// Returns the current position while marking it stable, i.e. + /// generated bytes so far wouldn't be affected by relaxation. + pub fn mark_stable_position(&mut self) -> u64 { + let pos = self.writer.seek(SeekFrom::Current(0)).unwrap(); + if self.relax_limit < pos { + self.relax_limit = pos; + } + pos } + } - fn _emit_label(&mut self, label: &str) -> EncodeResult { - // There are various strings that we have access to, such as - // the name of a record field, which do not actually appear in - // the encoded EBML (normally). This is just for - // efficiency. When debugging, though, we can emit such - // labels and then they will be checked by decoder to - // try and check panics more quickly. - if DEBUG { self.wr_tagged_str(EsLabel as uint, label) } - else { Ok(()) } + impl<'a> Encoder<'a> { + // used internally to emit things like the vector length and so on + fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult { + if let Some(v) = v.to_u8() { + self.wr_tagged_raw_u8(EsSub8 as usize, v) + } else if let Some(v) = v.to_u32() { + self.wr_tagged_raw_u32(EsSub32 as usize, v) + } else { + Err(io::Error::new(io::ErrorKind::Other, + &format!("length or variant id too big: {}", + v)[..])) + } } pub fn emit_opaque(&mut self, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder) -> EncodeResult, + F: FnOnce(&mut Encoder) -> EncodeResult, { - try!(self.start_tag(EsOpaque as uint)); + try!(self.start_tag(EsOpaque as usize)); try!(f(self)); self.end_tag() } } - impl<'a, W: Writer + Seek> serialize::Encoder for Encoder<'a, W> { - type Error = old_io::IoError; + impl<'a> serialize::Encoder for Encoder<'a> { + type Error = io::Error; 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_uint(&mut self, v: usize) -> EncodeResult { + self.emit_u64(v as u64) } fn emit_u64(&mut self, v: u64) -> EncodeResult { - self.wr_tagged_u64(EsU64 as uint, v) + match v.to_u32() { + Some(v) => self.emit_u32(v), + None => self.wr_tagged_raw_u64(EsU64 as usize, v) + } } fn emit_u32(&mut self, v: u32) -> EncodeResult { - self.wr_tagged_u32(EsU32 as uint, v) + match v.to_u16() { + Some(v) => self.emit_u16(v), + None => self.wr_tagged_raw_u32(EsU32 as usize, v) + } } fn emit_u16(&mut self, v: u16) -> EncodeResult { - self.wr_tagged_u16(EsU16 as uint, v) + match v.to_u8() { + Some(v) => self.emit_u8(v), + None => self.wr_tagged_raw_u16(EsU16 as usize, v) + } } fn emit_u8(&mut self, v: u8) -> EncodeResult { - self.wr_tagged_u8(EsU8 as uint, v) + self.wr_tagged_raw_u8(EsU8 as usize, v) } - fn emit_int(&mut self, v: int) -> EncodeResult { - self.wr_tagged_i64(EsInt as uint, v as i64) + fn emit_int(&mut self, v: isize) -> EncodeResult { + self.emit_i64(v as i64) } fn emit_i64(&mut self, v: i64) -> EncodeResult { - self.wr_tagged_i64(EsI64 as uint, v) + match v.to_i32() { + Some(v) => self.emit_i32(v), + None => self.wr_tagged_raw_i64(EsI64 as usize, v) + } } fn emit_i32(&mut self, v: i32) -> EncodeResult { - self.wr_tagged_i32(EsI32 as uint, v) + match v.to_i16() { + Some(v) => self.emit_i16(v), + None => self.wr_tagged_raw_i32(EsI32 as usize, v) + } } fn emit_i16(&mut self, v: i16) -> EncodeResult { - self.wr_tagged_i16(EsI16 as uint, v) + match v.to_i8() { + Some(v) => self.emit_i8(v), + None => self.wr_tagged_raw_i16(EsI16 as usize, v) + } } fn emit_i8(&mut self, v: i8) -> EncodeResult { - self.wr_tagged_i8(EsI8 as uint, v) + self.wr_tagged_raw_i8(EsI8 as usize, v) } fn emit_bool(&mut self, v: bool) -> EncodeResult { - self.wr_tagged_u8(EsBool as uint, v as u8) + self.wr_tagged_raw_u8(EsBool as usize, 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) + self.wr_tagged_raw_u64(EsF64 as usize, bits) } fn emit_f32(&mut self, v: f32) -> EncodeResult { let bits = unsafe { mem::transmute(v) }; - self.wr_tagged_u32(EsF32 as uint, bits) + self.wr_tagged_raw_u32(EsF32 as usize, bits) } fn emit_char(&mut self, v: char) -> EncodeResult { - self.wr_tagged_u32(EsChar as uint, v as u32) + self.wr_tagged_raw_u32(EsChar as usize, v as u32) } fn emit_str(&mut self, v: &str) -> EncodeResult { - self.wr_tagged_str(EsStr as uint, v) + self.wr_tagged_str(EsStr as usize, v) } - fn emit_enum(&mut self, name: &str, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { - try!(self._emit_label(name)); - try!(self.start_tag(EsEnum as uint)); + try!(self.start_tag(EsEnum as usize)); try!(f(self)); self.end_tag() } fn emit_enum_variant(&mut self, _: &str, - v_id: uint, - _: uint, + v_id: usize, + _: usize, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { - try!(self._emit_tagged_uint(EsEnumVid, v_id)); - try!(self.start_tag(EsEnumBody as uint)); - try!(f(self)); - self.end_tag() + try!(self._emit_tagged_sub(v_id)); + f(self) } - fn emit_enum_variant_arg(&mut self, _: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { f(self) } fn emit_enum_struct_variant(&mut self, v_name: &str, - v_id: uint, - cnt: uint, + v_id: usize, + cnt: usize, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_enum_variant(v_name, v_id, cnt, f) } fn emit_enum_struct_variant_field(&mut self, _: &str, - idx: uint, + idx: usize, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_enum_variant_arg(idx, f) } - fn emit_struct(&mut self, _: &str, _len: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { f(self) } - fn emit_struct_field(&mut self, name: &str, _: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { - try!(self._emit_label(name)); f(self) } - fn emit_tuple(&mut self, len: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_seq(len, f) } - fn emit_tuple_arg(&mut self, idx: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_seq_elt(idx, f) } - fn emit_tuple_struct(&mut self, _: &str, len: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_seq(len, f) } - fn emit_tuple_struct_arg(&mut self, idx: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_seq_elt(idx, f) } fn emit_option(&mut self, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_enum("Option", f) } @@ -1037,54 +1254,62 @@ pub mod writer { self.emit_enum_variant("None", 0, 0, |_| Ok(())) } fn emit_option_some(&mut self, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { self.emit_enum_variant("Some", 1, 1, f) } - fn emit_seq(&mut self, len: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { + if len == 0 { + // empty vector optimization + return self.wr_tagged_bytes(EsVec as usize, &[]); + } - try!(self.start_tag(EsVec as uint)); - try!(self._emit_tagged_uint(EsVecLen, len)); + try!(self.start_tag(EsVec as usize)); + try!(self._emit_tagged_sub(len)); try!(f(self)); self.end_tag() } - fn emit_seq_elt(&mut self, _idx: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { - try!(self.start_tag(EsVecElt as uint)); + try!(self.start_tag(EsVecElt as usize)); try!(f(self)); self.end_tag() } - fn emit_map(&mut self, len: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_map(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { + if len == 0 { + // empty map optimization + return self.wr_tagged_bytes(EsMap as usize, &[]); + } - try!(self.start_tag(EsMap as uint)); - try!(self._emit_tagged_uint(EsMapLen, len)); + try!(self.start_tag(EsMap as usize)); + try!(self._emit_tagged_sub(len)); try!(f(self)); self.end_tag() } - fn emit_map_elt_key(&mut self, _idx: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { - try!(self.start_tag(EsMapKey as uint)); + try!(self.start_tag(EsMapKey as usize)); try!(f(self)); self.end_tag() } - fn emit_map_elt_val(&mut self, _idx: uint, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder<'a, W>) -> EncodeResult, + fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { - try!(self.start_tag(EsMapVal as uint)); + try!(self.start_tag(EsMapVal as usize)); try!(f(self)); self.end_tag() } @@ -1097,12 +1322,10 @@ pub mod writer { #[cfg(test)] mod tests { use super::{Doc, reader, writer}; - use super::io::SeekableMemWriter; use serialize::{Encodable, Decodable}; - use std::option::Option; - use std::option::Option::{None, Some}; + use std::io::Cursor; #[test] fn test_vuint_at() { @@ -1154,9 +1377,9 @@ mod tests { #[test] fn test_option_int() { - fn test_v(v: Option) { + fn test_v(v: Option) { debug!("v == {:?}", v); - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); { let mut rbml_w = writer::Encoder::new(&mut wr); let _ = v.encode(&mut rbml_w); @@ -1182,9 +1405,9 @@ mod bench { #[bench] pub fn vuint_at_A_aligned(b: &mut Bencher) { - let data = (0i32..4*100).map(|i| { + let data = (0..4*100).map(|i| { match i % 2 { - 0 => 0x80u8, + 0 => 0x80, _ => i as u8, } }).collect::>(); @@ -1200,9 +1423,9 @@ mod bench { #[bench] pub fn vuint_at_A_unaligned(b: &mut Bencher) { - let data = (0i32..4*100+1).map(|i| { + let data = (0..4*100+1).map(|i| { match i % 2 { - 1 => 0x80u8, + 1 => 0x80, _ => i as u8 } }).collect::>(); @@ -1218,11 +1441,11 @@ mod bench { #[bench] pub fn vuint_at_D_aligned(b: &mut Bencher) { - let data = (0i32..4*100).map(|i| { + let data = (0..4*100).map(|i| { match i % 4 { - 0 => 0x10u8, + 0 => 0x10, 3 => i as u8, - _ => 0u8 + _ => 0 } }).collect::>(); let mut sum = 0; @@ -1237,11 +1460,11 @@ mod bench { #[bench] pub fn vuint_at_D_unaligned(b: &mut Bencher) { - let data = (0i32..4*100+1).map(|i| { + let data = (0..4*100+1).map(|i| { match i % 4 { - 1 => 0x10u8, + 1 => 0x10, 0 => i as u8, - _ => 0u8 + _ => 0 } }).collect::>(); let mut sum = 0; diff --git a/src/librustc/README.md b/src/librustc/README.md new file mode 100644 index 0000000000..31812e19ae --- /dev/null +++ b/src/librustc/README.md @@ -0,0 +1,128 @@ +An informal guide to reading and working on the rustc compiler. +================================================================== + +If you wish to expand on this document, or have a more experienced +Rust contributor add anything else to it, please get in touch: + +* http://internals.rust-lang.org/ +* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust + +or file a bug: + +https://github.com/rust-lang/rust/issues + +Your concerns are probably the same as someone else's. + +The crates of rustc +=================== + +Rustc consists of a number of crates, including `libsyntax`, +`librustc`, `librustc_back`, `librustc_trans`, and `librustc_driver` +(the names and divisions are not set in stone and may change; +in general, a finer-grained division of crates is preferable): + +- `libsyntax` contains those things concerned purely with syntax – + that is, the AST, parser, pretty-printer, lexer, macro expander, and + utilities for traversing ASTs – are in a separate crate called + "syntax", whose files are in `./../libsyntax`, where `.` is the + current directory (that is, the parent directory of front/, middle/, + back/, and so on). + +- `librustc` (the current directory) contains the high-level analysis + passes, such as the type checker, borrow checker, and so forth. + It is the heart of the compiler. + +- `librustc_back` contains some very low-level details that are + specific to different LLVM targets and so forth. + +- `librustc_trans` contains the code to convert from Rust IR into LLVM + IR, and then from LLVM IR into machine code, as well as the main + driver that orchestrates all the other passes and various other bits + of miscellany. In general it contains code that runs towards the + end of the compilation process. + +- `librustc_driver` invokes the compiler from `libsyntax`, then the + analysis phases from `librustc`, and finally the lowering and + codegen passes from `librustc_trans`. + +Roughly speaking the "order" of the three crates is as follows: + + libsyntax -> librustc -> librustc_trans + | | + +-----------------+-------------------+ + | + librustc_driver + + +Modules in the rustc crate +========================== + +The rustc crate itself consists of the following submodules +(mostly, but not entirely, in their own directories): + +- session: options and data that pertain to the compilation session as + a whole +- middle: middle-end: name resolution, typechecking, LLVM code + generation +- metadata: encoder and decoder for data required by separate + compilation +- plugin: infrastructure for compiler plugins +- lint: infrastructure for compiler warnings +- util: ubiquitous types and helper functions +- lib: bindings to LLVM + +The entry-point for the compiler is main() in the librustc_trans +crate. + +The 3 central data structures: +------------------------------ + +1. `./../libsyntax/ast.rs` defines the AST. The AST is treated as + immutable after parsing, but it depends on mutable context data + structures (mainly hash maps) to give it meaning. + + - Many – though not all – nodes within this data structure are + wrapped in the type `spanned`, meaning that the front-end has + marked the input coordinates of that node. The member `node` is + the data itself, the member `span` is the input location (file, + line, column; both low and high). + + - Many other nodes within this data structure carry a + `def_id`. These nodes represent the 'target' of some name + reference elsewhere in the tree. When the AST is resolved, by + `middle/resolve.rs`, all names wind up acquiring a def that they + point to. So anything that can be pointed-to by a name winds + up with a `def_id`. + +2. `middle/ty.rs` defines the datatype `sty`. This is the type that + represents types after they have been resolved and normalized by + the middle-end. The typeck phase converts every ast type to a + `ty::sty`, and the latter is used to drive later phases of + compilation. Most variants in the `ast::ty` tag have a + corresponding variant in the `ty::sty` tag. + +3. `./../librustc_llvm/lib.rs` defines the exported types + `ValueRef`, `TypeRef`, `BasicBlockRef`, and several others. + Each of these is an opaque pointer to an LLVM type, + manipulated through the `lib::llvm` interface. + + +Control and information flow within the compiler: +------------------------------------------------- + +- main() in lib.rs assumes control on startup. Options are + parsed, platform is detected, etc. + +- `./../libsyntax/parse/parser.rs` parses the input files and produces + an AST that represents the input crate. + +- Multiple middle-end passes (`middle/resolve.rs`, `middle/typeck.rs`) + analyze the semantics of the resulting AST. Each pass generates new + information about the AST and stores it in various environment data + structures. The driver passes environments to each compiler pass + that needs to refer to them. + +- Finally, the `trans` module in `librustc_trans` translates the Rust + AST to LLVM bitcode in a type-directed way. When it's finished + synthesizing LLVM values, rustc asks LLVM to write them out in some + form (`.bc`, `.o`) and possibly run the system linker. diff --git a/src/librustc/README.txt b/src/librustc/README.txt deleted file mode 100644 index 37097764f7..0000000000 --- a/src/librustc/README.txt +++ /dev/null @@ -1,124 +0,0 @@ -An informal guide to reading and working on the rustc compiler. -================================================================== - -If you wish to expand on this document, or have a more experienced -Rust contributor add anything else to it, please get in touch: - -* http://internals.rust-lang.org/ -* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust - -or file a bug: - -https://github.com/rust-lang/rust/issues - -Your concerns are probably the same as someone else's. - -The crates of rustc -=================== - -Rustc consists of four crates altogether: `libsyntax`, `librustc`, -`librustc_back`, and `librustc_trans` (the names and divisions are not -set in stone and may change; in general, a finer-grained division of -crates is preferable): - -- `libsyntax` contains those things concerned purely with syntax -- - that is, the AST, parser, pretty-printer, lexer, macro expander, and - utilities for traversing ASTs -- are in a separate crate called - "syntax", whose files are in ./../libsyntax, where . is the current - directory (that is, the parent directory of front/, middle/, back/, - and so on). - -- `librustc` (the current directory) contains the high-level analysis - passes, such as the type checker, borrow checker, and so forth. - It is the heart of the compiler. - -- `librustc_back` contains some very low-level details that are - specific to different LLVM targets and so forth. - -- `librustc_trans` contains the code to convert from Rust IR into LLVM - IR, and then from LLVM IR into machine code, as well as the main - driver that orchestrates all the other passes and various other bits - of miscellany. In general it contains code that runs towards the - end of the compilation process. - -Roughly speaking the "order" of the three crates is as follows: - - libsyntax -> librustc -> librustc_trans - | | - +-----------------+-------------------+ - | - librustc_trans/driver - -Here the role of `librustc_trans/driver` is to invoke the compiler -from libsyntax, then the analysis phases from librustc, and finally -the lowering and codegen passes from librustc_trans. - -Modules in the rustc crate -========================== - -The rustc crate itself consists of the following subdirectories -(mostly, but not entirely, in their own directories): - -session - options and data that pertain to the compilation session as a whole -middle - middle-end: name resolution, typechecking, LLVM code - generation -metadata - encoder and decoder for data required by - separate compilation -util - ubiquitous types and helper functions -lib - bindings to LLVM - -The entry-point for the compiler is main() in the librustc_trans -crate. - -The 3 central data structures: ------------------------------- - -#1: ./../libsyntax/ast.rs defines the AST. The AST is treated as immutable - after parsing, but it depends on mutable context data structures - (mainly hash maps) to give it meaning. - - - Many -- though not all -- nodes within this data structure are - wrapped in the type `spanned`, meaning that the front-end has - marked the input coordinates of that node. The member .node is - the data itself, the member .span is the input location (file, - line, column; both low and high). - - - Many other nodes within this data structure carry a - def_id. These nodes represent the 'target' of some name - reference elsewhere in the tree. When the AST is resolved, by - middle/resolve.rs, all names wind up acquiring a def that they - point to. So anything that can be pointed-to by a name winds - up with a def_id. - -#2: middle/ty.rs defines the datatype sty. This is the type that - represents types after they have been resolved and normalized by - the middle-end. The typeck phase converts every ast type to a - ty::sty, and the latter is used to drive later phases of - compilation. Most variants in the ast::ty tag have a - corresponding variant in the ty::sty tag. - -#3: lib/llvm.rs (in librustc_trans) defines the exported types - ValueRef, TypeRef, BasicBlockRef, and several others. Each of - these is an opaque pointer to an LLVM type, manipulated through - the lib::llvm interface. - - -Control and information flow within the compiler: -------------------------------------------------- - -- main() in lib.rs assumes control on startup. Options are - parsed, platform is detected, etc. - -- ./../libsyntax/parse/parser.rs parses the input files and produces an AST - that represents the input crate. - -- Multiple middle-end passes (middle/resolve.rs, middle/typeck.rs) - analyze the semantics of the resulting AST. Each pass generates new - information about the AST and stores it in various environment data - structures. The driver passes environments to each compiler pass - that needs to refer to them. - -- Finally, the `trans` module in `librustc_trans` translates the Rust - AST to LLVM bitcode in a type-directed way. When it's finished - synthesizing LLVM values, rustc asks LLVM to write them out in some - form (.bc, .o) and possibly run the system linker. diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 133bef30e4..0a29ed90ad 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -68,6 +68,8 @@ register_diagnostics! { E0019, E0020, E0022, + E0079, // enum variant: expected signed integer constant + E0080, // enum variant: constant evaluation error E0109, E0110, E0133, @@ -128,8 +130,8 @@ register_diagnostics! { E0313, // lifetime of borrowed pointer outlives lifetime of captured variable E0314, // closure outlives stack frame E0315, // cannot invoke closure outside of its lifetime - E0316 // nested quantification of lifetimes + E0316, // nested quantification of lifetimes + E0370 // discriminant overflow } __build_diagnostic_array! { DIAGNOSTICS } - diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index fe9a81bb7c..a4bb17bc35 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -28,20 +30,22 @@ #![feature(collections)] #![feature(core)] #![feature(hash)] -#![feature(int_uint)] -#![feature(old_io)] #![feature(libc)] -#![feature(env)] -#![feature(old_path)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(unsafe_destructor)] #![feature(staged_api)] #![feature(std_misc)] -#![feature(unicode)] +#![feature(path_ext)] +#![feature(str_words)] +#![feature(str_char)] +#![feature(into_cow)] +#![feature(slice_patterns)] #![cfg_attr(test, feature(test))] +#![allow(trivial_casts)] + extern crate arena; extern crate flate; extern crate fmt_macros; @@ -57,7 +61,7 @@ extern crate collections; #[macro_use] extern crate syntax; #[macro_use] #[no_link] extern crate rustc_bitflags; -extern crate "serialize" as rustc_serialize; // used by deriving +extern crate serialize as rustc_serialize; // used by deriving #[cfg(test)] extern crate test; @@ -116,6 +120,8 @@ pub mod middle { pub mod traits; pub mod ty; pub mod ty_fold; + pub mod ty_match; + pub mod ty_relate; pub mod ty_walk; pub mod weak_lang_items; } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index dc81e89902..495044f945 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,1955 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Lints built in to rustc. +//! Some lints that are built in to the compiler. //! -//! This is a sibling of `lint::context` in order to ensure that -//! lints implemented here use the same public API as lint plugins. -//! -//! To add a new lint to rustc, declare it here using `declare_lint!()`. -//! Then add code to emit the new lint in the appropriate circumstances. -//! You can do that in an existing `LintPass` if it makes sense, or in -//! a new `LintPass`, or using `Session::add_lint` elsewhere in the -//! compiler. Only do the latter if the check can't be written cleanly -//! as a `LintPass`. -//! -//! If you define a new `LintPass`, you will also need to add it to the -//! `add_builtin!` or `add_builtin_with_new!` invocation in `context.rs`. -//! Use the former for unit-like structs and the latter for structs with -//! a `pub fn new()`. -use self::MethodContext::*; - -use metadata::{csearch, decoder}; -use middle::def::*; -use middle::subst::Substs; -use middle::ty::{self, Ty}; -use middle::{def, pat_util, stability}; -use middle::const_eval::{eval_const_expr_partial, const_int, const_uint}; -use middle::cfg; -use util::ppaux::{ty_to_string}; -use util::nodemap::{FnvHashMap, NodeSet}; -use lint::{Level, Context, LintPass, LintArray, Lint}; - -use std::collections::BitSet; -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::num::SignedInt; -use std::{cmp, slice}; -use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; - -use syntax::{abi, ast, ast_map}; -use syntax::ast_util::is_shift_binop; -use syntax::attr::{self, AttrMetaMethods}; -use syntax::codemap::{self, Span}; -use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType}; -use syntax::parse::token; -use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; -use syntax::ast_util; -use syntax::ptr::P; -use syntax::visit::{self, Visitor}; - -declare_lint! { - WHILE_TRUE, - Warn, - "suggest using `loop { }` instead of `while true { }`" -} - -#[derive(Copy)] -pub struct WhileTrue; - -impl LintPass for WhileTrue { - fn get_lints(&self) -> LintArray { - lint_array!(WHILE_TRUE) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - if let ast::ExprWhile(ref cond, _, _) = e.node { - if let ast::ExprLit(ref lit) = cond.node { - if let ast::LitBool(true) = lit.node { - cx.span_lint(WHILE_TRUE, e.span, - "denote infinite loops with loop { ... }"); - } - } - } - } -} - -declare_lint! { - UNUSED_TYPECASTS, - Allow, - "detects unnecessary type casts that can be removed" -} - -#[derive(Copy)] -pub struct UnusedCasts; - -impl LintPass for UnusedCasts { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_TYPECASTS) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - if let ast::ExprCast(ref expr, ref ty) = e.node { - let t_t = ty::expr_ty(cx.tcx, e); - if ty::expr_ty(cx.tcx, &**expr) == t_t { - cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast"); - } - } - } -} - -declare_lint! { - UNSIGNED_NEGATION, - Warn, - "using an unary minus operator on unsigned type" -} - -declare_lint! { - UNUSED_COMPARISONS, - Warn, - "comparisons made useless by limits of the types involved" -} - -declare_lint! { - OVERFLOWING_LITERALS, - Warn, - "literal out of range for its type" -} - -declare_lint! { - EXCEEDING_BITSHIFTS, - Deny, - "shift exceeds the type's number of bits" -} - -#[derive(Copy)] -pub struct TypeLimits { - /// Id of the last visited negated expression - negated_expr_id: ast::NodeId, -} - -impl TypeLimits { - pub fn new() -> TypeLimits { - TypeLimits { - negated_expr_id: -1, - } - } -} - -impl LintPass for TypeLimits { - fn get_lints(&self) -> LintArray { - lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS, - EXCEEDING_BITSHIFTS) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - match e.node { - ast::ExprUnary(ast::UnNeg, ref expr) => { - match expr.node { - ast::ExprLit(ref lit) => { - match lit.node { - ast::LitInt(_, ast::UnsignedIntLit(_)) => { - cx.span_lint(UNSIGNED_NEGATION, e.span, - "negation of unsigned int literal may \ - be unintentional"); - }, - _ => () - } - }, - _ => { - let t = ty::expr_ty(cx.tcx, &**expr); - match t.sty { - ty::ty_uint(_) => { - cx.span_lint(UNSIGNED_NEGATION, e.span, - "negation of unsigned int variable may \ - be unintentional"); - }, - _ => () - } - } - }; - // propagate negation, if the negation itself isn't negated - if self.negated_expr_id != e.id { - self.negated_expr_id = expr.id; - } - }, - ast::ExprParen(ref expr) if self.negated_expr_id == e.id => { - self.negated_expr_id = expr.id; - }, - ast::ExprBinary(binop, ref l, ref r) => { - if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) { - cx.span_lint(UNUSED_COMPARISONS, e.span, - "comparison is useless due to type limits"); - } - - if is_shift_binop(binop.node) { - let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty { - ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), - ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), - _ => None - }; - - if let Some(bits) = opt_ty_bits { - let exceeding = if let ast::ExprLit(ref lit) = r.node { - if let ast::LitInt(shift, _) = lit.node { shift >= bits } - else { false } - } else { - match eval_const_expr_partial(cx.tcx, &**r, Some(cx.tcx.types.uint)) { - Ok(const_int(shift)) => { shift as u64 >= bits }, - Ok(const_uint(shift)) => { shift >= bits }, - _ => { false } - } - }; - if exceeding { - cx.span_lint(EXCEEDING_BITSHIFTS, e.span, - "bitshift exceeds the type's number of bits"); - } - }; - } - }, - ast::ExprLit(ref lit) => { - match ty::expr_ty(cx.tcx, e).sty { - ty::ty_int(t) => { - match lit.node { - ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | - ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => { - let int_type = if let ast::TyIs(_) = t { - cx.sess().target.int_type - } else { t }; - let (min, max) = int_ty_range(int_type); - let negative = self.negated_expr_id == e.id; - - if (negative && v > (min.abs() as u64)) || - (!negative && v > (max.abs() as u64)) { - cx.span_lint(OVERFLOWING_LITERALS, e.span, - &*format!("literal out of range for {:?}", t)); - return; - } - } - _ => panic!() - }; - }, - ty::ty_uint(t) => { - let uint_type = if let ast::TyUs(_) = t { - cx.sess().target.uint_type - } else { t }; - let (min, max) = uint_ty_range(uint_type); - let lit_val: u64 = match lit.node { - ast::LitByte(_v) => return, // _v is u8, within range by definition - ast::LitInt(v, _) => v, - _ => panic!() - }; - if lit_val < min || lit_val > max { - cx.span_lint(OVERFLOWING_LITERALS, e.span, - &*format!("literal out of range for {:?}", t)); - } - }, - ty::ty_float(t) => { - let (min, max) = float_ty_range(t); - let lit_val: f64 = match lit.node { - ast::LitFloat(ref v, _) | - ast::LitFloatUnsuffixed(ref v) => { - match v.parse().ok() { - Some(f) => f, - None => return - } - } - _ => panic!() - }; - if lit_val < min || lit_val > max { - cx.span_lint(OVERFLOWING_LITERALS, e.span, - &*format!("literal out of range for {:?}", t)); - } - }, - _ => () - }; - }, - _ => () - }; - - fn is_valid(binop: ast::BinOp, v: T, - min: T, max: T) -> bool { - match binop.node { - ast::BiLt => v > min && v <= max, - ast::BiLe => v >= min && v < max, - ast::BiGt => v >= min && v < max, - ast::BiGe => v > min && v <= max, - ast::BiEq | ast::BiNe => v >= min && v <= max, - _ => panic!() - } - } - - fn rev_binop(binop: ast::BinOp) -> ast::BinOp { - codemap::respan(binop.span, match binop.node { - ast::BiLt => ast::BiGt, - ast::BiLe => ast::BiGe, - ast::BiGt => ast::BiLt, - ast::BiGe => ast::BiLe, - _ => return binop - }) - } - - // for int & uint, be conservative with the warnings, so that the - // warnings are consistent between 32- and 64-bit platforms - fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) { - match int_ty { - ast::TyIs(_) => (i64::MIN, i64::MAX), - ast::TyI8 => (i8::MIN as i64, i8::MAX as i64), - ast::TyI16 => (i16::MIN as i64, i16::MAX as i64), - ast::TyI32 => (i32::MIN as i64, i32::MAX as i64), - ast::TyI64 => (i64::MIN, i64::MAX) - } - } - - fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) { - match uint_ty { - ast::TyUs(_) => (u64::MIN, u64::MAX), - ast::TyU8 => (u8::MIN as u64, u8::MAX as u64), - ast::TyU16 => (u16::MIN as u64, u16::MAX as u64), - ast::TyU32 => (u32::MIN as u64, u32::MAX as u64), - ast::TyU64 => (u64::MIN, u64::MAX) - } - } - - fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) { - match float_ty { - ast::TyF32 => (f32::MIN as f64, f32::MAX as f64), - ast::TyF64 => (f64::MIN, f64::MAX) - } - } - - fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 { - match int_ty { - ast::TyIs(_) => int_ty_bits(target_int_ty, target_int_ty), - ast::TyI8 => i8::BITS as u64, - ast::TyI16 => i16::BITS as u64, - ast::TyI32 => i32::BITS as u64, - ast::TyI64 => i64::BITS as u64 - } - } - - fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 { - match uint_ty { - ast::TyUs(_) => uint_ty_bits(target_uint_ty, target_uint_ty), - ast::TyU8 => u8::BITS as u64, - ast::TyU16 => u16::BITS as u64, - ast::TyU32 => u32::BITS as u64, - ast::TyU64 => u64::BITS as u64 - } - } - - fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp, - l: &ast::Expr, r: &ast::Expr) -> bool { - let (lit, expr, swap) = match (&l.node, &r.node) { - (&ast::ExprLit(_), _) => (l, r, true), - (_, &ast::ExprLit(_)) => (r, l, false), - _ => return true - }; - // Normalize the binop so that the literal is always on the RHS in - // the comparison - let norm_binop = if swap { rev_binop(binop) } else { binop }; - match ty::expr_ty(tcx, expr).sty { - ty::ty_int(int_ty) => { - let (min, max) = int_ty_range(int_ty); - let lit_val: i64 = match lit.node { - ast::ExprLit(ref li) => match li.node { - ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | - ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64, - ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) | - ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64), - _ => return true - }, - _ => panic!() - }; - is_valid(norm_binop, lit_val, min, max) - } - ty::ty_uint(uint_ty) => { - let (min, max): (u64, u64) = uint_ty_range(uint_ty); - let lit_val: u64 = match lit.node { - ast::ExprLit(ref li) => match li.node { - ast::LitInt(v, _) => v, - _ => return true - }, - _ => panic!() - }; - is_valid(norm_binop, lit_val, min, max) - } - _ => true - } - } - - fn is_comparison(binop: ast::BinOp) -> bool { - match binop.node { - ast::BiEq | ast::BiLt | ast::BiLe | - ast::BiNe | ast::BiGe | ast::BiGt => true, - _ => false - } - } - } -} - -declare_lint! { - IMPROPER_CTYPES, - Warn, - "proper use of libc types in foreign modules" -} - -struct ImproperCTypesVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> -} - -impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { - fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) { - match self.cx.tcx.def_map.borrow()[path_id].clone() { - def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => { - self.cx.span_lint(IMPROPER_CTYPES, sp, - "found rust type `isize` in foreign module, while \ - libc::c_int or libc::c_long should be used"); - } - def::DefPrimTy(ast::TyUint(ast::TyUs(_))) => { - self.cx.span_lint(IMPROPER_CTYPES, sp, - "found rust type `usize` in foreign module, while \ - libc::c_uint or libc::c_ulong should be used"); - } - def::DefTy(..) => { - let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty_id) { - Some(&ty::atttce_resolved(t)) => t, - _ => panic!("ast_ty_to_ty_cache was incomplete after typeck!") - }; - - if !ty::is_ffi_safe(self.cx.tcx, tty) { - self.cx.span_lint(IMPROPER_CTYPES, sp, - "found type without foreign-function-safe - representation annotation in foreign module, consider \ - adding a #[repr(...)] attribute to the type"); - } - } - _ => () - } - } -} - -impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &ast::Ty) { - match ty.node { - ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id), - _ => (), - } - visit::walk_ty(self, ty); - } -} - -#[derive(Copy)] -pub struct ImproperCTypes; - -impl LintPass for ImproperCTypes { - fn get_lints(&self) -> LintArray { - lint_array!(IMPROPER_CTYPES) - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - fn check_ty(cx: &Context, ty: &ast::Ty) { - let mut vis = ImproperCTypesVisitor { cx: cx }; - vis.visit_ty(ty); - } - - fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) { - for input in &decl.inputs { - check_ty(cx, &*input.ty); - } - if let ast::Return(ref ret_ty) = decl.output { - check_ty(cx, &**ret_ty); - } - } - - match it.node { - ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => { - for ni in &nmod.items { - match ni.node { - ast::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl), - ast::ForeignItemStatic(ref t, _) => check_ty(cx, &**t) - } - } - } - _ => (), - } - } -} - -declare_lint! { - BOX_POINTERS, - Allow, - "use of owned (Box type) heap memory" -} - -#[derive(Copy)] -pub struct BoxPointers; - -impl BoxPointers { - fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>, - span: Span, ty: Ty<'tcx>) { - let mut n_uniq: usize = 0; - ty::fold_ty(cx.tcx, ty, |t| { - match t.sty { - ty::ty_uniq(_) => { - n_uniq += 1; - } - _ => () - }; - t - }); - - if n_uniq > 0 { - let s = ty_to_string(cx.tcx, ty); - let m = format!("type uses owned (Box type) pointers: {}", s); - cx.span_lint(BOX_POINTERS, span, &m[..]); - } - } -} - -impl LintPass for BoxPointers { - fn get_lints(&self) -> LintArray { - lint_array!(BOX_POINTERS) - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - match it.node { - ast::ItemFn(..) | - ast::ItemTy(..) | - ast::ItemEnum(..) | - ast::ItemStruct(..) => - self.check_heap_type(cx, it.span, - ty::node_id_to_type(cx.tcx, it.id)), - _ => () - } - - // If it's a struct, we also have to check the fields' types - match it.node { - ast::ItemStruct(ref struct_def, _) => { - for struct_field in &struct_def.fields { - self.check_heap_type(cx, struct_field.span, - ty::node_id_to_type(cx.tcx, struct_field.node.id)); - } - } - _ => () - } - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - let ty = ty::expr_ty(cx.tcx, e); - self.check_heap_type(cx, e.span, ty); - } -} - -declare_lint! { - RAW_POINTER_DERIVE, - Warn, - "uses of #[derive] with raw pointers are rarely correct" -} - -struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> -} - -impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &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_DERIVE, ty.span, MSG); - } - visit::walk_ty(self, ty); - } - // explicit override to a no-op to reduce code bloat - fn visit_expr(&mut self, _: &ast::Expr) {} - fn visit_block(&mut self, _: &ast::Block) {} -} - -pub struct RawPointerDerive { - checked_raw_pointers: NodeSet, -} - -impl RawPointerDerive { - pub fn new() -> RawPointerDerive { - RawPointerDerive { - checked_raw_pointers: NodeSet(), - } - } -} - -impl LintPass for RawPointerDerive { - fn get_lints(&self) -> LintArray { - lint_array!(RAW_POINTER_DERIVE) - } - - fn check_item(&mut self, cx: &Context, item: &ast::Item) { - if !attr::contains_name(&item.attrs[], "automatically_derived") { - return - } - let did = match item.node { - ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { - // Deriving the Copy trait does not cause a warning - if let &Some(ref trait_ref) = t_ref_opt { - let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref); - if Some(def_id) == cx.tcx.lang_items.copy_trait() { - return - } - } - - match ty::node_id_to_type(cx.tcx, item.id).sty { - ty::ty_enum(did, _) => did, - ty::ty_struct(did, _) => did, - _ => return, - } - } - _ => return, - }; - if !ast_util::is_local(did) { return } - let item = match cx.tcx.map.find(did.node) { - Some(ast_map::NodeItem(item)) => item, - _ => return, - }; - if !self.checked_raw_pointers.insert(item.id) { return } - match item.node { - ast::ItemStruct(..) | ast::ItemEnum(..) => { - let mut visitor = RawPtrDeriveVisitor { cx: cx }; - visit::walk_item(&mut visitor, &*item); - } - _ => {} - } - } -} - -declare_lint! { - UNUSED_ATTRIBUTES, - Warn, - "detects attributes that were not used by the compiler" -} - -#[derive(Copy)] -pub struct UnusedAttributes; - -impl LintPass for UnusedAttributes { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_ATTRIBUTES) - } - - fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) { - for &(ref name, ty) in KNOWN_ATTRIBUTES { - match ty { - AttributeType::Whitelisted - | AttributeType::Gated(_, _) if attr.check_name(name) => { - break; - }, - _ => () - } - } - - if !attr::is_used(attr) { - cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); - if KNOWN_ATTRIBUTES.contains(&(&attr.name()[], AttributeType::CrateLevel)) { - let msg = match attr.node.style { - ast::AttrOuter => "crate-level attribute should be an inner \ - attribute: add an exclamation mark: #![foo]", - ast::AttrInner => "crate-level attribute should be in the \ - root module", - }; - cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg); - } - } - } -} - -declare_lint! { - pub PATH_STATEMENTS, - Warn, - "path statements with no effect" -} - -#[derive(Copy)] -pub struct PathStatements; - -impl LintPass for PathStatements { - fn get_lints(&self) -> LintArray { - lint_array!(PATH_STATEMENTS) - } - - fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { - match s.node { - ast::StmtSemi(ref expr, _) => { - match expr.node { - ast::ExprPath(_) => cx.span_lint(PATH_STATEMENTS, s.span, - "path statement with no effect"), - _ => () - } - } - _ => () - } - } -} - -declare_lint! { - pub UNUSED_MUST_USE, - Warn, - "unused result of a type flagged as #[must_use]" -} - -declare_lint! { - pub UNUSED_RESULTS, - Allow, - "unused result of an expression in a statement" -} - -#[derive(Copy)] -pub struct UnusedResults; - -impl LintPass for UnusedResults { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) - } - - fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { - let expr = match s.node { - ast::StmtSemi(ref expr, _) => &**expr, - _ => return - }; - - if let ast::ExprRet(..) = expr.node { - return; - } - - let t = ty::expr_ty(cx.tcx, expr); - let mut warned = false; - match t.sty { - ty::ty_tup(ref tys) if tys.is_empty() => return, - ty::ty_bool => return, - ty::ty_struct(did, _) | - ty::ty_enum(did, _) => { - if ast_util::is_local(did) { - if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) { - warned |= check_must_use(cx, &it.attrs[], s.span); - } - } else { - let attrs = csearch::get_item_attrs(&cx.sess().cstore, did); - warned |= check_must_use(cx, &attrs[..], s.span); - } - } - _ => {} - } - if !warned { - cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); - } - - fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool { - for attr in attrs { - if attr.check_name("must_use") { - let mut msg = "unused result which must be used".to_string(); - // check for #[must_use="..."] - match attr.value_str() { - None => {} - Some(s) => { - msg.push_str(": "); - msg.push_str(&s); - } - } - cx.span_lint(UNUSED_MUST_USE, sp, &msg); - return true; - } - } - false - } - } -} - -declare_lint! { - pub NON_CAMEL_CASE_TYPES, - Warn, - "types, variants, traits and type parameters should have camel case names" -} - -#[derive(Copy)] -pub struct NonCamelCaseTypes; - -impl NonCamelCaseTypes { - fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { - fn is_camel_case(ident: ast::Ident) -> bool { - let ident = token::get_ident(ident); - if ident.is_empty() { return true; } - let ident = ident.trim_matches('_'); - - // start with a non-lowercase letter rather than non-uppercase - // ones (some scripts don't have a concept of upper/lowercase) - ident.len() > 0 && !ident.char_at(0).is_lowercase() && !ident.contains_char('_') - } - - fn to_camel_case(s: &str) -> String { - s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)| - if i == 0 { c.to_uppercase() } - else { c } - )).collect() - } - - let s = token::get_ident(ident); - - if !is_camel_case(ident) { - let c = to_camel_case(&s); - let m = if c.is_empty() { - format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s) - } else { - format!("{} `{}` should have a camel case name such as `{}`", sort, s, c) - }; - cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]); - } - } -} - -impl LintPass for NonCamelCaseTypes { - fn get_lints(&self) -> LintArray { - lint_array!(NON_CAMEL_CASE_TYPES) - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - let has_extern_repr = it.attrs.iter().map(|attr| { - attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter() - .any(|r| r == &attr::ReprExtern) - }).any(|x| x); - if has_extern_repr { return } - - match it.node { - ast::ItemTy(..) | ast::ItemStruct(..) => { - self.check_case(cx, "type", it.ident, it.span) - } - ast::ItemTrait(..) => { - self.check_case(cx, "trait", it.ident, it.span) - } - ast::ItemEnum(ref enum_definition, _) => { - if has_extern_repr { return } - self.check_case(cx, "type", it.ident, it.span); - for variant in &enum_definition.variants { - self.check_case(cx, "variant", variant.node.name, variant.span); - } - } - _ => () - } - } - - fn check_generics(&mut self, cx: &Context, it: &ast::Generics) { - for gen in &*it.ty_params { - self.check_case(cx, "type parameter", gen.ident, gen.span); - } - } -} - -#[derive(PartialEq)] -enum MethodContext { - TraitDefaultImpl, - TraitImpl, - PlainImpl -} - -fn method_context(cx: &Context, m: &ast::Method) -> MethodContext { - let did = ast::DefId { - krate: ast::LOCAL_CRATE, - node: m.id - }; - - match cx.tcx.impl_or_trait_items.borrow().get(&did).cloned() { - None => cx.sess().span_bug(m.span, "missing method descriptor?!"), - Some(md) => { - match md { - ty::MethodTraitItem(md) => { - match md.container { - ty::TraitContainer(..) => TraitDefaultImpl, - ty::ImplContainer(cid) => { - match ty::impl_trait_ref(cx.tcx, cid) { - Some(..) => TraitImpl, - None => PlainImpl - } - } - } - } - ty::TypeTraitItem(typedef) => { - match typedef.container { - ty::TraitContainer(..) => TraitDefaultImpl, - ty::ImplContainer(cid) => { - match ty::impl_trait_ref(cx.tcx, cid) { - Some(..) => TraitImpl, - None => PlainImpl - } - } - } - } - } - } - } -} - -declare_lint! { - pub NON_SNAKE_CASE, - Warn, - "methods, functions, lifetime parameters and modules should have snake case names" -} - -#[derive(Copy)] -pub struct NonSnakeCase; - -impl NonSnakeCase { - fn to_snake_case(mut str: &str) -> String { - let mut words = vec![]; - // Preserve leading underscores - str = str.trim_left_matches(|c: char| { - if c == '_' { - words.push(String::new()); - true - } else { false } - }); - for s in str.split('_') { - let mut last_upper = false; - let mut buf = String::new(); - if s.is_empty() { continue; } - for ch in s.chars() { - if !buf.is_empty() && buf != "'" - && ch.is_uppercase() - && !last_upper { - words.push(buf); - buf = String::new(); - } - last_upper = ch.is_uppercase(); - buf.push(ch.to_lowercase()); - } - words.push(buf); - } - words.connect("_") - } - - fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { - fn is_snake_case(ident: ast::Ident) -> bool { - let ident = token::get_ident(ident); - if ident.is_empty() { return true; } - let ident = ident.trim_left_matches('\''); - let ident = ident.trim_matches('_'); - - let mut allow_underscore = true; - ident.chars().all(|c| { - allow_underscore = match c { - '_' if !allow_underscore => return false, - '_' => false, - c if !c.is_uppercase() => true, - _ => return false, - }; - true - }) - } - - let s = token::get_ident(ident); - - if !is_snake_case(ident) { - let sc = NonSnakeCase::to_snake_case(&s); - if sc != &s[..] { - cx.span_lint(NON_SNAKE_CASE, span, - &*format!("{} `{}` should have a snake case name such as `{}`", - sort, s, sc)); - } else { - cx.span_lint(NON_SNAKE_CASE, span, - &*format!("{} `{}` should have a snake case name", - sort, s)); - } - } - } -} - -impl LintPass for NonSnakeCase { - fn get_lints(&self) -> LintArray { - lint_array!(NON_SNAKE_CASE) - } - - fn check_fn(&mut self, cx: &Context, - fk: visit::FnKind, _: &ast::FnDecl, - _: &ast::Block, span: Span, _: ast::NodeId) { - match fk { - visit::FkMethod(ident, _, m) => match method_context(cx, m) { - PlainImpl - => self.check_snake_case(cx, "method", ident, span), - TraitDefaultImpl - => self.check_snake_case(cx, "trait method", ident, span), - _ => (), - }, - visit::FkItemFn(ident, _, _, _) - => self.check_snake_case(cx, "function", ident, span), - _ => (), - } - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - if let ast::ItemMod(_) = it.node { - self.check_snake_case(cx, "module", it.ident, it.span); - } - } - - fn check_ty_method(&mut self, cx: &Context, t: &ast::TypeMethod) { - self.check_snake_case(cx, "trait method", t.ident, t.span); - } - - fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) { - self.check_snake_case(cx, "lifetime", t.lifetime.name.ident(), t.lifetime.span); - } - - fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { - if let &ast::PatIdent(_, ref path1, _) = &p.node { - if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) { - self.check_snake_case(cx, "variable", path1.node, p.span); - } - } - } - - fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef, - _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { - for sf in &s.fields { - if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node { - self.check_snake_case(cx, "structure field", ident, sf.span); - } - } - } -} - -declare_lint! { - pub NON_UPPER_CASE_GLOBALS, - Warn, - "static constants should have uppercase identifiers" -} - -#[derive(Copy)] -pub struct NonUpperCaseGlobals; - -impl NonUpperCaseGlobals { - fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) { - let s = token::get_ident(ident); - - if s.chars().any(|c| c.is_lowercase()) { - let uc: String = NonSnakeCase::to_snake_case(&s).chars() - .map(|c| c.to_uppercase()).collect(); - if uc != &s[..] { - cx.span_lint(NON_UPPER_CASE_GLOBALS, span, - &format!("{} `{}` should have an upper case name such as `{}`", - sort, s, uc)); - } else { - cx.span_lint(NON_UPPER_CASE_GLOBALS, span, - &format!("{} `{}` should have an upper case name", - sort, s)); - } - } - } -} - -impl LintPass for NonUpperCaseGlobals { - fn get_lints(&self) -> LintArray { - lint_array!(NON_UPPER_CASE_GLOBALS) - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - match it.node { - // only check static constants - ast::ItemStatic(_, ast::MutImmutable, _) => { - NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span); - } - ast::ItemConst(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.span); - } - _ => {} - } - } - - fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { - // Lint for constants that look like binding identifiers (#7526) - match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) { - (&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", - path1.node, p.span); - } - _ => {} - } - } -} - -declare_lint! { - UNUSED_PARENS, - Warn, - "`if`, `match`, `while` and `return` do not need parentheses" -} - -#[derive(Copy)] -pub struct UnusedParens; - -impl UnusedParens { - fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str, - struct_lit_needs_parens: bool) { - if let ast::ExprParen(ref inner) = value.node { - let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); - if !necessary { - cx.span_lint(UNUSED_PARENS, value.span, - &format!("unnecessary parentheses around {}", - msg)[]) - } - } - - /// Expressions that syntactically contain an "exterior" struct - /// literal i.e. not surrounded by any parens or other - /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo - /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X { - /// y: 1 }) == foo` does not. - fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { - match value.node { - ast::ExprStruct(..) => true, - - ast::ExprAssign(ref lhs, ref rhs) | - ast::ExprAssignOp(_, ref lhs, ref rhs) | - ast::ExprBinary(_, ref lhs, ref rhs) => { - // X { y: 1 } + X { y: 2 } - contains_exterior_struct_lit(&**lhs) || - contains_exterior_struct_lit(&**rhs) - } - ast::ExprUnary(_, ref x) | - ast::ExprCast(ref x, _) | - ast::ExprField(ref x, _) | - ast::ExprTupField(ref x, _) | - ast::ExprIndex(ref x, _) => { - // &X { y: 1 }, X { y: 1 }.y - contains_exterior_struct_lit(&**x) - } - - ast::ExprMethodCall(_, _, ref exprs) => { - // X { y: 1 }.bar(...) - contains_exterior_struct_lit(&*exprs[0]) - } - - _ => false - } - } - } -} - -impl LintPass for UnusedParens { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_PARENS) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - let (value, msg, struct_lit_needs_parens) = match e.node { - ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), - ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), - ast::ExprMatch(ref head, _, source) => match source { - ast::MatchSource::Normal => (head, "`match` head expression", true), - ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), - ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), - ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true), - }, - ast::ExprRet(Some(ref value)) => (value, "`return` value", false), - ast::ExprAssign(_, ref value) => (value, "assigned value", false), - ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false), - _ => return - }; - self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); - } - - fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { - let (value, msg) = match s.node { - ast::StmtDecl(ref decl, _) => match decl.node { - ast::DeclLocal(ref local) => match local.init { - Some(ref value) => (value, "assigned value"), - None => return - }, - _ => return - }, - _ => return - }; - self.check_unused_parens_core(cx, &**value, msg, false); - } -} - -declare_lint! { - UNUSED_IMPORT_BRACES, - Allow, - "unnecessary braces around an imported item" -} - -#[derive(Copy)] -pub struct UnusedImportBraces; - -impl LintPass for UnusedImportBraces { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_IMPORT_BRACES) - } - - fn check_item(&mut self, cx: &Context, item: &ast::Item) { - match item.node { - ast::ItemUse(ref view_path) => { - match view_path.node { - ast::ViewPathList(_, ref items) => { - if items.len() == 1 { - match items[0].node { - ast::PathListIdent {ref name, ..} => { - let m = format!("braces around {} is unnecessary", - &token::get_ident(*name)); - cx.span_lint(UNUSED_IMPORT_BRACES, item.span, - &m[..]); - }, - _ => () - } - } - } - _ => () - } - }, - _ => () - } - } -} - -declare_lint! { - NON_SHORTHAND_FIELD_PATTERNS, - Warn, - "using `Struct { x: x }` instead of `Struct { x }`" -} - -#[derive(Copy)] -pub struct NonShorthandFieldPatterns; - -impl LintPass for NonShorthandFieldPatterns { - fn get_lints(&self) -> LintArray { - lint_array!(NON_SHORTHAND_FIELD_PATTERNS) - } - - fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { - let def_map = cx.tcx.def_map.borrow(); - if let ast::PatStruct(_, ref v, _) = pat.node { - for fieldpat in v.iter() - .filter(|fieldpat| !fieldpat.node.is_shorthand) - .filter(|fieldpat| def_map.get(&fieldpat.node.pat.id) - == Some(&def::DefLocal(fieldpat.node.pat.id))) { - if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node { - if ident.node.as_str() == fieldpat.node.ident.as_str() { - cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, - &format!("the `{}:` in this pattern is redundant and can \ - be removed", ident.node.as_str())[]) - } - } - } - } - } -} - -declare_lint! { - pub UNUSED_UNSAFE, - Warn, - "unnecessary use of an `unsafe` block" -} - -#[derive(Copy)] -pub struct UnusedUnsafe; - -impl LintPass for UnusedUnsafe { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_UNSAFE) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - if let ast::ExprBlock(ref blk) = e.node { - // Don't warn about generated blocks, that'll just pollute the output. - if blk.rules == ast::UnsafeBlock(ast::UserProvided) && - !cx.tcx.used_unsafe.borrow().contains(&blk.id) { - cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block"); - } - } - } -} - -declare_lint! { - UNSAFE_BLOCKS, - Allow, - "usage of an `unsafe` block" -} - -#[derive(Copy)] -pub struct UnsafeBlocks; - -impl LintPass for UnsafeBlocks { - fn get_lints(&self) -> LintArray { - lint_array!(UNSAFE_BLOCKS) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - if let ast::ExprBlock(ref blk) = e.node { - // Don't warn about generated blocks, that'll just pollute the output. - if blk.rules == ast::UnsafeBlock(ast::UserProvided) { - cx.span_lint(UNSAFE_BLOCKS, blk.span, "usage of an `unsafe` block"); - } - } - } -} - -declare_lint! { - pub UNUSED_MUT, - Warn, - "detect mut variables which don't need to be mutable" -} - -#[derive(Copy)] -pub struct UnusedMut; - -impl UnusedMut { - fn check_unused_mut_pat(&self, cx: &Context, pats: &[P]) { - // collect all mutable pattern and group their NodeIDs by their Identifier to - // avoid false warnings in match arms with multiple patterns - - let mut mutables = FnvHashMap(); - for p in pats { - pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| { - let ident = path1.node; - if let ast::BindByValue(ast::MutMutable) = mode { - if !token::get_ident(ident).starts_with("_") { - match mutables.entry(ident.name.usize()) { - Vacant(entry) => { entry.insert(vec![id]); }, - Occupied(mut entry) => { entry.get_mut().push(id); }, - } - } - } - }); - } - - let used_mutables = cx.tcx.used_mut_nodes.borrow(); - for (_, v) in &mutables { - if !v.iter().any(|e| used_mutables.contains(e)) { - cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]), - "variable does not need to be mutable"); - } - } - } -} - -impl LintPass for UnusedMut { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_MUT) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - if let ast::ExprMatch(_, ref arms, _) = e.node { - for a in arms { - self.check_unused_mut_pat(cx, &a.pats[]) - } - } - } - - fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { - if let ast::StmtDecl(ref d, _) = s.node { - if let ast::DeclLocal(ref l) = d.node { - self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); - } - } - } - - fn check_fn(&mut self, cx: &Context, - _: visit::FnKind, decl: &ast::FnDecl, - _: &ast::Block, _: Span, _: ast::NodeId) { - for a in &decl.inputs { - self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat)); - } - } -} - -declare_lint! { - UNUSED_ALLOCATION, - Warn, - "detects unnecessary allocations that can be eliminated" -} - -#[derive(Copy)] -pub struct UnusedAllocation; - -impl LintPass for UnusedAllocation { - fn get_lints(&self) -> LintArray { - lint_array!(UNUSED_ALLOCATION) - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - match e.node { - ast::ExprUnary(ast::UnUniq, _) => (), - _ => return - } - - if let Some(adjustment) = cx.tcx.adjustments.borrow().get(&e.id) { - if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment { - match autoref { - &Some(ty::AutoPtr(_, ast::MutImmutable, None)) => { - cx.span_lint(UNUSED_ALLOCATION, e.span, - "unnecessary allocation, use & instead"); - } - &Some(ty::AutoPtr(_, ast::MutMutable, None)) => { - cx.span_lint(UNUSED_ALLOCATION, e.span, - "unnecessary allocation, use &mut instead"); - } - _ => () - } - } - } - } -} - -declare_lint! { - MISSING_DOCS, - Allow, - "detects missing documentation for public members" -} - -pub struct MissingDoc { - /// Stack of IDs of struct definitions. - struct_def_stack: Vec, - - /// True if inside variant definition - in_variant: bool, - - /// Stack of whether #[doc(hidden)] is set - /// at each level which has lint attributes. - doc_hidden_stack: Vec, -} - -impl MissingDoc { - pub fn new() -> MissingDoc { - MissingDoc { - struct_def_stack: vec!(), - in_variant: false, - doc_hidden_stack: vec!(false), - } - } - - fn doc_hidden(&self) -> bool { - *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") - } - - fn check_missing_docs_attrs(&self, - cx: &Context, - id: Option, - attrs: &[ast::Attribute], - sp: Span, - desc: &'static str) { - // If we're building a test harness, then warning about - // documentation is probably not really relevant right now. - if cx.sess().opts.test { return } - - // `#[doc(hidden)]` disables missing_docs check. - if self.doc_hidden() { return } - - // Only check publicly-visible items, using the result from the privacy pass. - // It's an option so the crate root can also use this function (it doesn't - // have a NodeId). - if let Some(ref id) = id { - if !cx.exported_items.contains(id) { - return; - } - } - - let has_doc = attrs.iter().any(|a| { - match a.node.value.node { - ast::MetaNameValue(ref name, _) if *name == "doc" => true, - _ => false - } - }); - if !has_doc { - cx.span_lint(MISSING_DOCS, sp, - &format!("missing documentation for {}", desc)[]); - } - } -} - -impl LintPass for MissingDoc { - fn get_lints(&self) -> LintArray { - lint_array!(MISSING_DOCS) - } - - fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) { - let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { - attr.check_name("doc") && match attr.meta_item_list() { - None => false, - Some(l) => attr::contains_name(&l[..], "hidden"), - } - }); - self.doc_hidden_stack.push(doc_hidden); - } - - fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { - self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); - } - - fn check_struct_def(&mut self, _: &Context, - _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { - self.struct_def_stack.push(id); - } - - fn check_struct_def_post(&mut self, _: &Context, - _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { - let popped = self.struct_def_stack.pop().expect("empty struct_def_stack"); - assert!(popped == id); - } - - fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) { - self.check_missing_docs_attrs(cx, None, &krate.attrs[], - krate.span, "crate"); - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - let desc = match it.node { - ast::ItemFn(..) => "a function", - ast::ItemMod(..) => "a module", - ast::ItemEnum(..) => "an enum", - ast::ItemStruct(..) => "a struct", - ast::ItemTrait(..) => "a trait", - ast::ItemTy(..) => "a type alias", - _ => return - }; - self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs[], - it.span, desc); - } - - fn check_fn(&mut self, cx: &Context, - fk: visit::FnKind, _: &ast::FnDecl, - _: &ast::Block, _: Span, _: ast::NodeId) { - if let visit::FkMethod(_, _, m) = fk { - // If the method is an impl for a trait, don't doc. - if method_context(cx, m) == TraitImpl { return; } - - // Otherwise, doc according to privacy. This will also check - // doc for default methods defined on traits. - self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs[], - m.span, "a method"); - } - } - - fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) { - self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs[], - tm.span, "a type method"); - } - - fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) { - if let ast::NamedField(_, vis) = sf.node.kind { - if vis == ast::Public || self.in_variant { - let cur_struct_def = *self.struct_def_stack.last() - .expect("empty struct_def_stack"); - self.check_missing_docs_attrs(cx, Some(cur_struct_def), - &sf.node.attrs[], sf.span, - "a struct field") - } - } - } - - fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) { - self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs[], - v.span, "a variant"); - assert!(!self.in_variant); - self.in_variant = true; - } - - fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { - assert!(self.in_variant); - self.in_variant = false; - } -} - -#[derive(Copy)] -pub struct MissingCopyImplementations; - -impl LintPass for MissingCopyImplementations { - fn get_lints(&self) -> LintArray { - lint_array!(MISSING_COPY_IMPLEMENTATIONS) - } - - fn check_item(&mut self, cx: &Context, item: &ast::Item) { - if !cx.exported_items.contains(&item.id) { - return - } - if cx.tcx - .destructor_for_type - .borrow() - .contains_key(&ast_util::local_def(item.id)) { - return - } - let ty = match item.node { - ast::ItemStruct(_, ref ast_generics) => { - if ast_generics.is_parameterized() { - return - } - ty::mk_struct(cx.tcx, - ast_util::local_def(item.id), - cx.tcx.mk_substs(Substs::empty())) - } - ast::ItemEnum(_, ref ast_generics) => { - if ast_generics.is_parameterized() { - return - } - ty::mk_enum(cx.tcx, - ast_util::local_def(item.id), - cx.tcx.mk_substs(Substs::empty())) - } - _ => return, - }; - let parameter_environment = ty::empty_parameter_environment(cx.tcx); - if !ty::type_moves_by_default(¶meter_environment, item.span, ty) { - return - } - if ty::can_type_implement_copy(¶meter_environment, item.span, ty).is_ok() { - cx.span_lint(MISSING_COPY_IMPLEMENTATIONS, - item.span, - "type could implement `Copy`; consider adding `impl \ - Copy`") - } - } -} - -declare_lint! { - MISSING_DEBUG_IMPLEMENTATIONS, - Allow, - "detects missing implementations of fmt::Debug" -} - -pub struct MissingDebugImplementations { - impling_types: Option, -} - -impl MissingDebugImplementations { - pub fn new() -> MissingDebugImplementations { - MissingDebugImplementations { - impling_types: None, - } - } -} - -impl LintPass for MissingDebugImplementations { - fn get_lints(&self) -> LintArray { - lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) - } - - fn check_item(&mut self, cx: &Context, item: &ast::Item) { - if !cx.exported_items.contains(&item.id) { - return; - } - - match item.node { - ast::ItemStruct(..) | ast::ItemEnum(..) => {}, - _ => return, - } - - let debug = match cx.tcx.lang_items.debug_trait() { - Some(debug) => debug, - None => return, - }; - - if self.impling_types.is_none() { - let impls = cx.tcx.trait_impls.borrow(); - let impls = match impls.get(&debug) { - Some(impls) => { - impls.borrow().iter() - .filter(|d| d.krate == ast::LOCAL_CRATE) - .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node))) - .map(|d| d.node) - .collect() - } - None => NodeSet(), - }; - self.impling_types = Some(impls); - debug!("{:?}", self.impling_types); - } - - if !self.impling_types.as_ref().unwrap().contains(&item.id) { - cx.span_lint(MISSING_DEBUG_IMPLEMENTATIONS, - item.span, - "type does not implement `fmt::Debug`; consider adding #[derive(Debug)] \ - or a manual implementation") - } - } -} - -declare_lint! { - DEPRECATED, - Warn, - "detects use of #[deprecated] items" -} - -/// Checks for use of items with `#[deprecated]` attributes -#[derive(Copy)] -pub struct Stability; - -impl Stability { - fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option) { - - // deprecated attributes apply in-crate and cross-crate - let (lint, label) = match *stability { - Some(attr::Stability { deprecated_since: Some(_), .. }) => - (DEPRECATED, "deprecated"), - _ => return - }; - - output(cx, span, stability, lint, label); - - fn output(cx: &Context, span: Span, stability: &Option, - lint: &'static Lint, label: &'static str) { - let msg = match *stability { - Some(attr::Stability { reason: Some(ref s), .. }) => { - format!("use of {} item: {}", label, *s) - } - _ => format!("use of {} item", label) - }; - - cx.span_lint(lint, span, &msg[..]); - } - } -} - -impl LintPass for Stability { - fn get_lints(&self) -> LintArray { - lint_array!(DEPRECATED) - } - - fn check_item(&mut self, cx: &Context, item: &ast::Item) { - stability::check_item(cx.tcx, item, false, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); - } - - fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - stability::check_expr(cx.tcx, e, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); - } - - fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) { - stability::check_path(cx.tcx, path, id, - &mut |id, sp, stab| self.lint(cx, id, sp, stab)); - } -} - -declare_lint! { - pub UNCONDITIONAL_RECURSION, - Warn, - "functions that cannot return without calling themselves" -} - -#[derive(Copy)] -pub struct UnconditionalRecursion; - - -impl LintPass for UnconditionalRecursion { - fn get_lints(&self) -> LintArray { - lint_array![UNCONDITIONAL_RECURSION] - } - - fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl, - blk: &ast::Block, sp: Span, id: ast::NodeId) { - type F = for<'tcx> fn(&ty::ctxt<'tcx>, - ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool; - - let (name, checker) = match fn_kind { - visit::FkItemFn(name, _, _, _) => (name, id_refers_to_this_fn as F), - visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F), - // closures can't recur, so they don't matter. - visit::FkFnBlock => return - }; +//! These are the built-in lints that are emitted direct in the main +//! compiler code, rather than using their own custom pass. Those +//! lints are all available in `rustc_lint::builtin`. - let impl_def_id = ty::impl_of_method(cx.tcx, ast_util::local_def(id)) - .unwrap_or(ast_util::local_def(ast::DUMMY_NODE_ID)); - assert!(ast_util::is_local(impl_def_id)); - let impl_node_id = impl_def_id.node; - - // Walk through this function (say `f`) looking to see if - // every possible path references itself, i.e. the function is - // called recursively unconditionally. This is done by trying - // to find a path from the entry node to the exit node that - // *doesn't* call `f` by traversing from the entry while - // pretending that calls of `f` are sinks (i.e. ignoring any - // exit edges from them). - // - // NB. this has an edge case with non-returning statements, - // like `loop {}` or `panic!()`: control flow never reaches - // the exit node through these, so one can have a function - // that never actually calls itselfs but is still picked up by - // this lint: - // - // fn f(cond: bool) { - // if !cond { panic!() } // could come from `assert!(cond)` - // f(false) - // } - // - // In general, functions of that form may be able to call - // itself a finite number of times and then diverge. The lint - // considers this to be an error for two reasons, (a) it is - // easier to implement, and (b) it seems rare to actually want - // to have behaviour like the above, rather than - // e.g. accidentally recurring after an assert. - - let cfg = cfg::CFG::new(cx.tcx, blk); - - let mut work_queue = vec![cfg.entry]; - let mut reached_exit_without_self_call = false; - let mut self_call_spans = vec![]; - let mut visited = BitSet::new(); - - while let Some(idx) = work_queue.pop() { - let cfg_id = idx.node_id(); - if idx == cfg.exit { - // found a path! - reached_exit_without_self_call = true; - break - } else if visited.contains(&cfg_id) { - // already done - continue - } - visited.insert(cfg_id); - let node_id = cfg.graph.node_data(idx).id; - - // is this a recursive call? - if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) { - - self_call_spans.push(cx.tcx.map.span(node_id)); - // this is a self call, so we shouldn't explore past - // this node in the CFG. - continue - } - // add the successors of this node to explore the graph further. - cfg.graph.each_outgoing_edge(idx, |_, edge| { - let target_idx = edge.target(); - let target_cfg_id = target_idx.node_id(); - if !visited.contains(&target_cfg_id) { - work_queue.push(target_idx) - } - true - }); - } - - // check the number of sell calls because a function that - // doesn't return (e.g. calls a `-> !` function or `loop { /* - // no break */ }`) shouldn't be linted unless it actually - // recurs. - if !reached_exit_without_self_call && self_call_spans.len() > 0 { - cx.span_lint(UNCONDITIONAL_RECURSION, sp, - "function cannot return without recurring"); - - // FIXME #19668: these could be span_lint_note's instead of this manual guard. - if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow { - let sess = cx.sess(); - // offer some help to the programmer. - for call in &self_call_spans { - sess.span_note(*call, "recursive call site") - } - sess.span_help(sp, "a `loop` may express intention better if this is on purpose") - } - } - - // all done - return; - - // Functions for identifying if the given NodeId `id` - // represents a call to the function `fn_id`/method - // `method_id`. - - fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>, - _: ast::NodeId, - fn_id: ast::NodeId, - _: ast::Ident, - id: ast::NodeId) -> bool { - tcx.def_map.borrow().get(&id) - .map_or(false, |def| { - let did = def.def_id(); - ast_util::is_local(did) && did.node == fn_id - }) - } - - // check if the method call `id` refers to method `method_id` - // (with name `method_name` contained in impl `impl_id`). - fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>, - impl_id: ast::NodeId, - method_id: ast::NodeId, - method_name: ast::Ident, - id: ast::NodeId) -> bool { - let did = match tcx.method_map.borrow().get(&ty::MethodCall::expr(id)) { - None => return false, - Some(m) => match m.origin { - // There's no way to know if a method call via a - // vtable is recursion, so we assume it's not. - ty::MethodTraitObject(_) => return false, - - // This `did` refers directly to the method definition. - ty::MethodStatic(did) | ty::MethodStaticClosure(did) => did, - - // MethodTypeParam are methods from traits: - - // The `impl ... for ...` of this method call - // isn't known, e.g. it might be a default method - // in a trait, so we get the def-id of the trait - // method instead. - ty::MethodTypeParam( - ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => { - ty::trait_item(tcx, trait_ref.def_id, method_num).def_id() - } - - // The `impl` is known, so we check that with a - // special case: - ty::MethodTypeParam( - ty::MethodParam { impl_def_id: Some(impl_def_id), .. }) => { - - let name = match tcx.map.expect_expr(id).node { - ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node, - _ => tcx.sess.span_bug( - tcx.map.span(id), - "non-method call expr behaving like a method call?") - }; - // it matches if it comes from the same impl, - // and has the same method name. - return ast_util::is_local(impl_def_id) - && impl_def_id.node == impl_id - && method_name.name == name.name - } - } - }; - - ast_util::is_local(did) && did.node == method_id - } - } -} - -declare_lint! { - PLUGIN_AS_LIBRARY, - Warn, - "compiler plugin used as ordinary library in non-plugin crate" -} - -#[derive(Copy)] -pub struct PluginAsLibrary; - -impl LintPass for PluginAsLibrary { - fn get_lints(&self) -> LintArray { - lint_array![PLUGIN_AS_LIBRARY] - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - if cx.sess().plugin_registrar_fn.get().is_some() { - // We're compiling a plugin; it's fine to link other plugins. - return; - } - - match it.node { - ast::ItemExternCrate(..) => (), - _ => return, - }; - - let md = match cx.sess().cstore.find_extern_mod_stmt_cnum(it.id) { - Some(cnum) => cx.sess().cstore.get_crate_data(cnum), - None => { - // Probably means we aren't linking the crate for some reason. - // - // Not sure if / when this could happen. - return; - } - }; - - if decoder::get_plugin_registrar_fn(md.data()).is_some() { - cx.span_lint(PLUGIN_AS_LIBRARY, it.span, - "compiler plugin used as an ordinary library"); - } - } -} +use lint::{LintPass, LintArray}; declare_lint! { pub UNUSED_IMPORTS, @@ -2043,14 +101,19 @@ declare_lint! { } declare_lint! { - pub MISSING_COPY_IMPLEMENTATIONS, + pub TRIVIAL_CASTS, Allow, - "detects potentially-forgotten implementations of `Copy`" + "detects trivial casts which could be removed" } +declare_lint! { + pub TRIVIAL_NUMERIC_CASTS, + Allow, + "detects trivial casts of numeric types which could be removed" +} /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct HardwiredLints; impl LintPass for HardwiredLints { @@ -2069,86 +132,9 @@ impl LintPass for HardwiredLints { STABLE_FEATURES, UNKNOWN_CRATE_TYPES, VARIANT_SIZE_DIFFERENCES, - FAT_PTR_TRANSMUTES + FAT_PTR_TRANSMUTES, + TRIVIAL_CASTS, + TRIVIAL_NUMERIC_CASTS ) } } - -declare_lint! { - PRIVATE_NO_MANGLE_FNS, - Warn, - "functions marked #[no_mangle] should be exported" -} - -declare_lint! { - PRIVATE_NO_MANGLE_STATICS, - Warn, - "statics marked #[no_mangle] should be exported" -} - -declare_lint! { - NO_MANGLE_CONST_ITEMS, - Deny, - "const items will not have their symbols exported" -} - -#[derive(Copy)] -pub struct InvalidNoMangleItems; - -impl LintPass for InvalidNoMangleItems { - fn get_lints(&self) -> LintArray { - lint_array!(PRIVATE_NO_MANGLE_FNS, - PRIVATE_NO_MANGLE_STATICS, - NO_MANGLE_CONST_ITEMS) - } - - fn check_item(&mut self, cx: &Context, it: &ast::Item) { - match it.node { - ast::ItemFn(..) => { - if attr::contains_name(&it.attrs, "no_mangle") && - !cx.exported_items.contains(&it.id) { - let msg = format!("function {} is marked #[no_mangle], but not exported", - it.ident); - cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg); - } - }, - ast::ItemStatic(..) => { - if attr::contains_name(it.attrs.as_slice(), "no_mangle") && - !cx.exported_items.contains(&it.id) { - let msg = format!("static {} is marked #[no_mangle], but not exported", - it.ident); - cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg.as_slice()); - } - }, - ast::ItemConst(..) => { - if attr::contains_name(it.attrs.as_slice(), "no_mangle") { - // Const items do not refer to a particular location in memory, and therefore - // don't have anything to attach a symbol to - let msg = "const items should never be #[no_mangle], consider instead using \ - `pub static`"; - cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); - } - } - _ => {}, - } - } -} - -/// Forbids using the `#[feature(...)]` attribute -#[derive(Copy)] -pub struct UnstableFeatures; - -declare_lint!(UNSTABLE_FEATURES, Allow, - "enabling unstable features"); - -impl LintPass for UnstableFeatures { - fn get_lints(&self) -> LintArray { - lint_array!(UNSTABLE_FEATURES) - } - fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) { - use syntax::attr; - if attr::contains_name(&[attr.node.value.clone()], "feature") { - ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature"); - } - } -} diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 068c179d34..9688447dc0 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -105,7 +105,7 @@ impl LintStore { } pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] { - &self.lints[] + &self.lints } pub fn get_lint_groups<'t>(&'t self) -> Vec<(&'static str, Vec, bool)> { @@ -159,7 +159,7 @@ impl LintStore { } } - fn register_renamed(&mut self, old_name: &str, new_name: &str) { + pub fn register_renamed(&mut self, old_name: &str, new_name: &str) { let target = match self.by_name.get(new_name) { Some(&Id(lint_id)) => lint_id.clone(), _ => panic!("invalid lint renaming of {} to {}", old_name, new_name) @@ -167,80 +167,6 @@ impl LintStore { self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target)); } - pub fn register_builtin(&mut self, sess: Option<&Session>) { - macro_rules! add_builtin { - ($sess:ident, $($name:ident),*,) => ( - {$( - self.register_pass($sess, false, box builtin::$name as LintPassObject); - )*} - ) - } - - macro_rules! add_builtin_with_new { - ($sess:ident, $($name:ident),*,) => ( - {$( - self.register_pass($sess, false, box builtin::$name::new() as LintPassObject); - )*} - ) - } - - macro_rules! add_lint_group { - ($sess:ident, $name:expr, $($lint:ident),*) => ( - self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]); - ) - } - - add_builtin!(sess, - HardwiredLints, - WhileTrue, - UnusedCasts, - ImproperCTypes, - BoxPointers, - UnusedAttributes, - PathStatements, - UnusedResults, - NonCamelCaseTypes, - NonSnakeCase, - NonUpperCaseGlobals, - UnusedParens, - UnusedImportBraces, - NonShorthandFieldPatterns, - UnusedUnsafe, - UnsafeBlocks, - UnusedMut, - UnusedAllocation, - MissingCopyImplementations, - UnstableFeatures, - Stability, - UnconditionalRecursion, - InvalidNoMangleItems, - PluginAsLibrary, - ); - - add_builtin_with_new!(sess, - TypeLimits, - RawPointerDerive, - MissingDoc, - MissingDebugImplementations, - ); - - add_lint_group!(sess, "bad_style", - NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS); - - add_lint_group!(sess, "unused", - UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE, - UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE, - UNUSED_UNSAFE, PATH_STATEMENTS); - - // We have one lint pass defined in this module. - self.register_pass(sess, false, box GatherNodeLevels as LintPassObject); - - // Insert temporary renamings for a one-time deprecation - self.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); - - self.register_renamed("unknown_features", "unused_features"); - } - #[allow(unused_variables)] fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) -> Option @@ -276,7 +202,7 @@ impl LintStore { .collect::>(); } None => sess.err(&format!("unknown {} flag: {}", - level.as_str(), lint_name)[]), + level.as_str(), lint_name)), } } } @@ -286,7 +212,7 @@ impl LintStore { fn maybe_stage_features(&mut self, sess: &Session) { let lvl = match sess.opts.unstable_features { UnstableFeatures::Default => return, - UnstableFeatures::Disallow => Warn, + UnstableFeatures::Disallow => Forbid, UnstableFeatures::Cheat => Allow }; match self.by_name.get("unstable_features") { @@ -527,7 +453,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> { self.tcx.sess.span_err(span, &format!("{}({}) overruled by outer forbid({})", level.as_str(), lint_name, - lint_name)[]); + lint_name)); } else if now != level { let src = self.lints.get_level_source(lint_id).1; self.level_stack.push((lint_id, (now, src))); @@ -562,7 +488,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_item(&mut self, it: &ast::Item) { - self.with_lint_attrs(&it.attrs[], |cx| { + self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_item, it); cx.visit_ids(|v| v.visit_item(it)); visit::walk_item(cx, it); @@ -570,7 +496,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { - self.with_lint_attrs(&it.attrs[], |cx| { + self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_foreign_item, it); visit::walk_foreign_item(cx, it); }) @@ -593,28 +519,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v ast::FnDecl, body: &'v ast::Block, span: Span, id: ast::NodeId) { - match fk { - visit::FkMethod(_, _, m) => { - self.with_lint_attrs(&m.attrs[], |cx| { - run_lints!(cx, check_fn, fk, decl, body, span, id); - cx.visit_ids(|v| { - v.visit_fn(fk, decl, body, span, id); - }); - visit::walk_fn(cx, fk, decl, body, span); - }) - }, - _ => { - run_lints!(self, check_fn, fk, decl, body, span, id); - visit::walk_fn(self, fk, decl, body, span); - } - } - } - - fn visit_ty_method(&mut self, t: &ast::TypeMethod) { - self.with_lint_attrs(&t.attrs[], |cx| { - run_lints!(cx, check_ty_method, t); - visit::walk_ty_method(cx, t); - }) + run_lints!(self, check_fn, fk, decl, body, span, id); + visit::walk_fn(self, fk, decl, body, span); } fn visit_struct_def(&mut self, @@ -628,23 +534,23 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_struct_field(&mut self, s: &ast::StructField) { - self.with_lint_attrs(&s.node.attrs[], |cx| { + self.with_lint_attrs(&s.node.attrs, |cx| { run_lints!(cx, check_struct_field, s); visit::walk_struct_field(cx, s); }) } fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) { - self.with_lint_attrs(&v.node.attrs[], |cx| { + self.with_lint_attrs(&v.node.attrs, |cx| { run_lints!(cx, check_variant, v, g); visit::walk_variant(cx, v, g); run_lints!(cx, check_variant_post, v, g); }) } - // FIXME(#10894) should continue recursing fn visit_ty(&mut self, t: &ast::Ty) { run_lints!(self, check_ty, t); + visit::walk_ty(self, t); } fn visit_ident(&mut self, sp: Span, id: ast::Ident) { @@ -685,9 +591,20 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { visit::walk_generics(self, g); } - fn visit_trait_item(&mut self, m: &ast::TraitItem) { - run_lints!(self, check_trait_method, m); - visit::walk_trait_item(self, m); + fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + self.with_lint_attrs(&trait_item.attrs, |cx| { + run_lints!(cx, check_trait_item, trait_item); + cx.visit_ids(|v| v.visit_trait_item(trait_item)); + visit::walk_trait_item(cx, trait_item); + }); + } + + fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { + self.with_lint_attrs(&impl_item.attrs, |cx| { + run_lints!(cx, check_impl_item, impl_item); + cx.visit_ids(|v| v.visit_impl_item(impl_item)); + visit::walk_impl_item(cx, impl_item); + }); } fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option) { @@ -741,7 +658,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> { // nodes, so that the variant size difference check in trans can call // `raw_emit_lint`. -struct GatherNodeLevels; +pub struct GatherNodeLevels; impl LintPass for GatherNodeLevels { fn get_lints(&self) -> LintArray { @@ -779,7 +696,7 @@ pub fn check_crate(tcx: &ty::ctxt, let mut cx = Context::new(tcx, krate, exported_items); // Visit the whole crate. - cx.with_lint_attrs(&krate.attrs[], |cx| { + cx.with_lint_attrs(&krate.attrs, |cx| { cx.visit_id(ast::CRATE_NODE_ID); cx.visit_ids(|v| { v.visited_outermost = true; diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index bdcc10ebce..498b2ce518 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -37,10 +37,11 @@ use syntax::codemap::Span; use syntax::visit::FnKind; use syntax::ast; -pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs}; +pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs, + GatherNodeLevels}; /// Specification of a single lint. -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub struct Lint { /// A string identifier for the lint. /// @@ -142,8 +143,8 @@ pub trait LintPass { fn check_generics(&mut self, _: &Context, _: &ast::Generics) { } fn check_fn(&mut self, _: &Context, _: FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } - fn check_ty_method(&mut self, _: &Context, _: &ast::TypeMethod) { } - fn check_trait_method(&mut self, _: &Context, _: &ast::TraitItem) { } + fn check_trait_item(&mut self, _: &Context, _: &ast::TraitItem) { } + fn check_impl_item(&mut self, _: &Context, _: &ast::ImplItem) { } fn check_struct_def(&mut self, _: &Context, _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } fn check_struct_def_post(&mut self, _: &Context, @@ -185,14 +186,6 @@ impl PartialEq for LintId { impl Eq for LintId { } -#[cfg(stage0)] -impl hash::Hash for LintId { - fn hash(&self, state: &mut S) { - let ptr = self.lint as *const Lint; - ptr.hash(state); - } -} -#[cfg(not(stage0))] impl hash::Hash for LintId { fn hash(&self, state: &mut H) { let ptr = self.lint as *const Lint; diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 4930eddb35..cda0084768 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -14,85 +14,89 @@ pub use self::astencode_tag::*; use back::svh::Svh; -// EBML enum definitions and utils shared by the encoder and decoder +// RBML enum definitions and utils shared by the encoder and decoder +// +// 0x00..0x1f: reserved for RBML generic type tags +// 0x20..0xef: free for use, preferred for frequent tags +// 0xf0..0xff: internally used by RBML to encode 0x100..0xfff in two bytes +// 0x100..0xfff: free for use, preferred for infrequent tags -pub const tag_items: uint = 0x00; +pub const tag_items: usize = 0x100; // top-level only -pub const tag_paths_data_name: uint = 0x01; +pub const tag_paths_data_name: usize = 0x20; -pub const tag_def_id: uint = 0x02; +pub const tag_def_id: usize = 0x21; -pub const tag_items_data: uint = 0x03; +pub const tag_items_data: usize = 0x22; -pub const tag_items_data_item: uint = 0x04; +pub const tag_items_data_item: usize = 0x23; -pub const tag_items_data_item_family: uint = 0x05; +pub const tag_items_data_item_family: usize = 0x24; -pub const tag_items_data_item_type: uint = 0x07; +pub const tag_items_data_item_type: usize = 0x25; -pub const tag_items_data_item_symbol: uint = 0x08; +pub const tag_items_data_item_symbol: usize = 0x26; -pub const tag_items_data_item_variant: uint = 0x09; +pub const tag_items_data_item_variant: usize = 0x27; -pub const tag_items_data_parent_item: uint = 0x0a; +pub const tag_items_data_parent_item: usize = 0x28; -pub const tag_items_data_item_is_tuple_struct_ctor: uint = 0x0b; +pub const tag_items_data_item_is_tuple_struct_ctor: usize = 0x29; -pub const tag_index: uint = 0x0c; +pub const tag_index: usize = 0x2a; -pub const tag_index_buckets: uint = 0x0d; +pub const tag_index_buckets: usize = 0x2b; -pub const tag_index_buckets_bucket: uint = 0x0e; +pub const tag_index_buckets_bucket: usize = 0x2c; -pub const tag_index_buckets_bucket_elt: uint = 0x0f; +pub const tag_index_buckets_bucket_elt: usize = 0x2d; -pub const tag_index_table: uint = 0x10; +pub const tag_index_table: usize = 0x2e; -pub const tag_meta_item_name_value: uint = 0x11; +pub const tag_meta_item_name_value: usize = 0x2f; -pub const tag_meta_item_name: uint = 0x12; +pub const tag_meta_item_name: usize = 0x30; -pub const tag_meta_item_value: uint = 0x13; +pub const tag_meta_item_value: usize = 0x31; -pub const tag_attributes: uint = 0x14; +pub const tag_attributes: usize = 0x101; // top-level only -pub const tag_attribute: uint = 0x15; +pub const tag_attribute: usize = 0x32; -pub const tag_meta_item_word: uint = 0x16; +pub const tag_meta_item_word: usize = 0x33; -pub const tag_meta_item_list: uint = 0x17; +pub const tag_meta_item_list: usize = 0x34; // The list of crates that this crate depends on -pub const tag_crate_deps: uint = 0x18; +pub const tag_crate_deps: usize = 0x102; // top-level only // A single crate dependency -pub const tag_crate_dep: uint = 0x19; +pub const tag_crate_dep: usize = 0x35; -pub const tag_crate_hash: uint = 0x1a; -pub const tag_crate_crate_name: uint = 0x1b; +pub const tag_crate_hash: usize = 0x103; // top-level only +pub const tag_crate_crate_name: usize = 0x104; // top-level only -pub const tag_crate_dep_crate_name: uint = 0x1d; -pub const tag_crate_dep_hash: uint = 0x1e; +pub const tag_crate_dep_crate_name: usize = 0x36; +pub const tag_crate_dep_hash: usize = 0x37; -pub const tag_mod_impl: uint = 0x1f; +pub const tag_mod_impl: usize = 0x38; -pub const tag_item_trait_item: uint = 0x20; +pub const tag_item_trait_item: usize = 0x39; -pub const tag_item_trait_ref: uint = 0x21; -pub const tag_item_super_trait_ref: uint = 0x22; +pub const tag_item_trait_ref: usize = 0x3a; // discriminator value for variants -pub const tag_disr_val: uint = 0x23; +pub const tag_disr_val: usize = 0x3c; // used to encode ast_map::PathElem -pub const tag_path: uint = 0x24; -pub const tag_path_len: uint = 0x25; -pub const tag_path_elem_mod: uint = 0x26; -pub const tag_path_elem_name: uint = 0x27; -pub const tag_item_field: uint = 0x28; -pub const tag_item_field_origin: uint = 0x29; - -pub const tag_item_variances: uint = 0x2a; +pub const tag_path: usize = 0x3d; +pub const tag_path_len: usize = 0x3e; +pub const tag_path_elem_mod: usize = 0x3f; +pub const tag_path_elem_name: usize = 0x40; +pub const tag_item_field: usize = 0x41; +pub const tag_item_field_origin: usize = 0x42; + +pub const tag_item_variances: usize = 0x43; /* trait items contain tag_item_trait_item elements, impl items contain tag_item_impl_item elements, and classes @@ -101,60 +105,59 @@ pub const tag_item_variances: uint = 0x2a; both, tag_item_trait_item and tag_item_impl_item have to be two different tags. */ -pub const tag_item_impl_item: uint = 0x30; -pub const tag_item_trait_method_explicit_self: uint = 0x31; +pub const tag_item_impl_item: usize = 0x44; +pub const tag_item_trait_method_explicit_self: usize = 0x45; // Reexports are found within module tags. Each reexport contains def_ids // and names. -pub const tag_items_data_item_reexport: uint = 0x38; -pub const tag_items_data_item_reexport_def_id: uint = 0x39; -pub const tag_items_data_item_reexport_name: uint = 0x3a; +pub const tag_items_data_item_reexport: usize = 0x46; +pub const tag_items_data_item_reexport_def_id: usize = 0x47; +pub const tag_items_data_item_reexport_name: usize = 0x48; // used to encode crate_ctxt side tables -#[derive(Copy, PartialEq, FromPrimitive)] -#[repr(uint)] -pub enum astencode_tag { // Reserves 0x40 -- 0x5f - tag_ast = 0x40, - - tag_tree = 0x41, - - tag_id_range = 0x42, - - tag_table = 0x43, - tag_table_id = 0x44, - tag_table_val = 0x45, - tag_table_def = 0x46, - tag_table_node_type = 0x47, - tag_table_item_subst = 0x48, - tag_table_freevars = 0x49, - tag_table_tcache = 0x4a, - tag_table_param_defs = 0x4b, - tag_table_mutbl = 0x4c, - tag_table_last_use = 0x4d, - tag_table_spill = 0x4e, - tag_table_method_map = 0x4f, - tag_table_vtable_map = 0x50, - tag_table_adjustments = 0x51, - tag_table_moves_map = 0x52, - tag_table_capture_map = 0x53, - tag_table_closure_tys = 0x54, - tag_table_closure_kinds = 0x55, - tag_table_upvar_capture_map = 0x56, - tag_table_capture_modes = 0x57, - tag_table_object_cast_map = 0x58, - tag_table_const_qualif = 0x59, +#[derive(Copy, Clone, PartialEq, FromPrimitive)] +#[repr(usize)] +pub enum astencode_tag { // Reserves 0x50 -- 0x6f + tag_ast = 0x50, + + tag_tree = 0x51, + + tag_id_range = 0x52, + + tag_table = 0x53, + // GAP 0x54, 0x55 + tag_table_def = 0x56, + tag_table_node_type = 0x57, + tag_table_item_subst = 0x58, + tag_table_freevars = 0x59, + tag_table_tcache = 0x5a, + tag_table_param_defs = 0x5b, + tag_table_mutbl = 0x5c, + tag_table_last_use = 0x5d, + tag_table_spill = 0x5e, + tag_table_method_map = 0x5f, + tag_table_vtable_map = 0x60, + tag_table_adjustments = 0x61, + tag_table_moves_map = 0x62, + tag_table_capture_map = 0x63, + tag_table_closure_tys = 0x64, + tag_table_closure_kinds = 0x65, + tag_table_upvar_capture_map = 0x66, + tag_table_capture_modes = 0x67, + tag_table_object_cast_map = 0x68, + tag_table_const_qualif = 0x69, } -pub const tag_item_trait_item_sort: uint = 0x60; +pub const tag_item_trait_item_sort: usize = 0x70; -pub const tag_item_trait_parent_sort: uint = 0x61; +pub const tag_item_trait_parent_sort: usize = 0x71; -pub const tag_item_impl_type_basename: uint = 0x62; +pub const tag_item_impl_type_basename: usize = 0x72; -pub const tag_crate_triple: uint = 0x66; +pub const tag_crate_triple: usize = 0x105; // top-level only -pub const tag_dylib_dependency_formats: uint = 0x67; +pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only // Language items are a top-level directory (for speed). Hierarchy: // @@ -163,51 +166,47 @@ pub const tag_dylib_dependency_formats: uint = 0x67; // - tag_lang_items_item_id: u32 // - tag_lang_items_item_node_id: u32 -pub const tag_lang_items: uint = 0x70; -pub const tag_lang_items_item: uint = 0x71; -pub const tag_lang_items_item_id: uint = 0x72; -pub const tag_lang_items_item_node_id: uint = 0x73; -pub const tag_lang_items_missing: uint = 0x74; - -pub const tag_item_unnamed_field: uint = 0x75; -pub const tag_items_data_item_visibility: uint = 0x76; +pub const tag_lang_items: usize = 0x107; // top-level only +pub const tag_lang_items_item: usize = 0x73; +pub const tag_lang_items_item_id: usize = 0x74; +pub const tag_lang_items_item_node_id: usize = 0x75; +pub const tag_lang_items_missing: usize = 0x76; -pub const tag_item_method_tps: uint = 0x79; -pub const tag_item_method_fty: uint = 0x7a; +pub const tag_item_unnamed_field: usize = 0x77; +pub const tag_items_data_item_visibility: usize = 0x78; -pub const tag_mod_child: uint = 0x7b; -pub const tag_misc_info: uint = 0x7c; -pub const tag_misc_info_crate_items: uint = 0x7d; +pub const tag_item_method_tps: usize = 0x79; +pub const tag_item_method_fty: usize = 0x7a; -pub const tag_item_method_provided_source: uint = 0x7e; -pub const tag_item_impl_vtables: uint = 0x7f; +pub const tag_mod_child: usize = 0x7b; +pub const tag_misc_info: usize = 0x108; // top-level only +pub const tag_misc_info_crate_items: usize = 0x7c; -pub const tag_impls: uint = 0x80; -pub const tag_impls_impl: uint = 0x81; +pub const tag_item_method_provided_source: usize = 0x7d; +pub const tag_item_impl_vtables: usize = 0x7e; -pub const tag_items_data_item_inherent_impl: uint = 0x82; -pub const tag_items_data_item_extension_impl: uint = 0x83; +pub const tag_impls: usize = 0x109; // top-level only +pub const tag_impls_impl: usize = 0x7f; -// GAP 0x84, 0x85, 0x86 +pub const tag_items_data_item_inherent_impl: usize = 0x80; +pub const tag_items_data_item_extension_impl: usize = 0x81; -pub const tag_native_libraries: uint = 0x87; -pub const tag_native_libraries_lib: uint = 0x88; -pub const tag_native_libraries_name: uint = 0x89; -pub const tag_native_libraries_kind: uint = 0x8a; +pub const tag_native_libraries: usize = 0x10a; // top-level only +pub const tag_native_libraries_lib: usize = 0x82; +pub const tag_native_libraries_name: usize = 0x83; +pub const tag_native_libraries_kind: usize = 0x84; -pub const tag_plugin_registrar_fn: uint = 0x8b; +pub const tag_plugin_registrar_fn: usize = 0x10b; // top-level only -// GAP 0x8c, 0x8d +pub const tag_method_argument_names: usize = 0x85; +pub const tag_method_argument_name: usize = 0x86; -pub const tag_method_argument_names: uint = 0x8e; -pub const tag_method_argument_name: uint = 0x8f; +pub const tag_reachable_extern_fns: usize = 0x10c; // top-level only +pub const tag_reachable_extern_fn_id: usize = 0x87; -pub const tag_reachable_extern_fns: uint = 0x90; -pub const tag_reachable_extern_fn_id: uint = 0x91; +pub const tag_items_data_item_stability: usize = 0x88; -pub const tag_items_data_item_stability: uint = 0x92; - -pub const tag_items_data_item_repr: uint = 0x93; +pub const tag_items_data_item_repr: usize = 0x89; #[derive(Clone, Debug)] pub struct LinkMeta { @@ -215,42 +214,45 @@ pub struct LinkMeta { pub crate_hash: Svh, } -// GAP 0x94...0x98 +pub const tag_struct_fields: usize = 0x10d; // top-level only +pub const tag_struct_field: usize = 0x8a; +pub const tag_struct_field_id: usize = 0x8b; + +pub const tag_attribute_is_sugared_doc: usize = 0x8c; -pub const tag_struct_fields: uint = 0x99; -pub const tag_struct_field: uint = 0x9a; -pub const tag_struct_field_id: uint = 0x9b; +pub const tag_items_data_region: usize = 0x8e; -pub const tag_attribute_is_sugared_doc: uint = 0x9c; +pub const tag_region_param_def: usize = 0x8f; +pub const tag_region_param_def_ident: usize = 0x90; +pub const tag_region_param_def_def_id: usize = 0x91; +pub const tag_region_param_def_space: usize = 0x92; +pub const tag_region_param_def_index: usize = 0x93; -pub const tag_trait_def_bounds: uint = 0x9d; +pub const tag_type_param_def: usize = 0x94; -pub const tag_items_data_region: uint = 0x9e; +pub const tag_item_generics: usize = 0x95; +pub const tag_method_ty_generics: usize = 0x96; -pub const tag_region_param_def: uint = 0xa0; -pub const tag_region_param_def_ident: uint = 0xa1; -pub const tag_region_param_def_def_id: uint = 0xa2; -pub const tag_region_param_def_space: uint = 0xa3; -pub const tag_region_param_def_index: uint = 0xa4; +pub const tag_predicate: usize = 0x97; +pub const tag_predicate_space: usize = 0x98; +pub const tag_predicate_data: usize = 0x99; -pub const tag_type_param_def: uint = 0xa5; +pub const tag_unsafety: usize = 0x9a; -pub const tag_item_generics: uint = 0xa6; -pub const tag_method_ty_generics: uint = 0xa7; +pub const tag_associated_type_names: usize = 0x9b; +pub const tag_associated_type_name: usize = 0x9c; -pub const tag_predicate: uint = 0xa8; -pub const tag_predicate_space: uint = 0xa9; -pub const tag_predicate_data: uint = 0xb0; +pub const tag_polarity: usize = 0x9d; -pub const tag_unsafety: uint = 0xb1; +pub const tag_macro_defs: usize = 0x10e; // top-level only +pub const tag_macro_def: usize = 0x9e; +pub const tag_macro_def_body: usize = 0x9f; -pub const tag_associated_type_names: uint = 0xb2; -pub const tag_associated_type_name: uint = 0xb3; +pub const tag_paren_sugar: usize = 0xa0; -pub const tag_polarity: uint = 0xb4; +pub const tag_codemap: usize = 0xa1; +pub const tag_codemap_filemap: usize = 0xa2; -pub const tag_macro_defs: uint = 0xb5; -pub const tag_macro_def: uint = 0xb6; -pub const tag_macro_def_body: uint = 0xb7; +pub const tag_item_super_predicates: usize = 0xa3; -pub const tag_paren_sugar: uint = 0xb8; +pub const tag_defaulted_trait: usize = 0xa4; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index d48a404176..b6a8525675 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -21,12 +21,13 @@ use metadata::decoder; use metadata::loader; use metadata::loader::CratePaths; +use std::path::{Path, PathBuf}; use std::rc::Rc; use syntax::ast; use syntax::abi; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::codemap::{Span, mk_sp}; +use syntax::codemap::{self, Span, mk_sp, Pos}; use syntax::parse; use syntax::parse::token::InternedString; use syntax::parse::token; @@ -61,7 +62,7 @@ fn dump_crates(cstore: &CStore) { } fn should_link(i: &ast::Item) -> bool { - !attr::contains_name(&i.attrs[], "no_link") + !attr::contains_name(&i.attrs, "no_link") } struct CrateInfo { @@ -72,7 +73,7 @@ struct CrateInfo { } pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { - let err = |s: &str| { + let say = |s: &str| { match (sp, sess) { (_, None) => panic!("{}", s), (Some(sp), Some(sess)) => sess.span_err(sp, s), @@ -80,12 +81,12 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { } }; if s.len() == 0 { - err("crate name must not be empty"); + say("crate name must not be empty"); } for c in s.chars() { if c.is_alphanumeric() { continue } - if c == '_' || c == '-' { continue } - err(&format!("invalid character `{}` in crate name: `{}`", c, s)[]); + if c == '_' { continue } + say(&format!("invalid character `{}` in crate name: `{}`", c, s)); } match sess { Some(sess) => sess.abort_if_errors(), @@ -124,7 +125,7 @@ fn register_native_lib(sess: &Session, // Extra info about a crate loaded for plugins or exported macros. struct ExtensionCrate { metadata: PMDSource, - dylib: Option, + dylib: Option, target_only: bool, } @@ -150,8 +151,9 @@ impl<'a> CrateReader<'a> { } } - // Traverses an AST, reading all the information about use'd crates and extern - // libraries necessary for later resolving, typechecking, linking, etc. + // Traverses an AST, reading all the information about use'd crates and + // extern libraries necessary for later resolving, typechecking, linking, + // etc. pub fn read_crates(&mut self, krate: &ast::Crate) { self.process_crate(krate); visit::walk_crate(self, krate); @@ -181,11 +183,10 @@ impl<'a> CrateReader<'a> { debug!("resolving extern crate stmt. ident: {} path_opt: {:?}", ident, path_opt); let name = match *path_opt { - Some((ref path_str, _)) => { - let name = path_str.to_string(); - validate_crate_name(Some(self.sess), &name[..], + Some(name) => { + validate_crate_name(Some(self.sess), name.as_str(), Some(i.span)); - name + name.as_str().to_string() } None => ident.to_string(), }; @@ -210,8 +211,8 @@ impl<'a> CrateReader<'a> { match self.extract_crate_info(i) { Some(info) => { let (cnum, _, _) = self.resolve_crate(&None, - &info.ident[], - &info.name[], + &info.ident, + &info.name, None, i.span, PathKind::Crate); @@ -268,7 +269,7 @@ impl<'a> CrateReader<'a> { } else { self.sess.span_err(m.span, &format!("unknown kind: `{}`", - k)[]); + k)); cstore::NativeUnknown } } @@ -371,15 +372,17 @@ impl<'a> CrateReader<'a> { // Maintain a reference to the top most crate. let root = if root.is_some() { root } else { &crate_paths }; - let cnum_map = self.resolve_crate_deps(root, lib.metadata.as_slice(), span); + let loader::Library { dylib, rlib, metadata } = lib; - let loader::Library{ dylib, rlib, metadata } = lib; + let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), span); + let codemap_import_info = import_codemap(self.sess.codemap(), &metadata); let cmeta = Rc::new( cstore::crate_metadata { name: name.to_string(), data: metadata, cnum_map: cnum_map, cnum: cnum, + codemap_import_info: codemap_import_info, span: span, }); @@ -413,7 +416,7 @@ impl<'a> CrateReader<'a> { hash: hash.map(|a| &*a), filesearch: self.sess.target_filesearch(kind), target: &self.sess.target.target, - triple: &self.sess.opts.target_triple[], + triple: &self.sess.opts.target_triple, root: root, rejected_via_hash: vec!(), rejected_via_triple: vec!(), @@ -440,8 +443,8 @@ impl<'a> CrateReader<'a> { decoder::get_crate_deps(cdata).iter().map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); let (local_cnum, _, _) = self.resolve_crate(root, - &dep.name[], - &dep.name[], + &dep.name, + &dep.name, Some(&dep.hash), span, PathKind::Dependency); @@ -450,7 +453,7 @@ impl<'a> CrateReader<'a> { } fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate { - let target_triple = &self.sess.opts.target_triple[]; + let target_triple = &self.sess.opts.target_triple[..]; let is_cross = target_triple != config::host_triple(); let mut should_link = info.should_link && !is_cross; let mut target_only = false; @@ -488,13 +491,13 @@ impl<'a> CrateReader<'a> { }; let dylib = library.dylib.clone(); - let register = should_link && self.existing_match(info.name.as_slice(), + let register = should_link && self.existing_match(&info.name, None, PathKind::Crate).is_none(); let metadata = if register { // Register crate now to avoid double-reading metadata - let (_, cmd, _) = self.register_crate(&None, &info.ident[], - &info.name[], span, library); + let (_, cmd, _) = self.register_crate(&None, &info.ident, + &info.name, span, library); PMDSource::Registered(cmd) } else { // Not registering the crate; just hold on to the metadata @@ -537,6 +540,7 @@ impl<'a> CrateReader<'a> { // overridden in plugin/load.rs export: false, use_locally: false, + allow_internal_unstable: false, body: body, }); @@ -547,7 +551,8 @@ impl<'a> CrateReader<'a> { } /// Look for a plugin registrar. Returns library path and symbol name. - pub fn find_plugin_registrar(&mut self, span: Span, name: &str) -> Option<(Path, String)> { + pub fn find_plugin_registrar(&mut self, span: Span, name: &str) + -> Option<(PathBuf, String)> { let ekrate = self.read_extension_crate(span, &CrateInfo { name: name.to_string(), ident: name.to_string(), @@ -570,7 +575,7 @@ impl<'a> CrateReader<'a> { .map(|id| decoder::get_symbol(ekrate.metadata.as_slice(), id)); match (ekrate.dylib.as_ref(), registrar) { - (Some(dylib), Some(reg)) => Some((dylib.clone(), reg)), + (Some(dylib), Some(reg)) => Some((dylib.to_path_buf(), reg)), (None, Some(_)) => { let message = format!("plugin `{}` only found in rlib format, \ but must be available in dylib format", @@ -584,3 +589,131 @@ impl<'a> CrateReader<'a> { } } } + +/// Imports the codemap from an external crate into the codemap of the crate +/// currently being compiled (the "local crate"). +/// +/// The import algorithm works analogous to how AST items are inlined from an +/// external crate's metadata: +/// For every FileMap in the external codemap an 'inline' copy is created in the +/// local codemap. The correspondence relation between external and local +/// FileMaps is recorded in the `ImportedFileMap` objects returned from this +/// function. When an item from an external crate is later inlined into this +/// crate, this correspondence information is used to translate the span +/// information of the inlined item so that it refers the correct positions in +/// the local codemap (see `astencode::DecodeContext::tr_span()`). +/// +/// The import algorithm in the function below will reuse FileMaps already +/// existing in the local codemap. For example, even if the FileMap of some +/// source file of libstd gets imported many times, there will only ever be +/// one FileMap object for the corresponding file in the local codemap. +/// +/// Note that imported FileMaps do not actually contain the source code of the +/// file they represent, just information about length, line breaks, and +/// multibyte characters. This information is enough to generate valid debuginfo +/// for items inlined from other crates. +fn import_codemap(local_codemap: &codemap::CodeMap, + metadata: &MetadataBlob) + -> Vec { + let external_codemap = decoder::get_imported_filemaps(metadata.as_slice()); + + let imported_filemaps = external_codemap.into_iter().map(|filemap_to_import| { + // Try to find an existing FileMap that can be reused for the filemap to + // be imported. A FileMap is reusable if it is exactly the same, just + // positioned at a different offset within the codemap. + let reusable_filemap = { + local_codemap.files + .borrow() + .iter() + .find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import)) + .map(|rc| rc.clone()) + }; + + match reusable_filemap { + Some(fm) => { + cstore::ImportedFileMap { + original_start_pos: filemap_to_import.start_pos, + original_end_pos: filemap_to_import.end_pos, + translated_filemap: fm + } + } + None => { + // We can't reuse an existing FileMap, so allocate a new one + // containing the information we need. + let codemap::FileMap { + name, + start_pos, + end_pos, + lines, + multibyte_chars, + .. + } = filemap_to_import; + + let source_length = (end_pos - start_pos).to_usize(); + + // Translate line-start positions and multibyte character + // position into frame of reference local to file. + // `CodeMap::new_imported_filemap()` will then translate those + // coordinates to their new global frame of reference when the + // offset of the FileMap is known. + let lines = lines.into_inner().map_in_place(|pos| pos - start_pos); + let multibyte_chars = multibyte_chars + .into_inner() + .map_in_place(|mbc| + codemap::MultiByteChar { + pos: mbc.pos + start_pos, + bytes: mbc.bytes + }); + + let local_version = local_codemap.new_imported_filemap(name, + source_length, + lines, + multibyte_chars); + cstore::ImportedFileMap { + original_start_pos: start_pos, + original_end_pos: end_pos, + translated_filemap: local_version + } + } + } + }).collect(); + + return imported_filemaps; + + fn are_equal_modulo_startpos(fm1: &codemap::FileMap, + fm2: &codemap::FileMap) + -> bool { + if fm1.name != fm2.name { + return false; + } + + let lines1 = fm1.lines.borrow(); + let lines2 = fm2.lines.borrow(); + + if lines1.len() != lines2.len() { + return false; + } + + for (&line1, &line2) in lines1.iter().zip(lines2.iter()) { + if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) { + return false; + } + } + + let multibytes1 = fm1.multibyte_chars.borrow(); + let multibytes2 = fm2.multibyte_chars.borrow(); + + if multibytes1.len() != multibytes2.len() { + return false; + } + + for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) { + if (mb1.bytes != mb2.bytes) || + ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) { + return false; + } + } + + true + } +} diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 7eeb058911..d528e38d34 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -29,7 +29,7 @@ use syntax::parse::token; use std::collections::hash_map::HashMap; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct MethodInfo { pub name: ast::Name, pub def_id: ast::DefId, @@ -46,7 +46,7 @@ pub fn each_lang_item(cstore: &cstore::CStore, cnum: ast::CrateNum, f: F) -> bool where - F: FnMut(ast::NodeId, uint) -> bool, + F: FnMut(ast::NodeId, usize) -> bool, { let crate_data = cstore.get_crate_data(cnum); decoder::each_lang_item(&*crate_data, f) @@ -92,7 +92,7 @@ pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec // FIXME #1920: This path is not always correct if the crate is not linked // into the root namespace. - let mut r = vec![ast_map::PathMod(token::intern(&cdata.name[]))]; + let mut r = vec![ast_map::PathMod(token::intern(&cdata.name))]; r.push_all(&path); r } @@ -150,12 +150,9 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name { def.node) } -pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId) - -> (ast::Name, def::TraitItemKind) { +pub fn is_static_method(cstore: &cstore::CStore, def: ast::DefId) -> bool { let cdata = cstore.get_crate_data(def.krate); - decoder::get_trait_item_name_and_kind(cstore.intr.clone(), - &*cdata, - def.node) + decoder::is_static_method(&*cdata, def.node) } pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId) @@ -178,14 +175,6 @@ pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>, decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.node, tcx) } -pub fn get_supertraits<'tcx>(tcx: &ty::ctxt<'tcx>, - def: ast::DefId) - -> Vec>> { - let cstore = &tcx.sess.cstore; - let cdata = cstore.get_crate_data(def.krate); - decoder::get_supertraits(&*cdata, def.node, tcx) -} - pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: ast::DefId) -> Option { let cdata = cstore.get_crate_data(def.krate); @@ -241,6 +230,14 @@ pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) decoder::get_predicates(&*cdata, def.node, tcx) } +pub fn get_super_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) + -> ty::GenericPredicates<'tcx> +{ + let cstore = &tcx.sess.cstore; + let cdata = cstore.get_crate_data(def.krate); + decoder::get_super_predicates(&*cdata, def.node, tcx) +} + pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId, def: ast::DefId) -> ty::TypeScheme<'tcx> { let cstore = &tcx.sess.cstore; @@ -391,7 +388,7 @@ pub fn is_staged_api(cstore: &cstore::CStore, def: ast::DefId) -> bool { let cdata = cstore.get_crate_data(def.krate); let attrs = decoder::get_crate_attributes(cdata.data()); for attr in &attrs { - if &attr.name()[] == "staged_api" { + if &attr.name()[..] == "staged_api" { match attr.node.value.node { ast::MetaWord(_) => return true, _ => (/*pass*/) } } } @@ -410,3 +407,12 @@ pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool { decoder::is_associated_type(&*cdata, def.node) } +pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) -> bool { + let cdata = cstore.get_crate_data(trait_def_id.krate); + decoder::is_defaulted_trait(&*cdata, trait_def_id.node) +} + +pub fn is_default_impl(cstore: &cstore::CStore, impl_did: ast::DefId) -> bool { + let cdata = cstore.get_crate_data(impl_did.krate); + decoder::is_default_impl(&*cdata, impl_did.node) +} diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index a3f7d57da6..811aa21a0b 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -25,9 +25,10 @@ use util::nodemap::{FnvHashMap, NodeMap}; use std::cell::RefCell; use std::rc::Rc; +use std::path::PathBuf; use flate::Bytes; use syntax::ast; -use syntax::codemap::Span; +use syntax::codemap; use syntax::parse::token::IdentInterner; // A map from external crate numbers (as decoded from some crate file) to @@ -41,12 +42,24 @@ pub enum MetadataBlob { MetadataArchive(loader::ArchiveMetadata), } +/// Holds information about a codemap::FileMap imported from another crate. +/// See creader::import_codemap() for more information. +pub struct ImportedFileMap { + /// This FileMap's byte-offset within the codemap of its original crate + pub original_start_pos: codemap::BytePos, + /// The end of this FileMap within the codemap of its original crate + pub original_end_pos: codemap::BytePos, + /// The imported FileMap's representation within the local codemap + pub translated_filemap: Rc +} + pub struct crate_metadata { pub name: String, pub data: MetadataBlob, pub cnum_map: cnum_map, pub cnum: ast::CrateNum, - pub span: Span, + pub codemap_import_info: Vec, + pub span: codemap::Span, } #[derive(Copy, Debug, PartialEq, Clone)] @@ -66,8 +79,8 @@ pub enum NativeLibraryKind { // must be non-None. #[derive(PartialEq, Clone)] pub struct CrateSource { - pub dylib: Option<(Path, PathKind)>, - pub rlib: Option<(Path, PathKind)>, + pub dylib: Option<(PathBuf, PathKind)>, + pub rlib: Option<(PathBuf, PathKind)>, pub cnum: ast::CrateNum, } @@ -98,7 +111,7 @@ impl CStore { } pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc { - (*self.metas.borrow())[cnum].clone() + self.metas.borrow().get(&cnum).unwrap().clone() } pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh { @@ -160,7 +173,7 @@ impl CStore { // topological sort of all crates putting the leaves at the right-most // positions. pub fn get_used_crates(&self, prefer: LinkagePreference) - -> Vec<(ast::CrateNum, Option)> { + -> Vec<(ast::CrateNum, Option)> { let mut ordering = Vec::new(); fn visit(cstore: &CStore, cnum: ast::CrateNum, ordering: &mut Vec) { @@ -230,7 +243,7 @@ impl crate_metadata { impl MetadataBlob { pub fn as_slice<'a>(&'a self) -> &'a [u8] { let slice = match *self { - MetadataVec(ref vec) => vec.as_slice(), + MetadataVec(ref vec) => &vec[..], MetadataArchive(ref ar) => ar.as_slice(), }; if slice.len() < 4 { @@ -239,7 +252,7 @@ impl MetadataBlob { let len = (((slice[0] as u32) << 24) | ((slice[1] as u32) << 16) | ((slice[2] as u32) << 8) | - ((slice[3] as u32) << 0)) as uint; + ((slice[3] as u32) << 0)) as usize; if len + 4 <= slice.len() { &slice[4.. len + 4] } else { diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index e5576de6e8..92810b407f 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -22,9 +22,8 @@ use metadata::csearch::MethodInfo; use metadata::csearch; use metadata::cstore; use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id, - parse_type_param_def_data, parse_bounds_data, - parse_bare_fn_ty_data, parse_trait_ref_data, - parse_predicate_data}; + parse_type_param_def_data, parse_bare_fn_ty_data, + parse_trait_ref_data, parse_predicate_data}; use middle::def; use middle::lang_items; use middle::subst; @@ -34,10 +33,11 @@ use middle::astencode::vtable_decoder_helpers; use std::collections::HashMap; use std::hash::{self, Hash, SipHasher}; -use std::old_io::extensions::u64_from_be_bytes; -use std::old_io; +use std::io::prelude::*; +use std::io; use std::num::FromPrimitive; use std::rc::Rc; +use std::slice::bytes; use std::str; use rbml::reader; @@ -60,20 +60,26 @@ pub type Cmd<'a> = &'a crate_metadata; // what crate that's in and give us a def_id that makes sense for the current // build. +fn u32_from_be_bytes(bytes: &[u8]) -> u32 { + let mut b = [0; 4]; + bytes::copy_memory(&bytes[..4], &mut b); + unsafe { (*(b.as_ptr() as *const u32)).to_be() } +} + fn lookup_hash<'a, F>(d: rbml::Doc<'a>, mut eq_fn: F, hash: u64) -> Option> where F: FnMut(&[u8]) -> bool, { let index = reader::get_doc(d, tag_index); let table = reader::get_doc(index, tag_index_table); - let hash_pos = table.start + (hash % 256 * 4) as uint; - let pos = u64_from_be_bytes(d.data, hash_pos, 4) as uint; + let hash_pos = table.start + (hash % 256 * 4) as usize; + let pos = u32_from_be_bytes(&d.data[hash_pos..]) as usize; let tagged_doc = reader::doc_at(d.data, pos).unwrap(); let belt = tag_index_buckets_bucket_elt; let mut ret = None; reader::tagged_docs(tagged_doc.doc, belt, |elt| { - let pos = u64_from_be_bytes(elt.data, elt.start, 4) as uint; + let pos = u32_from_be_bytes(&elt.data[elt.start..]) as usize; if eq_fn(&elt.data[elt.start + 4 .. elt.end]) { ret = Some(reader::doc_at(d.data, pos).unwrap().doc); false @@ -87,9 +93,7 @@ fn lookup_hash<'a, F>(d: rbml::Doc<'a>, mut eq_fn: F, hash: u64) -> Option(item_id: ast::NodeId, items: rbml::Doc<'a>) -> Option> { fn eq_item(bytes: &[u8], item_id: ast::NodeId) -> bool { - return u64_from_be_bytes( - &bytes[0..4], 0, 4) as ast::NodeId - == item_id; + u32_from_be_bytes(bytes) == item_id } lookup_hash(items, |a| eq_item(a, item_id), @@ -119,13 +123,13 @@ enum Family { StaticMethod, // F Method, // h Type, // y - ForeignType, // T Mod, // m ForeignMod, // n Enum, // t TupleVariant, // v StructVariant, // V Impl, // i + DefaultImpl, // d Trait, // I Struct, // S PublicField, // g @@ -144,13 +148,13 @@ fn item_family(item: rbml::Doc) -> Family { 'F' => StaticMethod, 'h' => Method, 'y' => Type, - 'T' => ForeignType, 'm' => Mod, 'n' => ForeignMod, 't' => Enum, 'v' => TupleVariant, 'V' => StructVariant, 'i' => Impl, + 'd' => DefaultImpl, 'I' => Trait, 'S' => Struct, 'g' => PublicField, @@ -172,16 +176,13 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility { } } -fn item_sort(item: rbml::Doc) -> char { +fn item_sort(item: rbml::Doc) -> Option { let mut ret = None; reader::tagged_docs(item, tag_item_trait_item_sort, |doc| { ret = Some(doc.as_str_slice().as_bytes()[0] as char); false }); - match ret { - Some(r) => r, - None => panic!("No item_sort found") - } + ret } fn item_symbol(item: rbml::Doc) -> String { @@ -258,18 +259,6 @@ fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) doc_trait_ref(tp, tcx, cdata) } -fn doc_bounds<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) - -> ty::ParamBounds<'tcx> { - parse_bounds_data(doc.data, cdata.cnum, doc.start, tcx, - |_, did| translate_def_id(cdata, did)) -} - -fn trait_def_bounds<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) - -> ty::ParamBounds<'tcx> { - let d = reader::get_doc(doc, tag_trait_def_bounds); - doc_bounds(d, tcx, cdata) -} - fn enum_variant_ids(item: rbml::Doc, cdata: Cmd) -> Vec { let mut ids: Vec = Vec::new(); let v = tag_items_data_item_variant; @@ -285,7 +274,7 @@ fn item_path(item_doc: rbml::Doc) -> Vec { let path_doc = reader::get_doc(item_doc, tag_path); let len_doc = reader::get_doc(path_doc, tag_path_len); - let len = reader::doc_as_u32(len_doc) as uint; + let len = reader::doc_as_u32(len_doc) as usize; let mut result = Vec::with_capacity(len); reader::docs(path_doc, |tag, elt_doc| { @@ -337,14 +326,16 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) def::FromImpl(item_reqd_and_translated_parent_item(cnum, item)) }; - match fam { - // We don't bother to get encode/decode the trait id, we don't need it. - Method => DlDef(def::DefMethod(did, None, provenance)), - StaticMethod => DlDef(def::DefStaticMethod(did, provenance)), - _ => panic!() + DlDef(def::DefMethod(did, provenance)) + } + Type => { + if item_sort(item) == Some('t') { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + DlDef(def::DefAssociatedTy(trait_did, did)) + } else { + DlDef(def::DefTy(did, false)) } } - Type | ForeignType => DlDef(def::DefTy(did, false)), Mod => DlDef(def::DefMod(did)), ForeignMod => DlDef(def::DefForeignMod(did)), StructVariant => { @@ -357,7 +348,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) } Trait => DlDef(def::DefTrait(did)), Enum => DlDef(def::DefTy(did, true)), - Impl => DlImpl(did), + Impl | DefaultImpl => DlImpl(did), PublicField | InheritedField => DlField, } } @@ -402,7 +393,6 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, { let item_doc = lookup_item(item_id, cdata.data()); let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); - let bounds = trait_def_bounds(item_doc, tcx, cdata); let unsafety = parse_unsafety(item_doc); let associated_type_names = parse_associated_type_names(item_doc); let paren_sugar = parse_paren_sugar(item_doc); @@ -411,7 +401,6 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, paren_sugar: paren_sugar, unsafety: unsafety, generics: generics, - bounds: bounds, trait_ref: item_trait_ref(item_doc, tcx, cdata), associated_type_names: associated_type_names, } @@ -426,6 +415,15 @@ pub fn get_predicates<'tcx>(cdata: Cmd, doc_predicates(item_doc, tcx, cdata, tag_item_generics) } +pub fn get_super_predicates<'tcx>(cdata: Cmd, + item_id: ast::NodeId, + tcx: &ty::ctxt<'tcx>) + -> ty::GenericPredicates<'tcx> +{ + let item_doc = lookup_item(item_id, cdata.data()); + doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates) +} + pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>) -> ty::TypeScheme<'tcx> { @@ -480,7 +478,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd, let item_doc = lookup_item(id, cdata.data()); let fam = item_family(item_doc); match fam { - Family::Impl => { + Family::Impl | Family::DefaultImpl => { reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| { doc_trait_ref(tp, tcx, cdata) }) @@ -515,13 +513,13 @@ pub enum DefLike { /// Iterates over the language items in the given crate. pub fn each_lang_item(cdata: Cmd, mut f: F) -> bool where - F: FnMut(ast::NodeId, uint) -> bool, + F: FnMut(ast::NodeId, usize) -> bool, { let root = rbml::Doc::new(cdata.data()); let lang_items = reader::get_doc(root, tag_lang_items); reader::tagged_docs(lang_items, tag_lang_items_item, |item_doc| { let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id); - let id = reader::doc_as_u32(id_doc) as uint; + let id = reader::doc_as_u32(id_doc) as usize; let node_id_doc = reader::get_doc(item_doc, tag_lang_items_item_node_id); let node_id = reader::doc_as_u32(node_id_doc) as ast::NodeId; @@ -779,7 +777,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc, cdata: Cmd, id: ast::Nod _ => { /* empty */ } } let old_disr_val = disr_val; - disr_val += 1; + disr_val = disr_val.wrapping_add(1); Rc::new(ty::VariantInfo { args: arg_tys, arg_names: arg_names, @@ -829,8 +827,10 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId) tag_item_impl_item, |doc| { let def_id = item_def_id(doc, cdata); match item_sort(doc) { - 'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)), - 't' => impl_items.push(ty::TypeTraitItemId(def_id)), + Some('r') | Some('p') => { + impl_items.push(ty::MethodTraitItemId(def_id)) + } + Some('t') => impl_items.push(ty::TypeTraitItemId(def_id)), _ => panic!("unknown impl item sort"), } true @@ -847,22 +847,13 @@ pub fn get_trait_name(intr: Rc, item_name(&*intr, doc) } -pub fn get_trait_item_name_and_kind(intr: Rc, - cdata: Cmd, - id: ast::NodeId) - -> (ast::Name, def::TraitItemKind) { +pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool { let doc = lookup_item(id, cdata.data()); - let name = item_name(&*intr, doc); match item_sort(doc) { - 'r' | 'p' => { - let explicit_self = get_explicit_self(doc); - (name, def::TraitItemKind::from_explicit_self_category(explicit_self)) - } - 't' => (name, def::TypeTraitItemKind), - c => { - panic!("get_trait_item_name_and_kind(): unknown trait item kind \ - in metadata: `{}`", c) + Some('r') | Some('p') => { + get_explicit_self(doc) == ty::StaticExplicitSelfCategory } + _ => false } } @@ -887,7 +878,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, let vis = item_visibility(method_doc); match item_sort(method_doc) { - 'r' | 'p' => { + Some('r') | Some('p') => { let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics); let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics); let fty = doc_method_fty(method_doc, tcx, cdata); @@ -904,7 +895,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc, container, provided_source))) } - 't' => { + Some('t') => { ty::TypeTraitItem(Rc::new(ty::AssociatedType { name: name, vis: vis, @@ -924,8 +915,10 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId) reader::tagged_docs(item, tag_item_trait_item, |mth| { let def_id = item_def_id(mth, cdata); match item_sort(mth) { - 'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)), - 't' => result.push(ty::TypeTraitItemId(def_id)), + Some('r') | Some('p') => { + result.push(ty::MethodTraitItemId(def_id)); + } + Some('t') => result.push(ty::TypeTraitItemId(def_id)), _ => panic!("unknown trait item sort"), } true @@ -954,7 +947,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc, let did = item_def_id(mth_id, cdata); let mth = lookup_item(did.node, data); - if item_sort(mth) == 'p' { + if item_sort(mth) == Some('p') { let trait_item = get_impl_or_trait_item(intr.clone(), cdata, did.node, @@ -972,24 +965,6 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc, return result; } -/// Returns the supertraits of the given trait. -pub fn get_supertraits<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>) - -> Vec>> { - let mut results = Vec::new(); - let item_doc = lookup_item(id, cdata.data()); - reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| { - // NB. Only reads the ones that *aren't* builtin-bounds. See also - // get_trait_def() for collecting the builtin bounds. - // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place. - let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); - if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() { - results.push(trait_ref); - } - true - }); - return results; -} - pub fn get_type_name_if_impl(cdata: Cmd, node_id: ast::NodeId) -> Option { let item = lookup_item(node_id, cdata.data()); @@ -1192,7 +1167,7 @@ fn get_attributes(md: rbml::Doc) -> Vec { } fn list_crate_attributes(md: rbml::Doc, hash: &Svh, - out: &mut old_io::Writer) -> old_io::IoResult<()> { + out: &mut io::Write) -> io::Result<()> { try!(write!(out, "=Crate Attributes ({})=\n", *hash)); let r = get_attributes(md); @@ -1219,13 +1194,13 @@ pub fn get_crate_deps(data: &[u8]) -> Vec { let cratedoc = rbml::Doc::new(data); let depsdoc = reader::get_doc(cratedoc, tag_crate_deps); let mut crate_num = 1; - fn docstr(doc: rbml::Doc, tag_: uint) -> String { + fn docstr(doc: rbml::Doc, tag_: usize) -> String { let d = reader::get_doc(doc, tag_); d.as_str_slice().to_string() } reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| { let name = docstr(depdoc, tag_crate_dep_crate_name); - let hash = Svh::new(&docstr(depdoc, tag_crate_dep_hash)[]); + let hash = Svh::new(&docstr(depdoc, tag_crate_dep_hash)); deps.push(CrateDep { cnum: crate_num, name: name, @@ -1237,7 +1212,7 @@ pub fn get_crate_deps(data: &[u8]) -> Vec { return deps; } -fn list_crate_deps(data: &[u8], out: &mut old_io::Writer) -> old_io::IoResult<()> { +fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> { try!(write!(out, "=External Dependencies=\n")); for dep in &get_crate_deps(data) { try!(write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)); @@ -1276,7 +1251,7 @@ pub fn get_crate_name(data: &[u8]) -> String { maybe_get_crate_name(data).expect("no crate name in crate") } -pub fn list_crate_metadata(bytes: &[u8], out: &mut old_io::Writer) -> old_io::IoResult<()> { +pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> { let hash = get_crate_hash(bytes); let md = rbml::Doc::new(bytes); try!(list_crate_attributes(md, &hash, out)); @@ -1356,7 +1331,7 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) let parent_item_doc = lookup_item(parent_item_id.node, cdata.data()); match item_family(parent_item_doc) { Trait => Some(item_def_id(parent_item_doc, cdata)), - Impl => { + Impl | DefaultImpl => { reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref) .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id) } @@ -1479,7 +1454,7 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool { fn doc_generics<'tcx>(base_doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd, - tag: uint) + tag: usize) -> ty::Generics<'tcx> { let doc = reader::get_doc(base_doc, tag); @@ -1504,7 +1479,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc, let def_id = translate_def_id(cdata, def_id); let doc = reader::get_doc(rp_doc, tag_region_param_def_space); - let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as uint); + let space = subst::ParamSpace::from_uint(reader::doc_as_u64(doc) as usize); let doc = reader::get_doc(rp_doc, tag_region_param_def_index); let index = reader::doc_as_u64(doc) as u32; @@ -1533,7 +1508,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc, fn doc_predicates<'tcx>(base_doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd, - tag: uint) + tag: usize) -> ty::GenericPredicates<'tcx> { let doc = reader::get_doc(base_doc, tag); @@ -1541,7 +1516,7 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc, let mut predicates = subst::VecPerParamSpace::empty(); reader::tagged_docs(doc, tag_predicate, |predicate_doc| { let space_doc = reader::get_doc(predicate_doc, tag_predicate_space); - let space = subst::ParamSpace::from_uint(reader::doc_as_u8(space_doc) as uint); + let space = subst::ParamSpace::from_uint(reader::doc_as_u8(space_doc) as usize); let data_doc = reader::get_doc(predicate_doc, tag_predicate_data); let data = parse_predicate_data(data_doc.data, data_doc.start, cdata.cnum, tcx, @@ -1558,6 +1533,34 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool { let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items); match maybe_find_item(id, items) { None => false, - Some(item) => item_sort(item) == 't', + Some(item) => item_sort(item) == Some('t'), } } + +pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool { + let trait_doc = lookup_item(trait_id, cdata.data()); + assert!(item_family(trait_doc) == Family::Trait); + let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait); + reader::doc_as_u8(defaulted_doc) != 0 +} + +pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool { + let impl_doc = lookup_item(impl_id, cdata.data()); + item_family(impl_doc) == Family::DefaultImpl +} + +pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { + let crate_doc = rbml::Doc::new(metadata); + let cm_doc = reader::get_doc(crate_doc, tag_codemap); + + let mut filemaps = vec![]; + + reader::tagged_docs(cm_doc, tag_codemap_filemap, |filemap_doc| { + let mut decoder = reader::Decoder::new(filemap_doc); + let filemap: codemap::FileMap = Decodable::decode(&mut decoder).unwrap(); + filemaps.push(filemap); + true + }); + + return filemaps; +} diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 42a70cec5d..862ced78c0 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -22,7 +22,7 @@ use metadata::cstore; use metadata::decoder; use metadata::tyencode; use middle::def; -use middle::ty::{lookup_item_type}; +use middle::ty::lookup_item_type; use middle::ty::{self, Ty}; use middle::stability; use util::nodemap::{FnvHashMap, NodeMap, NodeSet}; @@ -30,10 +30,11 @@ use util::nodemap::{FnvHashMap, NodeMap, NodeSet}; use serialize::Encodable; use std::cell::RefCell; use std::hash::{Hash, Hasher, SipHasher}; +use std::io::prelude::*; +use std::io::{Cursor, SeekFrom}; use syntax::abi; use syntax::ast::{self, DefId, NodeId}; -use syntax::ast_map::{PathElem, PathElems}; -use syntax::ast_map; +use syntax::ast_map::{self, LinkedPath, PathElem, PathElems}; use syntax::ast_util::*; use syntax::ast_util; use syntax::attr; @@ -46,8 +47,7 @@ use syntax::ptr::P; use syntax::visit::Visitor; use syntax::visit; use syntax; -use rbml::writer; -use rbml::io::SeekableMemWriter; +use rbml::writer::Encoder; /// A borrowed version of `ast::InlinedItem`. pub enum InlinedItemRef<'a> { @@ -57,8 +57,6 @@ pub enum InlinedItemRef<'a> { IIForeignRef(&'a ast::ForeignItem) } -pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>; - pub type EncodeInlinedItem<'a> = Box; @@ -94,7 +92,7 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) { } pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) { - rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id)[]); + rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id)); } #[derive(Clone)] @@ -106,7 +104,7 @@ struct entry { fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, trait_ref: &ty::TraitRef<'tcx>, - tag: uint) { + tag: usize) { let ty_str_ctxt = &tyencode::ctxt { diag: ecx.diag, ds: def_to_string, @@ -115,15 +113,13 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder, }; rbml_w.start_tag(tag); - tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref); + tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref); rbml_w.end_tag(); } // Item info table encoding fn encode_family(rbml_w: &mut Encoder, c: char) { - rbml_w.start_tag(tag_items_data_item_family); - rbml_w.writer.write_all(&[c as u8]); - rbml_w.end_tag(); + rbml_w.wr_tagged_u8(tag_items_data_item_family, c as u8); } pub fn def_to_string(did: DefId) -> String { @@ -157,14 +153,9 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder, } fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { - rbml_w.start_tag(tag_items_data_item_variant); let s = def_to_string(vid); - rbml_w.writer.write_all(s.as_bytes()); - rbml_w.end_tag(); - - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&s[..]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_items_data_item_variant, &s[..]); + rbml_w.wr_tagged_str(tag_mod_child, &s[..]); } pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, @@ -176,7 +167,7 @@ pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, tcx: ecx.tcx, abbrevs: &ecx.type_abbrevs }; - tyencode::enc_closure_ty(rbml_w.writer, ty_str_ctxt, closure_type); + tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type); } pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, @@ -188,7 +179,7 @@ pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, tcx: ecx.tcx, abbrevs: &ecx.type_abbrevs }; - tyencode::enc_ty(rbml_w.writer, ty_str_ctxt, typ); + tyencode::enc_ty(rbml_w, ty_str_ctxt, typ); } pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, @@ -200,7 +191,7 @@ pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, tcx: ecx.tcx, abbrevs: &ecx.type_abbrevs }; - tyencode::enc_trait_ref(rbml_w.writer, ty_str_ctxt, trait_ref); + tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref); } pub fn write_region(ecx: &EncodeContext, @@ -212,22 +203,7 @@ pub fn write_region(ecx: &EncodeContext, tcx: ecx.tcx, abbrevs: &ecx.type_abbrevs }; - tyencode::enc_region(rbml_w.writer, ty_str_ctxt, r); -} - -fn encode_bounds<'a, 'tcx>(rbml_w: &mut Encoder, - ecx: &EncodeContext<'a, 'tcx>, - bounds: &ty::ParamBounds<'tcx>, - tag: uint) { - rbml_w.start_tag(tag); - - let ty_str_ctxt = &tyencode::ctxt { diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs }; - tyencode::enc_bounds(rbml_w.writer, ty_str_ctxt, bounds); - - rbml_w.end_tag(); + tyencode::enc_region(rbml_w, ty_str_ctxt, r); } fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, @@ -257,7 +233,7 @@ fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, tcx: ecx.tcx, abbrevs: &ecx.type_abbrevs }; - tyencode::enc_bare_fn_ty(rbml_w.writer, ty_str_ctxt, typ); + tyencode::enc_bare_fn_ty(rbml_w, ty_str_ctxt, typ); rbml_w.end_tag(); } @@ -265,34 +241,26 @@ fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, fn encode_symbol(ecx: &EncodeContext, rbml_w: &mut Encoder, id: NodeId) { - rbml_w.start_tag(tag_items_data_item_symbol); match ecx.item_symbols.borrow().get(&id) { Some(x) => { debug!("encode_symbol(id={}, str={})", id, *x); - rbml_w.writer.write_all(x.as_bytes()); + rbml_w.wr_tagged_str(tag_items_data_item_symbol, x); } None => { ecx.diag.handler().bug( - &format!("encode_symbol: id not found {}", id)[]); + &format!("encode_symbol: id not found {}", id)); } } - rbml_w.end_tag(); } fn encode_disr_val(_: &EncodeContext, rbml_w: &mut Encoder, disr_val: ty::Disr) { - rbml_w.start_tag(tag_disr_val); - let s = disr_val.to_string(); - rbml_w.writer.write_all(s.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_disr_val, &disr_val.to_string()); } fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) { - rbml_w.start_tag(tag_items_data_parent_item); - let s = def_to_string(id); - rbml_w.writer.write_all(s.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_items_data_parent_item, &def_to_string(id)); } fn encode_struct_fields(rbml_w: &mut Encoder, @@ -307,10 +275,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder, } encode_struct_field_family(rbml_w, f.vis); encode_def_id(rbml_w, f.id); - rbml_w.start_tag(tag_item_field_origin); - let s = def_to_string(origin); - rbml_w.writer.write_all(s.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_item_field_origin, &def_to_string(origin)); rbml_w.end_tag(); } } @@ -330,7 +295,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, let def_id = local_def(variant.node.id); index.push(entry { val: variant.node.id as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); rbml_w.start_tag(tag_items_data_item); encode_def_id(rbml_w, def_id); @@ -341,8 +306,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext, encode_name(rbml_w, variant.node.name.name); encode_parent_item(rbml_w, local_def(id)); encode_visibility(rbml_w, variant.node.vis); - encode_attributes(rbml_w, &variant.node.attrs[]); - encode_repr_attrs(rbml_w, ecx, &variant.node.attrs[]); + encode_attributes(rbml_w, &variant.node.attrs); + encode_repr_attrs(rbml_w, ecx, &variant.node.attrs); let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id)); encode_stability(rbml_w, stab); @@ -367,7 +332,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path)); rbml_w.end_tag(); - disr_val += 1; + disr_val = disr_val.wrapping_add(1); i += 1; } } @@ -393,14 +358,11 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder, debug!("(encode reexported static method) {}::{}", exp.name, token::get_name(method_name)); rbml_w.start_tag(tag_items_data_item_reexport); - rbml_w.start_tag(tag_items_data_item_reexport_def_id); - rbml_w.wr_str(&def_to_string(method_def_id)[]); - rbml_w.end_tag(); - rbml_w.start_tag(tag_items_data_item_reexport_name); - rbml_w.wr_str(&format!("{}::{}", - exp.name, - token::get_name(method_name))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id, + &def_to_string(method_def_id)); + rbml_w.wr_tagged_str(tag_items_data_item_reexport_name, + &format!("{}::{}", exp.name, + token::get_name(method_name))); rbml_w.end_tag(); } @@ -412,7 +374,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext, match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) { Some(implementations) => { for base_impl_did in &**implementations { - for &method_did in &*(*impl_items)[*base_impl_did] { + for &method_did in impl_items.get(base_impl_did).unwrap() { let impl_item = ty::impl_or_trait_item( ecx.tcx, method_did.def_id()); @@ -536,12 +498,10 @@ fn encode_reexports(ecx: &EncodeContext, exp.def_id.node, id); rbml_w.start_tag(tag_items_data_item_reexport); - rbml_w.start_tag(tag_items_data_item_reexport_def_id); - rbml_w.wr_str(&def_to_string(exp.def_id)[]); - rbml_w.end_tag(); - rbml_w.start_tag(tag_items_data_item_reexport_name); - rbml_w.wr_str(exp.name.as_str()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_items_data_item_reexport_def_id, + &def_to_string(exp.def_id)); + rbml_w.wr_tagged_str(tag_items_data_item_reexport_name, + exp.name.as_str()); rbml_w.end_tag(); encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp); } @@ -569,15 +529,12 @@ fn encode_info_for_mod(ecx: &EncodeContext, // Encode info about all the module children. for item in &md.items { - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&def_to_string(local_def(item.id))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_child, + &def_to_string(local_def(item.id))); each_auxiliary_node_id(&**item, |auxiliary_node_id| { - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&def_to_string(local_def( - auxiliary_node_id))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_child, + &def_to_string(local_def(auxiliary_node_id))); true }); @@ -587,9 +544,8 @@ fn encode_info_for_mod(ecx: &EncodeContext, token::get_ident(ident), did, ecx.tcx.map.node_to_string(did)); - rbml_w.start_tag(tag_mod_impl); - rbml_w.wr_str(&def_to_string(local_def(did))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_impl, + &def_to_string(local_def(did))); } } @@ -618,67 +574,56 @@ fn encode_struct_field_family(rbml_w: &mut Encoder, } fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) { - rbml_w.start_tag(tag_items_data_item_visibility); let ch = match visibility { ast::Public => 'y', ast::Inherited => 'i', }; - rbml_w.wr_str(&ch.to_string()[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8); } fn encode_explicit_self(rbml_w: &mut Encoder, explicit_self: &ty::ExplicitSelfCategory) { - rbml_w.start_tag(tag_item_trait_method_explicit_self); + let tag = tag_item_trait_method_explicit_self; // Encode the base self type. match *explicit_self { ty::StaticExplicitSelfCategory => { - rbml_w.writer.write_all(&[ 's' as u8 ]); + rbml_w.wr_tagged_bytes(tag, &['s' as u8]); } ty::ByValueExplicitSelfCategory => { - rbml_w.writer.write_all(&[ 'v' as u8 ]); + rbml_w.wr_tagged_bytes(tag, &['v' as u8]); } ty::ByBoxExplicitSelfCategory => { - rbml_w.writer.write_all(&[ '~' as u8 ]); + rbml_w.wr_tagged_bytes(tag, &['~' as u8]); } ty::ByReferenceExplicitSelfCategory(_, m) => { // FIXME(#4846) encode custom lifetime - rbml_w.writer.write_all(&['&' as u8]); - encode_mutability(rbml_w, m); + let ch = encode_mutability(m); + rbml_w.wr_tagged_bytes(tag, &['&' as u8, ch]); } } - rbml_w.end_tag(); - - fn encode_mutability(rbml_w: &mut Encoder, - m: ast::Mutability) { + fn encode_mutability(m: ast::Mutability) -> u8 { match m { - ast::MutImmutable => { rbml_w.writer.write_all(&[ 'i' as u8 ]); } - ast::MutMutable => { rbml_w.writer.write_all(&[ 'm' as u8 ]); } + ast::MutImmutable => 'i' as u8, + ast::MutMutable => 'm' as u8, } } } fn encode_item_sort(rbml_w: &mut Encoder, sort: char) { - rbml_w.start_tag(tag_item_trait_item_sort); - rbml_w.writer.write_all(&[ sort as u8 ]); - rbml_w.end_tag(); + rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8); } fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) { - rbml_w.start_tag(tag_item_trait_parent_sort); - rbml_w.writer.write_all(&[ sort as u8 ]); - rbml_w.end_tag(); + rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8); } fn encode_provided_source(rbml_w: &mut Encoder, source_opt: Option) { if let Some(source) = source_opt { - rbml_w.start_tag(tag_item_method_provided_source); - let s = def_to_string(source); - rbml_w.writer.write_all(s.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_item_method_provided_source, + &def_to_string(source)); } } @@ -697,10 +642,11 @@ fn encode_info_for_struct(ecx: &EncodeContext, let nm = field.name; let id = field.id.node; - index.push(entry {val: id as i64, pos: rbml_w.writer.tell().unwrap()}); + let pos = rbml_w.mark_stable_position(); + index.push(entry {val: id as i64, pos: pos}); global_index.push(entry { val: id as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: pos, }); rbml_w.start_tag(tag_items_data_item); debug!("encode_info_for_struct: doing {} {}", @@ -726,7 +672,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext, struct_id: NodeId) { index.push(entry { val: ctor_id as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); rbml_w.start_tag(tag_items_data_item); @@ -747,8 +693,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext, // indicate that this is a tuple struct ctor, because downstream users will normally want // the tuple struct definition, but without this there is no way for them to tell that // they actually have a ctor rather than a normal function - rbml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor); - rbml_w.end_tag(); + rbml_w.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]); rbml_w.end_tag(); } @@ -757,7 +702,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, generics: &ty::Generics<'tcx>, predicates: &ty::GenericPredicates<'tcx>, - tag: uint) + tag: usize) { rbml_w.start_tag(tag); @@ -768,9 +713,10 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, tcx: ecx.tcx, abbrevs: &ecx.type_abbrevs }; + for param in generics.types.iter() { rbml_w.start_tag(tag_type_param_def); - tyencode::enc_type_param_def(rbml_w.writer, ty_str_ctxt, param); + tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param); rbml_w.end_tag(); } @@ -783,7 +729,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, rbml_w.end_tag(); rbml_w.wr_tagged_str(tag_region_param_def_def_id, - &def_to_string(param.def_id)[]); + &def_to_string(param.def_id)); rbml_w.wr_tagged_u64(tag_region_param_def_space, param.space.to_uint() as u64); @@ -798,18 +744,42 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, rbml_w.end_tag(); } + encode_predicates_in_current_doc(rbml_w, ecx, predicates); + + rbml_w.end_tag(); +} + +fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder, + ecx: &EncodeContext<'a,'tcx>, + predicates: &ty::GenericPredicates<'tcx>) +{ + let ty_str_ctxt = &tyencode::ctxt { + diag: ecx.diag, + ds: def_to_string, + tcx: ecx.tcx, + abbrevs: &ecx.type_abbrevs + }; + for (space, _, predicate) in predicates.predicates.iter_enumerated() { rbml_w.start_tag(tag_predicate); rbml_w.wr_tagged_u8(tag_predicate_space, space as u8); rbml_w.start_tag(tag_predicate_data); - tyencode::enc_predicate(rbml_w.writer, ty_str_ctxt, predicate); + tyencode::enc_predicate(rbml_w, ty_str_ctxt, predicate); rbml_w.end_tag(); rbml_w.end_tag(); } +} +fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder, + ecx: &EncodeContext<'a,'tcx>, + predicates: &ty::GenericPredicates<'tcx>, + tag: usize) +{ + rbml_w.start_tag(tag); + encode_predicates_in_current_doc(rbml_w, ecx, predicates); rbml_w.end_tag(); } @@ -838,7 +808,7 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, impl_path: PathElems, is_default_impl: bool, parent_id: NodeId, - ast_item_opt: Option<&ast::ImplItem>) { + impl_item_opt: Option<&ast::ImplItem>) { debug!("encode_info_for_method: {:?} {:?}", m.def_id, token::get_name(m.name)); @@ -856,21 +826,20 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, let elem = ast_map::PathName(m.name); encode_path(rbml_w, impl_path.chain(Some(elem).into_iter())); - match ast_item_opt { - Some(&ast::MethodImplItem(ref ast_method)) => { - encode_attributes(rbml_w, &ast_method.attrs[]); + if let Some(impl_item) = impl_item_opt { + if let ast::MethodImplItem(ref sig, _) = impl_item.node { + encode_attributes(rbml_w, &impl_item.attrs); let scheme = ty::lookup_item_type(ecx.tcx, m.def_id); let any_types = !scheme.generics.types.is_empty(); - if any_types || is_default_impl || should_inline(&ast_method.attrs[]) { + if any_types || is_default_impl || attr::requests_inline(&impl_item.attrs) { encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id), - ast_item_opt.unwrap())); + impl_item)); } if !any_types { encode_symbol(ecx, rbml_w, m.def_id.node); } - encode_method_argument_names(rbml_w, ast_method.pe_fn_decl()); + encode_method_argument_names(rbml_w, &sig.decl); } - Some(_) | None => {} } rbml_w.end_tag(); @@ -881,7 +850,7 @@ fn encode_info_for_associated_type(ecx: &EncodeContext, associated_type: &ty::AssociatedType, impl_path: PathElems, parent_id: NodeId, - typedef_opt: Option>) { + impl_item_opt: Option<&ast::ImplItem>) { debug!("encode_info_for_associated_type({:?},{:?})", associated_type.def_id, token::get_name(associated_type.name)); @@ -903,13 +872,9 @@ fn encode_info_for_associated_type(ecx: &EncodeContext, let elem = ast_map::PathName(associated_type.name); encode_path(rbml_w, impl_path.chain(Some(elem).into_iter())); - match typedef_opt { - None => {} - Some(typedef) => { - encode_attributes(rbml_w, &typedef.attrs[]); - encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx, - typedef.id)); - } + if let Some(ii) = impl_item_opt { + encode_attributes(rbml_w, &ii.attrs); + encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx, ii.id)); } rbml_w.end_tag(); @@ -919,12 +884,13 @@ fn encode_method_argument_names(rbml_w: &mut Encoder, decl: &ast::FnDecl) { rbml_w.start_tag(tag_method_argument_names); for arg in &decl.inputs { - rbml_w.start_tag(tag_method_argument_name); + let tag = tag_method_argument_name; if let ast::PatIdent(_, ref path1, _) = arg.pat.node { let name = token::get_ident(path1.node); - rbml_w.writer.write_all(name.as_bytes()); + rbml_w.wr_tagged_bytes(tag, name.as_bytes()); + } else { + rbml_w.wr_tagged_bytes(tag, &[]); } - rbml_w.end_tag(); } rbml_w.end_tag(); } @@ -954,14 +920,6 @@ const FN_FAMILY: char = 'f'; const STATIC_METHOD_FAMILY: char = 'F'; const METHOD_FAMILY: char = 'h'; -fn should_inline(attrs: &[ast::Attribute]) -> bool { - use syntax::attr::*; - match find_inline_attr(attrs) { - InlineNone | InlineNever => false, - InlineHint | InlineAlways => true - } -} - // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(ecx: &EncodeContext, rbml_w: &mut Encoder, @@ -1010,11 +968,11 @@ fn encode_info_for_item(ecx: &EncodeContext, vis: ast::Visibility) { let tcx = ecx.tcx; - fn add_to_index(item: &ast::Item, rbml_w: &Encoder, + fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder, index: &mut Vec>) { index.push(entry { val: item.id as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); } @@ -1040,7 +998,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_path(rbml_w, path); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); - encode_attributes(rbml_w, &item.attrs[]); + encode_attributes(rbml_w, &item.attrs); rbml_w.end_tag(); } ast::ItemConst(_, _) => { @@ -1066,8 +1024,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_bounds_and_type_for_item(rbml_w, ecx, item.id); encode_name(rbml_w, item.ident.name); encode_path(rbml_w, path); - encode_attributes(rbml_w, &item.attrs[]); - if tps_len > 0 || should_inline(&item.attrs[]) { + encode_attributes(rbml_w, &item.attrs); + if tps_len > 0 || attr::requests_inline(&item.attrs) { encode_inlined_item(ecx, rbml_w, IIItemRef(item)); } if tps_len == 0 { @@ -1083,7 +1041,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_info_for_mod(ecx, rbml_w, m, - &item.attrs[], + &item.attrs, item.id, path, item.ident, @@ -1099,9 +1057,8 @@ fn encode_info_for_item(ecx: &EncodeContext, // Encode all the items in this module. for foreign_item in &fm.items { - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&def_to_string(local_def(foreign_item.id))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_child, + &def_to_string(local_def(foreign_item.id))); } encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); @@ -1128,8 +1085,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_item_variances(rbml_w, ecx, item.id); encode_bounds_and_type_for_item(rbml_w, ecx, item.id); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, &item.attrs[]); - encode_repr_attrs(rbml_w, ecx, &item.attrs[]); + encode_attributes(rbml_w, &item.attrs); + encode_repr_attrs(rbml_w, ecx, &item.attrs); for v in &enum_definition.variants { encode_variant_id(rbml_w, local_def(v.node.id)); } @@ -1146,7 +1103,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_enum_variant_info(ecx, rbml_w, item.id, - &(*enum_definition).variants[], + &(*enum_definition).variants, index); } ast::ItemStruct(ref struct_def, _) => { @@ -1172,11 +1129,11 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_item_variances(rbml_w, ecx, item.id); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, &item.attrs[]); + encode_attributes(rbml_w, &item.attrs); encode_path(rbml_w, path.clone()); encode_stability(rbml_w, stab); encode_visibility(rbml_w, vis); - encode_repr_attrs(rbml_w, ecx, &item.attrs[]); + encode_repr_attrs(rbml_w, ecx, &item.attrs); /* Encode def_ids for each field and method for methods, write all the stuff get_trait_method @@ -1201,11 +1158,23 @@ fn encode_info_for_item(ecx: &EncodeContext, None => {} } } + ast::ItemDefaultImpl(unsafety, _) => { + add_to_index(item, rbml_w, index); + rbml_w.start_tag(tag_items_data_item); + encode_def_id(rbml_w, def_id); + encode_family(rbml_w, 'd'); + encode_name(rbml_w, item.ident.name); + encode_unsafety(rbml_w, unsafety); + + let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id); + encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref); + rbml_w.end_tag(); + } ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => { // We need to encode information about the default methods we // have inherited, so we drive this based on the impl structure. let impl_items = tcx.impl_items.borrow(); - let items = &(*impl_items)[def_id]; + let items = impl_items.get(&def_id).unwrap(); add_to_index(item, rbml_w, index); rbml_w.start_tag(tag_items_data_item); @@ -1213,11 +1182,11 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_family(rbml_w, 'i'); encode_bounds_and_type_for_item(rbml_w, ecx, item.id); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, &item.attrs[]); + 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 => { + ast::TyPath(None, ref path) if path.segments.len() == 1 => { let ident = path.segments.last().unwrap().identifier; encode_impl_type_basename(rbml_w, ident); } @@ -1237,9 +1206,8 @@ fn encode_info_for_item(ecx: &EncodeContext, } rbml_w.end_tag(); } - if let Some(ref ast_trait_ref) = *opt_trait { - let trait_ref = ty::node_id_to_trait_ref( - tcx, ast_trait_ref.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id); encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref); } encode_path(rbml_w, path.clone()); @@ -1253,21 +1221,18 @@ fn encode_info_for_item(ecx: &EncodeContext, let num_implemented_methods = ast_items.len(); for (i, &trait_item_def_id) in items.iter().enumerate() { let ast_item = if i < num_implemented_methods { - Some(&ast_items[i]) + Some(&*ast_items[i]) } else { None }; index.push(entry { val: trait_item_def_id.def_id().node as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); - let trait_item_type = - ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()); - match (trait_item_type, ast_item) { - (ty::MethodTraitItem(ref method_type), - Some(&ast::MethodImplItem(_))) => { + match ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()) { + ty::MethodTraitItem(ref method_type) => { encode_info_for_method(ecx, rbml_w, &**method_type, @@ -1276,31 +1241,13 @@ fn encode_info_for_item(ecx: &EncodeContext, item.id, ast_item) } - (ty::MethodTraitItem(ref method_type), _) => { - encode_info_for_method(ecx, - rbml_w, - &**method_type, - path.clone(), - false, - item.id, - None) - } - (ty::TypeTraitItem(ref associated_type), - Some(&ast::TypeImplItem(ref typedef))) => { + ty::TypeTraitItem(ref associated_type) => { encode_info_for_associated_type(ecx, rbml_w, &**associated_type, path.clone(), item.id, - Some((*typedef).clone())) - } - (ty::TypeTraitItem(ref associated_type), _) => { - encode_info_for_associated_type(ecx, - rbml_w, - &**associated_type, - path.clone(), - item.id, - None) + ast_item) } } } @@ -1315,11 +1262,14 @@ fn encode_info_for_item(ecx: &EncodeContext, let trait_predicates = ty::lookup_predicates(tcx, def_id); encode_unsafety(rbml_w, trait_def.unsafety); encode_paren_sugar(rbml_w, trait_def.paren_sugar); + encode_defaulted(rbml_w, ty::trait_has_default_impl(tcx, def_id)); encode_associated_type_names(rbml_w, &trait_def.associated_type_names); encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates, tag_item_generics); + encode_predicates(rbml_w, ecx, &ty::lookup_super_predicates(tcx, def_id), + tag_item_super_predicates); encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref); encode_name(rbml_w, item.ident.name); - encode_attributes(rbml_w, &item.attrs[]); + encode_attributes(rbml_w, &item.attrs); encode_visibility(rbml_w, vis); encode_stability(rbml_w, stab); for &method_def_id in &*ty::trait_item_def_ids(tcx, def_id) { @@ -1336,14 +1286,11 @@ fn encode_info_for_item(ecx: &EncodeContext, } rbml_w.end_tag(); - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&def_to_string(method_def_id.def_id())[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_child, + &def_to_string(method_def_id.def_id())); } encode_path(rbml_w, path.clone()); - encode_bounds(rbml_w, ecx, &trait_def.bounds, tag_trait_def_bounds); - // Encode the implementations of this trait. encode_extension_implementations(ecx, rbml_w, def_id); @@ -1359,7 +1306,7 @@ fn encode_info_for_item(ecx: &EncodeContext, index.push(entry { val: item_def_id.def_id().node as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); rbml_w.start_tag(tag_items_data_item); @@ -1414,35 +1361,29 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_parent_sort(rbml_w, 't'); - let trait_item = &ms[i]; - let encode_trait_item = |rbml_w: &mut Encoder| { - // If this is a static method, we've already - // encoded this. - if is_nonstatic_method { - // FIXME: I feel like there is something funny - // going on. - encode_bounds_and_type_for_item(rbml_w, ecx, item_def_id.def_id().local_id()); - } - }; - match trait_item { - &ast::RequiredMethod(ref m) => { - encode_attributes(rbml_w, &m.attrs[]); - encode_trait_item(rbml_w); - encode_item_sort(rbml_w, 'r'); - encode_method_argument_names(rbml_w, &*m.decl); - } + let trait_item = &*ms[i]; + encode_attributes(rbml_w, &trait_item.attrs); + match trait_item.node { + ast::MethodTraitItem(ref sig, ref body) => { + // If this is a static method, we've already + // encoded this. + if is_nonstatic_method { + // FIXME: I feel like there is something funny + // going on. + encode_bounds_and_type_for_item(rbml_w, ecx, + item_def_id.def_id().local_id()); + } - &ast::ProvidedMethod(ref m) => { - encode_attributes(rbml_w, &m.attrs[]); - encode_trait_item(rbml_w); - encode_item_sort(rbml_w, 'p'); - encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item)); - encode_method_argument_names(rbml_w, &*m.pe_fn_decl()); + if body.is_some() { + encode_item_sort(rbml_w, 'p'); + encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item)); + } else { + encode_item_sort(rbml_w, 'r'); + } + encode_method_argument_names(rbml_w, &sig.decl); } - &ast::TypeTraitItem(ref associated_type) => { - encode_attributes(rbml_w, - &associated_type.attrs[]); + ast::TypeTraitItem(..) => { encode_item_sort(rbml_w, 't'); } } @@ -1464,7 +1405,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, abi: abi::Abi) { index.push(entry { val: nitem.id as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); rbml_w.start_tag(tag_items_data_item); @@ -1564,14 +1505,14 @@ fn encode_info_for_items(ecx: &EncodeContext, rbml_w.start_tag(tag_items_data); index.push(entry { val: ast::CRATE_NODE_ID as i64, - pos: rbml_w.writer.tell().unwrap(), + pos: rbml_w.mark_stable_position(), }); encode_info_for_mod(ecx, rbml_w, &krate.module, &[], ast::CRATE_NODE_ID, - [].iter().cloned().chain(None), + [].iter().cloned().chain(LinkedPath::empty()), syntax::parse::token::special_idents::invalid, ast::Public); @@ -1588,57 +1529,15 @@ fn encode_info_for_items(ecx: &EncodeContext, // Path and definition ID indexing -#[cfg(stage0)] fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: F) where - F: FnMut(&mut SeekableMemWriter, &T), - T: Hash, -{ - let mut buckets: Vec>> = (0..256u16).map(|_| Vec::new()).collect(); - for elt in index { - let mut s = SipHasher::new(); - elt.val.hash(&mut s); - let h = s.finish() as uint; - (&mut buckets[h % 256]).push(elt); - } - - rbml_w.start_tag(tag_index); - let mut bucket_locs = Vec::new(); - rbml_w.start_tag(tag_index_buckets); - for bucket in &buckets { - bucket_locs.push(rbml_w.writer.tell().unwrap()); - rbml_w.start_tag(tag_index_buckets_bucket); - for elt in bucket { - rbml_w.start_tag(tag_index_buckets_bucket_elt); - assert!(elt.pos < 0xffff_ffff); - { - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(elt.pos as u32); - } - write_fn(rbml_w.writer, &elt.val); - rbml_w.end_tag(); - } - rbml_w.end_tag(); - } - rbml_w.end_tag(); - rbml_w.start_tag(tag_index_table); - for pos in &bucket_locs { - assert!(*pos < 0xffff_ffff); - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(*pos as u32); - } - rbml_w.end_tag(); - rbml_w.end_tag(); -} -#[cfg(not(stage0))] -fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: F) where - F: FnMut(&mut SeekableMemWriter, &T), + F: FnMut(&mut Cursor>, &T), T: Hash, { let mut buckets: Vec>> = (0..256u16).map(|_| Vec::new()).collect(); for elt in index { let mut s = SipHasher::new(); elt.val.hash(&mut s); - let h = s.finish() as uint; + let h = s.finish() as usize; (&mut buckets[h % 256]).push(elt); } @@ -1646,14 +1545,14 @@ fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: let mut bucket_locs = Vec::new(); rbml_w.start_tag(tag_index_buckets); for bucket in &buckets { - bucket_locs.push(rbml_w.writer.tell().unwrap()); + bucket_locs.push(rbml_w.mark_stable_position()); rbml_w.start_tag(tag_index_buckets_bucket); for elt in bucket { rbml_w.start_tag(tag_index_buckets_bucket_elt); assert!(elt.pos < 0xffff_ffff); { - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(elt.pos as u32); + let wr: &mut Cursor> = rbml_w.writer; + write_be_u32(wr, elt.pos as u32); } write_fn(rbml_w.writer, &elt.val); rbml_w.end_tag(); @@ -1664,38 +1563,41 @@ fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: rbml_w.start_tag(tag_index_table); for pos in &bucket_locs { assert!(*pos < 0xffff_ffff); - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(*pos as u32); + let wr: &mut Cursor> = rbml_w.writer; + write_be_u32(wr, *pos as u32); } rbml_w.end_tag(); rbml_w.end_tag(); } -fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) { - let wr: &mut SeekableMemWriter = writer; +fn write_i64(writer: &mut Cursor>, &n: &i64) { + let wr: &mut Cursor> = writer; assert!(n < 0x7fff_ffff); - wr.write_be_u32(n as u32); + write_be_u32(wr, n as u32); +} + +fn write_be_u32(w: &mut Write, u: u32) { + w.write_all(&[ + (u >> 24) as u8, + (u >> 16) as u8, + (u >> 8) as u8, + (u >> 0) as u8, + ]); } fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { match mi.node { ast::MetaWord(ref name) => { rbml_w.start_tag(tag_meta_item_word); - rbml_w.start_tag(tag_meta_item_name); - rbml_w.writer.write_all(name.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_meta_item_name, name); rbml_w.end_tag(); } ast::MetaNameValue(ref name, ref value) => { match value.node { ast::LitStr(ref value, _) => { rbml_w.start_tag(tag_meta_item_name_value); - rbml_w.start_tag(tag_meta_item_name); - rbml_w.writer.write_all(name.as_bytes()); - rbml_w.end_tag(); - rbml_w.start_tag(tag_meta_item_value); - rbml_w.writer.write_all(value.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_meta_item_name, name); + rbml_w.wr_tagged_str(tag_meta_item_value, value); rbml_w.end_tag(); } _ => {/* FIXME (#623): encode other variants */ } @@ -1703,9 +1605,7 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) { } ast::MetaList(ref name, ref items) => { rbml_w.start_tag(tag_meta_item_list); - rbml_w.start_tag(tag_meta_item_name); - rbml_w.writer.write_all(name.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_meta_item_name, name); for inner_item in items { encode_meta_item(rbml_w, &**inner_item); } @@ -1738,6 +1638,11 @@ fn encode_paren_sugar(rbml_w: &mut Encoder, paren_sugar: bool) { rbml_w.wr_tagged_u8(tag_paren_sugar, byte); } +fn encode_defaulted(rbml_w: &mut Encoder, is_defaulted: bool) { + let byte: u8 = if is_defaulted {1} else {0}; + rbml_w.wr_tagged_u8(tag_defaulted_trait, byte); +} + fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) { rbml_w.start_tag(tag_associated_type_names); for &name in names { @@ -1799,22 +1704,9 @@ fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) { if let Some(id) = def_id { if id.krate == ast::LOCAL_CRATE { rbml_w.start_tag(tag_lang_items_item); - - rbml_w.start_tag(tag_lang_items_item_id); - { - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(i as u32); - } - rbml_w.end_tag(); // tag_lang_items_item_id - - rbml_w.start_tag(tag_lang_items_item_node_id); - { - let wr: &mut SeekableMemWriter = rbml_w.writer; - wr.write_be_u32(id.node as u32); - } - rbml_w.end_tag(); // tag_lang_items_item_node_id - - rbml_w.end_tag(); // tag_lang_items_item + rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32); + rbml_w.wr_tagged_u32(tag_lang_items_item_node_id, id.node as u32); + rbml_w.end_tag(); } } } @@ -1835,15 +1727,8 @@ fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) { cstore::NativeStatic => {} // these libraries are not propagated cstore::NativeFramework | cstore::NativeUnknown => { rbml_w.start_tag(tag_native_libraries_lib); - - rbml_w.start_tag(tag_native_libraries_kind); - rbml_w.writer.write_be_u32(kind as u32); - rbml_w.end_tag(); - - rbml_w.start_tag(tag_native_libraries_name); - rbml_w.writer.write_all(lib.as_bytes()); - rbml_w.end_tag(); - + rbml_w.wr_tagged_u32(tag_native_libraries_kind, kind as u32); + rbml_w.wr_tagged_str(tag_native_libraries_name, lib); rbml_w.end_tag(); } } @@ -1859,6 +1744,28 @@ fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) { } } +fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) { + rbml_w.start_tag(tag_codemap); + let codemap = ecx.tcx.sess.codemap(); + + for filemap in &codemap.files.borrow()[..] { + + if filemap.lines.borrow().len() == 0 || filemap.is_imported() { + // No need to export empty filemaps, as they can't contain spans + // that need translation. + // Also no need to re-export imported filemaps, as any downstream + // crate will import them from their original source. + continue; + } + + rbml_w.start_tag(tag_codemap_filemap); + filemap.encode(rbml_w); + rbml_w.end_tag(); + } + + rbml_w.end_tag(); +} + /// Serialize the text of the exported macros fn encode_macro_defs(rbml_w: &mut Encoder, krate: &ast::Crate) { @@ -1867,11 +1774,10 @@ fn encode_macro_defs(rbml_w: &mut Encoder, rbml_w.start_tag(tag_macro_def); encode_name(rbml_w, def.ident.name); - encode_attributes(rbml_w, &def.attrs[]); + encode_attributes(rbml_w, &def.attrs); - rbml_w.start_tag(tag_macro_def_body); - rbml_w.wr_str(&pprust::tts_to_string(&def.body[])[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_macro_def_body, + &pprust::tts_to_string(&def.body)); rbml_w.end_tag(); } @@ -1887,7 +1793,7 @@ fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) { fn visit_struct_field(&mut self, field: &ast::StructField) { self.rbml_w.start_tag(tag_struct_field); self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id); - encode_attributes(self.rbml_w, &field.node.attrs[]); + encode_attributes(self.rbml_w, &field.node.attrs); self.rbml_w.end_tag(); } } @@ -1909,9 +1815,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 { - 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(); + let def_id = self.ecx.tcx.def_map.borrow().get(&trait_ref.ref_id).unwrap().def_id(); // Load eagerly if this is an implementation of the Drop trait // or if the trait is not defined in this crate. @@ -1958,21 +1862,18 @@ fn encode_misc_info(ecx: &EncodeContext, rbml_w.start_tag(tag_misc_info); rbml_w.start_tag(tag_misc_info_crate_items); for item in &krate.module.items { - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&def_to_string(local_def(item.id))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_child, + &def_to_string(local_def(item.id))); each_auxiliary_node_id(&**item, |auxiliary_node_id| { - rbml_w.start_tag(tag_mod_child); - rbml_w.wr_str(&def_to_string(local_def( - auxiliary_node_id))[]); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_mod_child, + &def_to_string(local_def(auxiliary_node_id))); true }); } // Encode reexports for the root module. - encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(None)); + encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(LinkedPath::empty())); rbml_w.end_tag(); rbml_w.end_tag(); @@ -1997,35 +1898,25 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, rbml_w: &mut Encoder) { fn encode_crate_dep(rbml_w: &mut Encoder, dep: decoder::CrateDep) { rbml_w.start_tag(tag_crate_dep); - rbml_w.start_tag(tag_crate_dep_crate_name); - rbml_w.writer.write_all(dep.name.as_bytes()); - rbml_w.end_tag(); - rbml_w.start_tag(tag_crate_dep_hash); - rbml_w.writer.write_all(dep.hash.as_str().as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name); + rbml_w.wr_tagged_str(tag_crate_dep_hash, dep.hash.as_str()); rbml_w.end_tag(); } fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) { - rbml_w.start_tag(tag_crate_hash); - rbml_w.writer.write_all(hash.as_str().as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str()); } fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) { - rbml_w.start_tag(tag_crate_crate_name); - rbml_w.writer.write_all(crate_name.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name); } fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) { - rbml_w.start_tag(tag_crate_triple); - rbml_w.writer.write_all(triple.as_bytes()); - rbml_w.end_tag(); + rbml_w.wr_tagged_str(tag_crate_triple, triple); } fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) { - rbml_w.start_tag(tag_dylib_dependency_formats); + let tag = tag_dylib_dependency_formats; match ecx.tcx.dependency_formats.borrow().get(&config::CrateTypeDylib) { Some(arr) => { let s = arr.iter().enumerate().filter_map(|(i, slot)| { @@ -2034,21 +1925,28 @@ fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) { cstore::RequireStatic => "s", })).to_string()) }).collect::>(); - rbml_w.writer.write_all(s.connect(",").as_bytes()); + rbml_w.wr_tagged_str(tag, &s.connect(",")); + } + None => { + rbml_w.wr_tagged_str(tag, ""); } - None => {} } - rbml_w.end_tag(); } // NB: Increment this as you change the metadata encoding version. #[allow(non_upper_case_globals)] -pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 1 ]; +pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ]; pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec { - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); encode_metadata_inner(&mut wr, parms, krate); - let mut v = wr.unwrap(); + + // RBML compacts the encoded bytes whenever appropriate, + // so there are some garbages left after the end of the data. + let metalen = wr.seek(SeekFrom::Current(0)).unwrap() as usize; + let mut v = wr.into_inner(); + v.truncate(metalen); + assert_eq!(v.len(), metalen); // And here we run into yet another obscure archive bug: in which metadata // loaded from archives may have trailing garbage bytes. Awhile back one of @@ -2076,7 +1974,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec { return v; } -fn encode_metadata_inner(wr: &mut SeekableMemWriter, +fn encode_metadata_inner(wr: &mut Cursor>, parms: EncodeParams, krate: &ast::Crate) { struct Stats { @@ -2085,6 +1983,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, lang_item_bytes: u64, native_lib_bytes: u64, plugin_registrar_fn_bytes: u64, + codemap_bytes: u64, macro_defs_bytes: u64, impl_bytes: u64, misc_bytes: u64, @@ -2099,6 +1998,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, lang_item_bytes: 0, native_lib_bytes: 0, plugin_registrar_fn_bytes: 0, + codemap_bytes: 0, macro_defs_bytes: 0, impl_bytes: 0, misc_bytes: 0, @@ -2130,70 +2030,75 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, reachable: reachable, }; - let mut rbml_w = writer::Encoder::new(wr); + let mut rbml_w = Encoder::new(wr); - encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name[]); + encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name); encode_crate_triple(&mut rbml_w, &tcx.sess .opts .target_triple - []); + ); encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash); encode_dylib_dependency_formats(&mut rbml_w, &ecx); - let mut i = rbml_w.writer.tell().unwrap(); - encode_attributes(&mut rbml_w, &krate.attrs[]); - stats.attr_bytes = rbml_w.writer.tell().unwrap() - i; + let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_attributes(&mut rbml_w, &krate.attrs); + stats.attr_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_crate_deps(&mut rbml_w, ecx.cstore); - stats.dep_bytes = rbml_w.writer.tell().unwrap() - i; + stats.dep_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the language items. - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_lang_items(&ecx, &mut rbml_w); - stats.lang_item_bytes = rbml_w.writer.tell().unwrap() - i; + stats.lang_item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the native libraries used - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_native_libraries(&ecx, &mut rbml_w); - stats.native_lib_bytes = rbml_w.writer.tell().unwrap() - i; + stats.native_lib_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the plugin registrar function - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_plugin_registrar_fn(&ecx, &mut rbml_w); - stats.plugin_registrar_fn_bytes = rbml_w.writer.tell().unwrap() - i; + stats.plugin_registrar_fn_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; + + // Encode codemap + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); + encode_codemap(&ecx, &mut rbml_w); + stats.codemap_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode macro definitions - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_macro_defs(&mut rbml_w, krate); - stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i; + stats.macro_defs_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode the def IDs of impls, for coherence checking. - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_impls(&ecx, krate, &mut rbml_w); - stats.impl_bytes = rbml_w.writer.tell().unwrap() - i; + stats.impl_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode miscellaneous info. - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_misc_info(&ecx, krate, &mut rbml_w); encode_reachable_extern_fns(&ecx, &mut rbml_w); - stats.misc_bytes = rbml_w.writer.tell().unwrap() - i; + stats.misc_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; // Encode and index the items. rbml_w.start_tag(tag_items); - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate); - stats.item_bytes = rbml_w.writer.tell().unwrap() - i; + stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; - i = rbml_w.writer.tell().unwrap(); + i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); encode_index(&mut rbml_w, items_index, write_i64); - stats.index_bytes = rbml_w.writer.tell().unwrap() - i; + stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i; rbml_w.end_tag(); encode_struct_field_attrs(&mut rbml_w, krate); - stats.total_bytes = rbml_w.writer.tell().unwrap(); + stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); if tcx.sess.meta_stats() { for e in rbml_w.writer.get_ref() { @@ -2208,6 +2113,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, println!(" lang item bytes: {}", stats.lang_item_bytes); println!(" native bytes: {}", stats.native_lib_bytes); println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes); + println!(" codemap bytes: {}", stats.codemap_bytes); println!(" macro def bytes: {}", stats.macro_defs_bytes); println!(" impl bytes: {}", stats.impl_bytes); println!(" misc bytes: {}", stats.misc_bytes); @@ -2220,12 +2126,12 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, // Get the encoded string for a type pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String { - let mut wr = SeekableMemWriter::new(); - tyencode::enc_ty(&mut wr, &tyencode::ctxt { + let mut wr = Cursor::new(Vec::new()); + tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt { diag: tcx.sess.diagnostic(), ds: def_to_string, tcx: tcx, abbrevs: &RefCell::new(FnvHashMap()) }, t); - String::from_utf8(wr.unwrap()).unwrap() + String::from_utf8(wr.into_inner()).unwrap() } diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 3caa0f5b4d..1567f4b994 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -14,13 +14,14 @@ pub use self::FileMatch::*; use std::collections::HashSet; use std::env; -use std::old_io::fs::PathExtensions; -use std::old_io::fs; +use std::fs; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; use util::fs as myfs; use session::search_paths::{SearchPaths, PathKind}; -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum FileMatch { FileMatches, FileDoesntMatch, @@ -49,20 +50,20 @@ impl<'a> FileSearch<'a> { FileMatches => found = true, FileDoesntMatch => () } - visited_dirs.insert(path.as_vec().to_vec()); + visited_dirs.insert(path.to_path_buf()); } debug!("filesearch: searching lib path"); let tlib_path = make_target_lib_path(self.sysroot, self.triple); - if !visited_dirs.contains(tlib_path.as_vec()) { + if !visited_dirs.contains(&tlib_path) { match f(&tlib_path, PathKind::All) { FileMatches => found = true, FileDoesntMatch => () } } - visited_dirs.insert(tlib_path.as_vec().to_vec()); + visited_dirs.insert(tlib_path); // Try RUST_PATH if !found { let rustpath = rust_path(); @@ -70,10 +71,10 @@ impl<'a> FileSearch<'a> { let tlib_path = make_rustpkg_lib_path( self.sysroot, path, self.triple); debug!("is {} in visited_dirs? {}", tlib_path.display(), - visited_dirs.contains(&tlib_path.as_vec().to_vec())); + visited_dirs.contains(&tlib_path)); - if !visited_dirs.contains(tlib_path.as_vec()) { - visited_dirs.insert(tlib_path.as_vec().to_vec()); + if !visited_dirs.contains(&tlib_path) { + visited_dirs.insert(tlib_path.clone()); // Don't keep searching the RUST_PATH if one match turns up -- // if we did, we'd get a "multiple matching crates" error match f(&tlib_path, PathKind::All) { @@ -87,7 +88,7 @@ impl<'a> FileSearch<'a> { } } - pub fn get_lib_path(&self) -> Path { + pub fn get_lib_path(&self) -> PathBuf { make_target_lib_path(self.sysroot, self.triple) } @@ -96,11 +97,13 @@ impl<'a> FileSearch<'a> { { self.for_each_lib_search_path(|lib_search_path, kind| { debug!("searching {}", lib_search_path.display()); - match fs::readdir(lib_search_path) { + match fs::read_dir(lib_search_path) { Ok(files) => { + let files = files.filter_map(|p| p.ok().map(|s| s.path())) + .collect::>(); let mut rslt = FileDoesntMatch; - fn is_rlib(p: & &Path) -> bool { - p.extension_str() == Some("rlib") + fn is_rlib(p: &Path) -> bool { + p.extension().and_then(|s| s.to_str()) == Some("rlib") } // Reading metadata out of rlibs is faster, and if we find both // an rlib and a dylib we only read one of the files of @@ -142,56 +145,57 @@ impl<'a> FileSearch<'a> { } // Returns a list of directories where target-specific dylibs might be located. - pub fn get_dylib_search_paths(&self) -> Vec { + pub fn get_dylib_search_paths(&self) -> Vec { let mut paths = Vec::new(); self.for_each_lib_search_path(|lib_search_path, _| { - paths.push(lib_search_path.clone()); + paths.push(lib_search_path.to_path_buf()); FileDoesntMatch }); paths } // Returns a list of directories where target-specific tool binaries are located. - pub fn get_tools_search_paths(&self) -> Vec { - let mut p = Path::new(self.sysroot); - p.push(find_libdir(self.sysroot)); - p.push(rustlibdir()); - p.push(self.triple); + pub fn get_tools_search_paths(&self) -> Vec { + let mut p = PathBuf::from(self.sysroot); + p.push(&find_libdir(self.sysroot)); + p.push(&rustlibdir()); + p.push(&self.triple); p.push("bin"); vec![p] } } -pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> Path { - let mut p = Path::new(find_libdir(sysroot)); +pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { + let mut p = PathBuf::from(&find_libdir(sysroot)); assert!(p.is_relative()); - p.push(rustlibdir()); + p.push(&rustlibdir()); p.push(target_triple); p.push("lib"); p } fn make_target_lib_path(sysroot: &Path, - target_triple: &str) -> Path { + target_triple: &str) -> PathBuf { sysroot.join(&relative_target_lib_path(sysroot, target_triple)) } fn make_rustpkg_lib_path(sysroot: &Path, dir: &Path, - triple: &str) -> Path { - let mut p = dir.join(find_libdir(sysroot)); + triple: &str) -> PathBuf { + let mut p = dir.join(&find_libdir(sysroot)); p.push(triple); p } -pub fn get_or_default_sysroot() -> Path { +pub fn get_or_default_sysroot() -> PathBuf { // Follow symlinks. If the resolved path is relative, make it absolute. - fn canonicalize(path: Option) -> Option { - path.and_then(|path| + fn canonicalize(path: Option) -> Option { + path.and_then(|path| { match myfs::realpath(&path) { Ok(canon) => Some(canon), Err(e) => panic!("failed to get realpath: {}", e), - }) + } + }) } match canonicalize(env::current_exe().ok()) { @@ -201,9 +205,9 @@ pub fn get_or_default_sysroot() -> Path { } #[cfg(windows)] -static PATH_ENTRY_SEPARATOR: &'static str = ";"; +const PATH_ENTRY_SEPARATOR: char = ';'; #[cfg(not(windows))] -static PATH_ENTRY_SEPARATOR: &'static str = ":"; +const PATH_ENTRY_SEPARATOR: char = ':'; /// Returns RUST_PATH as a string, without default paths added pub fn get_rust_path() -> Option { @@ -215,16 +219,16 @@ pub fn get_rust_path() -> Option { /// $HOME/.rust /// DIR/.rust for any DIR that's the current working directory /// or an ancestor of it -pub fn rust_path() -> Vec { - let mut env_rust_path: Vec = match get_rust_path() { +pub fn rust_path() -> Vec { + let mut env_rust_path: Vec = match get_rust_path() { Some(env_path) => { let env_path_components = - env_path.split_str(PATH_ENTRY_SEPARATOR); - env_path_components.map(|s| Path::new(s)).collect() + env_path.split(PATH_ENTRY_SEPARATOR); + env_path_components.map(|s| PathBuf::from(s)).collect() } None => Vec::new() }; - let mut cwd = env::current_dir().unwrap(); + let cwd = env::current_dir().unwrap(); // now add in default entries let cwd_dot_rust = cwd.join(".rust"); if !env_rust_path.contains(&cwd_dot_rust) { @@ -233,15 +237,13 @@ pub fn rust_path() -> Vec { if !env_rust_path.contains(&cwd) { env_rust_path.push(cwd.clone()); } - loop { - if { let f = cwd.filename(); f.is_none() || f.unwrap() == b".." } { - break - } - cwd.set_filename(".rust"); - if !env_rust_path.contains(&cwd) && cwd.exists() { - env_rust_path.push(cwd.clone()); + let mut cur = &*cwd; + while let Some(parent) = cur.parent() { + let candidate = parent.join(".rust"); + if !env_rust_path.contains(&candidate) && candidate.exists() { + env_rust_path.push(candidate.clone()); } - cwd.pop(); + cur = parent; } if let Some(h) = env::home_dir() { let p = h.join(".rust"); @@ -266,7 +268,7 @@ fn find_libdir(sysroot: &Path) -> String { match option_env!("CFG_LIBDIR_RELATIVE") { Some(libdir) if libdir != "lib" => return libdir.to_string(), - _ => if sysroot.join(primary_libdir_name()).join(rustlibdir()).exists() { + _ => if sysroot.join(&primary_libdir_name()).join(&rustlibdir()).exists() { return primary_libdir_name(); } else { return secondary_libdir_name(); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 01d1f4e701..7b63e38b58 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -212,7 +212,7 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::loader or metadata::creader for all the juicy details! -use back::archive::{METADATA_FILENAME}; +use back::archive::METADATA_FILENAME; use back::svh::Svh; use session::Session; use session::search_paths::PathKind; @@ -226,13 +226,14 @@ use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use syntax::codemap::Span; use syntax::diagnostic::SpanHandler; use util::fs; +use util::common; use rustc_back::target::Target; -use std::ffi::CString; use std::cmp; use std::collections::HashMap; -use std::old_io::fs::PathExtensions; -use std::old_io; +use std::io::prelude::*; +use std::io; +use std::path::{Path, PathBuf}; use std::ptr; use std::slice; use std::time::Duration; @@ -240,7 +241,7 @@ use std::time::Duration; use flate; pub struct CrateMismatch { - path: Path, + path: PathBuf, got: String, } @@ -262,8 +263,8 @@ pub struct Context<'a> { } pub struct Library { - pub dylib: Option<(Path, PathKind)>, - pub rlib: Option<(Path, PathKind)>, + pub dylib: Option<(PathBuf, PathKind)>, + pub rlib: Option<(PathBuf, PathKind)>, pub metadata: MetadataBlob, } @@ -275,12 +276,12 @@ pub struct ArchiveMetadata { pub struct CratePaths { pub ident: String, - pub dylib: Option, - pub rlib: Option + pub dylib: Option, + pub rlib: Option } impl CratePaths { - fn paths(&self) -> Vec { + fn paths(&self) -> Vec { match (&self.dylib, &self.rlib) { (&None, &None) => vec!(), (&Some(ref p), &None) | @@ -329,7 +330,7 @@ impl<'a> Context<'a> { for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() { self.sess.fileline_note(self.span, &format!("crate `{}`, path #{}, triple {}: {}", - self.ident, i+1, got, path.display())[]); + self.ident, i+1, got, path.display())); } } if self.rejected_via_hash.len() > 0 { @@ -339,7 +340,7 @@ impl<'a> Context<'a> { for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() { self.sess.fileline_note(self.span, &format!("crate `{}` path #{}: {}", - self.ident, i+1, path.display())[]); + self.ident, i+1, path.display())); } match self.root { &None => {} @@ -347,19 +348,19 @@ impl<'a> Context<'a> { for (i, path) in r.paths().iter().enumerate() { self.sess.fileline_note(self.span, &format!("crate `{}` path #{}: {}", - r.ident, i+1, path.display())[]); + r.ident, i+1, path.display())); } } } } if self.rejected_via_kind.len() > 0 { - self.sess.span_help(self.span, "please recompile this crate using \ + self.sess.fileline_help(self.span, "please recompile this crate using \ --crate-type lib"); let mismatches = self.rejected_via_kind.iter(); for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() { self.sess.fileline_note(self.span, &format!("crate `{}` path #{}: {}", - self.ident, i+1, path.display())[]); + self.ident, i+1, path.display())); } } self.sess.abort_if_errors(); @@ -400,7 +401,7 @@ impl<'a> Context<'a> { // // The goal of this step is to look at as little metadata as possible. self.filesearch.search(|path, kind| { - let file = match path.filename_str() { + let file = match path.file_name().and_then(|s| s.to_str()) { None => return FileDoesntMatch, Some(file) => file, }; @@ -416,7 +417,7 @@ impl<'a> Context<'a> { if file.starts_with(&staticlib_prefix[..]) && file.ends_with(".a") { staticlibs.push(CrateMismatch { - path: path.clone(), + path: path.to_path_buf(), got: "static".to_string() }); } @@ -425,8 +426,8 @@ impl<'a> Context<'a> { info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); - let slot = candidates.entry(hash_str).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert((HashMap::new(), HashMap::new()))); + let slot = candidates.entry(hash_str) + .or_insert_with(|| (HashMap::new(), HashMap::new())); let (ref mut rlibs, ref mut dylibs) = *slot; if rlib { rlibs.insert(fs::realpath(path).unwrap(), kind); @@ -472,26 +473,26 @@ impl<'a> Context<'a> { _ => { self.sess.span_err(self.span, &format!("multiple matching crates for `{}`", - self.crate_name)[]); + self.crate_name)); self.sess.note("candidates:"); for lib in &libraries { match lib.dylib { Some((ref p, _)) => { self.sess.note(&format!("path: {}", - p.display())[]); + p.display())); } None => {} } match lib.rlib { Some((ref p, _)) => { self.sess.note(&format!("path: {}", - p.display())[]); + p.display())); } None => {} } let data = lib.metadata.as_slice(); let name = decoder::get_crate_name(data); - note_crate_name(self.sess.diagnostic(), &name[]); + note_crate_name(self.sess.diagnostic(), &name); } None } @@ -506,9 +507,9 @@ impl<'a> Context<'a> { // read the metadata from it if `*slot` is `None`. If the metadata couldn't // be read, it is assumed that the file isn't a valid rust library (no // errors are emitted). - fn extract_one(&mut self, m: HashMap, flavor: &str, - slot: &mut Option) -> Option<(Path, PathKind)> { - let mut ret = None::<(Path, PathKind)>; + fn extract_one(&mut self, m: HashMap, flavor: &str, + slot: &mut Option) -> Option<(PathBuf, PathKind)> { + let mut ret = None::<(PathBuf, PathKind)>; let mut error = 0; if slot.is_some() { @@ -545,11 +546,11 @@ impl<'a> Context<'a> { &format!("multiple {} candidates for `{}` \ found", flavor, - self.crate_name)[]); + self.crate_name)); self.sess.span_note(self.span, &format!(r"candidate #1: {}", ret.as_ref().unwrap().0 - .display())[]); + .display())); error = 1; ret = None; } @@ -557,7 +558,7 @@ impl<'a> Context<'a> { error += 1; self.sess.span_note(self.span, &format!(r"candidate #{}: {}", error, - lib.display())[]); + lib.display())); continue } *slot = Some(metadata); @@ -587,7 +588,7 @@ impl<'a> Context<'a> { if triple != self.triple { info!("Rejecting via crate triple: expected {} got {}", self.triple, triple); self.rejected_via_triple.push(CrateMismatch { - path: libpath.clone(), + path: libpath.to_path_buf(), got: triple.to_string() }); return false; @@ -599,7 +600,7 @@ impl<'a> Context<'a> { if *myhash != hash { info!("Rejecting via hash: expected {} got {}", *myhash, hash); self.rejected_via_hash.push(CrateMismatch { - path: libpath.clone(), + path: libpath.to_path_buf(), got: myhash.as_str().to_string() }); false @@ -627,17 +628,17 @@ impl<'a> Context<'a> { let mut rlibs = HashMap::new(); let mut dylibs = HashMap::new(); { - let locs = locs.iter().map(|l| Path::new(&l[..])).filter(|loc| { + let locs = locs.iter().map(|l| PathBuf::from(l)).filter(|loc| { if !loc.exists() { sess.err(&format!("extern location for {} does not exist: {}", - self.crate_name, loc.display())[]); + self.crate_name, loc.display())); return false; } - let file = match loc.filename_str() { + let file = match loc.file_name().and_then(|s| s.to_str()) { Some(file) => file, None => { sess.err(&format!("extern location for {} is not a file: {}", - self.crate_name, loc.display())[]); + self.crate_name, loc.display())); return false; } }; @@ -651,14 +652,14 @@ impl<'a> Context<'a> { } } sess.err(&format!("extern location for {} is of an unknown type: {}", - self.crate_name, loc.display())[]); + self.crate_name, loc.display())); false }); // Now that we have an iterator of good candidates, make sure // there's at most one rlib and at most one dylib. for loc in locs { - if loc.filename_str().unwrap().ends_with(".rlib") { + if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { rlibs.insert(fs::realpath(&loc).unwrap(), PathKind::ExternFlag); } else { @@ -686,7 +687,7 @@ impl<'a> Context<'a> { } pub fn note_crate_name(diag: &SpanHandler, name: &str) { - diag.handler().note(&format!("crate name: {}", name)[]); + diag.handler().note(&format!("crate name: {}", name)); } impl ArchiveMetadata { @@ -714,7 +715,7 @@ fn get_metadata_section(is_osx: bool, filename: &Path) -> Result {}ms", filename.filename_display(), + info!("reading {:?} => {}ms", filename.file_name().unwrap(), dur.num_milliseconds()); return ret.unwrap();; } @@ -723,7 +724,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result Result { - return Err((format!("failed to read rlib metadata: '{}'", - filename.display()))) - } - Some(blob) => return Ok(blob) - } + None => Err(format!("failed to read rlib metadata: '{}'", + filename.display())), + Some(blob) => Ok(blob) + }; } unsafe { - let buf = CString::new(filename.as_vec()).unwrap(); + let buf = common::path2cstr(filename); let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()); - if mb as int == 0 { + if mb as isize == 0 { return Err(format!("error reading library: '{}'", filename.display())) } @@ -762,12 +761,12 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result Result return Ok(MetadataVec(inflated)), - None => {} + Ok(inflated) => return Ok(MetadataVec(inflated)), + Err(_) => {} } } llvm::LLVMMoveToNextSection(si.llsi); } - return Err(format!("metadata not found: '{}'", filename.display())); + Err(format!("metadata not found: '{}'", filename.display())) } } @@ -813,7 +812,7 @@ pub fn read_meta_section_name(is_osx: bool) -> &'static str { // A diagnostic function for dumping crate metadata to an output stream pub fn list_file_metadata(is_osx: bool, path: &Path, - out: &mut old_io::Writer) -> old_io::IoResult<()> { + out: &mut io::Write) -> io::Result<()> { match get_metadata_section(is_osx, path) { Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), Err(msg) => { diff --git a/src/librustc/metadata/macro_import.rs b/src/librustc/metadata/macro_import.rs index 28c98d455f..c2d7911d15 100644 --- a/src/librustc/metadata/macro_import.rs +++ b/src/librustc/metadata/macro_import.rs @@ -78,16 +78,7 @@ impl<'a, 'v> Visitor<'v> for MacroLoader<'a> { for attr in &item.attrs { let mut used = true; - match &attr.name()[] { - "phase" => { - self.sess.span_err(attr.span, "#[phase] is deprecated"); - } - "plugin" => { - self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated"); - self.sess.span_help(attr.span, &format!("use a crate attribute instead, \ - i.e. #![plugin({})]", - item.ident.as_str())[]); - } + match &attr.name()[..] { "macro_use" => { let names = attr.meta_item_list(); if names.is_none() { @@ -166,6 +157,9 @@ impl<'a> MacroLoader<'a> { Some(sel) => sel.contains_key(&name), }; def.export = reexport.contains_key(&name); + def.allow_internal_unstable = attr::contains_name(&def.attrs, + "allow_internal_unstable"); + debug!("load_macros: loaded: {:?}", def); self.macros.push(def); } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 5805725a8f..3fb128b188 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -43,7 +43,7 @@ use syntax::parse::token; // def-id will depend on where it originated from. Therefore, the conversion // function is given an indicator of the source of the def-id. See // astencode.rs for more information. -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum DefIdSource { // Identifies a struct, trait, enum, etc. NominalType, @@ -66,7 +66,7 @@ pub enum DefIdSource { pub struct PState<'a, 'tcx: 'a> { data: &'a [u8], krate: ast::CrateNum, - pos: uint, + pos: usize, tcx: &'a ty::ctxt<'tcx> } @@ -119,7 +119,7 @@ fn parse_name_(st: &mut PState, is_last: F) -> ast::Name where } pub fn parse_state_from_data<'a, 'tcx>(data: &'a [u8], crate_num: ast::CrateNum, - pos: uint, tcx: &'a ty::ctxt<'tcx>) + pos: usize, tcx: &'a ty::ctxt<'tcx>) -> PState<'a, 'tcx> { PState { data: data, @@ -129,7 +129,7 @@ pub fn parse_state_from_data<'a, 'tcx>(data: &'a [u8], crate_num: ast::CrateNum, } } -fn data_log_string(data: &[u8], pos: uint) -> String { +fn data_log_string(data: &[u8], pos: usize) -> String { let mut buf = String::new(); buf.push_str("<<"); for i in pos..data.len() { @@ -146,7 +146,7 @@ fn data_log_string(data: &[u8], pos: uint) -> String { pub fn parse_ty_closure_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, - pos: uint, + pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> ty::ClosureTy<'tcx> where @@ -156,7 +156,7 @@ pub fn parse_ty_closure_data<'tcx, F>(data: &[u8], parse_closure_ty(&mut st, conv) } -pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint, +pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> Ty<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { @@ -165,7 +165,7 @@ pub fn parse_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint, parse_ty(&mut st, conv) } -pub fn parse_region_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt, +pub fn parse_region_data(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt, conv: F) -> ty::Region where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { @@ -174,7 +174,7 @@ pub fn parse_region_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tc parse_region(&mut st, conv) } -pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint, +pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> ty::BareFnTy<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, @@ -184,7 +184,7 @@ pub fn parse_bare_fn_ty_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos parse_bare_fn_ty(&mut st, conv) } -pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint, +pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> Rc> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, @@ -194,7 +194,7 @@ pub fn parse_trait_ref_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: parse_trait_ref(&mut st, conv) } -pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: uint, +pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> subst::Substs<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { @@ -204,7 +204,7 @@ pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: ui } pub fn parse_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, - pos: uint, tcx: &ty::ctxt<'tcx>, conv: F) + pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> ty::ParamBounds<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { @@ -213,7 +213,7 @@ pub fn parse_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, } pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, - pos: uint, tcx: &ty::ctxt<'tcx>, conv: F) + pos: usize, tcx: &ty::ctxt<'tcx>, conv: F) -> ty::ExistentialBounds<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { @@ -222,7 +222,7 @@ pub fn parse_existential_bounds_data<'tcx, F>(data: &[u8], crate_num: ast::Crate } pub fn parse_builtin_bounds_data(data: &[u8], crate_num: ast::CrateNum, - pos: uint, tcx: &ty::ctxt, conv: F) + pos: usize, tcx: &ty::ctxt, conv: F) -> ty::BuiltinBounds where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { @@ -230,7 +230,7 @@ pub fn parse_builtin_bounds_data(data: &[u8], crate_num: ast::CrateNum, parse_builtin_bounds(&mut st, conv) } -fn parse_size(st: &mut PState) -> Option { +fn parse_size(st: &mut PState) -> Option { assert_eq!(next(st), '/'); if peek(st) == '|' { @@ -305,7 +305,7 @@ fn parse_bound_region_(st: &mut PState, conv: &mut F) -> ty::BoundRegion wher } '[' => { let def = parse_def_(st, RegionParameter, conv); - let ident = token::str_to_ident(&parse_str(st, ']')[]); + let ident = token::str_to_ident(&parse_str(st, ']')); ty::BrNamed(def, ident.name) } 'f' => { @@ -344,7 +344,7 @@ fn parse_region_(st: &mut PState, conv: &mut F) -> ty::Region where assert_eq!(next(st), '|'); let index = parse_u32(st); assert_eq!(next(st), '|'); - let nm = token::str_to_ident(&parse_str(st, ']')[]); + let nm = token::str_to_ident(&parse_str(st, ']')); ty::ReEarlyBound(node_id, space, index, nm.name) } 'f' => { @@ -447,8 +447,8 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w let tcx = st.tcx; match next(st) { 'b' => return tcx.types.bool, - 'i' => { /* eat the s of is */ next(st); return tcx.types.int }, - 'u' => { /* eat the s of us */ next(st); return tcx.types.uint }, + 'i' => { /* eat the s of is */ next(st); return tcx.types.isize }, + 'u' => { /* eat the s of us */ next(st); return tcx.types.usize }, 'M' => { match next(st) { 'b' => return tcx.types.u8, @@ -485,7 +485,7 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w assert_eq!(next(st), '|'); let space = parse_param_space(st); assert_eq!(next(st), '|'); - let name = token::intern(&parse_str(st, ']')[]); + let name = token::intern(&parse_str(st, ']')); return ty::mk_param(tcx, space, index, name); } '~' => return ty::mk_uniq(tcx, parse_ty_(st, conv)), @@ -555,11 +555,9 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w 'k' => { assert_eq!(next(st), '['); let did = parse_def_(st, ClosureSource, conv); - let region = parse_region_(st, conv); let substs = parse_substs_(st, conv); assert_eq!(next(st), ']'); - return ty::mk_closure(st.tcx, did, - st.tcx.mk_region(region), st.tcx.mk_substs(substs)); + return ty::mk_closure(st.tcx, did, st.tcx.mk_substs(substs)); } 'P' => { assert_eq!(next(st), '['); @@ -594,21 +592,21 @@ fn parse_def_(st: &mut PState, source: DefIdSource, conv: &mut F) -> ast::Def return (*conv)(source, scan(st, |c| { c == '|' }, parse_def_id)); } -fn parse_uint(st: &mut PState) -> uint { +fn parse_uint(st: &mut PState) -> usize { let mut n = 0; loop { let cur = peek(st); if cur < '0' || cur > '9' { return n; } st.pos = st.pos + 1; n *= 10; - n += (cur as uint) - ('0' as uint); + n += (cur as usize) - ('0' as usize); }; } fn parse_u32(st: &mut PState) -> u32 { let n = parse_uint(st); let m = n as u32; - assert_eq!(m as uint, n); + assert_eq!(m as usize, n); m } @@ -616,7 +614,7 @@ fn parse_param_space(st: &mut PState) -> subst::ParamSpace { subst::ParamSpace::from_uint(parse_uint(st)) } -fn parse_hex(st: &mut PState) -> uint { +fn parse_hex(st: &mut PState) -> usize { let mut n = 0; loop { let cur = peek(st); @@ -624,8 +622,8 @@ fn parse_hex(st: &mut PState) -> uint { st.pos = st.pos + 1; n *= 16; if '0' <= cur && cur <= '9' { - n += (cur as uint) - ('0' as uint); - } else { n += 10 + (cur as uint) - ('a' as uint); } + n += (cur as usize) - ('0' as usize); + } else { n += 10 + (cur as usize) - ('a' as usize); } }; } @@ -727,14 +725,14 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId { let def_part = &buf[colon_idx + 1..len]; let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| { - s.parse::().ok() + s.parse::().ok() }) { Some(cn) => cn as ast::CrateNum, None => panic!("internal error: parse_def_id: crate number expected, found {:?}", crate_part) }; let def_num = match str::from_utf8(def_part).ok().and_then(|s| { - s.parse::().ok() + s.parse::().ok() }) { Some(dn) => dn as ast::NodeId, None => panic!("internal error: parse_def_id: id expected, found {:?}", @@ -744,7 +742,7 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId { } pub fn parse_predicate_data<'tcx, F>(data: &[u8], - start: uint, + start: usize, crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>, conv: F) @@ -796,7 +794,7 @@ fn parse_projection_predicate_<'a,'tcx, F>( } } -pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: uint, +pub fn parse_type_param_def_data<'tcx, F>(data: &[u8], start: usize, crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>, conv: F) -> ty::TypeParameterDef<'tcx> where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, @@ -822,7 +820,6 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) assert_eq!(next(st), '|'); let index = parse_u32(st); assert_eq!(next(st), '|'); - let bounds = parse_bounds_(st, conv); let default = parse_opt(st, |st| parse_ty_(st, conv)); let object_lifetime_default = parse_object_lifetime_default(st, conv); @@ -831,7 +828,6 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) def_id: def_id, space: space, index: index, - bounds: bounds, default: default, object_lifetime_default: object_lifetime_default, } @@ -924,18 +920,18 @@ fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) { let builtin_bounds = parse_builtin_bounds_(st, conv); + let region_bounds = parse_region_bounds_(st, conv); + let mut param_bounds = ty::ParamBounds { - region_bounds: Vec::new(), + region_bounds: region_bounds, builtin_bounds: builtin_bounds, trait_bounds: Vec::new(), projection_bounds: Vec::new(), }; + + loop { match next(st) { - 'R' => { - param_bounds.region_bounds.push( - parse_region_(st, conv)); - } 'I' => { param_bounds.trait_bounds.push( ty::Binder(parse_trait_ref_(st, conv))); @@ -953,3 +949,17 @@ fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) } } } + +fn parse_region_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) + -> Vec where + F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, +{ + let mut region_bounds = Vec::new(); + loop { + match next(st) { + 'R' => { region_bounds.push(parse_region_(st, conv)); } + '.' => { return region_bounds; } + c => { panic!("parse_bounds: bad bounds ('{}')", c); } + } + } +} diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index e1e9d49dd0..7a2df49662 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -14,6 +14,7 @@ #![allow(non_camel_case_types)] use std::cell::RefCell; +use std::io::prelude::*; use middle::region; use middle::subst; @@ -27,9 +28,9 @@ use syntax::ast; use syntax::diagnostic::SpanHandler; use syntax::parse::token; -use rbml::io::SeekableMemWriter; +use rbml::writer::Encoder; -macro_rules! mywrite { ($($arg:tt)*) => ({ write!($($arg)*); }) } +macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) } pub struct ctxt<'a, 'tcx: 'a> { pub diag: &'a SpanHandler, @@ -49,19 +50,21 @@ pub struct ty_abbrev { pub type abbrev_map<'tcx> = RefCell, ty_abbrev>>; -pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { +pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { match cx.abbrevs.borrow_mut().get(&t) { - Some(a) => { w.write_all(a.s.as_bytes()); return; } + Some(a) => { w.writer.write_all(a.s.as_bytes()); return; } None => {} } - let pos = w.tell().unwrap(); + + // type abbreviations needs a stable position + let pos = w.mark_stable_position(); match t.sty { ty::ty_bool => mywrite!(w, "b"), ty::ty_char => mywrite!(w, "c"), ty::ty_int(t) => { match t { - ast::TyIs(_) => mywrite!(w, "is"), + ast::TyIs => mywrite!(w, "is"), ast::TyI8 => mywrite!(w, "MB"), ast::TyI16 => mywrite!(w, "MW"), ast::TyI32 => mywrite!(w, "ML"), @@ -70,7 +73,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t } ty::ty_uint(t) => { match t { - ast::TyUs(_) => mywrite!(w, "us"), + ast::TyUs => mywrite!(w, "us"), ast::TyU8 => mywrite!(w, "Mb"), ast::TyU16 => mywrite!(w, "Mw"), ast::TyU32 => mywrite!(w, "Ml"), @@ -139,9 +142,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t enc_substs(w, cx, substs); mywrite!(w, "]"); } - ty::ty_closure(def, region, substs) => { + ty::ty_closure(def, substs) => { mywrite!(w, "k[{}|", (cx.ds)(def)); - enc_region(w, cx, *region); enc_substs(w, cx, substs); mywrite!(w, "]"); } @@ -153,12 +155,9 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t ty::ty_err => { mywrite!(w, "e"); } - ty::ty_open(_) => { - cx.diag.handler().bug("unexpected type in enc_sty (ty_open)"); - } } - let end = w.tell().unwrap(); + let end = w.mark_stable_position(); let len = end - pos; fn estimate_sz(u: u64) -> u64 { let mut n = u; @@ -175,21 +174,21 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t } } -fn enc_mutability(w: &mut SeekableMemWriter, mt: ast::Mutability) { +fn enc_mutability(w: &mut Encoder, mt: ast::Mutability) { match mt { ast::MutImmutable => (), ast::MutMutable => mywrite!(w, "m"), } } -fn enc_mt<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, mt: ty::mt<'tcx>) { enc_mutability(w, mt.mutbl); enc_ty(w, cx, mt.ty); } -fn enc_opt(w: &mut SeekableMemWriter, t: Option, enc_f: F) where - F: FnOnce(&mut SeekableMemWriter, T), +fn enc_opt(w: &mut Encoder, t: Option, enc_f: F) where + F: FnOnce(&mut Encoder, T), { match t { None => mywrite!(w, "n"), @@ -200,11 +199,11 @@ fn enc_opt(w: &mut SeekableMemWriter, t: Option, enc_f: F) where } } -fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut SeekableMemWriter, +fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, v: &VecPerParamSpace, mut op: F) where - F: FnMut(&mut SeekableMemWriter, &ctxt<'a, 'tcx>, &T), + F: FnMut(&mut Encoder, &ctxt<'a, 'tcx>, &T), { for &space in &subst::ParamSpace::all() { mywrite!(w, "["); @@ -215,14 +214,14 @@ fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut SeekableMemWriter, } } -pub fn enc_substs<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +pub fn enc_substs<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, substs: &subst::Substs<'tcx>) { enc_region_substs(w, cx, &substs.regions); enc_vec_per_param_space(w, cx, &substs.types, |w, cx, &ty| enc_ty(w, cx, ty)); } -fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::RegionSubsts) { +fn enc_region_substs(w: &mut Encoder, cx: &ctxt, substs: &subst::RegionSubsts) { match *substs { subst::ErasedRegions => { mywrite!(w, "e"); @@ -235,7 +234,7 @@ fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Regio } } -pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) { +pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { match r { ty::ReLateBound(id, br) => { mywrite!(w, "b[{}|", id.depth); @@ -274,7 +273,7 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) { } } -fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) { +fn enc_scope(w: &mut Encoder, _cx: &ctxt, scope: region::CodeExtent) { match scope { region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id), region::CodeExtent::Remainder(region::BlockRemainder { @@ -283,12 +282,12 @@ fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) { } } -fn enc_destruction_scope_data(w: &mut SeekableMemWriter, +fn enc_destruction_scope_data(w: &mut Encoder, d: region::DestructionScopeData) { mywrite!(w, "{}", d.node_id); } -fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) { +fn enc_bound_region(w: &mut Encoder, cx: &ctxt, br: ty::BoundRegion) { match br { ty::BrAnon(idx) => { mywrite!(w, "a{}|", idx); @@ -307,40 +306,40 @@ fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) { } } -pub fn enc_trait_ref<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, s: &ty::TraitRef<'tcx>) { mywrite!(w, "{}|", (cx.ds)(s.def_id)); enc_substs(w, cx, s.substs); } -fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) { +fn enc_unsafety(w: &mut Encoder, p: ast::Unsafety) { match p { ast::Unsafety::Normal => mywrite!(w, "n"), ast::Unsafety::Unsafe => mywrite!(w, "u"), } } -fn enc_abi(w: &mut SeekableMemWriter, abi: Abi) { +fn enc_abi(w: &mut Encoder, abi: Abi) { mywrite!(w, "["); mywrite!(w, "{}", abi.name()); mywrite!(w, "]") } -pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, ft: &ty::BareFnTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } -pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +pub fn enc_closure_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, ft: &ty::ClosureTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_fn_sig(w, cx, &ft.sig); enc_abi(w, ft.abi); } -fn enc_fn_sig<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +fn enc_fn_sig<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, fsig: &ty::PolyFnSig<'tcx>) { mywrite!(w, "["); for ty in &fsig.0.inputs { @@ -362,7 +361,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, } } -pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::BuiltinBounds) { +pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) { for bound in bs { match bound { ty::BoundSend => mywrite!(w, "S"), @@ -375,7 +374,7 @@ pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::Builti mywrite!(w, "."); } -pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter, +pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder, cx: &ctxt<'a,'tcx>, bs: &ty::ExistentialBounds<'tcx>) { let param_bounds = ty::ParamBounds { trait_bounds: vec!(), @@ -385,14 +384,11 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter, enc_bounds(w, cx, ¶m_bounds); } -pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +pub fn enc_bounds<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, bs: &ty::ParamBounds<'tcx>) { enc_builtin_bounds(w, cx, &bs.builtin_bounds); - for &r in &bs.region_bounds { - mywrite!(w, "R"); - enc_region(w, cx, r); - } + enc_region_bounds(w, cx, &bs.region_bounds); for tp in &bs.trait_bounds { mywrite!(w, "I"); @@ -407,17 +403,27 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, mywrite!(w, "."); } -pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, +pub fn enc_region_bounds<'a, 'tcx>(w: &mut Encoder, + cx: &ctxt<'a, 'tcx>, + rs: &[ty::Region]) { + for &r in rs { + mywrite!(w, "R"); + enc_region(w, cx, r); + } + + mywrite!(w, "."); +} + +pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, v: &ty::TypeParameterDef<'tcx>) { mywrite!(w, "{}:{}|{}|{}|", token::get_name(v.name), (cx.ds)(v.def_id), v.space.to_uint(), v.index); - enc_bounds(w, cx, &v.bounds); enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); enc_object_lifetime_default(w, cx, v.object_lifetime_default); } -fn enc_object_lifetime_default<'a, 'tcx>(w: &mut SeekableMemWriter, +fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, default: Option) { @@ -431,7 +437,7 @@ fn enc_object_lifetime_default<'a, 'tcx>(w: &mut SeekableMemWriter, } } -pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter, +pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, p: &ty::Predicate<'tcx>) { @@ -462,7 +468,7 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter, } } -fn enc_projection_predicate<'a, 'tcx>(w: &mut SeekableMemWriter, +fn enc_projection_predicate<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, data: &ty::ProjectionPredicate<'tcx>) { enc_trait_ref(w, cx, &*data.projection_ty.trait_ref); diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index 7143e3caac..698cf105ae 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -19,71 +19,60 @@ use middle::ty::{self, Ty}; use syntax::ast; use util::ppaux::Repr; -pub const NO_REGIONS: uint = 1; -pub const NO_TPS: uint = 2; +pub const NO_REGIONS: usize = 1; +pub const NO_TPS: usize = 2; -pub fn check_path_args(tcx: &ty::ctxt, - path: &ast::Path, - flags: uint) { - if (flags & NO_TPS) != 0 { - if path.segments.iter().any(|s| s.parameters.has_types()) { - span_err!(tcx.sess, path.span, E0109, - "type parameters are not allowed on this type"); +pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: usize) { + for segment in segments { + if (flags & NO_TPS) != 0 { + for typ in segment.parameters.types() { + span_err!(tcx.sess, typ.span, E0109, + "type parameters are not allowed on this type"); + break; + } } - } - if (flags & NO_REGIONS) != 0 { - if path.segments.iter().any(|s| s.parameters.has_lifetimes()) { - span_err!(tcx.sess, path.span, E0110, - "region parameters are not allowed on this type"); + if (flags & NO_REGIONS) != 0 { + for lifetime in segment.parameters.lifetimes() { + span_err!(tcx.sess, lifetime.span, E0110, + "lifetime parameters are not allowed on this type"); + break; + } } } } +pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>, + segments: &[ast::PathSegment], + nty: ast::PrimTy) + -> Ty<'tcx> { + check_path_args(tcx, segments, NO_TPS | NO_REGIONS); + match nty { + ast::TyBool => tcx.types.bool, + ast::TyChar => tcx.types.char, + ast::TyInt(it) => ty::mk_mach_int(tcx, it), + ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit), + ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft), + ast::TyStr => ty::mk_str(tcx) + } +} + pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { - match ast_ty.node { - ast::TyPath(ref path, id) => { - let a_def = match tcx.def_map.borrow().get(&id) { - None => { - tcx.sess.span_bug(ast_ty.span, - &format!("unbound path {}", - path.repr(tcx))[]) - } - Some(&d) => d - }; - match a_def { - def::DefPrimTy(nty) => { - match nty { - ast::TyBool => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(tcx.types.bool) - } - ast::TyChar => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(tcx.types.char) - } - ast::TyInt(it) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_int(tcx, it)) - } - ast::TyUint(uit) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_uint(tcx, uit)) - } - ast::TyFloat(ft) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - Some(ty::mk_mach_float(tcx, ft)) - } - ast::TyStr => { - Some(ty::mk_str(tcx)) - } - } - } - _ => None + if let ast::TyPath(None, ref path) = ast_ty.node { + let def = match tcx.def_map.borrow().get(&ast_ty.id) { + None => { + tcx.sess.span_bug(ast_ty.span, + &format!("unbound path {}", path.repr(tcx))) } + Some(d) => d.full_def() + }; + if let def::DefPrimTy(nty) = def { + Some(prim_ty_to_ty(tcx, &path.segments, nty)) + } else { + None } - _ => None + } else { + None } } - diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index ae10eb686b..b6061f3923 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -25,30 +25,34 @@ use metadata::tydecode::{RegionParameter, ClosureSource}; use metadata::tyencode; use middle::check_const::ConstQualif; use middle::mem_categorization::Typer; +use middle::privacy::{AllPublic, LastMod}; use middle::subst; use middle::subst::VecPerParamSpace; use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin}; use util::ppaux::ty_to_string; use syntax::{ast, ast_map, ast_util, codemap, fold}; -use syntax::ast_util::PostExpansionMethod; use syntax::codemap::Span; use syntax::fold::Folder; use syntax::parse::token; use syntax::ptr::P; use syntax; -use std::old_io::Seek; +use std::cell::Cell; +use std::io::SeekFrom; +use std::io::prelude::*; use std::num::FromPrimitive; use std::rc::Rc; +use std::fmt::Debug; -use rbml::io::SeekableMemWriter; -use rbml::{reader, writer}; +use rbml::reader; +use rbml::writer::Encoder; use rbml; use serialize; use serialize::{Decodable, Decoder, DecoderHelpers, Encodable}; -use serialize::{EncoderHelpers}; +use serialize::EncoderHelpers; +#[cfg(test)] use std::io::Cursor; #[cfg(test)] use syntax::parse; #[cfg(test)] use syntax::print::pprust; @@ -56,7 +60,9 @@ struct DecodeContext<'a, 'b, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, cdata: &'b cstore::crate_metadata, from_id_range: ast_util::IdRange, - to_id_range: ast_util::IdRange + to_id_range: ast_util::IdRange, + // Cache the last used filemap for translating spans as an optimization. + last_filemap_index: Cell, } trait tr { @@ -67,8 +73,6 @@ trait tr_intern { fn tr_intern(&self, dcx: &DecodeContext) -> ast::DefId; } -pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>; - // ______________________________________________________________________ // Top-level methods. @@ -78,21 +82,18 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext, let id = match ii { e::IIItemRef(i) => i.id, e::IIForeignRef(i) => i.id, - e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id, - e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id, - e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.ty_param.id, - e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id, - e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id, + e::IITraitItemRef(_, ti) => ti.id, + e::IIImplItemRef(_, ii) => ii.id, }; debug!("> Encoding inlined item: {} ({:?})", ecx.tcx.map.path_to_string(id), - rbml_w.writer.tell()); + rbml_w.writer.seek(SeekFrom::Current(0))); // Folding could be avoided with a smarter encoder. let ii = simplify_ast(ii); let id_range = ast_util::compute_id_range_for_inlined_item(&ii); - rbml_w.start_tag(c::tag_ast as uint); + rbml_w.start_tag(c::tag_ast as usize); id_range.encode(rbml_w); encode_ast(rbml_w, &ii); encode_side_tables_for_ii(ecx, rbml_w, &ii); @@ -100,7 +101,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext, debug!("< Encoded inlined fn: {} ({:?})", ecx.tcx.map.path_to_string(id), - rbml_w.writer.tell()); + rbml_w.writer.seek(SeekFrom::Current(0))); } impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> { @@ -120,6 +121,8 @@ impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> { } } +/// Decodes an item from its AST in the cdata's metadata and adds it to the +/// ast-map. pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata, tcx: &ty::ctxt<'tcx>, path: Vec, @@ -143,7 +146,8 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata, cdata: cdata, tcx: tcx, from_id_range: from_id_range, - to_id_range: to_id_range + to_id_range: to_id_range, + last_filemap_index: Cell::new(0) }; let raw_ii = decode_ast(ast_doc); let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, raw_ii, dcx); @@ -151,19 +155,8 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata, let ident = match *ii { ast::IIItem(ref i) => i.ident, ast::IIForeign(ref i) => i.ident, - ast::IITraitItem(_, ref ti) => { - match *ti { - ast::ProvidedMethod(ref m) => m.pe_ident(), - ast::RequiredMethod(ref ty_m) => ty_m.ident, - ast::TypeTraitItem(ref ti) => ti.ty_param.ident, - } - }, - ast::IIImplItem(_, ref m) => { - match *m { - ast::MethodImplItem(ref m) => m.pe_ident(), - ast::TypeImplItem(ref ti) => ti.ident, - } - } + ast::IITraitItem(_, ref ti) => ti.ident, + ast::IIImplItem(_, ref ii) => ii.ident }; debug!("Fn named: {}", token::get_ident(ident)); debug!("< Decoded inlined fn: {}::{}", @@ -204,7 +197,9 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> { pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId { // from_id_range should be non-empty assert!(!self.from_id_range.empty()); - (id - self.from_id_range.min + self.to_id_range.min) + // Use wrapping arithmetic because otherwise it introduces control flow. + // Maybe we should just have the control flow? -- aatch + (id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min)) } /// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded @@ -232,8 +227,62 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> { assert_eq!(did.krate, ast::LOCAL_CRATE); ast::DefId { krate: ast::LOCAL_CRATE, node: self.tr_id(did.node) } } - pub fn tr_span(&self, _span: Span) -> Span { - codemap::DUMMY_SP // FIXME (#1972): handle span properly + + /// Translates a `Span` from an extern crate to the corresponding `Span` + /// within the local crate's codemap. `creader::import_codemap()` will + /// already have allocated any additionally needed FileMaps in the local + /// codemap as a side-effect of creating the crate_metadata's + /// `codemap_import_info`. + pub fn tr_span(&self, span: Span) -> Span { + let imported_filemaps = &self.cdata.codemap_import_info[..]; + + let span = if span.lo > span.hi { + // Currently macro expansion sometimes produces invalid Span values + // where lo > hi. In order not to crash the compiler when trying to + // translate these values, let's transform them into something we + // can handle (and which will produce useful debug locations at + // least some of the time). + // This workaround is only necessary as long as macro expansion is + // not fixed. FIXME(#23480) + codemap::mk_sp(span.lo, span.lo) + } else { + span + }; + + let filemap_index = { + // Optimize for the case that most spans within a translated item + // originate from the same filemap. + let last_filemap_index = self.last_filemap_index.get(); + + if span.lo >= imported_filemaps[last_filemap_index].original_start_pos && + span.lo <= imported_filemaps[last_filemap_index].original_end_pos && + span.hi >= imported_filemaps[last_filemap_index].original_start_pos && + span.hi <= imported_filemaps[last_filemap_index].original_end_pos { + last_filemap_index + } else { + let mut a = 0; + let mut b = imported_filemaps.len(); + + while b - a > 1 { + let m = (a + b) / 2; + if imported_filemaps[m].original_start_pos > span.lo { + b = m; + } else { + a = m; + } + } + + self.last_filemap_index.set(a); + a + } + }; + + let lo = (span.lo - imported_filemaps[filemap_index].original_start_pos) + + imported_filemaps[filemap_index].translated_filemap.start_pos; + let hi = (span.hi - imported_filemaps[filemap_index].original_start_pos) + + imported_filemaps[filemap_index].translated_filemap.start_pos; + + codemap::mk_sp(lo, hi) } } @@ -265,9 +314,11 @@ trait def_id_encoder_helpers { fn emit_def_id(&mut self, did: ast::DefId); } -impl def_id_encoder_helpers for S { +impl def_id_encoder_helpers for S + where ::Error: Debug +{ fn emit_def_id(&mut self, did: ast::DefId) { - did.encode(self).ok().unwrap() + did.encode(self).unwrap() } } @@ -277,15 +328,18 @@ trait def_id_decoder_helpers { cdata: &cstore::crate_metadata) -> ast::DefId; } -impl def_id_decoder_helpers for D { +impl def_id_decoder_helpers for D + where ::Error: Debug +{ fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId { - let did: ast::DefId = Decodable::decode(self).ok().unwrap(); + let did: ast::DefId = Decodable::decode(self).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(); + cdata: &cstore::crate_metadata) + -> ast::DefId { + let did: ast::DefId = Decodable::decode(self).unwrap(); decoder::translate_def_id(cdata, did) } } @@ -306,7 +360,7 @@ impl def_id_decoder_helpers for D { // but eventually we should add entries to the local codemap as required. fn encode_ast(rbml_w: &mut Encoder, item: &ast::InlinedItem) { - rbml_w.start_tag(c::tag_tree as uint); + rbml_w.start_tag(c::tag_tree as usize); item.encode(rbml_w); rbml_w.end_tag(); } @@ -365,38 +419,16 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem { .expect_one("expected one item")) } e::IITraitItemRef(d, ti) => { - ast::IITraitItem(d, match *ti { - ast::ProvidedMethod(ref m) => { - ast::ProvidedMethod( - fold::noop_fold_method(m.clone(), &mut fld) - .expect_one("noop_fold_method must produce \ - exactly one method")) - } - ast::RequiredMethod(ref ty_m) => { - ast::RequiredMethod( - fold::noop_fold_type_method(ty_m.clone(), &mut fld)) - } - ast::TypeTraitItem(ref associated_type) => { - ast::TypeTraitItem( - P(fold::noop_fold_associated_type( - (**associated_type).clone(), - &mut fld))) - } - }) + ast::IITraitItem(d, + fold::noop_fold_trait_item(P(ti.clone()), &mut fld) + .expect_one("noop_fold_trait_item must produce \ + exactly one trait item")) } - e::IIImplItemRef(d, m) => { - ast::IIImplItem(d, match *m { - ast::MethodImplItem(ref m) => { - ast::MethodImplItem( - fold::noop_fold_method(m.clone(), &mut fld) - .expect_one("noop_fold_method must produce \ - exactly one method")) - } - ast::TypeImplItem(ref td) => { - ast::TypeImplItem( - P(fold::noop_fold_typedef((**td).clone(), &mut fld))) - } - }) + e::IIImplItemRef(d, ii) => { + ast::IIImplItem(d, + fold::noop_fold_impl_item(P(ii.clone()), &mut fld) + .expect_one("noop_fold_impl_item must produce \ + exactly one impl item")) } e::IIForeignRef(i) => { ast::IIForeign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld)) @@ -405,7 +437,7 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem { } fn decode_ast(par_doc: rbml::Doc) -> ast::InlinedItem { - let chi_doc = par_doc.get(c::tag_tree as uint); + let chi_doc = par_doc.get(c::tag_tree as usize); let mut d = reader::Decoder::new(chi_doc); Decodable::decode(&mut d).unwrap() } @@ -413,9 +445,8 @@ fn decode_ast(par_doc: rbml::Doc) -> ast::InlinedItem { // ______________________________________________________________________ // Encoding and decoding of ast::def -fn decode_def(dcx: &DecodeContext, doc: rbml::Doc) -> def::Def { - let mut dsr = reader::Decoder::new(doc); - let def: def::Def = Decodable::decode(&mut dsr).unwrap(); +fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> def::Def { + let def: def::Def = Decodable::decode(dsr).unwrap(); def.tr(dcx) } @@ -423,13 +454,8 @@ impl tr for def::Def { fn tr(&self, dcx: &DecodeContext) -> def::Def { match *self { def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor), - def::DefStaticMethod(did, p) => { - def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx))) - } - def::DefMethod(did0, did1, p) => { - def::DefMethod(did0.tr(dcx), - did1.map(|did1| did1.tr(dcx)), - p.map(|did2| did2.tr(dcx))) + def::DefMethod(did, p) => { + def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx))) } def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) } def::DefMod(did) => { def::DefMod(did.tr(dcx)) } @@ -442,11 +468,8 @@ impl tr for def::Def { }, def::DefTrait(did) => def::DefTrait(did.tr(dcx)), def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum), - def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)), - def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) => - def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident), - def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) => - def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident), + def::DefAssociatedTy(trait_did, did) => + def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)), def::DefPrimTy(p) => def::DefPrimTy(p), def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n), def::DefUse(did) => def::DefUse(did.tr(dcx)), @@ -455,9 +478,6 @@ impl tr for def::Def { } def::DefStruct(did) => def::DefStruct(did.tr(dcx)), def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)), - def::DefTyParamBinder(nid) => { - def::DefTyParamBinder(dcx.tr_id(nid)) - } def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)) } } @@ -921,7 +941,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_type_param_def<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, type_param_def: &ty::TypeParameterDef<'tcx>) { self.emit_opaque(|this| { - Ok(tyencode::enc_type_param_def(this.writer, + Ok(tyencode::enc_type_param_def(this, &ecx.ty_str_ctxt(), type_param_def)) }); @@ -930,7 +950,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, predicate: &ty::Predicate<'tcx>) { self.emit_opaque(|this| { - Ok(tyencode::enc_predicate(this.writer, + Ok(tyencode::enc_predicate(this, &ecx.ty_str_ctxt(), predicate)) }); @@ -964,20 +984,20 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, bounds: &ty::ExistentialBounds<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer, + self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this, &ecx.ty_str_ctxt(), bounds))); } fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) { - self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this.writer, + self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this, &ecx.ty_str_ctxt(), bounds))); } fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, substs: &subst::Substs<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_substs(this.writer, + self.emit_opaque(|this| Ok(tyencode::enc_substs(this, &ecx.ty_str_ctxt(), substs))); } @@ -994,8 +1014,14 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { }) } + ty::AdjustUnsafeFnPointer => { + this.emit_enum_variant("AdjustUnsafeFnPointer", 2, 0, |_| { + Ok(()) + }) + } + ty::AdjustDerefRef(ref auto_deref_ref) => { - this.emit_enum_variant("AdjustDerefRef", 2, 2, |this| { + this.emit_enum_variant("AdjustDerefRef", 3, 2, |this| { this.emit_enum_variant_arg(0, |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref))) }) @@ -1103,6 +1129,11 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { this.emit_enum_variant_arg(1, |this| Ok(this.emit_ty(ecx, self_ty))) }) } + ty::UnsizeUpcast(target_ty) => { + this.emit_enum_variant("UnsizeUpcast", 3, 1, |this| { + this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ecx, target_ty))) + }) + } } }); } @@ -1119,13 +1150,13 @@ impl<'a> write_tag_and_id for Encoder<'a> { f: F) where F: FnOnce(&mut Encoder<'a>), { - self.start_tag(tag_id as uint); + self.start_tag(tag_id as usize); f(self); self.end_tag(); } fn id(&mut self, id: ast::NodeId) { - self.wr_tagged_u64(c::tag_table_id as uint, id as u64); + id.encode(self).unwrap(); } } @@ -1144,7 +1175,7 @@ impl<'a, 'b, 'c, 'tcx> ast_util::IdVisitingOperation for fn encode_side_tables_for_ii(ecx: &e::EncodeContext, rbml_w: &mut Encoder, ii: &ast::InlinedItem) { - rbml_w.start_tag(c::tag_table as uint); + rbml_w.start_tag(c::tag_table as usize); ast_util::visit_ids_for_inlined_item(ii, &mut SideTableEncodingIdVisitor { ecx: ecx, rbml_w: rbml_w @@ -1159,54 +1190,47 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, debug!("Encoding side tables for id {}", id); - if let Some(def) = tcx.def_map.borrow().get(&id) { + if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { rbml_w.tag(c::tag_table_def, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap()); + def.encode(rbml_w).unwrap(); }) } - if let Some(ty) = tcx.node_types.borrow().get(&id) { + if let Some(ty) = tcx.node_types().get(&id) { rbml_w.tag(c::tag_table_node_type, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_ty(ecx, *ty); - }) + rbml_w.emit_ty(ecx, *ty); }) } if let Some(item_substs) = tcx.item_substs.borrow().get(&id) { rbml_w.tag(c::tag_table_item_subst, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_substs(ecx, &item_substs.substs); - }) + rbml_w.emit_substs(ecx, &item_substs.substs); }) } if let Some(fv) = tcx.freevars.borrow().get(&id) { rbml_w.tag(c::tag_table_freevars, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| { - Ok(encode_freevar_entry(rbml_w, fv_entry)) - }); - }) + rbml_w.emit_from_vec(fv, |rbml_w, fv_entry| { + Ok(encode_freevar_entry(rbml_w, fv_entry)) + }); }); for freevar in fv { rbml_w.tag(c::tag_table_upvar_capture_map, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - let var_id = freevar.def.def_id().node; - let upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: id - }; - let upvar_capture = tcx.upvar_capture_map.borrow()[upvar_id].clone(); - var_id.encode(rbml_w); - upvar_capture.encode(rbml_w); - }) + + let var_id = freevar.def.def_id().node; + let upvar_id = ty::UpvarId { + var_id: var_id, + closure_expr_id: id + }; + let upvar_capture = tcx.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone(); + var_id.encode(rbml_w); + upvar_capture.encode(rbml_w); }) } } @@ -1215,18 +1239,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, if let Some(type_scheme) = tcx.tcache.borrow().get(&lid) { rbml_w.tag(c::tag_table_tcache, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_type_scheme(ecx, type_scheme.clone()); - }) + rbml_w.emit_type_scheme(ecx, type_scheme.clone()); }) } if let Some(type_param_def) = tcx.ty_param_defs.borrow().get(&id) { rbml_w.tag(c::tag_table_param_defs, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_type_param_def(ecx, type_param_def) - }) + rbml_w.emit_type_param_def(ecx, type_param_def) }) } @@ -1234,18 +1254,14 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, if let Some(method) = tcx.method_map.borrow().get(&method_call) { rbml_w.tag(c::tag_table_method_map, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - encode_method_callee(ecx, rbml_w, method_call.adjustment, method) - }) + encode_method_callee(ecx, rbml_w, method_call.adjustment, method) }) } if let Some(trait_ref) = tcx.object_cast_map.borrow().get(&id) { rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_trait_ref(ecx, &*trait_ref.0); - }) + rbml_w.emit_trait_ref(ecx, &*trait_ref.0); }) } @@ -1256,9 +1272,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, if let Some(method) = tcx.method_map.borrow().get(&method_call) { rbml_w.tag(c::tag_table_method_map, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - encode_method_callee(ecx, rbml_w, method_call.adjustment, method) - }) + encode_method_callee(ecx, rbml_w, method_call.adjustment, method) }) } } @@ -1269,10 +1283,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, if let Some(method) = tcx.method_map.borrow().get(&method_call) { rbml_w.tag(c::tag_table_method_map, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - encode_method_callee(ecx, rbml_w, - method_call.adjustment, method) - }) + encode_method_callee(ecx, rbml_w, + method_call.adjustment, method) }) } } @@ -1284,49 +1296,41 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, rbml_w.tag(c::tag_table_adjustments, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_auto_adjustment(ecx, adjustment); - }) + rbml_w.emit_auto_adjustment(ecx, adjustment); }) } if let Some(closure_type) = tcx.closure_tys.borrow().get(&ast_util::local_def(id)) { rbml_w.tag(c::tag_table_closure_tys, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_closure_type(ecx, closure_type); - }) + rbml_w.emit_closure_type(ecx, closure_type); }) } if let Some(closure_kind) = tcx.closure_kinds.borrow().get(&ast_util::local_def(id)) { rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - encode_closure_kind(rbml_w, *closure_kind) - }) + encode_closure_kind(rbml_w, *closure_kind) }) } for &qualif in tcx.const_qualif_map.borrow().get(&id).iter() { rbml_w.tag(c::tag_table_const_qualif, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |rbml_w| { - qualif.encode(rbml_w).unwrap() - }) + qualif.encode(rbml_w).unwrap() }) } } trait doc_decoder_helpers { - fn as_int(&self) -> int; + fn as_int(&self) -> isize; fn opt_child(&self, tag: c::astencode_tag) -> Option; } impl<'a> doc_decoder_helpers for rbml::Doc<'a> { - fn as_int(&self) -> int { reader::doc_as_u64(*self) as int } + fn as_int(&self) -> isize { reader::doc_as_u64(*self) as isize } fn opt_child(&self, tag: c::astencode_tag) -> Option> { - reader::maybe_get_doc(*self, tag as uint) + reader::maybe_get_doc(*self, tag as usize) } } @@ -1642,6 +1646,9 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { ty::AdjustReifyFnPointer(def_id) } 2 => { + ty::AdjustUnsafeFnPointer + } + 3 => { let auto_deref_ref: ty::AutoDerefRef = this.read_enum_variant_arg(0, |this| Ok(this.read_auto_deref_ref(dcx))).unwrap(); @@ -1735,11 +1742,11 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_unsize_kind<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> ty::UnsizeKind<'tcx> { self.read_enum("UnsizeKind", |this| { - let variants = &["UnsizeLength", "UnsizeStruct", "UnsizeVtable"]; + let variants = &["UnsizeLength", "UnsizeStruct", "UnsizeVtable", "UnsizeUpcast"]; this.read_enum_variant(variants, |this, i| { Ok(match i { 0 => { - let len: uint = + let len: usize = this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap(); ty::UnsizeLength(len) @@ -1748,7 +1755,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { let uk: ty::UnsizeKind = this.read_enum_variant_arg(0, |this| Ok(this.read_unsize_kind(dcx))).unwrap(); - let idx: uint = + let idx: usize = this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap(); ty::UnsizeStruct(box uk, idx) @@ -1769,6 +1776,11 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { this.read_enum_variant_arg(1, |this| Ok(this.read_ty(dcx))).unwrap(); ty::UnsizeVtable(ty_trait, self_ty) } + 3 => { + let target_ty = + this.read_enum_variant_arg(0, |this| Ok(this.read_ty(dcx))).unwrap(); + ty::UnsizeUpcast(target_ty) + } _ => panic!("bad enum variant for ty::UnsizeKind") }) }) @@ -1778,7 +1790,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>) -> ty::ClosureKind { - Decodable::decode(self).ok().unwrap() + Decodable::decode(self).unwrap() } fn read_closure_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) @@ -1839,36 +1851,40 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn decode_side_tables(dcx: &DecodeContext, ast_doc: rbml::Doc) { - let tbl_doc = ast_doc.get(c::tag_table as uint); + let tbl_doc = ast_doc.get(c::tag_table as usize); reader::docs(tbl_doc, |tag, entry_doc| { - let id0 = entry_doc.get(c::tag_table_id as uint).as_int(); - let id = dcx.tr_id(id0 as ast::NodeId); + let mut entry_dsr = reader::Decoder::new(entry_doc); + let id0: ast::NodeId = Decodable::decode(&mut entry_dsr).unwrap(); + let id = dcx.tr_id(id0); debug!(">> Side table document with tag 0x{:x} \ found for id {} (orig {})", tag, id, id0); - let decoded_tag: Option = FromPrimitive::from_uint(tag); + let decoded_tag: Option = FromPrimitive::from_usize(tag); match decoded_tag { None => { dcx.tcx.sess.bug( &format!("unknown tag found in side tables: {:x}", - tag)[]); + tag)); } Some(value) => { - let val_doc = entry_doc.get(c::tag_table_val as uint); - let mut val_dsr = reader::Decoder::new(val_doc); - let val_dsr = &mut val_dsr; + let val_dsr = &mut entry_dsr; match value { c::tag_table_def => { - let def = decode_def(dcx, val_doc); - dcx.tcx.def_map.borrow_mut().insert(id, def); + let def = decode_def(dcx, val_dsr); + dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution { + base_def: def, + // This doesn't matter cross-crate. + last_private: LastMod(AllPublic), + depth: 0 + }); } c::tag_table_node_type => { let ty = val_dsr.read_ty(dcx); debug!("inserting ty for node {}: {}", id, ty_to_string(dcx.tcx, ty)); - dcx.tcx.node_types.borrow_mut().insert(id, ty); + dcx.tcx.node_type_insert(id, ty); } c::tag_table_item_subst => { let item_substs = ty::ItemSubsts { @@ -1937,7 +1953,7 @@ fn decode_side_tables(dcx: &DecodeContext, _ => { dcx.tcx.sess.bug( &format!("unknown tag found in side tables: {:x}", - tag)[]); + tag)); } } } @@ -1953,14 +1969,14 @@ fn decode_side_tables(dcx: &DecodeContext, #[cfg(test)] fn encode_item_ast(rbml_w: &mut Encoder, item: &ast::Item) { - rbml_w.start_tag(c::tag_tree as uint); + rbml_w.start_tag(c::tag_tree as usize); (*item).encode(rbml_w); rbml_w.end_tag(); } #[cfg(test)] fn decode_item_ast(par_doc: rbml::Doc) -> ast::Item { - let chi_doc = par_doc.get(c::tag_tree as uint); + let chi_doc = par_doc.get(c::tag_tree as usize); let mut d = reader::Decoder::new(chi_doc); Decodable::decode(&mut d).unwrap() } @@ -1999,8 +2015,8 @@ fn mk_ctxt() -> parse::ParseSess { #[cfg(test)] fn roundtrip(in_item: Option>) { let in_item = in_item.unwrap(); - let mut wr = SeekableMemWriter::new(); - encode_item_ast(&mut writer::Encoder::new(&mut wr), &*in_item); + let mut wr = Cursor::new(Vec::new()); + encode_item_ast(&mut Encoder::new(&mut wr), &*in_item); let rbml_doc = rbml::Doc::new(wr.get_ref()); let out_item = decode_item_ast(rbml_doc); @@ -2019,7 +2035,7 @@ fn test_basic() { fn test_smalltalk() { let cx = mk_ctxt(); roundtrip(quote_item!(&cx, - fn foo() -> int { 3 + 4 } // first smalltalk program ever executed. + fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed. )); } */ @@ -2028,7 +2044,7 @@ fn test_smalltalk() { fn test_more() { let cx = mk_ctxt(); roundtrip(quote_item!(&cx, - fn foo(x: uint, y: uint) -> uint { + fn foo(x: usize, y: usize) -> usize { let z = x + y; return z; } @@ -2039,15 +2055,15 @@ fn test_more() { fn test_simplification() { let cx = mk_ctxt(); let item = quote_item!(&cx, - fn new_int_alist() -> alist { - fn eq_int(a: int, b: int) -> bool { a == b } + fn new_int_alist() -> alist { + fn eq_int(a: isize, b: isize) -> bool { a == b } return alist {eq_fn: eq_int, data: Vec::new()}; } ).unwrap(); let item_in = e::IIItemRef(&*item); let item_out = simplify_ast(item_in); let item_exp = ast::IIItem(quote_item!(&cx, - fn new_int_alist() -> alist { + fn new_int_alist() -> alist { return alist {eq_fn: eq_int, data: Vec::new()}; } ).unwrap()); diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index d39b94a202..cbc2ef1535 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -11,22 +11,21 @@ use middle::cfg::*; use middle::def; use middle::graph; +use middle::pat_util; use middle::region::CodeExtent; use middle::ty; use syntax::ast; use syntax::ast_util; use syntax::ptr::P; -use util::nodemap::NodeMap; struct CFGBuilder<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, - exit_map: NodeMap, graph: CFGGraph, fn_exit: CFGIndex, loop_scopes: Vec, } -#[derive(Copy)] +#[derive(Copy, Clone)] struct LoopScope { loop_id: ast::NodeId, // id of loop/while node continue_index: CFGIndex, // where to go on a `loop` @@ -36,17 +35,16 @@ struct LoopScope { pub fn construct(tcx: &ty::ctxt, blk: &ast::Block) -> CFG { let mut graph = graph::Graph::new(); - let entry = add_initial_dummy_node(&mut graph); + let entry = graph.add_node(CFGNodeData::Entry); // `fn_exit` is target of return exprs, which lies somewhere // outside input `blk`. (Distinguishing `fn_exit` and `block_exit` // also resolves chicken-and-egg problem that arises if you try to // have return exprs jump to `block_exit` during construction.) - let fn_exit = add_initial_dummy_node(&mut graph); + let fn_exit = graph.add_node(CFGNodeData::Exit); let block_exit; let mut cfg_builder = CFGBuilder { - exit_map: NodeMap(), graph: graph, fn_exit: fn_exit, tcx: tcx, @@ -54,17 +52,12 @@ pub fn construct(tcx: &ty::ctxt, }; block_exit = cfg_builder.block(blk, entry); cfg_builder.add_contained_edge(block_exit, fn_exit); - let CFGBuilder {exit_map, graph, ..} = cfg_builder; - CFG {exit_map: exit_map, - graph: graph, + let CFGBuilder {graph, ..} = cfg_builder; + CFG {graph: graph, entry: entry, exit: fn_exit} } -fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex { - g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID }) -} - impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex { let mut stmts_exit = pred; @@ -74,19 +67,19 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let expr_exit = self.opt_expr(&blk.expr, stmts_exit); - self.add_node(blk.id, &[expr_exit]) + self.add_ast_node(blk.id, &[expr_exit]) } fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex { match stmt.node { ast::StmtDecl(ref decl, id) => { let exit = self.decl(&**decl, pred); - self.add_node(id, &[exit]) + self.add_ast_node(id, &[exit]) } ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => { let exit = self.expr(&**expr, pred); - self.add_node(id, &[exit]) + self.add_ast_node(id, &[exit]) } ast::StmtMac(..) => { @@ -115,33 +108,33 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { ast::PatLit(..) | ast::PatRange(..) | ast::PatWild(_) => { - self.add_node(pat.id, &[pred]) + self.add_ast_node(pat.id, &[pred]) } ast::PatBox(ref subpat) | ast::PatRegion(ref subpat, _) | ast::PatIdent(_, _, Some(ref subpat)) => { let subpat_exit = self.pat(&**subpat, pred); - self.add_node(pat.id, &[subpat_exit]) + self.add_ast_node(pat.id, &[subpat_exit]) } ast::PatEnum(_, Some(ref subpats)) | ast::PatTup(ref subpats) => { let pats_exit = self.pats_all(subpats.iter(), pred); - self.add_node(pat.id, &[pats_exit]) + self.add_ast_node(pat.id, &[pats_exit]) } ast::PatStruct(_, ref subpats, _) => { let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred); - self.add_node(pat.id, &[pats_exit]) + self.add_ast_node(pat.id, &[pats_exit]) } ast::PatVec(ref pre, ref vec, ref post) => { let pre_exit = self.pats_all(pre.iter(), pred); let vec_exit = self.pats_all(vec.iter(), pre_exit); let post_exit = self.pats_all(post.iter(), vec_exit); - self.add_node(pat.id, &[post_exit]) + self.add_ast_node(pat.id, &[post_exit]) } ast::PatMac(_) => { @@ -157,28 +150,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { pats.fold(pred, |pred, pat| self.pat(&**pat, pred)) } - fn pats_any(&mut self, - pats: &[P], - pred: CFGIndex) -> CFGIndex { - //! Handles case where just one of the patterns must match. - - if pats.len() == 1 { - self.pat(&*pats[0], pred) - } else { - let collect = self.add_dummy_node(&[]); - for pat in pats { - let pat_exit = self.pat(&**pat, pred); - self.add_contained_edge(pat_exit, collect); - } - collect - } - } - fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex { match expr.node { ast::ExprBlock(ref blk) => { let blk_exit = self.block(&**blk, pred); - self.add_node(expr.id, &[blk_exit]) + self.add_ast_node(expr.id, &[blk_exit]) } ast::ExprIf(ref cond, ref then, None) => { @@ -198,7 +174,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // let cond_exit = self.expr(&**cond, pred); // 1 let then_exit = self.block(&**then, cond_exit); // 2 - self.add_node(expr.id, &[cond_exit, then_exit]) // 3,4 + self.add_ast_node(expr.id, &[cond_exit, then_exit]) // 3,4 } ast::ExprIf(ref cond, ref then, Some(ref otherwise)) => { @@ -219,7 +195,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let cond_exit = self.expr(&**cond, pred); // 1 let then_exit = self.block(&**then, cond_exit); // 2 let else_exit = self.expr(&**otherwise, cond_exit); // 3 - self.add_node(expr.id, &[then_exit, else_exit]) // 4, 5 + self.add_ast_node(expr.id, &[then_exit, else_exit]) // 4, 5 } ast::ExprIfLet(..) => { @@ -247,7 +223,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Is the condition considered part of the loop? let loopback = self.add_dummy_node(&[pred]); // 1 let cond_exit = self.expr(&**cond, loopback); // 2 - let expr_exit = self.add_node(expr.id, &[cond_exit]); // 3 + let expr_exit = self.add_ast_node(expr.id, &[cond_exit]); // 3 self.loop_scopes.push(LoopScope { loop_id: expr.id, continue_index: loopback, @@ -283,7 +259,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // may cause additional edges. let loopback = self.add_dummy_node(&[pred]); // 1 - let expr_exit = self.add_node(expr.id, &[]); // 2 + let expr_exit = self.add_ast_node(expr.id, &[]); // 2 self.loop_scopes.push(LoopScope { loop_id: expr.id, continue_index: loopback, @@ -296,45 +272,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::ExprMatch(ref discr, ref arms, _) => { - // - // [pred] - // | - // v 1 - // [discr] - // | - // v 2 - // [cond1] - // / \ - // | \ - // v 3 \ - // [pat1] \ - // | | - // v 4 | - // [guard1] | - // | | - // | | - // v 5 v - // [body1] [cond2] - // | / \ - // | ... ... - // | | | - // v 6 v v - // [.....expr.....] - // - let discr_exit = self.expr(&**discr, pred); // 1 - - let expr_exit = self.add_node(expr.id, &[]); - let mut cond_exit = discr_exit; - for arm in arms { - cond_exit = self.add_dummy_node(&[cond_exit]); // 2 - let pats_exit = self.pats_any(&arm.pats[], - cond_exit); // 3 - let guard_exit = self.opt_expr(&arm.guard, - pats_exit); // 4 - let body_exit = self.expr(&*arm.body, guard_exit); // 5 - self.add_contained_edge(body_exit, expr_exit); // 6 - } - expr_exit + self.match_(expr.id, &discr, &arms, pred) } ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => { @@ -354,30 +292,30 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // let l_exit = self.expr(&**l, pred); // 1 let r_exit = self.expr(&**r, l_exit); // 2 - self.add_node(expr.id, &[l_exit, r_exit]) // 3,4 + self.add_ast_node(expr.id, &[l_exit, r_exit]) // 3,4 } ast::ExprRet(ref v) => { let v_exit = self.opt_expr(v, pred); - let b = self.add_node(expr.id, &[v_exit]); + let b = self.add_ast_node(expr.id, &[v_exit]); self.add_returning_edge(expr, b); - self.add_node(ast::DUMMY_NODE_ID, &[]) + self.add_unreachable_node() } ast::ExprBreak(label) => { let loop_scope = self.find_scope(expr, label); - let b = self.add_node(expr.id, &[pred]); + let b = self.add_ast_node(expr.id, &[pred]); self.add_exiting_edge(expr, b, loop_scope, loop_scope.break_index); - self.add_node(ast::DUMMY_NODE_ID, &[]) + self.add_unreachable_node() } ast::ExprAgain(label) => { let loop_scope = self.find_scope(expr, label); - let a = self.add_node(expr.id, &[pred]); + let a = self.add_ast_node(expr.id, &[pred]); self.add_exiting_edge(expr, a, loop_scope, loop_scope.continue_index); - self.add_node(ast::DUMMY_NODE_ID, &[]) + self.add_unreachable_node() } ast::ExprVec(ref elems) => { @@ -454,14 +392,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let &(_, ref expr, _) = a; &**expr }), post_inputs); - self.add_node(expr.id, &[post_outputs]) + self.add_ast_node(expr.id, &[post_outputs]) } ast::ExprMac(..) | ast::ExprClosure(..) | ast::ExprLit(..) | - ast::ExprPath(..) | - ast::ExprQPath(..) => { + ast::ExprPath(..) => { self.straightline(expr, pred, None::.iter()) } } @@ -481,7 +418,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let ret = self.straightline(call_expr, func_or_rcvr_exit, args); if return_ty.diverges() { - self.add_node(ast::DUMMY_NODE_ID, &[]) + self.add_unreachable_node() } else { ret } @@ -508,20 +445,126 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { //! Handles case of an expression that evaluates `subexprs` in order let subexprs_exit = self.exprs(subexprs, pred); - self.add_node(expr.id, &[subexprs_exit]) + self.add_ast_node(expr.id, &[subexprs_exit]) + } + + fn match_(&mut self, id: ast::NodeId, discr: &ast::Expr, + arms: &[ast::Arm], pred: CFGIndex) -> CFGIndex { + // The CFG for match expression is quite complex, so no ASCII + // art for it (yet). + // + // The CFG generated below matches roughly what trans puts + // out. Each pattern and guard is visited in parallel, with + // arms containing multiple patterns generating multiple nodes + // for the same guard expression. The guard expressions chain + // into each other from top to bottom, with a specific + // exception to allow some additional valid programs + // (explained below). Trans differs slightly in that the + // pattern matching may continue after a guard but the visible + // behaviour should be the same. + // + // What is going on is explained in further comments. + + // Visit the discriminant expression + let discr_exit = self.expr(discr, pred); + + // Add a node for the exit of the match expression as a whole. + let expr_exit = self.add_ast_node(id, &[]); + + // Keep track of the previous guard expressions + let mut prev_guards = Vec::new(); + // Track if the previous pattern contained bindings or wildcards + let mut prev_has_bindings = false; + + for arm in arms { + // Add an exit node for when we've visited all the + // patterns and the guard (if there is one) in the arm. + let arm_exit = self.add_dummy_node(&[]); + + for pat in &arm.pats { + // Visit the pattern, coming from the discriminant exit + let mut pat_exit = self.pat(&**pat, discr_exit); + + // If there is a guard expression, handle it here + if let Some(ref guard) = arm.guard { + // Add a dummy node for the previous guard + // expression to target + let guard_start = self.add_dummy_node(&[pat_exit]); + // Visit the guard expression + let guard_exit = self.expr(&**guard, guard_start); + + let this_has_bindings = pat_util::pat_contains_bindings_or_wild( + &self.tcx.def_map, &**pat); + + // If both this pattern and the previous pattern + // were free of bindings, they must consist only + // of "constant" patterns. Note we cannot match an + // all-constant pattern, fail the guard, and then + // match *another* all-constant pattern. This is + // because if the previous pattern matches, then + // we *cannot* match this one, unless all the + // constants are the same (which is rejected by + // `check_match`). + // + // We can use this to be smarter about the flow + // along guards. If the previous pattern matched, + // then we know we will not visit the guard in + // this one (whether or not the guard succeeded), + // if the previous pattern failed, then we know + // the guard for that pattern will not have been + // visited. Thus, it is not possible to visit both + // the previous guard and the current one when + // both patterns consist only of constant + // sub-patterns. + // + // However, if the above does not hold, then all + // previous guards need to be wired to visit the + // current guard pattern. + if prev_has_bindings || this_has_bindings { + while let Some(prev) = prev_guards.pop() { + self.add_contained_edge(prev, guard_start); + } + } + + prev_has_bindings = this_has_bindings; + + // Push the guard onto the list of previous guards + prev_guards.push(guard_exit); + + // Update the exit node for the pattern + pat_exit = guard_exit; + } + + // Add an edge from the exit of this pattern to the + // exit of the arm + self.add_contained_edge(pat_exit, arm_exit); + } + + // Visit the body of this arm + let body_exit = self.expr(&arm.body, arm_exit); + + // Link the body to the exit of the expression + self.add_contained_edge(body_exit, expr_exit); + } + + expr_exit } fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex { - self.add_node(ast::DUMMY_NODE_ID, preds) + self.add_node(CFGNodeData::Dummy, preds) } - fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex { - assert!(!self.exit_map.contains_key(&id)); - let node = self.graph.add_node(CFGNodeData {id: id}); - if id != ast::DUMMY_NODE_ID { - assert!(!self.exit_map.contains_key(&id)); - self.exit_map.insert(id, node); - } + fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex { + assert!(id != ast::DUMMY_NODE_ID); + self.add_node(CFGNodeData::AST(id), preds) + } + + fn add_unreachable_node(&mut self) -> CFGIndex { + self.add_node(CFGNodeData::Unreachable, &[]) + } + + fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex]) -> CFGIndex { + let node = self.graph.add_node(data); for &pred in preds { self.add_contained_edge(pred, node); } @@ -566,32 +609,24 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn find_scope(&self, expr: &ast::Expr, label: Option) -> LoopScope { - match label { - None => { - return *self.loop_scopes.last().unwrap(); - } - - Some(_) => { - match self.tcx.def_map.borrow().get(&expr.id) { - Some(&def::DefLabel(loop_id)) => { - for l in &self.loop_scopes { - if l.loop_id == loop_id { - return *l; - } - } - self.tcx.sess.span_bug( - expr.span, - &format!("no loop scope for id {}", - loop_id)[]); - } + if label.is_none() { + return *self.loop_scopes.last().unwrap(); + } - r => { - self.tcx.sess.span_bug( - expr.span, - &format!("bad entry `{:?}` in def_map for label", - r)[]); + match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { + Some(def::DefLabel(loop_id)) => { + for l in &self.loop_scopes { + if l.loop_id == loop_id { + return *l; } } + self.tcx.sess.span_bug(expr.span, + &format!("no loop scope for id {}", loop_id)); + } + + r => { + self.tcx.sess.span_bug(expr.span, + &format!("bad entry `{:?}` in def_map for label", r)); } } } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index 46b4a51c9d..3a6966ab11 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -54,10 +54,10 @@ fn replace_newline_with_backslash_l(s: String) -> String { } impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { - fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[]).ok().unwrap() } + fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).unwrap() } fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> { - dot::Id::new(format!("N{}", i.node_id())).ok().unwrap() + dot::Id::new(format!("N{}", i.node_id())).unwrap() } fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> { @@ -65,10 +65,10 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { dot::LabelText::LabelStr("entry".into_cow()) } else if i == self.cfg.exit { dot::LabelText::LabelStr("exit".into_cow()) - } else if n.data.id == ast::DUMMY_NODE_ID { + } else if n.data.id() == ast::DUMMY_NODE_ID { dot::LabelText::LabelStr("(dummy_node)".into_cow()) } else { - let s = self.ast_map.node_to_string(n.data.id); + let s = self.ast_map.node_to_string(n.data.id()); // left-aligns the lines let s = replace_newline_with_backslash_l(s); dot::LabelText::EscStr(s.into_cow()) @@ -92,7 +92,7 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { let s = replace_newline_with_backslash_l(s); label.push_str(&format!("exiting scope_{} {}", i, - &s[..])[]); + &s[..])); } dot::LabelText::EscStr(label.into_cow()) } @@ -124,4 +124,3 @@ impl<'a, 'ast> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) } fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) } } - diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs index 0ca146a295..ad4fdcd7b8 100644 --- a/src/librustc/middle/cfg/mod.rs +++ b/src/librustc/middle/cfg/mod.rs @@ -14,21 +14,33 @@ use middle::graph; use middle::ty; use syntax::ast; -use util::nodemap::NodeMap; mod construct; pub mod graphviz; pub struct CFG { - pub exit_map: NodeMap, pub graph: CFGGraph, pub entry: CFGIndex, pub exit: CFGIndex, } -#[derive(Copy)] -pub struct CFGNodeData { - pub id: ast::NodeId +#[derive(Copy, Clone, PartialEq)] +pub enum CFGNodeData { + AST(ast::NodeId), + Entry, + Exit, + Dummy, + Unreachable, +} + +impl CFGNodeData { + pub fn id(&self) -> ast::NodeId { + if let CFGNodeData::AST(id) = *self { + id + } else { + ast::DUMMY_NODE_ID + } + } } pub struct CFGEdgeData { @@ -50,6 +62,6 @@ impl CFG { } pub fn node_is_reachable(&self, id: ast::NodeId) -> bool { - self.graph.depth_traverse(self.entry).any(|node| node.id == id) + self.graph.depth_traverse(self.entry).any(|node| node.id() == id) } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 41d425cd2f..ce011f2561 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -76,7 +76,7 @@ bitflags! { } } -#[derive(Copy, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq)] enum Mode { Const, Static, @@ -176,7 +176,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { }; self.tcx.sess.span_err(e.span, &format!("mutable statics are not allowed \ - to have {}", suffix)[]); + to have {}", suffix)); } fn check_static_type(&self, e: &ast::Expr) { @@ -307,8 +307,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { match const_eval::eval_const_expr_partial(self.tcx, ex, None) { Ok(_) => {} Err(msg) => { - span_err!(self.tcx.sess, ex.span, E0020, - "{} in a constant expression", msg) + span_err!(self.tcx.sess, msg.span, E0020, + "{} in a constant expression", + msg.description()) } } } @@ -382,7 +383,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, if v.mode != Mode::Var { v.tcx.sess.span_err(e.span, &format!("{}s are not allowed to have destructors", - v.msg())[]); + v.msg())); } } _ => {} @@ -439,8 +440,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } } } - ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = v.tcx.def_map.borrow().get(&e.id).cloned(); + ast::ExprPath(..) => { + let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match def { Some(def::DefVariant(_, _, _)) => { // Count the discriminator or function pointer. @@ -452,8 +453,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, v.add_qualif(NON_ZERO_SIZED); } } - Some(def::DefFn(..)) | - Some(def::DefStaticMethod(..)) | Some(def::DefMethod(..)) => { + Some(def::DefFn(..)) | Some(def::DefMethod(..)) => { // Count the function pointer. v.add_qualif(NON_ZERO_SIZED); } @@ -500,7 +500,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, _ => break }; } - let def = v.tcx.def_map.borrow().get(&callee.id).cloned(); + let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); match def { Some(def::DefStruct(..)) => {} Some(def::DefVariant(..)) => { diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index ea58440794..bf6829d967 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -21,7 +21,7 @@ enum Context { Normal, Loop, Closure } -#[derive(Copy)] +#[derive(Copy, Clone)] struct CheckLoopVisitor<'a> { sess: &'a Session, cx: Context diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 86c59b24e3..79f4d62b45 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -13,11 +13,12 @@ use self::Usefulness::*; use self::WitnessPreference::*; use middle::const_eval::{compare_const_vals, const_bool, const_float, const_val}; -use middle::const_eval::{const_expr_to_pat, eval_const_expr, lookup_const_by_id}; +use middle::const_eval::{eval_const_expr, eval_const_expr_partial}; +use middle::const_eval::{const_expr_to_pat, lookup_const_by_id}; use middle::def::*; use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init}; use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode}; -use middle::expr_use_visitor::{WriteAndRead}; +use middle::expr_use_visitor::WriteAndRead; use middle::expr_use_visitor as euv; use middle::mem_categorization::cmt; use middle::pat_util::*; @@ -26,7 +27,6 @@ use middle::ty; use std::cmp::Ordering; use std::fmt; use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat}; -use std::num::Float; use std::slice; use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat}; use syntax::ast_util; @@ -72,7 +72,7 @@ impl<'a> fmt::Debug for Matrix<'a> { let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0); assert!(m.iter().all(|row| row.len() == column_count)); - let column_widths: Vec = (0..column_count).map(|col| { + let column_widths: Vec = (0..column_count).map(|col| { pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0) }).collect(); @@ -116,9 +116,9 @@ pub enum Constructor { /// Ranges of literal values (2..5). ConstantRange(const_val, const_val), /// Array patterns of length n. - Slice(uint), + Slice(usize), /// Array patterns with a subslice. - SliceWithSubslice(uint, uint) + SliceWithSubslice(usize, usize) } #[derive(Clone, PartialEq)] @@ -128,7 +128,7 @@ enum Usefulness { NotUseful } -#[derive(Copy)] +#[derive(Copy, Clone)] enum WitnessPreference { ConstructWitness, LeaveOutWitness @@ -163,7 +163,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { // First, check legality of move bindings. check_legality_of_move_bindings(cx, arm.guard.is_some(), - &arm.pats[]); + &arm.pats); // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. @@ -229,20 +229,13 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { } } -fn is_expr_const_nan(tcx: &ty::ctxt, expr: &ast::Expr) -> bool { - match eval_const_expr(tcx, expr) { - const_float(f) => f.is_nan(), - _ => false - } -} - fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) { ast_util::walk_pat(pat, |p| { match p.node { ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => { let pat_ty = ty::pat_ty(cx.tcx, p); if let ty::ty_enum(def_id, _) = pat_ty.sty { - let def = cx.tcx.def_map.borrow().get(&p.id).cloned(); + let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); if let Some(DefLocal(_)) = def { if ty::enum_variants(cx.tcx, def_id).iter().any(|variant| token::get_name(variant.name) == token::get_name(ident.node.name) @@ -252,7 +245,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) "pattern binding `{}` is named the same as one \ of the variants of the type `{}`", &token::get_ident(ident.node), ty_to_string(cx.tcx, pat_ty)); - span_help!(cx.tcx.sess, p.span, + fileline_help!(cx.tcx.sess, p.span, "if you meant to match on a variant, \ consider making the path in the pattern qualified: `{}::{}`", ty_to_string(cx.tcx, pat_ty), &token::get_ident(ident.node)); @@ -269,13 +262,26 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) // Check that we do not match against a static NaN (#6804) fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) { ast_util::walk_pat(pat, |p| { - match p.node { - ast::PatLit(ref expr) if is_expr_const_nan(cx.tcx, &**expr) => { - span_warn!(cx.tcx.sess, p.span, E0003, - "unmatchable NaN in pattern, \ - use the is_nan method in a guard instead"); + if let ast::PatLit(ref expr) = p.node { + match eval_const_expr_partial(cx.tcx, &**expr, None) { + Ok(const_float(f)) if f.is_nan() => { + span_warn!(cx.tcx.sess, p.span, E0003, + "unmatchable NaN in pattern, \ + use the is_nan method in a guard instead"); + } + Ok(_) => {} + + Err(err) => { + let subspan = p.span.lo <= err.span.lo && err.span.hi <= p.span.hi; + cx.tcx.sess.span_err(err.span, + &format!("constant evaluation error: {}", + err.description())); + if !subspan { + cx.tcx.sess.span_note(p.span, + "in pattern here") + } + } } - _ => () } true }); @@ -434,7 +440,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { fn fold_pat(&mut self, pat: P) -> P { return match pat.node { ast::PatIdent(..) | ast::PatEnum(..) => { - let def = self.tcx.def_map.borrow().get(&pat.id).cloned(); + let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()); match def { Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) { Some(const_expr) => { @@ -492,7 +498,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { /// left_ty: tuple of 3 elements /// pats: [10, 20, _] => (10, 20, _) /// -/// left_ty: struct X { a: (bool, &'static str), b: uint} +/// left_ty: struct X { a: (bool, &'static str), b: usize} /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor, pats: Vec<&Pat>, left_ty: Ty) -> P { @@ -574,7 +580,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor, } fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix, - left_ty: Ty, max_slice_length: uint) -> Option { + left_ty: Ty, max_slice_length: usize) -> Option { let used_constructors: Vec = rows.iter() .flat_map(|row| pat_constructors(cx, row[0], left_ty, max_slice_length).into_iter()) .collect(); @@ -588,7 +594,7 @@ fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix, /// but is instead bounded by the maximum fixed length of slice patterns in /// the column of patterns being analyzed. fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty, - max_slice_length: uint) -> Vec { + max_slice_length: usize) -> Vec { match left_ty.sty { ty::ty_bool => [true, false].iter().map(|b| ConstantValue(const_bool(*b))).collect(), @@ -639,6 +645,7 @@ fn is_useful(cx: &MatchCheckCtxt, if rows[0].len() == 0 { return NotUseful; } + assert!(rows.iter().all(|r| r.len() == v.len())); let real_pat = match rows.iter().find(|r| (*r)[0].id != DUMMY_NODE_ID) { Some(r) => raw_pat(r[0]), None if v.len() == 0 => return NotUseful, @@ -647,7 +654,12 @@ fn is_useful(cx: &MatchCheckCtxt, let left_ty = if real_pat.id == DUMMY_NODE_ID { ty::mk_nil(cx.tcx) } else { - ty::pat_ty(cx.tcx, &*real_pat) + let left_ty = ty::pat_ty(cx.tcx, &*real_pat); + + match real_pat.node { + ast::PatIdent(ast::BindByRef(..), _, _) => ty::deref(left_ty, false).unwrap().ty, + _ => left_ty, + } }; let max_slice_length = rows.iter().filter_map(|row| match row[0].node { @@ -729,32 +741,32 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, /// On the other hand, a wild pattern and an identifier pattern cannot be /// specialized in any way. fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, - left_ty: Ty, max_slice_length: uint) -> Vec { + left_ty: Ty, max_slice_length: usize) -> Vec { let pat = raw_pat(p); match pat.node { ast::PatIdent(..) => - match cx.tcx.def_map.borrow().get(&pat.id) { - Some(&DefConst(..)) => + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => cx.tcx.sess.span_bug(pat.span, "const pattern should've \ been rewritten"), - Some(&DefStruct(_)) => vec!(Single), - Some(&DefVariant(_, id, _)) => vec!(Variant(id)), + Some(DefStruct(_)) => vec!(Single), + Some(DefVariant(_, id, _)) => vec!(Variant(id)), _ => vec!() }, ast::PatEnum(..) => - match cx.tcx.def_map.borrow().get(&pat.id) { - Some(&DefConst(..)) => + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => cx.tcx.sess.span_bug(pat.span, "const pattern should've \ been rewritten"), - Some(&DefVariant(_, id, _)) => vec!(Variant(id)), + Some(DefVariant(_, id, _)) => vec!(Variant(id)), _ => vec!(Single) }, ast::PatStruct(..) => - match cx.tcx.def_map.borrow().get(&pat.id) { - Some(&DefConst(..)) => + match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => cx.tcx.sess.span_bug(pat.span, "const pattern should've \ been rewritten"), - Some(&DefVariant(_, id, _)) => vec!(Variant(id)), + Some(DefVariant(_, id, _)) => vec!(Variant(id)), _ => vec!(Single) }, ast::PatLit(ref expr) => @@ -786,7 +798,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat, /// /// For instance, a tuple pattern (_, 42, Some([])) has the arity of 3. /// A struct pattern's arity is the number of fields it contains, etc. -pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> uint { +pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize { match ty.sty { ty::ty_tup(ref fs) => fs.len(), ty::ty_uniq(_) => 1, @@ -838,7 +850,7 @@ fn range_covered_by_constructor(ctor: &Constructor, /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing /// fields filled with wild patterns. pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], - constructor: &Constructor, col: uint, arity: uint) -> Option> { + constructor: &Constructor, col: usize, arity: usize) -> Option> { let &Pat { id: pat_id, ref node, span: pat_span } = raw_pat(r[col]); @@ -847,7 +859,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], Some(repeat(DUMMY_WILD_PAT).take(arity).collect()), ast::PatIdent(_, _, _) => { - let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned(); + let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def()); match opt_def { Some(DefConst(..)) => cx.tcx.sess.span_bug(pat_span, "const pattern should've \ @@ -862,7 +874,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], } ast::PatEnum(_, ref args) => { - let def = cx.tcx.def_map.borrow()[pat_id].clone(); + let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); match def { DefConst(..) => cx.tcx.sess.span_bug(pat_span, "const pattern should've \ @@ -880,7 +892,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat], ast::PatStruct(_, ref pattern_fields, _) => { // Is this a struct or an enum variant? - let def = cx.tcx.def_map.borrow()[pat_id].clone(); + let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); let class_id = match def { DefConst(..) => cx.tcx.sess.span_bug(pat_span, "const pattern should've \ @@ -1101,7 +1113,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, &format!("binding pattern {} is not an \ identifier: {:?}", p.id, - p.node)[]); + p.node)); } } } diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs index 4280b7fe3f..b97978fc03 100644 --- a/src/librustc/middle/check_static_recursion.rs +++ b/src/librustc/middle/check_static_recursion.rs @@ -93,10 +93,10 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { - match self.def_map.borrow().get(&e.id) { - Some(&DefStatic(def_id, _)) | - Some(&DefConst(def_id)) if + ast::ExprPath(..) => { + match self.def_map.borrow().get(&e.id).map(|d| d.base_def) { + Some(DefStatic(def_id, _)) | + Some(DefConst(def_id)) if ast_util::is_local(def_id) => { match self.ast_map.get(def_id.node) { ast_map::NodeItem(item) => diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 5bf7422dbc..367bcbbe1d 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -13,25 +13,31 @@ pub use self::const_val::*; +use self::ErrKind::*; + use metadata::csearch; use middle::{astencode, def}; use middle::pat_util::def_to_path; use middle::ty::{self, Ty}; -use middle::astconv_util::{ast_ty_to_prim_ty}; +use middle::astconv_util::ast_ty_to_prim_ty; use syntax::ast::{self, Expr}; use syntax::codemap::Span; +use syntax::feature_gate; use syntax::parse::token::InternedString; use syntax::ptr::P; use syntax::{ast_map, ast_util, codemap}; +use std::borrow::{Cow, IntoCow}; +use std::num::wrapping::OverflowingOps; +use std::num::ToPrimitive; use std::cmp::Ordering; use std::collections::hash_map::Entry::Vacant; use std::{i8, i16, i32, i64}; use std::rc::Rc; fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> { - let opt_def = tcx.def_map.borrow().get(&e.id).cloned(); + let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match opt_def { Some(def::DefConst(def_id)) => { lookup_const_by_id(tcx, def_id) @@ -77,7 +83,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt, None => {} } let expr_id = match csearch::maybe_get_item_ast(tcx, enum_def, - box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) { + Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) { csearch::FoundAst::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 @@ -117,7 +123,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, - box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) { + Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) { csearch::FoundAst::Found(&ast::IIItem(ref item)) => match item.node { ast::ItemConst(_, ref const_expr) => Some(const_expr.id), _ => None @@ -130,16 +136,16 @@ pub fn lookup_const_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId) } } -// FIXME (#33): this doesn't handle big integer/float literals correctly -// (nor does the rest of our literal handling). #[derive(Clone, PartialEq)] pub enum const_val { const_float(f64), const_int(i64), const_uint(u64), const_str(InternedString), - const_binary(Rc >), - const_bool(bool) + const_binary(Rc>), + const_bool(bool), + Struct(ast::NodeId), + Tuple(ast::NodeId) } pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P { @@ -148,11 +154,11 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()), ast::ExprCall(ref callee, ref args) => { - let def = tcx.def_map.borrow()[callee.id].clone(); + let def = *tcx.def_map.borrow().get(&callee.id).unwrap(); if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) { entry.insert(def); } - let path = match def { + let path = match def.full_def() { def::DefStruct(def_id) => def_to_path(tcx, def_id), def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did), _ => unreachable!() @@ -178,8 +184,8 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P ast::PatVec(pats, None, vec![]) } - ast::ExprPath(ref path) => { - let opt_def = tcx.def_map.borrow().get(&expr.id).cloned(); + ast::ExprPath(_, ref path) => { + let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()); match opt_def { Some(def::DefStruct(..)) => ast::PatStruct(path.clone(), vec![], false), @@ -194,13 +200,6 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P } } - ast::ExprQPath(_) => { - match lookup_const(tcx, expr) { - Some(actual) => return const_expr_to_pat(tcx, actual, span), - _ => unreachable!() - } - } - _ => ast::PatLit(P(expr.clone())) }; P(ast::Pat { id: expr.id, node: pat, span: span }) @@ -209,106 +208,457 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val { match eval_const_expr_partial(tcx, e, None) { Ok(r) => r, - Err(s) => tcx.sess.span_fatal(e.span, &s[..]) + Err(s) => tcx.sess.span_fatal(s.span, &s.description()) + } +} + + +#[derive(Clone)] +pub struct ConstEvalErr { + pub span: Span, + pub kind: ErrKind, +} + +#[derive(Clone)] +pub enum ErrKind { + CannotCast, + CannotCastTo(&'static str), + InvalidOpForBools(ast::BinOp_), + InvalidOpForFloats(ast::BinOp_), + InvalidOpForIntUint(ast::BinOp_), + InvalidOpForUintInt(ast::BinOp_), + NegateOnString, + NegateOnBoolean, + NegateOnBinary, + NegateOnStruct, + NegateOnTuple, + NotOnFloat, + NotOnString, + NotOnBinary, + NotOnStruct, + NotOnTuple, + + NegateWithOverflow(i64), + AddiWithOverflow(i64, i64), + SubiWithOverflow(i64, i64), + MuliWithOverflow(i64, i64), + AdduWithOverflow(u64, u64), + SubuWithOverflow(u64, u64), + MuluWithOverflow(u64, u64), + DivideByZero, + DivideWithOverflow, + ModuloByZero, + ModuloWithOverflow, + ShiftLeftWithOverflow, + ShiftRightWithOverflow, + MissingStructField, + NonConstPath, + ExpectedConstTuple, + ExpectedConstStruct, + TupleIndexOutOfBounds, + + MiscBinaryOp, + MiscCatchAll, +} + +impl ConstEvalErr { + pub fn description(&self) -> Cow { + use self::ErrKind::*; + + match self.kind { + CannotCast => "can't cast this type".into_cow(), + CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(), + InvalidOpForBools(_) => "can't do this op on bools".into_cow(), + InvalidOpForFloats(_) => "can't do this op on floats".into_cow(), + InvalidOpForIntUint(..) => "can't do this op on an isize and usize".into_cow(), + InvalidOpForUintInt(..) => "can't do this op on a usize and isize".into_cow(), + NegateOnString => "negate on string".into_cow(), + NegateOnBoolean => "negate on boolean".into_cow(), + NegateOnBinary => "negate on binary literal".into_cow(), + NegateOnStruct => "negate on struct".into_cow(), + NegateOnTuple => "negate on tuple".into_cow(), + NotOnFloat => "not on float or string".into_cow(), + NotOnString => "not on float or string".into_cow(), + NotOnBinary => "not on binary literal".into_cow(), + NotOnStruct => "not on struct".into_cow(), + NotOnTuple => "not on tuple".into_cow(), + + NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(), + AddiWithOverflow(..) => "attempted to add with overflow".into_cow(), + SubiWithOverflow(..) => "attempted to sub with overflow".into_cow(), + MuliWithOverflow(..) => "attempted to mul with overflow".into_cow(), + AdduWithOverflow(..) => "attempted to add with overflow".into_cow(), + SubuWithOverflow(..) => "attempted to sub with overflow".into_cow(), + MuluWithOverflow(..) => "attempted to mul with overflow".into_cow(), + DivideByZero => "attempted to divide by zero".into_cow(), + DivideWithOverflow => "attempted to divide with overflow".into_cow(), + ModuloByZero => "attempted remainder with a divisor of zero".into_cow(), + ModuloWithOverflow => "attempted remainder with overflow".into_cow(), + ShiftLeftWithOverflow => "attempted left shift with overflow".into_cow(), + ShiftRightWithOverflow => "attempted right shift with overflow".into_cow(), + MissingStructField => "nonexistent struct field".into_cow(), + NonConstPath => "non-constant path in constant expr".into_cow(), + ExpectedConstTuple => "expected constant tuple".into_cow(), + ExpectedConstStruct => "expected constant struct".into_cow(), + TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(), + + MiscBinaryOp => "bad operands for binary".into_cow(), + MiscCatchAll => "unsupported constant expr".into_cow(), + } + } +} + +pub type EvalResult = Result; +pub type CastResult = Result; + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum IntTy { I8, I16, I32, I64 } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum UintTy { U8, U16, U32, U64 } + +impl IntTy { + pub fn from(tcx: &ty::ctxt, t: ast::IntTy) -> IntTy { + let t = if let ast::TyIs = t { + tcx.sess.target.int_type + } else { + t + }; + match t { + ast::TyIs => unreachable!(), + ast::TyI8 => IntTy::I8, + ast::TyI16 => IntTy::I16, + ast::TyI32 => IntTy::I32, + ast::TyI64 => IntTy::I64, + } + } +} + +impl UintTy { + pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy { + let t = if let ast::TyUs = t { + tcx.sess.target.uint_type + } else { + t + }; + match t { + ast::TyUs => unreachable!(), + ast::TyU8 => UintTy::U8, + ast::TyU16 => UintTy::U16, + ast::TyU32 => UintTy::U32, + ast::TyU64 => UintTy::U64, + } + } +} + +macro_rules! signal { + ($e:expr, $exn:expr) => { + return Err(ConstEvalErr { span: $e.span, kind: $exn }) + } +} + +// The const_{int,uint}_checked_{neg,add,sub,mul,div,shl,shr} family +// of functions catch and signal overflow errors during constant +// evaluation. +// +// They all take the operator's arguments (`a` and `b` if binary), the +// overall expression (`e`) and, if available, whole expression's +// concrete type (`opt_ety`). +// +// If the whole expression's concrete type is None, then this is a +// constant evaluation happening before type check (e.g. in the check +// to confirm that a pattern range's left-side is not greater than its +// right-side). We do not do arithmetic modulo the type's bitwidth in +// such a case; we just do 64-bit arithmetic and assume that later +// passes will do it again with the type information, and thus do the +// overflow checks then. + +pub fn const_int_checked_neg<'a>( + a: i64, e: &'a Expr, opt_ety: Option) -> EvalResult { + + let (min,max) = match opt_ety { + // (-i8::MIN is itself not an i8, etc, but this is an easy way + // to allow literals to pass the check. Of course that does + // not work for i64::MIN.) + Some(IntTy::I8) => (-(i8::MAX as i64), -(i8::MIN as i64)), + Some(IntTy::I16) => (-(i16::MAX as i64), -(i16::MIN as i64)), + Some(IntTy::I32) => (-(i32::MAX as i64), -(i32::MIN as i64)), + None | Some(IntTy::I64) => (-i64::MAX, -(i64::MIN+1)), + }; + + let oflo = a < min || a > max; + if oflo { + signal!(e, NegateWithOverflow(a)); + } else { + Ok(const_int(-a)) + } +} + +pub fn const_uint_checked_neg<'a>( + a: u64, _e: &'a Expr, _opt_ety: Option) -> EvalResult { + // This always succeeds, and by definition, returns `(!a)+1`. + Ok(const_uint((!a).wrapping_add(1))) +} + +macro_rules! overflow_checking_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident, + lhs: $to_8_lhs:ident $to_16_lhs:ident $to_32_lhs:ident, + rhs: $to_8_rhs:ident $to_16_rhs:ident $to_32_rhs:ident $to_64_rhs:ident, + $EnumTy:ident $T8: ident $T16: ident $T32: ident $T64: ident, + $result_type: ident) => { { + let (a,b,opt_ety) = ($a,$b,$ety); + match opt_ety { + Some($EnumTy::$T8) => match (a.$to_8_lhs(), b.$to_8_rhs()) { + (Some(a), Some(b)) => { + let (a, oflo) = a.$overflowing_op(b); + (a as $result_type, oflo) + } + (None, _) | (_, None) => (0, true) + }, + Some($EnumTy::$T16) => match (a.$to_16_lhs(), b.$to_16_rhs()) { + (Some(a), Some(b)) => { + let (a, oflo) = a.$overflowing_op(b); + (a as $result_type, oflo) + } + (None, _) | (_, None) => (0, true) + }, + Some($EnumTy::$T32) => match (a.$to_32_lhs(), b.$to_32_rhs()) { + (Some(a), Some(b)) => { + let (a, oflo) = a.$overflowing_op(b); + (a as $result_type, oflo) + } + (None, _) | (_, None) => (0, true) + }, + None | Some($EnumTy::$T64) => match b.$to_64_rhs() { + Some(b) => a.$overflowing_op(b), + None => (0, true), + } + } + } } +} + +macro_rules! int_arith_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_i8 to_i16 to_i32, + rhs: to_i8 to_i16 to_i32 to_i64, IntTy I8 I16 I32 I64, i64) + } +} + +macro_rules! uint_arith_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_u8 to_u16 to_u32, + rhs: to_u8 to_u16 to_u32 to_u64, UintTy U8 U16 U32 U64, u64) + } +} + +macro_rules! int_shift_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_i8 to_i16 to_i32, + rhs: to_u32 to_u32 to_u32 to_u32, IntTy I8 I16 I32 I64, i64) + } +} + +macro_rules! uint_shift_body { + ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => { + overflow_checking_body!( + $a, $b, $ety, $overflowing_op, + lhs: to_u8 to_u16 to_u32, + rhs: to_u32 to_u32 to_u32 to_u32, UintTy U8 U16 U32 U64, u64) + } +} + +macro_rules! pub_fn_checked_op { + {$fn_name:ident ($a:ident : $a_ty:ty, $b:ident : $b_ty:ty,.. $WhichTy:ident) { + $ret_oflo_body:ident $overflowing_op:ident + $const_ty:ident $signal_exn:expr + }} => { + pub fn $fn_name<'a>($a: $a_ty, + $b: $b_ty, + e: &'a Expr, + opt_ety: Option<$WhichTy>) -> EvalResult { + let (ret, oflo) = $ret_oflo_body!($a, $b, opt_ety, $overflowing_op); + if !oflo { Ok($const_ty(ret)) } else { signal!(e, $signal_exn) } + } } } +pub_fn_checked_op!{ const_int_checked_add(a: i64, b: i64,.. IntTy) { + int_arith_body overflowing_add const_int AddiWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_int_checked_sub(a: i64, b: i64,.. IntTy) { + int_arith_body overflowing_sub const_int SubiWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_int_checked_mul(a: i64, b: i64,.. IntTy) { + int_arith_body overflowing_mul const_int MuliWithOverflow(a, b) +}} + +pub fn const_int_checked_div<'a>( + a: i64, b: i64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, DivideByZero); } + let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_div); + if !oflo { Ok(const_int(ret)) } else { signal!(e, DivideWithOverflow) } +} + +pub fn const_int_checked_rem<'a>( + a: i64, b: i64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, ModuloByZero); } + let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_rem); + if !oflo { Ok(const_int(ret)) } else { signal!(e, ModuloWithOverflow) } +} + +pub_fn_checked_op!{ const_int_checked_shl(a: i64, b: i64,.. IntTy) { + int_shift_body overflowing_shl const_int ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_int_checked_shl_via_uint(a: i64, b: u64,.. IntTy) { + int_shift_body overflowing_shl const_int ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_int_checked_shr(a: i64, b: i64,.. IntTy) { + int_shift_body overflowing_shr const_int ShiftRightWithOverflow +}} + +pub_fn_checked_op!{ const_int_checked_shr_via_uint(a: i64, b: u64,.. IntTy) { + int_shift_body overflowing_shr const_int ShiftRightWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_add(a: u64, b: u64,.. UintTy) { + uint_arith_body overflowing_add const_uint AdduWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_uint_checked_sub(a: u64, b: u64,.. UintTy) { + uint_arith_body overflowing_sub const_uint SubuWithOverflow(a, b) +}} + +pub_fn_checked_op!{ const_uint_checked_mul(a: u64, b: u64,.. UintTy) { + uint_arith_body overflowing_mul const_uint MuluWithOverflow(a, b) +}} + +pub fn const_uint_checked_div<'a>( + a: u64, b: u64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, DivideByZero); } + let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_div); + if !oflo { Ok(const_uint(ret)) } else { signal!(e, DivideWithOverflow) } +} + +pub fn const_uint_checked_rem<'a>( + a: u64, b: u64, e: &'a Expr, opt_ety: Option) -> EvalResult { + if b == 0 { signal!(e, ModuloByZero); } + let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_rem); + if !oflo { Ok(const_uint(ret)) } else { signal!(e, ModuloWithOverflow) } +} + +pub_fn_checked_op!{ const_uint_checked_shl(a: u64, b: u64,.. UintTy) { + uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_shl_via_int(a: u64, b: i64,.. UintTy) { + uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_shr(a: u64, b: u64,.. UintTy) { + uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow +}} + +pub_fn_checked_op!{ const_uint_checked_shr_via_int(a: u64, b: i64,.. UintTy) { + uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow +}} + pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, e: &Expr, - ty_hint: Option>) - -> Result { - fn fromb(b: bool) -> Result { Ok(const_int(b as i64)) } + ty_hint: Option>) -> EvalResult { + fn fromb(b: bool) -> const_val { const_int(b as i64) } let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e)); - match e.node { + // If type of expression itself is int or uint, normalize in these + // bindings so that isize/usize is mapped to a type with an + // inherently known bitwidth. + let expr_int_type = ety.and_then(|ty| { + if let ty::ty_int(t) = ty.sty { + Some(IntTy::from(tcx, t)) } else { None } + }); + let expr_uint_type = ety.and_then(|ty| { + if let ty::ty_uint(t) = ty.sty { + Some(UintTy::from(tcx, t)) } else { None } + }); + + let result = match e.node { ast::ExprUnary(ast::UnNeg, ref inner) => { - match eval_const_expr_partial(tcx, &**inner, ety) { - Ok(const_float(f)) => Ok(const_float(-f)), - Ok(const_int(i)) => Ok(const_int(-i)), - Ok(const_uint(i)) => Ok(const_uint(-i)), - Ok(const_str(_)) => Err("negate on string".to_string()), - Ok(const_bool(_)) => Err("negate on boolean".to_string()), - ref err => ((*err).clone()) + match try!(eval_const_expr_partial(tcx, &**inner, ety)) { + const_float(f) => const_float(-f), + const_int(n) => try!(const_int_checked_neg(n, e, expr_int_type)), + const_uint(i) => { + if !tcx.sess.features.borrow().negate_unsigned { + feature_gate::emit_feature_err( + &tcx.sess.parse_sess.span_diagnostic, + "negate_unsigned", + e.span, + "unary negation of unsigned integers may be removed in the future"); + } + try!(const_uint_checked_neg(i, e, expr_uint_type)) + } + const_str(_) => signal!(e, NegateOnString), + const_bool(_) => signal!(e, NegateOnBoolean), + const_binary(_) => signal!(e, NegateOnBinary), + const_val::Tuple(_) => signal!(e, NegateOnTuple), + const_val::Struct(..) => signal!(e, NegateOnStruct), } } ast::ExprUnary(ast::UnNot, ref inner) => { - match eval_const_expr_partial(tcx, &**inner, ety) { - Ok(const_int(i)) => Ok(const_int(!i)), - Ok(const_uint(i)) => Ok(const_uint(!i)), - Ok(const_bool(b)) => Ok(const_bool(!b)), - _ => Err("not on float or string".to_string()) + match try!(eval_const_expr_partial(tcx, &**inner, ety)) { + const_int(i) => const_int(!i), + const_uint(i) => const_uint(!i), + const_bool(b) => const_bool(!b), + const_str(_) => signal!(e, NotOnString), + const_float(_) => signal!(e, NotOnFloat), + const_binary(_) => signal!(e, NotOnBinary), + const_val::Tuple(_) => signal!(e, NotOnTuple), + const_val::Struct(..) => signal!(e, NotOnStruct), } } ast::ExprBinary(op, ref a, ref b) => { let b_ty = match op.node { - ast::BiShl | ast::BiShr => Some(tcx.types.uint), + ast::BiShl | ast::BiShr => Some(tcx.types.usize), _ => ety }; - match (eval_const_expr_partial(tcx, &**a, ety), - eval_const_expr_partial(tcx, &**b, b_ty)) { - (Ok(const_float(a)), Ok(const_float(b))) => { + match (try!(eval_const_expr_partial(tcx, &**a, ety)), + try!(eval_const_expr_partial(tcx, &**b, b_ty))) { + (const_float(a), const_float(b)) => { match op.node { - ast::BiAdd => Ok(const_float(a + b)), - ast::BiSub => Ok(const_float(a - b)), - ast::BiMul => Ok(const_float(a * b)), - ast::BiDiv => Ok(const_float(a / b)), - ast::BiRem => Ok(const_float(a % b)), + ast::BiAdd => const_float(a + b), + ast::BiSub => const_float(a - b), + ast::BiMul => const_float(a * b), + ast::BiDiv => const_float(a / b), + ast::BiRem => const_float(a % b), ast::BiEq => fromb(a == b), ast::BiLt => fromb(a < b), ast::BiLe => fromb(a <= b), ast::BiNe => fromb(a != b), ast::BiGe => fromb(a >= b), ast::BiGt => fromb(a > b), - _ => Err("can't do this op on floats".to_string()) + _ => signal!(e, InvalidOpForFloats(op.node)) } } - (Ok(const_int(a)), Ok(const_int(b))) => { - let is_a_min_value = |&:| { - let int_ty = match ty::expr_ty_opt(tcx, e).map(|ty| &ty.sty) { - Some(&ty::ty_int(int_ty)) => int_ty, - _ => return false - }; - let int_ty = if let ast::TyIs(_) = int_ty { - tcx.sess.target.int_type - } else { - int_ty - }; - match int_ty { - ast::TyI8 => (a as i8) == i8::MIN, - ast::TyI16 => (a as i16) == i16::MIN, - ast::TyI32 => (a as i32) == i32::MIN, - ast::TyI64 => (a as i64) == i64::MIN, - ast::TyIs(_) => unreachable!() - } - }; + (const_int(a), const_int(b)) => { match op.node { - ast::BiAdd => Ok(const_int(a + b)), - ast::BiSub => Ok(const_int(a - b)), - ast::BiMul => Ok(const_int(a * b)), - ast::BiDiv => { - if b == 0 { - Err("attempted to divide by zero".to_string()) - } else if b == -1 && is_a_min_value() { - Err("attempted to divide with overflow".to_string()) - } else { - Ok(const_int(a / b)) - } - } - ast::BiRem => { - if b == 0 { - Err("attempted remainder with a divisor of zero".to_string()) - } else if b == -1 && is_a_min_value() { - Err("attempted remainder with overflow".to_string()) - } else { - Ok(const_int(a % b)) - } - } - ast::BiAnd | ast::BiBitAnd => Ok(const_int(a & b)), - ast::BiOr | ast::BiBitOr => Ok(const_int(a | b)), - ast::BiBitXor => Ok(const_int(a ^ b)), - ast::BiShl => Ok(const_int(a << b as uint)), - ast::BiShr => Ok(const_int(a >> b as uint)), + ast::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)), + ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)), + ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)), + ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)), + ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)), + ast::BiAnd | ast::BiBitAnd => const_int(a & b), + ast::BiOr | ast::BiBitOr => const_int(a | b), + ast::BiBitXor => const_int(a ^ b), + ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)), + ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)), ast::BiEq => fromb(a == b), ast::BiLt => fromb(a < b), ast::BiLe => fromb(a <= b), @@ -317,25 +667,18 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, ast::BiGt => fromb(a > b) } } - (Ok(const_uint(a)), Ok(const_uint(b))) => { + (const_uint(a), const_uint(b)) => { match op.node { - ast::BiAdd => Ok(const_uint(a + b)), - ast::BiSub => Ok(const_uint(a - b)), - ast::BiMul => Ok(const_uint(a * b)), - ast::BiDiv if b == 0 => { - Err("attempted to divide by zero".to_string()) - } - ast::BiDiv => Ok(const_uint(a / b)), - ast::BiRem if b == 0 => { - Err("attempted remainder with a divisor of \ - zero".to_string()) - } - ast::BiRem => Ok(const_uint(a % b)), - ast::BiAnd | ast::BiBitAnd => Ok(const_uint(a & b)), - ast::BiOr | ast::BiBitOr => Ok(const_uint(a | b)), - ast::BiBitXor => Ok(const_uint(a ^ b)), - ast::BiShl => Ok(const_uint(a << b as uint)), - ast::BiShr => Ok(const_uint(a >> b as uint)), + ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)), + ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)), + ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)), + ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)), + ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)), + ast::BiAnd | ast::BiBitAnd => const_uint(a & b), + ast::BiOr | ast::BiBitOr => const_uint(a | b), + ast::BiBitXor => const_uint(a ^ b), + ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)), + ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)), ast::BiEq => fromb(a == b), ast::BiLt => fromb(a < b), ast::BiLe => fromb(a <= b), @@ -345,22 +688,22 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, } } // shifts can have any integral type as their rhs - (Ok(const_int(a)), Ok(const_uint(b))) => { + (const_int(a), const_uint(b)) => { match op.node { - ast::BiShl => Ok(const_int(a << b as uint)), - ast::BiShr => Ok(const_int(a >> b as uint)), - _ => Err("can't do this op on an int and uint".to_string()) + ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)), + ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)), + _ => signal!(e, InvalidOpForIntUint(op.node)), } } - (Ok(const_uint(a)), Ok(const_int(b))) => { + (const_uint(a), const_int(b)) => { match op.node { - ast::BiShl => Ok(const_uint(a << b as uint)), - ast::BiShr => Ok(const_uint(a >> b as uint)), - _ => Err("can't do this op on a uint and int".to_string()) + ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)), + ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)), + _ => signal!(e, InvalidOpForUintInt(op.node)), } } - (Ok(const_bool(a)), Ok(const_bool(b))) => { - Ok(const_bool(match op.node { + (const_bool(a), const_bool(b)) => { + const_bool(match op.node { ast::BiAnd => a && b, ast::BiOr => a || b, ast::BiBitXor => a ^ b, @@ -368,10 +711,11 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, ast::BiBitOr => a | b, ast::BiEq => a == b, ast::BiNe => a != b, - _ => return Err("can't do this op on bools".to_string()) - })) + _ => signal!(e, InvalidOpForBools(op.node)), + }) } - _ => Err("bad operands for binary".to_string()) + + _ => signal!(e, MiscBinaryOp), } } ast::ExprCast(ref base, ref target_ty) => { @@ -383,13 +727,21 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, tcx.sess.span_fatal(target_ty.span, "target type not found for const cast") }); + // Prefer known type to noop, but always have a type hint. + // + // FIXME (#23833): the type-hint can cause problems, + // e.g. `(i8::MAX + 1_i8) as u32` feeds in `u32` as result + // type to the sum, and thus no overflow is signaled. let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety); let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint))); - cast_const(val, ety) + match cast_const(tcx, val, ety) { + Ok(val) => val, + Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }), + } } - ast::ExprPath(_) | ast::ExprQPath(_) => { - let opt_def = tcx.def_map.borrow().get(&e.id).cloned(); + ast::ExprPath(..) => { + let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); let (const_expr, const_ty) = match opt_def { Some(def::DefConst(def_id)) => { if ast_util::is_local(def_id) { @@ -413,87 +765,117 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, }; let const_expr = match const_expr { Some(actual_e) => actual_e, - None => return Err("non-constant path in constant expr".to_string()) + None => signal!(e, NonConstPath) }; let ety = ety.or_else(|| const_ty.and_then(|ty| ast_ty_to_prim_ty(tcx, ty))); - eval_const_expr_partial(tcx, const_expr, ety) + try!(eval_const_expr_partial(tcx, const_expr, ety)) } ast::ExprLit(ref lit) => { - Ok(lit_to_const(&**lit, ety)) + lit_to_const(&**lit, ety) } - ast::ExprParen(ref e) => eval_const_expr_partial(tcx, &**e, ety), + ast::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ety)), ast::ExprBlock(ref block) => { match block.expr { - Some(ref expr) => eval_const_expr_partial(tcx, &**expr, ety), - None => Ok(const_int(0i64)) + Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ety)), + None => const_int(0) } } + ast::ExprTup(_) => { + const_val::Tuple(e.id) + } + ast::ExprStruct(..) => { + const_val::Struct(e.id) + } ast::ExprTupField(ref base, index) => { - // Get the base tuple if it is constant - if let Some(&ast::ExprTup(ref fields)) = lookup_const(tcx, &**base).map(|s| &s.node) { - // Check that the given index is within bounds and evaluate its value - if fields.len() > index.node { - return eval_const_expr_partial(tcx, &*fields[index.node], None) + if let Ok(c) = eval_const_expr_partial(tcx, base, None) { + if let const_val::Tuple(tup_id) = c { + if let ast::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node { + if index.node < fields.len() { + return eval_const_expr_partial(tcx, &fields[index.node], None) + } else { + signal!(e, TupleIndexOutOfBounds); + } + } else { + unreachable!() + } } else { - return Err("tuple index out of bounds".to_string()) + signal!(base, ExpectedConstTuple); } + } else { + signal!(base, NonConstPath) } - - Err("non-constant struct in constant expr".to_string()) } ast::ExprField(ref base, field_name) => { // Get the base expression if it is a struct and it is constant - if let Some(&ast::ExprStruct(_, ref fields, _)) = lookup_const(tcx, &**base) - .map(|s| &s.node) { - // Check that the given field exists and evaluate it - if let Some(f) = fields.iter().find(|f| - f.ident.node.as_str() == field_name.node.as_str()) { - return eval_const_expr_partial(tcx, &*f.expr, None) + if let Ok(c) = eval_const_expr_partial(tcx, base, None) { + if let const_val::Struct(struct_id) = c { + if let ast::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node { + // Check that the given field exists and evaluate it + if let Some(f) = fields.iter().find(|f| f.ident.node.as_str() + == field_name.node.as_str()) { + return eval_const_expr_partial(tcx, &*f.expr, None) + } else { + signal!(e, MissingStructField); + } + } else { + unreachable!() + } } else { - return Err("nonexistent struct field".to_string()) + signal!(base, ExpectedConstStruct); } + } else { + signal!(base, NonConstPath); } - - Err("non-constant struct in constant expr".to_string()) } - _ => Err("unsupported constant expr".to_string()) - } + _ => signal!(e, MiscCatchAll) + }; + + Ok(result) } -fn cast_const(val: const_val, ty: Ty) -> Result { - macro_rules! define_casts { - ($($ty_pat:pat => ( - $intermediate_ty:ty, - $const_type:ident, - $target_ty:ty - )),*) => (match ty.sty { - $($ty_pat => { - match val { - const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)), - const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)), - const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)), - const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)), - _ => Err(concat!("can't cast this type to ", - stringify!($const_type)).to_string()) - } - },)* - _ => Err("can't cast this type".to_string()) - }) +fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult { + macro_rules! convert_val { + ($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => { + match val { + const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)), + const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)), + const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)), + const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)), + _ => Err(ErrKind::CannotCastTo(stringify!($const_type))), + } + } + } + + // Issue #23890: If isize/usize, then dispatch to appropriate target representation type + match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) { + (&ty::ty_int(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, const_int, i64), + (&ty::ty_int(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, const_int, i64), + (&ty::ty_int(ast::TyIs), _, _) => panic!("unexpected target.int_type"), + + (&ty::ty_uint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, const_uint, u64), + (&ty::ty_uint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, const_uint, u64), + (&ty::ty_uint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"), + + _ => {} } - define_casts!{ - ty::ty_int(ast::TyIs(_)) => (int, const_int, i64), - ty::ty_int(ast::TyI8) => (i8, const_int, i64), - ty::ty_int(ast::TyI16) => (i16, const_int, i64), - ty::ty_int(ast::TyI32) => (i32, const_int, i64), - ty::ty_int(ast::TyI64) => (i64, const_int, i64), - ty::ty_uint(ast::TyUs(_)) => (uint, const_uint, u64), - ty::ty_uint(ast::TyU8) => (u8, const_uint, u64), - ty::ty_uint(ast::TyU16) => (u16, const_uint, u64), - ty::ty_uint(ast::TyU32) => (u32, const_uint, u64), - ty::ty_uint(ast::TyU64) => (u64, const_uint, u64), - ty::ty_float(ast::TyF32) => (f32, const_float, f64), - ty::ty_float(ast::TyF64) => (f64, const_float, f64) + match ty.sty { + ty::ty_int(ast::TyIs) => unreachable!(), + ty::ty_uint(ast::TyUs) => unreachable!(), + + ty::ty_int(ast::TyI8) => convert_val!(i8, const_int, i64), + ty::ty_int(ast::TyI16) => convert_val!(i16, const_int, i64), + ty::ty_int(ast::TyI32) => convert_val!(i32, const_int, i64), + ty::ty_int(ast::TyI64) => convert_val!(i64, const_int, i64), + + ty::ty_uint(ast::TyU8) => convert_val!(u8, const_uint, u64), + ty::ty_uint(ast::TyU16) => convert_val!(u16, const_uint, u64), + ty::ty_uint(ast::TyU32) => convert_val!(u32, const_uint, u64), + ty::ty_uint(ast::TyU64) => convert_val!(u64, const_uint, u64), + + ty::ty_float(ast::TyF32) => convert_val!(f32, const_float, f64), + ty::ty_float(ast::TyF64) => convert_val!(f64, const_float, f64), + _ => Err(ErrKind::CannotCast), } } @@ -551,15 +933,15 @@ pub fn compare_lit_exprs<'tcx>(tcx: &ty::ctxt<'tcx>, -> Option { let a = match eval_const_expr_partial(tcx, a, ty_hint) { Ok(a) => a, - Err(s) => { - tcx.sess.span_err(a.span, &s[..]); + Err(e) => { + tcx.sess.span_err(a.span, &e.description()); return None; } }; let b = match eval_const_expr_partial(tcx, b, ty_hint) { Ok(b) => b, - Err(s) => { - tcx.sess.span_err(b.span, &s[..]); + Err(e) => { + tcx.sess.span_err(b.span, &e.description()); return None; } }; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 085d5cbc34..f69ac03052 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -19,7 +19,7 @@ pub use self::EntryOrExit::*; use middle::cfg; use middle::cfg::CFGIndex; use middle::ty; -use std::old_io; +use std::io; use std::usize; use std::iter::repeat; use syntax::ast; @@ -28,7 +28,7 @@ use syntax::visit; use syntax::print::{pp, pprust}; use util::nodemap::NodeMap; -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum EntryOrExit { Entry, Exit, @@ -45,15 +45,15 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> { oper: O, /// number of bits to propagate per id - bits_per_id: uint, + bits_per_id: usize, /// number of words we will use to store bits_per_id. /// equal to bits_per_id/usize::BITS rounded up. - words_per_id: uint, + words_per_id: usize, // mapping from node to cfg node index // FIXME (#6298): Shouldn't this go with CFG? - nodeid_to_index: NodeMap, + nodeid_to_index: NodeMap>, // Bit sets per cfg node. The following three fields (`gens`, `kills`, // and `on_entry`) all have the same structure. For each id in @@ -62,19 +62,19 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> { // the full vector (see the method `compute_id_range()`). /// bits generated as we exit the cfg node. Updated by `add_gen()`. - gens: Vec, + gens: Vec, /// bits killed as we exit the cfg node. Updated by `add_kill()`. - kills: Vec, + kills: Vec, /// bits that are valid on entry to the cfg node. Updated by /// `propagate()`. - on_entry: Vec, + on_entry: Vec, } pub trait BitwiseOperator { /// Joins two predecessor bits together, typically either `|` or `&` - fn join(&self, succ: uint, pred: uint) -> uint; + fn join(&self, succ: usize, pred: usize) -> usize; } /// Parameterization for the precise form of data flow that is used. @@ -88,11 +88,9 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> { changed: bool } -fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap) -> CFGIndex { - let opt_cfgindex = index.get(&id).cloned(); - opt_cfgindex.unwrap_or_else(|| { - panic!("nodeid_to_index does not have entry for NodeId {}", id); - }) +fn get_cfg_indices<'a>(id: ast::NodeId, index: &'a NodeMap>) -> &'a [CFGIndex] { + let opt_indices = index.get(&id); + opt_indices.map(|v| &v[..]).unwrap_or(&[]) } impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { @@ -105,18 +103,22 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> { fn pre(&self, ps: &mut pprust::State, - node: pprust::AnnNode) -> old_io::IoResult<()> { + node: pprust::AnnNode) -> io::Result<()> { let id = match node { pprust::NodeIdent(_) | pprust::NodeName(_) => 0, pprust::NodeExpr(expr) => expr.id, pprust::NodeBlock(blk) => blk.id, - pprust::NodeItem(_) => 0, + pprust::NodeItem(_) | pprust::NodeSubItem(_) => 0, pprust::NodePat(pat) => pat.id }; - if self.has_bitset_for_nodeid(id) { - assert!(self.bits_per_id > 0); - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); + if !self.has_bitset_for_nodeid(id) { + return Ok(()); + } + + assert!(self.bits_per_id > 0); + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { let (start, end) = self.compute_id_range(cfgidx); let on_entry = &self.on_entry[start.. end]; let entry_str = bits_to_string(on_entry); @@ -144,7 +146,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O } fn build_nodeid_to_index(decl: Option<&ast::FnDecl>, - cfg: &cfg::CFG) -> NodeMap { + cfg: &cfg::CFG) -> NodeMap> { let mut index = NodeMap(); // FIXME (#6298): Would it be better to fold formals from decl @@ -157,28 +159,28 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>, } cfg.graph.each_node(|node_idx, node| { - if node.data.id != ast::DUMMY_NODE_ID { - index.insert(node.data.id, node_idx); + if let cfg::CFGNodeData::AST(id) = node.data { + index.entry(id).or_insert(vec![]).push(node_idx); } true }); return index; - fn add_entries_from_fn_decl(index: &mut NodeMap, + fn add_entries_from_fn_decl(index: &mut NodeMap>, decl: &ast::FnDecl, entry: CFGIndex) { //! add mappings from the ast nodes for the formal bindings to //! the entry-node in the graph. struct Formals<'a> { entry: CFGIndex, - index: &'a mut NodeMap, + index: &'a mut NodeMap>, } let mut formals = Formals { entry: entry, index: index }; visit::walk_fn_decl(&mut formals, decl); impl<'a, 'v> visit::Visitor<'v> for Formals<'a> { fn visit_pat(&mut self, p: &ast::Pat) { - self.index.insert(p.id, self.entry); + self.index.entry(p.id).or_insert(vec![]).push(self.entry); visit::walk_pat(self, p) } } @@ -192,8 +194,8 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { cfg: &cfg::CFG, oper: O, id_range: IdRange, - bits_per_id: uint) -> DataFlowContext<'a, 'tcx, O> { - let words_per_id = (bits_per_id + usize::BITS - 1) / usize::BITS; + bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> { + let words_per_id = (bits_per_id + usize::BITS as usize - 1) / usize::BITS as usize; let num_nodes = cfg.graph.all_nodes().len(); debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \ @@ -223,33 +225,37 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } } - pub fn add_gen(&mut self, id: ast::NodeId, bit: uint) { + pub fn add_gen(&mut self, id: ast::NodeId, bit: usize) { //! Indicates that `id` generates `bit` debug!("{} add_gen(id={}, bit={})", self.analysis_name, id, bit); assert!(self.nodeid_to_index.contains_key(&id)); assert!(self.bits_per_id > 0); - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range(cfgidx); - let gens = &mut self.gens[start.. end]; - set_bit(gens, bit); + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + let (start, end) = self.compute_id_range(cfgidx); + let gens = &mut self.gens[start.. end]; + set_bit(gens, bit); + } } - pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) { + pub fn add_kill(&mut self, id: ast::NodeId, bit: usize) { //! Indicates that `id` kills `bit` debug!("{} add_kill(id={}, bit={})", self.analysis_name, id, bit); assert!(self.nodeid_to_index.contains_key(&id)); assert!(self.bits_per_id > 0); - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range(cfgidx); - let kills = &mut self.kills[start.. end]; - set_bit(kills, bit); + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + let (start, end) = self.compute_id_range(cfgidx); + let kills = &mut self.kills[start.. end]; + set_bit(kills, bit); + } } - fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [uint]) { + fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [usize]) { //! Applies the gen and kill sets for `cfgidx` to `bits` debug!("{} apply_gen_kill(cfgidx={:?}, bits={}) [before]", self.analysis_name, cfgidx, mut_bits_to_string(bits)); @@ -265,7 +271,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { self.analysis_name, cfgidx, mut_bits_to_string(bits)); } - fn compute_id_range(&self, cfgidx: CFGIndex) -> (uint, uint) { + fn compute_id_range(&self, cfgidx: CFGIndex) -> (usize, usize) { let n = cfgidx.node_id(); let start = n * self.words_per_id; let end = start + self.words_per_id; @@ -279,20 +285,25 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } - pub fn each_bit_on_entry(&self, id: ast::NodeId, f: F) -> bool where - F: FnMut(uint) -> bool, + pub fn each_bit_on_entry(&self, id: ast::NodeId, mut f: F) -> bool where + F: FnMut(usize) -> bool, { //! Iterates through each bit that is set on entry to `id`. //! Only useful after `propagate()` has been called. if !self.has_bitset_for_nodeid(id) { return true; } - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - self.each_bit_for_node(Entry, cfgidx, f) + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + if !self.each_bit_for_node(Entry, cfgidx, |i| f(i)) { + return false; + } + } + return true; } pub fn each_bit_for_node(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where - F: FnMut(uint) -> bool, + F: FnMut(usize) -> bool, { //! Iterates through each bit that is set on entry/exit to `cfgidx`. //! Only useful after `propagate()` has been called. @@ -320,8 +331,8 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { self.each_bit(slice, f) } - pub fn each_gen_bit(&self, id: ast::NodeId, f: F) -> bool where - F: FnMut(uint) -> bool, + pub fn each_gen_bit(&self, id: ast::NodeId, mut f: F) -> bool where + F: FnMut(usize) -> bool, { //! Iterates through each bit in the gen set for `id`. if !self.has_bitset_for_nodeid(id) { @@ -334,16 +345,21 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { return true; } - let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range(cfgidx); - let gens = &self.gens[start.. end]; - debug!("{} each_gen_bit(id={}, gens={})", - self.analysis_name, id, bits_to_string(gens)); - self.each_bit(gens, f) + let indices = get_cfg_indices(id, &self.nodeid_to_index); + for &cfgidx in indices { + let (start, end) = self.compute_id_range(cfgidx); + let gens = &self.gens[start.. end]; + debug!("{} each_gen_bit(id={}, gens={})", + self.analysis_name, id, bits_to_string(gens)); + if !self.each_bit(gens, |i| f(i)) { + return false; + } + } + return true; } - fn each_bit(&self, words: &[uint], mut f: F) -> bool where - F: FnMut(uint) -> bool, + fn each_bit(&self, words: &[usize], mut f: F) -> bool where + F: FnMut(usize) -> bool, { //! Helper for iterating over the bits in a bit set. //! Returns false on the first call to `f` that returns false; @@ -351,7 +367,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { for (word_index, &word) in words.iter().enumerate() { if word != 0 { - let base_index = word_index * usize::BITS; + let base_index = word_index * usize::BITS as usize; for offset in 0..usize::BITS { let bit = 1 << offset; if (word & bit) != 0 { @@ -364,7 +380,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { // whether the bit_index is greater than the // actual value the user specified and stop // iterating if so. - let bit_index = base_index + offset; + let bit_index = base_index + offset as usize; if bit_index >= self.bits_per_id { return true; } else if !f(bit_index) { @@ -400,13 +416,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let mut changed = false; for &node_id in &edge.data.exiting_scopes { - let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned(); + let opt_cfg_idx = self.nodeid_to_index.get(&node_id); match opt_cfg_idx { - Some(cfg_idx) => { - let (start, end) = self.compute_id_range(cfg_idx); - let kills = &self.kills[start.. end]; - if bitwise(&mut orig_kills, kills, &Union) { - changed = true; + Some(indices) => { + for &cfg_idx in indices { + let (start, end) = self.compute_id_range(cfg_idx); + let kills = &self.kills[start.. end]; + if bitwise(&mut orig_kills, kills, &Union) { + changed = true; + } } } None => { @@ -457,13 +475,15 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { debug!("Dataflow result for {}:", self.analysis_name); debug!("{}", { - self.pretty_print_to(box old_io::stderr(), blk).unwrap(); + let mut v = Vec::new(); + self.pretty_print_to(box &mut v, blk).unwrap(); + println!("{}", String::from_utf8(v).unwrap()); "" }); } - fn pretty_print_to(&self, wr: Box, - blk: &ast::Block) -> old_io::IoResult<()> { + fn pretty_print_to<'b>(&self, wr: Box, + blk: &ast::Block) -> io::Result<()> { let mut ps = pprust::rust_printer_annotated(wr, self); try!(ps.cbox(pprust::indent_unit)); try!(ps.ibox(0)); @@ -475,14 +495,14 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> { impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { fn walk_cfg(&mut self, cfg: &cfg::CFG, - in_out: &mut [uint]) { + in_out: &mut [usize]) { debug!("DataFlowContext::walk_cfg(in_out={}) {}", bits_to_string(in_out), self.dfcx.analysis_name); assert!(self.dfcx.bits_per_id > 0); cfg.graph.each_node(|node_index, node| { debug!("DataFlowContext::walk_cfg idx={:?} id={} begin in_out={}", - node_index, node.data.id, bits_to_string(in_out)); + node_index, node.data.id(), bits_to_string(in_out)); let (start, end) = self.dfcx.compute_id_range(node_index); @@ -499,7 +519,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { }); } - fn reset(&mut self, bits: &mut [uint]) { + fn reset(&mut self, bits: &mut [usize]) { let e = if self.dfcx.oper.initial_value() {usize::MAX} else {0}; for b in bits { *b = e; @@ -507,7 +527,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { } fn propagate_bits_into_graph_successors_of(&mut self, - pred_bits: &[uint], + pred_bits: &[usize], cfg: &cfg::CFG, cfgidx: CFGIndex) { cfg.graph.each_outgoing_edge(cfgidx, |_e_idx, edge| { @@ -517,7 +537,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { } fn propagate_bits_into_entry_set_for(&mut self, - pred_bits: &[uint], + pred_bits: &[usize], edge: &cfg::CFGEdge) { let source = edge.source(); let cfgidx = edge.target(); @@ -540,11 +560,11 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { } } -fn mut_bits_to_string(words: &mut [uint]) -> String { +fn mut_bits_to_string(words: &mut [usize]) -> String { bits_to_string(words) } -fn bits_to_string(words: &[uint]) -> String { +fn bits_to_string(words: &[usize]) -> String { let mut result = String::new(); let mut sep = '['; @@ -554,7 +574,7 @@ fn bits_to_string(words: &[uint]) -> String { let mut v = word; for _ in 0..usize::BYTES { result.push(sep); - result.push_str(&format!("{:02x}", v & 0xFF)[]); + result.push_str(&format!("{:02x}", v & 0xFF)); v >>= 8; sep = '-'; } @@ -564,8 +584,8 @@ fn bits_to_string(words: &[uint]) -> String { } #[inline] -fn bitwise(out_vec: &mut [uint], - in_vec: &[uint], +fn bitwise(out_vec: &mut [usize], + in_vec: &[usize], op: &Op) -> bool { assert_eq!(out_vec.len(), in_vec.len()); let mut changed = false; @@ -578,11 +598,11 @@ fn bitwise(out_vec: &mut [uint], changed } -fn set_bit(words: &mut [uint], bit: uint) -> bool { +fn set_bit(words: &mut [usize], bit: usize) -> bool { debug!("set_bit: words={} bit={}", mut_bits_to_string(words), bit_str(bit)); - let word = bit / usize::BITS; - let bit_in_word = bit % usize::BITS; + let word = bit / usize::BITS as usize; + let bit_in_word = bit % usize::BITS as usize; let bit_mask = 1 << bit_in_word; debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, word); let oldv = words[word]; @@ -591,7 +611,7 @@ fn set_bit(words: &mut [uint], bit: uint) -> bool { oldv != newv } -fn bit_str(bit: uint) -> String { +fn bit_str(bit: usize) -> String { let byte = bit >> 8; let lobits = 1 << (bit & 0xFF); format!("[{}:{}-{:02x}]", bit, byte, lobits) @@ -599,9 +619,9 @@ fn bit_str(bit: uint) -> String { struct Union; impl BitwiseOperator for Union { - fn join(&self, a: uint, b: uint) -> uint { a | b } + fn join(&self, a: usize, b: usize) -> usize { a | b } } struct Subtract; impl BitwiseOperator for Subtract { - fn join(&self, a: uint, b: uint) -> uint { a & !b } + fn join(&self, a: usize, b: usize) -> usize { a & !b } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ff78deb8d1..568375597c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -18,7 +18,7 @@ use util::nodemap::NodeSet; use std::collections::HashSet; use syntax::{ast, ast_map, codemap}; -use syntax::ast_util::{local_def, is_local, PostExpansionMethod}; +use syntax::ast_util::{local_def, is_local}; use syntax::attr::{self, AttrMetaMethods}; use syntax::visit::{self, Visitor}; @@ -71,13 +71,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { self.tcx.def_map.borrow().get(id).map(|def| { - match def { - &def::DefConst(_) => { + match def.full_def() { + def::DefConst(_) => { self.check_def_id(def.def_id()) } _ if self.ignore_non_const_paths => (), - &def::DefPrimTy(_) => (), - &def::DefVariant(enum_id, variant_id, _) => { + def::DefPrimTy(_) => (), + def::DefVariant(enum_id, variant_id, _) => { self.check_def_id(enum_id); self.check_def_id(variant_id); } @@ -145,7 +145,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: uint) { + fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: usize) { match ty::expr_ty_adjusted(self.tcx, lhs).sty { ty::ty_struct(id, _) => { let fields = ty::lookup_struct_fields(self.tcx, id); @@ -158,7 +158,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[codemap::Spanned]) { - let id = match (*self.tcx.def_map.borrow())[lhs.id] { + let id = match self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def() { def::DefVariant(_, id, _) => id, _ => { match ty::ty_to_def_id(ty::node_id_to_type(self.tcx, @@ -228,16 +228,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ => () } } - ast_map::NodeTraitItem(trait_method) => { - visit::walk_trait_item(self, trait_method); + ast_map::NodeTraitItem(trait_item) => { + visit::walk_trait_item(self, trait_item); } ast_map::NodeImplItem(impl_item) => { - match *impl_item { - ast::MethodImplItem(ref method) => { - visit::walk_method_helper(self, method); - } - ast::TypeImplItem(_) => {} - } + visit::walk_impl_item(self, impl_item); } ast_map::NodeForeignItem(foreign_item) => { visit::walk_foreign_item(self, &*foreign_item); @@ -355,13 +350,29 @@ impl<'v> Visitor<'v> for LifeSeeder { 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::ItemTrait(_, _, _, ref trait_items) => { + for trait_item in trait_items { + match trait_item.node { + ast::MethodTraitItem(_, Some(_)) => { + if has_allow_dead_code_or_lang_attr(&trait_item.attrs) { + self.worklist.push(trait_item.id); + } + } + _ => {} + } + } + } + ast::ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => { for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - self.worklist.push(method.id); + match impl_item.node { + ast::MethodImplItem(..) => { + if opt_trait.is_some() || + has_allow_dead_code_or_lang_attr(&impl_item.attrs) { + self.worklist.push(impl_item.id); + } } ast::TypeImplItem(_) => {} + ast::MacImplItem(_) => panic!("unexpanded macro") } } } @@ -369,21 +380,6 @@ impl<'v> Visitor<'v> for LifeSeeder { } visit::walk_item(self, item); } - - fn visit_fn(&mut self, fk: visit::FnKind<'v>, - _: &'v ast::FnDecl, block: &'v ast::Block, - _: codemap::Span, id: ast::NodeId) { - // Check for method here because methods are not ast::Item - match fk { - visit::FkMethod(_, _, method) => { - if has_allow_dead_code_or_lang_attr(&method.attrs) { - self.worklist.push(id); - } - } - _ => () - } - visit::walk_block(self, block); - } } fn create_and_seed_worklist(tcx: &ty::ctxt, @@ -500,7 +496,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { None => (), Some(impl_list) => { for impl_did in &**impl_list { - for item_did in &(*impl_items)[*impl_did] { + for item_did in &*impl_items.get(impl_did).unwrap() { if self.live_symbols.contains(&item_did.def_id() .node) { return true; @@ -561,7 +557,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { span: codemap::Span, id: ast::NodeId) { // Have to warn method here because methods are not ast::Item match fk { - visit::FkMethod(name, _, _) => { + visit::FkMethod(name, _) => { if !self.symbol_is_live(id, None) { self.warn_dead_code(id, span, name, "method"); } @@ -582,12 +578,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { // Overwrite so that we don't warn the trait method itself. fn visit_trait_item(&mut self, trait_method: &ast::TraitItem) { - match *trait_method { - ast::ProvidedMethod(ref method) => { - visit::walk_block(self, &*method.pe_body()) + match trait_method.node { + ast::MethodTraitItem(_, Some(ref body)) => { + visit::walk_block(self, body) } - ast::RequiredMethod(_) => {} - ast::TypeTraitItem(_) => {} + ast::MethodTraitItem(_, None) | + ast::TypeTraitItem(..) => {} } } } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 7857bcad81..6707a4d3fd 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -10,10 +10,9 @@ pub use self::Def::*; pub use self::MethodProvenance::*; -pub use self::TraitItemKind::*; +use middle::privacy::LastPrivate; use middle::subst::ParamSpace; -use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory}; use util::nodemap::NodeMap; use syntax::ast; use syntax::ast_util::local_def; @@ -23,7 +22,6 @@ use std::cell::RefCell; #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Def { DefFn(ast::DefId, bool /* is_ctor */), - DefStaticMethod(/* method */ ast::DefId, MethodProvenance), DefSelfTy(/* trait id */ ast::NodeId), DefMod(ast::DefId), DefForeignMod(ast::DefId), @@ -32,12 +30,7 @@ pub enum Def { DefLocal(ast::NodeId), DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), DefTy(ast::DefId, bool /* is_enum */), - DefAssociatedTy(ast::DefId), - // A partially resolved path to an associated type `T::U` where `T` is a concrete - // type (indicated by the DefId) which implements a trait which has an associated - // type `U` (indicated by the Ident). - // FIXME(#20301) -- should use Name - DefAssociatedPath(TyParamProvenance, ast::Ident), + DefAssociatedTy(ast::DefId /* trait */, ast::DefId), DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), DefTyParam(ParamSpace, u32, ast::DefId, ast::Name), @@ -54,19 +47,64 @@ pub enum Def { /// - If it's an ExprPath referring to some tuple struct, then DefMap maps /// it to a def whose id is the StructDef.ctor_id. DefStruct(ast::DefId), - DefTyParamBinder(ast::NodeId), /* struct, impl or trait with ty params */ DefRegion(ast::NodeId), DefLabel(ast::NodeId), - DefMethod(ast::DefId /* method */, Option /* trait */, MethodProvenance), + DefMethod(ast::DefId /* method */, MethodProvenance), +} + +/// The result of resolving a path. +/// Before type checking completes, `depth` represents the number of +/// trailing segments which are yet unresolved. Afterwards, if there +/// were no errors, all paths should be fully resolved, with `depth` +/// set to `0` and `base_def` representing the final resolution. +/// +/// module::Type::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_def depth = 3 +/// +/// ::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_def depth = 2 +#[derive(Copy, Clone, Debug)] +pub struct PathResolution { + pub base_def: Def, + pub last_private: LastPrivate, + pub depth: usize +} + +impl PathResolution { + /// Get the definition, if fully resolved, otherwise panic. + pub fn full_def(&self) -> Def { + if self.depth != 0 { + panic!("path not fully resolved: {:?}", self); + } + self.base_def + } + + /// Get the DefId, if fully resolved, otherwise panic. + pub fn def_id(&self) -> ast::DefId { + self.full_def().def_id() + } + + pub fn new(base_def: Def, + last_private: LastPrivate, + depth: usize) + -> PathResolution { + PathResolution { + base_def: base_def, + last_private: last_private, + depth: depth, + } + } } // Definition mapping -pub type DefMap = RefCell>; +pub type DefMap = RefCell>; // This is the replacement export map. It maps a module to all of the exports // within. pub type ExportMap = NodeMap>; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Export { pub name: ast::Name, // The name of the target. pub def_id: ast::DefId, // The definition of the target. @@ -78,12 +116,6 @@ pub enum MethodProvenance { FromImpl(ast::DefId), } -#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TyParamProvenance { - FromSelf(ast::DefId), - FromParam(ast::DefId), -} - impl MethodProvenance { pub fn map(self, f: F) -> MethodProvenance where F: FnOnce(ast::DefId) -> ast::DefId, @@ -95,34 +127,6 @@ impl MethodProvenance { } } -impl TyParamProvenance { - pub fn def_id(&self) -> ast::DefId { - match *self { - TyParamProvenance::FromSelf(ref did) => did.clone(), - TyParamProvenance::FromParam(ref did) => did.clone(), - } - } -} - -#[derive(Clone, Copy, Eq, PartialEq)] -pub enum TraitItemKind { - NonstaticMethodTraitItemKind, - StaticMethodTraitItemKind, - TypeTraitItemKind, -} - -impl TraitItemKind { - pub fn from_explicit_self_category(explicit_self_category: - ExplicitSelfCategory) - -> TraitItemKind { - if explicit_self_category == StaticExplicitSelfCategory { - StaticMethodTraitItemKind - } else { - NonstaticMethodTraitItemKind - } - } -} - impl Def { pub fn local_node_id(&self) -> ast::NodeId { let def_id = self.def_id(); @@ -132,25 +136,21 @@ impl Def { pub fn def_id(&self) -> ast::DefId { match *self { - DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) | - DefForeignMod(id) | DefStatic(id, _) | - DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) | + DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) | + DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) | DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) | - DefMethod(id, _, _) | DefConst(id) | - DefAssociatedPath(TyParamProvenance::FromSelf(id), _) | - DefAssociatedPath(TyParamProvenance::FromParam(id), _) => { + DefMethod(id, _) | DefConst(id) => { id } DefLocal(id) | DefSelfTy(id) | DefUpvar(id, _) | DefRegion(id) | - DefTyParamBinder(id) | DefLabel(id) => { local_def(id) } - DefPrimTy(_) => panic!() + DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy") } } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index ad9f4eade5..0b688e1e08 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -118,7 +118,7 @@ fn calculate_type(sess: &session::Session, let src = sess.cstore.get_used_crate_source(cnum).unwrap(); if src.rlib.is_some() { return } sess.err(&format!("dependency `{}` not found in rlib format", - data.name)[]); + data.name)); }); return Vec::new(); } @@ -172,7 +172,7 @@ fn calculate_type(sess: &session::Session, assert!(src.rlib.is_some()); debug!("adding staticlib: {}", data.name); add_library(sess, cnum, cstore::RequireStatic, &mut formats); - ret[cnum as uint - 1] = Some(cstore::RequireStatic); + ret[cnum as usize - 1] = Some(cstore::RequireStatic); } }); @@ -197,7 +197,7 @@ fn calculate_type(sess: &session::Session, match kind { cstore::RequireStatic => "rlib", cstore::RequireDynamic => "dylib", - })[]); + })); } } } @@ -222,7 +222,7 @@ fn add_library(sess: &session::Session, let data = sess.cstore.get_crate_data(cnum); sess.err(&format!("cannot satisfy dependencies so `{}` only \ shows up once", - data.name)[]); + data.name)); sess.help("having upstream crates all available in one format \ will likely make this go away"); } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index abb8f35f66..814492cbef 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -9,7 +9,7 @@ // except according to those terms. //! Enforces the Rust effect system. Currently there is just one effect, -/// `unsafe`. +//! `unsafe`. use self::UnsafeContext::*; use middle::def; @@ -18,12 +18,11 @@ use middle::ty::MethodCall; use util::ppaux; use syntax::ast; -use syntax::ast_util::PostExpansionMethod; use syntax::codemap::Span; use syntax::visit; use syntax::visit::Visitor; -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum UnsafeContext { SafeContext, UnsafeFn, @@ -90,8 +89,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { let (is_item_fn, is_unsafe_fn) = match fn_kind { visit::FkItemFn(_, _, fn_style, _) => (true, fn_style == ast::Unsafety::Unsafe), - visit::FkMethod(_, _, method) => - (true, method.pe_unsafety() == ast::Unsafety::Unsafe), + visit::FkMethod(_, sig) => + (true, sig.unsafety == ast::Unsafety::Unsafe), _ => (false, false), }; @@ -142,7 +141,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { match expr.node { ast::ExprMethodCall(_, _, _) => { let method_call = MethodCall::expr(expr.id); - let base_type = (*self.tcx.method_map.borrow())[method_call].ty; + let base_type = self.tcx.method_map.borrow().get(&method_call).unwrap().ty; debug!("effect: method call case, base type is {}", ppaux::ty_to_string(self.tcx, base_type)); if type_is_unsafe_function(base_type) { @@ -175,7 +174,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { ast::ExprInlineAsm(..) => { self.require_unsafe(expr.span, "use of inline assembly"); } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) { self.require_unsafe(expr.span, "use of mutable static"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index e99d214742..2fa9c7c8fb 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -94,7 +94,7 @@ pub trait Delegate<'tcx> { mode: MutateMode); } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum LoanCause { ClosureCapture(Span), AddrOf, @@ -106,20 +106,20 @@ pub enum LoanCause { MatchDiscriminant } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum ConsumeMode { Copy, // reference to x where x has a type that copies Move(MoveReason), // reference to x where x has a type that moves } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum MoveReason { DirectRefMove, PatBindingMove, CaptureMove, } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum MatchMode { NonBindingMatch, BorrowingMatch, @@ -127,7 +127,7 @@ pub enum MatchMode { MovingMatch, } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum TrackMatchMode { Unknown, Definite(MatchMode), @@ -194,14 +194,14 @@ impl TrackMatchMode { } } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum MutateMode { Init, JustWrite, // x = y WriteAndRead, // x += y } -#[derive(Copy)] +#[derive(Copy, Clone)] enum OverloadedCallType { FnOverloadedCall, FnMutOverloadedCall, @@ -422,7 +422,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { self.walk_expr(&**subexpr) } - ast::ExprPath(_) | ast::ExprQPath(_) => { } + ast::ExprPath(..) => { } ast::ExprUnary(ast::UnDeref, ref base) => { // *base if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) { @@ -442,7 +442,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], - PassArgs::ByRef) { + PassArgs::ByValue) { self.select_from_expr(&**lhs); self.consume_expr(&**rhs); } @@ -790,7 +790,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { None => { } Some(adjustment) => { match *adjustment { - ty::AdjustReifyFnPointer(..) => { + ty::AdjustReifyFnPointer(..) | + ty::AdjustUnsafeFnPointer(..) => { // Creating a closure/fn-pointer consumes the // input and stores it into the resulting // rvalue. @@ -822,7 +823,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { /// `deref()` is declared with `&self`, this is an autoref of `x`. fn walk_autoderefs(&mut self, expr: &ast::Expr, - autoderefs: uint) { + autoderefs: usize) { debug!("walk_autoderefs expr={} autoderefs={}", expr.repr(self.tcx()), autoderefs); for i in 0..autoderefs { @@ -841,7 +842,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { ty::ty_rptr(r, ref m) => (m.mutbl, r), _ => self.tcx().sess.span_bug(expr.span, &format!("bad overloaded deref type {}", - method_ty.repr(self.tcx()))[]) + method_ty.repr(self.tcx()))) }; let bk = ty::BorrowKind::from_mutbl(m); self.delegate.borrow(expr.id, expr.span, cmt, @@ -854,31 +855,16 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { fn walk_autoref(&mut self, expr: &ast::Expr, autoref: &ty::AutoRef, - n: uint) { + n: usize) { debug!("walk_autoref expr={}", expr.repr(self.tcx())); - // Match for unique trait coercions first, since we don't need the - // call to cat_expr_autoderefd. - match *autoref { - ty::AutoUnsizeUniq(ty::UnsizeVtable(..)) | - ty::AutoUnsize(ty::UnsizeVtable(..)) => { - assert!(n == 1, format!("Expected exactly 1 deref with Uniq \ - AutoRefs, found: {}", n)); - let cmt_unadjusted = - return_if_err!(self.mc.cat_expr_unadjusted(expr)); - self.delegate_consume(expr.id, expr.span, cmt_unadjusted); - return; - } - _ => {} - } - - let cmt_derefd = return_if_err!( - self.mc.cat_expr_autoderefd(expr, n)); - debug!("walk_adjustment: cmt_derefd={}", - cmt_derefd.repr(self.tcx())); - match *autoref { ty::AutoPtr(r, m, _) => { + let cmt_derefd = return_if_err!( + self.mc.cat_expr_autoderefd(expr, n)); + debug!("walk_adjustment: cmt_derefd={}", + cmt_derefd.repr(self.tcx())); + self.delegate.borrow(expr.id, expr.span, cmt_derefd, @@ -886,10 +872,24 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { ty::BorrowKind::from_mutbl(m), AutoRef); } - ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) | ty::AutoUnsafe(..) => {} + ty::AutoUnsize(_) | + ty::AutoUnsizeUniq(_) => { + assert!(n == 1, format!("Expected exactly 1 deref with Uniq \ + AutoRefs, found: {}", n)); + let cmt_unadjusted = + return_if_err!(self.mc.cat_expr_unadjusted(expr)); + self.delegate_consume(expr.id, expr.span, cmt_unadjusted); + } + ty::AutoUnsafe(..) => { + } } } + // When this returns true, it means that the expression *is* a + // method-call (i.e. via the operator-overload). This true result + // also implies that walk_overloaded_operator already took care of + // recursively processing the input arguments, and thus the caller + // should not do so. fn walk_overloaded_operator(&mut self, expr: &ast::Expr, receiver: &ast::Expr, @@ -1017,7 +1017,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { // Each match binding is effectively an assignment to the // binding being produced. - let def = def_map.borrow()[pat.id].clone(); + let def = def_map.borrow().get(&pat.id).unwrap().full_def(); match mc.cat_def(pat.id, pat.span, pat_ty, def) { Ok(binding_cmt) => { delegate.mutate(pat.id, pat.span, binding_cmt, Init); @@ -1097,13 +1097,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { match pat.node { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { - match def_map.get(&pat.id) { + match def_map.get(&pat.id).map(|d| d.full_def()) { None => { // no definition found: pat is not a // struct or enum pattern. } - Some(&def::DefVariant(enum_did, variant_did, _is_struct)) => { + Some(def::DefVariant(enum_did, variant_did, _is_struct)) => { let downcast_cmt = if ty::enum_is_univariant(tcx, enum_did) { cmt_pat @@ -1119,7 +1119,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { delegate.matched_pat(pat, downcast_cmt, match_mode); } - Some(&def::DefStruct(..)) | Some(&def::DefTy(_, false)) => { + Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => { // A struct (in either the value or type // namespace; we encounter the former on // e.g. patterns for unit structs). @@ -1131,14 +1131,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { delegate.matched_pat(pat, cmt_pat, match_mode); } - Some(&def::DefConst(..)) | - Some(&def::DefLocal(..)) => { + Some(def::DefConst(..)) | + Some(def::DefLocal(..)) => { // This is a leaf (i.e. identifier binding // or constant value to match); thus no // `matched_pat` call. } - Some(def @ &def::DefTy(_, true)) => { + Some(def @ def::DefTy(_, true)) => { // An enum's type -- should never be in a // pattern. diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index b33e5a802f..36065aaca5 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -25,11 +25,11 @@ pub enum SimplifiedType { StrSimplifiedType, VecSimplifiedType, PtrSimplifiedType, - TupleSimplifiedType(uint), + TupleSimplifiedType(usize), TraitSimplifiedType(ast::DefId), StructSimplifiedType(ast::DefId), ClosureSimplifiedType(ast::DefId), - FunctionSimplifiedType(uint), + FunctionSimplifiedType(usize), ParameterSimplifiedType, } @@ -74,7 +74,7 @@ pub fn simplify_type(tcx: &ty::ctxt, let def_id = tcx.lang_items.owned_box().unwrap(); Some(StructSimplifiedType(def_id)) } - ty::ty_closure(def_id, _, _) => { + ty::ty_closure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) } ty::ty_tup(ref tys) => { @@ -93,7 +93,6 @@ pub fn simplify_type(tcx: &ty::ctxt, None } } - ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None, + ty::ty_infer(_) | ty::ty_err => None, } } - diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index 436f04fc9e..a9ac61b49e 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -62,33 +62,33 @@ impl Debug for Edge { } #[derive(Clone, Copy, PartialEq, Debug)] -pub struct NodeIndex(pub uint); +pub struct NodeIndex(pub usize); #[allow(non_upper_case_globals)] pub const InvalidNodeIndex: NodeIndex = NodeIndex(usize::MAX); -#[derive(Copy, PartialEq, Debug)] -pub struct EdgeIndex(pub uint); +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct EdgeIndex(pub usize); #[allow(non_upper_case_globals)] pub const InvalidEdgeIndex: EdgeIndex = EdgeIndex(usize::MAX); // Use a private field here to guarantee no more instances are created: -#[derive(Copy, Debug)] -pub struct Direction { repr: uint } +#[derive(Copy, Clone, Debug)] +pub struct Direction { repr: usize } #[allow(non_upper_case_globals)] pub const Outgoing: Direction = Direction { repr: 0 }; #[allow(non_upper_case_globals)] pub const Incoming: Direction = Direction { repr: 1 }; impl NodeIndex { - fn get(&self) -> uint { let NodeIndex(v) = *self; v } + fn get(&self) -> usize { let NodeIndex(v) = *self; v } /// Returns unique id (unique with respect to the graph holding associated node). - pub fn node_id(&self) -> uint { self.get() } + pub fn node_id(&self) -> usize { self.get() } } impl EdgeIndex { - fn get(&self) -> uint { let EdgeIndex(v) = *self; v } + fn get(&self) -> usize { let EdgeIndex(v) = *self; v } /// Returns unique id (unique with respect to the graph holding associated edge). - pub fn edge_id(&self) -> uint { self.get() } + pub fn edge_id(&self) -> usize { self.get() } } impl Graph { @@ -99,8 +99,8 @@ impl Graph { } } - pub fn with_capacity(num_nodes: uint, - num_edges: uint) -> Graph { + pub fn with_capacity(num_nodes: usize, + num_edges: usize) -> Graph { Graph { nodes: Vec::with_capacity(num_nodes), edges: Vec::with_capacity(num_edges), @@ -275,7 +275,7 @@ impl Graph { // computation. pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F) where - F: FnMut(uint, EdgeIndex, &'a Edge) -> bool, + F: FnMut(usize, EdgeIndex, &'a Edge) -> bool, { let mut iteration = 0; let mut changed = true; diff --git a/src/librustc/middle/infer/bivariate.rs b/src/librustc/middle/infer/bivariate.rs index 93c80fb754..940dc75271 100644 --- a/src/librustc/middle/infer/bivariate.rs +++ b/src/librustc/middle/infer/bivariate.rs @@ -25,86 +25,54 @@ //! In particular, it might be enough to say (A,B) are bivariant for //! all (A,B). -use middle::ty::{BuiltinBounds}; +use super::combine::{self, CombineFields}; +use super::type_variable::{BiTo}; + use middle::ty::{self, Ty}; use middle::ty::TyVar; -use middle::infer::combine::*; -use middle::infer::{cres}; -use middle::infer::type_variable::{BiTo}; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use util::ppaux::{Repr}; -use syntax::ast::{Unsafety}; - -pub struct Bivariate<'f, 'tcx: 'f> { - fields: CombineFields<'f, 'tcx> -} - -#[allow(non_snake_case)] -pub fn Bivariate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Bivariate<'f, 'tcx> { - Bivariate { fields: cf } +pub struct Bivariate<'a, 'tcx: 'a> { + fields: CombineFields<'a, 'tcx> } -impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> { - fn tag(&self) -> String { "Bivariate".to_string() } - fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - - fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> - { - match v { - ty::Invariant => self.equate().tys(a, b), - ty::Covariant => self.tys(a, b), - ty::Contravariant => self.tys(a, b), - ty::Bivariant => self.tys(a, b), - } - } - - fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> - { - match v { - ty::Invariant => self.equate().regions(a, b), - ty::Covariant => self.regions(a, b), - ty::Contravariant => self.regions(a, b), - ty::Bivariant => self.regions(a, b), - } - } - - fn regions(&self, a: ty::Region, _: ty::Region) -> cres<'tcx, ty::Region> { - Ok(a) +impl<'a, 'tcx> Bivariate<'a, 'tcx> { + pub fn new(fields: CombineFields<'a, 'tcx>) -> Bivariate<'a, 'tcx> { + Bivariate { fields: fields } } +} - fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { - debug!("mts({} <: {})", - a.repr(self.fields.infcx.tcx), - b.repr(self.fields.infcx.tcx)); +impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { + fn tag(&self) -> &'static str { "Bivariate" } - if a.mutbl != b.mutbl { return Err(ty::terr_mutability); } - let t = try!(self.tys(a.ty, b.ty)); - Ok(ty::mt { mutbl: a.mutbl, ty: t }) - } + fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() } - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { - if a != b { - Err(ty::terr_unsafety_mismatch(expected_found(self, a, b))) - } else { - Ok(a) - } - } + fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn builtin_bounds(&self, - a: BuiltinBounds, - b: BuiltinBounds) - -> cres<'tcx, BuiltinBounds> + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> { - if a != b { - Err(ty::terr_builtin_bounds(expected_found(self, a, b))) - } else { - Ok(a) + match variance { + // If we have Foo and Foo is invariant w/r/t A, + // and we want to assert that + // + // Foo <: Foo || + // Foo <: Foo + // + // then still A must equal B. + ty::Invariant => self.relate(a, b), + + ty::Covariant => self.relate(a, b), + ty::Bivariant => self.relate(a, b), + ty::Contravariant => self.relate(a, b), } } - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug!("{}.tys({}, {})", self.tag(), a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx)); if a == b { return Ok(a); } @@ -129,17 +97,22 @@ impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> { } _ => { - super_tys(self, a, b) + combine::super_combine_tys(self.fields.infcx, self, a, b) } } } - fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> - where T : Combineable<'tcx> + fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> { + Ok(a) + } + + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a,'tcx> { let a1 = ty::erase_late_bound_regions(self.tcx(), a); let b1 = ty::erase_late_bound_regions(self.tcx(), b); - let c = try!(Combineable::combine(self, &a1, &b1)); + let c = try!(self.relate(&a1, &b1)); Ok(ty::Binder(c)) } } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 0eeafb767d..86f12b669b 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -37,369 +37,21 @@ use super::equate::Equate; use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; -use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; -use super::{InferCtxt, cres}; +use super::{InferCtxt}; use super::{MiscVariable, TypeTrace}; use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf}; -use middle::subst; -use middle::subst::{ErasedRegions, NonerasedRegions, Substs}; -use middle::ty::{FloatVar, FnSig, IntVar, TyVar}; +use middle::ty::{TyVar}; use middle::ty::{IntType, UintType}; -use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; use middle::ty_fold; use middle::ty_fold::{TypeFolder, TypeFoldable}; +use middle::ty_relate::{self, Relate, RelateResult, TypeRelation}; use util::ppaux::Repr; -use std::rc::Rc; -use syntax::ast::Unsafety; use syntax::ast; -use syntax::abi; use syntax::codemap::Span; -pub trait Combine<'tcx> : Sized { - fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx } - fn tag(&self) -> String; - - fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx>; - - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields().infcx } - fn a_is_expected(&self) -> bool { self.fields().a_is_expected } - fn trace(&self) -> TypeTrace<'tcx> { self.fields().trace.clone() } - fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { self.fields().equate() } - fn bivariate<'a>(&'a self) -> Bivariate<'a, 'tcx> { self.fields().bivariate() } - - fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { self.fields().sub() } - fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields().clone()) } - fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields().clone()) } - - fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>>; - - fn tys_with_variance(&self, variance: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>>; - - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>; - - fn regions_with_variance(&self, variance: ty::Variance, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region>; - - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>; - - fn substs(&self, - item_def_id: ast::DefId, - a_subst: &subst::Substs<'tcx>, - b_subst: &subst::Substs<'tcx>) - -> cres<'tcx, subst::Substs<'tcx>> - { - debug!("substs: item_def_id={} a_subst={} b_subst={}", - item_def_id.repr(self.infcx().tcx), - a_subst.repr(self.infcx().tcx), - b_subst.repr(self.infcx().tcx)); - - let variances = if self.infcx().tcx.variance_computed.get() { - Some(ty::item_variances(self.infcx().tcx, item_def_id)) - } else { - None - }; - self.substs_variances(variances.as_ref().map(|v| &**v), a_subst, b_subst) - } - - fn substs_variances(&self, - variances: Option<&ty::ItemVariances>, - a_subst: &subst::Substs<'tcx>, - b_subst: &subst::Substs<'tcx>) - -> cres<'tcx, subst::Substs<'tcx>> - { - let mut substs = subst::Substs::empty(); - - for &space in &subst::ParamSpace::all() { - let a_tps = a_subst.types.get_slice(space); - let b_tps = b_subst.types.get_slice(space); - let t_variances = variances.map(|v| v.types.get_slice(space)); - let tps = try!(relate_type_params(self, t_variances, a_tps, b_tps)); - substs.types.replace(space, tps); - } - - match (&a_subst.regions, &b_subst.regions) { - (&ErasedRegions, _) | (_, &ErasedRegions) => { - substs.regions = ErasedRegions; - } - - (&NonerasedRegions(ref a), &NonerasedRegions(ref b)) => { - for &space in &subst::ParamSpace::all() { - let a_regions = a.get_slice(space); - let b_regions = b.get_slice(space); - let r_variances = variances.map(|v| v.regions.get_slice(space)); - let regions = try!(relate_region_params(self, - r_variances, - a_regions, - b_regions)); - substs.mut_regions().replace(space, regions); - } - } - } - - return Ok(substs); - - fn relate_type_params<'tcx, C: Combine<'tcx>>(this: &C, - variances: Option<&[ty::Variance]>, - a_tys: &[Ty<'tcx>], - b_tys: &[Ty<'tcx>]) - -> cres<'tcx, Vec>> - { - if a_tys.len() != b_tys.len() { - return Err(ty::terr_ty_param_size(expected_found(this, - a_tys.len(), - b_tys.len()))); - } - - range(0, a_tys.len()).map(|i| { - let a_ty = a_tys[i]; - let b_ty = b_tys[i]; - let v = variances.map_or(ty::Invariant, |v| v[i]); - this.tys_with_variance(v, a_ty, b_ty) - }).collect() - } - - fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C, - variances: Option<&[ty::Variance]>, - a_rs: &[ty::Region], - b_rs: &[ty::Region]) - -> cres<'tcx, Vec> - { - let tcx = this.infcx().tcx; - let num_region_params = a_rs.len(); - - debug!("relate_region_params(\ - a_rs={}, \ - b_rs={}, - variances={})", - a_rs.repr(tcx), - b_rs.repr(tcx), - variances.repr(tcx)); - - assert_eq!(num_region_params, - variances.map_or(num_region_params, - |v| v.len())); - - assert_eq!(num_region_params, b_rs.len()); - - (0..a_rs.len()).map(|i| { - let a_r = a_rs[i]; - let b_r = b_rs[i]; - let variance = variances.map_or(ty::Invariant, |v| v[i]); - this.regions_with_variance(variance, a_r, b_r) - }).collect() - } - } - - fn bare_fn_tys(&self, a: &ty::BareFnTy<'tcx>, - b: &ty::BareFnTy<'tcx>) -> cres<'tcx, ty::BareFnTy<'tcx>> { - let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); - let abi = try!(self.abi(a.abi, b.abi)); - let sig = try!(self.binders(&a.sig, &b.sig)); - Ok(ty::BareFnTy {unsafety: unsafety, - abi: abi, - sig: sig}) - } - - fn fn_sigs(&self, a: &ty::FnSig<'tcx>, b: &ty::FnSig<'tcx>) -> cres<'tcx, ty::FnSig<'tcx>> { - if a.variadic != b.variadic { - return Err(ty::terr_variadic_mismatch(expected_found(self, a.variadic, b.variadic))); - } - - let inputs = try!(argvecs(self, - &a.inputs, - &b.inputs)); - - let output = try!(match (a.output, b.output) { - (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) => - Ok(ty::FnConverging(try!(self.tys(a_ty, b_ty)))), - (ty::FnDiverging, ty::FnDiverging) => - Ok(ty::FnDiverging), - (a, b) => - Err(ty::terr_convergence_mismatch( - expected_found(self, a != ty::FnDiverging, b != ty::FnDiverging))), - }); - - return Ok(ty::FnSig {inputs: inputs, - output: output, - variadic: a.variadic}); - - - fn argvecs<'tcx, C: Combine<'tcx>>(combiner: &C, - a_args: &[Ty<'tcx>], - b_args: &[Ty<'tcx>]) - -> cres<'tcx, Vec>> - { - if a_args.len() == b_args.len() { - a_args.iter().zip(b_args.iter()) - .map(|(a, b)| combiner.args(*a, *b)).collect() - } else { - Err(ty::terr_arg_count) - } - } - } - - fn args(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - self.tys_with_variance(ty::Contravariant, a, b).and_then(|t| Ok(t)) - } - - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>; - - fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<'tcx, abi::Abi> { - if a == b { - Ok(a) - } else { - Err(ty::terr_abi_mismatch(expected_found(self, a, b))) - } - } - - fn projection_tys(&self, - a: &ty::ProjectionTy<'tcx>, - b: &ty::ProjectionTy<'tcx>) - -> cres<'tcx, ty::ProjectionTy<'tcx>> - { - if a.item_name != b.item_name { - Err(ty::terr_projection_name_mismatched( - expected_found(self, a.item_name, b.item_name))) - } else { - // Note that the trait refs for the projection must be - // *equal*. This is because there is no inherent - // relationship between `::Bar` and `::Bar` that we can derive based on how `T` relates - // to `U`. Issue #21726 contains further discussion and - // in-depth examples. - let trait_ref = try!(self.equate().trait_refs(&*a.trait_ref, &*b.trait_ref)); - Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name }) - } - } - - fn projection_predicates(&self, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>) - -> cres<'tcx, ty::ProjectionPredicate<'tcx>> - { - let projection_ty = try!(self.projection_tys(&a.projection_ty, &b.projection_ty)); - let ty = try!(self.tys(a.ty, b.ty)); - Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) - } - - fn projection_bounds(&self, - a: &Vec>, - b: &Vec>) - -> cres<'tcx, Vec>> - { - // To be compatible, `a` and `b` must be for precisely the - // same set of traits and item names. We always require that - // projection bounds lists are sorted by trait-def-id and item-name, - // so we can just iterate through the lists pairwise, so long as they are the - // same length. - if a.len() != b.len() { - Err(ty::terr_projection_bounds_length(expected_found(self, a.len(), b.len()))) - } else { - a.iter() - .zip(b.iter()) - .map(|(a, b)| self.binders(a, b)) - .collect() - } - } - - fn existential_bounds(&self, - a: &ty::ExistentialBounds<'tcx>, - b: &ty::ExistentialBounds<'tcx>) - -> cres<'tcx, ty::ExistentialBounds<'tcx>> - { - let r = try!(self.regions_with_variance(ty::Contravariant, a.region_bound, b.region_bound)); - let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds)); - let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds)); - Ok(ty::ExistentialBounds { region_bound: r, - builtin_bounds: nb, - projection_bounds: pb }) - } - - fn builtin_bounds(&self, - a: ty::BuiltinBounds, - b: ty::BuiltinBounds) - -> cres<'tcx, ty::BuiltinBounds>; - - fn trait_refs(&self, - a: &ty::TraitRef<'tcx>, - b: &ty::TraitRef<'tcx>) - -> cres<'tcx, ty::TraitRef<'tcx>> - { - // Different traits cannot be related - if a.def_id != b.def_id { - Err(ty::terr_traits(expected_found(self, a.def_id, b.def_id))) - } else { - let substs = try!(self.substs(a.def_id, a.substs, b.substs)); - Ok(ty::TraitRef { def_id: a.def_id, substs: self.tcx().mk_substs(substs) }) - } - } - - fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> - where T : Combineable<'tcx>; - // this must be overridden to do correctly, so as to account for higher-ranked - // behavior -} - -pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> { - fn combine>(combiner: &C, a: &Self, b: &Self) -> cres<'tcx, Self>; -} - -impl<'tcx,T> Combineable<'tcx> for Rc - where T : Combineable<'tcx> -{ - fn combine>(combiner: &C, - a: &Rc, - b: &Rc) - -> cres<'tcx, Rc> - { - Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b)))) - } -} - -impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> { - fn combine>(combiner: &C, - a: &ty::TraitRef<'tcx>, - b: &ty::TraitRef<'tcx>) - -> cres<'tcx, ty::TraitRef<'tcx>> - { - combiner.trait_refs(a, b) - } -} - -impl<'tcx> Combineable<'tcx> for Ty<'tcx> { - fn combine>(combiner: &C, - a: &Ty<'tcx>, - b: &Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> - { - combiner.tys(*a, *b) - } -} - -impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> { - fn combine>(combiner: &C, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>) - -> cres<'tcx, ty::ProjectionPredicate<'tcx>> - { - combiner.projection_predicates(a, b) - } -} - -impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> { - fn combine>(combiner: &C, - a: &ty::FnSig<'tcx>, - b: &ty::FnSig<'tcx>) - -> cres<'tcx, ty::FnSig<'tcx>> - { - combiner.fn_sigs(a, b) - } -} - #[derive(Clone)] pub struct CombineFields<'a, 'tcx: 'a> { pub infcx: &'a InferCtxt<'a, 'tcx>, @@ -407,254 +59,133 @@ pub struct CombineFields<'a, 'tcx: 'a> { pub trace: TypeTrace<'tcx>, } -pub fn expected_found<'tcx, C: Combine<'tcx>, T>( - this: &C, a: T, b: T) -> ty::expected_found { - if this.a_is_expected() { - ty::expected_found {expected: a, found: b} - } else { - ty::expected_found {expected: b, found: a} - } -} - -pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> +pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>, + relation: &mut R, + a: Ty<'tcx>, + b: Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a,'tcx> { - let tcx = this.infcx().tcx; - let a_sty = &a.sty; - let b_sty = &b.sty; - debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty); - return match (a_sty, b_sty) { - // The "subtype" ought to be handling cases involving var: - (&ty::ty_infer(TyVar(_)), _) | - (_, &ty::ty_infer(TyVar(_))) => { - tcx.sess.bug( - &format!("{}: bot and var types should have been handled ({},{})", - this.tag(), - a.repr(this.infcx().tcx), - b.repr(this.infcx().tcx))[]); - } - - (&ty::ty_err, _) | (_, &ty::ty_err) => { - Ok(tcx.types.err) - } + let a_is_expected = relation.a_is_expected(); + match (&a.sty, &b.sty) { // Relate integral variables to other types - (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => { - try!(this.infcx().simple_vars(this.a_is_expected(), - a_id, b_id)); + (&ty::ty_infer(ty::IntVar(a_id)), &ty::ty_infer(ty::IntVar(b_id))) => { + try!(infcx.int_unification_table + .borrow_mut() + .unify_var_var(a_id, b_id) + .map_err(|e| int_unification_error(a_is_expected, e))); Ok(a) } - (&ty::ty_infer(IntVar(v_id)), &ty::ty_int(v)) => { - unify_integral_variable(this, this.a_is_expected(), - v_id, IntType(v)) + (&ty::ty_infer(ty::IntVar(v_id)), &ty::ty_int(v)) => { + unify_integral_variable(infcx, a_is_expected, v_id, IntType(v)) } - (&ty::ty_int(v), &ty::ty_infer(IntVar(v_id))) => { - unify_integral_variable(this, !this.a_is_expected(), - v_id, IntType(v)) + (&ty::ty_int(v), &ty::ty_infer(ty::IntVar(v_id))) => { + unify_integral_variable(infcx, !a_is_expected, v_id, IntType(v)) } - (&ty::ty_infer(IntVar(v_id)), &ty::ty_uint(v)) => { - unify_integral_variable(this, this.a_is_expected(), - v_id, UintType(v)) + (&ty::ty_infer(ty::IntVar(v_id)), &ty::ty_uint(v)) => { + unify_integral_variable(infcx, a_is_expected, v_id, UintType(v)) } - (&ty::ty_uint(v), &ty::ty_infer(IntVar(v_id))) => { - unify_integral_variable(this, !this.a_is_expected(), - v_id, UintType(v)) + (&ty::ty_uint(v), &ty::ty_infer(ty::IntVar(v_id))) => { + unify_integral_variable(infcx, !a_is_expected, v_id, UintType(v)) } // Relate floating-point variables to other types - (&ty::ty_infer(FloatVar(a_id)), &ty::ty_infer(FloatVar(b_id))) => { - try!(this.infcx().simple_vars(this.a_is_expected(), a_id, b_id)); + (&ty::ty_infer(ty::FloatVar(a_id)), &ty::ty_infer(ty::FloatVar(b_id))) => { + try!(infcx.float_unification_table + .borrow_mut() + .unify_var_var(a_id, b_id) + .map_err(|e| float_unification_error(relation.a_is_expected(), e))); Ok(a) } - (&ty::ty_infer(FloatVar(v_id)), &ty::ty_float(v)) => { - unify_float_variable(this, this.a_is_expected(), v_id, v) + (&ty::ty_infer(ty::FloatVar(v_id)), &ty::ty_float(v)) => { + unify_float_variable(infcx, a_is_expected, v_id, v) } - (&ty::ty_float(v), &ty::ty_infer(FloatVar(v_id))) => { - unify_float_variable(this, !this.a_is_expected(), v_id, v) + (&ty::ty_float(v), &ty::ty_infer(ty::FloatVar(v_id))) => { + unify_float_variable(infcx, !a_is_expected, v_id, v) } - (&ty::ty_char, _) | - (&ty::ty_bool, _) | - (&ty::ty_int(_), _) | - (&ty::ty_uint(_), _) | - (&ty::ty_float(_), _) => { - if a == b { - Ok(a) - } else { - Err(ty::terr_sorts(expected_found(this, a, b))) + // All other cases of inference are errors + (&ty::ty_infer(_), _) | + (_, &ty::ty_infer(_)) => { + Err(ty::terr_sorts(ty_relate::expected_found(relation, &a, &b))) } - } - - (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if - a_p.idx == b_p.idx && a_p.space == b_p.space => { - Ok(a) - } - - (&ty::ty_enum(a_id, a_substs), - &ty::ty_enum(b_id, b_substs)) - if a_id == b_id => { - let substs = try!(this.substs(a_id, - a_substs, - b_substs)); - Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs))) - } - - (&ty::ty_trait(ref a_), - &ty::ty_trait(ref b_)) => { - debug!("Trying to match traits {:?} and {:?}", a, b); - let principal = try!(this.binders(&a_.principal, &b_.principal)); - let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds)); - Ok(ty::mk_trait(tcx, principal, bounds)) - } - - (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs)) - if a_id == b_id => { - let substs = try!(this.substs(a_id, a_substs, b_substs)); - Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs))) - } - - (&ty::ty_closure(a_id, a_region, a_substs), - &ty::ty_closure(b_id, b_region, b_substs)) - if a_id == b_id => { - // All ty_closure types with the same id represent - // the (anonymous) type of the same closure expression. So - // all of their regions should be equated. - let region = try!(this.equate().regions(*a_region, *b_region)); - let substs = try!(this.substs_variances(None, a_substs, b_substs)); - Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), tcx.mk_substs(substs))) - } - - (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => { - let typ = try!(this.tys(a_inner, b_inner)); - Ok(ty::mk_uniq(tcx, typ)) - } - - (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => { - let mt = try!(this.mts(a_mt, b_mt)); - Ok(ty::mk_ptr(tcx, mt)) - } - - (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => { - let r = try!(this.regions_with_variance(ty::Contravariant, *a_r, *b_r)); - - // FIXME(14985) If we have mutable references to trait objects, we - // used to use covariant subtyping. I have preserved this behaviour, - // even though it is probably incorrect. So don't go down the usual - // path which would require invariance. - let mt = match (&a_mt.ty.sty, &b_mt.ty.sty) { - (&ty::ty_trait(..), &ty::ty_trait(..)) if a_mt.mutbl == b_mt.mutbl => { - let ty = try!(this.tys(a_mt.ty, b_mt.ty)); - ty::mt { ty: ty, mutbl: a_mt.mutbl } - } - _ => try!(this.mts(a_mt, b_mt)) - }; - Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt)) - } - - (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => { - this.tys(a_t, b_t).and_then(|t| { - if sz_a == sz_b { - Ok(ty::mk_vec(tcx, t, Some(sz_a))) - } else { - Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b))) - } - }) - } - - (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => { - this.tys(a_t, b_t).and_then(|t| { - if sz_a == sz_b { - Ok(ty::mk_vec(tcx, t, sz_a)) - } else { - Err(ty::terr_sorts(expected_found(this, a, b))) - } - }) - } - - (&ty::ty_str, &ty::ty_str) => { - Ok(ty::mk_str(tcx)) - } - - (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => { - if as_.len() == bs.len() { - as_.iter().zip(bs.iter()) - .map(|(a, b)| this.tys(*a, *b)) - .collect::>() - .map(|ts| ty::mk_tup(tcx, ts)) - } else if as_.len() != 0 && bs.len() != 0 { - Err(ty::terr_tuple_size( - expected_found(this, as_.len(), bs.len()))) - } else { - Err(ty::terr_sorts(expected_found(this, a, b))) - } - } - - (&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty)) - if a_opt_def_id == b_opt_def_id => - { - let fty = try!(this.bare_fn_tys(a_fty, b_fty)); - Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty))) - } - - (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => { - let projection_ty = try!(this.projection_tys(a_data, b_data)); - Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name)) - } - _ => Err(ty::terr_sorts(expected_found(this, a, b))) - }; - fn unify_integral_variable<'tcx, C: Combine<'tcx>>( - this: &C, - vid_is_expected: bool, - vid: ty::IntVid, - val: ty::IntVarValue) -> cres<'tcx, Ty<'tcx>> - { - try!(this.infcx().simple_var_t(vid_is_expected, vid, val)); - match val { - IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)), - UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)) + _ => { + ty_relate::super_relate_tys(relation, a, b) } } +} - fn unify_float_variable<'tcx, C: Combine<'tcx>>( - this: &C, - vid_is_expected: bool, - vid: ty::FloatVid, - val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>> - { - try!(this.infcx().simple_var_t(vid_is_expected, vid, val)); - Ok(ty::mk_mach_float(this.tcx(), val)) +fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + vid_is_expected: bool, + vid: ty::IntVid, + val: ty::IntVarValue) + -> RelateResult<'tcx, Ty<'tcx>> +{ + try!(infcx + .int_unification_table + .borrow_mut() + .unify_var_value(vid, val) + .map_err(|e| int_unification_error(vid_is_expected, e))); + match val { + IntType(v) => Ok(ty::mk_mach_int(infcx.tcx, v)), + UintType(v) => Ok(ty::mk_mach_uint(infcx.tcx, v)), } } -impl<'f, 'tcx> CombineFields<'f, 'tcx> { - pub fn switch_expected(&self) -> CombineFields<'f, 'tcx> { +fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + vid_is_expected: bool, + vid: ty::FloatVid, + val: ast::FloatTy) + -> RelateResult<'tcx, Ty<'tcx>> +{ + try!(infcx + .float_unification_table + .borrow_mut() + .unify_var_value(vid, val) + .map_err(|e| float_unification_error(vid_is_expected, e))); + Ok(ty::mk_mach_float(infcx.tcx, val)) +} + +impl<'a, 'tcx> CombineFields<'a, 'tcx> { + pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { + self.infcx.tcx + } + + pub fn switch_expected(&self) -> CombineFields<'a, 'tcx> { CombineFields { a_is_expected: !self.a_is_expected, ..(*self).clone() } } - fn equate(&self) -> Equate<'f, 'tcx> { - Equate((*self).clone()) + pub fn equate(&self) -> Equate<'a, 'tcx> { + Equate::new(self.clone()) } - fn bivariate(&self) -> Bivariate<'f, 'tcx> { - Bivariate((*self).clone()) + pub fn bivariate(&self) -> Bivariate<'a, 'tcx> { + Bivariate::new(self.clone()) } - fn sub(&self) -> Sub<'f, 'tcx> { - Sub((*self).clone()) + pub fn sub(&self) -> Sub<'a, 'tcx> { + Sub::new(self.clone()) + } + + pub fn lub(&self) -> Lub<'a, 'tcx> { + Lub::new(self.clone()) + } + + pub fn glb(&self) -> Glb<'a, 'tcx> { + Glb::new(self.clone()) } pub fn instantiate(&self, a_ty: Ty<'tcx>, dir: RelationDir, b_vid: ty::TyVid) - -> cres<'tcx, ()> + -> RelateResult<'tcx, ()> { let tcx = self.infcx.tcx; let mut stack = Vec::new(); @@ -696,12 +227,8 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { None => { // ...not yet instantiated: // Generalize type if necessary. let generalized_ty = try!(match dir { - EqTo => { - self.generalize(a_ty, b_vid, false) - } - BiTo | SupertypeOf | SubtypeOf => { - self.generalize(a_ty, b_vid, true) - } + EqTo => self.generalize(a_ty, b_vid, false), + BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true), }); debug!("instantiate(a_ty={}, dir={:?}, \ b_vid={}, generalized_ty={})", @@ -722,23 +249,12 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { // relations wind up attributed to the same spans. We need // to associate causes/spans with each of the relations in // the stack to get this right. - match dir { - BiTo => { - try!(self.bivariate().tys(a_ty, b_ty)); - } - - EqTo => { - try!(self.equate().tys(a_ty, b_ty)); - } - - SubtypeOf => { - try!(self.sub().tys(a_ty, b_ty)); - } - - SupertypeOf => { - try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)); - } - } + try!(match dir { + BiTo => self.bivariate().relate(&a_ty, &b_ty), + EqTo => self.equate().relate(&a_ty, &b_ty), + SubtypeOf => self.sub().relate(&a_ty, &b_ty), + SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty), + }); } Ok(()) @@ -752,13 +268,15 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> { ty: Ty<'tcx>, for_vid: ty::TyVid, make_region_vars: bool) - -> cres<'tcx, Ty<'tcx>> + -> RelateResult<'tcx, Ty<'tcx>> { - let mut generalize = Generalizer { infcx: self.infcx, - span: self.trace.origin.span(), - for_vid: for_vid, - make_region_vars: make_region_vars, - cycle_detected: false }; + let mut generalize = Generalizer { + infcx: self.infcx, + span: self.trace.origin.span(), + for_vid: for_vid, + make_region_vars: make_region_vars, + cycle_detected: false + }; let u = ty.fold_with(&mut generalize); if generalize.cycle_detected { Err(ty::terr_cyclic_ty) @@ -818,7 +336,7 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> { self.tcx().sess.span_bug( self.span, &format!("Encountered early bound region when generalizing: {}", - r.repr(self.tcx()))[]); + r.repr(self.tcx()))); } // Always make a fresh region variable for skolemized regions; @@ -843,3 +361,37 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> { self.infcx.next_region_var(MiscVariable(self.span)) } } + +pub trait RelateResultCompare<'tcx, T> { + fn compare(&self, t: T, f: F) -> RelateResult<'tcx, T> where + F: FnOnce() -> ty::type_err<'tcx>; +} + +impl<'tcx, T:Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'tcx, T> { + fn compare(&self, t: T, f: F) -> RelateResult<'tcx, T> where + F: FnOnce() -> ty::type_err<'tcx>, + { + self.clone().and_then(|s| { + if s == t { + self.clone() + } else { + Err(f()) + } + }) + } +} + +fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue)) + -> ty::type_err<'tcx> +{ + let (a, b) = v; + ty::terr_int_mismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b)) +} + +fn float_unification_error<'tcx>(a_is_expected: bool, + v: (ast::FloatTy, ast::FloatTy)) + -> ty::type_err<'tcx> +{ + let (a, b) = v; + ty::terr_float_mismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b)) +} diff --git a/src/librustc/middle/infer/equate.rs b/src/librustc/middle/infer/equate.rs index 7194e20b0c..2003f459d8 100644 --- a/src/librustc/middle/infer/equate.rs +++ b/src/librustc/middle/infer/equate.rs @@ -8,89 +8,43 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::ty::{BuiltinBounds}; +use super::combine::{self, CombineFields}; +use super::higher_ranked::HigherRankedRelations; +use super::{Subtype}; +use super::type_variable::{EqTo}; + use middle::ty::{self, Ty}; use middle::ty::TyVar; -use middle::infer::combine::*; -use middle::infer::{cres}; -use middle::infer::{Subtype}; -use middle::infer::type_variable::{EqTo}; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use util::ppaux::{Repr}; -use syntax::ast::Unsafety; - -pub struct Equate<'f, 'tcx: 'f> { - fields: CombineFields<'f, 'tcx> -} - -#[allow(non_snake_case)] -pub fn Equate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Equate<'f, 'tcx> { - Equate { fields: cf } +pub struct Equate<'a, 'tcx: 'a> { + fields: CombineFields<'a, 'tcx> } -impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> { - fn tag(&self) -> String { "Equate".to_string() } - fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - - fn tys_with_variance(&self, _: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> - { - // Once we're equating, it doesn't matter what the variance is. - self.tys(a, b) - } - - fn regions_with_variance(&self, _: ty::Variance, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> - { - // Once we're equating, it doesn't matter what the variance is. - self.regions(a, b) - } - - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { - debug!("{}.regions({}, {})", - self.tag(), - a.repr(self.fields.infcx.tcx), - b.repr(self.fields.infcx.tcx)); - self.infcx().region_vars.make_eqregion(Subtype(self.trace()), a, b); - Ok(a) +impl<'a, 'tcx> Equate<'a, 'tcx> { + pub fn new(fields: CombineFields<'a, 'tcx>) -> Equate<'a, 'tcx> { + Equate { fields: fields } } +} - fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { - debug!("mts({} <: {})", - a.repr(self.fields.infcx.tcx), - b.repr(self.fields.infcx.tcx)); +impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { + fn tag(&self) -> &'static str { "Equate" } - if a.mutbl != b.mutbl { return Err(ty::terr_mutability); } - let t = try!(self.tys(a.ty, b.ty)); - Ok(ty::mt { mutbl: a.mutbl, ty: t }) - } + fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() } - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { - if a != b { - Err(ty::terr_unsafety_mismatch(expected_found(self, a, b))) - } else { - Ok(a) - } - } + fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn builtin_bounds(&self, - a: BuiltinBounds, - b: BuiltinBounds) - -> cres<'tcx, BuiltinBounds> + fn relate_with_variance>(&mut self, + _: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> { - // More bounds is a subtype of fewer bounds. - // - // e.g., fn:Copy() <: fn(), because the former is a function - // that only closes over copyable things, but the latter is - // any function at all. - if a != b { - Err(ty::terr_builtin_bounds(expected_found(self, a, b))) - } else { - Ok(a) - } + self.relate(a, b) } - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug!("{}.tys({}, {})", self.tag(), a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx)); if a == b { return Ok(a); } @@ -115,15 +69,26 @@ impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> { } _ => { - super_tys(self, a, b) + combine::super_combine_tys(self.fields.infcx, self, a, b) } } } - fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> - where T : Combineable<'tcx> + fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + debug!("{}.regions({}, {})", + self.tag(), + a.repr(self.fields.infcx.tcx), + b.repr(self.fields.infcx.tcx)); + let origin = Subtype(self.fields.trace.clone()); + self.fields.infcx.region_vars.make_eqregion(origin, a, b); + Ok(a) + } + + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a, 'tcx> { - try!(self.sub().binders(a, b)); - self.sub().binders(b, a) + try!(self.fields.higher_ranked_sub(a, b)); + self.fields.higher_ranked_sub(b, a) } } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 53032f9b9a..36229a558e 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -83,7 +83,7 @@ use std::rc::Rc; use std::string::String; use syntax::ast; use syntax::ast_map; -use syntax::ast_util::{name_to_dummy_lifetime, PostExpansionMethod}; +use syntax::ast_util::name_to_dummy_lifetime; use syntax::owned_slice::OwnedSlice; use syntax::codemap; use syntax::parse::token; @@ -357,23 +357,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { } }; - let message_root_str = match trace.origin { - infer::Misc(_) => "mismatched types", - infer::MethodCompatCheck(_) => "method not compatible with trait", - infer::ExprAssignable(_) => "mismatched types", - infer::RelateTraitRefs(_) => "mismatched traits", - infer::RelateSelfType(_) => "mismatched types", - infer::RelateOutputImplTypes(_) => "mismatched types", - infer::MatchExpressionArm(_, _) => "match arms have incompatible types", - infer::IfExpression(_) => "if and else have incompatible types", - infer::IfExpressionWithNoElse(_) => "if may be missing an else clause", - infer::RangeExpression(_) => "start and end of range have incompatible types", - infer::EquatePredicate(_) => "equality predicate not satisfied", - }; - span_err!(self.tcx.sess, trace.origin.span(), E0308, "{}: {} ({})", - message_root_str, + trace.origin, expected_found_str, ty::type_err_to_str(self.tcx, terr)); @@ -444,23 +430,23 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { // Does the required lifetime have a nice name we can print? span_err!(self.tcx.sess, origin.span(), E0309, "{} may not live long enough", labeled_user_string); - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( origin.span(), &format!( "consider adding an explicit lifetime bound `{}: {}`...", bound_kind.user_string(self.tcx), - sub.user_string(self.tcx))[]); + sub.user_string(self.tcx))); } ty::ReStatic => { // Does the required lifetime have a nice name we can print? span_err!(self.tcx.sess, origin.span(), E0310, "{} may not live long enough", labeled_user_string); - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( origin.span(), &format!( "consider adding an explicit lifetime bound `{}: 'static`...", - bound_kind.user_string(self.tcx))[]); + bound_kind.user_string(self.tcx))); } _ => { @@ -468,14 +454,14 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span_err!(self.tcx.sess, origin.span(), E0311, "{} may not live long enough", labeled_user_string); - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( origin.span(), &format!( "consider adding an explicit lifetime bound for `{}`", - bound_kind.user_string(self.tcx))[]); + bound_kind.user_string(self.tcx))); note_and_explain_region( self.tcx, - &format!("{} must be valid for ", labeled_user_string)[], + &format!("{} must be valid for ", labeled_user_string), sub, "..."); } @@ -525,7 +511,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { &format!("...but `{}` is only valid for ", ty::local_var_name_str(self.tcx, upvar_id.var_id) - .to_string())[], + .to_string()), sup, ""); } @@ -568,7 +554,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { &format!("captured variable `{}` does not \ outlive the enclosing closure", ty::local_var_name_str(self.tcx, - id).to_string())[]); + id).to_string())); note_and_explain_region( self.tcx, "captured variable is valid for ", @@ -610,7 +596,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, &format!("the type `{}` does not fulfill the \ required lifetime", - self.ty_to_string(ty))[]); + self.ty_to_string(ty))); note_and_explain_region(self.tcx, "type must outlive ", sub, @@ -636,7 +622,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, &format!("the type `{}` (provided as the value of \ a type parameter) is not valid at this point", - self.ty_to_string(ty))[]); + self.ty_to_string(ty))); note_and_explain_region(self.tcx, "type must outlive ", sub, @@ -713,7 +699,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, &format!("type of expression contains references \ that are not valid during the expression: `{}`", - self.ty_to_string(t))[]); + self.ty_to_string(t))); note_and_explain_region( self.tcx, "type is only valid for ", @@ -752,7 +738,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { span, &format!("in type `{}`, reference has a longer lifetime \ than the data it references", - self.ty_to_string(ty))[]); + self.ty_to_string(ty))); note_and_explain_region( self.tcx, "the pointer is valid for ", @@ -841,33 +827,34 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ast_map::NodeItem(ref item) => { match item.node { ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => { - Some((&**fn_decl, gen, pur, item.ident, None, item.span)) + Some((fn_decl, gen, pur, item.ident, None, item.span)) }, _ => None } } - ast_map::NodeImplItem(ref item) => { - match **item { - ast::MethodImplItem(ref m) => { - Some((m.pe_fn_decl(), - m.pe_generics(), - m.pe_unsafety(), - m.pe_ident(), - Some(&m.pe_explicit_self().node), - m.span)) + ast_map::NodeImplItem(item) => { + match item.node { + ast::MethodImplItem(ref sig, _) => { + Some((&sig.decl, + &sig.generics, + sig.unsafety, + item.ident, + Some(&sig.explicit_self.node), + item.span)) } ast::TypeImplItem(_) => None, + ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro") } }, - ast_map::NodeTraitItem(ref item) => { - match **item { - ast::ProvidedMethod(ref m) => { - Some((m.pe_fn_decl(), - m.pe_generics(), - m.pe_unsafety(), - m.pe_ident(), - Some(&m.pe_explicit_self().node), - m.span)) + ast_map::NodeTraitItem(item) => { + match item.node { + ast::MethodTraitItem(ref sig, Some(_)) => { + Some((&sig.decl, + &sig.generics, + sig.unsafety, + item.ident, + Some(&sig.explicit_self.node), + item.span)) } _ => None } @@ -988,7 +975,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { names.push(lt_name); } names.sort(); - let name = token::str_to_ident(&names[0][]).name; + let name = token::str_to_ident(&names[0]).name; return (name_to_dummy_lifetime(name), Kept); } return (self.life_giver.give_lifetime(), Fresh); @@ -1233,16 +1220,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } ty_queue.push(&*mut_ty.ty); } - ast::TyPath(ref path, id) => { - let a_def = match self.tcx.def_map.borrow().get(&id) { + ast::TyPath(ref maybe_qself, ref path) => { + let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) { None => { self.tcx .sess .fatal(&format!( "unbound path {}", - pprust::path_to_string(path))[]) + pprust::path_to_string(path))) } - Some(&d) => d + Some(d) => d.full_def() }; match a_def { def::DefTy(did, _) | def::DefStruct(did) => { @@ -1277,9 +1264,16 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { region_names: region_names }; let new_path = self.rebuild_path(rebuild_info, lifetime); + let qself = maybe_qself.as_ref().map(|qself| { + ast::QSelf { + ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime, + anon_nums, region_names), + position: qself.position + } + }); let to = ast::Ty { id: cur_ty.id, - node: ast::TyPath(new_path, id), + node: ast::TyPath(qself, new_path), span: cur_ty.span }; new_ty = self.rebuild_ty(new_ty, P(to)); @@ -1479,7 +1473,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { var_origin.span(), &format!("cannot infer an appropriate lifetime{} \ due to conflicting requirements", - var_description)[]); + var_description)); } fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) { @@ -1487,38 +1481,38 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { infer::Subtype(ref trace) => { let desc = match trace.origin { infer::Misc(_) => { - format!("types are compatible") + "types are compatible" } infer::MethodCompatCheck(_) => { - format!("method type is compatible with trait") + "method type is compatible with trait" } infer::ExprAssignable(_) => { - format!("expression is assignable") + "expression is assignable" } infer::RelateTraitRefs(_) => { - format!("traits are compatible") + "traits are compatible" } infer::RelateSelfType(_) => { - format!("self type matches impl self type") + "self type matches impl self type" } infer::RelateOutputImplTypes(_) => { - format!("trait type parameters matches those \ - specified on the impl") + "trait type parameters matches those \ + specified on the impl" } infer::MatchExpressionArm(_, _) => { - format!("match arms have compatible types") + "match arms have compatible types" } infer::IfExpression(_) => { - format!("if and else have compatible types") + "if and else have compatible types" } infer::IfExpressionWithNoElse(_) => { - format!("if may be missing an else clause") + "if may be missing an else clause" } infer::RangeExpression(_) => { - format!("start and end of range have compatible types") + "start and end of range have compatible types" } infer::EquatePredicate(_) => { - format!("equality where clause is satisfied") + "equality where clause is satisfied" } }; @@ -1527,7 +1521,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.sess.span_note( trace.origin.span(), &format!("...so that {} ({})", - desc, values_str)[]); + desc, values_str)); } None => { // Really should avoid printing this error at @@ -1536,7 +1530,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { // doing right now. - nmatsakis self.tcx.sess.span_note( trace.origin.span(), - &format!("...so that {}", desc)[]); + &format!("...so that {}", desc)); } } } @@ -1552,7 +1546,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { &format!( "...so that closure can access `{}`", ty::local_var_name_str(self.tcx, upvar_id.var_id) - .to_string())[]) + .to_string())) } infer::InfStackClosure(span) => { self.tcx.sess.span_note( @@ -1577,7 +1571,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { does not outlive the enclosing closure", ty::local_var_name_str( self.tcx, - id).to_string())[]); + id).to_string())); } infer::IndexSlice(span) => { self.tcx.sess.span_note( @@ -1626,7 +1620,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, &format!("...so type `{}` of expression is valid during the \ expression", - self.ty_to_string(t))[]); + self.ty_to_string(t))); } infer::BindingTypeIsNotValidAtDecl(span) => { self.tcx.sess.span_note( @@ -1638,14 +1632,14 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, &format!("...so that the reference type `{}` \ does not outlive the data it points at", - self.ty_to_string(ty))[]); + self.ty_to_string(ty))); } infer::RelateParamBound(span, t) => { self.tcx.sess.span_note( span, &format!("...so that the type `{}` \ will meet its required lifetime bounds", - self.ty_to_string(t))[]); + self.ty_to_string(t))); } infer::RelateDefaultParamBound(span, t) => { self.tcx.sess.span_note( @@ -1653,13 +1647,13 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { &format!("...so that type parameter \ instantiated with `{}`, \ will meet its declared lifetime bounds", - self.ty_to_string(t))[]); + self.ty_to_string(t))); } infer::RelateRegionParamBound(span) => { self.tcx.sess.span_note( span, - &format!("...so that the declared lifetime parameter bounds \ - are satisfied")[]); + "...so that the declared lifetime parameter bounds \ + are satisfied"); } infer::SafeDestructor(span) => { self.tcx.sess.span_note( @@ -1717,18 +1711,19 @@ fn lifetimes_in_scope(tcx: &ty::ctxt, Some(node) => match node { ast_map::NodeItem(item) => match item.node { ast::ItemFn(_, _, _, ref gen, _) => { - taken.push_all(&gen.lifetimes[]); + taken.push_all(&gen.lifetimes); None }, _ => None }, ast_map::NodeImplItem(ii) => { - match *ii { - ast::MethodImplItem(ref m) => { - taken.push_all(&m.pe_generics().lifetimes[]); - Some(m.id) + match ii.node { + ast::MethodImplItem(ref sig, _) => { + taken.push_all(&sig.generics.lifetimes); + Some(ii.id) } ast::TypeImplItem(_) => None, + ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro") } } _ => None @@ -1757,7 +1752,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt, // LifeGiver is responsible for generating fresh lifetime names struct LifeGiver { taken: HashSet, - counter: Cell, + counter: Cell, generated: RefCell>, } @@ -1784,7 +1779,7 @@ impl LifeGiver { let mut lifetime; loop { let mut s = String::from_str("'"); - s.push_str(&num_to_string(self.counter.get())[]); + s.push_str(&num_to_string(self.counter.get())); if !self.taken.contains(&s) { lifetime = name_to_dummy_lifetime( token::str_to_ident(&s[..]).name); @@ -1797,7 +1792,7 @@ impl LifeGiver { return lifetime; // 0 .. 25 generates a .. z, 26 .. 51 generates aa .. zz, and so on - fn num_to_string(counter: uint) -> String { + fn num_to_string(counter: usize) -> String { let mut s = String::new(); let (n, r) = (counter/26 + 1, counter % 26); let letter: char = from_u32((r+97) as u32).unwrap(); diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs index 1b7e6c33c0..29f74d12ea 100644 --- a/src/librustc/middle/infer/freshen.rs +++ b/src/librustc/middle/infer/freshen.rs @@ -37,7 +37,7 @@ use middle::ty_fold::TypeFolder; use std::collections::hash_map::{self, Entry}; use super::InferCtxt; -use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; +use super::unify::ToType; pub struct TypeFreshener<'a, 'tcx:'a> { infcx: &'a InferCtxt<'a, 'tcx>, @@ -104,29 +104,38 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + let tcx = self.infcx.tcx; + match t.sty { ty::ty_infer(ty::TyVar(v)) => { - self.freshen(self.infcx.type_variables.borrow().probe(v), - ty::TyVar(v), - ty::FreshTy) + self.freshen( + self.infcx.type_variables.borrow().probe(v), + ty::TyVar(v), + ty::FreshTy) } ty::ty_infer(ty::IntVar(v)) => { - self.freshen(self.infcx.probe_var(v), - ty::IntVar(v), - ty::FreshIntTy) + self.freshen( + self.infcx.int_unification_table.borrow_mut() + .probe(v) + .map(|v| v.to_type(tcx)), + ty::IntVar(v), + ty::FreshIntTy) } ty::ty_infer(ty::FloatVar(v)) => { - self.freshen(self.infcx.probe_var(v), - ty::FloatVar(v), - ty::FreshIntTy) + self.freshen( + self.infcx.float_unification_table.borrow_mut() + .probe(v) + .map(|v| v.to_type(tcx)), + ty::FloatVar(v), + ty::FreshIntTy) } ty::ty_infer(ty::FreshTy(c)) | ty::ty_infer(ty::FreshIntTy(c)) => { if c >= self.freshen_count { - self.tcx().sess.bug( + tcx.sess.bug( &format!("Encountered a freshend type with id {} \ but our counter is only at {}", c, @@ -135,7 +144,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { t } - ty::ty_open(..) | ty::ty_bool | ty::ty_char | ty::ty_int(..) | diff --git a/src/librustc/middle/infer/glb.rs b/src/librustc/middle/infer/glb.rs index 33303808e8..5822fb0f2d 100644 --- a/src/librustc/middle/infer/glb.rs +++ b/src/librustc/middle/infer/glb.rs @@ -8,117 +8,79 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::combine::*; -use super::lattice::*; +use super::combine::CombineFields; use super::higher_ranked::HigherRankedRelations; -use super::{cres}; +use super::InferCtxt; +use super::lattice::{self, LatticeDir}; use super::Subtype; -use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; -use syntax::ast::{MutImmutable, MutMutable, Unsafety}; -use util::ppaux::mt_to_string; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use util::ppaux::Repr; /// "Greatest lower bound" (common subtype) -pub struct Glb<'f, 'tcx: 'f> { - fields: CombineFields<'f, 'tcx> +pub struct Glb<'a, 'tcx: 'a> { + fields: CombineFields<'a, 'tcx> } -#[allow(non_snake_case)] -pub fn Glb<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Glb<'f, 'tcx> { - Glb { fields: cf } -} - -impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> { - fn tag(&self) -> String { "Glb".to_string() } - fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - - fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> - { - match v { - ty::Invariant => self.equate().tys(a, b), - ty::Covariant => self.tys(a, b), - ty::Bivariant => self.bivariate().tys(a, b), - ty::Contravariant => self.lub().tys(a, b), - } +impl<'a, 'tcx> Glb<'a, 'tcx> { + pub fn new(fields: CombineFields<'a, 'tcx>) -> Glb<'a, 'tcx> { + Glb { fields: fields } } +} - fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> - { - match v { - ty::Invariant => self.equate().regions(a, b), - ty::Covariant => self.regions(a, b), - ty::Bivariant => self.bivariate().regions(a, b), - ty::Contravariant => self.lub().regions(a, b), - } - } - - fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { - let tcx = self.fields.infcx.tcx; - - debug!("{}.mts({}, {})", - self.tag(), - mt_to_string(tcx, a), - mt_to_string(tcx, b)); - - match (a.mutbl, b.mutbl) { - // If one side or both is mut, then the GLB must use - // the precise type from the mut side. - (MutMutable, MutMutable) => { - let t = try!(self.equate().tys(a.ty, b.ty)); - Ok(ty::mt {ty: t, mutbl: MutMutable}) - } +impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> { + fn tag(&self) -> &'static str { "Glb" } - // If one side or both is immutable, we can use the GLB of - // both sides but mutbl must be `MutImmutable`. - (MutImmutable, MutImmutable) => { - let t = try!(self.tys(a.ty, b.ty)); - Ok(ty::mt {ty: t, mutbl: MutImmutable}) - } + fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() } - // There is no mutual subtype of these combinations. - (MutMutable, MutImmutable) | - (MutImmutable, MutMutable) => { - Err(ty::terr_mutability) - } - } - } + fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { - match (a, b) { - (Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal), - (Unsafety::Unsafe, Unsafety::Unsafe) => Ok(Unsafety::Unsafe) + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> + { + match variance { + ty::Invariant => self.fields.equate().relate(a, b), + ty::Covariant => self.relate(a, b), + ty::Bivariant => self.fields.bivariate().relate(a, b), + ty::Contravariant => self.fields.lub().relate(a, b), } } - fn builtin_bounds(&self, - a: ty::BuiltinBounds, - b: ty::BuiltinBounds) - -> cres<'tcx, ty::BuiltinBounds> { - // More bounds is a subtype of fewer bounds, so - // the GLB (mutual subtype) is the union. - Ok(a.union(b)) + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + lattice::super_lattice_tys(self, a, b) } - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { debug!("{}.regions({}, {})", self.tag(), a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx)); - Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b)) + let origin = Subtype(self.fields.trace.clone()); + Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b)) } - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - super_lattice_tys(self, a, b) + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a, 'tcx> + { + self.fields.higher_ranked_glb(a, b) } +} - fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> - where T : Combineable<'tcx> - { - self.higher_ranked_glb(a, b) +impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> { + fn infcx(&self) -> &'a InferCtxt<'a,'tcx> { + self.fields.infcx + } + + fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { + let mut sub = self.fields.sub(); + try!(sub.relate(&v, &a)); + try!(sub.relate(&v, &b)); + Ok(()) } } diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index a729156c88..f347d28b93 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -11,24 +11,26 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType, SkolemizationMap}; -use super::combine::{Combine, Combineable}; +use super::{CombinedSnapshot, InferCtxt, HigherRankedType, SkolemizationMap}; +use super::combine::CombineFields; +use middle::subst; use middle::ty::{self, Binder}; use middle::ty_fold::{self, TypeFoldable}; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use syntax::codemap::Span; use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux::Repr; -pub trait HigherRankedRelations<'tcx> { - fn higher_ranked_sub(&self, a: &Binder, b: &Binder) -> cres<'tcx, Binder> - where T : Combineable<'tcx>; +pub trait HigherRankedRelations<'a,'tcx> { + fn higher_ranked_sub(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> + where T: Relate<'a,'tcx>; - fn higher_ranked_lub(&self, a: &Binder, b: &Binder) -> cres<'tcx, Binder> - where T : Combineable<'tcx>; + fn higher_ranked_lub(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> + where T: Relate<'a,'tcx>; - fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> cres<'tcx, Binder> - where T : Combineable<'tcx>; + fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> + where T: Relate<'a,'tcx>; } trait InferCtxtExt { @@ -39,15 +41,15 @@ trait InferCtxtExt { -> Vec; } -impl<'tcx,C> HigherRankedRelations<'tcx> for C - where C : Combine<'tcx> -{ +impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { fn higher_ranked_sub(&self, a: &Binder, b: &Binder) - -> cres<'tcx, Binder> - where T : Combineable<'tcx> + -> RelateResult<'tcx, Binder> + where T: Relate<'a,'tcx> { + let tcx = self.infcx.tcx; + debug!("higher_ranked_sub(a={}, b={})", - a.repr(self.tcx()), b.repr(self.tcx())); + a.repr(tcx), b.repr(tcx)); // Rather than checking the subtype relationship between `a` and `b` // as-is, we need to do some extra work here in order to make sure @@ -59,32 +61,32 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C // Start a snapshot so we can examine "all bindings that were // created as part of this type comparison". - return self.infcx().try(|snapshot| { + return self.infcx.commit_if_ok(|snapshot| { // First, we instantiate each bound region in the subtype with a fresh // region variable. let (a_prime, _) = - self.infcx().replace_late_bound_regions_with_fresh_var( - self.trace().origin.span(), + self.infcx.replace_late_bound_regions_with_fresh_var( + self.trace.origin.span(), HigherRankedType, a); // Second, we instantiate each bound region in the supertype with a // fresh concrete region. let (b_prime, skol_map) = - self.infcx().skolemize_late_bound_regions(b, snapshot); + self.infcx.skolemize_late_bound_regions(b, snapshot); - debug!("a_prime={}", a_prime.repr(self.tcx())); - debug!("b_prime={}", b_prime.repr(self.tcx())); + debug!("a_prime={}", a_prime.repr(tcx)); + debug!("b_prime={}", b_prime.repr(tcx)); // Compare types now that bound regions have been replaced. - let result = try!(Combineable::combine(self, &a_prime, &b_prime)); + let result = try!(self.sub().relate(&a_prime, &b_prime)); // Presuming type comparison succeeds, we need to check // that the skolemized regions do not "leak". - match leak_check(self.infcx(), &skol_map, snapshot) { + match leak_check(self.infcx, &skol_map, snapshot) { Ok(()) => { } Err((skol_br, tainted_region)) => { - if self.a_is_expected() { + if self.a_is_expected { debug!("Not as polymorphic!"); return Err(ty::terr_regions_insufficiently_polymorphic(skol_br, tainted_region)); @@ -97,42 +99,42 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C } debug!("higher_ranked_sub: OK result={}", - result.repr(self.tcx())); + result.repr(tcx)); Ok(ty::Binder(result)) }); } - fn higher_ranked_lub(&self, a: &Binder, b: &Binder) -> cres<'tcx, Binder> - where T : Combineable<'tcx> + fn higher_ranked_lub(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> + where T: Relate<'a,'tcx> { // Start a snapshot so we can examine "all bindings that were // created as part of this type comparison". - return self.infcx().try(|snapshot| { + return self.infcx.commit_if_ok(|snapshot| { // Instantiate each bound region with a fresh region variable. - let span = self.trace().origin.span(); + let span = self.trace.origin.span(); let (a_with_fresh, a_map) = - self.infcx().replace_late_bound_regions_with_fresh_var( + self.infcx.replace_late_bound_regions_with_fresh_var( span, HigherRankedType, a); let (b_with_fresh, _) = - self.infcx().replace_late_bound_regions_with_fresh_var( + self.infcx.replace_late_bound_regions_with_fresh_var( span, HigherRankedType, b); // Collect constraints. let result0 = - try!(Combineable::combine(self, &a_with_fresh, &b_with_fresh)); + try!(self.lub().relate(&a_with_fresh, &b_with_fresh)); let result0 = - self.infcx().resolve_type_vars_if_possible(&result0); + self.infcx.resolve_type_vars_if_possible(&result0); debug!("lub result0 = {}", result0.repr(self.tcx())); // Generalize the regions appearing in result0 if possible - let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot); - let span = self.trace().origin.span(); + let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot); + let span = self.trace.origin.span(); let result1 = fold_regions_in( self.tcx(), &result0, - |r, debruijn| generalize_region(self.infcx(), span, snapshot, debruijn, + |r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn, &new_vars, &a_map, r)); debug!("lub({},{}) = {}", @@ -189,44 +191,44 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C span, &format!("region {:?} is not associated with \ any bound region from A!", - r0)[]) + r0)) } } - fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> cres<'tcx, Binder> - where T : Combineable<'tcx> + fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> + where T: Relate<'a,'tcx> { - debug!("{}.higher_ranked_glb({}, {})", - self.tag(), a.repr(self.tcx()), b.repr(self.tcx())); + debug!("higher_ranked_glb({}, {})", + a.repr(self.tcx()), b.repr(self.tcx())); // Make a snapshot so we can examine "all bindings that were // created as part of this type comparison". - return self.infcx().try(|snapshot| { + return self.infcx.commit_if_ok(|snapshot| { // Instantiate each bound region with a fresh region variable. let (a_with_fresh, a_map) = - self.infcx().replace_late_bound_regions_with_fresh_var( - self.trace().origin.span(), HigherRankedType, a); + self.infcx.replace_late_bound_regions_with_fresh_var( + self.trace.origin.span(), HigherRankedType, a); let (b_with_fresh, b_map) = - self.infcx().replace_late_bound_regions_with_fresh_var( - self.trace().origin.span(), HigherRankedType, b); + self.infcx.replace_late_bound_regions_with_fresh_var( + self.trace.origin.span(), HigherRankedType, b); let a_vars = var_ids(self, &a_map); let b_vars = var_ids(self, &b_map); // Collect constraints. let result0 = - try!(Combineable::combine(self, &a_with_fresh, &b_with_fresh)); + try!(self.glb().relate(&a_with_fresh, &b_with_fresh)); let result0 = - self.infcx().resolve_type_vars_if_possible(&result0); + self.infcx.resolve_type_vars_if_possible(&result0); debug!("glb result0 = {}", result0.repr(self.tcx())); // Generalize the regions appearing in result0 if possible - let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot); - let span = self.trace().origin.span(); + let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot); + let span = self.trace.origin.span(); let result1 = fold_regions_in( self.tcx(), &result0, - |r, debruijn| generalize_region(self.infcx(), span, snapshot, debruijn, + |r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn, &new_vars, &a_map, &a_vars, &b_vars, r)); @@ -322,7 +324,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C } infcx.tcx.sess.span_bug( span, - &format!("could not find original bound region for {:?}", r)[]); + &format!("could not find original bound region for {:?}", r)); } fn fresh_bound_variable(infcx: &InferCtxt, debruijn: ty::DebruijnIndex) -> ty::Region { @@ -331,17 +333,19 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C } } -fn var_ids<'tcx, T: Combine<'tcx>>(combiner: &T, - map: &FnvHashMap) - -> Vec { - map.iter().map(|(_, r)| match *r { - ty::ReInfer(ty::ReVar(r)) => { r } - r => { - combiner.infcx().tcx.sess.span_bug( - combiner.trace().origin.span(), - &format!("found non-region-vid: {:?}", r)[]); - } - }).collect() +fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx>, + map: &FnvHashMap) + -> Vec { + map.iter() + .map(|(_, r)| match *r { + ty::ReInfer(ty::ReVar(r)) => { r } + r => { + fields.tcx().sess.span_bug( + fields.trace.origin.span(), + &format!("found non-region-vid: {:?}", r)); + } + }) + .collect() } fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region) -> bool { @@ -355,8 +359,8 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>, unbound_value: &T, mut fldr: F) -> T - where T : Combineable<'tcx>, - F : FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region, + where T: TypeFoldable<'tcx>, + F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region, { unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, &mut |region, current_depth| { // we should only be encountering "escaping" late-bound regions here, @@ -455,6 +459,63 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> { } } +/// Constructs and returns a substitution that, for a given type +/// scheme parameterized by `generics`, will replace every generic +/// parmeter in the type with a skolemized type/region (which one can +/// think of as a "fresh constant", except at the type/region level of +/// reasoning). +/// +/// Since we currently represent bound/free type parameters in the +/// same way, this only has an effect on regions. +/// +/// (Note that unlike a substitution from `ty::construct_free_substs`, +/// this inserts skolemized regions rather than free regions; this +/// allows one to use `fn leak_check` to catch attmepts to unify the +/// skolemized regions with e.g. the `'static` lifetime) +pub fn construct_skolemized_substs<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + generics: &ty::Generics<'tcx>, + snapshot: &CombinedSnapshot) + -> (subst::Substs<'tcx>, SkolemizationMap) +{ + let mut map = FnvHashMap(); + + // map T => T + let mut types = subst::VecPerParamSpace::empty(); + push_types_from_defs(infcx.tcx, &mut types, generics.types.as_slice()); + + // map early- or late-bound 'a => fresh 'a + let mut regions = subst::VecPerParamSpace::empty(); + push_region_params(infcx, &mut map, &mut regions, generics.regions.as_slice(), snapshot); + + let substs = subst::Substs { types: types, + regions: subst::NonerasedRegions(regions) }; + return (substs, map); + + fn push_region_params<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + map: &mut SkolemizationMap, + regions: &mut subst::VecPerParamSpace, + region_params: &[ty::RegionParameterDef], + snapshot: &CombinedSnapshot) + { + for r in region_params { + let br = r.to_bound_region(); + let skol_var = infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot); + let sanity_check = map.insert(br, skol_var); + assert!(sanity_check.is_none()); + regions.push(r.space, skol_var); + } + } + + fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>, + types: &mut subst::VecPerParamSpace>, + defs: &[ty::TypeParameterDef<'tcx>]) { + for def in defs { + let ty = ty::mk_param_from_def(tcx, def); + types.push(def.space, ty); + } + } +} + pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, binder: &ty::Binder, snapshot: &CombinedSnapshot) @@ -465,7 +526,8 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, * Replace all regions bound by `binder` with skolemized regions and * return a map indicating which bound-region was replaced with what * skolemized region. This is the first step of checking subtyping - * when higher-ranked things are involved. See `doc.rs` for more details. + * when higher-ranked things are involved. See `README.md` for more + * details. */ let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br| { @@ -490,7 +552,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, * and checks to determine whether any of the skolemized regions created * in `skol_map` would "escape" -- meaning that they are related to * other regions in some way. If so, the higher-ranked subtyping doesn't - * hold. See `doc.rs` for more details. + * hold. See `README.md` for more details. */ debug!("leak_check: skol_map={}", @@ -533,7 +595,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, /// passed; currently, it's used in the trait matching code to create /// a set of nested obligations frmo an impl that matches against /// something higher-ranked. More details can be found in -/// `middle::traits::doc.rs`. +/// `librustc/middle/traits/README.md`. /// /// As a brief example, consider the obligation `for<'a> Fn(&'a int) /// -> &'a int`, and the impl: diff --git a/src/librustc/middle/infer/lattice.rs b/src/librustc/middle/infer/lattice.rs index 121e5405f2..57001083b0 100644 --- a/src/librustc/middle/infer/lattice.rs +++ b/src/librustc/middle/infer/lattice.rs @@ -29,48 +29,32 @@ //! over a `LatticeValue`, which is a value defined with respect to //! a lattice. -use super::*; -use super::combine::*; -use super::glb::Glb; -use super::lub::Lub; +use super::combine; +use super::InferCtxt; -use middle::ty::{TyVar}; +use middle::ty::TyVar; use middle::ty::{self, Ty}; +use middle::ty_relate::{RelateResult, TypeRelation}; use util::ppaux::Repr; -pub trait LatticeDir<'tcx> { +pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> { + fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>; + // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. - fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()>; -} - -impl<'a, 'tcx> LatticeDir<'tcx> for Lub<'a, 'tcx> { - fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()> { - let sub = self.sub(); - try!(sub.tys(a, v)); - try!(sub.tys(b, v)); - Ok(()) - } -} - -impl<'a, 'tcx> LatticeDir<'tcx> for Glb<'a, 'tcx> { - fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()> { - let sub = self.sub(); - try!(sub.tys(v, a)); - try!(sub.tys(v, b)); - Ok(()) - } + fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>; } -pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> +pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L, + a: Ty<'tcx>, + b: Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where 'tcx: 'a { debug!("{}.lattice_tys({}, {})", this.tag(), - a.repr(this.infcx().tcx), - b.repr(this.infcx().tcx)); + a.repr(this.tcx()), + b.repr(this.tcx())); if a == b { return Ok(a); @@ -95,7 +79,7 @@ pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L, } _ => { - super_tys(this, a, b) + combine::super_combine_tys(this.infcx(), this, a, b) } } } diff --git a/src/librustc/middle/infer/lub.rs b/src/librustc/middle/infer/lub.rs index 3570effa9f..f456687be1 100644 --- a/src/librustc/middle/infer/lub.rs +++ b/src/librustc/middle/infer/lub.rs @@ -8,112 +8,80 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::combine::*; +use super::combine::CombineFields; use super::higher_ranked::HigherRankedRelations; -use super::lattice::*; -use super::{cres}; -use super::{Subtype}; +use super::InferCtxt; +use super::lattice::{self, LatticeDir}; +use super::Subtype; -use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; -use syntax::ast::{MutMutable, MutImmutable, Unsafety}; -use util::ppaux::mt_to_string; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use util::ppaux::Repr; /// "Least upper bound" (common supertype) -pub struct Lub<'f, 'tcx: 'f> { - fields: CombineFields<'f, 'tcx> +pub struct Lub<'a, 'tcx: 'a> { + fields: CombineFields<'a, 'tcx> } -#[allow(non_snake_case)] -pub fn Lub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Lub<'f, 'tcx> { - Lub { fields: cf } -} - -impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> { - fn tag(&self) -> String { "Lub".to_string() } - fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } - - fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> - { - match v { - ty::Invariant => self.equate().tys(a, b), - ty::Covariant => self.tys(a, b), - ty::Bivariant => self.bivariate().tys(a, b), - ty::Contravariant => self.glb().tys(a, b), - } - } - - fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> - { - match v { - ty::Invariant => self.equate().regions(a, b), - ty::Covariant => self.regions(a, b), - ty::Bivariant => self.bivariate().regions(a, b), - ty::Contravariant => self.glb().regions(a, b), - } +impl<'a, 'tcx> Lub<'a, 'tcx> { + pub fn new(fields: CombineFields<'a, 'tcx>) -> Lub<'a, 'tcx> { + Lub { fields: fields } } +} - fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { - let tcx = self.tcx(); - - debug!("{}.mts({}, {})", - self.tag(), - mt_to_string(tcx, a), - mt_to_string(tcx, b)); - - if a.mutbl != b.mutbl { - return Err(ty::terr_mutability) - } +impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> { + fn tag(&self) -> &'static str { "Lub" } - let m = a.mutbl; - match m { - MutImmutable => { - let t = try!(self.tys(a.ty, b.ty)); - Ok(ty::mt {ty: t, mutbl: m}) - } + fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() } - MutMutable => { - let t = try!(self.equate().tys(a.ty, b.ty)); - Ok(ty::mt {ty: t, mutbl: m}) - } - } - } + fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { - match (a, b) { - (Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe), - (Unsafety::Normal, Unsafety::Normal) => Ok(Unsafety::Normal), + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> + { + match variance { + ty::Invariant => self.fields.equate().relate(a, b), + ty::Covariant => self.relate(a, b), + ty::Bivariant => self.fields.bivariate().relate(a, b), + ty::Contravariant => self.fields.glb().relate(a, b), } } - fn builtin_bounds(&self, - a: ty::BuiltinBounds, - b: ty::BuiltinBounds) - -> cres<'tcx, ty::BuiltinBounds> { - // More bounds is a subtype of fewer bounds, so - // the LUB (mutual supertype) is the intersection. - Ok(a.intersection(b)) + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + lattice::super_lattice_tys(self, a, b) } - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { debug!("{}.regions({}, {})", self.tag(), a.repr(self.tcx()), b.repr(self.tcx())); - Ok(self.infcx().region_vars.lub_regions(Subtype(self.trace()), a, b)) + let origin = Subtype(self.fields.trace.clone()); + Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b)) } - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - super_lattice_tys(self, a, b) + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a, 'tcx> + { + self.fields.higher_ranked_lub(a, b) } +} - fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> - where T : Combineable<'tcx> - { - self.higher_ranked_lub(a, b) +impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> { + fn infcx(&self) -> &'a InferCtxt<'a,'tcx> { + self.fields.infcx + } + + fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { + let mut sub = self.fields.sub(); + try!(sub.relate(&a, &v)); + try!(sub.relate(&b, &v)); + Ok(()) } } + diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index b0576ff55f..b11e25c059 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -28,21 +28,20 @@ use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric}; use middle::ty::replace_late_bound_regions; use middle::ty::{self, Ty}; use middle::ty_fold::{TypeFolder, TypeFoldable}; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use std::cell::{RefCell}; +use std::fmt; use std::rc::Rc; use syntax::ast; use syntax::codemap; use syntax::codemap::Span; use util::nodemap::FnvHashMap; -use util::ppaux::{ty_to_string}; +use util::ppaux::ty_to_string; use util::ppaux::{Repr, UserString}; -use self::combine::{Combine, Combineable, CombineFields}; +use self::combine::CombineFields; use self::region_inference::{RegionVarBindings, RegionSnapshot}; -use self::equate::Equate; -use self::sub::Sub; -use self::lub::Lub; -use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes}; +use self::unify::{ToType, UnificationTable}; use self::error_reporting::ErrorReporting; pub mod bivariate; @@ -61,9 +60,7 @@ pub mod type_variable; pub mod unify; pub type Bound = Option; - -pub type cres<'tcx, T> = Result>; // "combine result" -pub type ures<'tcx> = cres<'tcx, ()>; // "unify result" +pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type fres = Result; // "fixup result" pub struct InferCtxt<'a, 'tcx: 'a> { @@ -128,6 +125,30 @@ pub enum TypeOrigin { EquatePredicate(Span), } +impl TypeOrigin { + fn as_str(&self) -> &'static str { + match self { + &TypeOrigin::Misc(_) | + &TypeOrigin::RelateSelfType(_) | + &TypeOrigin::RelateOutputImplTypes(_) | + &TypeOrigin::ExprAssignable(_) => "mismatched types", + &TypeOrigin::RelateTraitRefs(_) => "mismatched traits", + &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait", + &TypeOrigin::MatchExpressionArm(_, _) => "match arms have incompatible types", + &TypeOrigin::IfExpression(_) => "if and else have incompatible types", + &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause", + &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types", + &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied", + } + } +} + +impl fmt::Display for TypeOrigin { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> { + fmt::Display::fmt(self.as_str(), f) + } +} + /// See `error_reporting.rs` for more details #[derive(Clone, Debug)] pub enum ValuePairs<'tcx> { @@ -240,7 +261,7 @@ pub enum LateBoundRegionConversionTime { /// /// See `error_reporting.rs` for more details #[derive(Clone, Debug)] -pub enum RegionVariableOrigin<'tcx> { +pub enum RegionVariableOrigin { // Region variables created for ill-categorized reasons, // mostly indicates places in need of refactoring MiscVariable(Span), @@ -255,7 +276,7 @@ pub enum RegionVariableOrigin<'tcx> { Autoref(Span), // Regions created as part of an automatic coercion - Coercion(TypeTrace<'tcx>), + Coercion(Span), // Region variables created as the values for early-bound regions EarlyBoundRegion(Span, ast::Name), @@ -269,7 +290,7 @@ pub enum RegionVariableOrigin<'tcx> { BoundRegionInCoherence(ast::Name), } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum fixup_err { unresolved_int_ty(IntVid), unresolved_float_ty(FloatVid), @@ -318,8 +339,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, values: Types(expected_found(a_is_expected, a, b)) }; - let result = - cx.commit_if_ok(|| cx.lub(a_is_expected, trace.clone()).tys(a, b)); + let result = cx.commit_if_ok(|_| cx.lub(a_is_expected, trace.clone()).relate(&a, &b)); match result { Ok(t) => t, Err(ref err) => { @@ -334,29 +354,28 @@ pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> ures<'tcx> + -> UnitResult<'tcx> { debug!("mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx)); - cx.commit_if_ok(|| { - cx.sub_types(a_is_expected, origin, a, b) - }) + cx.sub_types(a_is_expected, origin, a, b) } pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) - -> ures<'tcx> { + -> UnitResult<'tcx> { debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx)); cx.probe(|_| { let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP), values: Types(expected_found(true, a, b)) }; - cx.sub(true, trace).tys(a, b).to_ures() + cx.sub(true, trace).relate(&a, &b).map(|_| ()) }) } -pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> ures<'tcx> +pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) + -> UnitResult<'tcx> { cx.can_equate(&a, &b) } @@ -376,11 +395,10 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> ures<'tcx> + -> UnitResult<'tcx> { debug!("mk_eqty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx)); - cx.commit_if_ok( - || cx.eq_types(a_is_expected, origin, a, b)) + cx.commit_if_ok(|_| cx.eq_types(a_is_expected, origin, a, b)) } pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, @@ -388,12 +406,11 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: ty::PolyTraitRef<'tcx>, b: ty::PolyTraitRef<'tcx>) - -> ures<'tcx> + -> UnitResult<'tcx> { debug!("mk_sub_trait_refs({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx)); - cx.commit_if_ok( - || cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone())) + cx.commit_if_ok(|_| cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone())) } fn expected_found(a_is_expected: bool, @@ -408,57 +425,6 @@ fn expected_found(a_is_expected: bool, } } -trait then<'tcx> { - fn then(&self, f: F) -> Result> where - T: Clone, - F: FnOnce() -> Result>; -} - -impl<'tcx> then<'tcx> for ures<'tcx> { - fn then(&self, f: F) -> Result> where - T: Clone, - F: FnOnce() -> Result>, - { - self.and_then(move |_| f()) - } -} - -trait ToUres<'tcx> { - fn to_ures(&self) -> ures<'tcx>; -} - -impl<'tcx, T> ToUres<'tcx> for cres<'tcx, T> { - fn to_ures(&self) -> ures<'tcx> { - match *self { - Ok(ref _v) => Ok(()), - Err(ref e) => Err((*e)) - } - } -} - -trait CresCompare<'tcx, T> { - fn compare(&self, t: T, f: F) -> cres<'tcx, T> where - F: FnOnce() -> ty::type_err<'tcx>; -} - -impl<'tcx, T:Clone + PartialEq> CresCompare<'tcx, T> for cres<'tcx, T> { - fn compare(&self, t: T, f: F) -> cres<'tcx, T> where - F: FnOnce() -> ty::type_err<'tcx>, - { - (*self).clone().and_then(move |s| { - if s == t { - (*self).clone() - } else { - Err(f()) - } - }) - } -} - -pub fn uok<'tcx>() -> ures<'tcx> { - Ok(()) -} - #[must_use = "once you start a snapshot, you should always consume it"] pub struct CombinedSnapshot { type_snapshot: type_variable::Snapshot, @@ -487,41 +453,56 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat}; match ty.sty { ty::ty_infer(ty::IntVar(vid)) => { - match self.int_unification_table.borrow_mut().get(self.tcx, vid).value { - None => UnconstrainedInt, - _ => Neither, + if self.int_unification_table.borrow_mut().has_value(vid) { + Neither + } else { + UnconstrainedInt } }, ty::ty_infer(ty::FloatVar(vid)) => { - match self.float_unification_table.borrow_mut().get(self.tcx, vid).value { - None => return UnconstrainedFloat, - _ => Neither, + if self.float_unification_table.borrow_mut().has_value(vid) { + Neither + } else { + UnconstrainedFloat } }, _ => Neither, } } - pub fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> CombineFields<'b, 'tcx> { + fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) + -> CombineFields<'a, 'tcx> { CombineFields {infcx: self, a_is_expected: a_is_expected, trace: trace} } - pub fn equate<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> Equate<'b, 'tcx> { - Equate(self.combine_fields(a_is_expected, trace)) + // public so that it can be used from the rustc_driver unit tests + pub fn equate(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) + -> equate::Equate<'a, 'tcx> + { + self.combine_fields(a_is_expected, trace).equate() + } + + // public so that it can be used from the rustc_driver unit tests + pub fn sub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) + -> sub::Sub<'a, 'tcx> + { + self.combine_fields(a_is_expected, trace).sub() } - pub fn sub<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> Sub<'b, 'tcx> { - Sub(self.combine_fields(a_is_expected, trace)) + // public so that it can be used from the rustc_driver unit tests + pub fn lub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) + -> lub::Lub<'a, 'tcx> + { + self.combine_fields(a_is_expected, trace).lub() } - pub fn lub<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> Lub<'b, 'tcx> { - Lub(self.combine_fields(a_is_expected, trace)) + // public so that it can be used from the rustc_driver unit tests + pub fn glb(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) + -> glb::Glb<'a, 'tcx> + { + self.combine_fields(a_is_expected, trace).glb() } fn start_snapshot(&self) -> CombinedSnapshot { @@ -584,11 +565,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { r } - /// Execute `f` and commit the bindings if successful + /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)` pub fn commit_if_ok(&self, f: F) -> Result where - F: FnOnce() -> Result + F: FnOnce(&CombinedSnapshot) -> Result { - self.commit_unconditionally(move || self.try(move |_| f())) + debug!("commit_if_ok()"); + let snapshot = self.start_snapshot(); + let r = f(&snapshot); + debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); + match r { + Ok(_) => { self.commit_from(snapshot); } + Err(_) => { self.rollback_to(snapshot); } + } + r } /// Execute `f` and commit only the region bindings if successful. @@ -603,7 +592,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { float_snapshot, region_vars_snapshot } = self.start_snapshot(); - let r = self.try(move |_| f()); + let r = self.commit_if_ok(|_| f()); // Roll back any non-region bindings - they should be resolved // inside `f`, with, e.g. `resolve_type_vars_if_possible`. @@ -624,25 +613,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { r } - /// Execute `f`, unroll bindings on panic - pub fn try(&self, f: F) -> Result where - F: FnOnce(&CombinedSnapshot) -> Result - { - debug!("try()"); - let snapshot = self.start_snapshot(); - let r = f(&snapshot); - debug!("try() -- r.is_ok() = {}", r.is_ok()); - match r { - Ok(_) => { - self.commit_from(snapshot); - } - Err(_) => { - self.rollback_to(snapshot); - } - } - r - } - /// Execute `f` then unroll any bindings it creates pub fn probe(&self, f: F) -> R where F: FnOnce(&CombinedSnapshot) -> R, @@ -666,12 +636,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> ures<'tcx> + -> UnitResult<'tcx> { debug!("sub_types({} <: {})", a.repr(self.tcx), b.repr(self.tcx)); - self.commit_if_ok(|| { + self.commit_if_ok(|_| { let trace = TypeTrace::types(origin, a_is_expected, a, b); - self.sub(a_is_expected, trace).tys(a, b).to_ures() + self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) }) } @@ -680,11 +650,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> ures<'tcx> + -> UnitResult<'tcx> { - self.commit_if_ok(|| { + self.commit_if_ok(|_| { let trace = TypeTrace::types(origin, a_is_expected, a, b); - self.equate(a_is_expected, trace).tys(a, b).to_ures() + self.equate(a_is_expected, trace).relate(&a, &b).map(|_| ()) }) } @@ -693,17 +663,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: Rc>, b: Rc>) - -> ures<'tcx> + -> UnitResult<'tcx> { debug!("sub_trait_refs({} <: {})", a.repr(self.tcx), b.repr(self.tcx)); - self.commit_if_ok(|| { + self.commit_if_ok(|_| { let trace = TypeTrace { origin: origin, values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) }; - self.sub(a_is_expected, trace).trait_refs(&*a, &*b).to_ures() + self.sub(a_is_expected, trace).relate(&*a, &*b).map(|_| ()) }) } @@ -712,20 +682,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: ty::PolyTraitRef<'tcx>, b: ty::PolyTraitRef<'tcx>) - -> ures<'tcx> + -> UnitResult<'tcx> { debug!("sub_poly_trait_refs({} <: {})", a.repr(self.tcx), b.repr(self.tcx)); - self.commit_if_ok(|| { + self.commit_if_ok(|_| { let trace = TypeTrace { origin: origin, values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) }; - self.sub(a_is_expected, trace).binders(&a, &b).to_ures() + self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) }) } + pub fn construct_skolemized_subst(&self, + generics: &ty::Generics<'tcx>, + snapshot: &CombinedSnapshot) + -> (subst::Substs<'tcx>, SkolemizationMap) { + /*! See `higher_ranked::construct_skolemized_subst` */ + + higher_ranked::construct_skolemized_substs(self, generics, snapshot) + } + pub fn skolemize_late_bound_regions(&self, value: &ty::Binder, snapshot: &CombinedSnapshot) @@ -740,7 +719,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn leak_check(&self, skol_map: &SkolemizationMap, snapshot: &CombinedSnapshot) - -> ures<'tcx> + -> UnitResult<'tcx> { /*! See `higher_ranked::leak_check` */ @@ -765,8 +744,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn equality_predicate(&self, span: Span, predicate: &ty::PolyEquatePredicate<'tcx>) - -> ures<'tcx> { - self.try(|snapshot| { + -> UnitResult<'tcx> { + self.commit_if_ok(|snapshot| { let (ty::EquatePredicate(a, b), skol_map) = self.skolemize_late_bound_regions(predicate, snapshot); let origin = EquatePredicate(span); @@ -778,8 +757,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn region_outlives_predicate(&self, span: Span, predicate: &ty::PolyRegionOutlivesPredicate) - -> ures<'tcx> { - self.try(|snapshot| { + -> UnitResult<'tcx> { + self.commit_if_ok(|snapshot| { let (ty::OutlivesPredicate(r_a, r_b), skol_map) = self.skolemize_late_bound_regions(predicate, snapshot); let origin = RelateRegionParamBound(span); @@ -802,7 +781,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::mk_var(self.tcx, self.next_ty_var_id(true)) } - pub fn next_ty_vars(&self, n: uint) -> Vec> { + pub fn next_ty_vars(&self, n: usize) -> Vec> { (0..n).map(|_i| self.next_ty_var()).collect() } @@ -818,7 +797,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .new_key(None) } - pub fn next_region_var(&self, origin: RegionVariableOrigin<'tcx>) -> ty::Region { + pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region { ty::ReInfer(ty::ReVar(self.region_vars.new_region_var(origin))) } @@ -914,12 +893,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } ty::ty_infer(ty::IntVar(v)) => { - self.probe_var(v) + self.int_unification_table + .borrow_mut() + .probe(v) + .map(|v| v.to_type(self.tcx)) .unwrap_or(typ) } ty::ty_infer(ty::FloatVar(v)) => { - self.probe_var(v) + self.float_unification_table + .borrow_mut() + .probe(v) + .map(|v| v.to_type(self.tcx)) .unwrap_or(typ) } @@ -999,7 +984,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess.span_err(sp, &format!("{}{}", mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty), - error_str)[]); + error_str)); if let Some(err) = err { ty::note_and_explain_type_err(self.tcx, err) @@ -1070,8 +1055,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.region_vars.verify_generic_bound(origin, kind, a, bs); } - pub fn can_equate(&self, a: &T, b: &T) -> ures<'tcx> - where T : Combineable<'tcx> + Repr<'tcx> + pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx> + where T: Relate<'b,'tcx> + Repr<'tcx> { debug!("can_equate({}, {})", a.repr(self.tcx), b.repr(self.tcx)); self.probe(|_| { @@ -1082,9 +1067,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let e = self.tcx.types.err; let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP), values: Types(expected_found(true, e, e)) }; - let eq = self.equate(true, trace); - Combineable::combine(&eq, a, b) - }).to_ures() + self.equate(true, trace).relate(a, b) + }).map(|_| ()) } } @@ -1270,14 +1254,14 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> { } } -impl<'tcx> RegionVariableOrigin<'tcx> { +impl RegionVariableOrigin { pub fn span(&self) -> Span { match *self { MiscVariable(a) => a, PatternRegion(a) => a, AddrOfRegion(a) => a, Autoref(a) => a, - Coercion(ref a) => a.span(), + Coercion(a) => a, EarlyBoundRegion(a, _) => a, LateBoundRegion(a, _, _) => a, BoundRegionInCoherence(_) => codemap::DUMMY_SP, @@ -1286,7 +1270,7 @@ impl<'tcx> RegionVariableOrigin<'tcx> { } } -impl<'tcx> Repr<'tcx> for RegionVariableOrigin<'tcx> { +impl<'tcx> Repr<'tcx> for RegionVariableOrigin { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { MiscVariable(a) => { @@ -1299,7 +1283,7 @@ impl<'tcx> Repr<'tcx> for RegionVariableOrigin<'tcx> { format!("AddrOfRegion({})", a.repr(tcx)) } Autoref(a) => format!("Autoref({})", a.repr(tcx)), - Coercion(ref a) => format!("Coercion({})", a.repr(tcx)), + Coercion(a) => format!("Coercion({})", a.repr(tcx)), EarlyBoundRegion(a, b) => { format!("EarlyBoundRegion({},{})", a.repr(tcx), b.repr(tcx)) } diff --git a/src/librustc/middle/infer/region_inference/README.md b/src/librustc/middle/infer/region_inference/README.md index a009e0a823..e44211da4a 100644 --- a/src/librustc/middle/infer/region_inference/README.md +++ b/src/librustc/middle/infer/region_inference/README.md @@ -249,114 +249,61 @@ there is a reference created whose lifetime does not enclose the borrow expression, we must issue sufficient restrictions to ensure that the pointee remains valid. -## Adding closures - -The other significant complication to the region hierarchy is -closures. I will describe here how closures should work, though some -of the work to implement this model is ongoing at the time of this -writing. - -The body of closures are type-checked along with the function that -creates them. However, unlike other expressions that appear within the -function body, it is not entirely obvious when a closure body executes -with respect to the other expressions. This is because the closure -body will execute whenever the closure is called; however, we can -never know precisely when the closure will be called, especially -without some sort of alias analysis. - -However, we can place some sort of limits on when the closure -executes. In particular, the type of every closure `fn:'r K` includes -a region bound `'r`. This bound indicates the maximum lifetime of that -closure; once we exit that region, the closure cannot be called -anymore. Therefore, we say that the lifetime of the closure body is a -sublifetime of the closure bound, but the closure body itself is unordered -with respect to other parts of the code. - -For example, consider the following fragment of code: - - 'a: { - let closure: fn:'a() = || 'b: { - 'c: ... - }; - 'd: ... - } - -Here we have four lifetimes, `'a`, `'b`, `'c`, and `'d`. The closure -`closure` is bounded by the lifetime `'a`. The lifetime `'b` is the -lifetime of the closure body, and `'c` is some statement within the -closure body. Finally, `'d` is a statement within the outer block that -created the closure. - -We can say that the closure body `'b` is a sublifetime of `'a` due to -the closure bound. By the usual lexical scoping conventions, the -statement `'c` is clearly a sublifetime of `'b`, and `'d` is a -sublifetime of `'d`. However, there is no ordering between `'c` and -`'d` per se (this kind of ordering between statements is actually only -an issue for dataflow; passes like the borrow checker must assume that -closures could execute at any time from the moment they are created -until they go out of scope). - -### Complications due to closure bound inference - -There is only one problem with the above model: in general, we do not -actually *know* the closure bounds during region inference! In fact, -closure bounds are almost always region variables! This is very tricky -because the inference system implicitly assumes that we can do things -like compute the LUB of two scoped lifetimes without needing to know -the values of any variables. - -Here is an example to illustrate the problem: - - fn identify(x: T) -> T { x } - - fn foo() { // 'foo is the function body - 'a: { - let closure = identity(|| 'b: { - 'c: ... - }); - 'd: closure(); - } - 'e: ...; - } - -In this example, the closure bound is not explicit. At compile time, -we will create a region variable (let's call it `V0`) to represent the -closure bound. - -The primary difficulty arises during the constraint propagation phase. -Imagine there is some variable with incoming edges from `'c` and `'d`. -This means that the value of the variable must be `LUB('c, -'d)`. However, without knowing what the closure bound `V0` is, we -can't compute the LUB of `'c` and `'d`! Any we don't know the closure -bound until inference is done. - -The solution is to rely on the fixed point nature of inference. -Basically, when we must compute `LUB('c, 'd)`, we just use the current -value for `V0` as the closure's bound. If `V0`'s binding should -change, then we will do another round of inference, and the result of -`LUB('c, 'd)` will change. - -One minor implication of this is that the graph does not in fact track -the full set of dependencies between edges. We cannot easily know -whether the result of a LUB computation will change, since there may -be indirect dependencies on other variables that are not reflected on -the graph. Therefore, we must *always* iterate over all edges when -doing the fixed point calculation, not just those adjacent to nodes -whose values have changed. - -Were it not for this requirement, we could in fact avoid fixed-point -iteration altogether. In that universe, we could instead first -identify and remove strongly connected components (SCC) in the graph. -Note that such components must consist solely of region variables; all -of these variables can effectively be unified into a single variable. -Once SCCs are removed, we are left with a DAG. At this point, we -could walk the DAG in topological order once to compute the expanding -nodes, and again in reverse topological order to compute the -contracting nodes. However, as I said, this does not work given the -current treatment of closure bounds, but perhaps in the future we can -address this problem somehow and make region inference somewhat more -efficient. Note that this is solely a matter of performance, not -expressiveness. +## Modeling closures + +Integrating closures properly into the model is a bit of +work-in-progress. In an ideal world, we would model closures as +closely as possible after their desugared equivalents. That is, a +closure type would be modeled as a struct, and the region hierarchy of +different closure bodies would be completely distinct from all other +fns. We are generally moving in that direction but there are +complications in terms of the implementation. + +In practice what we currently do is somewhat different. The basis for +the current approach is the observation that the only time that +regions from distinct fn bodies interact with one another is through +an upvar or the type of a fn parameter (since closures live in the fn +body namespace, they can in fact have fn parameters whose types +include regions from the surrounding fn body). For these cases, there +are separate mechanisms which ensure that the regions that appear in +upvars/parameters outlive the dynamic extent of each call to the +closure: + +1. Types must outlive the region of any expression where they are used. + For a closure type `C` to outlive a region `'r`, that implies that the + types of all its upvars must outlive `'r`. +2. Parameters must outlive the region of any fn that they are passed to. + +Therefore, we can -- sort of -- assume that any region from an +enclosing fns is larger than any region from one of its enclosed +fn. And that is precisely what we do: when building the region +hierarchy, each region lives in its own distinct subtree, but if we +are asked to compute the `LUB(r1, r2)` of two regions, and those +regions are in disjoint subtrees, we compare the lexical nesting of +the two regions. + +*Ideas for improving the situation:* (FIXME #3696) The correctness +argument here is subtle and a bit hand-wavy. The ideal, as stated +earlier, would be to model things in such a way that it corresponds +more closely to the desugared code. The best approach for doing this +is a bit unclear: it may in fact be possible to *actually* desugar +before we start, but I don't think so. The main option that I've been +thinking through is imposing a "view shift" as we enter the fn body, +so that regions appearing in the types of fn parameters and upvars are +translated from being regions in the outer fn into free region +parameters, just as they would be if we applied the desugaring. The +challenge here is that type inference may not have fully run, so the +types may not be fully known: we could probably do this translation +lazilly, as type variables are instantiated. We would also have to +apply a kind of inverse translation to the return value. This would be +a good idea anyway, as right now it is possible for free regions +instantiated within the closure to leak into the parent: this +currently leads to type errors, since those regions cannot outlive any +expressions within the parent hierarchy. Much like the current +handling of closures, there are no known cases where this leads to a +type-checking accepting incorrect code (though it sometimes rejects +what might be considered correct code; see rust-lang/rust#22557), but +it still doesn't feel like the right approach. ### Skolemization diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 67875ae225..1fcbf80c90 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -28,8 +28,10 @@ use util::ppaux::Repr; use std::borrow::Cow; use std::collections::hash_map::Entry::Vacant; -use std::old_io::{self, File}; use std::env; +use std::fs::File; +use std::io; +use std::io::prelude::*; use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; use syntax::ast; @@ -67,13 +69,13 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, return; } - let requested_output = env::var("RUST_REGION_GRAPH").ok(); + let requested_output = env::var("RUST_REGION_GRAPH"); debug!("requested_output: {:?} requested_node: {:?}", requested_output, requested_node); let output_path = { let output_template = match requested_output { - Some(ref s) if &**s == "help" => { + Ok(ref s) if &**s == "help" => { static PRINTED_YET: AtomicBool = ATOMIC_BOOL_INIT; if !PRINTED_YET.load(Ordering::SeqCst) { print_help_message(); @@ -82,15 +84,15 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, return; } - Some(other_path) => other_path, - None => "/tmp/constraints.node%.dot".to_string(), + Ok(other_path) => other_path, + Err(_) => "/tmp/constraints.node%.dot".to_string(), }; if output_template.len() == 0 { tcx.sess.bug("empty string provided as RUST_REGION_GRAPH"); } - if output_template.contains_char('%') { + if output_template.contains('%') { let mut new_str = String::new(); for c in output_template.chars() { if c == '%' { @@ -119,7 +121,7 @@ struct ConstraintGraph<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, graph_name: String, map: &'a FnvHashMap>, - node_ids: FnvHashMap, + node_ids: FnvHashMap, } #[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)] @@ -169,7 +171,7 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> { impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> { fn graph_id(&self) -> dot::Id { - dot::Id::new(&*self.graph_name).ok().unwrap() + dot::Id::new(&*self.graph_name).unwrap() } fn node_id(&self, n: &Node) -> dot::Id { let node_id = match self.node_ids.get(n) { @@ -256,10 +258,11 @@ pub type ConstraintMap<'tcx> = FnvHashMap>; fn dump_region_constraints_to<'a, 'tcx:'a >(tcx: &'a ty::ctxt<'tcx>, map: &ConstraintMap<'tcx>, - path: &str) -> old_io::IoResult<()> { + path: &str) -> io::Result<()> { debug!("dump_region_constraints map (len: {}) path: {}", map.len(), path); let g = ConstraintGraph::new(tcx, format!("region_constraints"), map); - let mut f = File::create(&Path::new(path)); debug!("dump_region_constraints calling render"); - dot::render(&g, &mut f) + let mut v = Vec::new(); + dot::render(&g, &mut v).unwrap(); + File::create(path).and_then(|mut f| f.write_all(&v)) } diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index b4fd34f206..d41fdc5f09 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See doc.rs +//! See README.md pub use self::Constraint::*; pub use self::Verify::*; @@ -18,7 +18,6 @@ pub use self::RegionResolutionError::*; pub use self::VarValue::*; use self::Classification::*; -use super::cres; use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable}; use middle::region; @@ -26,6 +25,7 @@ use middle::ty::{self, Ty}; use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid}; use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound}; use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; +use middle::ty_relate::RelateResult; use middle::graph; use middle::graph::{Direction, NodeIndex}; use util::common::indenter; @@ -74,24 +74,24 @@ pub enum GenericKind<'tcx> { Projection(ty::ProjectionTy<'tcx>), } -#[derive(Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct TwoRegions { a: Region, b: Region, } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum UndoLogEntry { OpenSnapshot, CommitedSnapshot, AddVar(RegionVid), AddConstraint(Constraint), - AddVerify(uint), + AddVerify(usize), AddGiven(ty::FreeRegion, ty::RegionVid), AddCombination(CombineMapType, TwoRegions) } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum CombineMapType { Lub, Glb } @@ -115,7 +115,7 @@ pub enum RegionResolutionError<'tcx> { /// Could not infer a value for `v` because `sub_r <= v` (due to /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and /// `sub_r <= sup_r` does not hold. - SubSupConflict(RegionVariableOrigin<'tcx>, + SubSupConflict(RegionVariableOrigin, SubregionOrigin<'tcx>, Region, SubregionOrigin<'tcx>, Region), @@ -124,7 +124,7 @@ pub enum RegionResolutionError<'tcx> { /// Could not infer a value for `v` because `v <= r1` (due to /// `origin1`) and `v <= r2` (due to `origin2`) and /// `r1` and `r2` have no intersection. - SupSupConflict(RegionVariableOrigin<'tcx>, + SupSupConflict(RegionVariableOrigin, SubregionOrigin<'tcx>, Region, SubregionOrigin<'tcx>, Region), @@ -132,7 +132,7 @@ pub enum RegionResolutionError<'tcx> { /// more specific errors message by suggesting to the user where they /// should put a lifetime. In those cases we process and put those errors /// into `ProcessedErrors` before we do any reporting. - ProcessedErrors(Vec>, + ProcessedErrors(Vec, Vec<(TypeTrace<'tcx>, ty::type_err<'tcx>)>, Vec), } @@ -168,7 +168,7 @@ pub type CombineMap = FnvHashMap; pub struct RegionVarBindings<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, - var_origins: RefCell>>, + var_origins: RefCell>, // Constraints of the form `A <= B` introduced by the region // checker. Here at least one of `A` and `B` must be a region @@ -224,7 +224,7 @@ pub struct RegionVarBindings<'a, 'tcx: 'a> { #[derive(Debug)] pub struct RegionSnapshot { - length: uint, + length: usize, skolemization_count: u32, } @@ -284,7 +284,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { AddVar(vid) => { let mut var_origins = self.var_origins.borrow_mut(); var_origins.pop().unwrap(); - assert_eq!(var_origins.len(), vid.index as uint); + assert_eq!(var_origins.len(), vid.index as usize); } AddConstraint(ref constraint) => { self.constraints.borrow_mut().remove(constraint); @@ -312,11 +312,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { pub fn num_vars(&self) -> u32 { let len = self.var_origins.borrow().len(); // enforce no overflow - assert!(len as u32 as uint == len); + assert!(len as u32 as usize == len); len as u32 } - pub fn new_region_var(&self, origin: RegionVariableOrigin<'tcx>) -> RegionVid { + pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid { let id = self.num_vars(); self.var_origins.borrow_mut().push(origin.clone()); let vid = RegionVid { index: id }; @@ -473,7 +473,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { origin.span(), &format!("cannot relate bound region: {} <= {}", sub.repr(self.tcx), - sup.repr(self.tcx))[]); + sup.repr(self.tcx))); } (_, ReStatic) => { // all regions are subregions of static, so we can ignore this @@ -557,7 +557,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { match *self.values.borrow() { None => { self.tcx.sess.span_bug( - (*self.var_origins.borrow())[rid.index as uint].span(), + (*self.var_origins.borrow())[rid.index as usize].span(), "attempt to resolve region variable before values have \ been computed!") } @@ -629,7 +629,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { let mut result_set = vec!(r0); let mut result_index = 0; while result_index < result_set.len() { - // nb: can't use uint::range() here because result_set grows + // nb: can't use usize::range() here because result_set grows let r = result_set[result_index]; debug!("result_index={}, r={:?}", result_index, r); @@ -733,7 +733,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { self.tcx.sess.bug( &format!("cannot relate bound region: LUB({}, {})", a.repr(self.tcx), - b.repr(self.tcx))[]); + b.repr(self.tcx))); } (ReStatic, _) | (_, ReStatic) => { @@ -746,11 +746,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { (ReInfer(ReVar(v_id)), _) | (_, ReInfer(ReVar(v_id))) => { self.tcx.sess.span_bug( - (*self.var_origins.borrow())[v_id.index as uint].span(), + (*self.var_origins.borrow())[v_id.index as usize].span(), &format!("lub_concrete_regions invoked with \ non-concrete regions: {:?}, {:?}", a, - b)[]); + b)); } (ReFree(ref fr), ReScope(s_id)) | @@ -760,15 +760,17 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // at least as big as the block fr.scope_id". So, we can // reasonably compare free regions and scopes: let fr_scope = fr.scope.to_code_extent(); - match self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) { + let r_id = self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id); + + if r_id == fr_scope { // if the free region's scope `fr.scope_id` is bigger than // the scope region `s_id`, then the LUB is the free // region itself: - Some(r_id) if r_id == fr_scope => f, - + f + } else { // otherwise, we don't know what the free region is, // so we must conservatively say the LUB is static: - _ => ReStatic + ReStatic } } @@ -776,10 +778,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // The region corresponding to an outer block is a // subtype of the region corresponding to an inner // block. - match self.tcx.region_maps.nearest_common_ancestor(a_id, b_id) { - Some(r_id) => ReScope(r_id), - _ => ReStatic - } + ReScope(self.tcx.region_maps.nearest_common_ancestor(a_id, b_id)) } (ReFree(ref a_fr), ReFree(ref b_fr)) => { @@ -799,7 +798,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { /// regions are given as argument, in any order, a consistent result is returned. fn lub_free_regions(&self, a: &FreeRegion, - b: &FreeRegion) -> ty::Region + b: &FreeRegion) + -> ty::Region { return match a.cmp(b) { Less => helper(self, a, b), @@ -824,7 +824,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { fn glb_concrete_regions(&self, a: Region, b: Region) - -> cres<'tcx, Region> { + -> RelateResult<'tcx, Region> + { debug!("glb_concrete_regions({:?}, {:?})", a, b); match (a, b) { (ReLateBound(..), _) | @@ -834,7 +835,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { self.tcx.sess.bug( &format!("cannot relate bound region: GLB({}, {})", a.repr(self.tcx), - b.repr(self.tcx))[]); + b.repr(self.tcx))); } (ReStatic, r) | (r, ReStatic) => { @@ -850,11 +851,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { (ReInfer(ReVar(v_id)), _) | (_, ReInfer(ReVar(v_id))) => { self.tcx.sess.span_bug( - (*self.var_origins.borrow())[v_id.index as uint].span(), + (*self.var_origins.borrow())[v_id.index as usize].span(), &format!("glb_concrete_regions invoked with \ non-concrete regions: {:?}, {:?}", a, - b)[]); + b)); } (ReFree(ref fr), ReScope(s_id)) | @@ -866,9 +867,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // is the scope `s_id`. Otherwise, as we do not know // big the free region is precisely, the GLB is undefined. let fr_scope = fr.scope.to_code_extent(); - match self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) { - Some(r_id) if r_id == fr_scope => Ok(s), - _ => Err(ty::terr_regions_no_overlap(b, a)) + if self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) == fr_scope { + Ok(s) + } else { + Err(ty::terr_regions_no_overlap(b, a)) } } @@ -898,7 +900,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { /// returned. fn glb_free_regions(&self, a: &FreeRegion, - b: &FreeRegion) -> cres<'tcx, ty::Region> + b: &FreeRegion) + -> RelateResult<'tcx, ty::Region> { return match a.cmp(b) { Less => helper(self, a, b), @@ -908,7 +911,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>, a: &FreeRegion, - b: &FreeRegion) -> cres<'tcx, ty::Region> + b: &FreeRegion) -> RelateResult<'tcx, ty::Region> { if this.tcx.region_maps.sub_free_region(*a, *b) { Ok(ty::ReFree(*a)) @@ -926,7 +929,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { region_a: ty::Region, region_b: ty::Region, scope_a: region::CodeExtent, - scope_b: region::CodeExtent) -> cres<'tcx, Region> + scope_b: region::CodeExtent) + -> RelateResult<'tcx, Region> { // We want to generate the intersection of two // scopes or two free regions. So, if one of @@ -934,20 +938,23 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // it. Otherwise fail. debug!("intersect_scopes(scope_a={:?}, scope_b={:?}, region_a={:?}, region_b={:?})", scope_a, scope_b, region_a, region_b); - match self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b) { - Some(r_id) if scope_a == r_id => Ok(ReScope(scope_b)), - Some(r_id) if scope_b == r_id => Ok(ReScope(scope_a)), - _ => Err(ty::terr_regions_no_overlap(region_a, region_b)) + let r_id = self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b); + if r_id == scope_a { + Ok(ReScope(scope_b)) + } else if r_id == scope_b { + Ok(ReScope(scope_a)) + } else { + Err(ty::terr_regions_no_overlap(region_a, region_b)) } } } // ______________________________________________________________________ -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum Classification { Expanding, Contracting } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum VarValue { NoValue, Value(Region), ErrorValue } struct VarData { @@ -984,7 +991,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } fn construct_var_data(&self) -> Vec { - (0..self.num_vars() as uint).map(|_| { + (0..self.num_vars() as usize).map(|_| { VarData { // All nodes are initially classified as contracting; during // the expansion phase, we will shift the classification for @@ -1013,14 +1020,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { .repr(self.tcx)); match *constraint { ConstrainRegSubVar(a_region, b_vid) => { - let b_data = &mut var_data[b_vid.index as uint]; + let b_data = &mut var_data[b_vid.index as usize]; self.expand_node(a_region, b_vid, b_data) } ConstrainVarSubVar(a_vid, b_vid) => { - match var_data[a_vid.index as uint].value { + match var_data[a_vid.index as usize].value { NoValue | ErrorValue => false, Value(a_region) => { - let b_node = &mut var_data[b_vid.index as uint]; + let b_node = &mut var_data[b_vid.index as usize]; self.expand_node(a_region, b_vid, b_node) } } @@ -1101,16 +1108,16 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { false } ConstrainVarSubVar(a_vid, b_vid) => { - match var_data[b_vid.index as uint].value { + match var_data[b_vid.index as usize].value { NoValue | ErrorValue => false, Value(b_region) => { - let a_data = &mut var_data[a_vid.index as uint]; + let a_data = &mut var_data[a_vid.index as usize]; self.contract_node(a_vid, a_data, b_region) } } } ConstrainVarSubReg(a_vid, b_region) => { - let a_data = &mut var_data[a_vid.index as uint]; + let a_data = &mut var_data[a_vid.index as usize]; self.contract_node(a_vid, a_data, b_region) } } @@ -1133,18 +1140,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { true // changed } - ErrorValue => { - false // no change - } + ErrorValue => false, // no change Value(a_region) => { match a_data.classification { - Expanding => { - check_node(self, a_vid, a_data, a_region, b_region) - } - Contracting => { - adjust_node(self, a_vid, a_data, a_region, b_region) - } + Expanding => check_node(self, a_vid, a_data, a_region, b_region), + Contracting => adjust_node(self, a_vid, a_data, a_region, b_region), } } }; @@ -1154,7 +1155,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { a_data: &mut VarData, a_region: Region, b_region: Region) - -> bool { + -> bool { if !this.is_subregion_of(a_region, b_region) { debug!("Setting {:?} to ErrorValue: {} not subregion of {}", a_vid, @@ -1170,7 +1171,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { a_data: &mut VarData, a_region: Region, b_region: Region) - -> bool { + -> bool { match this.glb_concrete_regions(a_region, b_region) { Ok(glb) => { if glb == a_region { @@ -1256,11 +1257,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // idea is to report errors that derive from independent // regions of the graph, but not those that derive from // overlapping locations. - let mut dup_vec: Vec<_> = repeat(u32::MAX).take(self.num_vars() as uint).collect(); + let mut dup_vec: Vec<_> = repeat(u32::MAX).take(self.num_vars() as usize).collect(); let mut opt_graph = None; - for idx in 0..self.num_vars() as uint { + for idx in 0..self.num_vars() as usize { match var_data[idx].value { Value(_) => { /* Inference successful */ @@ -1317,7 +1318,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } } - (0..self.num_vars() as uint).map(|idx| var_data[idx].value).collect() + (0..self.num_vars() as usize).map(|idx| var_data[idx].value).collect() } fn construct_graph(&self) -> RegionGraph { @@ -1326,7 +1327,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { let constraints = self.constraints.borrow(); let num_edges = constraints.len(); - let mut graph = graph::Graph::with_capacity(num_vars as uint + 1, + let mut graph = graph::Graph::with_capacity(num_vars as usize + 1, num_edges); for _ in 0..num_vars { @@ -1337,17 +1338,17 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { for (constraint, _) in &*constraints { match *constraint { ConstrainVarSubVar(a_id, b_id) => { - graph.add_edge(NodeIndex(a_id.index as uint), - NodeIndex(b_id.index as uint), + graph.add_edge(NodeIndex(a_id.index as usize), + NodeIndex(b_id.index as usize), *constraint); } ConstrainRegSubVar(_, b_id) => { graph.add_edge(dummy_idx, - NodeIndex(b_id.index as uint), + NodeIndex(b_id.index as usize), *constraint); } ConstrainVarSubReg(a_id, _) => { - graph.add_edge(NodeIndex(a_id.index as uint), + graph.add_edge(NodeIndex(a_id.index as usize), dummy_idx, *constraint); } @@ -1401,7 +1402,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { debug!("pushing SubSupConflict sub: {:?} sup: {:?}", lower_bound.region, upper_bound.region); errors.push(SubSupConflict( - (*self.var_origins.borrow())[node_idx.index as uint].clone(), + (*self.var_origins.borrow())[node_idx.index as usize].clone(), lower_bound.origin.clone(), lower_bound.region, upper_bound.origin.clone(), @@ -1412,12 +1413,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } self.tcx.sess.span_bug( - (*self.var_origins.borrow())[node_idx.index as uint].span(), + (*self.var_origins.borrow())[node_idx.index as usize].span(), &format!("collect_error_for_expanding_node() could not find error \ for var {:?}, lower_bounds={}, upper_bounds={}", node_idx, lower_bounds.repr(self.tcx), - upper_bounds.repr(self.tcx))[]); + upper_bounds.repr(self.tcx))); } fn collect_error_for_contracting_node( @@ -1445,7 +1446,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { Ok(_) => {} Err(_) => { errors.push(SupSupConflict( - (*self.var_origins.borrow())[node_idx.index as uint].clone(), + (*self.var_origins.borrow())[node_idx.index as usize].clone(), upper_bound_1.origin.clone(), upper_bound_1.region, upper_bound_2.origin.clone(), @@ -1457,11 +1458,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } self.tcx.sess.span_bug( - (*self.var_origins.borrow())[node_idx.index as uint].span(), + (*self.var_origins.borrow())[node_idx.index as usize].span(), &format!("collect_error_for_contracting_node() could not find error \ for var {:?}, upper_bounds={}", node_idx, - upper_bounds.repr(self.tcx))[]); + upper_bounds.repr(self.tcx))); } fn collect_concrete_regions(&self, @@ -1491,12 +1492,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { while !state.stack.is_empty() { let node_idx = state.stack.pop().unwrap(); - let classification = var_data[node_idx.index as uint].classification; + let classification = var_data[node_idx.index as usize].classification; // check whether we've visited this node on some previous walk - if dup_vec[node_idx.index as uint] == u32::MAX { - dup_vec[node_idx.index as uint] = orig_node_idx.index; - } else if dup_vec[node_idx.index as uint] != orig_node_idx.index { + if dup_vec[node_idx.index as usize] == u32::MAX { + dup_vec[node_idx.index as usize] = orig_node_idx.index; + } else if dup_vec[node_idx.index as usize] != orig_node_idx.index { state.dup_found = true; } @@ -1524,7 +1525,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { dir: Direction) { debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir); - let source_node_index = NodeIndex(source_vid.index as uint); + let source_node_index = NodeIndex(source_vid.index as usize); graph.each_adjacent_edge(source_node_index, dir, |_, edge| { match edge.data { ConstrainVarSubVar(from_vid, to_vid) => { @@ -1539,7 +1540,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { ConstrainVarSubReg(_, region) => { state.result.push(RegionAndOrigin { region: region, - origin: this.constraints.borrow()[edge.data].clone() + origin: this.constraints.borrow().get(&edge.data).unwrap().clone() }); } } @@ -1609,7 +1610,7 @@ fn normalize(values: &Vec, r: ty::Region) -> ty::Region { } fn lookup(values: &Vec, rid: ty::RegionVid) -> ty::Region { - match values[rid.index as uint] { + match values[rid.index as usize] { Value(r) => r, NoValue => ReEmpty, // No constraints, return ty::ReEmpty ErrorValue => ReStatic, // Previously reported error. diff --git a/src/librustc/middle/infer/resolve.rs b/src/librustc/middle/infer/resolve.rs index 7bb3106b0b..b9025d0106 100644 --- a/src/librustc/middle/infer/resolve.rs +++ b/src/librustc/middle/infer/resolve.rs @@ -96,7 +96,7 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { ty::ty_infer(_) => { self.infcx.tcx.sess.bug( &format!("Unexpected type in full type resolver: {}", - t.repr(self.infcx.tcx))[]); + t.repr(self.infcx.tcx))); } _ => { ty_fold::super_fold_ty(self, t) @@ -112,4 +112,3 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { } } } - diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index 33da3092b2..31b654a5b3 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -8,112 +8,49 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::combine::*; -use super::{cres, CresCompare}; +use super::combine::{self, CombineFields}; use super::higher_ranked::HigherRankedRelations; -use super::{Subtype}; +use super::Subtype; use super::type_variable::{SubtypeOf, SupertypeOf}; -use middle::ty::{BuiltinBounds}; use middle::ty::{self, Ty}; use middle::ty::TyVar; +use middle::ty_relate::{Relate, RelateResult, TypeRelation}; use util::ppaux::{Repr}; -use syntax::ast::{MutImmutable, MutMutable, Unsafety}; - - /// "Greatest lower bound" (common subtype) -pub struct Sub<'f, 'tcx: 'f> { - fields: CombineFields<'f, 'tcx> +pub struct Sub<'a, 'tcx: 'a> { + fields: CombineFields<'a, 'tcx> } -#[allow(non_snake_case)] -pub fn Sub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Sub<'f, 'tcx> { - Sub { fields: cf } +impl<'a, 'tcx> Sub<'a, 'tcx> { + pub fn new(f: CombineFields<'a, 'tcx>) -> Sub<'a, 'tcx> { + Sub { fields: f } + } } -impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { - fn tag(&self) -> String { "Sub".to_string() } - fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields } +impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { + fn tag(&self) -> &'static str { "Sub" } + fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.infcx.tcx } + fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, Ty<'tcx>> + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> { - match v { - ty::Invariant => self.equate().tys(a, b), - ty::Covariant => self.tys(a, b), - ty::Bivariant => self.bivariate().tys(a, b), - ty::Contravariant => Sub(self.fields.switch_expected()).tys(b, a), + match variance { + ty::Invariant => self.fields.equate().relate(a, b), + ty::Covariant => self.relate(a, b), + ty::Bivariant => self.fields.bivariate().relate(a, b), + ty::Contravariant => self.fields.switch_expected().sub().relate(b, a), } } - fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region) - -> cres<'tcx, ty::Region> - { - match v { - ty::Invariant => self.equate().regions(a, b), - ty::Covariant => self.regions(a, b), - ty::Bivariant => self.bivariate().regions(a, b), - ty::Contravariant => Sub(self.fields.switch_expected()).regions(b, a), - } - } + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + debug!("{}.tys({}, {})", self.tag(), a.repr(self.tcx()), b.repr(self.tcx())); - fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { - debug!("{}.regions({}, {})", - self.tag(), - a.repr(self.tcx()), - b.repr(self.tcx())); - self.infcx().region_vars.make_subregion(Subtype(self.trace()), a, b); - Ok(a) - } - - fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> { - debug!("mts({} <: {})", - a.repr(self.tcx()), - b.repr(self.tcx())); - - if a.mutbl != b.mutbl { - return Err(ty::terr_mutability); - } - - match b.mutbl { - MutMutable => { - // If supertype is mut, subtype must match exactly - // (i.e., invariant if mut): - try!(self.equate().tys(a.ty, b.ty)); - } - MutImmutable => { - // Otherwise we can be covariant: - try!(self.tys(a.ty, b.ty)); - } - } - - Ok(*a) // return is meaningless in sub, just return *a - } - - fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { - self.lub().unsafeties(a, b).compare(b, || { - ty::terr_unsafety_mismatch(expected_found(self, a, b)) - }) - } - - fn builtin_bounds(&self, a: BuiltinBounds, b: BuiltinBounds) - -> cres<'tcx, BuiltinBounds> { - // More bounds is a subtype of fewer bounds. - // - // e.g., fn:Copy() <: fn(), because the former is a function - // that only closes over copyable things, but the latter is - // any function at all. - if a.is_superset(&b) { - Ok(a) - } else { - Err(ty::terr_builtin_bounds(expected_found(self, a, b))) - } - } - - fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> { - debug!("{}.tys({}, {})", self.tag(), - a.repr(self.tcx()), b.repr(self.tcx())); if a == b { return Ok(a); } let infcx = self.fields.infcx; @@ -128,8 +65,8 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { } (&ty::ty_infer(TyVar(a_id)), _) => { try!(self.fields - .switch_expected() - .instantiate(b, SupertypeOf, a_id)); + .switch_expected() + .instantiate(b, SupertypeOf, a_id)); Ok(a) } (_, &ty::ty_infer(TyVar(b_id))) => { @@ -142,15 +79,25 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { } _ => { - super_tys(self, a, b) + combine::super_combine_tys(self.fields.infcx, self, a, b) } } } - fn binders(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> - where T : Combineable<'tcx> + fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + debug!("{}.regions({}, {})", + self.tag(), + a.repr(self.tcx()), + b.repr(self.tcx())); + let origin = Subtype(self.fields.trace.clone()); + self.fields.infcx.region_vars.make_subregion(origin, a, b); + Ok(a) + } + + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a,'tcx> { - self.higher_ranked_sub(a, b) + self.fields.higher_ranked_sub(a, b) } } - diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs index a856137af0..03612a6c1a 100644 --- a/src/librustc/middle/infer/type_variable.rs +++ b/src/librustc/middle/infer/type_variable.rs @@ -47,7 +47,7 @@ struct Delegate<'tcx>(PhantomData<&'tcx ()>); type Relation = (RelationDir, ty::TyVid); -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum RelationDir { SubtypeOf, SupertypeOf, EqTo, BiTo } @@ -69,11 +69,11 @@ impl<'tcx> TypeVariableTable<'tcx> { } fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec { - relations(self.values.get_mut(a.index as uint)) + relations(self.values.get_mut(a.index as usize)) } pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool { - self.values.get(vid.index as uint).diverging + self.values.get(vid.index as usize).diverging } /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`. @@ -97,7 +97,7 @@ impl<'tcx> TypeVariableTable<'tcx> { stack: &mut Vec<(Ty<'tcx>, RelationDir, ty::TyVid)>) { let old_value = { - let value_ptr = &mut self.values.get_mut(vid.index as uint).value; + let value_ptr = &mut self.values.get_mut(vid.index as usize).value; mem::replace(value_ptr, Known(ty)) }; @@ -123,7 +123,7 @@ impl<'tcx> TypeVariableTable<'tcx> { } pub fn probe(&self, vid: ty::TyVid) -> Option> { - match self.values.get(vid.index as uint).value { + match self.values.get(vid.index as usize).value { Bounded(..) => None, Known(t) => Some(t) } @@ -206,12 +206,12 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> { action: UndoEntry) { match action { SpecifyVar(vid, relations) => { - values[vid.index as uint].value = Bounded(relations); + values[vid.index as usize].value = Bounded(relations); } Relate(a, b) => { - relations(&mut (*values)[a.index as uint]).pop(); - relations(&mut (*values)[b.index as uint]).pop(); + relations(&mut (*values)[a.index as usize]).pop(); + relations(&mut (*values)[b.index as usize]).pop(); } } } diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index 0675cec6f6..4bbced1d75 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -12,11 +12,8 @@ pub use self::VarValue::*; use std::marker; -use middle::ty::{expected_found, IntVarValue}; +use middle::ty::{IntVarValue}; use middle::ty::{self, Ty}; -use middle::infer::{uok, ures}; -use middle::infer::InferCtxt; -use std::cell::RefCell; use std::fmt::Debug; use std::marker::PhantomData; use syntax::ast; @@ -35,14 +32,9 @@ use util::snapshot_vec as sv; pub trait UnifyKey : Clone + Debug + PartialEq { type Value : UnifyValue; - fn index(&self) -> uint; + fn index(&self) -> u32; - fn from_index(u: uint) -> Self; - - // Given an inference context, returns the unification table - // appropriate to this key type. - fn unification_table<'v>(infcx: &'v InferCtxt) - -> &'v RefCell>; + fn from_index(u: u32) -> Self; fn tag(k: Option) -> &'static str; } @@ -67,7 +59,7 @@ pub trait UnifyValue : Clone + PartialEq + Debug { #[derive(PartialEq,Clone,Debug)] pub enum VarValue { Redirect(K), - Root(K::Value, uint), + Root(K::Value, usize), } /// Table of unification keys and their values. @@ -89,10 +81,10 @@ pub struct Snapshot { pub struct Node { pub key: K, pub value: K::Value, - pub rank: uint, + pub rank: usize, } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Delegate(PhantomData); // We can't use V:LatticeValue, much as I would like to, @@ -130,21 +122,25 @@ impl UnificationTable { pub fn new_key(&mut self, value: K::Value) -> K { let index = self.values.push(Root(value, 0)); - let k = UnifyKey::from_index(index); + let k = UnifyKey::from_index(index as u32); debug!("{}: created new key: {:?}", UnifyKey::tag(None::), k); k } - /// Find the root node for `vid`. This uses the standard union-find algorithm with path - /// compression: http://en.wikipedia.org/wiki/Disjoint-set_data_structure - pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node { - let index = vid.index(); + /// Find the root node for `vid`. This uses the standard + /// union-find algorithm with path compression: + /// . + /// + /// NB. This is a building-block operation and you would probably + /// prefer to call `probe` below. + fn get(&mut self, vid: K) -> Node { + let index = vid.index() as usize; let value = (*self.values.get(index)).clone(); match value { Redirect(redirect) => { - let node: Node = self.get(tcx, redirect.clone()); + let node: Node = self.get(redirect.clone()); if node.key != redirect { // Path compression self.values.set(index, Redirect(node.key.clone())); @@ -158,58 +154,58 @@ impl UnificationTable { } fn is_root(&self, key: &K) -> bool { - match *self.values.get(key.index()) { + let index = key.index() as usize; + match *self.values.get(index) { Redirect(..) => false, Root(..) => true, } } - /// Sets the value for `vid` to `new_value`. `vid` MUST be a root node! Also, we must be in the - /// middle of a snapshot. - pub fn set<'tcx>(&mut self, - _tcx: &ty::ctxt<'tcx>, - key: K, - new_value: VarValue) - { + /// Sets the value for `vid` to `new_value`. `vid` MUST be a root + /// node! This is an internal operation used to impl other things. + fn set(&mut self, key: K, new_value: VarValue) { assert!(self.is_root(&key)); debug!("Updating variable {:?} to {:?}", key, new_value); - self.values.set(key.index(), new_value); + let index = key.index() as usize; + self.values.set(index, new_value); } - /// Either redirects node_a to node_b or vice versa, depending on the relative rank. Returns - /// the new root and rank. You should then update the value of the new root to something - /// suitable. - pub fn unify<'tcx>(&mut self, - tcx: &ty::ctxt<'tcx>, - node_a: &Node, - node_b: &Node) - -> (K, uint) - { + /// Either redirects `node_a` to `node_b` or vice versa, depending + /// on the relative rank. The value associated with the new root + /// will be `new_value`. + /// + /// NB: This is the "union" operation of "union-find". It is + /// really more of a building block. If the values associated with + /// your key are non-trivial, you would probably prefer to call + /// `unify_var_var` below. + fn unify(&mut self, node_a: &Node, node_b: &Node, new_value: K::Value) { debug!("unify(node_a(id={:?}, rank={:?}), node_b(id={:?}, rank={:?}))", node_a.key, node_a.rank, node_b.key, node_b.rank); - if node_a.rank > node_b.rank { + let (new_root, new_rank) = if node_a.rank > node_b.rank { // a has greater rank, so a should become b's parent, // i.e., b should redirect to a. - self.set(tcx, node_b.key.clone(), Redirect(node_a.key.clone())); + self.set(node_b.key.clone(), Redirect(node_a.key.clone())); (node_a.key.clone(), node_a.rank) } else if node_a.rank < node_b.rank { // b has greater rank, so a should redirect to b. - self.set(tcx, node_a.key.clone(), Redirect(node_b.key.clone())); + self.set(node_a.key.clone(), Redirect(node_b.key.clone())); (node_b.key.clone(), node_b.rank) } else { // If equal, redirect one to the other and increment the // other's rank. assert_eq!(node_a.rank, node_b.rank); - self.set(tcx, node_b.key.clone(), Redirect(node_a.key.clone())); + self.set(node_b.key.clone(), Redirect(node_a.key.clone())); (node_a.key.clone(), node_a.rank + 1) - } + }; + + self.set(new_root, Root(new_value, new_rank)); } } @@ -223,69 +219,26 @@ impl sv::SnapshotVecDelegate for Delegate { } /////////////////////////////////////////////////////////////////////////// -// Code to handle simple keys like ints, floats---anything that -// doesn't have a subtyping relationship we need to worry about. - -/// Indicates a type that does not have any kind of subtyping -/// relationship. -pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Debug { - fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>; - fn to_type_err(expected_found) -> ty::type_err<'tcx>; -} - -pub fn err<'tcx, V:SimplyUnifiable<'tcx>>(a_is_expected: bool, - a_t: V, - b_t: V) - -> ures<'tcx> { - if a_is_expected { - Err(SimplyUnifiable::to_type_err( - ty::expected_found {expected: a_t, found: b_t})) - } else { - Err(SimplyUnifiable::to_type_err( - ty::expected_found {expected: b_t, found: a_t})) - } -} - -pub trait InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V> - where K : UnifyKey>, - V : SimplyUnifiable<'tcx>, - Option : UnifyValue, -{ - fn simple_vars(&self, - a_is_expected: bool, - a_id: K, - b_id: K) - -> ures<'tcx>; - fn simple_var_t(&self, - a_is_expected: bool, - a_id: K, - b: V) - -> ures<'tcx>; - fn probe_var(&self, a_id: K) -> Option>; -} - -impl<'a,'tcx,V,K> InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V> for InferCtxt<'a,'tcx> - where K : UnifyKey>, - V : SimplyUnifiable<'tcx>, - Option : UnifyValue, +// Code to handle keys which carry a value, like ints, +// floats---anything that doesn't have a subtyping relationship we +// need to worry about. + +impl<'tcx,K,V> UnificationTable + where K: UnifyKey>, + V: Clone+PartialEq, + Option: UnifyValue, { - /// Unifies two simple keys. Because simple keys do not have any subtyping relationships, if - /// both keys have already been associated with a value, then those two values must be the - /// same. - fn simple_vars(&self, - a_is_expected: bool, - a_id: K, - b_id: K) - -> ures<'tcx> + pub fn unify_var_var(&mut self, + a_id: K, + b_id: K) + -> Result<(),(V,V)> { - let tcx = self.tcx; - let table = UnifyKey::unification_table(self); - let node_a: Node = table.borrow_mut().get(tcx, a_id); - let node_b: Node = table.borrow_mut().get(tcx, b_id); + let node_a = self.get(a_id); + let node_b = self.get(b_id); let a_id = node_a.key.clone(); let b_id = node_b.key.clone(); - if a_id == b_id { return uok(); } + if a_id == b_id { return Ok(()); } let combined = { match (&node_a.value, &node_b.value) { @@ -293,61 +246,52 @@ impl<'a,'tcx,V,K> InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V> for InferCtx None } (&Some(ref v), &None) | (&None, &Some(ref v)) => { - Some((*v).clone()) + Some(v.clone()) } (&Some(ref v1), &Some(ref v2)) => { if *v1 != *v2 { - return err(a_is_expected, (*v1).clone(), (*v2).clone()) + return Err((v1.clone(), v2.clone())); } - Some((*v1).clone()) + Some(v1.clone()) } } }; - let (new_root, new_rank) = table.borrow_mut().unify(tcx, - &node_a, - &node_b); - table.borrow_mut().set(tcx, new_root, Root(combined, new_rank)); - return Ok(()) + Ok(self.unify(&node_a, &node_b, combined)) } /// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping /// relationships, if `a_id` already has a value, it must be the same as `b`. - fn simple_var_t(&self, - a_is_expected: bool, - a_id: K, - b: V) - -> ures<'tcx> + pub fn unify_var_value(&mut self, + a_id: K, + b: V) + -> Result<(),(V,V)> { - let tcx = self.tcx; - let table = UnifyKey::unification_table(self); - let node_a = table.borrow_mut().get(tcx, a_id); + let node_a = self.get(a_id); let a_id = node_a.key.clone(); match node_a.value { None => { - table.borrow_mut().set(tcx, a_id, Root(Some(b), node_a.rank)); - return Ok(()); + self.set(a_id, Root(Some(b), node_a.rank)); + Ok(()) } Some(ref a_t) => { if *a_t == b { - return Ok(()); + Ok(()) } else { - return err(a_is_expected, (*a_t).clone(), b); + Err((a_t.clone(), b)) } } } } - fn probe_var(&self, a_id: K) -> Option> { - let tcx = self.tcx; - let table = UnifyKey::unification_table(self); - let node_a = table.borrow_mut().get(tcx, a_id); - match node_a.value { - None => None, - Some(ref a_t) => Some(a_t.to_type(tcx)) - } + pub fn has_value(&mut self, id: K) -> bool { + self.get(id).value.is_some() + } + + pub fn probe(&mut self, a_id: K) -> Option { + self.get(a_id).value.clone() } } @@ -355,33 +299,24 @@ impl<'a,'tcx,V,K> InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V> for InferCtx // Integral type keys +pub trait ToType<'tcx> { + fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>; +} + impl UnifyKey for ty::IntVid { type Value = Option; - - fn index(&self) -> uint { self.index as uint } - - fn from_index(i: uint) -> ty::IntVid { ty::IntVid { index: i as u32 } } - - fn unification_table<'v>(infcx: &'v InferCtxt) -> &'v RefCell> { - return &infcx.int_unification_table; - } - - fn tag(_: Option) -> &'static str { - "IntVid" - } + fn index(&self) -> u32 { self.index } + fn from_index(i: u32) -> ty::IntVid { ty::IntVid { index: i } } + fn tag(_: Option) -> &'static str { "IntVid" } } -impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue { +impl<'tcx> ToType<'tcx> for IntVarValue { fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { match *self { ty::IntType(i) => ty::mk_mach_int(tcx, i), ty::UintType(i) => ty::mk_mach_uint(tcx, i), } } - - fn to_type_err(err: expected_found) -> ty::type_err<'tcx> { - return ty::terr_int_mismatch(err); - } } impl UnifyValue for Option { } @@ -390,29 +325,16 @@ impl UnifyValue for Option { } impl UnifyKey for ty::FloatVid { type Value = Option; - - fn index(&self) -> uint { self.index as uint } - - fn from_index(i: uint) -> ty::FloatVid { ty::FloatVid { index: i as u32 } } - - fn unification_table<'v>(infcx: &'v InferCtxt) -> &'v RefCell> { - return &infcx.float_unification_table; - } - - fn tag(_: Option) -> &'static str { - "FloatVid" - } + fn index(&self) -> u32 { self.index } + fn from_index(i: u32) -> ty::FloatVid { ty::FloatVid { index: i } } + fn tag(_: Option) -> &'static str { "FloatVid" } } impl UnifyValue for Option { } -impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy { +impl<'tcx> ToType<'tcx> for ast::FloatTy { fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { ty::mk_mach_float(tcx, *self) } - - fn to_type_err(err: expected_found) -> ty::type_err<'tcx> { - ty::terr_float_mismatch(err) - } } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index bd96a8a0f2..2a4c253454 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -28,8 +28,8 @@ pub fn check_crate(tcx: &ctxt) { let mut visitor = IntrinsicCheckingVisitor { tcx: tcx, param_envs: Vec::new(), - dummy_sized_ty: tcx.types.int, - dummy_unsized_ty: ty::mk_vec(tcx, tcx.types.int, None), + dummy_sized_ty: tcx.types.isize, + dummy_unsized_ty: ty::mk_vec(tcx, tcx.types.isize, None), }; visit::walk_crate(&mut visitor, tcx.map.krate()); } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 56c5928a13..a08de58f90 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -46,7 +46,7 @@ macro_rules! lets_do_this { $( $variant:ident, $name:expr, $method:ident; )* ) => { -#[derive(Copy, FromPrimitive, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq, Hash)] pub enum LangItem { $($variant),* } @@ -70,8 +70,8 @@ impl LanguageItems { self.items.iter().enumerate() } - pub fn item_name(index: uint) -> &'static str { - let item: Option = FromPrimitive::from_uint(index); + pub fn item_name(index: usize) -> &'static str { + let item: Option = FromPrimitive::from_usize(index); match item { $( Some($variant) => $name, )* None => "???" @@ -79,11 +79,11 @@ impl LanguageItems { } pub fn require(&self, it: LangItem) -> Result { - match self.items[it as uint] { + match self.items[it as usize] { Some(id) => Ok(id), None => { Err(format!("requires `{}` lang_item", - LanguageItems::item_name(it as uint))) + LanguageItems::item_name(it as usize))) } } } @@ -132,7 +132,7 @@ impl LanguageItems { $( #[allow(dead_code)] pub fn $method(&self) -> Option { - self.items[$variant as uint] + self.items[$variant as usize] } )* } @@ -142,7 +142,7 @@ struct LanguageItemCollector<'a> { session: &'a Session, - item_refs: FnvHashMap<&'static str, uint>, + item_refs: FnvHashMap<&'static str, usize>, } impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> { @@ -163,7 +163,7 @@ impl<'a> LanguageItemCollector<'a> { pub fn new(session: &'a Session) -> LanguageItemCollector<'a> { let mut item_refs = FnvHashMap(); - $( item_refs.insert($name, $variant as uint); )* + $( item_refs.insert($name, $variant as usize); )* LanguageItemCollector { session: session, @@ -172,7 +172,7 @@ impl<'a> LanguageItemCollector<'a> { } } - pub fn collect_item(&mut self, item_index: uint, + pub fn collect_item(&mut self, item_index: usize, item_def_id: ast::DefId, span: Span) { // Check for duplicates. match self.items.items[item_index] { @@ -239,6 +239,24 @@ pub fn collect_language_items(krate: &ast::Crate, lets_do_this! { // Variant name, Name, Method name; + CharImplItem, "char", char_impl; + StrImplItem, "str", str_impl; + SliceImplItem, "slice", slice_impl; + ConstPtrImplItem, "const_ptr", const_ptr_impl; + MutPtrImplItem, "mut_ptr", mut_ptr_impl; + I8ImplItem, "i8", i8_impl; + I16ImplItem, "i16", i16_impl; + I32ImplItem, "i32", i32_impl; + I64ImplItem, "i64", i64_impl; + IsizeImplItem, "isize", isize_impl; + U8ImplItem, "u8", u8_impl; + U16ImplItem, "u16", u16_impl; + U32ImplItem, "u32", u32_impl; + U64ImplItem, "u64", u64_impl; + UsizeImplItem, "usize", usize_impl; + F32ImplItem, "f32", f32_impl; + F64ImplItem, "f64", f64_impl; + SendTraitLangItem, "send", send_trait; SizedTraitLangItem, "sized", sized_trait; CopyTraitLangItem, "copy", copy_trait; @@ -298,9 +316,6 @@ lets_do_this! { StartFnLangItem, "start", start_fn; - TyDescStructLangItem, "ty_desc", ty_desc; - OpaqueStructLangItem, "opaque", opaque; - EhPersonalityLangItem, "eh_personality", eh_personality; ExchangeHeapLangItem, "exchange_heap", exchange_heap; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index e58136fb3f..d7161607b6 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -51,8 +51,8 @@ //! enclosing function. On the way down the tree, it identifies those AST //! nodes and variable IDs that will be needed for the liveness analysis //! and assigns them contiguous IDs. The liveness id for an AST node is -//! called a `live_node` (it's a newtype'd uint) and the id for a variable -//! is called a `variable` (another newtype'd uint). +//! called a `live_node` (it's a newtype'd usize) and the id for a variable +//! is called a `variable` (another newtype'd usize). //! //! On the way back up the tree, as we are about to exit from a function //! declaration we allocate a `liveness` instance. Now that we know @@ -118,9 +118,11 @@ use middle::ty::ClosureTyper; use lint; use util::nodemap::NodeMap; -use std::{fmt, old_io, uint}; -use std::rc::Rc; +use std::{fmt, usize}; +use std::io::prelude::*; +use std::io; use std::iter::repeat; +use std::rc::Rc; use syntax::ast::{self, NodeId, Expr}; use syntax::codemap::{BytePos, original_sp, Span}; use syntax::parse::token::{self, special_idents}; @@ -137,18 +139,18 @@ enum LoopKind<'a> { WhileLoop(&'a Expr), } -#[derive(Copy, PartialEq)] -struct Variable(uint); +#[derive(Copy, Clone, PartialEq)] +struct Variable(usize); #[derive(Copy, PartialEq)] -struct LiveNode(uint); +struct LiveNode(usize); impl Variable { - fn get(&self) -> uint { let Variable(v) = *self; v } + fn get(&self) -> usize { let Variable(v) = *self; v } } impl LiveNode { - fn get(&self) -> uint { let LiveNode(v) = *self; v } + fn get(&self) -> usize { let LiveNode(v) = *self; v } } impl Clone for LiveNode { @@ -157,7 +159,7 @@ impl Clone for LiveNode { } } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum LiveNodeKind { FreeVarNode(Span), ExprNode(Span), @@ -232,24 +234,24 @@ impl fmt::Debug for Variable { impl LiveNode { fn is_valid(&self) -> bool { - self.get() != uint::MAX + self.get() != usize::MAX } } -fn invalid_node() -> LiveNode { LiveNode(uint::MAX) } +fn invalid_node() -> LiveNode { LiveNode(usize::MAX) } struct CaptureInfo { ln: LiveNode, var_nid: NodeId } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] struct LocalInfo { id: NodeId, ident: ast::Ident } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum VarKind { Arg(NodeId, ast::Ident), Local(LocalInfo), @@ -260,8 +262,8 @@ enum VarKind { struct IrMaps<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, - num_live_nodes: uint, - num_vars: uint, + num_live_nodes: usize, + num_vars: usize, live_node_map: NodeMap, variable_map: NodeMap, capture_info_map: NodeMap>>, @@ -325,7 +327,7 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { self.tcx .sess .span_bug(span, &format!("no variable registered for id {}", - node_id)[]); + node_id)); } } } @@ -445,8 +447,8 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) { fn visit_expr(ir: &mut IrMaps, expr: &Expr) { match expr.node { // live nodes required for uses or definitions of variables: - ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = ir.tcx.def_map.borrow()[expr.id].clone(); + ast::ExprPath(..) => { + let def = ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def(); debug!("expr {}: path that leads to {:?}", expr.id, def); if let DefLocal(..) = def { ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); @@ -532,7 +534,7 @@ fn invalid_users() -> Users { } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Specials { exit_ln: LiveNode, fallthrough_ln: LiveNode, @@ -540,9 +542,9 @@ struct Specials { clean_exit_var: Variable } -static ACC_READ: uint = 1; -static ACC_WRITE: uint = 2; -static ACC_USE: uint = 4; +const ACC_READ: u32 = 1; +const ACC_WRITE: u32 = 2; +const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx: 'a> { ir: &'a mut IrMaps<'a, 'tcx>, @@ -585,7 +587,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.tcx.sess.span_bug( span, &format!("no live node registered for node {}", - node_id)[]); + node_id)); } } } @@ -631,7 +633,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { succ } - fn idx(&self, ln: LiveNode, var: Variable) -> uint { + fn idx(&self, ln: LiveNode, var: Variable) -> usize { ln.get() * self.ir.num_vars + var.get() } @@ -670,7 +672,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn indices2(&mut self, ln: LiveNode, succ_ln: LiveNode, mut op: F) where - F: FnMut(&mut Liveness<'a, 'tcx>, uint, uint), + F: FnMut(&mut Liveness<'a, 'tcx>, usize, usize), { let node_base_idx = self.idx(ln, Variable(0)); let succ_base_idx = self.idx(succ_ln, Variable(0)); @@ -680,11 +682,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn write_vars(&self, - wr: &mut old_io::Writer, + wr: &mut Write, ln: LiveNode, mut test: F) - -> old_io::IoResult<()> where - F: FnMut(uint) -> LiveNode, + -> io::Result<()> where + F: FnMut(usize) -> LiveNode, { let node_base_idx = self.idx(ln, Variable(0)); for var_idx in 0..self.ir.num_vars { @@ -705,8 +707,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { Some(_) => { // Refers to a labeled loop. Use the results of resolve // to find with one - match self.ir.tcx.def_map.borrow().get(&id) { - Some(&DefLabel(loop_id)) => loop_id, + match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { + Some(DefLabel(loop_id)) => loop_id, _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \ doesn't refer to a loop") } @@ -727,7 +729,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn ln_str(&self, ln: LiveNode) -> String { let mut wr = Vec::new(); { - let wr = &mut wr as &mut old_io::Writer; + let wr = &mut wr as &mut Write; write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln)); self.write_vars(wr, ln, |idx| self.users[idx].reader); write!(wr, " writes"); @@ -807,7 +809,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } // Either read, write, or both depending on the acc bitset - fn acc(&mut self, ln: LiveNode, var: Variable, acc: uint) { + fn acc(&mut self, ln: LiveNode, var: Variable, acc: u32) { debug!("{:?} accesses[{:x}] {:?}: {}", ln, acc, var, self.ln_str(ln)); @@ -947,7 +949,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match expr.node { // Interesting cases with control flow or which gen/kill - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { self.access_path(expr, succ, ACC_READ | ACC_USE) } @@ -1275,7 +1277,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // just ignore such cases and treat them as reads. match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => succ, + ast::ExprPath(..) => succ, ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ), ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ), _ => self.propagate_through_expr(expr, succ) @@ -1283,10 +1285,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } // see comment on propagate_through_lvalue() - fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint) + fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { self.access_path(expr, succ, acc) } @@ -1298,9 +1300,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint) + fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode { - match self.ir.tcx.def_map.borrow()[expr.id].clone() { + match self.ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() { DefLocal(nid) => { let ln = self.live_node(expr.id, expr.span); if acc != 0 { @@ -1468,7 +1470,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) | ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) | - ast::ExprRange(..) | ast::ExprQPath(..) => { + ast::ExprRange(..) => { visit::walk_expr(this, expr); } ast::ExprIfLet(..) => { @@ -1496,7 +1498,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> { let fn_ty = ty::node_id_to_type(self.ir.tcx, id); match fn_ty.sty { - ty::ty_closure(closure_def_id, _, substs) => + ty::ty_closure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), _ => ty::ty_fn_ret(fn_ty), @@ -1561,8 +1563,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_lvalue(&mut self, expr: &Expr) { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { - if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() { + ast::ExprPath(..) => { + if let DefLocal(nid) = self.ir.tcx.def_map.borrow().get(&expr.id) + .unwrap() + .full_def() { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually // mutable, then check for a reassignment to flag the mutability diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 4be7bb9c36..85255d04df 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -71,11 +71,13 @@ pub use self::Note::*; pub use self::deref_kind::*; pub use self::categorization::*; +use self::Aliasability::*; + use middle::check_const; use middle::def; use middle::region; use middle::ty::{self, Ty}; -use util::nodemap::{NodeMap}; +use util::nodemap::NodeMap; use util::ppaux::{Repr, UserString}; use syntax::ast::{MutImmutable, MutMutable}; @@ -94,7 +96,7 @@ pub enum categorization<'tcx> { cat_static_item, cat_upvar(Upvar), // upvar referenced by closure env cat_local(ast::NodeId), // local variable - cat_deref(cmt<'tcx>, uint, PointerKind), // deref of a ptr + cat_deref(cmt<'tcx>, usize, PointerKind), // deref of a ptr cat_interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc cat_downcast(cmt<'tcx>, ast::DefId), // selects a particular enum variant (*1) @@ -135,7 +137,7 @@ pub enum InteriorKind { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum FieldName { NamedField(ast::Name), - PositionalField(uint) + PositionalField(usize) } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] @@ -197,7 +199,7 @@ pub type cmt<'tcx> = Rc>; // We pun on *T to mean both actual deref of a ptr as well // as accessing of components: -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum deref_kind { deref_ptr(PointerKind), deref_interior(InteriorKind), @@ -261,6 +263,9 @@ pub struct MemCategorizationContext<'t,TYPER:'t> { } impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {} +impl<'t,TYPER:'t> Clone for MemCategorizationContext<'t,TYPER> { + fn clone(&self) -> MemCategorizationContext<'t,TYPER> { *self } +} pub type McResult = Result; @@ -295,23 +300,29 @@ pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> { impl MutabilityCategory { pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory { - match m { + let ret = match m { MutImmutable => McImmutable, MutMutable => McDeclared - } + }; + debug!("MutabilityCategory::{}({:?}) => {:?}", + "from_mutbl", m, ret); + ret } pub fn from_borrow_kind(borrow_kind: ty::BorrowKind) -> MutabilityCategory { - match borrow_kind { + let ret = match borrow_kind { ty::ImmBorrow => McImmutable, ty::UniqueImmBorrow => McImmutable, ty::MutBorrow => McDeclared, - } + }; + debug!("MutabilityCategory::{}({:?}) => {:?}", + "from_borrow_kind", borrow_kind, ret); + ret } - pub fn from_pointer_kind(base_mutbl: MutabilityCategory, - ptr: PointerKind) -> MutabilityCategory { - match ptr { + fn from_pointer_kind(base_mutbl: MutabilityCategory, + ptr: PointerKind) -> MutabilityCategory { + let ret = match ptr { Unique => { base_mutbl.inherit() } @@ -321,11 +332,14 @@ impl MutabilityCategory { UnsafePtr(m) => { MutabilityCategory::from_mutbl(m) } - } + }; + debug!("MutabilityCategory::{}({:?}, {:?}) => {:?}", + "from_pointer_kind", base_mutbl, ptr, ret); + ret } fn from_local(tcx: &ty::ctxt, id: ast::NodeId) -> MutabilityCategory { - match tcx.map.get(id) { + let ret = match tcx.map.get(id) { ast_map::NodeLocal(p) | ast_map::NodeArg(p) => match p.node { ast::PatIdent(bind_mode, _, _) => { if bind_mode == ast::BindByValue(ast::MutMutable) { @@ -337,30 +351,39 @@ impl MutabilityCategory { _ => tcx.sess.span_bug(p.span, "expected identifier pattern") }, _ => tcx.sess.span_bug(tcx.map.span(id), "expected identifier pattern") - } + }; + debug!("MutabilityCategory::{}(tcx, id={:?}) => {:?}", + "from_local", id, ret); + ret } pub fn inherit(&self) -> MutabilityCategory { - match *self { + let ret = match *self { McImmutable => McImmutable, McDeclared => McInherited, McInherited => McInherited, - } + }; + debug!("{:?}.inherit() => {:?}", self, ret); + ret } pub fn is_mutable(&self) -> bool { - match *self { + let ret = match *self { McImmutable => false, McInherited => true, McDeclared => true, - } + }; + debug!("{:?}.is_mutable() => {:?}", self, ret); + ret } pub fn is_immutable(&self) -> bool { - match *self { + let ret = match *self { McImmutable => true, McDeclared | McInherited => false - } + }; + debug!("{:?}.is_immutable() => {:?}", self, ret); + ret } pub fn to_user_str(&self) -> &'static str { @@ -428,7 +451,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Some(adjustment) => { match *adjustment { - ty::AdjustReifyFnPointer(..) => { + ty::AdjustReifyFnPointer(..) | + ty::AdjustUnsafeFnPointer(..) => { debug!("cat_expr(AdjustReifyFnPointer): {}", expr.repr(self.tcx())); // Convert a bare fn to a closure by adding NULL env. @@ -461,7 +485,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { pub fn cat_expr_autoderefd(&self, expr: &ast::Expr, - autoderefs: uint) + autoderefs: usize) -> McResult> { let mut cmt = try!(self.cat_expr_unadjusted(expr)); debug!("cat_expr_autoderefd: autoderefs={}, cmt={}", @@ -529,8 +553,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } - ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = (*self.tcx().def_map.borrow())[expr.id]; + ast::ExprPath(..) => { + let def = self.tcx().def_map.borrow().get(&expr.id).unwrap().full_def(); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -575,14 +599,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { match def { def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) | - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => { + def::DefFn(..) | 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::DefTyParam(..) | def::DefRegion(_) | def::DefLabel(_) | def::DefSelfTy(..) | - def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> { + def::DefAssociatedTy(..) => { Ok(Rc::new(cmt_ { id:id, span:span, @@ -607,7 +631,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { def::DefUpvar(var_id, fn_node_id) => { let ty = try!(self.node_ty(fn_node_id)); match ty.sty { - ty::ty_closure(closure_id, _, _) => { + ty::ty_closure(closure_id, _) => { match self.typer.closure_kind(closure_id) { Some(kind) => { self.cat_upvar(id, span, var_id, fn_node_id, kind) @@ -624,7 +648,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { span, &format!("Upvar of non-closure {} - {}", fn_node_id, - ty.repr(self.tcx()))[]); + ty.repr(self.tcx()))); } } } @@ -732,7 +756,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } }; - Ok(Rc::new(cmt_result)) + let ret = Rc::new(cmt_result); + debug!("cat_upvar ret={}", ret.repr(self.tcx())); + Ok(ret) } fn env_deref(&self, @@ -793,14 +819,18 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { McDeclared | McInherited => { } } - cmt_ { + let ret = cmt_ { id: id, span: span, cat: cat_deref(Rc::new(cmt_result), 0, env_ptr), mutbl: deref_mutbl, ty: var_ty, note: NoteClosureEnv(upvar_id) - } + }; + + debug!("env_deref ret {}", ret.repr(self.tcx())); + + ret } pub fn cat_rvalue_node(&self, @@ -830,7 +860,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } }; - self.cat_rvalue(id, span, re, expr_ty) + let ret = self.cat_rvalue(id, span, re, expr_ty); + debug!("cat_rvalue_node ret {}", ret.repr(self.tcx())); + ret } pub fn cat_rvalue(&self, @@ -838,14 +870,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { span: Span, temp_scope: ty::Region, expr_ty: Ty<'tcx>) -> cmt<'tcx> { - Rc::new(cmt_ { + let ret = Rc::new(cmt_ { id:cmt_id, span:span, cat:cat_rvalue(temp_scope), mutbl:McDeclared, ty:expr_ty, note: NoteNone - }) + }); + debug!("cat_rvalue ret {}", ret.repr(self.tcx())); + ret } pub fn cat_field(&self, @@ -854,36 +888,40 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { f_name: ast::Name, f_ty: Ty<'tcx>) -> cmt<'tcx> { - Rc::new(cmt_ { + let ret = Rc::new(cmt_ { id: node.id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), cat: cat_interior(base_cmt, InteriorField(NamedField(f_name))), ty: f_ty, note: NoteNone - }) + }); + debug!("cat_field ret {}", ret.repr(self.tcx())); + ret } pub fn cat_tup_field(&self, node: &N, base_cmt: cmt<'tcx>, - f_idx: uint, + f_idx: usize, f_ty: Ty<'tcx>) -> cmt<'tcx> { - Rc::new(cmt_ { + let ret = Rc::new(cmt_ { id: node.id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), cat: cat_interior(base_cmt, InteriorField(PositionalField(f_idx))), ty: f_ty, note: NoteNone - }) + }); + debug!("cat_tup_field ret {}", ret.repr(self.tcx())); + ret } fn cat_deref(&self, node: &N, base_cmt: cmt<'tcx>, - deref_cnt: uint, + deref_cnt: usize, deref_context: DerefKindContext) -> McResult> { let adjustment = match self.typer.adjustments().borrow().get(&node.id()) { @@ -912,10 +950,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { }; let base_cmt_ty = base_cmt.ty; match ty::deref(base_cmt_ty, true) { - Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, + Some(mt) => { + let ret = self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, deref_context, - /* implicit: */ false), + /* implicit: */ false); + debug!("cat_deref ret {}", ret.repr(self.tcx())); + ret + } None => { debug!("Explicit deref of non-derefable type: {}", base_cmt_ty.repr(self.tcx())); @@ -927,7 +969,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { fn cat_deref_common(&self, node: &N, base_cmt: cmt<'tcx>, - deref_cnt: uint, + deref_cnt: usize, deref_ty: Ty<'tcx>, deref_context: DerefKindContext, implicit: bool) @@ -953,14 +995,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { (base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior)) } }; - Ok(Rc::new(cmt_ { + let ret = Rc::new(cmt_ { id: node.id(), span: node.span(), cat: cat, mutbl: m, ty: deref_ty, note: NoteNone - })) + }); + debug!("cat_deref_common ret {}", ret.repr(self.tcx())); + Ok(ret) } pub fn cat_index(&self, @@ -1008,8 +1052,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { }; let m = base_cmt.mutbl.inherit(); - return Ok(interior(elt, base_cmt.clone(), base_cmt.ty, - m, context, element_ty)); + let ret = interior(elt, base_cmt.clone(), base_cmt.ty, + m, context, element_ty); + debug!("cat_index ret {}", ret.repr(self.tcx())); + return Ok(ret); fn interior<'tcx, N: ast_node>(elt: &N, of_cmt: cmt<'tcx>, @@ -1038,14 +1084,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { context: InteriorOffsetKind) -> McResult> { - match try!(deref_kind(base_cmt.ty, Some(context))) { + let ret = match try!(deref_kind(base_cmt.ty, Some(context))) { deref_ptr(ptr) => { // for unique ptrs, we inherit mutability from the // owning reference. let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr); // the deref is explicit in the resulting cmt - Ok(Rc::new(cmt_ { + Rc::new(cmt_ { id:elt.id(), span:elt.span(), cat:cat_deref(base_cmt.clone(), 0, ptr), @@ -1055,13 +1101,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { None => self.tcx().sess.bug("Found non-derefable type") }, note: NoteNone - })) + }) } deref_interior(_) => { - Ok(base_cmt) + base_cmt } - } + }; + debug!("deref_vec ret {}", ret.repr(self.tcx())); + Ok(ret) } /// Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is the cmt for `P`, `slice_pat` is @@ -1111,14 +1159,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { interior_ty: Ty<'tcx>, interior: InteriorKind) -> cmt<'tcx> { - Rc::new(cmt_ { + let ret = Rc::new(cmt_ { id: node.id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), cat: cat_interior(base_cmt, interior), ty: interior_ty, note: NoteNone - }) + }); + debug!("cat_imm_interior ret={}", ret.repr(self.tcx())); + ret } pub fn cat_downcast(&self, @@ -1127,14 +1177,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { downcast_ty: Ty<'tcx>, variant_did: ast::DefId) -> cmt<'tcx> { - Rc::new(cmt_ { + let ret = Rc::new(cmt_ { id: node.id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), cat: cat_downcast(base_cmt, variant_did), ty: downcast_ty, note: NoteNone - }) + }); + debug!("cat_downcast ret={}", ret.repr(self.tcx())); + ret } pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()> @@ -1199,14 +1251,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { (*op)(self, cmt.clone(), pat); - let def_map = self.tcx().def_map.borrow(); - let opt_def = def_map.get(&pat.id); + let opt_def = self.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def()); // Note: This goes up here (rather than within the PatEnum arm // alone) because struct patterns can refer to struct types or // to struct variants within enums. let cmt = match opt_def { - Some(&def::DefVariant(enum_did, variant_did, _)) + Some(def::DefVariant(enum_did, variant_did, _)) // univariant enums do not need downcasts if !ty::enum_is_univariant(self.tcx(), enum_did) => { self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) @@ -1224,7 +1275,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } ast::PatEnum(_, Some(ref subpats)) => { match opt_def { - Some(&def::DefVariant(..)) => { + Some(def::DefVariant(..)) => { // variant(x, y, z) for (i, subpat) in subpats.iter().enumerate() { let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) @@ -1237,7 +1288,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { try!(self.cat_pattern_(subcmt, &**subpat, op)); } } - Some(&def::DefStruct(..)) => { + Some(def::DefStruct(..)) => { for (i, subpat) in subpats.iter().enumerate() { let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let cmt_field = @@ -1247,7 +1298,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { try!(self.cat_pattern_(cmt_field, &**subpat, op)); } } - Some(&def::DefConst(..)) => { + Some(def::DefConst(..)) => { for subpat in subpats { try!(self.cat_pattern_(cmt.clone(), &**subpat, op)); } @@ -1341,17 +1392,25 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } -#[derive(Copy)] +#[derive(Copy, Clone, Debug)] pub enum InteriorSafety { InteriorUnsafe, InteriorSafe } -#[derive(Copy)] +#[derive(Clone, Debug)] +pub enum Aliasability { + FreelyAliasable(AliasableReason), + NonAliasable, + ImmutableUnique(Box), +} + +#[derive(Copy, Clone, Debug)] pub enum AliasableReason { AliasableBorrowed, AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env AliasableOther, + UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique AliasableStatic(InteriorSafety), AliasableStaticMut(InteriorSafety), } @@ -1380,9 +1439,9 @@ impl<'tcx> cmt_<'tcx> { } } - /// Returns `Some(_)` if this lvalue represents a freely aliasable pointer type. + /// Returns `FreelyAliasable(_)` if this lvalue represents a freely aliasable pointer type. pub fn freely_aliasable(&self, ctxt: &ty::ctxt<'tcx>) - -> Option { + -> Aliasability { // Maybe non-obvious: copied upvars can only be considered // non-aliasable in once closures, since any other kind can be // aliased and eventually recused. @@ -1393,17 +1452,27 @@ impl<'tcx> cmt_<'tcx> { cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) | cat_deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) | cat_downcast(ref b, _) | - cat_deref(ref b, _, Unique) | cat_interior(ref b, _) => { // Aliasability depends on base cmt b.freely_aliasable(ctxt) } + cat_deref(ref b, _, Unique) => { + let sub = b.freely_aliasable(ctxt); + if b.mutbl.is_mutable() { + // Aliasability depends on base cmt alone + sub + } else { + // Do not allow mutation through an immutable box. + ImmutableUnique(Box::new(sub)) + } + } + cat_rvalue(..) | cat_local(..) | cat_upvar(..) | cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but... - None + NonAliasable } cat_static_item(..) => { @@ -1414,17 +1483,18 @@ impl<'tcx> cmt_<'tcx> { }; if self.mutbl.is_mutable() { - Some(AliasableStaticMut(int_safe)) + FreelyAliasable(AliasableStaticMut(int_safe)) } else { - Some(AliasableStatic(int_safe)) + FreelyAliasable(AliasableStatic(int_safe)) } } cat_deref(ref base, _, BorrowedPtr(ty::ImmBorrow, _)) | cat_deref(ref base, _, Implicit(ty::ImmBorrow, _)) => { match base.cat { - cat_upvar(Upvar{ id, .. }) => Some(AliasableClosure(id.closure_expr_id)), - _ => Some(AliasableBorrowed) + cat_upvar(Upvar{ id, .. }) => + FreelyAliasable(AliasableClosure(id.closure_expr_id)), + _ => FreelyAliasable(AliasableBorrowed) } } } @@ -1636,4 +1706,3 @@ impl<'tcx> UserString<'tcx> for Upvar { format!("captured outer variable in an `{}` closure", kind) } } - diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 01dc55c3ee..12b56562c8 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -13,7 +13,7 @@ use middle::ty; use util::nodemap::FnvHashMap; use syntax::ast; -use syntax::ast_util::{walk_pat}; +use syntax::ast_util::walk_pat; use syntax::codemap::{Span, DUMMY_SP}; pub type PatIdMap = FnvHashMap; @@ -34,8 +34,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { - match dm.borrow().get(&pat.id) { - Some(&DefVariant(..)) => true, + match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefVariant(..)) => true, _ => false } } @@ -49,8 +49,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { - match dm.borrow().get(&pat.id) { - Some(&DefVariant(..)) | Some(&DefStruct(..)) => true, + match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefVariant(..)) | Some(DefStruct(..)) => true, _ => false } } @@ -61,8 +61,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool { pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool { match pat.node { ast::PatIdent(_, _, None) | ast::PatEnum(..) => { - match dm.borrow().get(&pat.id) { - Some(&DefConst(..)) => true, + match dm.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(DefConst(..)) => true, _ => false } } @@ -119,6 +119,39 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool { contains_bindings } +/// Checks if the pattern contains any `ref` or `ref mut` bindings. +pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> bool { + let mut result = false; + pat_bindings(dm, pat, |mode, _, _, _| { + match mode { + ast::BindingMode::BindByRef(_) => { result = true; } + ast::BindingMode::BindByValue(_) => { } + } + }); + result +} + +/// Checks if the patterns for this arm contain any `ref` or `ref mut` +/// bindings. +pub fn arm_contains_ref_binding(dm: &DefMap, arm: &ast::Arm) -> bool { + arm.pats.iter().any(|pat| pat_contains_ref_binding(dm, pat)) +} + +/// Checks if the pattern contains any patterns that bind something to +/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`, +pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool { + let mut contains_bindings = false; + walk_pat(pat, |p| { + if pat_is_binding_or_wild(dm, p) { + contains_bindings = true; + false // there's at least one binding/wildcard, can short circuit now. + } else { + true + } + }); + contains_bindings +} + pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> { match pat.node { ast::PatIdent(ast::BindByValue(_), ref path1, None) => { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index dd1e32d13a..d8efb5655a 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -16,7 +16,7 @@ pub use self::PrivateDep::*; pub use self::ImportUse::*; pub use self::LastPrivate::*; -use util::nodemap::{DefIdSet, NodeMap, NodeSet}; +use util::nodemap::{DefIdSet, NodeSet}; use syntax::ast; @@ -32,10 +32,7 @@ pub type ExternalExports = DefIdSet; /// reexporting a public struct doesn't inline the doc). pub type PublicItems = NodeSet; -// FIXME: dox -pub type LastPrivateMap = NodeMap; - -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum LastPrivate { LastMod(PrivateDep), // `use` directives (imports) can refer to two separate definitions in the @@ -49,14 +46,14 @@ pub enum LastPrivate { type_used: ImportUse}, } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum PrivateDep { AllPublic, DependsOn(ast::DefId), } // How an import is used. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum ImportUse { Unused, // The import is not used. Used, // The import is used. diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 0af226de25..1bd45b5fc8 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -25,21 +25,11 @@ use std::collections::HashSet; use syntax::abi; use syntax::ast; use syntax::ast_map; -use syntax::ast_util::{is_local, PostExpansionMethod}; -use syntax::attr::{InlineAlways, InlineHint, InlineNever, InlineNone}; +use syntax::ast_util::is_local; use syntax::attr; use syntax::visit::Visitor; use syntax::visit; -// Returns true if the given set of attributes contains the `#[inline]` -// attribute. -fn attributes_specify_inlining(attrs: &[ast::Attribute]) -> bool { - match attr::find_inline_attr(attrs) { - InlineNone | InlineNever => false, - InlineAlways | InlineHint => true, - } -} - // Returns true if the given set of generics implies that the item it's // associated with must be inlined. fn generics_require_inlining(generics: &ast::Generics) -> bool { @@ -50,7 +40,7 @@ fn generics_require_inlining(generics: &ast::Generics) -> bool { // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. fn item_might_be_inlined(item: &ast::Item) -> bool { - if attributes_specify_inlining(&item.attrs[]) { + if attr::requests_inline(&item.attrs) { return true } @@ -63,10 +53,11 @@ fn item_might_be_inlined(item: &ast::Item) -> bool { } } -fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method, +fn method_might_be_inlined(tcx: &ty::ctxt, sig: &ast::MethodSig, + impl_item: &ast::ImplItem, impl_src: ast::DefId) -> bool { - if attributes_specify_inlining(&method.attrs[]) || - generics_require_inlining(method.pe_generics()) { + if attr::requests_inline(&impl_item.attrs) || + generics_require_inlining(&sig.generics) { return true } if is_local(impl_src) { @@ -76,13 +67,13 @@ fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method, item_might_be_inlined(&*item) } Some(..) | None => { - tcx.sess.span_bug(method.span, "impl did is not an item") + tcx.sess.span_bug(impl_item.span, "impl did is not an item") } } } } else { - tcx.sess.span_bug(method.span, "found a foreign impl as a parent of a \ - local method") + tcx.sess.span_bug(impl_item.span, "found a foreign impl as a parent \ + of a local method") } } @@ -104,9 +95,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let def = match self.tcx.def_map.borrow().get(&expr.id) { - Some(&def) => def, + Some(d) => d.full_def(), None => { self.tcx.sess.span_bug(expr.span, "def ID not in def map?!") @@ -137,7 +128,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { } ast::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - match (*self.tcx.method_map.borrow())[method_call].origin { + match (*self.tcx.method_map.borrow()).get(&method_call).unwrap().origin { ty::MethodStatic(def_id) => { if is_local(def_id) { if self.def_id_represents_local_inlined_item(def_id) { @@ -191,18 +182,16 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } } Some(ast_map::NodeTraitItem(trait_method)) => { - match *trait_method { - ast::RequiredMethod(_) => false, - ast::ProvidedMethod(_) => true, - ast::TypeTraitItem(_) => false, + match trait_method.node { + ast::MethodTraitItem(_, ref body) => body.is_some(), + ast::TypeTraitItem(..) => false, } } Some(ast_map::NodeImplItem(impl_item)) => { - match *impl_item { - ast::MethodImplItem(ref method) => { - if generics_require_inlining(method.pe_generics()) || - attributes_specify_inlining( - &method.attrs[]) { + match impl_item.node { + ast::MethodImplItem(ref sig, _) => { + if generics_require_inlining(&sig.generics) || + attr::requests_inline(&impl_item.attrs) { true } else { let impl_did = self.tcx @@ -224,6 +213,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } } ast::TypeImplItem(_) => false, + ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro") } } Some(_) => false, @@ -249,7 +239,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { None => { self.tcx.sess.bug(&format!("found unmapped ID in worklist: \ {}", - search_item)[]) + search_item)) } } } @@ -301,7 +291,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { ast::ItemTy(..) | ast::ItemStatic(_, _, _) | ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemImpl(..) | ast::ItemTrait(..) | - ast::ItemStruct(..) | ast::ItemEnum(..) => {} + ast::ItemStruct(..) | ast::ItemEnum(..) | + ast::ItemDefaultImpl(..) => {} _ => { self.tcx.sess.span_bug(item.span, @@ -311,25 +302,26 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } } ast_map::NodeTraitItem(trait_method) => { - match *trait_method { - ast::RequiredMethod(..) => { + match trait_method.node { + ast::MethodTraitItem(_, None) => { // Keep going, nothing to get exported } - ast::ProvidedMethod(ref method) => { - visit::walk_block(self, &*method.pe_body()); + ast::MethodTraitItem(_, Some(ref body)) => { + visit::walk_block(self, body); } - ast::TypeTraitItem(_) => {} + ast::TypeTraitItem(..) => {} } } ast_map::NodeImplItem(impl_item) => { - match *impl_item { - ast::MethodImplItem(ref method) => { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { let did = self.tcx.map.get_parent_did(search_item); - if method_might_be_inlined(self.tcx, &**method, did) { - visit::walk_block(self, method.pe_body()) + if method_might_be_inlined(self.tcx, sig, impl_item, did) { + visit::walk_block(self, body) } } ast::TypeImplItem(_) => {} + ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro") } } // Nothing to recurse on for these @@ -342,7 +334,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { .bug(&format!("found unexpected thingy in worklist: {}", self.tcx .map - .node_to_string(search_item))[]) + .node_to_string(search_item))) } } } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index e539f6ae6c..652f661325 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -25,7 +25,7 @@ use std::cell::RefCell; use syntax::codemap::{self, Span}; use syntax::{ast, visit}; use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local}; -use syntax::ast_util::{stmt_id}; +use syntax::ast_util::stmt_id; use syntax::ast_map; use syntax::ptr::P; use syntax::visit::{Visitor, FnKind}; @@ -136,7 +136,7 @@ impl DestructionScopeData { RustcDecodable, Debug, Copy)] pub struct BlockRemainder { pub block: ast::NodeId, - pub first_statement_index: uint, + pub first_statement_index: usize, } impl CodeExtent { @@ -206,56 +206,72 @@ impl CodeExtent { } /// The region maps encode information about region relationships. -/// -/// - `scope_map` maps from a scope id to the enclosing scope id; this is -/// usually corresponding to the lexical nesting, though in the case of -/// closures the parent scope is the innermost conditional expression or repeating -/// block. (Note that the enclosing scope id for the block -/// associated with a closure is the closure itself.) -/// -/// - `var_map` maps from a variable or binding id to the block in which -/// that variable is declared. -/// -/// - `free_region_map` maps from a free region `a` to a list of free -/// regions `bs` such that `a <= b for all b in bs` -/// - the free region map is populated during type check as we check -/// each function. See the function `relate_free_regions` for -/// more information. -/// -/// - `rvalue_scopes` includes entries for those expressions whose cleanup -/// scope is larger than the default. The map goes from the expression -/// id to the cleanup scope id. For rvalues not present in this table, -/// the appropriate cleanup scope is the innermost enclosing statement, -/// conditional expression, or repeating block (see `terminating_scopes`). -/// -/// - `terminating_scopes` is a set containing the ids of each statement, -/// or conditional/repeating expression. These scopes are calling "terminating -/// scopes" because, when attempting to find the scope of a temporary, by -/// default we search up the enclosing scopes until we encounter the -/// terminating scope. A conditional/repeating -/// expression is one which is not guaranteed to execute exactly once -/// upon entering the parent scope. This could be because the expression -/// only executes conditionally, such as the expression `b` in `a && b`, -/// or because the expression may execute many times, such as a loop -/// body. The reason that we distinguish such expressions is that, upon -/// exiting the parent scope, we cannot statically know how many times -/// the expression executed, and thus if the expression creates -/// temporaries we cannot know statically how many such temporaries we -/// would have to cleanup. Therefore we ensure that the temporaries never -/// outlast the conditional/repeating expression, preventing the need -/// for dynamic checks and/or arbitrary amounts of stack space. pub struct RegionMaps { + /// `scope_map` maps from a scope id to the enclosing scope id; + /// this is usually corresponding to the lexical nesting, though + /// in the case of closures the parent scope is the innermost + /// conditional expression or repeating block. (Note that the + /// enclosing scope id for the block associated with a closure is + /// the closure itself.) scope_map: RefCell>, + + /// `var_map` maps from a variable or binding id to the block in + /// which that variable is declared. var_map: RefCell>, + + /// `free_region_map` maps from a free region `a` to a list of + /// free regions `bs` such that `a <= b for all b in bs` + /// + /// NB. the free region map is populated during type check as we + /// check each function. See the function `relate_free_regions` + /// for more information. free_region_map: RefCell>>, + + /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is + /// larger than the default. The map goes from the expression id + /// to the cleanup scope id. For rvalues not present in this + /// table, the appropriate cleanup scope is the innermost + /// enclosing statement, conditional expression, or repeating + /// block (see `terminating_scopes`). rvalue_scopes: RefCell>, + + /// `terminating_scopes` is a set containing the ids of each + /// statement, or conditional/repeating expression. These scopes + /// are calling "terminating scopes" because, when attempting to + /// find the scope of a temporary, by default we search up the + /// enclosing scopes until we encounter the terminating scope. A + /// conditional/repeating expression is one which is not + /// guaranteed to execute exactly once upon entering the parent + /// scope. This could be because the expression only executes + /// conditionally, such as the expression `b` in `a && b`, or + /// because the expression may execute many times, such as a loop + /// body. The reason that we distinguish such expressions is that, + /// upon exiting the parent scope, we cannot statically know how + /// many times the expression executed, and thus if the expression + /// creates temporaries we cannot know statically how many such + /// temporaries we would have to cleanup. Therefore we ensure that + /// the temporaries never outlast the conditional/repeating + /// expression, preventing the need for dynamic checks and/or + /// arbitrary amounts of stack space. terminating_scopes: RefCell>, + + /// Encodes the hierarchy of fn bodies. Every fn body (including + /// closures) forms its own distinct region hierarchy, rooted in + /// the block that is the fn body. This map points from the id of + /// that root block to the id of the root block for the enclosing + /// fn, if any. Thus the map structures the fn bodies into a + /// hierarchy based on their lexical mapping. This is used to + /// handle the relationships between regions in a fn and in a + /// closure defined by that fn. See the "Modeling closures" + /// section of the README in middle::infer::region_inference for + /// more details. + fn_tree: RefCell>, } /// Carries the node id for the innermost block or match expression, /// for building up the `var_map` which maps ids to the blocks in /// which they were declared. -#[derive(PartialEq, Eq, Debug, Copy)] +#[derive(PartialEq, Eq, Debug, Copy, Clone)] enum InnermostDeclaringBlock { None, Block(ast::NodeId), @@ -280,11 +296,11 @@ impl InnermostDeclaringBlock { /// Contextual information for declarations introduced by a statement /// (i.e. `let`). It carries node-id's for statement and enclosing /// block both, as well as the statement's index within the block. -#[derive(PartialEq, Eq, Debug, Copy)] +#[derive(PartialEq, Eq, Debug, Copy, Clone)] struct DeclaringStatementContext { stmt_id: ast::NodeId, block_id: ast::NodeId, - stmt_index: uint, + stmt_index: usize, } impl DeclaringStatementContext { @@ -296,7 +312,7 @@ impl DeclaringStatementContext { } } -#[derive(PartialEq, Eq, Debug, Copy)] +#[derive(PartialEq, Eq, Debug, Copy, Clone)] enum InnermostEnclosingExpr { None, Some(ast::NodeId), @@ -318,10 +334,20 @@ impl InnermostEnclosingExpr { } } -#[derive(Debug, Copy)] +#[derive(Debug, Copy, Clone)] pub struct Context { + /// the root of the current region tree. This is typically the id + /// of the innermost fn body. Each fn forms its own disjoint tree + /// in the region hierarchy. These fn bodies are themselves + /// arranged into a tree. See the "Modeling closures" section of + /// the README in middle::infer::region_inference for more + /// details. + root_id: Option, + + /// the scope that contains any new variables declared var_parent: InnermostDeclaringBlock, + /// region parent of expressions etc parent: InnermostEnclosingExpr, } @@ -379,19 +405,40 @@ impl RegionMaps { self.free_region_map.borrow_mut().insert(sub, vec!(sup)); } + /// Records that `sub_fn` is defined within `sup_fn`. These ids + /// should be the id of the block that is the fn body, which is + /// also the root of the region hierarchy for that fn. + fn record_fn_parent(&self, sub_fn: ast::NodeId, sup_fn: ast::NodeId) { + debug!("record_fn_parent(sub_fn={:?}, sup_fn={:?})", sub_fn, sup_fn); + assert!(sub_fn != sup_fn); + let previous = self.fn_tree.borrow_mut().insert(sub_fn, sup_fn); + assert!(previous.is_none()); + } + + fn fn_is_enclosed_by(&self, mut sub_fn: ast::NodeId, sup_fn: ast::NodeId) -> bool { + let fn_tree = self.fn_tree.borrow(); + loop { + if sub_fn == sup_fn { return true; } + match fn_tree.get(&sub_fn) { + Some(&s) => { sub_fn = s; } + None => { return false; } + } + } + } + pub fn record_encl_scope(&self, sub: CodeExtent, sup: CodeExtent) { debug!("record_encl_scope(sub={:?}, sup={:?})", sub, sup); assert!(sub != sup); self.scope_map.borrow_mut().insert(sub, sup); } - pub fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { + fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.node_id()); self.var_map.borrow_mut().insert(var, lifetime); } - pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { + fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime); assert!(var != lifetime.node_id()); self.rvalue_scopes.borrow_mut().insert(var, lifetime); @@ -400,7 +447,7 @@ impl RegionMaps { /// Records that a scope is a TERMINATING SCOPE. Whenever we create automatic temporaries -- /// e.g. by an expression like `a().f` -- they will be freed within the innermost terminating /// scope. - pub fn mark_as_terminating_scope(&self, scope_id: CodeExtent) { + fn mark_as_terminating_scope(&self, scope_id: CodeExtent) { debug!("record_terminating_scope(scope_id={:?})", scope_id); self.terminating_scopes.borrow_mut().insert(scope_id); } @@ -560,15 +607,15 @@ impl RegionMaps { pub fn nearest_common_ancestor(&self, scope_a: CodeExtent, scope_b: CodeExtent) - -> Option { - if scope_a == scope_b { return Some(scope_a); } + -> CodeExtent { + if scope_a == scope_b { return scope_a; } let a_ancestors = ancestors_of(self, scope_a); let b_ancestors = ancestors_of(self, scope_b); let mut a_index = a_ancestors.len() - 1; let mut b_index = b_ancestors.len() - 1; - // Here, ~[ab]_ancestors is a vector going from narrow to broad. + // Here, [ab]_ancestors is a vector going from narrow to broad. // The end of each vector will be the item where the scope is // defined; if there are any common ancestors, then the tails of // the vector will be the same. So basically we want to walk @@ -577,23 +624,47 @@ impl RegionMaps { // then the corresponding scope is a superscope of the other. if a_ancestors[a_index] != b_ancestors[b_index] { - return None; + // In this case, the two regions belong to completely + // different functions. Compare those fn for lexical + // nesting. The reasoning behind this is subtle. See the + // "Modeling closures" section of the README in + // middle::infer::region_inference for more details. + let a_root_scope = a_ancestors[a_index]; + let b_root_scope = a_ancestors[a_index]; + return match (a_root_scope, b_root_scope) { + (CodeExtent::DestructionScope(a_root_id), + CodeExtent::DestructionScope(b_root_id)) => { + if self.fn_is_enclosed_by(a_root_id, b_root_id) { + // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` + scope_b + } else if self.fn_is_enclosed_by(b_root_id, a_root_id) { + // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b` + scope_a + } else { + // neither fn encloses the other + unreachable!() + } + } + _ => { + // root ids are always Misc right now + unreachable!() + } + }; } loop { // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index] // for all indices between a_index and the end of the array - if a_index == 0 { return Some(scope_a); } - if b_index == 0 { return Some(scope_b); } + if a_index == 0 { return scope_a; } + if b_index == 0 { return scope_b; } a_index -= 1; b_index -= 1; if a_ancestors[a_index] != b_ancestors[b_index] { - return Some(a_ancestors[a_index + 1]); + return a_ancestors[a_index + 1]; } } - fn ancestors_of(this: &RegionMaps, scope: CodeExtent) - -> Vec { + fn ancestors_of(this: &RegionMaps, scope: CodeExtent) -> Vec { // debug!("ancestors_of(scope={:?})", scope); let mut result = vec!(scope); let mut scope = scope; @@ -643,6 +714,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) { let prev_cx = visitor.cx; let blk_scope = CodeExtent::Misc(blk.id); + // If block was previously marked as a terminating scope during // the recursive visit of its parent node in the AST, then we need // to account for the destruction scope representing the extent of @@ -682,6 +754,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) { // itself has returned. visitor.cx = Context { + root_id: prev_cx.root_id, var_parent: InnermostDeclaringBlock::Block(blk.id), parent: InnermostEnclosingExpr::Some(blk.id), }; @@ -708,6 +781,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) { record_superlifetime( visitor, declaring.to_code_extent(), statement.span); visitor.cx = Context { + root_id: prev_cx.root_id, var_parent: InnermostDeclaringBlock::Statement(declaring), parent: InnermostEnclosingExpr::Statement(declaring), }; @@ -852,7 +926,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { // The idea is that call.callee_id represents *the time when // the invoked function is actually running* and call.id // represents *the time to prepare the arguments and make the - // call*. See the section "Borrows in Calls" borrowck/doc.rs + // call*. See the section "Borrows in Calls" borrowck/README.md // for an extended explanation of why this distinction is // important. // @@ -1101,6 +1175,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) { // Items create a new outer block scope as far as we're concerned. let prev_cx = visitor.cx; visitor.cx = Context { + root_id: None, var_parent: InnermostDeclaringBlock::None, parent: InnermostEnclosingExpr::None }; @@ -1109,7 +1184,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) { } fn resolve_fn(visitor: &mut RegionResolutionVisitor, - fk: FnKind, + _: FnKind, decl: &ast::FnDecl, body: &ast::Block, sp: Span, @@ -1125,42 +1200,36 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, let body_scope = CodeExtent::from_node_id(body.id); visitor.region_maps.mark_as_terminating_scope(body_scope); + let dtor_scope = CodeExtent::DestructionScope(body.id); visitor.region_maps.record_encl_scope(body_scope, dtor_scope); + record_superlifetime(visitor, dtor_scope, body.span); + if let Some(root_id) = visitor.cx.root_id { + visitor.region_maps.record_fn_parent(body.id, root_id); + } + let outer_cx = visitor.cx; // The arguments and `self` are parented to the body of the fn. visitor.cx = Context { + root_id: Some(body.id), parent: InnermostEnclosingExpr::Some(body.id), var_parent: InnermostDeclaringBlock::Block(body.id) }; visit::walk_fn_decl(visitor, decl); - // The body of the fn itself is either a root scope (top-level fn) - // or it continues with the inherited scope (closures). - match fk { - visit::FkItemFn(..) | visit::FkMethod(..) => { - visitor.cx = Context { - parent: InnermostEnclosingExpr::None, - var_parent: InnermostDeclaringBlock::None - }; - visitor.visit_block(body); - visitor.cx = outer_cx; - } - visit::FkFnBlock(..) => { - // FIXME(#3696) -- at present we are place the closure body - // within the region hierarchy exactly where it appears lexically. - // This is wrong because the closure may live longer - // than the enclosing expression. We should probably fix this, - // but the correct fix is a bit subtle, and I am also not sure - // that the present approach is unsound -- it may not permit - // any illegal programs. See issue for more details. - visitor.cx = outer_cx; - visitor.visit_block(body); - } - } + // The body of the every fn is a root scope. + visitor.cx = Context { + root_id: Some(body.id), + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None + }; + visitor.visit_block(body); + + // Restore context we had at the start. + visitor.cx = outer_cx; } impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> { @@ -1201,12 +1270,14 @@ pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps { free_region_map: RefCell::new(FnvHashMap()), rvalue_scopes: RefCell::new(NodeMap()), terminating_scopes: RefCell::new(FnvHashSet()), + fn_tree: RefCell::new(NodeMap()), }; { let mut visitor = RegionResolutionVisitor { sess: sess, region_maps: &maps, cx: Context { + root_id: None, parent: InnermostEnclosingExpr::None, var_parent: InnermostDeclaringBlock::None, } @@ -1223,6 +1294,7 @@ pub fn resolve_inlined_item(sess: &Session, sess: sess, region_maps: region_maps, cx: Context { + root_id: None, parent: InnermostEnclosingExpr::None, var_parent: InnermostDeclaringBlock::None } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 3ba08c1032..a3d71c989b 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -28,7 +28,7 @@ use syntax::ast; use syntax::codemap::Span; use syntax::parse::token::special_idents; use syntax::parse::token; -use syntax::print::pprust::{lifetime_to_string}; +use syntax::print::pprust::lifetime_to_string; use syntax::visit; use syntax::visit::Visitor; use util::nodemap::NodeMap; @@ -115,6 +115,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::ItemUse(_) | ast::ItemMod(..) | ast::ItemMac(..) | + ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) | ast::ItemStatic(..) | ast::ItemConst(..) => { @@ -141,12 +142,16 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, b: &'v ast::Block, s: Span, _: ast::NodeId) { match fk { - visit::FkItemFn(_, generics, _, _) | - visit::FkMethod(_, generics, _) => { + visit::FkItemFn(_, generics, _, _) => { self.visit_early_late(subst::FnSpace, generics, |this| { visit::walk_fn(this, fk, fd, b, s) }) } + visit::FkMethod(_, sig) => { + self.visit_early_late(subst::FnSpace, &sig.generics, |this| { + visit::walk_fn(this, fk, fd, b, s) + }) + } visit::FkFnBlock(..) => { visit::walk_fn(self, fk, fd, b, s) } @@ -164,13 +169,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_ty(this, ty); }); } - ast::TyPath(ref path, id) => { + ast::TyPath(None, ref path) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. - match self.def_map.borrow().get(&id) { - Some(&def::DefTrait(..)) => { + match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) { + Some((def::DefTrait(..), 0)) => { self.with(LateScope(&Vec::new(), self.scope), |_, this| { - this.visit_path(path, id); + this.visit_path(path, ty.id); }); } _ => { @@ -184,10 +189,14 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { } } - fn visit_ty_method(&mut self, m: &ast::TypeMethod) { - self.visit_early_late( - subst::FnSpace, &m.generics, - |this| visit::walk_ty_method(this, m)) + fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + if let ast::MethodTraitItem(ref sig, None) = trait_item.node { + self.visit_early_late( + subst::FnSpace, &sig.generics, + |this| visit::walk_trait_item(this, trait_item)) + } else { + visit::walk_trait_item(self, trait_item); + } } fn visit_block(&mut self, b: &ast::Block) { @@ -269,16 +278,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { for lifetime in &trait_ref.bound_lifetimes { this.visit_lifetime_def(lifetime); } - this.visit_trait_ref(&trait_ref.trait_ref) + visit::walk_path(this, &trait_ref.trait_ref.path) }) } else { self.visit_trait_ref(&trait_ref.trait_ref) } } - - fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) { - self.visit_path(&trait_ref.path, trait_ref.ref_id); - } } impl<'a> LifetimeContext<'a> { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 0a0f555f97..7043b26136 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -22,12 +22,11 @@ use syntax::codemap::{Span, DUMMY_SP}; use syntax::{attr, visit}; use syntax::ast; use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant}; -use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem}; -use syntax::ast::{TypeMethod, Method, Generics, StructField, TypeTraitItem}; +use syntax::ast::{Item, Generics, StructField}; use syntax::ast_util::is_local; use syntax::attr::{Stability, AttrMetaMethods}; -use syntax::visit::{FnKind, FkMethod, Visitor}; -use syntax::feature_gate::emit_feature_warn; +use syntax::visit::{FnKind, Visitor}; +use syntax::feature_gate::emit_feature_err; use util::nodemap::{NodeMap, DefIdMap, FnvHashSet, FnvHashMap}; use util::ppaux::Repr; @@ -58,8 +57,10 @@ impl<'a> Annotator<'a> { attrs: &Vec, item_sp: Span, f: F, required: bool) where F: FnOnce(&mut Annotator), { + debug!("annotate(id = {:?}, attrs = {:?})", id, attrs); match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) { Some(stab) => { + debug!("annotate: found {:?}", stab); self.index.local.insert(id, stab.clone()); // Don't inherit #[stable(feature = "rust1", since = "1.0.0")] @@ -72,6 +73,8 @@ impl<'a> Annotator<'a> { } } None => { + debug!("annotate: not found, use_parent = {:?}, parent = {:?}", + use_parent, self.parent); if use_parent { if let Some(stab) = self.parent.clone() { self.index.local.insert(id, stab); @@ -120,31 +123,20 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> { } } - fn visit_fn(&mut self, fk: FnKind<'v>, _: &'v FnDecl, - _: &'v Block, sp: Span, _: NodeId) { - if let FkMethod(_, _, meth) = fk { - // Methods are not already annotated, so we annotate it - self.annotate(meth.id, true, &meth.attrs, sp, |_| {}, true); - } + fn visit_fn(&mut self, _: FnKind<'v>, _: &'v FnDecl, + _: &'v Block, _: Span, _: NodeId) { // Items defined in a function body have no reason to have // a stability attribute, so we don't recurse. } - fn visit_trait_item(&mut self, t: &TraitItem) { - let (id, attrs, sp) = match *t { - RequiredMethod(TypeMethod {id, ref attrs, span, ..}) => (id, attrs, span), - - // work around lack of pattern matching for @ types - ProvidedMethod(ref method) => { - match **method { - Method {ref attrs, id, span, ..} => (id, attrs, span), - } - } + fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + self.annotate(ti.id, true, &ti.attrs, ti.span, + |v| visit::walk_trait_item(v, ti), true); + } - TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs, - typedef.ty_param.span), - }; - self.annotate(id, true, attrs, sp, |v| visit::walk_trait_item(v, t), true); + fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + self.annotate(ii.id, true, &ii.attrs, ii.span, + |v| visit::walk_impl_item(v, ii), true); } fn visit_variant(&mut self, var: &Variant, g: &'v Generics) { @@ -181,7 +173,7 @@ impl Index { pub fn new(krate: &Crate) -> Index { let mut staged_api = false; for attr in &krate.attrs { - if &attr.name()[] == "staged_api" { + if &attr.name()[..] == "staged_api" { match attr.node.value.node { ast::MetaWord(_) => { attr::mark_used(attr); @@ -245,7 +237,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { None => format!("use of unstable library feature '{}'", &feature) }; - emit_feature_warn(&self.tcx.sess.parse_sess.span_diagnostic, + emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic, &feature, span, &msg); } } @@ -299,6 +291,12 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> { &mut |id, sp, stab| self.check(id, sp, stab)); visit::walk_path(self, path) } + + fn visit_pat(&mut self, pat: &ast::Pat) { + check_pat(self.tcx, pat, + &mut |id, sp, stab| self.check(id, sp, stab)); + visit::walk_pat(self, pat) + } } /// Helper for discovering nodes to check for stability @@ -321,26 +319,15 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool, // individually as it's possible to have a stable trait with unstable // items. ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => { - let trait_did = tcx.def_map.borrow()[t.ref_id].def_id(); + let trait_did = tcx.def_map.borrow().get(&t.ref_id).unwrap().def_id(); let trait_items = ty::trait_items(tcx, trait_did); for impl_item in impl_items { - let (ident, span) = match *impl_item { - ast::MethodImplItem(ref method) => { - (match method.node { - ast::MethDecl(ident, _, _, _, _, _, _, _) => ident, - ast::MethMac(..) => unreachable!(), - }, method.span) - } - ast::TypeImplItem(ref typedef) => { - (typedef.ident, typedef.span) - } - }; let item = trait_items.iter().find(|item| { - item.name() == ident.name + item.name() == impl_item.ident.name }).unwrap(); if warn_about_defns { - maybe_do_stability_check(tcx, item.def_id(), span, cb); + maybe_do_stability_check(tcx, item.def_id(), impl_item.span, cb); } } } @@ -352,8 +339,6 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool, /// Helper for discovering nodes to check for stability pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, cb: &mut FnMut(ast::DefId, Span, &Option)) { - if is_internal(tcx, e.span) { return; } - let span; let id = match e.node { ast::ExprMethodCall(i, _, _) => { @@ -385,6 +370,76 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, None => return } } + ast::ExprField(ref base_e, ref field) => { + span = field.span; + match ty::expr_ty_adjusted(tcx, base_e).sty { + ty::ty_struct(did, _) => { + ty::lookup_struct_fields(tcx, did) + .iter() + .find(|f| f.name == field.node.name) + .unwrap_or_else(|| { + tcx.sess.span_bug(field.span, + "stability::check_expr: unknown named field access") + }) + .id + } + _ => tcx.sess.span_bug(e.span, + "stability::check_expr: named field access on non-struct") + } + } + ast::ExprTupField(ref base_e, ref field) => { + span = field.span; + match ty::expr_ty_adjusted(tcx, base_e).sty { + ty::ty_struct(did, _) => { + ty::lookup_struct_fields(tcx, did) + .get(field.node) + .unwrap_or_else(|| { + tcx.sess.span_bug(field.span, + "stability::check_expr: unknown unnamed field access") + }) + .id + } + ty::ty_tup(..) => return, + _ => tcx.sess.span_bug(e.span, + "stability::check_expr: unnamed field access on \ + something other than a tuple or struct") + } + } + ast::ExprStruct(_, ref expr_fields, _) => { + let type_ = ty::expr_ty(tcx, e); + match type_.sty { + ty::ty_struct(did, _) => { + let struct_fields = ty::lookup_struct_fields(tcx, did); + // check the stability of each field that appears + // in the construction expression. + for field in expr_fields { + let did = struct_fields + .iter() + .find(|f| f.name == field.ident.node.name) + .unwrap_or_else(|| { + tcx.sess.span_bug(field.span, + "stability::check_expr: unknown named \ + field access") + }) + .id; + maybe_do_stability_check(tcx, did, field.span, cb); + } + + // we're done. + return + } + // we don't look at stability attributes on + // struct-like enums (yet...), but it's definitely not + // a bug to have construct one. + ty::ty_enum(..) => return, + _ => { + tcx.sess.span_bug(e.span, + &format!("stability::check_expr: struct construction \ + of non-struct, type {:?}", + type_.repr(tcx))); + } + } + } _ => return }; @@ -393,23 +448,67 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr, pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId, cb: &mut FnMut(ast::DefId, Span, &Option)) { - let did = match tcx.def_map.borrow().get(&id) { - Some(&def::DefPrimTy(..)) => return, - Some(def) => def.def_id(), - None => return + match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { + Some(def::DefPrimTy(..)) => {} + Some(def) => { + maybe_do_stability_check(tcx, def.def_id(), path.span, cb); + } + None => {} + } + +} + +pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat, + cb: &mut FnMut(ast::DefId, Span, &Option)) { + debug!("check_pat(pat = {:?})", pat); + if is_internal(tcx, pat.span) { return; } + + let did = match ty::pat_ty_opt(tcx, pat) { + Some(&ty::TyS { sty: ty::ty_struct(did, _), .. }) => did, + Some(_) | None => return, }; - maybe_do_stability_check(tcx, did, path.span, cb) + let struct_fields = ty::lookup_struct_fields(tcx, did); + match pat.node { + // Foo(a, b, c) + ast::PatEnum(_, Some(ref pat_fields)) => { + for (field, struct_field) in pat_fields.iter().zip(struct_fields.iter()) { + // a .. pattern is fine, but anything positional is + // not. + if let ast::PatWild(ast::PatWildMulti) = field.node { + continue + } + maybe_do_stability_check(tcx, struct_field.id, field.span, cb) + } + } + // Foo { a, b, c } + ast::PatStruct(_, ref pat_fields, _) => { + for field in pat_fields { + let did = struct_fields + .iter() + .find(|f| f.name == field.node.ident.name) + .unwrap_or_else(|| { + tcx.sess.span_bug(field.span, + "stability::check_pat: unknown named field access") + }) + .id; + maybe_do_stability_check(tcx, did, field.span, cb); + } + } + // everything else is fine. + _ => {} + } } fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span, cb: &mut FnMut(ast::DefId, Span, &Option)) { if !is_staged_api(tcx, id) { return } + if is_internal(tcx, span) { return } let ref stability = lookup(tcx, id); cb(id, span, stability); } fn is_internal(tcx: &ty::ctxt, span: Span) -> bool { - tcx.sess.codemap().span_is_internal(span) + tcx.sess.codemap().span_allows_unstable(span) } fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 04fd03ab34..e2ebe2bc0f 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -98,7 +98,7 @@ impl<'tcx> Substs<'tcx> { } pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> { - *self.types.get(ty_param_def.space, ty_param_def.index as uint) + *self.types.get(ty_param_def.space, ty_param_def.index as usize) } pub fn has_regions_escaping_depth(&self, depth: u32) -> bool { @@ -193,7 +193,7 @@ impl ParamSpace { [TypeSpace, SelfSpace, FnSpace] } - pub fn to_uint(self) -> uint { + pub fn to_uint(self) -> usize { match self { TypeSpace => 0, SelfSpace => 1, @@ -201,7 +201,7 @@ impl ParamSpace { } } - pub fn from_uint(u: uint) -> ParamSpace { + pub fn from_uint(u: usize) -> ParamSpace { match u { 0 => TypeSpace, 1 => SelfSpace, @@ -226,8 +226,8 @@ pub struct VecPerParamSpace { // AF(self) = (self.content[..self.type_limit], // self.content[self.type_limit..self.self_limit], // self.content[self.self_limit..]) - type_limit: uint, - self_limit: uint, + type_limit: usize, + self_limit: usize, content: Vec, } @@ -251,7 +251,7 @@ impl fmt::Debug for VecPerParamSpace { } impl VecPerParamSpace { - fn limits(&self, space: ParamSpace) -> (uint, uint) { + fn limits(&self, space: ParamSpace) -> (usize, usize) { match space { TypeSpace => (0, self.type_limit), SelfSpace => (self.type_limit, self.self_limit), @@ -290,7 +290,7 @@ impl VecPerParamSpace { } } - fn new_internal(content: Vec, type_limit: uint, self_limit: uint) + fn new_internal(content: Vec, type_limit: usize, self_limit: usize) -> VecPerParamSpace { VecPerParamSpace { @@ -343,7 +343,7 @@ impl VecPerParamSpace { } } - pub fn truncate(&mut self, space: ParamSpace, len: uint) { + pub fn truncate(&mut self, space: ParamSpace, len: usize) { // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n). while self.len(space) > len { self.pop(space); @@ -364,7 +364,7 @@ impl VecPerParamSpace { if v.len() == 0 { None } else { Some(&v[0]) } } - pub fn len(&self, space: ParamSpace) -> uint { + pub fn len(&self, space: ParamSpace) -> usize { self.get_slice(space).len() } @@ -384,13 +384,13 @@ impl VecPerParamSpace { pub fn opt_get<'a>(&'a self, space: ParamSpace, - index: uint) + index: usize) -> Option<&'a T> { let v = self.get_slice(space); if index < v.len() { Some(&v[index]) } else { None } } - pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T { + pub fn get<'a>(&'a self, space: ParamSpace, index: usize) -> &'a T { &self.get_slice(space)[index] } @@ -441,7 +441,7 @@ impl VecPerParamSpace { } pub fn map_enumerated(&self, pred: P) -> VecPerParamSpace where - P: FnMut((ParamSpace, uint, &T)) -> U, + P: FnMut((ParamSpace, usize, &T)) -> U, { let result = self.iter_enumerated().map(pred).collect(); VecPerParamSpace::new_internal(result, @@ -487,8 +487,8 @@ impl VecPerParamSpace { #[derive(Clone)] pub struct EnumeratedItems<'a,T:'a> { vec: &'a VecPerParamSpace, - space_index: uint, - elem_index: uint + space_index: usize, + elem_index: usize } impl<'a,T> EnumeratedItems<'a,T> { @@ -511,9 +511,9 @@ impl<'a,T> EnumeratedItems<'a,T> { } impl<'a,T> Iterator for EnumeratedItems<'a,T> { - type Item = (ParamSpace, uint, &'a T); + type Item = (ParamSpace, usize, &'a T); - fn next(&mut self) -> Option<(ParamSpace, uint, &'a T)> { + fn next(&mut self) -> Option<(ParamSpace, usize, &'a T)> { let spaces = ParamSpace::all(); if self.space_index < spaces.len() { let space = spaces[self.space_index]; @@ -598,7 +598,7 @@ struct SubstFolder<'a, 'tcx: 'a> { root_ty: Option>, // Depth of type stack - ty_stack_depth: uint, + ty_stack_depth: usize, // Number of region binders we have passed through while doing the substitution region_binders_passed: u32, @@ -626,7 +626,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { match self.substs.regions { ErasedRegions => ty::ReStatic, NonerasedRegions(ref regions) => - match regions.opt_get(space, i as uint) { + match regions.opt_get(space, i as usize) { Some(&r) => { self.shift_region_through_binders(r) } @@ -639,7 +639,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { (space={:?}, index={})", region_name.as_str(), self.root_ty.repr(self.tcx()), - space, i)[]); + space, i)); } } } @@ -682,7 +682,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { impl<'a,'tcx> SubstFolder<'a,'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.types.opt_get(p.space, p.idx as uint); + let opt_ty = self.substs.types.opt_get(p.space, p.idx as usize); let ty = match opt_ty { Some(t) => *t, None => { @@ -696,7 +696,7 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> { p.space, p.idx, self.root_ty.repr(self.tcx()), - self.substs.repr(self.tcx()))[]); + self.substs.repr(self.tcx()))); } }; diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index e199a60c37..2f2db8f38b 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -8,24 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See `doc.rs` for high-level documentation +//! See `README.md` for high-level documentation use super::Normalized; use super::SelectionContext; -use super::{ObligationCause}; +use super::ObligationCause; use super::PredicateObligation; use super::project; use super::util; -use middle::subst::{Subst, TypeSpace}; +use middle::subst::{Subst, Substs, TypeSpace}; use middle::ty::{self, ToPolyTraitRef, Ty}; use middle::infer::{self, InferCtxt}; -use std::collections::HashSet; use std::rc::Rc; use syntax::ast; -use syntax::codemap::DUMMY_SP; +use syntax::codemap::{DUMMY_SP, Span}; use util::ppaux::Repr; +#[derive(Copy, Clone)] +struct ParamIsLocal(bool); + /// True if there exist types that satisfy both of the two given impls. pub fn overlapping_impls(infcx: &InferCtxt, impl1_def_id: ast::DefId, @@ -52,8 +54,21 @@ fn overlap(selcx: &mut SelectionContext, b_def_id: ast::DefId) -> bool { - let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, a_def_id); - let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, b_def_id); + debug!("overlap(a_def_id={}, b_def_id={})", + a_def_id.repr(selcx.tcx()), + b_def_id.repr(selcx.tcx())); + + let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, + a_def_id, + util::free_substs_for_impl); + + let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, + b_def_id, + util::fresh_type_vars_for_impl); + + debug!("overlap: a_trait_ref={}", a_trait_ref.repr(selcx.tcx())); + + debug!("overlap: b_trait_ref={}", b_trait_ref.repr(selcx.tcx())); // Does `a <: b` hold? If not, no overlap. if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(), @@ -64,21 +79,71 @@ fn overlap(selcx: &mut SelectionContext, return false; } + debug!("overlap: subtraitref check succeeded"); + // Are any of the obligations unsatisfiable? If so, no overlap. - a_obligations.iter() - .chain(b_obligations.iter()) - .all(|o| selcx.evaluate_obligation(o)) + let tcx = selcx.tcx(); + let infcx = selcx.infcx(); + let opt_failing_obligation = + a_obligations.iter() + .chain(b_obligations.iter()) + .map(|o| infcx.resolve_type_vars_if_possible(o)) + .find(|o| !selcx.evaluate_obligation(o)); + + if let Some(failing_obligation) = opt_failing_obligation { + debug!("overlap: obligation unsatisfiable {}", failing_obligation.repr(tcx)); + return false + } + + true +} + +pub fn trait_ref_is_knowable<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> bool +{ + debug!("trait_ref_is_knowable(trait_ref={})", trait_ref.repr(tcx)); + + // if the orphan rules pass, that means that no ancestor crate can + // impl this, so it's up to us. + if orphan_check_trait_ref(tcx, trait_ref, ParamIsLocal(false)).is_ok() { + debug!("trait_ref_is_knowable: orphan check passed"); + return true; + } + + // if the trait is not marked fundamental, then it's always possible that + // an ancestor crate will impl this in the future, if they haven't + // already + if + trait_ref.def_id.krate != ast::LOCAL_CRATE && + !ty::has_attr(tcx, trait_ref.def_id, "fundamental") + { + debug!("trait_ref_is_knowable: trait is neither local nor fundamental"); + return false; + } + + // find out when some downstream (or cousin) crate could impl this + // trait-ref, presuming that all the parameters were instantiated + // with downstream types. If not, then it could only be + // implemented by an upstream crate, which means that the impl + // must be visible to us, and -- since the trait is fundamental + // -- we can test. + orphan_check_trait_ref(tcx, trait_ref, ParamIsLocal(true)).is_err() } +type SubstsFn = for<'a,'tcx> fn(infcx: &InferCtxt<'a, 'tcx>, + span: Span, + impl_def_id: ast::DefId) + -> Substs<'tcx>; + /// Instantiate fresh variables for all bound parameters of the impl /// and return the impl trait ref with those variables substituted. fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, - impl_def_id: ast::DefId) + impl_def_id: ast::DefId, + substs_fn: SubstsFn) -> (Rc>, Vec>) { let impl_substs = - &util::fresh_substs_for_impl(selcx.infcx(), DUMMY_SP, impl_def_id); + &substs_fn(selcx.infcx(), DUMMY_SP, impl_def_id); let impl_trait_ref = ty::impl_trait_ref(selcx.tcx(), impl_def_id).unwrap(); let impl_trait_ref = @@ -117,12 +182,12 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>, impl_def_id: ast::DefId) -> Result<(), OrphanCheckErr<'tcx>> { - debug!("impl_is_local({})", impl_def_id.repr(tcx)); + debug!("orphan_check({})", impl_def_id.repr(tcx)); // We only except this routine to be invoked on implementations // of a trait, not inherent implementations. let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap(); - debug!("trait_ref={}", trait_ref.repr(tcx)); + debug!("orphan_check: trait_ref={}", trait_ref.repr(tcx)); // If the *trait* is local to the crate, ok. if trait_ref.def_id.krate == ast::LOCAL_CRATE { @@ -131,34 +196,106 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>, return Ok(()); } + orphan_check_trait_ref(tcx, &trait_ref, ParamIsLocal(false)) +} + +fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_ref: &ty::TraitRef<'tcx>, + param_is_local: ParamIsLocal) + -> Result<(), OrphanCheckErr<'tcx>> +{ + debug!("orphan_check_trait_ref(trait_ref={}, param_is_local={})", + trait_ref.repr(tcx), param_is_local.0); + // First, create an ordered iterator over all the type parameters to the trait, with the self // type appearing first. let input_tys = Some(trait_ref.self_ty()); let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace).iter()); - let mut input_tys = input_tys; // Find the first input type that either references a type parameter OR // some local type. - match input_tys.find(|&&input_ty| references_local_or_type_parameter(tcx, input_ty)) { - Some(&input_ty) => { - // Within this first type, check that all type parameters are covered by a local - // type constructor. Note that if there is no local type constructor, then any - // type parameter at all will be an error. - let covered_params = type_parameters_covered_by_ty(tcx, input_ty); - let all_params = type_parameters_reachable_from_ty(input_ty); - for ¶m in all_params.difference(&covered_params) { - return Err(OrphanCheckErr::UncoveredTy(param)); + for input_ty in input_tys { + if ty_is_local(tcx, input_ty, param_is_local) { + debug!("orphan_check_trait_ref: ty_is_local `{}`", input_ty.repr(tcx)); + + // First local input type. Check that there are no + // uncovered type parameters. + let uncovered_tys = uncovered_tys(tcx, input_ty, param_is_local); + for uncovered_ty in uncovered_tys { + if let Some(param) = uncovered_ty.walk().find(|t| is_type_parameter(t)) { + debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx)); + return Err(OrphanCheckErr::UncoveredTy(param)); + } } + + // OK, found local type, all prior types upheld invariant. + return Ok(()); } - None => { - return Err(OrphanCheckErr::NoLocalInputType); + + // Otherwise, enforce invariant that there are no type + // parameters reachable. + if !param_is_local.0 { + if let Some(param) = input_ty.walk().find(|t| is_type_parameter(t)) { + debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx)); + return Err(OrphanCheckErr::UncoveredTy(param)); + } } } - return Ok(()); + // If we exit above loop, never found a local type. + debug!("orphan_check_trait_ref: no local type"); + return Err(OrphanCheckErr::NoLocalInputType); } -fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { +fn uncovered_tys<'tcx>(tcx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>, + param_is_local: ParamIsLocal) + -> Vec> +{ + if ty_is_local_constructor(tcx, ty, param_is_local) { + vec![] + } else if fundamental_ty(tcx, ty) { + ty.walk_shallow() + .flat_map(|t| uncovered_tys(tcx, t, param_is_local).into_iter()) + .collect() + } else { + vec![ty] + } +} + +fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool { + match ty.sty { + // FIXME(#20590) straighten story about projection types + ty::ty_projection(..) | ty::ty_param(..) => true, + _ => false, + } +} + +fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, param_is_local: ParamIsLocal) -> bool +{ + ty_is_local_constructor(tcx, ty, param_is_local) || + fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, param_is_local)) +} + +fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool +{ + match ty.sty { + ty::ty_uniq(..) | ty::ty_rptr(..) => + true, + ty::ty_enum(def_id, _) | ty::ty_struct(def_id, _) => + ty::has_attr(tcx, def_id, "fundamental"), + ty::ty_trait(ref data) => + ty::has_attr(tcx, data.principal_def_id(), "fundamental"), + _ => + false + } +} + +fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>, + param_is_local: ParamIsLocal) + -> bool +{ debug!("ty_is_local_constructor({})", ty.repr(tcx)); match ty.sty { @@ -173,11 +310,15 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::ty_ptr(..) | ty::ty_rptr(..) | ty::ty_tup(..) | - ty::ty_param(..) | + ty::ty_infer(..) | ty::ty_projection(..) => { false } + ty::ty_param(..) => { + param_is_local.0 + } + ty::ty_enum(def_id, _) | ty::ty_struct(def_id, _) => { def_id.krate == ast::LOCAL_CRATE @@ -193,40 +334,12 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { } ty::ty_closure(..) | - ty::ty_infer(..) | - ty::ty_open(..) | ty::ty_err => { tcx.sess.bug( &format!("ty_is_local invoked on unexpected type: {}", - ty.repr(tcx))[]) + ty.repr(tcx))) } } } -fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>, - ty: Ty<'tcx>) - -> HashSet> -{ - if ty_is_local_constructor(tcx, ty) { - type_parameters_reachable_from_ty(ty) - } else { - ty.walk_children().flat_map(|t| type_parameters_covered_by_ty(tcx, t).into_iter()).collect() - } -} - -/// All type parameters reachable from `ty` -fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet> { - ty.walk().filter(|&t| is_type_parameter(t)).collect() -} -fn references_local_or_type_parameter<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - ty.walk().any(|ty| is_type_parameter(ty) || ty_is_local_constructor(tcx, ty)) -} - -fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool { - match ty.sty { - // FIXME(#20590) straighten story about projection types - ty::ty_projection(..) | ty::ty_param(..) => true, - _ => false, - } -} diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 2197cbeb85..d10ff06041 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -12,6 +12,7 @@ use super::{ FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + Obligation, ObligationCauseCode, OutputTypeParameterMismatch, PredicateObligation, @@ -21,6 +22,7 @@ use super::{ use fmt_macros::{Parser, Piece, Position}; use middle::infer::InferCtxt; use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef}; +use middle::ty_fold::TypeFoldable; use std::collections::HashMap; use syntax::codemap::{DUMMY_SP, Span}; use syntax::attr::{AttributeMethods, AttrMetaMethods}; @@ -137,24 +139,36 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, report } +/// Reports that an overflow has occurred and halts compilation. We +/// halt compilation unconditionally because it is important that +/// overflows never be masked -- they basically represent computations +/// whose result could not be truly determined and thus we can't say +/// if the program type checks or not -- and they are unusual +/// occurrences in any case. +pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, + obligation: &Obligation<'tcx, T>) + -> ! + where T: UserString<'tcx> + TypeFoldable<'tcx> +{ + let predicate = + infcx.resolve_type_vars_if_possible(&obligation.predicate); + span_err!(infcx.tcx.sess, obligation.cause.span, E0275, + "overflow evaluating the requirement `{}`", + predicate.user_string(infcx.tcx)); + + suggest_new_overflow_limit(infcx.tcx, obligation.cause.span); + + note_obligation_cause(infcx, obligation); + + infcx.tcx.sess.abort_if_errors(); + unreachable!(); +} + pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>) { match *error { - SelectionError::Overflow => { - // We could track the stack here more precisely if we wanted, I imagine. - let predicate = - infcx.resolve_type_vars_if_possible(&obligation.predicate); - span_err!(infcx.tcx.sess, obligation.cause.span, E0275, - "overflow evaluating the requirement `{}`", - predicate.user_string(infcx.tcx)); - - suggest_new_overflow_limit(infcx.tcx, obligation.cause.span); - - note_obligation_cause(infcx, obligation); - } - SelectionError::Unimplemented => { match &obligation.cause.code { &ObligationCauseCode::CompareImplMethodObligation => { @@ -309,8 +323,9 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, } } -fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - obligation: &PredicateObligation<'tcx>) +fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, + obligation: &Obligation<'tcx, T>) + where T: UserString<'tcx> { note_obligation_cause_code(infcx, &obligation.predicate, @@ -318,10 +333,11 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, &obligation.cause.code); } -fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - predicate: &ty::Predicate<'tcx>, - cause_span: Span, - cause_code: &ObligationCauseCode<'tcx>) +fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, + predicate: &T, + cause_span: Span, + cause_code: &ObligationCauseCode<'tcx>) + where T: UserString<'tcx> { let tcx = infcx.tcx; match *cause_code { @@ -422,5 +438,5 @@ pub fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) { span, &format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", - suggested_limit)[]); + suggested_limit)); } diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index a9cac4be3e..ffd3299175 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::infer::{InferCtxt}; +use middle::infer::InferCtxt; use middle::ty::{self, RegionEscape, Ty}; use std::collections::HashSet; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::default::Default; use syntax::ast; use util::common::ErrorReported; @@ -54,7 +53,7 @@ pub struct FulfillmentContext<'tcx> { // Remembers the count of trait obligations that we have already // attempted to select. This is used to avoid repeating work // when `select_new_obligations` is called. - attempted_mark: uint, + attempted_mark: usize, // A set of constraints that regionck must validate. Each // constraint has the form `T:'a`, meaning "some type `T` must @@ -164,6 +163,8 @@ impl<'tcx> FulfillmentContext<'tcx> { // debug output much nicer to read and so on. let obligation = infcx.resolve_type_vars_if_possible(&obligation); + assert!(!obligation.has_escaping_regions()); + if !self.duplicate_set.insert(obligation.predicate.clone()) { debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx)); return; @@ -227,7 +228,7 @@ impl<'tcx> FulfillmentContext<'tcx> { } pub fn pending_obligations(&self) -> &[PredicateObligation<'tcx>] { - &self.predicates[] + &self.predicates } /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it @@ -437,9 +438,7 @@ 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.insert(vec![region_obligation]); }, - Occupied(mut entry) => { entry.get_mut().push(region_obligation); }, - } + region_obligations.entry(region_obligation.cause.body_id).or_insert(vec![]) + .push(region_obligation); } diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index a63dcfc24a..8809abdd70 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -18,14 +18,15 @@ pub use self::ObligationCauseCode::*; use middle::subst; use middle::ty::{self, HasProjectionTypes, Ty}; use middle::ty_fold::TypeFoldable; -use middle::infer::{self, InferCtxt}; +use middle::infer::{self, fixup_err_to_string, InferCtxt}; use std::slice::Iter; use std::rc::Rc; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; -use util::ppaux::{Repr, UserString}; +use util::ppaux::Repr; pub use self::error_reporting::report_fulfillment_errors; +pub use self::error_reporting::report_overflow_error; pub use self::error_reporting::suggest_new_overflow_limit; pub use self::coherence::orphan_check; pub use self::coherence::overlapping_impls; @@ -38,6 +39,7 @@ pub use self::object_safety::is_object_safe; pub use self::object_safety::object_safety_violations; pub use self::object_safety::ObjectSafetyViolation; pub use self::object_safety::MethodViolationCode; +pub use self::object_safety::is_vtable_safe_method; pub use self::select::SelectionContext; pub use self::select::SelectionCache; pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; @@ -47,6 +49,8 @@ pub use self::util::get_vtable_index_of_object_method; pub use self::util::trait_ref_for_builtin_bound; pub use self::util::supertraits; pub use self::util::Supertraits; +pub use self::util::supertrait_def_ids; +pub use self::util::SupertraitDefIds; pub use self::util::transitive_bounds; pub use self::util::upcast; @@ -67,7 +71,7 @@ mod util; #[derive(Clone, PartialEq, Eq)] pub struct Obligation<'tcx, T> { pub cause: ObligationCause<'tcx>, - pub recursion_depth: uint, + pub recursion_depth: usize, pub predicate: T, } @@ -151,7 +155,6 @@ pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; #[derive(Clone,Debug)] pub enum SelectionError<'tcx> { Unimplemented, - Overflow, OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>, ty::type_err<'tcx>), @@ -221,6 +224,12 @@ pub enum Vtable<'tcx, N> { /// Vtable identifying a particular impl. VtableImpl(VtableImplData<'tcx, N>), + /// Vtable for default trait implementations + /// This carries the information and nested obligations with regards + /// to a default implementation for a trait `Trait`. The nested obligations + /// ensure the trait implementation holds for all the constituent types. + VtableDefaultImpl(VtableDefaultImplData), + /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if @@ -259,6 +268,12 @@ pub struct VtableImplData<'tcx, N> { pub nested: subst::VecPerParamSpace } +#[derive(Debug,Clone)] +pub struct VtableDefaultImplData { + pub trait_def_id: ast::DefId, + pub nested: Vec +} + #[derive(Debug,Clone)] pub struct VtableBuiltinData { pub nested: subst::VecPerParamSpace @@ -268,7 +283,11 @@ pub struct VtableBuiltinData { /// for the object type `Foo`. #[derive(PartialEq,Eq,Clone)] pub struct VtableObjectData<'tcx> { + /// the object type `Foo`. pub object_ty: Ty<'tcx>, + + /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. + pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, } /// Creates predicate obligations from the generic bounds. @@ -311,16 +330,9 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, let result = match fulfill_cx.select_all_or_error(infcx, typer) { Ok(()) => Ok(Some(())), // Success, we know it implements Copy. Err(errors) => { - // Check if overflow occurred anywhere and propagate that. - if errors.iter().any( - |err| match err.code { CodeSelectionError(Overflow) => true, _ => false }) - { - return Err(Overflow); - } - - // Otherwise, if there were any hard errors, propagate an - // arbitrary one of those. If no hard errors at all, - // report ambiguity. + // If there were any hard errors, propagate an arbitrary + // one of those. If no hard errors at all, report + // ambiguity. let sel_error = errors.iter() .filter_map(|err| { @@ -368,68 +380,71 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, // soldering on, so just treat this like not implemented false } - Err(Overflow) => { - span_err!(infcx.tcx.sess, span, E0285, - "overflow evaluating whether `{}` is `{}`", - ty.user_string(infcx.tcx), - bound.user_string(infcx.tcx)); - suggest_new_overflow_limit(infcx.tcx, span); - false - } Err(_) => { - // other errors: not implemented. + // errors: not implemented. false } } } +/// Normalizes the parameter environment, reporting errors if they occur. pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>, cause: ObligationCause<'tcx>) -> ty::ParameterEnvironment<'a,'tcx> { - match normalize_param_env(&unnormalized_env, cause) { - Ok(p) => p, + // I'm not wild about reporting errors here; I'd prefer to + // have the errors get reported at a defined place (e.g., + // during typeck). Instead I have all parameter + // environments, in effect, going through this function + // and hence potentially reporting errors. This ensurse of + // course that we never forget to normalize (the + // alternative seemed like it would involve a lot of + // manual invocations of this fn -- and then we'd have to + // deal with the errors at each of those sites). + // + // In any case, in practice, typeck constructs all the + // parameter environments once for every fn as it goes, + // and errors will get reported then; so after typeck we + // can be sure that no errors should occur. + + let tcx = unnormalized_env.tcx; + let span = cause.span; + let body_id = cause.body_id; + + debug!("normalize_param_env_or_error(unnormalized_env={})", + unnormalized_env.repr(tcx)); + + let infcx = infer::new_infer_ctxt(tcx); + let predicates = match fully_normalize(&infcx, &unnormalized_env, cause, + &unnormalized_env.caller_bounds) { + Ok(predicates) => predicates, Err(errors) => { - // I'm not wild about reporting errors here; I'd prefer to - // have the errors get reported at a defined place (e.g., - // during typeck). Instead I have all parameter - // environments, in effect, going through this function - // and hence potentially reporting errors. This ensurse of - // course that we never forget to normalize (the - // alternative seemed like it would involve a lot of - // manual invocations of this fn -- and then we'd have to - // deal with the errors at each of those sites). - // - // In any case, in practice, typeck constructs all the - // parameter environments once for every fn as it goes, - // and errors will get reported then; so after typeck we - // can be sure that no errors should occur. - let infcx = infer::new_infer_ctxt(unnormalized_env.tcx); report_fulfillment_errors(&infcx, &errors); - - // Normalized failed? use what they gave us, it's better than nothing. - unnormalized_env + return unnormalized_env; // an unnormalized env is better than nothing } - } -} - -pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>, - cause: ObligationCause<'tcx>) - -> Result, - Vec>> -{ - let tcx = param_env.tcx; - - debug!("normalize_param_env(param_env={})", - param_env.repr(tcx)); + }; - let infcx = infer::new_infer_ctxt(tcx); - let predicates = try!(fully_normalize(&infcx, param_env, cause, ¶m_env.caller_bounds)); + infcx.resolve_regions_and_report_errors(body_id); + let predicates = match infcx.fully_resolve(&predicates) { + Ok(predicates) => predicates, + Err(fixup_err) => { + // If we encounter a fixup error, it means that some type + // variable wound up unconstrained. I actually don't know + // if this can happen, and I certainly don't expect it to + // happen often, but if it did happen it probably + // represents a legitimate failure due to some kind of + // unconstrained variable, and it seems better not to ICE, + // all things considered. + let err_msg = fixup_err_to_string(fixup_err); + tcx.sess.span_err(span, &err_msg); + return unnormalized_env; // an unnormalized env is better than nothing + } + }; - debug!("normalize_param_env: predicates={}", + debug!("normalize_param_env_or_error: predicates={}", predicates.repr(tcx)); - Ok(param_env.with_caller_bounds(predicates)) + unnormalized_env.with_caller_bounds(predicates) } pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, @@ -441,8 +456,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, { let tcx = closure_typer.tcx(); - debug!("normalize_param_env(value={})", - value.repr(tcx)); + debug!("normalize_param_env(value={})", value.repr(tcx)); let mut selcx = &mut SelectionContext::new(infcx, closure_typer); let mut fulfill_cx = FulfillmentContext::new(); @@ -456,8 +470,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, } try!(fulfill_cx.select_all_or_error(infcx, closure_typer)); let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value); - debug!("normalize_param_env: resolved_value={}", - resolved_value.repr(tcx)); + debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx)); Ok(resolved_value) } @@ -472,7 +485,7 @@ impl<'tcx,O> Obligation<'tcx,O> { } fn with_depth(cause: ObligationCause<'tcx>, - recursion_depth: uint, + recursion_depth: usize, trait_ref: O) -> Obligation<'tcx, O> { @@ -513,17 +526,18 @@ impl<'tcx, N> Vtable<'tcx, N> { pub fn iter_nested(&self) -> Iter { match *self { VtableImpl(ref i) => i.iter_nested(), - VtableFnPointer(..) => (&[]).iter(), - VtableClosure(..) => (&[]).iter(), VtableParam(ref n) => n.iter(), - VtableObject(_) => (&[]).iter(), VtableBuiltin(ref i) => i.iter_nested(), + VtableObject(_) | + VtableDefaultImpl(..) | VtableFnPointer(..) | + VtableClosure(..) => (&[]).iter(), } } pub fn map_nested(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M { match *self { VtableImpl(ref i) => VtableImpl(i.map_nested(op)), + VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)), VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()), VtableClosure(d, ref s) => VtableClosure(d, s.clone()), VtableParam(ref n) => VtableParam(n.iter().map(op).collect()), @@ -539,6 +553,7 @@ impl<'tcx, N> Vtable<'tcx, N> { VtableImpl(i) => VtableImpl(i.map_move_nested(op)), VtableFnPointer(sig) => VtableFnPointer(sig), VtableClosure(d, s) => VtableClosure(d, s), + VtableDefaultImpl(t) => VtableDefaultImpl(t.map_move_nested(op)), VtableParam(n) => VtableParam(n.into_iter().map(op).collect()), VtableObject(p) => VtableObject(p), VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)), @@ -573,6 +588,31 @@ impl<'tcx, N> VtableImplData<'tcx, N> { } } +impl VtableDefaultImplData { + pub fn iter_nested(&self) -> Iter { + self.nested.iter() + } + + pub fn map_nested(&self, op: F) -> VtableDefaultImplData where + F: FnMut(&N) -> M, + { + VtableDefaultImplData { + trait_def_id: self.trait_def_id, + nested: self.nested.iter().map(op).collect() + } + } + + pub fn map_move_nested(self, op: F) -> VtableDefaultImplData where + F: FnMut(N) -> M, + { + let VtableDefaultImplData { trait_def_id, nested } = self; + VtableDefaultImplData { + trait_def_id: trait_def_id, + nested: nested.into_iter().map(op).collect() + } + } +} + impl VtableBuiltinData { pub fn iter_nested(&self) -> Iter { self.nested.iter() @@ -600,19 +640,10 @@ impl<'tcx> FulfillmentError<'tcx> { { FulfillmentError { obligation: obligation, code: code } } - - pub fn is_overflow(&self) -> bool { - match self.code { - CodeAmbiguity => false, - CodeSelectionError(Overflow) => true, - CodeSelectionError(_) => false, - CodeProjectionError(_) => false, - } - } } impl<'tcx> TraitObligation<'tcx> { - fn self_ty(&self) -> Ty<'tcx> { - self.predicate.0.self_ty() + fn self_ty(&self) -> ty::Binder> { + ty::Binder(self.predicate.skip_binder().self_ty()) } } diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index f10f7eb395..af6bb4cccc 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -22,7 +22,7 @@ use super::elaborate_predicates; use middle::subst::{self, SelfSpace, TypeSpace}; use middle::traits; -use middle::ty::{self, Ty}; +use middle::ty::{self, ToPolyTraitRef, Ty}; use std::rc::Rc; use syntax::ast; use util::ppaux::Repr; @@ -42,9 +42,6 @@ pub enum ObjectSafetyViolation<'tcx> { /// Reasons a method might not be object-safe. #[derive(Copy,Clone,Debug)] pub enum MethodViolationCode { - /// e.g., `fn(self)` - ByValueSelf, - /// e.g., `fn foo()` StaticMethod, @@ -56,36 +53,36 @@ pub enum MethodViolationCode { } pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>) + trait_def_id: ast::DefId) -> bool { // Because we query yes/no results frequently, we keep a cache: let cached_result = - tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).cloned(); + tcx.object_safety_cache.borrow().get(&trait_def_id).cloned(); let result = cached_result.unwrap_or_else(|| { - let result = object_safety_violations(tcx, trait_ref.clone()).is_empty(); + let result = object_safety_violations(tcx, trait_def_id).is_empty(); // Record just a yes/no result in the cache; this is what is // queried most frequently. Note that this may overwrite a // previous result, but always with the same thing. - tcx.object_safety_cache.borrow_mut().insert(trait_ref.def_id(), result); + tcx.object_safety_cache.borrow_mut().insert(trait_def_id, result); result }); - debug!("is_object_safe({}) = {}", trait_ref.repr(tcx), result); + debug!("is_object_safe({}) = {}", trait_def_id.repr(tcx), result); result } pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>, - sub_trait_ref: ty::PolyTraitRef<'tcx>) + trait_def_id: ast::DefId) -> Vec> { - supertraits(tcx, sub_trait_ref) - .flat_map(|tr| object_safety_violations_for_trait(tcx, tr.def_id()).into_iter()) + traits::supertrait_def_ids(tcx, trait_def_id) + .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id).into_iter()) .collect() } @@ -99,7 +96,7 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>, .flat_map(|item| { match *item { ty::MethodTraitItem(ref m) => { - object_safety_violations_for_method(tcx, trait_def_id, &**m) + object_safety_violation_for_method(tcx, trait_def_id, &**m) .map(|code| ObjectSafetyViolation::Method(m.clone(), code)) .into_iter() } @@ -131,9 +128,12 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>, { let trait_def = ty::lookup_trait_def(tcx, trait_def_id); let trait_ref = trait_def.trait_ref.clone(); - let predicates = ty::predicates_for_trait_ref(tcx, &ty::Binder(trait_ref)); + let trait_ref = trait_ref.to_poly_trait_ref(); + let predicates = ty::lookup_super_predicates(tcx, trait_def_id); predicates + .predicates .into_iter() + .map(|predicate| predicate.subst_supertrait(tcx, &trait_ref)) .any(|predicate| { match predicate { ty::Predicate::Trait(ref data) => { @@ -157,6 +157,16 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>, fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId) -> bool +{ + let trait_def = ty::lookup_trait_def(tcx, trait_def_id); + let trait_predicates = ty::lookup_predicates(tcx, trait_def_id); + generics_require_sized_self(tcx, &trait_def.generics, &trait_predicates) +} + +fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, + generics: &ty::Generics<'tcx>, + predicates: &ty::GenericPredicates<'tcx>) + -> bool { let sized_def_id = match tcx.lang_items.sized_trait() { Some(def_id) => def_id, @@ -164,12 +174,8 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, }; // Search for a predicate like `Self : Sized` amongst the trait bounds. - let trait_def = ty::lookup_trait_def(tcx, trait_def_id); - let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID); - - let trait_predicates = ty::lookup_predicates(tcx, trait_def_id); - let predicates = trait_predicates.instantiate(tcx, &free_substs).predicates.into_vec(); - + let free_substs = ty::construct_free_substs(tcx, generics, ast::DUMMY_NODE_ID); + let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec(); elaborate_predicates(tcx, predicates) .any(|predicate| { match predicate { @@ -187,22 +193,51 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, }) } -fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>, - trait_def_id: ast::DefId, - method: &ty::Method<'tcx>) - -> Option +/// Returns `Some(_)` if this method makes the containing trait not object safe. +fn object_safety_violation_for_method<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + method: &ty::Method<'tcx>) + -> Option { - // The method's first parameter must be something that derefs to - // `&self`. For now, we only accept `&self` and `Box`. - match method.explicit_self { - ty::ByValueExplicitSelfCategory => { - return Some(MethodViolationCode::ByValueSelf); - } + // Any method that has a `Self : Sized` requisite is otherwise + // exempt from the regulations. + if generics_require_sized_self(tcx, &method.generics, &method.predicates) { + return None; + } + + virtual_call_violation_for_method(tcx, trait_def_id, method) +} +/// We say a method is *vtable safe* if it can be invoked on a trait +/// object. Note that object-safe traits can have some +/// non-vtable-safe methods, so long as they require `Self:Sized` or +/// otherwise ensure that they cannot be used when `Self=Trait`. +pub fn is_vtable_safe_method<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + method: &ty::Method<'tcx>) + -> bool +{ + virtual_call_violation_for_method(tcx, trait_def_id, method).is_none() +} + +/// Returns `Some(_)` if this method cannot be called on a trait +/// object; this does not necessarily imply that the enclosing trait +/// is not object safe, because the method might have a where clause +/// `Self:Sized`. +fn virtual_call_violation_for_method<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + method: &ty::Method<'tcx>) + -> Option +{ + // The method's first parameter must be something that derefs (or + // autorefs) to `&self`. For now, we only accept `self`, `&self` + // and `Box`. + match method.explicit_self { ty::StaticExplicitSelfCategory => { return Some(MethodViolationCode::StaticMethod); } + ty::ByValueExplicitSelfCategory | ty::ByReferenceExplicitSelfCategory(..) | ty::ByBoxExplicitSelfCategory => { } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 13f309e129..7488b8f046 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -11,9 +11,9 @@ //! Code for projecting associated types out of trait references. use super::elaborate_predicates; +use super::report_overflow_error; use super::Obligation; use super::ObligationCause; -use super::Overflow; use super::PredicateObligation; use super::SelectionContext; use super::SelectionError; @@ -81,7 +81,7 @@ pub fn poly_project_and_unify_type<'cx,'tcx>( obligation.repr(selcx.tcx())); let infcx = selcx.infcx(); - infcx.try(|snapshot| { + infcx.commit_if_ok(|snapshot| { let (skol_predicate, skol_map) = infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); @@ -154,7 +154,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}", self_ty.sty); match self_ty.sty { - ty::ty_closure(closure_def_id, _, substs) => { + ty::ty_closure(closure_def_id, substs) => { let closure_typer = selcx.closure_typer(); let closure_type = closure_typer.closure_type(closure_def_id, substs); let ty::Binder((_, ret_type)) = @@ -197,7 +197,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, /// As `normalize`, but with a custom depth. pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>, cause: ObligationCause<'tcx>, - depth: uint, + depth: usize, value: &T) -> Normalized<'tcx, T> where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx> @@ -214,13 +214,13 @@ struct AssociatedTypeNormalizer<'a,'b:'a,'tcx:'b> { selcx: &'a mut SelectionContext<'b,'tcx>, cause: ObligationCause<'tcx>, obligations: Vec>, - depth: uint, + depth: usize, } impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> { fn new(selcx: &'a mut SelectionContext<'b,'tcx>, cause: ObligationCause<'tcx>, - depth: uint) + depth: usize) -> AssociatedTypeNormalizer<'a,'b,'tcx> { AssociatedTypeNormalizer { @@ -291,6 +291,7 @@ impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> { } } +#[derive(Clone)] pub struct Normalized<'tcx,T> { pub value: T, pub obligations: Vec>, @@ -314,7 +315,7 @@ pub fn normalize_projection_type<'a,'b,'tcx>( selcx: &'a mut SelectionContext<'b,'tcx>, projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>, - depth: uint) + depth: usize) -> NormalizedTy<'tcx> { opt_normalize_projection_type(selcx, projection_ty.clone(), cause.clone(), depth) @@ -344,7 +345,7 @@ fn opt_normalize_projection_type<'a,'b,'tcx>( selcx: &'a mut SelectionContext<'b,'tcx>, projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>, - depth: uint) + depth: usize) -> Option> { debug!("normalize_projection_type(\ @@ -412,7 +413,7 @@ fn opt_normalize_projection_type<'a,'b,'tcx>( fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>, - depth: uint) + depth: usize) -> NormalizedTy<'tcx> { let trait_ref = projection_ty.trait_ref.to_poly_trait_ref(); @@ -442,7 +443,7 @@ fn project_type<'cx,'tcx>( let recursion_limit = selcx.tcx().sess.recursion_limit.get(); if obligation.recursion_depth >= recursion_limit { debug!("project: overflow!"); - return Err(ProjectionTyError::TraitSelectionError(Overflow)); + report_overflow_error(selcx.infcx(), &obligation); } let obligation_trait_ref = @@ -535,7 +536,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>( /// In the case of a nested projection like <::FooT as Bar>::BarT, we may find /// that the definition of `Foo` has some clues: /// -/// ```rust +/// ``` /// trait Foo { /// type FooT : Bar /// } @@ -699,16 +700,17 @@ fn assemble_candidates_from_impls<'cx,'tcx>( // But wait, you say! What about an example like this: // // ``` - // fn bar>(...) { ... } + // fn bar>(...) { ... } // ``` // - // Doesn't the `T : Sometrait` predicate help + // Doesn't the `T : Sometrait` predicate help // resolve `T::Foo`? And of course it does, but in fact // that single predicate is desugared into two predicates // in the compiler: a trait predicate (`T : SomeTrait`) and a // projection. And the projection where clause is handled // in `assemble_candidates_from_param_env`. } + super::VtableDefaultImpl(..) | super::VtableBuiltin(..) => { // These traits have no associated types. selcx.tcx().sess.span_bug( @@ -788,10 +790,13 @@ fn confirm_callable_candidate<'cx,'tcx>( obligation.repr(tcx), fn_sig.repr(tcx)); + // the `Output` associated type is declared on `FnOnce` + let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap(); + // Note: we unwrap the binder here but re-create it below (1) let ty::Binder((trait_ref, ret_type)) = util::closure_trait_ref_and_return_type(tcx, - obligation.predicate.trait_ref.def_id, + fn_once_def_id, obligation.predicate.trait_ref.self_ty(), fn_sig, flag); @@ -853,10 +858,10 @@ fn confirm_impl_candidate<'cx,'tcx>( let impl_items_map = selcx.tcx().impl_items.borrow(); let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow(); - let impl_items = &impl_items_map[impl_vtable.impl_def_id]; + let impl_items = impl_items_map.get(&impl_vtable.impl_def_id).unwrap(); let mut impl_ty = None; for impl_item in impl_items { - let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] { + let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() { ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(), ty::MethodTraitItem(..) => { continue; } }; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 0e29892084..f7e7d071f8 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! See `doc.rs` for high-level documentation +//! See `README.md` for high-level documentation #![allow(dead_code)] // FIXME -- just temporarily pub use self::MethodMatchResult::*; @@ -17,19 +17,21 @@ use self::SelectionCandidate::*; use self::BuiltinBoundConditions::*; use self::EvaluationResult::*; -use super::{DerivedObligationCause}; -use super::{project}; -use super::project::Normalized; +use super::coherence; +use super::DerivedObligationCause; +use super::project; +use super::project::{normalize_with_depth, Normalized}; use super::{PredicateObligation, TraitObligation, ObligationCause}; -use super::{ObligationCauseCode, BuiltinDerivedObligation}; -use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch}; -use super::{Selection}; -use super::{SelectionResult}; +use super::report_overflow_error; +use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation}; +use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch}; +use super::Selection; +use super::SelectionResult; use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, - VtableFnPointer, VtableObject}; -use super::{VtableImplData, VtableObjectData, VtableBuiltinData}; + VtableFnPointer, VtableObject, VtableDefaultImpl}; +use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData}; use super::object_safety; -use super::{util}; +use super::util; use middle::fast_reject; use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace}; @@ -37,11 +39,13 @@ use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; use middle::infer; use middle::infer::{InferCtxt, TypeFreshener}; use middle::ty_fold::TypeFoldable; +use middle::ty_match; +use middle::ty_relate::TypeRelation; use std::cell::RefCell; -use std::collections::hash_map::HashMap; use std::rc::Rc; use syntax::{abi, ast}; use util::common::ErrorReported; +use util::nodemap::FnvHashMap; use util::ppaux::Repr; pub struct SelectionContext<'cx, 'tcx:'cx> { @@ -80,13 +84,13 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { /// selection-context's freshener. Used to check for recursion. fresh_trait_ref: ty::PolyTraitRef<'tcx>, - previous: Option<&'prev TraitObligationStack<'prev, 'tcx>> + previous: TraitObligationStackList<'prev, 'tcx>, } #[derive(Clone)] pub struct SelectionCache<'tcx> { - hashmap: RefCell>, - SelectionResult<'tcx, SelectionCandidate<'tcx>>>>, + hashmap: RefCell>, + SelectionResult<'tcx, SelectionCandidate<'tcx>>>>, } pub enum MethodMatchResult { @@ -95,7 +99,7 @@ pub enum MethodMatchResult { MethodDidNotMatch, } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum MethodMatchedData { // In the case of a precise match, we don't really need to store // how the match was found. So don't. @@ -109,7 +113,7 @@ pub enum MethodMatchedData { /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes /// we'll be able to say definitively that (e.g.) an impl does not -/// apply to the obligation: perhaps it is defined for `uint` but the +/// apply to the obligation: perhaps it is defined for `usize` but the /// obligation is for `int`. In that case, we drop the impl out of the /// list. But the other cases are considered *candidates*. /// @@ -136,6 +140,8 @@ enum SelectionCandidate<'tcx> { BuiltinCandidate(ty::BuiltinBound), ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(ast::DefId), + DefaultImplCandidate(ast::DefId), + DefaultImplObjectCandidate(ast::DefId), /// This is a trait matching with a projected type as `Self`, and /// we found an applicable bound in the trait definition. @@ -151,6 +157,8 @@ enum SelectionCandidate<'tcx> { ObjectCandidate, + BuiltinObjectCandidate, + ErrorCandidate, } @@ -167,7 +175,7 @@ struct SelectionCandidateSet<'tcx> { } enum BuiltinBoundConditions<'tcx> { - If(Vec>), + If(ty::Binder>>), ParameterBuiltin, AmbiguousBuiltin } @@ -240,7 +248,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("select({})", obligation.repr(self.tcx())); assert!(!obligation.predicate.has_escaping_regions()); - let stack = self.push_stack(None, obligation); + let stack = self.push_stack(TraitObligationStackList::empty(), obligation); match try!(self.candidate_from_obligation(&stack)) { None => { self.consider_unification_despite_ambiguity(obligation); @@ -288,9 +296,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // because if it is a closure type, it must be a closure type from // within this current fn, and hence none of the higher-ranked // lifetimes can appear inside the self-type. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.sty { - ty::ty_closure(id, _, ref substs) => (id, substs.clone()), + ty::ty_closure(id, ref substs) => (id, substs.clone()), _ => { return; } }; assert!(!substs.has_escaping_regions()); @@ -322,7 +330,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("evaluate_obligation({})", obligation.repr(self.tcx())); - self.evaluate_predicate_recursively(None, obligation).may_apply() + self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + .may_apply() } fn evaluate_builtin_bound_recursively<'o>(&mut self, @@ -341,7 +350,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match obligation { Ok(obligation) => { - self.evaluate_predicate_recursively(Some(previous_stack), &obligation) + self.evaluate_predicate_recursively(previous_stack.list(), &obligation) } Err(ErrorReported) => { EvaluatedToOk @@ -350,7 +359,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn evaluate_predicates_recursively<'a,'o,I>(&mut self, - stack: Option<&TraitObligationStack<'o, 'tcx>>, + stack: TraitObligationStackList<'o, 'tcx>, predicates: I) -> EvaluationResult<'tcx> where I : Iterator>, 'tcx:'a @@ -367,7 +376,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn evaluate_predicate_recursively<'o>(&mut self, - previous_stack: Option<&TraitObligationStack<'o, 'tcx>>, + previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &PredicateObligation<'tcx>) -> EvaluationResult<'tcx> { @@ -418,14 +427,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn evaluate_obligation_recursively<'o>(&mut self, - previous_stack: Option<&TraitObligationStack<'o, 'tcx>>, + previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &TraitObligation<'tcx>) -> EvaluationResult<'tcx> { debug!("evaluate_obligation_recursively({})", obligation.repr(self.tcx())); - let stack = self.push_stack(previous_stack.map(|x| x), obligation); + let stack = self.push_stack(previous_stack, obligation); let result = self.evaluate_stack(&stack); @@ -467,7 +476,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { unbound_input_types && (self.intercrate || stack.iter().skip(1).any( - |prev| stack.fresh_trait_ref.def_id() == prev.fresh_trait_ref.def_id())) + |prev| self.match_fresh_trait_refs(&stack.fresh_trait_ref, + &prev.fresh_trait_ref))) { debug!("evaluate_stack({}) --> unbound argument, recursion --> ambiguous", stack.fresh_trait_ref.repr(self.tcx())); @@ -533,7 +543,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.recursion_depth + 1, skol_map, snapshot); - self.winnow_selection(None, VtableImpl(vtable_impl)).may_apply() + self.winnow_selection(TraitObligationStackList::empty(), + VtableImpl(vtable_impl)).may_apply() } Err(()) => { false @@ -547,7 +558,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // The selection process begins by examining all in-scope impls, // caller obligations, and so forth and assembling a list of - // candidates. See `doc.rs` and the `Candidate` type for more details. + // candidates. See `README.md` and the `Candidate` type for more + // details. fn candidate_from_obligation<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) @@ -557,10 +569,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // not update) the cache. let recursion_limit = self.infcx.tcx.sess.recursion_limit.get(); if stack.obligation.recursion_depth >= recursion_limit { - debug!("{} --> overflow (limit={})", - stack.obligation.repr(self.tcx()), - recursion_limit); - return Err(Overflow) + report_overflow_error(self.infcx(), &stack.obligation); } // Check the cache. Note that we skolemize the trait-ref @@ -604,6 +613,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Ok(Some(ErrorCandidate)); } + if !self.is_knowable(stack) { + debug!("intercrate not knowable"); + return Ok(None); + } + let candidate_set = try!(self.assemble_candidates(stack)); if candidate_set.ambiguous { @@ -625,7 +639,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // for example, we are looking for $0:Eq where $0 is some // unconstrained type variable. In that case, we'll get a // candidate which assumes $0 == int, one that assumes $0 == - // uint, etc. This spells an ambiguity. + // usize, etc. This spells an ambiguity. // If there is more than one candidate, first winnow them down // by considering extra conditions (nested obligations and so @@ -704,6 +718,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(candidate)) } + fn is_knowable<'o>(&mut self, + stack: &TraitObligationStack<'o, 'tcx>) + -> bool + { + debug!("is_knowable(intercrate={})", self.intercrate); + + if !self.intercrate { + return true; + } + + let obligation = &stack.obligation; + let predicate = self.infcx().resolve_type_vars_if_possible(&obligation.predicate); + + // ok to skip binder because of the nature of the + // trait-ref-is-knowable check, which does not care about + // bound regions + let trait_ref = &predicate.skip_binder().trait_ref; + + coherence::trait_ref_is_knowable(self.tcx(), trait_ref) + } + fn pick_candidate_cache(&self) -> &SelectionCache<'tcx> { // If there are any where-clauses in scope, then we always use // a cache local to this particular scope. Otherwise, we @@ -817,31 +852,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("obligation self ty is {}", obligation.predicate.0.self_ty().repr(self.tcx())); + // User-defined copy impls are permitted, but only for + // structs and enums. try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); + // For other types, we'll use the builtin rules. try!(self.assemble_builtin_bound_candidates(ty::BoundCopy, stack, &mut candidates)); } - Some(bound @ ty::BoundSend) | - Some(bound @ ty::BoundSync) => { - try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); - - // No explicit impls were declared for this type, consider the fallback rules. - if candidates.vec.is_empty() && !candidates.ambiguous { - try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); - } - } - Some(bound @ ty::BoundSized) => { - // Sized and Copy are always automatically computed. + // Sized is never implementable by end-users, it is + // always automatically computed. try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates)); } + Some(ty::BoundSend) | + Some(ty::BoundSync) | None => { - // For the time being, we ignore user-defined impls for builtin-bounds, other than - // `Copy`. - // (And unboxed candidates only apply to the Fn/FnMut/etc traits.) try!(self.assemble_closure_candidates(obligation, &mut candidates)); try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates)); try!(self.assemble_candidates_from_impls(obligation, &mut candidates)); @@ -851,6 +879,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_candidates_from_projected_tys(obligation, &mut candidates); try!(self.assemble_candidates_from_caller_bounds(stack, &mut candidates)); + // Default implementations have lower priority, so we only + // consider triggering a default if there is no other impl that can apply. + if candidates.vec.len() == 0 { + try!(self.assemble_candidates_from_default_impls(obligation, &mut candidates)); + } debug!("candidate list size: {}", candidates.vec.len()); Ok(candidates) } @@ -1025,7 +1058,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx().probe(move |_| { match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { - self.evaluate_predicates_recursively(Some(stack), obligations.iter()) + self.evaluate_predicates_recursively(stack.list(), obligations.iter()) } Err(()) => { EvaluatedToErr(Unimplemented) @@ -1050,9 +1083,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => { return Ok(()); } }; - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + // ok to skip binder because the substs on closure types never + // touch bound regions, they just capture the in-scope + // type/region parameters + let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.sty { - ty::ty_closure(id, _, ref substs) => (id, substs.clone()), + ty::ty_closure(id, ref substs) => (id, substs.clone()), ty::ty_infer(ty::TyVar(_)) => { debug!("assemble_unboxed_closure_candidates: ambiguous self-type"); candidates.ambiguous = true; @@ -1069,7 +1105,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.closure_typer.closure_kind(closure_def_id) { Some(closure_kind) => { debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); - if closure_kind == kind { + if closure_kind.extends(kind) { candidates.vec.push(ClosureCandidate(closure_def_id, substs.clone())); } } @@ -1088,14 +1124,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(),SelectionError<'tcx>> { - // We provide a `Fn` impl for fn pointers. There is no need to provide - // the other traits (e.g. `FnMut`) since those are provided by blanket - // impls. - if Some(obligation.predicate.def_id()) != self.tcx().lang_items.fn_trait() { + // We provide impl of all fn traits for fn pointers. + if self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()).is_none() { return Ok(()); } - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + // ok to skip binder because what we are inspecting doesn't involve bound regions + let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); match self_ty.sty { ty::ty_infer(ty::TyVar(_)) => { debug!("assemble_fn_pointer_candidates: ambiguous self-type"); @@ -1127,10 +1162,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>) -> Result<(), SelectionError<'tcx>> { - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); - debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx())); + debug!("assemble_candidates_from_impls(obligation={})", obligation.repr(self.tcx())); - let all_impls = self.all_impls(obligation.predicate.def_id()); + let def_id = obligation.predicate.def_id(); + let all_impls = self.all_impls(def_id); for &impl_def_id in &all_impls { self.infcx.probe(|snapshot| { let (skol_obligation_trait_pred, skol_map) = @@ -1144,6 +1179,78 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }); } + + Ok(()) + } + + fn assemble_candidates_from_default_impls(&mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>) + -> Result<(), SelectionError<'tcx>> + { + // OK to skip binder here because the tests we do below do not involve bound regions + let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + debug!("assemble_candidates_from_default_impls(self_ty={})", self_ty.repr(self.tcx())); + + let def_id = obligation.predicate.def_id(); + + if ty::trait_has_default_impl(self.tcx(), def_id) { + match self_ty.sty { + ty::ty_trait(..) => { + // For object types, we don't know what the closed + // over types are. For most traits, this means we + // conservatively say nothing; a candidate may be + // added by `assemble_candidates_from_object_ty`. + // However, for the kind of magic reflect trait, + // we consider it to be implemented even for + // object types, because it just lets you reflect + // onto the object type, not into the object's + // interior. + if ty::has_attr(self.tcx(), def_id, "rustc_reflect_like") { + candidates.vec.push(DefaultImplObjectCandidate(def_id)); + } + } + ty::ty_param(..) | + ty::ty_projection(..) => { + // In these cases, we don't know what the actual + // type is. Therefore, we cannot break it down + // into its constituent types. So we don't + // consider the `..` impl but instead just add no + // candidates: this means that typeck will only + // succeed if there is another reason to believe + // that this obligation holds. That could be a + // where-clause or, in the case of an object type, + // it could be that the object type lists the + // trait (e.g. `Foo+Send : Send`). See + // `compile-fail/typeck-default-trait-impl-send-param.rs` + // for an example of a test case that exercises + // this path. + } + ty::ty_infer(ty::TyVar(_)) => { + // the defaulted impl might apply, we don't know + candidates.ambiguous = true; + } + _ => { + if self.constituent_types_for_ty(self_ty).is_some() { + candidates.vec.push(DefaultImplCandidate(def_id.clone())) + } else { + // We don't yet know what the constituent + // types are. So call it ambiguous for now, + // though this is a bit stronger than + // necessary: that is, we know that the + // defaulted impl applies, but we can't + // process the confirmation step without + // knowing the constituent types. (Anyway, in + // the particular case of defaulted impls, it + // doesn't really matter much either way, + // since we won't be aiding inference by + // processing the confirmation step.) + candidates.ambiguous = true; + } + } + } + } + Ok(()) } @@ -1152,10 +1259,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>) { - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); - debug!("assemble_candidates_from_object_ty(self_ty={})", - self_ty.repr(self.tcx())); + self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()).repr(self.tcx())); // Object-safety candidates are only applicable to object-safe // traits. Including this check is useful because it helps @@ -1164,43 +1269,56 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // self-type from one of the other inputs. Without this check, // these cases wind up being considered ambiguous due to a // (spurious) ambiguity introduced here. - if !object_safety::is_object_safe(self.tcx(), obligation.predicate.to_poly_trait_ref()) { + let predicate_trait_ref = obligation.predicate.to_poly_trait_ref(); + if !object_safety::is_object_safe(self.tcx(), predicate_trait_ref.def_id()) { return; } - let poly_trait_ref = match self_ty.sty { - ty::ty_trait(ref data) => { - data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) - } - ty::ty_infer(ty::TyVar(_)) => { - debug!("assemble_candidates_from_object_ty: ambiguous"); - candidates.ambiguous = true; // could wind up being an object type - return; - } - _ => { - return; - } - }; + self.infcx.commit_if_ok(|snapshot| { + let bound_self_ty = + self.infcx.resolve_type_vars_if_possible(&obligation.self_ty()); + let (self_ty, _) = + self.infcx().skolemize_late_bound_regions(&bound_self_ty, snapshot); + let poly_trait_ref = match self_ty.sty { + ty::ty_trait(ref data) => { + match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { + Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { + if data.bounds.builtin_bounds.contains(&bound) { + debug!("assemble_candidates_from_object_ty: matched builtin bound, \ + pushing candidate"); + candidates.vec.push(BuiltinObjectCandidate); + return Ok(()); + } + } + _ => {} + } - debug!("assemble_candidates_from_object_ty: poly_trait_ref={}", - poly_trait_ref.repr(self.tcx())); + data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) + } + ty::ty_infer(ty::TyVar(_)) => { + debug!("assemble_candidates_from_object_ty: ambiguous"); + candidates.ambiguous = true; // could wind up being an object type + return Ok(()); + } + _ => { + return Ok(()); + } + }; - // see whether the object trait can be upcast to the trait we are looking for - let obligation_def_id = obligation.predicate.def_id(); - let upcast_trait_ref = match util::upcast(self.tcx(), poly_trait_ref, obligation_def_id) { - Some(r) => r, - None => { return; } - }; + debug!("assemble_candidates_from_object_ty: poly_trait_ref={}", + poly_trait_ref.repr(self.tcx())); - debug!("assemble_candidates_from_object_ty: upcast_trait_ref={}", - upcast_trait_ref.repr(self.tcx())); + // see whether the object trait can be upcast to the trait we are looking for + let upcast_trait_refs = self.upcast(poly_trait_ref, obligation); + if upcast_trait_refs.len() > 1 { + // can be upcast in many ways; need more type information + candidates.ambiguous = true; + } else if upcast_trait_refs.len() == 1 { + candidates.vec.push(ObjectCandidate); + } - // check whether the upcast version of the trait-ref matches what we are looking for - if let Ok(()) = self.infcx.probe(|_| self.match_poly_trait_ref(obligation, - upcast_trait_ref.clone())) { - debug!("assemble_candidates_from_object_ty: matched, pushing candidate"); - candidates.vec.push(ObjectCandidate); - } + Ok::<(),()>(()) + }).unwrap(); } /////////////////////////////////////////////////////////////////////////// @@ -1224,7 +1342,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let result = self.infcx.probe(|_| { let candidate = (*candidate).clone(); match self.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => self.winnow_selection(Some(stack), selection), + Ok(selection) => self.winnow_selection(stack.list(), + selection), Err(error) => EvaluatedToErr(error), } }); @@ -1234,7 +1353,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn winnow_selection<'o>(&mut self, - stack: Option<&TraitObligationStack<'o, 'tcx>>, + stack: TraitObligationStackList<'o,'tcx>, selection: Selection<'tcx>) -> EvaluationResult<'tcx> { @@ -1257,6 +1376,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (&ImplCandidate(..), &ParamCandidate(..)) | (&ClosureCandidate(..), &ParamCandidate(..)) | (&FnPointerCandidate(..), &ParamCandidate(..)) | + (&BuiltinObjectCandidate(..), &ParamCandidate(_)) | (&BuiltinCandidate(..), &ParamCandidate(..)) => { // We basically prefer always prefer to use a // where-clause over another option. Where clauses @@ -1266,6 +1386,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // #18453. true } + (&DefaultImplCandidate(_), _) => { + // Prefer other candidates over default implementations. + self.tcx().sess.bug( + "default implementations shouldn't be recorded \ + when there are other valid candidates"); + } (&ProjectionCandidate, &ParamCandidate(_)) => { // FIXME(#20297) -- this gives where clauses precedent // over projections. Really these are just two means @@ -1337,92 +1463,76 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_bare_fn(..) | ty::ty_char => { // safe for everything - Ok(If(Vec::new())) + ok_if(Vec::new()) } - ty::ty_uniq(referent_ty) => { // Box + ty::ty_uniq(_) => { // Box match bound { - ty::BoundCopy => { - Err(Unimplemented) - } + ty::BoundCopy => Err(Unimplemented), - ty::BoundSized => { - Ok(If(Vec::new())) - } + ty::BoundSized => ok_if(Vec::new()), - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec![referent_ty])) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } ty::ty_ptr(..) => { // *const T, *mut T match bound { - ty::BoundCopy | - ty::BoundSized => { - Ok(If(Vec::new())) - } + ty::BoundCopy | ty::BoundSized => ok_if(Vec::new()), - ty::BoundSync | - ty::BoundSend => { - // sync and send are not implemented for *const, *mut - Err(Unimplemented) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } ty::ty_trait(ref data) => { match bound { - ty::BoundSized => { - Err(Unimplemented) - } - ty::BoundCopy | ty::BoundSync | ty::BoundSend => { + ty::BoundSized => Err(Unimplemented), + ty::BoundCopy => { if data.bounds.builtin_bounds.contains(&bound) { - Ok(If(Vec::new())) + ok_if(Vec::new()) } else { // Recursively check all supertraits to find out if any further // bounds are required and thus we must fulfill. let principal = data.principal_trait_ref_with_self_ty(self.tcx(), self.tcx().types.err); + let desired_def_id = obligation.predicate.def_id(); for tr in util::supertraits(self.tcx(), principal) { - let td = ty::lookup_trait_def(self.tcx(), tr.def_id()); - if td.bounds.builtin_bounds.contains(&bound) { - return Ok(If(Vec::new())) + if tr.def_id() == desired_def_id { + return ok_if(Vec::new()) } } Err(Unimplemented) } } + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); + } } } - ty::ty_rptr(_, ty::mt { ty: referent_ty, mutbl }) => { + ty::ty_rptr(_, ty::mt { ty: _, mutbl }) => { // &mut T or &T match bound { ty::BoundCopy => { match mutbl { // &mut T is affine and hence never `Copy` - ast::MutMutable => { - Err(Unimplemented) - } + ast::MutMutable => Err(Unimplemented), // &T is always copyable - ast::MutImmutable => { - Ok(If(Vec::new())) - } + ast::MutImmutable => ok_if(Vec::new()), } } - ty::BoundSized => { - Ok(If(Vec::new())) - } + ty::BoundSized => ok_if(Vec::new()), - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec![referent_ty])) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } @@ -1432,28 +1542,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match bound { ty::BoundCopy => { match *len { - Some(_) => { - // [T, ..n] is copy iff T is copy - Ok(If(vec![element_ty])) - } - None => { - // [T] is unsized and hence affine - Err(Unimplemented) - } + // [T, ..n] is copy iff T is copy + Some(_) => ok_if(vec![element_ty]), + + // [T] is unsized and hence affine + None => Err(Unimplemented), } } ty::BoundSized => { if len.is_some() { - Ok(If(Vec::new())) + ok_if(Vec::new()) } else { Err(Unimplemented) } } - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec![element_ty])) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } } } @@ -1461,24 +1567,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_str => { // Equivalent to [u8] match bound { - ty::BoundSync | - ty::BoundSend => { - Ok(If(Vec::new())) + ty::BoundSync | ty::BoundSend => { + self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()"); } - ty::BoundCopy | - ty::BoundSized => { - Err(Unimplemented) - } + ty::BoundCopy | ty::BoundSized => Err(Unimplemented), } } - ty::ty_tup(ref tys) => { - // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - Ok(If(tys.clone())) - } + // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet + ty::ty_tup(ref tys) => ok_if(tys.clone()), - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { // FIXME -- This case is tricky. In the case of by-ref // closures particularly, we need the results of // inference to decide how to reflect the type of each @@ -1501,13 +1601,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // unsized, so the closure struct as a whole must be // Sized. if bound == ty::BoundSized { - return Ok(If(Vec::new())); + return ok_if(Vec::new()); } match self.closure_typer.closure_upvars(def_id, substs) { - Some(upvars) => { - Ok(If(upvars.iter().map(|c| c.ty).collect())) - } + Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()), None => { debug!("assemble_builtin_bound_candidates: no upvar types available yet"); Ok(AmbiguousBuiltin) @@ -1520,7 +1618,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::struct_fields(self.tcx(), def_id, substs).iter() .map(|f| f.mt.ty) .collect(); - nominal(self, bound, def_id, types) + nominal(bound, types) } ty::ty_enum(def_id, substs) => { @@ -1530,11 +1628,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .flat_map(|variant| variant.args.iter()) .cloned() .collect(); - nominal(self, bound, def_id, types) + nominal(bound, types) } - ty::ty_projection(_) | - ty::ty_param(_) => { + ty::ty_projection(_) | ty::ty_param(_) => { // Note: A type parameter is only considered to meet a // particular bound if there is a where clause telling // us that it does, and that case is handled by @@ -1550,67 +1647,193 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(AmbiguousBuiltin) } - ty::ty_open(ty) => { - // these only crop up in trans, and represent an - // "opened" unsized/existential type (one that has - // been dereferenced) - match bound { - ty::BoundCopy | - ty::BoundSync | - ty::BoundSend => { - Ok(If(vec!(ty))) - } - - ty::BoundSized => { - Err(Unimplemented) - } - } - } - ty::ty_err => { - Ok(If(Vec::new())) - } + ty::ty_err => ok_if(Vec::new()), - ty::ty_infer(ty::FreshTy(_)) | - ty::ty_infer(ty::FreshIntTy(_)) => { + ty::ty_infer(ty::FreshTy(_)) + | ty::ty_infer(ty::FreshIntTy(_)) => { self.tcx().sess.bug( &format!( "asked to assemble builtin bounds of unexpected type: {}", - self_ty.repr(self.tcx()))[]); + self_ty.repr(self.tcx()))); } }; - fn nominal<'cx, 'tcx>(this: &mut SelectionContext<'cx, 'tcx>, - bound: ty::BuiltinBound, - def_id: ast::DefId, + fn ok_if<'tcx>(v: Vec>) + -> Result, SelectionError<'tcx>> { + Ok(If(ty::Binder(v))) + } + + fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound, types: Vec>) - -> Result,SelectionError<'tcx>> + -> Result, SelectionError<'tcx>> { // First check for markers and other nonsense. - let tcx = this.tcx(); match bound { - ty::BoundSend => { - if Some(def_id) == tcx.lang_items.managed_bound() { - return Err(Unimplemented) - } - } + // Fallback to whatever user-defined impls exist in this case. + ty::BoundCopy => Ok(ParameterBuiltin), - ty::BoundCopy => { - return Ok(ParameterBuiltin) - } + // Sized if all the component types are sized. + ty::BoundSized => ok_if(types), + + // Shouldn't be coming through here. + ty::BoundSend | ty::BoundSync => unreachable!(), + } + } + } + + /// For default impls, we need to break apart a type into its + /// "constituent types" -- meaning, the types that it contains. + /// + /// Here are some (simple) examples: + /// + /// ``` + /// (i32, u32) -> [i32, u32] + /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32] + /// Bar where struct Bar { x: T, y: u32 } -> [i32, u32] + /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] + /// ``` + fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option>> { + match t.sty { + ty::ty_uint(_) | + ty::ty_int(_) | + ty::ty_bool | + ty::ty_float(_) | + ty::ty_bare_fn(..) | + ty::ty_str | + ty::ty_err | + ty::ty_infer(ty::IntVar(_)) | + ty::ty_infer(ty::FloatVar(_)) | + ty::ty_char => { + Some(Vec::new()) + } + + ty::ty_trait(..) | + ty::ty_param(..) | + ty::ty_projection(..) | + ty::ty_infer(ty::TyVar(_)) | + ty::ty_infer(ty::FreshTy(_)) | + ty::ty_infer(ty::FreshIntTy(_)) => { + self.tcx().sess.bug( + &format!( + "asked to assemble constituent types of unexpected type: {}", + t.repr(self.tcx()))); + } + + ty::ty_uniq(referent_ty) => { // Box + Some(vec![referent_ty]) + } + + ty::ty_ptr(ty::mt { ty: element_ty, ..}) | + ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => { + Some(vec![element_ty]) + }, + + ty::ty_vec(element_ty, _) => { + Some(vec![element_ty]) + } - ty::BoundSync => { - if - Some(def_id) == tcx.lang_items.managed_bound() || - Some(def_id) == tcx.lang_items.unsafe_cell_type() - { - return Err(Unimplemented) + ty::ty_tup(ref tys) => { + // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet + Some(tys.clone()) + } + + ty::ty_closure(def_id, substs) => { + assert_eq!(def_id.krate, ast::LOCAL_CRATE); + + match self.closure_typer.closure_upvars(def_id, substs) { + Some(upvars) => { + Some(upvars.iter().map(|c| c.ty).collect()) + } + None => { + None } } + } + + // for `PhantomData`, we pass `T` + ty::ty_struct(def_id, substs) + if Some(def_id) == self.tcx().lang_items.phantom_data() => + { + Some(substs.types.get_slice(TypeSpace).to_vec()) + } - ty::BoundSized => { } + ty::ty_struct(def_id, substs) => { + Some(ty::struct_fields(self.tcx(), def_id, substs).iter() + .map(|f| f.mt.ty) + .collect()) } - Ok(If(types)) + ty::ty_enum(def_id, substs) => { + Some(ty::substd_enum_variants(self.tcx(), def_id, substs) + .iter() + .flat_map(|variant| variant.args.iter()) + .map(|&ty| ty) + .collect()) + } + } + } + + fn collect_predicates_for_types(&mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: ast::DefId, + types: ty::Binder>>) + -> Vec> + { + let derived_cause = match self.tcx().lang_items.to_builtin_kind(trait_def_id) { + Some(_) => { + self.derived_cause(obligation, BuiltinDerivedObligation) + }, + None => { + self.derived_cause(obligation, ImplDerivedObligation) + } + }; + + // Because the types were potentially derived from + // higher-ranked obligations they may reference late-bound + // regions. For example, `for<'a> Foo<&'a int> : Copy` would + // yield a type like `for<'a> &'a int`. In general, we + // maintain the invariant that we never manipulate bound + // regions, so we have to process these bound regions somehow. + // + // The strategy is to: + // + // 1. Instantiate those regions to skolemized regions (e.g., + // `for<'a> &'a int` becomes `&0 int`. + // 2. Produce something like `&'0 int : Copy` + // 3. Re-bind the regions back to `for<'a> &'a int : Copy` + + // Move the binder into the individual types + let bound_types: Vec>> = + types.skip_binder() + .iter() + .map(|&nested_ty| ty::Binder(nested_ty)) + .collect(); + + // For each type, produce a vector of resulting obligations + let obligations: Result>, _> = bound_types.iter().map(|nested_ty| { + self.infcx.commit_if_ok(|snapshot| { + let (skol_ty, skol_map) = + self.infcx().skolemize_late_bound_regions(nested_ty, snapshot); + let Normalized { value: normalized_ty, mut obligations } = + project::normalize_with_depth(self, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &skol_ty); + let skol_obligation = + try!(util::predicate_for_trait_def(self.tcx(), + derived_cause.clone(), + trait_def_id, + obligation.recursion_depth + 1, + normalized_ty)); + obligations.push(skol_obligation); + Ok(self.infcx().plug_leaks(skol_map, snapshot, &obligations)) + }) + }).collect(); + + // Flatten those vectors (couldn't do it above due `collect`) + match obligations { + Ok(obligations) => obligations.into_iter().flat_map(|o| o.into_iter()).collect(), + Err(ErrorReported) => Vec::new(), } } @@ -1619,7 +1842,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // Confirmation unifies the output type parameters of the trait // with the values found in the obligation, possibly yielding a - // type error. See `doc.rs` for more details. + // type error. See `README.md` for more details. fn confirm_candidate(&mut self, obligation: &TraitObligation<'tcx>, @@ -1646,6 +1869,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableParam(obligations)) } + DefaultImplCandidate(trait_def_id) => { + let data = self.confirm_default_impl_candidate(obligation, trait_def_id); + Ok(VtableDefaultImpl(data)) + } + + DefaultImplObjectCandidate(trait_def_id) => { + let data = self.confirm_default_impl_object_candidate(obligation, trait_def_id); + Ok(VtableDefaultImpl(data)) + } + ImplCandidate(impl_def_id) => { let vtable_impl = try!(self.confirm_impl_candidate(obligation, impl_def_id)); @@ -1657,6 +1890,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(VtableClosure(closure_def_id, substs)) } + BuiltinObjectCandidate => { + // This indicates something like `(Trait+Send) : + // Send`. In this case, we know that this holds + // because that's what the object type is telling us, + // and there's really no additional obligations to + // prove and no types in particular to unify etc. + Ok(VtableParam(Vec::new())) + } + ObjectCandidate => { let data = self.confirm_object_candidate(obligation); Ok(VtableObject(data)) @@ -1679,7 +1921,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>) { let _: Result<(),()> = - self.infcx.try(|snapshot| { + self.infcx.commit_if_ok(|snapshot| { let result = self.match_projection_obligation_against_bounds_from_trait(obligation, snapshot); @@ -1727,7 +1969,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().sess.span_bug( obligation.cause.span, &format!("builtin bound for {} was ambig", - obligation.repr(self.tcx()))[]); + obligation.repr(self.tcx()))); } } } @@ -1735,41 +1977,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn vtable_builtin_data(&mut self, obligation: &TraitObligation<'tcx>, bound: ty::BuiltinBound, - nested: Vec>) + nested: ty::Binder>>) -> VtableBuiltinData> { - let derived_cause = self.derived_cause(obligation, BuiltinDerivedObligation); - let obligations = nested.iter().map(|&bound_ty| { - // the obligation might be higher-ranked, e.g. for<'a> &'a - // int : Copy. In that case, we will wind up with - // late-bound regions in the `nested` vector. So for each - // one we instantiate to a skolemized region, do our work - // to produce something like `&'0 int : Copy`, and then - // re-bind it. This is a bit of busy-work but preserves - // the invariant that we only manipulate free regions, not - // bound ones. - self.infcx.try(|snapshot| { - let (skol_ty, skol_map) = - self.infcx().skolemize_late_bound_regions(&ty::Binder(bound_ty), snapshot); - let skol_predicate = - util::predicate_for_builtin_bound( - self.tcx(), - derived_cause.clone(), - bound, - obligation.recursion_depth + 1, - skol_ty); - match skol_predicate { - Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot, - &skol_predicate)), - Err(ErrorReported) => Err(ErrorReported) - } - }) - }).collect::>(); - let obligations = match obligations { - Ok(o) => o, - Err(ErrorReported) => Vec::new() + let trait_def = match self.tcx().lang_items.from_builtin_kind(bound) { + Ok(def_id) => def_id, + Err(_) => { + self.tcx().sess.bug("builtin trait definition not found"); + } }; + let obligations = self.collect_predicates_for_types(obligation, trait_def, nested); + let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new()); debug!("vtable_builtin_data: obligations={}", @@ -1778,6 +1997,107 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { VtableBuiltinData { nested: obligations } } + /// This handles the case where a `impl Foo for ..` impl is being used. + /// The idea is that the impl applies to `X : Foo` if the following conditions are met: + /// + /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds + /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds. + fn confirm_default_impl_candidate(&mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: ast::DefId) + -> VtableDefaultImplData> + { + debug!("confirm_default_impl_candidate({}, {})", + obligation.repr(self.tcx()), + trait_def_id.repr(self.tcx())); + + // binder is moved below + let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); + match self.constituent_types_for_ty(self_ty) { + Some(types) => self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types)), + None => { + self.tcx().sess.bug( + &format!( + "asked to confirm default implementation for ambiguous type: {}", + self_ty.repr(self.tcx()))); + } + } + } + + fn confirm_default_impl_object_candidate(&mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: ast::DefId) + -> VtableDefaultImplData> + { + debug!("confirm_default_impl_object_candidate({}, {})", + obligation.repr(self.tcx()), + trait_def_id.repr(self.tcx())); + + assert!(ty::has_attr(self.tcx(), trait_def_id, "rustc_reflect_like")); + + // OK to skip binder, it is reintroduced below + let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); + match self_ty.sty { + ty::ty_trait(ref data) => { + // OK to skip the binder, it is reintroduced below + let input_types = data.principal.skip_binder().substs.types.get_slice(TypeSpace); + let assoc_types = data.bounds.projection_bounds + .iter() + .map(|pb| pb.skip_binder().ty); + let all_types: Vec<_> = input_types.iter().cloned() + .chain(assoc_types) + .collect(); + + // reintroduce the two binding levels we skipped, then flatten into one + let all_types = ty::Binder(ty::Binder(all_types)); + let all_types = ty::flatten_late_bound_regions(self.tcx(), &all_types); + + self.vtable_default_impl(obligation, trait_def_id, all_types) + } + _ => { + self.tcx().sess.bug( + &format!( + "asked to confirm default object implementation for non-object type: {}", + self_ty.repr(self.tcx()))); + } + } + } + + /// See `confirm_default_impl_candidate` + fn vtable_default_impl(&mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: ast::DefId, + nested: ty::Binder>>) + -> VtableDefaultImplData> + { + debug!("vtable_default_impl_data: nested={}", nested.repr(self.tcx())); + + let mut obligations = self.collect_predicates_for_types(obligation, + trait_def_id, + nested); + + let trait_obligations: Result,()> = self.infcx.commit_if_ok(|snapshot| { + let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); + let (trait_ref, skol_map) = + self.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot); + Ok(self.impl_or_trait_obligations(obligation.cause.clone(), + obligation.recursion_depth + 1, + trait_def_id, + &trait_ref.substs, + skol_map, + snapshot)) + }); + + obligations.extend(trait_obligations.unwrap().into_iter()); // no Errors in that code above + + debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx())); + + VtableDefaultImplData { + trait_def_id: trait_def_id, + nested: obligations + } + } + fn confirm_impl_candidate(&mut self, obligation: &TraitObligation<'tcx>, impl_def_id: ast::DefId) @@ -1790,7 +2110,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.try(|snapshot| { + self.infcx.commit_if_ok(|snapshot| { let (skol_obligation_trait_ref, skol_map) = self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot); let substs = @@ -1806,7 +2126,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id: ast::DefId, substs: Normalized<'tcx, Substs<'tcx>>, cause: ObligationCause<'tcx>, - recursion_depth: uint, + recursion_depth: usize, skol_map: infer::SkolemizationMap, snapshot: &infer::CombinedSnapshot) -> VtableImplData<'tcx, PredicateObligation<'tcx>> @@ -1818,12 +2138,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { skol_map.repr(self.tcx())); let mut impl_obligations = - self.impl_obligations(cause, - recursion_depth, - impl_def_id, - &substs.value, - skol_map, - snapshot); + self.impl_or_trait_obligations(cause, + recursion_depth, + impl_def_id, + &substs.value, + skol_map, + snapshot); debug!("vtable_impl: impl_def_id={} impl_obligations={}", impl_def_id.repr(self.tcx()), @@ -1843,7 +2163,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_object_candidate({})", obligation.repr(self.tcx())); - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + // FIXME skipping binder here seems wrong -- we should + // probably flatten the binder from the obligation and the + // binder from the object. Have to try to make a broken test + // case that results. -nmatsakis + let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { ty::ty_trait(ref data) => { data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) @@ -1854,20 +2178,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } }; - let obligation_def_id = obligation.predicate.def_id(); - let upcast_trait_ref = match util::upcast(self.tcx(), - poly_trait_ref.clone(), - obligation_def_id) { - Some(r) => r, - None => { - self.tcx().sess.span_bug(obligation.cause.span, - &format!("unable to upcast from {} to {}", - poly_trait_ref.repr(self.tcx()), - obligation_def_id.repr(self.tcx()))); - } - }; + // Upcast the object type to the obligation type. There must + // be exactly one applicable trait-reference; if this were not + // the case, we would have reported an ambiguity error rather + // than successfully selecting one of the candidates. + let upcast_trait_refs = self.upcast(poly_trait_ref.clone(), obligation); + assert_eq!(upcast_trait_refs.len(), 1); + let upcast_trait_ref = upcast_trait_refs.into_iter().next().unwrap(); - match self.match_poly_trait_ref(obligation, upcast_trait_ref) { + match self.match_poly_trait_ref(obligation, upcast_trait_ref.clone()) { Ok(()) => { } Err(()) => { self.tcx().sess.span_bug(obligation.cause.span, @@ -1875,7 +2194,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - VtableObjectData { object_ty: self_ty } + VtableObjectData { object_ty: self_ty, + upcast_trait_ref: upcast_trait_ref } } fn confirm_fn_pointer_candidate(&mut self, @@ -1885,15 +2205,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_fn_pointer_candidate({})", obligation.repr(self.tcx())); - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + // ok to skip binder; it is reintroduced below + let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let sig = ty::ty_fn_sig(self_ty); - let ty::Binder((trait_ref, _)) = + let trait_ref = util::closure_trait_ref_and_return_type(self.tcx(), obligation.predicate.def_id(), self_ty, sig, - util::TupleArgumentsFlag::Yes); - let trait_ref = ty::Binder(trait_ref); + util::TupleArgumentsFlag::Yes) + .map_bound(|(trait_ref, _)| trait_ref); try!(self.confirm_poly_trait_refs(obligation.cause.clone(), obligation.predicate.to_poly_trait_ref(), @@ -1942,9 +2263,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// /// impl Fn(int) for Closure { ... } /// - /// Now imagine our obligation is `Fn(uint) for Closure`. So far + /// Now imagine our obligation is `Fn(usize) for Closure`. So far /// we have matched the self-type `Closure`. At this point we'll - /// compare the `int` to `uint` and generate an error. + /// compare the `int` to `usize` and generate an error. /// /// Note that this checking occurs *after* the impl has selected, /// because these output type parameters should not affect the @@ -1988,14 +2309,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { match self.match_impl(impl_def_id, obligation, snapshot, skol_map, skol_obligation_trait_ref) { - Ok(substs) => { - substs - } + Ok(substs) => substs, Err(()) => { self.tcx().sess.bug( &format!("Impl {} was matchable against {} but now is not", impl_def_id.repr(self.tcx()), - obligation.repr(self.tcx()))[]); + obligation.repr(self.tcx()))); } } } @@ -2017,9 +2336,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let impl_substs = util::fresh_substs_for_impl(self.infcx, - obligation.cause.span, - impl_def_id); + let impl_substs = util::fresh_type_vars_for_impl(self.infcx, + obligation.cause.span, + impl_def_id); let impl_trait_ref = impl_trait_ref.subst(self.tcx(), &impl_substs); @@ -2038,30 +2357,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { skol_obligation_trait_ref.repr(self.tcx())); let origin = infer::RelateOutputImplTypes(obligation.cause.span); - match self.infcx.sub_trait_refs(false, - origin, - impl_trait_ref.value.clone(), - skol_obligation_trait_ref) { - Ok(()) => { } - Err(e) => { - debug!("match_impl: failed sub_trait_refs due to `{}`", - ty::type_err_to_str(self.tcx(), &e)); - return Err(()); - } + if let Err(e) = self.infcx.sub_trait_refs(false, + origin, + impl_trait_ref.value.clone(), + skol_obligation_trait_ref) { + debug!("match_impl: failed sub_trait_refs due to `{}`", + ty::type_err_to_str(self.tcx(), &e)); + return Err(()); } - match self.infcx.leak_check(skol_map, snapshot) { - Ok(()) => { } - Err(e) => { - debug!("match_impl: failed leak check due to `{}`", - ty::type_err_to_str(self.tcx(), &e)); - return Err(()); - } + if let Err(e) = self.infcx.leak_check(skol_map, snapshot) { + debug!("match_impl: failed leak check due to `{}`", + ty::type_err_to_str(self.tcx(), &e)); + return Err(()); } debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx())); - Ok(Normalized { value: impl_substs, - obligations: impl_trait_ref.obligations }) + Ok(Normalized { + value: impl_substs, + obligations: impl_trait_ref.obligations + }) } fn fast_reject_trait_refs(&mut self, @@ -2097,9 +2412,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { where_clause_trait_ref: ty::PolyTraitRef<'tcx>) -> Result>,()> { - let () = - try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref)); - + try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref)); Ok(Vec::new()) } @@ -2143,9 +2456,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { // Create fresh type variables for each type parameter declared // on the impl etc. - let impl_substs = util::fresh_substs_for_impl(self.infcx, - obligation_cause.span, - impl_def_id); + let impl_substs = util::fresh_type_vars_for_impl(self.infcx, + obligation_cause.span, + impl_def_id); // Find the self type for the impl. let impl_self_ty = ty::lookup_item_type(self.tcx(), impl_def_id).ty; @@ -2195,8 +2508,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /////////////////////////////////////////////////////////////////////////// // Miscellany + fn match_fresh_trait_refs(&self, + previous: &ty::PolyTraitRef<'tcx>, + current: &ty::PolyTraitRef<'tcx>) + -> bool + { + let mut matcher = ty_match::Match::new(self.tcx()); + matcher.relate(previous, current).is_ok() + } + fn push_stack<'o,'s:'o>(&mut self, - previous_stack: Option<&'s TraitObligationStack<'s, 'tcx>>, + previous_stack: TraitObligationStackList<'s, 'tcx>, obligation: &'o TraitObligation<'tcx>) -> TraitObligationStack<'o, 'tcx> { @@ -2206,7 +2528,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TraitObligationStack { obligation: obligation, fresh_trait_ref: fresh_trait_ref, - previous: previous_stack.map(|p| p), // FIXME variance + previous: previous_stack, } } @@ -2216,7 +2538,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.tcx().trait_impls.borrow().get(&trait_def_id) { None => Vec::new(), - Some(impls) => impls.borrow().clone() + Some(impls) => impls.borrow().clone(), } } @@ -2243,28 +2565,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Binder(trait_ref) } - fn impl_obligations(&mut self, - cause: ObligationCause<'tcx>, - recursion_depth: uint, - impl_def_id: ast::DefId, - impl_substs: &Substs<'tcx>, - skol_map: infer::SkolemizationMap, - snapshot: &infer::CombinedSnapshot) - -> VecPerParamSpace> + /// Returns the obligations that are implied by instantiating an + /// impl or trait. The obligations are substituted and fully + /// normalized. This is used when confirming an impl or default + /// impl. + fn impl_or_trait_obligations(&mut self, + cause: ObligationCause<'tcx>, + recursion_depth: usize, + def_id: ast::DefId, // of impl or trait + substs: &Substs<'tcx>, // for impl or trait + skol_map: infer::SkolemizationMap, + snapshot: &infer::CombinedSnapshot) + -> VecPerParamSpace> { - let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id); - let bounds = impl_bounds.instantiate(self.tcx(), impl_substs); - let normalized_bounds = - project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds); - let normalized_bounds = - self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds); - let mut impl_obligations = + debug!("impl_or_trait_obligations(def_id={})", def_id.repr(self.tcx())); + + let predicates = ty::lookup_predicates(self.tcx(), def_id); + let predicates = predicates.instantiate(self.tcx(), substs); + let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates); + let predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates); + let mut obligations = util::predicates_for_generics(self.tcx(), cause, recursion_depth, - &normalized_bounds.value); - impl_obligations.extend(TypeSpace, normalized_bounds.obligations.into_iter()); - impl_obligations + &predicates.value); + obligations.extend(TypeSpace, predicates.obligations.into_iter()); + obligations } #[allow(unused_comparisons)] @@ -2298,6 +2624,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone() } } + + /// Upcasts an object trait-reference into those that match the obligation. + fn upcast(&mut self, obj_trait_ref: ty::PolyTraitRef<'tcx>, obligation: &TraitObligation<'tcx>) + -> Vec> + { + debug!("upcast(obj_trait_ref={}, obligation={})", + obj_trait_ref.repr(self.tcx()), + obligation.repr(self.tcx())); + + let obligation_def_id = obligation.predicate.def_id(); + let mut upcast_trait_refs = util::upcast(self.tcx(), obj_trait_ref, obligation_def_id); + + // Retain only those upcast versions that match the trait-ref + // we are looking for. In particular, we know that all of + // `upcast_trait_refs` apply to the correct trait, but + // possibly with incorrect type parameters. For example, we + // may be trying to upcast `Foo` to `Bar`, but `Foo` is + // declared as `trait Foo : Bar`. + upcast_trait_refs.retain(|upcast_trait_ref| { + let upcast_trait_ref = upcast_trait_ref.clone(); + self.infcx.probe(|_| self.match_poly_trait_ref(obligation, upcast_trait_ref)).is_ok() + }); + + debug!("upcast: upcast_trait_refs={}", upcast_trait_refs.repr(self.tcx())); + upcast_trait_refs + } } impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { @@ -2306,13 +2658,14 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { PhantomFnCandidate => format!("PhantomFnCandidate"), ErrorCandidate => format!("ErrorCandidate"), BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b), + BuiltinObjectCandidate => format!("BuiltinObjectCandidate"), ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)), ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)), + DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t), + DefaultImplObjectCandidate(t) => format!("DefaultImplObjectCandidate({:?})", t), ProjectionCandidate => format!("ProjectionCandidate"), FnPointerCandidate => format!("FnPointerCandidate"), - ObjectCandidate => { - format!("ObjectCandidate") - } + ObjectCandidate => format!("ObjectCandidate"), ClosureCandidate(c, ref s) => { format!("ClosureCandidate({:?},{})", c, s.repr(tcx)) } @@ -2323,34 +2676,51 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> { impl<'tcx> SelectionCache<'tcx> { pub fn new() -> SelectionCache<'tcx> { SelectionCache { - hashmap: RefCell::new(HashMap::new()) + hashmap: RefCell::new(FnvHashMap()) } } } -impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { - fn iter(&self) -> Option<&TraitObligationStack<'o, 'tcx>> { - Some(self) +impl<'o,'tcx> TraitObligationStack<'o,'tcx> { + fn list(&'o self) -> TraitObligationStackList<'o,'tcx> { + TraitObligationStackList::with(self) + } + + fn iter(&'o self) -> TraitObligationStackList<'o,'tcx> { + self.list() + } +} + +#[derive(Copy, Clone)] +struct TraitObligationStackList<'o,'tcx:'o> { + head: Option<&'o TraitObligationStack<'o,'tcx>> +} + +impl<'o,'tcx> TraitObligationStackList<'o,'tcx> { + fn empty() -> TraitObligationStackList<'o,'tcx> { + TraitObligationStackList { head: None } + } + + fn with(r: &'o TraitObligationStack<'o,'tcx>) -> TraitObligationStackList<'o,'tcx> { + TraitObligationStackList { head: Some(r) } } } -impl<'o, 'tcx> Iterator for Option<&'o TraitObligationStack<'o, 'tcx>> { +impl<'o,'tcx> Iterator for TraitObligationStackList<'o,'tcx>{ type Item = &'o TraitObligationStack<'o,'tcx>; - fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> { - match *self { + fn next(&mut self) -> Option<&'o TraitObligationStack<'o,'tcx>> { + match self.head { Some(o) => { *self = o.previous; Some(o) } - None => { - None - } + None => None } } } -impl<'o, 'tcx> Repr<'tcx> for TraitObligationStack<'o, 'tcx> { +impl<'o,'tcx> Repr<'tcx> for TraitObligationStack<'o,'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { format!("TraitObligationStack({})", self.obligation.repr(tcx)) @@ -2362,13 +2732,11 @@ impl<'tcx> EvaluationResult<'tcx> { match *self { EvaluatedToOk | EvaluatedToAmbig | - EvaluatedToErr(Overflow) | - EvaluatedToErr(OutputTypeParameterMismatch(..)) => { - true - } - EvaluatedToErr(Unimplemented) => { - false - } + EvaluatedToErr(OutputTypeParameterMismatch(..)) => + true, + + EvaluatedToErr(Unimplemented) => + false, } } } diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs index 6c54da1c13..297cea1320 100644 --- a/src/librustc/middle/traits/util.rs +++ b/src/librustc/middle/traits/util.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use middle::region; use middle::subst::{Substs, VecPerParamSpace}; use middle::infer::InferCtxt; use middle::ty::{self, Ty, AsPredicate, ToPolyTraitRef}; @@ -20,7 +21,7 @@ use util::nodemap::FnvHashSet; use util::ppaux::Repr; use super::{Obligation, ObligationCause, PredicateObligation, - VtableImpl, VtableParam, VtableImplData}; + VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData}; struct PredicateSet<'a,'tcx:'a> { tcx: &'a ty::ctxt<'tcx>, @@ -76,15 +77,10 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> { /// 'static`. pub struct Elaborator<'cx, 'tcx:'cx> { tcx: &'cx ty::ctxt<'tcx>, - stack: Vec>, + stack: Vec>, visited: PredicateSet<'cx,'tcx>, } -struct StackEntry<'tcx> { - position: uint, - predicates: Vec>, -} - pub fn elaborate_trait_ref<'cx, 'tcx>( tcx: &'cx ty::ctxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) @@ -111,21 +107,28 @@ pub fn elaborate_predicates<'cx, 'tcx>( { let mut visited = PredicateSet::new(tcx); predicates.retain(|pred| visited.insert(pred)); - let entry = StackEntry { position: 0, predicates: predicates }; - Elaborator { tcx: tcx, stack: vec![entry], visited: visited } + Elaborator { tcx: tcx, stack: predicates, visited: visited } } impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { - pub fn filter_to_traits(self) -> Supertraits<'cx, 'tcx> { - Supertraits { elaborator: self } + pub fn filter_to_traits(self) -> FilterToTraits> { + FilterToTraits::new(self) } fn push(&mut self, predicate: &ty::Predicate<'tcx>) { match *predicate { ty::Predicate::Trait(ref data) => { - let mut predicates = - ty::predicates_for_trait_ref(self.tcx, - &data.to_poly_trait_ref()); + // Predicates declared on the trait. + let predicates = ty::lookup_super_predicates(self.tcx, data.def_id()); + + let mut predicates: Vec<_> = + predicates.predicates + .iter() + .map(|p| p.subst_supertrait(self.tcx, &data.to_poly_trait_ref())) + .collect(); + + debug!("super_predicates: data={} predicates={}", + data.repr(self.tcx), predicates.repr(self.tcx)); // Only keep those bounds that we haven't already // seen. This is necessary to prevent infinite @@ -134,8 +137,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> { // Sized { }`. predicates.retain(|r| self.visited.insert(r)); - self.stack.push(StackEntry { position: 0, - predicates: predicates }); + self.stack.extend(predicates.into_iter()); } ty::Predicate::Equate(..) => { // Currently, we do not "elaborate" predicates like @@ -175,41 +177,16 @@ impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> { type Item = ty::Predicate<'tcx>; fn next(&mut self) -> Option> { - loop { - // Extract next item from top-most stack frame, if any. - let next_predicate = match self.stack.last_mut() { - None => { - // No more stack frames. Done. - return None; - } - Some(entry) => { - let p = entry.position; - if p < entry.predicates.len() { - // Still more predicates left in the top stack frame. - entry.position += 1; - - let next_predicate = - entry.predicates[p].clone(); - - Some(next_predicate) - } else { - None - } - } - }; - - match next_predicate { - Some(next_predicate) => { - self.push(&next_predicate); - return Some(next_predicate); - } - - None => { - // Top stack frame is exhausted, pop it. - self.stack.pop(); - } + // Extract next item from top-most stack frame, if any. + let next_predicate = match self.stack.pop() { + Some(predicate) => predicate, + None => { + // No more stack frames. Done. + return None; } - } + }; + self.push(&next_predicate); + return Some(next_predicate); } } @@ -217,11 +194,7 @@ impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> { // Supertrait iterator /////////////////////////////////////////////////////////////////////////// -/// A filter around the `Elaborator` that just yields up supertrait references, -/// not other kinds of predicates. -pub struct Supertraits<'cx, 'tcx:'cx> { - elaborator: Elaborator<'cx, 'tcx>, -} +pub type Supertraits<'cx, 'tcx> = FilterToTraits>; pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) @@ -237,12 +210,69 @@ pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, elaborate_trait_refs(tcx, bounds).filter_to_traits() } -impl<'cx, 'tcx> Iterator for Supertraits<'cx, 'tcx> { +/////////////////////////////////////////////////////////////////////////// +// Iterator over def-ids of supertraits + +pub struct SupertraitDefIds<'cx, 'tcx:'cx> { + tcx: &'cx ty::ctxt<'tcx>, + stack: Vec, + visited: FnvHashSet, +} + +pub fn supertrait_def_ids<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>, + trait_def_id: ast::DefId) + -> SupertraitDefIds<'cx, 'tcx> +{ + SupertraitDefIds { + tcx: tcx, + stack: vec![trait_def_id], + visited: Some(trait_def_id).into_iter().collect(), + } +} + +impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> { + type Item = ast::DefId; + + fn next(&mut self) -> Option { + let def_id = match self.stack.pop() { + Some(def_id) => def_id, + None => { return None; } + }; + + let predicates = ty::lookup_super_predicates(self.tcx, def_id); + let visited = &mut self.visited; + self.stack.extend( + predicates.predicates + .iter() + .filter_map(|p| p.to_opt_poly_trait_ref()) + .map(|t| t.def_id()) + .filter(|&super_def_id| visited.insert(super_def_id))); + Some(def_id) + } +} + +/////////////////////////////////////////////////////////////////////////// +// Other +/////////////////////////////////////////////////////////////////////////// + +/// A filter around an iterator of predicates that makes it yield up +/// just trait references. +pub struct FilterToTraits { + base_iterator: I +} + +impl FilterToTraits { + fn new(base: I) -> FilterToTraits { + FilterToTraits { base_iterator: base } + } +} + +impl<'tcx,I:Iterator>> Iterator for FilterToTraits { type Item = ty::PolyTraitRef<'tcx>; fn next(&mut self) -> Option> { loop { - match self.elaborator.next() { + match self.base_iterator.next() { None => { return None; } @@ -264,16 +294,44 @@ impl<'cx, 'tcx> Iterator for Supertraits<'cx, 'tcx> { // declared on the impl declaration e.g., `impl for Box<[(A,B)]>` // would return ($0, $1) where $0 and $1 are freshly instantiated type // variables. -pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - span: Span, - impl_def_id: ast::DefId) - -> Substs<'tcx> +pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, + span: Span, + impl_def_id: ast::DefId) + -> Substs<'tcx> { let tcx = infcx.tcx; let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics; infcx.fresh_substs_for_generics(span, &impl_generics) } +// determine the `self` type, using fresh variables for all variables +// declared on the impl declaration e.g., `impl for Box<[(A,B)]>` +// would return ($0, $1) where $0 and $1 are freshly instantiated type +// variables. +pub fn free_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, + _span: Span, + impl_def_id: ast::DefId) + -> Substs<'tcx> +{ + let tcx = infcx.tcx; + let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics; + + let some_types = impl_generics.types.map(|def| { + ty::mk_param_from_def(tcx, def) + }); + + let some_regions = impl_generics.regions.map(|def| { + // FIXME. This destruction scope information is pretty darn + // bogus; after all, the impl might not even be in this crate! + // But given what we do in coherence, it is harmless enough + // for now I think. -nmatsakis + let extent = region::DestructionScopeData::new(ast::DUMMY_NODE_ID); + ty::free_region_from_def(extent, def) + }); + + Substs::new(some_types, some_regions) +} + impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "VtableImpl({:?})", self.impl_def_id) @@ -289,7 +347,7 @@ impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> { /// See `super::obligations_for_generics` pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, - recursion_depth: uint, + recursion_depth: usize, generic_bounds: &ty::InstantiatedPredicates<'tcx>) -> VecPerParamSpace> { @@ -323,15 +381,13 @@ pub fn trait_ref_for_builtin_bound<'tcx>( } } -pub fn predicate_for_builtin_bound<'tcx>( - tcx: &ty::ctxt<'tcx>, + +pub fn predicate_for_trait_ref<'tcx>( cause: ObligationCause<'tcx>, - builtin_bound: ty::BuiltinBound, - recursion_depth: uint, - param_ty: Ty<'tcx>) + trait_ref: Rc>, + recursion_depth: usize) -> Result, ErrorReported> { - let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)); Ok(Obligation { cause: cause, recursion_depth: recursion_depth, @@ -339,25 +395,48 @@ pub fn predicate_for_builtin_bound<'tcx>( }) } +pub fn predicate_for_trait_def<'tcx>( + tcx: &ty::ctxt<'tcx>, + cause: ObligationCause<'tcx>, + trait_def_id: ast::DefId, + recursion_depth: usize, + param_ty: Ty<'tcx>) + -> Result, ErrorReported> +{ + let trait_ref = Rc::new(ty::TraitRef { + def_id: trait_def_id, + substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty)) + }); + predicate_for_trait_ref(cause, trait_ref, recursion_depth) +} + +pub fn predicate_for_builtin_bound<'tcx>( + tcx: &ty::ctxt<'tcx>, + cause: ObligationCause<'tcx>, + builtin_bound: ty::BuiltinBound, + recursion_depth: usize, + param_ty: Ty<'tcx>) + -> Result, ErrorReported> +{ + let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)); + predicate_for_trait_ref(cause, trait_ref, recursion_depth) +} + /// Cast a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>, source_trait_ref: ty::PolyTraitRef<'tcx>, target_trait_def_id: ast::DefId) - -> Option> + -> Vec> { if source_trait_ref.def_id() == target_trait_def_id { - return Some(source_trait_ref); // shorcut the most common case + return vec![source_trait_ref]; // shorcut the most common case } - for super_trait_ref in supertraits(tcx, source_trait_ref) { - if super_trait_ref.def_id() == target_trait_def_id { - return Some(super_trait_ref); - } - } - - None + supertraits(tcx, source_trait_ref) + .filter(|r| r.def_id() == target_trait_def_id) + .collect() } /// Given an object of type `object_trait_ref`, returns the index of @@ -367,7 +446,7 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>, pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait_ref: ty::PolyTraitRef<'tcx>, trait_def_id: ast::DefId, - method_offset_in_trait: uint) -> uint { + method_offset_in_trait: usize) -> usize { // We need to figure the "real index" of the method in a // listing of all the methods of an object. We do this by // iterating down the supertraits of the object's trait until @@ -444,6 +523,9 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> { super::VtableImpl(ref v) => v.repr(tcx), + super::VtableDefaultImpl(ref t) => + t.repr(tcx), + super::VtableClosure(ref d, ref s) => format!("VtableClosure({},{})", d.repr(tcx), @@ -483,6 +565,14 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData { } } +impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData { + fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { + format!("VtableDefaultImplData(trait_def_id={}, nested={})", + self.trait_def_id.repr(tcx), + self.nested.repr(tcx)) + } +} + impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { format!("VtableObject(object_ty={})", @@ -493,9 +583,6 @@ impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> { impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { match *self { - super::Overflow => - format!("Overflow"), - super::Unimplemented => format!("Unimplemented"), @@ -547,5 +634,3 @@ impl<'tcx> fmt::Debug for super::MismatchedProjectionTypes<'tcx> { write!(f, "MismatchedProjectionTypes(..)") } } - - diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index e9908397f9..1123c92363 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -17,7 +17,6 @@ pub use self::InferTy::*; pub use self::InferRegion::*; pub use self::ImplOrTraitItemId::*; pub use self::ClosureKind::*; -pub use self::ast_ty_to_ty_cache_entry::*; pub use self::Variance::*; pub use self::AutoAdjustment::*; pub use self::Representability::*; @@ -48,47 +47,50 @@ use middle::check_const; use middle::const_eval; use middle::def::{self, DefMap, ExportMap}; use middle::dependency_format; -use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; -use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem}; +use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::mem_categorization as mc; use middle::region; use middle::resolve_lifetime; use middle::infer; +use middle::pat_util; use middle::stability; -use middle::subst::{self, Subst, Substs, VecPerParamSpace}; +use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace}; use middle::traits; use middle::ty; use middle::ty_fold::{self, TypeFoldable, TypeFolder}; -use middle::ty_walk::TypeWalker; +use middle::ty_walk::{self, TypeWalker}; use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string}; use util::ppaux::ty_to_string; use util::ppaux::{Repr, UserString}; use util::common::{memoized, ErrorReported}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; -use util::nodemap::{FnvHashMap}; +use util::nodemap::FnvHashMap; use arena::TypedArena; use std::borrow::{Borrow, Cow}; -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, RefCell, Ref}; use std::cmp; use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; -#[cfg(stage0)] use std::hash::Writer; use std::mem; +use std::num::ToPrimitive; use std::ops; use std::rc::Rc; -use std::vec::{CowVec, IntoIter}; +use std::vec::IntoIter; use collections::enum_set::{EnumSet, CLike}; use std::collections::{HashMap, HashSet}; use syntax::abi; use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility}; -use syntax::ast_util::{self, is_local, lit_is_str, local_def, PostExpansionMethod}; -use syntax::attr::{self, AttrMetaMethods}; +use syntax::ast_util::{self, is_local, lit_is_str, local_def}; +use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt}; use syntax::codemap::Span; use syntax::parse::token::{self, InternedString, special_idents}; -use syntax::{ast, ast_map}; +use syntax::print::pprust; +use syntax::ptr::P; +use syntax::ast; +use syntax::ast_map::{self, LinkedPath}; pub type Disr = u64; @@ -260,17 +262,11 @@ pub struct field_ty { // Contains information needed to resolve types and (in the future) look up // the types of AST nodes. -#[derive(Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct creader_cache_key { pub cnum: CrateNum, - pub pos: uint, - pub len: uint -} - -#[derive(Copy)] -pub enum ast_ty_to_ty_cache_entry<'tcx> { - atttce_unresolved, /* not resolved yet */ - atttce_resolved(Ty<'tcx>) /* resolved to a type, irrespective of region */ + pub pos: usize, + pub len: usize } #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)] @@ -290,22 +286,24 @@ pub enum Variance { #[derive(Clone, Debug)] pub enum AutoAdjustment<'tcx> { AdjustReifyFnPointer(ast::DefId), // go from a fn-item type to a fn-pointer type + AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer AdjustDerefRef(AutoDerefRef<'tcx>) } #[derive(Clone, PartialEq, Debug)] pub enum UnsizeKind<'tcx> { - // [T, ..n] -> [T], the uint field is n. - UnsizeLength(uint), + // [T, ..n] -> [T], the usize field is n. + UnsizeLength(usize), // An unsize coercion applied to the tail field of a struct. - // The uint is the index of the type parameter which is unsized. - UnsizeStruct(Box>, uint), - UnsizeVtable(TyTrait<'tcx>, /* the self type of the trait */ Ty<'tcx>) + // The usize is the index of the type parameter which is unsized. + UnsizeStruct(Box>, usize), + UnsizeVtable(TyTrait<'tcx>, /* the self type of the trait */ Ty<'tcx>), + UnsizeUpcast(Ty<'tcx>), } #[derive(Clone, Debug)] pub struct AutoDerefRef<'tcx> { - pub autoderefs: uint, + pub autoderefs: usize, pub autoref: Option> } @@ -429,7 +427,7 @@ pub fn type_of_adjust<'tcx>(cx: &ctxt<'tcx>, adj: &AutoAdjustment<'tcx>) -> Opti #[derive(Clone, Copy, RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Debug)] pub struct param_index { pub space: subst::ParamSpace, - pub index: uint + pub index: usize } #[derive(Clone, Debug)] @@ -458,10 +456,10 @@ pub struct MethodParam<'tcx> { // instantiated with fresh variables at this point. pub trait_ref: Rc>, - // index of uint in the list of trait items. Note that this is NOT + // index of usize in the list of trait items. Note that this is NOT // the index into the vtable, because the list of trait items // includes associated types. - pub method_num: uint, + pub method_num: usize, /// The impl for the trait from which the method comes. This /// should only be used for certain linting/heuristic purposes @@ -480,13 +478,13 @@ pub struct MethodObject<'tcx> { pub object_trait_id: ast::DefId, // index of the method to be invoked amongst the trait's items - pub method_num: uint, + pub method_num: usize, // index into the actual runtime vtable. // the vtable is formed by concatenating together the method lists of // the base object trait and all supertraits; this is the index into // that vtable - pub vtable_index: uint, + pub vtable_index: usize, } #[derive(Clone)] @@ -517,7 +515,7 @@ pub struct MethodCall { #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)] pub enum ExprAdjustment { NoAdjustment, - AutoDeref(uint), + AutoDeref(usize), AutoObject } @@ -536,7 +534,7 @@ impl MethodCall { } } - pub fn autoderef(expr_id: ast::NodeId, autoderef: uint) -> MethodCall { + pub fn autoderef(expr_id: ast::NodeId, autoderef: usize) -> MethodCall { MethodCall { expr_id: expr_id, adjustment: AutoDeref(1 + autoderef) @@ -570,7 +568,7 @@ pub enum vtable_origin<'tcx> { The first argument is the param index (identifying T in the example), and the second is the bound number (identifying baz) */ - vtable_param(param_index, uint), + vtable_param(param_index, usize), /* Vtable automatically generated for a closure. The def ID is the @@ -598,7 +596,7 @@ pub type ObjectCastMap<'tcx> = RefCell>>; /// will push one or more such restriction into the /// `transmute_restrictions` vector during `intrinsicck`. They are /// then checked during `trans` by the fn `check_intrinsics`. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct TransmuteRestriction<'tcx> { /// The span whence the restriction comes. pub span: Span, @@ -645,12 +643,12 @@ impl<'tcx> CtxtArenas<'tcx> { pub struct CommonTypes<'tcx> { pub bool: Ty<'tcx>, pub char: Ty<'tcx>, - pub int: Ty<'tcx>, + pub isize: Ty<'tcx>, pub i8: Ty<'tcx>, pub i16: Ty<'tcx>, pub i32: Ty<'tcx>, pub i64: Ty<'tcx>, - pub uint: Ty<'tcx>, + pub usize: Ty<'tcx>, pub u8: Ty<'tcx>, pub u16: Ty<'tcx>, pub u32: Ty<'tcx>, @@ -691,7 +689,7 @@ pub struct ctxt<'tcx> { /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated until after typeck. See /// typeck::check::fn_ctxt for details. - pub node_types: RefCell>>, + node_types: RefCell>>, /// Stores the type parameters which were substituted to obtain the type /// of this node. This only applies to nodes that refer to entities @@ -710,25 +708,32 @@ pub struct ctxt<'tcx> { pub impl_trait_cache: RefCell>>>>, - pub trait_refs: RefCell>>>, + pub impl_trait_refs: RefCell>>>, pub trait_defs: RefCell>>>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its /// associated predicates. pub predicates: RefCell>>, + /// Maps from the def-id of a trait to the list of + /// super-predicates. This is a subset of the full list of + /// predicates. We store these in a separate map because we must + /// evaluate them even during type conversion, often before the + /// full predicates are available (note that supertraits have + /// additional acyclicity requirements). + pub super_predicates: RefCell>>, + /// Maps from node-id of a trait object cast (like `foo as /// Box`) to the trait reference. pub object_cast_map: ObjectCastMap<'tcx>, pub map: ast_map::Map<'tcx>, - pub intrinsic_defs: RefCell>>, pub freevars: RefCell, pub tcache: RefCell>>, pub rcache: RefCell>>, pub short_names_cache: RefCell, String>>, pub tc_cache: RefCell, TypeContents>>, - pub ast_ty_to_ty_cache: RefCell>>, + pub ast_ty_to_ty_cache: RefCell>>, pub enum_var_cache: RefCell>>>>>, pub ty_param_defs: RefCell>>, pub adjustments: RefCell>>, @@ -757,6 +762,9 @@ pub struct ctxt<'tcx> { /// Maps a trait onto a list of impls of that trait. pub trait_impls: RefCell>>>>, + /// A set of traits that have a default impl + traits_with_default_impls: RefCell>, + /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. @@ -785,6 +793,9 @@ pub struct ctxt<'tcx> { /// is used for lazy resolution of traits. pub populated_external_traits: RefCell, + /// The set of external primitive inherent implementations that have been read. + pub populated_external_primitive_impls: RefCell, + /// Borrows pub upvar_capture_map: RefCell, @@ -843,6 +854,13 @@ pub struct ctxt<'tcx> { pub const_qualif_map: RefCell>, } +impl<'tcx> ctxt<'tcx> { + pub fn node_types(&self) -> Ref>> { self.node_types.borrow() } + pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) { + self.node_types.borrow_mut().insert(id, ty); + } +} + // Flags that we track on types. These flags are propagated upwards // through the type during type construction, so that we can quickly // check whether the type has various kinds of types in it without @@ -868,12 +886,12 @@ macro_rules! sty_debug_print { // variable names. mod inner { use middle::ty; - #[derive(Copy)] + #[derive(Copy, Clone)] struct DebugStat { - total: uint, - region_infer: uint, - ty_infer: uint, - both_infer: uint, + total: usize, + region_infer: usize, + ty_infer: usize, + both_infer: usize, } pub fn go(tcx: &ty::ctxt) { @@ -928,7 +946,7 @@ impl<'tcx> ctxt<'tcx> { sty_debug_print!( self, ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait, - ty_struct, ty_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection); + ty_struct, ty_closure, ty_tup, ty_param, ty_infer, ty_projection); println!("Substs interner: #{}", self.substs_interner.borrow().len()); println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len()); @@ -959,16 +977,9 @@ impl<'tcx> PartialEq for TyS<'tcx> { } impl<'tcx> Eq for TyS<'tcx> {} -#[cfg(stage0)] -impl<'tcx, S: Writer + Hasher> Hash for TyS<'tcx> { - fn hash(&self, s: &mut S) { - (self as *const _).hash(s) - } -} -#[cfg(not(stage0))] impl<'tcx> Hash for TyS<'tcx> { fn hash(&self, s: &mut H) { - (self as *const _).hash(s) + (self as *const TyS).hash(s) } } @@ -988,13 +999,6 @@ impl<'tcx> PartialEq for InternedTy<'tcx> { impl<'tcx> Eq for InternedTy<'tcx> {} -#[cfg(stage0)] -impl<'tcx, S: Writer + Hasher> Hash for InternedTy<'tcx> { - fn hash(&self, s: &mut S) { - self.ty.sty.hash(s) - } -} -#[cfg(not(stage0))] impl<'tcx> Hash for InternedTy<'tcx> { fn hash(&self, s: &mut H) { self.ty.sty.hash(s) @@ -1031,7 +1035,7 @@ pub fn type_has_late_bound_regions(ty: Ty) -> bool { /// /// So, for example, consider a type like the following, which has two binders: /// -/// for<'a> fn(x: for<'b> fn(&'a int, &'b int)) +/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope /// @@ -1115,16 +1119,16 @@ pub type PolyFnSig<'tcx> = Binder>; impl<'tcx> PolyFnSig<'tcx> { pub fn inputs(&self) -> ty::Binder>> { - ty::Binder(self.0.inputs.clone()) + self.map_bound_ref(|fn_sig| fn_sig.inputs.clone()) } - pub fn input(&self, index: uint) -> ty::Binder> { - ty::Binder(self.0.inputs[index]) + pub fn input(&self, index: usize) -> ty::Binder> { + self.map_bound_ref(|fn_sig| fn_sig.inputs[index]) } pub fn output(&self) -> ty::Binder> { - ty::Binder(self.0.output.clone()) + self.map_bound_ref(|fn_sig| fn_sig.output.clone()) } pub fn variadic(&self) -> bool { - self.0.variadic + self.skip_binder().variadic } } @@ -1139,7 +1143,7 @@ pub struct ParamTy { /// regions (and perhaps later types) in a higher-ranked setting. In /// particular, imagine a type like this: /// -/// for<'a> fn(for<'b> fn(&'b int, &'a int), &'a char) +/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) /// ^ ^ | | | /// | | | | | /// | +------------+ 1 | | @@ -1156,11 +1160,11 @@ pub struct ParamTy { /// count the number of binders, inside out. Some examples should help /// clarify what I mean. /// -/// Let's start with the reference type `&'b int` that is the first +/// Let's start with the reference type `&'b isize` that is the first /// argument to the inner function. This region `'b` is assigned a De /// Bruijn index of 1, meaning "the innermost binder" (in this case, a /// fn). The region `'a` that appears in the second argument type (`&'a -/// int`) would then be assigned a De Bruijn index of 2, meaning "the +/// isize`) would then be assigned a De Bruijn index of 2, meaning "the /// second-innermost binder". (These indices are written on the arrays /// in the diagram). /// @@ -1241,14 +1245,14 @@ pub enum BorrowKind { /// implicit closure bindings. It is needed when you the closure /// is borrowing or mutating a mutable referent, e.g.: /// - /// let x: &mut int = ...; + /// let x: &mut isize = ...; /// let y = || *x += 5; /// /// If we were to try to translate this closure into a more explicit /// form, we'd encounter an error with the code as written: /// - /// struct Env { x: & &mut int } - /// let x: &mut int = ...; + /// struct Env { x: & &mut isize } + /// let x: &mut isize = ...; /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn /// fn fn_ptr(env: &mut Env) { **env.x += 5; } /// @@ -1256,8 +1260,8 @@ pub enum BorrowKind { /// in an aliasable location. To solve, you'd have to translate with /// an `&mut` borrow: /// - /// struct Env { x: & &mut int } - /// let x: &mut int = ...; + /// struct Env { x: & &mut isize } + /// let x: &mut isize = ...; /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x /// fn fn_ptr(env: &mut Env) { **env.x += 5; } /// @@ -1364,11 +1368,11 @@ pub enum sty<'tcx> { /// definition and not a concrete use of it. To get the correct `ty_enum` /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in /// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as - /// well.` + /// well. ty_enum(DefId, &'tcx Substs<'tcx>), ty_uniq(Ty<'tcx>), ty_str, - ty_vec(Ty<'tcx>, Option), // Second field is length. + ty_vec(Ty<'tcx>, Option), // Second field is length. ty_ptr(mt<'tcx>), ty_rptr(&'tcx Region, mt<'tcx>), @@ -1379,19 +1383,13 @@ pub enum sty<'tcx> { ty_trait(Box>), ty_struct(DefId, &'tcx Substs<'tcx>), - ty_closure(DefId, &'tcx Region, &'tcx Substs<'tcx>), + ty_closure(DefId, &'tcx Substs<'tcx>), ty_tup(Vec>), ty_projection(ProjectionTy<'tcx>), ty_param(ParamTy), // type parameter - ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value - // and its size. Only ever used in trans. It is not necessary - // earlier since we don't need to distinguish a DST with its - // size (e.g., in a deref) vs a DST with the size elsewhere ( - // e.g., in a field). - ty_infer(InferTy), // something used only during inference/typeck ty_err, // Also only used during inference/typeck, to represent // the type of an erroneous expression (helps cut down @@ -1504,7 +1502,7 @@ impl<'tcx> PolyTraitRef<'tcx> { } /// Binder is a binder for higher-ranked lifetimes. It is part of the -/// compiler's representation for things like `for<'a> Fn(&'a int)` +/// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == /// Binder`). Note that when we skolemize, instantiate, /// erase, or otherwise "discharge" these bound regions, we change the @@ -1513,6 +1511,43 @@ impl<'tcx> PolyTraitRef<'tcx> { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct Binder(pub T); +impl Binder { + /// Skips the binder and returns the "bound" value. This is a + /// risky thing to do because it's easy to get confused about + /// debruijn indices and the like. It is usually better to + /// discharge the binder using `no_late_bound_regions` or + /// `replace_late_bound_regions` or something like + /// that. `skip_binder` is only valid when you are either + /// extracting data that has nothing to do with bound regions, you + /// are doing some sort of test that does not involve bound + /// regions, or you are being very careful about your depth + /// accounting. + /// + /// Some examples where `skip_binder` is reasonable: + /// - extracting the def-id from a PolyTraitRef; + /// - comparing the self type of a PolyTraitRef to see if it is equal to + /// a type parameter `X`, since the type `X` does not reference any regions + pub fn skip_binder(&self) -> &T { + &self.0 + } + + pub fn as_ref(&self) -> Binder<&T> { + ty::Binder(&self.0) + } + + pub fn map_bound_ref(&self, f: F) -> Binder + where F: FnOnce(&T) -> U + { + self.as_ref().map_bound(f) + } + + pub fn map_bound(self, f: F) -> Binder + where F: FnOnce(T) -> U + { + ty::Binder(f(self.0)) + } +} + #[derive(Clone, Copy, PartialEq)] pub enum IntVarValue { IntType(ast::IntTy), @@ -1544,9 +1579,9 @@ pub enum type_err<'tcx> { terr_ptr_mutability, terr_ref_mutability, terr_vec_mutability, - terr_tuple_size(expected_found), - terr_fixed_array_size(expected_found), - terr_ty_param_size(expected_found), + terr_tuple_size(expected_found), + terr_fixed_array_size(expected_found), + terr_ty_param_size(expected_found), terr_arg_count, terr_regions_does_not_outlive(Region, Region), terr_regions_not_same(Region, Region), @@ -1563,7 +1598,7 @@ pub enum type_err<'tcx> { terr_cyclic_ty, terr_convergence_mismatch(expected_found), terr_projection_name_mismatched(expected_found), - terr_projection_bounds_length(expected_found), + terr_projection_bounds_length(expected_found), } /// Bounds suitable for a named type parameter like `A` in `fn foo` @@ -1592,7 +1627,7 @@ pub type BuiltinBounds = EnumSet; #[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, Debug, Copy)] -#[repr(uint)] +#[repr(usize)] pub enum BuiltinBound { BoundSend, BoundSized, @@ -1620,10 +1655,10 @@ pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> } impl CLike for BuiltinBound { - fn to_usize(&self) -> uint { - *self as uint + fn to_usize(&self) -> usize { + *self as usize } - fn from_usize(v: uint) -> BuiltinBound { + fn from_usize(v: usize) -> BuiltinBound { unsafe { mem::transmute(v) } } } @@ -1768,7 +1803,6 @@ pub struct TypeParameterDef<'tcx> { pub def_id: ast::DefId, pub space: subst::ParamSpace, pub index: u32, - pub bounds: ParamBounds<'tcx>, pub default: Option>, pub object_lifetime_default: Option, } @@ -1786,6 +1820,9 @@ impl RegionParameterDef { pub fn to_early_bound_region(&self) -> ty::Region { ty::ReEarlyBound(self.def_id.node, self.space, self.index, self.name) } + pub fn to_bound_region(&self) -> ty::BoundRegion { + ty::BoundRegion::BrNamed(self.def_id, self.name) + } } /// Information about the formal type/lifetime parameters associated @@ -1836,6 +1873,16 @@ impl<'tcx> GenericPredicates<'tcx> { predicates: self.predicates.subst(tcx, substs), } } + + pub fn instantiate_supertrait(&self, + tcx: &ty::ctxt<'tcx>, + poly_trait_ref: &ty::PolyTraitRef<'tcx>) + -> InstantiatedPredicates<'tcx> + { + InstantiatedPredicates { + predicates: self.predicates.map(|pred| pred.subst_supertrait(tcx, poly_trait_ref)) + } + } } #[derive(Clone, PartialEq, Eq, Hash, Debug)] @@ -1859,6 +1906,93 @@ pub enum Predicate<'tcx> { Projection(PolyProjectionPredicate<'tcx>), } +impl<'tcx> Predicate<'tcx> { + /// Performs a substituion suitable for going from a + /// poly-trait-ref to supertraits that must hold if that + /// poly-trait-ref holds. This is slightly different from a normal + /// substitution in terms of what happens with bound regions. See + /// lengthy comment below for details. + pub fn subst_supertrait(&self, + tcx: &ty::ctxt<'tcx>, + trait_ref: &ty::PolyTraitRef<'tcx>) + -> ty::Predicate<'tcx> + { + // The interaction between HRTB and supertraits is not entirely + // obvious. Let me walk you (and myself) through an example. + // + // Let's start with an easy case. Consider two traits: + // + // trait Foo<'a> : Bar<'a,'a> { } + // trait Bar<'b,'c> { } + // + // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then + // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we + // knew that `Foo<'x>` (for any 'x) then we also know that + // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from + // normal substitution. + // + // In terms of why this is sound, the idea is that whenever there + // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` + // holds. So if there is an impl of `T:Foo<'a>` that applies to + // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all + // `'a`. + // + // Another example to be careful of is this: + // + // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } + // trait Bar1<'b,'c> { } + // + // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? + // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The + // reason is similar to the previous example: any impl of + // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So + // basically we would want to collapse the bound lifetimes from + // the input (`trait_ref`) and the supertraits. + // + // To achieve this in practice is fairly straightforward. Let's + // consider the more complicated scenario: + // + // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` + // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, + // where both `'x` and `'b` would have a DB index of 1. + // The substitution from the input trait-ref is therefore going to be + // `'a => 'x` (where `'x` has a DB index of 1). + // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an + // early-bound parameter and `'b' is a late-bound parameter with a + // DB index of 1. + // - If we replace `'a` with `'x` from the input, it too will have + // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` + // just as we wanted. + // + // There is only one catch. If we just apply the substitution `'a + // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will + // adjust the DB index because we substituting into a binder (it + // tries to be so smart...) resulting in `for<'x> for<'b> + // Bar1<'x,'b>` (we have no syntax for this, so use your + // imagination). Basically the 'x will have DB index of 2 and 'b + // will have DB index of 1. Not quite what we want. So we apply + // the substitution to the *contents* of the trait reference, + // rather than the trait reference itself (put another way, the + // substitution code expects equal binding levels in the values + // from the substitution and the value being substituted into, and + // this trick achieves that). + + let substs = &trait_ref.0.substs; + match *self { + Predicate::Trait(ty::Binder(ref data)) => + Predicate::Trait(ty::Binder(data.subst(tcx, substs))), + Predicate::Equate(ty::Binder(ref data)) => + Predicate::Equate(ty::Binder(data.subst(tcx, substs))), + Predicate::RegionOutlives(ty::Binder(ref data)) => + Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))), + Predicate::TypeOutlives(ty::Binder(ref data)) => + Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))), + Predicate::Projection(ty::Binder(ref data)) => + Predicate::Projection(ty::Binder(data.subst(tcx, substs))), + } + } +} + #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct TraitPredicate<'tcx> { pub trait_ref: Rc> @@ -1955,8 +2089,7 @@ impl<'tcx> ToPolyTraitRef<'tcx> for Rc> { impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - // We are just preserving the binder levels here - ty::Binder(self.0.trait_ref.clone()) + self.map_bound_ref(|trait_pred| trait_pred.trait_ref.clone()) } } @@ -2095,8 +2228,8 @@ impl<'tcx> Predicate<'tcx> { /// /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like /// `[[], [U:Bar]]`. Now if there were some particular reference -/// like `Foo`, then the `InstantiatedPredicates` would be `[[], -/// [uint:Bar]]`. +/// like `Foo`, then the `InstantiatedPredicates` would be `[[], +/// [usize:Bar]]`. #[derive(Clone, Debug)] pub struct InstantiatedPredicates<'tcx> { pub predicates: VecPerParamSpace>, @@ -2186,8 +2319,8 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> { match cx.map.find(id) { Some(ast_map::NodeImplItem(ref impl_item)) => { - match **impl_item { - ast::MethodImplItem(ref method) => { + match impl_item.node { + ast::MethodImplItem(_, ref body) => { let method_def_id = ast_util::local_def(id); match ty::impl_or_trait_item(cx, method_def_id) { MethodTraitItem(ref method_ty) => { @@ -2195,10 +2328,10 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let method_bounds = &method_ty.predicates; construct_parameter_environment( cx, - method.span, + impl_item.span, method_generics, method_bounds, - method.pe_body().id) + body.id) } TypeTraitItem(_) => { cx.sess @@ -2213,18 +2346,19 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { can't create a parameter environment \ for type impl items") } + ast::MacImplItem(_) => cx.sess.bug("unexpanded macro") } } - Some(ast_map::NodeTraitItem(trait_method)) => { - match *trait_method { - ast::RequiredMethod(ref required) => { - cx.sess.span_bug(required.span, + Some(ast_map::NodeTraitItem(trait_item)) => { + match trait_item.node { + ast::MethodTraitItem(_, None) => { + cx.sess.span_bug(trait_item.span, "ParameterEnvironment::for_item(): can't create a parameter \ environment for required trait \ methods") } - ast::ProvidedMethod(ref method) => { + ast::MethodTraitItem(_, Some(ref body)) => { let method_def_id = ast_util::local_def(id); match ty::impl_or_trait_item(cx, method_def_id) { MethodTraitItem(ref method_ty) => { @@ -2232,10 +2366,10 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let method_bounds = &method_ty.predicates; construct_parameter_environment( cx, - method.span, + trait_item.span, method_generics, method_bounds, - method.pe_body().id) + body.id) } TypeTraitItem(_) => { cx.sess @@ -2245,7 +2379,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { } } } - ast::TypeTraitItem(_) => { + ast::TypeTraitItem(..) => { cx.sess.bug("ParameterEnvironment::from_item(): \ can't create a parameter environment \ for type trait items") @@ -2295,7 +2429,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { _ => { cx.sess.bug(&format!("ParameterEnvironment::from_item(): \ `{}` is not an item", - cx.map.node_to_string(id))[]) + cx.map.node_to_string(id))) } } } @@ -2343,9 +2477,6 @@ pub struct TraitDef<'tcx> { /// implements the trait. pub generics: Generics<'tcx>, - /// The "supertrait" bounds. - pub bounds: ParamBounds<'tcx>, - pub trait_ref: Rc>, /// A list of the associated types defined in this trait. Useful @@ -2360,8 +2491,11 @@ pub struct ItemSubsts<'tcx> { pub substs: Substs<'tcx>, } -#[derive(Clone, Copy, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] pub enum ClosureKind { + // Warning: Ordering is significant here! The ordering is chosen + // because the trait Fn is a subtrait of FnMut and so in turn, and + // hence we order it so that Fn < FnMut < FnOnce. FnClosureKind, FnMutClosureKind, FnOnceClosureKind, @@ -2383,6 +2517,20 @@ impl ClosureKind { Err(err) => cx.sess.fatal(&err[..]), } } + + /// True if this a type that impls this closure kind + /// must also implement `other`. + pub fn extends(self, other: ty::ClosureKind) -> bool { + match (self, other) { + (FnClosureKind, FnClosureKind) => true, + (FnClosureKind, FnMutClosureKind) => true, + (FnClosureKind, FnOnceClosureKind) => true, + (FnMutClosureKind, FnMutClosureKind) => true, + (FnMutClosureKind, FnOnceClosureKind) => true, + (FnOnceClosureKind, FnOnceClosureKind) => true, + _ => false, + } + } } pub trait ClosureTyper<'tcx> { @@ -2423,12 +2571,12 @@ impl<'tcx> CommonTypes<'tcx> { bool: intern_ty(arena, interner, ty_bool), char: intern_ty(arena, interner, ty_char), err: intern_ty(arena, interner, ty_err), - int: intern_ty(arena, interner, ty_int(ast::TyIs(false))), + isize: intern_ty(arena, interner, ty_int(ast::TyIs)), i8: intern_ty(arena, interner, ty_int(ast::TyI8)), i16: intern_ty(arena, interner, ty_int(ast::TyI16)), i32: intern_ty(arena, interner, ty_int(ast::TyI32)), i64: intern_ty(arena, interner, ty_int(ast::TyI64)), - uint: intern_ty(arena, interner, ty_uint(ast::TyUs(false))), + usize: intern_ty(arena, interner, ty_uint(ast::TyUs)), u8: intern_ty(arena, interner, ty_uint(ast::TyU8)), u16: intern_ty(arena, interner, ty_uint(ast::TyU16)), u32: intern_ty(arena, interner, ty_uint(ast::TyU32)), @@ -2441,7 +2589,7 @@ impl<'tcx> CommonTypes<'tcx> { pub fn mk_ctxt<'tcx>(s: Session, arenas: &'tcx CtxtArenas<'tcx>, - dm: DefMap, + def_map: DefMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, freevars: RefCell, @@ -2463,16 +2611,16 @@ pub fn mk_ctxt<'tcx>(s: Session, item_variance_map: RefCell::new(DefIdMap()), variance_computed: Cell::new(false), sess: s, - def_map: dm, + def_map: def_map, region_maps: region_maps, node_types: RefCell::new(FnvHashMap()), item_substs: RefCell::new(NodeMap()), - trait_refs: RefCell::new(NodeMap()), + impl_trait_refs: RefCell::new(NodeMap()), trait_defs: RefCell::new(DefIdMap()), predicates: RefCell::new(DefIdMap()), + super_predicates: RefCell::new(DefIdMap()), object_cast_map: RefCell::new(NodeMap()), map: map, - intrinsic_defs: RefCell::new(DefIdMap()), freevars: freevars, tcache: RefCell::new(DefIdMap()), rcache: RefCell::new(FnvHashMap()), @@ -2493,12 +2641,14 @@ pub fn mk_ctxt<'tcx>(s: Session, destructor_for_type: RefCell::new(DefIdMap()), destructors: RefCell::new(DefIdSet()), trait_impls: RefCell::new(DefIdMap()), + traits_with_default_impls: RefCell::new(DefIdMap()), inherent_impls: RefCell::new(DefIdMap()), impl_items: RefCell::new(DefIdMap()), used_unsafe: RefCell::new(NodeSet()), used_mut_nodes: RefCell::new(NodeSet()), populated_external_types: RefCell::new(DefIdSet()), populated_external_traits: RefCell::new(DefIdSet()), + populated_external_primitive_impls: RefCell::new(DefIdSet()), upvar_capture_map: RefCell::new(FnvHashMap()), extern_const_statics: RefCell::new(DefIdMap()), extern_const_variants: RefCell::new(DefIdMap()), @@ -2532,6 +2682,17 @@ impl<'tcx> ctxt<'tcx> { substs } + /// Create an unsafe fn ty based on a safe fn ty. + pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { + assert_eq!(bare_fn.unsafety, ast::Unsafety::Normal); + let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy { + unsafety: ast::Unsafety::Unsafe, + abi: bare_fn.abi, + sig: bare_fn.sig.clone() + }); + ty::mk_bare_fn(self, None, unsafe_fn_ty_a) + } + pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> { if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) { return *bare_fn; @@ -2553,7 +2714,7 @@ impl<'tcx> ctxt<'tcx> { } pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { - self.closure_kinds.borrow()[def_id] + *self.closure_kinds.borrow().get(&def_id).unwrap() } pub fn closure_type(&self, @@ -2561,7 +2722,22 @@ impl<'tcx> ctxt<'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.closure_tys.borrow()[def_id].subst(self, substs) + self.closure_tys.borrow().get(&def_id).unwrap().subst(self, substs) + } + + pub fn type_parameter_def(&self, + node_id: ast::NodeId) + -> TypeParameterDef<'tcx> + { + self.ty_param_defs.borrow().get(&node_id).unwrap().clone() + } + + pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> bool { + pat_util::pat_contains_ref_binding(&self.def_map, pat) + } + + pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> bool { + pat_util::arm_contains_ref_binding(&self.def_map, arm) } } @@ -2591,7 +2767,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena>, }; debug!("Interned type: {:?} Pointer: {:?}", - ty, ty as *const _); + ty, ty as *const TyS); interner.insert(InternedTy { ty: ty }, ty); @@ -2669,8 +2845,7 @@ impl FlagComputation { } } - &ty_closure(_, region, substs) => { - self.add_region(*region); + &ty_closure(_, substs) => { self.add_substs(substs); } @@ -2700,7 +2875,7 @@ impl FlagComputation { self.add_bounds(bounds); } - &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => { + &ty_uniq(tt) | &ty_vec(tt, _) => { self.add_ty(tt) } @@ -2737,7 +2912,7 @@ impl FlagComputation { fn add_fn_sig(&mut self, fn_sig: &PolyFnSig) { let mut computation = FlagComputation::new(); - computation.add_tys(&fn_sig.0.inputs[]); + computation.add_tys(&fn_sig.0.inputs); if let ty::FnConverging(output) = fn_sig.0.output { computation.add_ty(output); @@ -2786,7 +2961,7 @@ impl FlagComputation { pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> { match tm { - ast::TyIs(_) => tcx.types.int, + ast::TyIs => tcx.types.isize, ast::TyI8 => tcx.types.i8, ast::TyI16 => tcx.types.i16, ast::TyI32 => tcx.types.i32, @@ -2796,7 +2971,7 @@ pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> { pub fn mk_mach_uint<'tcx>(tcx: &ctxt<'tcx>, tm: ast::UintTy) -> Ty<'tcx> { match tm { - ast::TyUs(_) => tcx.types.uint, + ast::TyUs => tcx.types.usize, ast::TyU8 => tcx.types.u8, ast::TyU16 => tcx.types.u16, ast::TyU32 => tcx.types.u32, @@ -2855,7 +3030,7 @@ pub fn mk_nil_ptr<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::MutImmutable}) } -pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option) -> Ty<'tcx> { +pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option) -> Ty<'tcx> { mk_t(cx, ty_vec(ty, sz)) } @@ -2875,6 +3050,10 @@ pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { mk_tup(cx, Vec::new()) } +pub fn mk_bool<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { + mk_t(cx, ty_bool) +} + pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, opt_def_id: Option, fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { @@ -2938,10 +3117,9 @@ pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId, mk_t(cx, ty_struct(struct_id, substs)) } -pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, - region: &'tcx Region, substs: &'tcx Substs<'tcx>) +pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { - mk_t(cx, ty_closure(closure_id, region, substs)) + mk_t(cx, ty_closure(closure_id, substs)) } pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> { @@ -2975,8 +3153,6 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t mk_param(cx, def.space, def.index, def.name) } -pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) } - impl<'tcx> TyS<'tcx> { /// Iterator that walks `self` and any types reachable from /// `self`, in depth-first order. Note that just walks the types @@ -2984,29 +3160,19 @@ impl<'tcx> TyS<'tcx> { /// structs or variants. For example: /// /// ```notrust - /// int => { int } - /// Foo> => { Foo>, Bar, int } - /// [int] => { [int], int } + /// isize => { isize } + /// Foo> => { Foo>, Bar, isize } + /// [isize] => { [isize], isize } /// ``` pub fn walk(&'tcx self) -> TypeWalker<'tcx> { TypeWalker::new(self) } - /// Iterator that walks types reachable from `self`, in - /// depth-first order. Note that this is a shallow walk. For - /// example: - /// - /// ```notrust - /// int => { } - /// Foo> => { Bar, int } - /// [int] => { int } - /// ``` - pub fn walk_children(&'tcx self) -> TypeWalker<'tcx> { - // Walks type reachable from `self` but not `self - let mut walker = self.walk(); - let r = walker.next(); - assert_eq!(r, Some(self)); - walker + /// Iterator that walks the immediate children of `self`. Hence + /// `Foo, u32>` yields the sequence `[Bar, u32]` + /// (but not `i32`, like `walk`). + pub fn walk_shallow(&'tcx self) -> IntoIter> { + ty_walk::walk_shallow(self) } pub fn as_opt_param_ty(&self) -> Option { @@ -3015,6 +3181,13 @@ impl<'tcx> TyS<'tcx> { _ => None, } } + + pub fn is_param(&self, space: ParamSpace, index: u32) -> bool { + match self.sty { + ty::ty_param(ref data) => data.space == space && data.idx == index, + _ => false, + } + } } pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F) @@ -3175,9 +3348,8 @@ pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty_vec(ty, _) => ty, ty_str => mk_mach_uint(cx, ast::TyU8), - ty_open(ty) => sequence_element_type(cx, ty), _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}", - ty_to_string(cx, ty))[]), + ty_to_string(cx, ty))), } } @@ -3191,7 +3363,7 @@ pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { } } -pub fn simd_size(cx: &ctxt, ty: Ty) -> uint { +pub fn simd_size(cx: &ctxt, ty: Ty) -> usize { match ty.sty { ty_struct(did, _) => { let fields = lookup_struct_fields(cx, did); @@ -3239,8 +3411,12 @@ pub fn type_is_scalar(ty: Ty) -> bool { /// Returns true if this type is a floating point type and false otherwise. pub fn type_is_floating_point(ty: Ty) -> bool { match ty.sty { - ty_float(_) => true, - _ => false, + ty_float(_) | + ty_infer(FloatVar(_)) => + true, + + _ => + false, } } @@ -3459,8 +3635,8 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { cache.insert(ty, TC::None); let result = match ty.sty { - // uint and int are ffi-unsafe - ty_uint(ast::TyUs(_)) | ty_int(ast::TyIs(_)) => { + // usize and isize are ffi-unsafe + ty_uint(ast::TyUs) | ty_int(ast::TyIs) => { TC::ReachesFfiUnsafe } @@ -3520,13 +3696,11 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { apply_lang_items(cx, did, res) } - ty_closure(did, r, substs) => { + ty_closure(did, substs) => { // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure. let param_env = ty::empty_parameter_environment(cx); let upvars = closure_upvars(¶m_env, did, substs).unwrap(); - TypeContents::union(&upvars, - |f| tc_ty(cx, &f.ty, cache)) - | borrowed_contents(*r, MutMutable) + TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache)) } ty_tup(ref tys) => { @@ -3538,7 +3712,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { let variants = substd_enum_variants(cx, did, substs); let mut res = TypeContents::union(&variants[..], |variant| { - TypeContents::union(&variant.args[], + TypeContents::union(&variant.args, |arg_ty| { tc_ty(cx, *arg_ty, cache) }) @@ -3594,12 +3768,6 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { TC::All } - ty_open(ty) => { - let result = tc_ty(cx, ty, cache); - assert!(!result.is_sized(cx)); - result.unsafe_pointer() | TC::Nonsized - } - ty_infer(_) | ty_err => { cx.sess.bug("asked to compute contents of error type"); @@ -3758,7 +3926,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool { ty_vec(_, None) => { false } - ty_uniq(typ) | ty_open(typ) => { + ty_uniq(typ) => { type_requires(cx, seen, r_ty, typ) } ty_rptr(_, ref mt) => { @@ -3835,7 +4003,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool { /// /// The ordering of the cases is significant. They are sorted so that cmp::max /// will keep the "more erroneous" of two values. -#[derive(Copy, PartialOrd, Ord, Eq, PartialEq, Debug)] +#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] pub enum Representability { Representable, ContainsRecursive, @@ -3909,7 +4077,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>) let types_a = substs_a.types.get_slice(subst::TypeSpace); let types_b = substs_b.types.get_slice(subst::TypeSpace); - let pairs = types_a.iter().zip(types_b.iter()); + let mut pairs = types_a.iter().zip(types_b.iter()); pairs.all(|(&a, &b)| same_type(a, b)) } @@ -4031,7 +4199,7 @@ pub fn type_is_fresh(ty: Ty) -> bool { pub fn type_is_uint(ty: Ty) -> bool { match ty.sty { - ty_infer(IntVar(_)) | ty_uint(ast::TyUs(_)) => true, + ty_infer(IntVar(_)) | ty_uint(ast::TyUs) => true, _ => false } } @@ -4077,7 +4245,7 @@ pub fn type_is_signed(ty: Ty) -> bool { pub fn type_is_machine(ty: Ty) -> bool { match ty.sty { - ty_int(ast::TyIs(_)) | ty_uint(ast::TyUs(_)) => false, + ty_int(ast::TyIs) | ty_uint(ast::TyUs) => false, ty_int(..) | ty_uint(..) | ty_float(..) => true, _ => false } @@ -4117,14 +4285,6 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option> { } } -pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { - ty_open(ty) => mk_rptr(cx, cx.mk_region(ReStatic), mt {ty: ty, mutbl:ast::MutImmutable}), - _ => cx.sess.bug(&format!("Trying to close a non-open type {}", - ty_to_string(cx, ty))[]) - } -} - pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty_uniq(ty) => ty, @@ -4133,14 +4293,6 @@ pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { } } -// Extract the unsized type in an open type (or just return ty if it is not open). -pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { - ty_open(ty) => ty, - _ => ty - } -} - // Returns the type of ty[i] pub fn index<'tcx>(ty: Ty<'tcx>) -> Option> { match ty.sty { @@ -4164,7 +4316,7 @@ pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option /// For an enum `t`, `variant` is None only if `t` is a univariant enum. pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, - i: uint, + i: usize, variant: Option) -> Option> { match (&ty.sty, variant) { @@ -4216,13 +4368,13 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>, } } -pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) +pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Rc> { - match cx.trait_refs.borrow().get(&id) { + match cx.impl_trait_refs.borrow().get(&id) { Some(ty) => ty.clone(), None => cx.sess.bug( - &format!("node_id_to_trait_ref: no trait ref for node `{}`", - cx.map.node_to_string(id))[]) + &format!("impl_id_to_trait_ref: no trait ref for impl `{}`", + cx.map.node_to_string(id))) } } @@ -4231,7 +4383,7 @@ pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> { Some(ty) => ty, None => cx.sess.bug( &format!("node_id_to_type: no type for node `{}`", - cx.map.node_to_string(id))[]) + cx.map.node_to_string(id))) } } @@ -4305,7 +4457,7 @@ pub fn ty_region(tcx: &ctxt, tcx.sess.span_bug( span, &format!("ty_region() invoked on an inappropriate ty: {:?}", - s)[]); + s)); } } } @@ -4327,6 +4479,9 @@ pub fn free_region_from_def(outlives_extent: region::DestructionScopeData, pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> { return node_id_to_type(cx, pat.id); } +pub fn pat_ty_opt<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Option> { + return node_id_to_type_opt(cx, pat.id); +} // Returns the type of an expression as a monotype. @@ -4337,8 +4492,8 @@ pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> { // adjustments. See `expr_ty_adjusted()` instead. // // NB (2): This type doesn't provide type parameter substitutions; e.g. if you -// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int" -// instead of "fn(ty) -> T with T = int". +// ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" +// instead of "fn(ty) -> T with T = isize". pub fn expr_ty<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> { return node_id_to_type(cx, expr.id); } @@ -4370,11 +4525,11 @@ pub fn expr_span(cx: &ctxt, id: NodeId) -> Span { Some(f) => { cx.sess.bug(&format!("Node id {} is not an expr: {:?}", id, - f)[]); + f)); } None => { cx.sess.bug(&format!("Node id {} is not present \ - in the node map", id)[]); + in the node map", id)); } } } @@ -4390,14 +4545,14 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString { cx.sess.bug( &format!("Variable id {} maps to {:?}, not local", id, - pat)[]); + pat)); } } } r => { cx.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, - r)[]); + r)); } } } @@ -4428,11 +4583,23 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, cx.sess.bug( &format!("AdjustReifyFnPointer adjustment on non-fn-item: \ {:?}", - b)[]); + b)); } } } + AdjustUnsafeFnPointer => { + match unadjusted_ty.sty { + ty::ty_bare_fn(None, b) => cx.safe_to_unsafe_fn_ty(b), + ref b => { + cx.sess.bug( + &format!("AdjustReifyFnPointer adjustment on non-fn-item: \ + {:?}", + b)); + } + } + } + AdjustDerefRef(ref adj) => { let mut adjusted_ty = unadjusted_ty; @@ -4459,7 +4626,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, {}", i, ty_to_string(cx, adjusted_ty)) - []); + ); } } } @@ -4522,7 +4689,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>, } _ => cx.sess.span_bug(span, &format!("UnsizeLength with bad sty: {:?}", - ty_to_string(cx, ty))[]) + ty_to_string(cx, ty))) }, &UnsizeStruct(box ref k, tp_index) => match ty.sty { ty_struct(did, substs) => { @@ -4534,20 +4701,23 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>, } _ => cx.sess.span_bug(span, &format!("UnsizeStruct with bad sty: {:?}", - ty_to_string(cx, ty))[]) + ty_to_string(cx, ty))) }, &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => { mk_trait(cx, principal.clone(), bounds.clone()) } + &UnsizeUpcast(target_ty) => { + target_ty + } } } pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def { match tcx.def_map.borrow().get(&expr.id) { - Some(&def) => def, + Some(def) => def.full_def(), None => { tcx.sess.span_bug(expr.span, &format!( - "no def-map entry for expr {}", expr.id)[]); + "no def-map entry for expr {}", expr.id)); } } } @@ -4564,7 +4734,7 @@ pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool { /// two kinds of rvalues is an artifact of trans which reflects how we will /// generate code for that kind of expression. See trans/expr.rs for more /// information. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum ExprKind { LvalueExpr, RvalueDpsExpr, @@ -4592,7 +4762,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { } match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { match resolve_expr(tcx, expr) { def::DefVariant(tid, vid, _) => { let variant_info = enum_variant_with_id(tcx, tid, vid); @@ -4623,7 +4793,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { def::DefFn(_, true) => RvalueDpsExpr, // Fn pointers are just scalar values. - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr, + def::DefFn(..) | def::DefMethod(..) => RvalueDatumExpr, // Note: there is actually a good case to be made that // DefArg's, particularly those of immediate type, ought to @@ -4639,7 +4809,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { expr.span, &format!("uncategorized def for expr {}: {:?}", expr.id, - def)[]); + def)); } } } @@ -4680,32 +4850,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { RvalueDpsExpr } - ast::ExprCast(..) => { - match tcx.node_types.borrow().get(&expr.id) { - Some(&ty) => { - if type_is_trait(ty) { - RvalueDpsExpr - } else { - RvalueDatumExpr - } - } - None => { - // Technically, it should not happen that the expr is not - // present within the table. However, it DOES happen - // during type check, because the final types from the - // expressions are not yet recorded in the tcx. At that - // time, though, we are only interested in knowing lvalue - // vs rvalue. It would be better to base this decision on - // the AST type in cast node---but (at the time of this - // writing) it's not easy to distinguish casts to traits - // from other casts based on the AST. This should be - // easier in the future, when casts to traits - // would like @Foo, Box, or &Foo. - RvalueDatumExpr - } - } - } - ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprRet(..) | @@ -4721,17 +4865,17 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { ast::ExprUnary(..) | ast::ExprBox(None, _) | ast::ExprAddrOf(..) | - ast::ExprBinary(..) => { + ast::ExprBinary(..) | + ast::ExprCast(..) => { RvalueDatumExpr } ast::ExprBox(Some(ref place), _) => { // Special case `Box` for now: - let definition = match tcx.def_map.borrow().get(&place.id) { - Some(&def) => def, + let def_id = match tcx.def_map.borrow().get(&place.id) { + Some(def) => def.def_id(), None => panic!("no def for place"), }; - let def_id = definition.def_id(); if tcx.lang_items.exchange_heap() == Some(def_id) { RvalueDatumExpr } else { @@ -4759,7 +4903,7 @@ pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId { } pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field]) - -> uint { + -> usize { let mut i = 0; for f in fields { if f.name == name { return i; } i += 1; } tcx.sess.bug(&format!( @@ -4767,11 +4911,11 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field]) token::get_name(name), fields.iter() .map(|f| token::get_name(f.name).to_string()) - .collect::>())[]); + .collect::>())); } pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem]) - -> Option { + -> Option { trait_items.iter().position(|m| m.name() == id) } @@ -4813,7 +4957,6 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String { } } ty_err => "type error".to_string(), - ty_open(_) => "opened DST".to_string(), } } @@ -4995,39 +5138,23 @@ pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option { pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> Vec>> { if is_local(id) { - match cx.map.find(id.node) { - Some(ast_map::NodeItem(item)) => { - match item.node { - ItemTrait(_, _, _, ref ms) => { - let (_, p) = - ast_util::split_trait_methods(&ms[..]); - p.iter() - .map(|m| { - match impl_or_trait_item( - cx, - ast_util::local_def(m.id)) { - MethodTraitItem(m) => m, - TypeTraitItem(_) => { - cx.sess.bug("provided_trait_methods(): \ - split_trait_methods() put \ - associated types in the \ - provided method bucket?!") - } - } - }).collect() - } - _ => { - cx.sess.bug(&format!("provided_trait_methods: `{:?}` is \ - not a trait", - id)[]) + if let ItemTrait(_, _, _, ref ms) = cx.map.expect_item(id.node).node { + ms.iter().filter_map(|ti| { + if let ast::MethodTraitItem(_, Some(_)) = ti.node { + match impl_or_trait_item(cx, ast_util::local_def(ti.id)) { + MethodTraitItem(m) => Some(m), + TypeTraitItem(_) => { + cx.sess.bug("provided_trait_methods(): \ + associated type found from \ + looking up ProvidedMethod?!") + } } + } else { + None } - } - _ => { - cx.sess.bug(&format!("provided_trait_methods: `{:?}` is not a \ - trait", - id)[]) - } + }).collect() + } else { + cx.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id)) } } else { csearch::get_provided_trait_methods(cx, id) @@ -5060,7 +5187,7 @@ fn lookup_locally_or_in_crate_store(descr: &str, v } -pub fn trait_item<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId, idx: uint) +pub fn trait_item<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId, idx: usize) -> ImplOrTraitItem<'tcx> { let method_def_id = (*ty::trait_item_def_ids(cx, trait_did))[idx].def_id(); impl_or_trait_item(cx, method_def_id) @@ -5135,10 +5262,10 @@ pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool { pub fn associated_type_parameter_index(cx: &ctxt, trait_def: &TraitDef, associated_type_id: ast::DefId) - -> uint { + -> usize { for type_parameter_def in trait_def.generics.types.iter() { if type_parameter_def.def_id == associated_type_id { - return type_parameter_def.index as uint + return type_parameter_def.index as usize } } cx.sess.bug("couldn't find associated type parameter index") @@ -5159,22 +5286,16 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) memoized(&cx.impl_trait_cache, id, |id: ast::DefId| { if id.krate == ast::LOCAL_CRATE { debug!("(impl_trait_ref) searching for trait impl {:?}", id); - match cx.map.find(id.node) { - Some(ast_map::NodeItem(item)) => { - match item.node { - ast::ItemImpl(_, _, _, ref opt_trait, _, _) => { - match opt_trait { - &Some(ref t) => { - let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id); - Some(trait_ref) - } - &None => None - } - } - _ => None + if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) { + match item.node { + ast::ItemImpl(_, _, _, Some(_), _, _) | + ast::ItemDefaultImpl(..) => { + Some(ty::impl_id_to_trait_ref(cx, id.node)) } + _ => None } - _ => None + } else { + None } } else { csearch::get_impl_trait(cx, id) @@ -5183,10 +5304,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) } pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId { - let def = *tcx.def_map.borrow() - .get(&tr.ref_id) - .expect("no def-map entry for trait"); - def.def_id() + tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id() } pub fn try_add_builtin_trait( @@ -5212,7 +5330,7 @@ pub fn ty_to_def_id(ty: Ty) -> Option { Some(tt.principal_def_id()), ty_struct(id, _) | ty_enum(id, _) | - ty_closure(id, _, _) => + ty_closure(id, _) => Some(id), _ => None @@ -5262,7 +5380,7 @@ impl<'tcx> VariantInfo<'tcx> { }; }, ast::StructVariantKind(ref struct_def) => { - let fields: &[StructField] = &struct_def.fields[]; + let fields: &[StructField] = &struct_def.fields; assert!(fields.len() > 0); @@ -5312,7 +5430,7 @@ pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String { with_path(cx, id, |path| ast_map::path_to_string(path)).to_string() } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum DtorKind { NoDtor, TraitDtor(DefId, bool) @@ -5357,7 +5475,7 @@ pub fn with_path(cx: &ctxt, id: ast::DefId, f: F) -> T where if id.krate == ast::LOCAL_CRATE { cx.map.with_path(id.node, f) } else { - f(csearch::get_item_path(cx, id).iter().cloned().chain(None)) + f(csearch::get_item_path(cx, id).iter().cloned().chain(LinkedPath::empty())) } } @@ -5372,54 +5490,268 @@ pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool { } } +trait IntTypeExt { + fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>; + fn i64_to_disr(&self, val: i64) -> Option; + fn u64_to_disr(&self, val: u64) -> Option; + fn disr_incr(&self, val: Disr) -> Option; + fn disr_string(&self, val: Disr) -> String; + fn disr_wrap_incr(&self, val: Option) -> Disr; +} + +impl IntTypeExt for attr::IntType { + fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> { + match *self { + SignedInt(ast::TyI8) => cx.types.i8, + SignedInt(ast::TyI16) => cx.types.i16, + SignedInt(ast::TyI32) => cx.types.i32, + SignedInt(ast::TyI64) => cx.types.i64, + SignedInt(ast::TyIs) => cx.types.isize, + UnsignedInt(ast::TyU8) => cx.types.u8, + UnsignedInt(ast::TyU16) => cx.types.u16, + UnsignedInt(ast::TyU32) => cx.types.u32, + UnsignedInt(ast::TyU64) => cx.types.u64, + UnsignedInt(ast::TyUs) => cx.types.usize, + } + } + + fn i64_to_disr(&self, val: i64) -> Option { + match *self { + SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), + SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), + SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), + SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), + UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), + UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), + UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), + UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + fn u64_to_disr(&self, val: u64) -> Option { + match *self { + SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), + SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), + SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), + SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), + UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), + UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), + UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), + UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + fn disr_incr(&self, val: Disr) -> Option { + macro_rules! add1 { + ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) } + } + match *self { + // SignedInt repr means we *want* to reinterpret the bits + // treating the highest bit of Disr as a sign-bit, so + // cast to i64 before range-checking. + SignedInt(ast::TyI8) => add1!((val as i64).to_i8()), + SignedInt(ast::TyI16) => add1!((val as i64).to_i16()), + SignedInt(ast::TyI32) => add1!((val as i64).to_i32()), + SignedInt(ast::TyI64) => add1!(Some(val as i64)), + + UnsignedInt(ast::TyU8) => add1!(val.to_u8()), + UnsignedInt(ast::TyU16) => add1!(val.to_u16()), + UnsignedInt(ast::TyU32) => add1!(val.to_u32()), + UnsignedInt(ast::TyU64) => add1!(Some(val)), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + // This returns a String because (1.) it is only used for + // rendering an error message and (2.) a string can represent the + // full range from `i64::MIN` through `u64::MAX`. + fn disr_string(&self, val: Disr) -> String { + match *self { + SignedInt(ast::TyI8) => format!("{}", val as i8 ), + SignedInt(ast::TyI16) => format!("{}", val as i16), + SignedInt(ast::TyI32) => format!("{}", val as i32), + SignedInt(ast::TyI64) => format!("{}", val as i64), + UnsignedInt(ast::TyU8) => format!("{}", val as u8 ), + UnsignedInt(ast::TyU16) => format!("{}", val as u16), + UnsignedInt(ast::TyU32) => format!("{}", val as u32), + UnsignedInt(ast::TyU64) => format!("{}", val as u64), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } + + fn disr_wrap_incr(&self, val: Option) -> Disr { + macro_rules! add1 { + ($e:expr) => { ($e).wrapping_add(1) as Disr } + } + let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE); + match *self { + SignedInt(ast::TyI8) => add1!(val as i8 ), + SignedInt(ast::TyI16) => add1!(val as i16), + SignedInt(ast::TyI32) => add1!(val as i32), + SignedInt(ast::TyI64) => add1!(val as i64), + UnsignedInt(ast::TyU8) => add1!(val as u8 ), + UnsignedInt(ast::TyU16) => add1!(val as u16), + UnsignedInt(ast::TyU32) => add1!(val as u32), + UnsignedInt(ast::TyU64) => add1!(val as u64), + + UnsignedInt(ast::TyUs) | + SignedInt(ast::TyIs) => unreachable!(), + } + } +} + +/// Returns `(normalized_type, ty)`, where `normalized_type` is the +/// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8}, +/// and `ty` is the original type (i.e. may include `isize` or +/// `usize`). +pub fn enum_repr_type<'tcx>(cx: &ctxt<'tcx>, + opt_hint: Option<&attr::ReprAttr>) + -> (attr::IntType, Ty<'tcx>) +{ + let repr_type = match opt_hint { + // Feed in the given type + Some(&attr::ReprInt(_, int_t)) => int_t, + // ... but provide sensible default if none provided + // + // NB. Historically `fn enum_variants` generate i64 here, while + // rustc_typeck::check would generate isize. + _ => SignedInt(ast::TyIs), + }; + + let repr_type_ty = repr_type.to_ty(cx); + let repr_type = match repr_type { + SignedInt(ast::TyIs) => + SignedInt(cx.sess.target.int_type), + UnsignedInt(ast::TyUs) => + UnsignedInt(cx.sess.target.uint_type), + other => other + }; + + (repr_type, repr_type_ty) +} + +fn report_discrim_overflow(cx: &ctxt, + variant_span: Span, + variant_name: &str, + repr_type: attr::IntType, + prev_val: Disr) { + let computed_value = repr_type.disr_wrap_incr(Some(prev_val)); + let computed_value = repr_type.disr_string(computed_value); + let prev_val = repr_type.disr_string(prev_val); + let repr_type = repr_type.to_ty(cx).user_string(cx); + span_err!(cx.sess, variant_span, E0370, + "enum discriminant overflowed on value after {}: {}; \ + set explicitly via {} = {} if that is desired outcome", + prev_val, repr_type, variant_name, computed_value); +} + +// This computes the discriminant values for the sequence of Variants +// attached to a particular enum, taking into account the #[repr] (if +// any) provided via the `opt_hint`. +fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>, + vs: &'tcx [P], + opt_hint: Option<&attr::ReprAttr>) + -> Vec>> { + let mut variants: Vec> = Vec::new(); + let mut prev_disr_val: Option = None; + + let (repr_type, repr_type_ty) = ty::enum_repr_type(cx, opt_hint); + + for v in vs { + // If the discriminant value is specified explicitly in the + // enum, check whether the initialization expression is valid, + // otherwise use the last value plus one. + let current_disr_val; + + // This closure marks cases where, when an error occurs during + // the computation, attempt to assign a (hopefully) fresh + // value to avoid spurious error reports downstream. + let attempt_fresh_value = move || -> Disr { + repr_type.disr_wrap_incr(prev_disr_val) + }; + + match v.node.disr_expr { + Some(ref e) => { + debug!("disr expr, checking {}", pprust::expr_to_string(&**e)); + + // check_expr (from check_const pass) doesn't guarantee + // that the expression is in a form that eval_const_expr can + // handle, so we may still get an internal compiler error + // + // pnkfelix: The above comment was transcribed from + // the version of this code taken from rustc_typeck. + // Presumably the implication is that we need to deal + // with such ICE's as they arise. + // + // Since this can be called from `ty::enum_variants` + // anyway, best thing is to make `eval_const_expr` + // more robust (on case-by-case basis). + + match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) { + Ok(const_eval::const_int(val)) => current_disr_val = val as Disr, + Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr, + Ok(_) => { + span_err!(cx.sess, e.span, E0079, + "expected signed integer constant"); + current_disr_val = attempt_fresh_value(); + } + Err(ref err) => { + span_err!(cx.sess, err.span, E0080, + "constant evaluation error: {}", + err.description()); + current_disr_val = attempt_fresh_value(); + } + } + }, + None => { + current_disr_val = match prev_disr_val { + Some(prev_disr_val) => { + if let Some(v) = repr_type.disr_incr(prev_disr_val) { + v + } else { + report_discrim_overflow(cx, v.span, v.node.name.as_str(), + repr_type, prev_disr_val); + attempt_fresh_value() + } + } + None => ty::INITIAL_DISCRIMINANT_VALUE + } + } + } + + let variant_info = Rc::new(VariantInfo::from_ast_variant(cx, &**v, current_disr_val)); + prev_disr_val = Some(current_disr_val); + + variants.push(variant_info); + } + + return variants; +} + pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> Rc>>> { memoized(&cx.enum_var_cache, id, |id: ast::DefId| { if ast::LOCAL_CRATE != id.krate { Rc::new(csearch::get_enum_variants(cx, id)) } else { - /* - Although both this code and check_enum_variants in typeck/check - call eval_const_expr, it should never get called twice for the same - expr, since check_enum_variants also updates the enum_var_cache - */ match cx.map.get(id.node) { ast_map::NodeItem(ref item) => { match item.node { ast::ItemEnum(ref enum_definition, _) => { - let mut last_discriminant: Option = None; - Rc::new(enum_definition.variants.iter().map(|variant| { - - let mut discriminant = match last_discriminant { - Some(val) => val + 1, - None => INITIAL_DISCRIMINANT_VALUE - }; - - if let Some(ref e) = variant.node.disr_expr { - // Preserve all values, and prefer signed. - let ty = Some(cx.types.i64); - match const_eval::eval_const_expr_partial(cx, &**e, ty) { - Ok(const_eval::const_int(val)) => { - discriminant = val as Disr; - } - Ok(const_eval::const_uint(val)) => { - discriminant = val as Disr; - } - Ok(_) => { - span_err!(cx.sess, e.span, E0304, - "expected signed integer constant"); - } - Err(err) => { - span_err!(cx.sess, e.span, E0305, - "expected constant: {}", err); - } - } - }; - - last_discriminant = Some(discriminant); - Rc::new(VariantInfo::from_ast_variant(cx, &**variant, - discriminant)) - }).collect()) + Rc::new(compute_enum_variants( + cx, + &enum_definition.variants, + lookup_repr_hints(cx, id).get(0))) } _ => { cx.sess.bug("enum_variants: id not bound to an enum") @@ -5463,7 +5795,7 @@ pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) }) } -/// Given the did of a trait, returns its full set of predicates. +/// Given the did of an item, returns its full set of predicates. pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) -> GenericPredicates<'tcx> { @@ -5473,117 +5805,14 @@ pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) }) } -/// Given a reference to a trait, returns the "superbounds" declared -/// on the trait, with appropriate substitutions applied. Basically, -/// this applies a filter to the where clauses on the trait, returning -/// those that have the form: -/// -/// Self : SuperTrait<...> -/// Self : 'region -pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>, - trait_ref: &PolyTraitRef<'tcx>) - -> Vec> +/// Given the did of a trait, returns its superpredicates. +pub fn lookup_super_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) + -> GenericPredicates<'tcx> { - let trait_def = lookup_trait_def(tcx, trait_ref.def_id()); - - debug!("bounds_for_trait_ref(trait_def={:?}, trait_ref={:?})", - trait_def.repr(tcx), trait_ref.repr(tcx)); - - // The interaction between HRTB and supertraits is not entirely - // obvious. Let me walk you (and myself) through an example. - // - // Let's start with an easy case. Consider two traits: - // - // trait Foo<'a> : Bar<'a,'a> { } - // trait Bar<'b,'c> { } - // - // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then - // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we - // knew that `Foo<'x>` (for any 'x) then we also know that - // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from - // normal substitution. - // - // In terms of why this is sound, the idea is that whenever there - // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` - // holds. So if there is an impl of `T:Foo<'a>` that applies to - // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all - // `'a`. - // - // Another example to be careful of is this: - // - // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } - // trait Bar1<'b,'c> { } - // - // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? - // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The - // reason is similar to the previous example: any impl of - // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So - // basically we would want to collapse the bound lifetimes from - // the input (`trait_ref`) and the supertraits. - // - // To achieve this in practice is fairly straightforward. Let's - // consider the more complicated scenario: - // - // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` - // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, - // where both `'x` and `'b` would have a DB index of 1. - // The substitution from the input trait-ref is therefore going to be - // `'a => 'x` (where `'x` has a DB index of 1). - // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an - // early-bound parameter and `'b' is a late-bound parameter with a - // DB index of 1. - // - If we replace `'a` with `'x` from the input, it too will have - // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` - // just as we wanted. - // - // There is only one catch. If we just apply the substitution `'a - // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will - // adjust the DB index because we substituting into a binder (it - // tries to be so smart...) resulting in `for<'x> for<'b> - // Bar1<'x,'b>` (we have no syntax for this, so use your - // imagination). Basically the 'x will have DB index of 2 and 'b - // will have DB index of 1. Not quite what we want. So we apply - // the substitution to the *contents* of the trait reference, - // rather than the trait reference itself (put another way, the - // substitution code expects equal binding levels in the values - // from the substitution and the value being substituted into, and - // this trick achieves that). - - // Carefully avoid the binder introduced by each trait-ref by - // substituting over the substs, not the trait-refs themselves, - // thus achieving the "collapse" described in the big comment - // above. - let trait_bounds: Vec<_> = - trait_def.bounds.trait_bounds - .iter() - .map(|poly_trait_ref| ty::Binder(poly_trait_ref.0.subst(tcx, trait_ref.substs()))) - .collect(); - - let projection_bounds: Vec<_> = - trait_def.bounds.projection_bounds - .iter() - .map(|poly_proj| ty::Binder(poly_proj.0.subst(tcx, trait_ref.substs()))) - .collect(); - - debug!("bounds_for_trait_ref: trait_bounds={} projection_bounds={}", - trait_bounds.repr(tcx), - projection_bounds.repr(tcx)); - - // The region bounds and builtin bounds do not currently introduce - // binders so we can just substitute in a straightforward way here. - let region_bounds = - trait_def.bounds.region_bounds.subst(tcx, trait_ref.substs()); - let builtin_bounds = - trait_def.bounds.builtin_bounds.subst(tcx, trait_ref.substs()); - - let bounds = ty::ParamBounds { - trait_bounds: trait_bounds, - region_bounds: region_bounds, - builtin_bounds: builtin_bounds, - projection_bounds: projection_bounds, - }; - - predicates(tcx, trait_ref.self_ty(), &bounds) + memoized(&cx.super_predicates, did, |did: DefId| { + assert!(did.krate != ast::LOCAL_CRATE); + csearch::get_super_predicates(cx, did) + }) } pub fn predicates<'tcx>( @@ -5621,10 +5850,9 @@ pub fn predicates<'tcx>( /// Get the attributes of a definition. pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId) - -> CowVec<'tcx, ast::Attribute> { + -> Cow<'tcx, [ast::Attribute]> { if is_local(did) { - let item = tcx.map.expect_item(did.node); - Cow::Borrowed(&item.attrs[]) + Cow::Borrowed(tcx.map.attrs(did.node)) } else { Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did)) } @@ -5669,9 +5897,7 @@ 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 = tcache.entry(id).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(csearch::get_field_type(tcx, struct_id, id))); - pty.ty + tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty }; ty.subst(tcx, substs) } @@ -5686,7 +5912,7 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec { _ => { cx.sess.bug( &format!("ID not mapped to struct fields: {}", - cx.map.node_to_string(did.node))[]); + cx.map.node_to_string(did.node))); } } } else { @@ -5719,7 +5945,7 @@ pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tc pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec> { v.iter().enumerate().map(|(i, &f)| { field { - name: token::intern(&i.to_string()[]), + name: token::intern(&i.to_string()), mt: mt { ty: f, mutbl: MutImmutable @@ -5792,113 +6018,39 @@ pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>, } } -pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool { - #![allow(non_upper_case_globals)] - static tycat_other: int = 0; - static tycat_bool: int = 1; - static tycat_char: int = 2; - static tycat_int: int = 3; - static tycat_float: int = 4; - static tycat_raw_ptr: int = 6; - - static opcat_add: int = 0; - static opcat_sub: int = 1; - static opcat_mult: int = 2; - static opcat_shift: int = 3; - static opcat_rel: int = 4; - static opcat_eq: int = 5; - static opcat_bit: int = 6; - static opcat_logic: int = 7; - static opcat_mod: int = 8; - - fn opcat(op: ast::BinOp) -> int { - match op.node { - ast::BiAdd => opcat_add, - ast::BiSub => opcat_sub, - ast::BiMul => opcat_mult, - ast::BiDiv => opcat_mult, - ast::BiRem => opcat_mod, - ast::BiAnd => opcat_logic, - ast::BiOr => opcat_logic, - ast::BiBitXor => opcat_bit, - ast::BiBitAnd => opcat_bit, - ast::BiBitOr => opcat_bit, - ast::BiShl => opcat_shift, - ast::BiShr => opcat_shift, - ast::BiEq => opcat_eq, - ast::BiNe => opcat_eq, - ast::BiLt => opcat_rel, - ast::BiLe => opcat_rel, - ast::BiGe => opcat_rel, - ast::BiGt => opcat_rel - } - } - - fn tycat<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> int { - if type_is_simd(cx, ty) { - return tycat(cx, simd_type(cx, ty)) - } - match ty.sty { - ty_char => tycat_char, - ty_bool => tycat_bool, - ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int, - ty_float(_) | ty_infer(FloatVar(_)) => tycat_float, - ty_ptr(_) => tycat_raw_ptr, - _ => tycat_other - } - } - - static t: bool = true; - static f: bool = false; - - let tbl = [ - // +, -, *, shift, rel, ==, bit, logic, mod - /*other*/ [f, f, f, f, f, f, f, f, f], - /*bool*/ [f, f, f, f, t, t, t, t, f], - /*char*/ [f, f, f, f, t, t, f, f, f], - /*int*/ [t, t, t, t, t, t, t, f, t], - /*float*/ [t, t, t, f, t, t, f, f, f], - /*bot*/ [t, t, t, t, t, t, t, t, t], - /*raw ptr*/ [f, f, f, f, t, t, f, f, f]]; - - return tbl[tycat(cx, ty) as uint ][opcat(op) as uint]; -} - // Returns the repeat count for a repeating vector expression. -pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint { - match const_eval::eval_const_expr_partial(tcx, count_expr, Some(tcx.types.uint)) { +pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize { + match const_eval::eval_const_expr_partial(tcx, count_expr, Some(tcx.types.usize)) { Ok(val) => { let found = match val { - const_eval::const_uint(count) => return count as uint, - const_eval::const_int(count) if count >= 0 => return count as uint, - const_eval::const_int(_) => - "negative integer", - const_eval::const_float(_) => - "float", - const_eval::const_str(_) => - "string", - const_eval::const_bool(_) => - "boolean", - const_eval::const_binary(_) => - "binary array" + const_eval::const_uint(count) => return count as usize, + const_eval::const_int(count) if count >= 0 => return count as usize, + const_eval::const_int(_) => "negative integer", + const_eval::const_float(_) => "float", + const_eval::const_str(_) => "string", + const_eval::const_bool(_) => "boolean", + const_eval::const_binary(_) => "binary array", + const_eval::Struct(..) => "struct", + const_eval::Tuple(_) => "tuple" }; span_err!(tcx.sess, count_expr.span, E0306, "expected positive integer for repeat count, found {}", found); } - Err(_) => { + Err(err) => { + let err_description = err.description(); let found = match count_expr.node { - ast::ExprPath(ast::Path { + ast::ExprPath(None, ast::Path { global: false, ref segments, .. }) if segments.len() == 1 => - "variable", + format!("{}", "found variable"), _ => - "non-constant expression" + format!("but {}", err_description), }; span_err!(tcx.sess, count_expr.span, E0307, - "expected constant integer for repeat count, found {}", + "expected constant integer for repeat count, {}", found); } } @@ -5979,19 +6131,25 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>, .collect() } -pub fn get_tydesc_ty<'tcx>(tcx: &ctxt<'tcx>) -> Result, String> { - tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| { - tcx.intrinsic_defs.borrow().get(&tydesc_lang_item).cloned() - .expect("Failed to resolve TyDesc") - }) -} - pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc { lookup_locally_or_in_crate_store( "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(), || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id))) } +pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool { + populate_implementations_for_trait_if_necessary(tcx, trait_def_id); + tcx.traits_with_default_impls.borrow().contains_key(&trait_def_id) +} + +/// Records a trait-to-implementation mapping. +pub fn record_trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) { + // We're using the latest implementation found as the reference one. + // Duplicated implementations are caught and reported in the coherence + // step. + tcx.traits_with_default_impls.borrow_mut().insert(trait_def_id, ()); +} + /// Records a trait-to-implementation mapping. pub fn record_trait_implementation(tcx: &ctxt, trait_def_id: DefId, @@ -6008,6 +6166,25 @@ pub fn record_trait_implementation(tcx: &ctxt, tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id)))); } +/// Load primitive inherent implementations if necessary +pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt, lang_def_id: ast::DefId) { + if lang_def_id.krate == LOCAL_CRATE { + return + } + if tcx.populated_external_primitive_impls.borrow().contains(&lang_def_id) { + return + } + + debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", lang_def_id); + + let impl_items = csearch::get_impl_items(&tcx.sess.cstore, lang_def_id); + + // Store the implementation info. + tcx.impl_items.borrow_mut().insert(lang_def_id, impl_items); + + tcx.populated_external_primitive_impls.borrow_mut().insert(lang_def_id); +} + /// Populates the type context with all the implementations for the given type /// if necessary. pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, @@ -6022,8 +6199,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt, debug!("populate_implementations_for_type_if_necessary: searching for {:?}", type_id); let mut inherent_impls = Vec::new(); - csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, - |impl_def_id| { + csearch::each_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| { let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id); // Record the trait->implementation mappings, if applicable. @@ -6069,12 +6245,16 @@ pub fn populate_implementations_for_trait_if_necessary( if trait_id.krate == LOCAL_CRATE { return } + if tcx.populated_external_traits.borrow().contains(&trait_id) { return } - csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id, - |implementation_def_id| { + if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) { + record_trait_has_default_impl(tcx, trait_id); + } + + csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id, |implementation_def_id| { let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id); // Record the trait->implementation mapping. @@ -6088,8 +6268,8 @@ pub fn populate_implementations_for_trait_if_necessary( MethodTraitItem(method) => { if let Some(source) = method.provided_source { tcx.provided_method_sources - .borrow_mut() - .insert(method_def_id, source); + .borrow_mut() + .insert(method_def_id, source); } } TypeTraitItem(_) => {} @@ -6299,16 +6479,14 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) - hash!(p.idx); hash!(token::get_name(p.name)); } - ty_open(_) => byte!(22), ty_infer(_) => unreachable!(), - ty_err => byte!(23), - ty_closure(d, r, _) => { - byte!(24); + ty_err => byte!(21), + ty_closure(d, _) => { + byte!(22); did(state, d); - region(state, *r); } ty_projection(ref data) => { - byte!(25); + byte!(23); did(state, data.trait_ref.def_id); hash!(token::get_name(data.item_name)); } @@ -6518,7 +6696,7 @@ impl<'tcx> ctxt<'tcx> { } pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { - Some(self.upvar_capture_map.borrow()[upvar_id].clone()) + Some(self.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone()) } } @@ -6619,8 +6797,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, ty_struct(_, substs) => { accum_substs(accumulator, substs); } - ty_closure(_, region, substs) => { - accumulator.push(*region); + ty_closure(_, substs) => { accum_substs(accumulator, substs); } ty_bool | @@ -6637,7 +6814,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, ty_projection(_) | ty_param(_) | ty_infer(_) | - ty_open(_) | ty_err => { } } @@ -6689,6 +6865,7 @@ impl<'tcx> AutoAdjustment<'tcx> { pub fn is_identity(&self) -> bool { match *self { AdjustReifyFnPointer(..) => false, + AdjustUnsafeFnPointer(..) => false, AdjustDerefRef(ref r) => r.is_identity(), } } @@ -6717,7 +6894,7 @@ pub fn liberate_late_bound_regions<'tcx, T>( pub fn count_late_bound_regions<'tcx, T>( tcx: &ty::ctxt<'tcx>, value: &Binder) - -> uint + -> usize where T : TypeFoldable<'tcx> + Repr<'tcx> { let (_, skol_map) = replace_late_bound_regions(tcx, value, |_| ty::ReStatic); @@ -6733,6 +6910,30 @@ pub fn binds_late_bound_regions<'tcx, T>( count_late_bound_regions(tcx, value) > 0 } +/// Flattens two binding levels into one. So `for<'a> for<'b> Foo` +/// becomes `for<'a,'b> Foo`. +pub fn flatten_late_bound_regions<'tcx, T>( + tcx: &ty::ctxt<'tcx>, + bound2_value: &Binder>) + -> Binder + where T: TypeFoldable<'tcx> + Repr<'tcx> +{ + let bound0_value = bound2_value.skip_binder().skip_binder(); + let value = ty_fold::fold_regions(tcx, bound0_value, |region, current_depth| { + match region { + ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => { + // should be true if no escaping regions from bound2_value + assert!(debruijn.depth - current_depth <= 1); + ty::ReLateBound(DebruijnIndex::new(current_depth), br) + } + _ => { + region + } + } + }); + Binder(value) +} + pub fn no_late_bound_regions<'tcx, T>( tcx: &ty::ctxt<'tcx>, value: &Binder) @@ -6763,8 +6964,8 @@ pub fn erase_late_bound_regions<'tcx, T>( /// /// The chief purpose of this function is to canonicalize regions so that two /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become -/// structurally identical. For example, `for<'a, 'b> fn(&'a int, &'b int)` and -/// `for<'a, 'b> fn(&'b int, &'a int)` will become identical after anonymization. +/// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and +/// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. pub fn anonymize_late_bound_regions<'tcx, T>( tcx: &ctxt<'tcx>, sig: &Binder) @@ -6797,9 +6998,7 @@ 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 => { - let region = - * map.entry(br).get().unwrap_or_else( - |vacant_entry| vacant_entry.insert(mapf(br))); + let region = *map.entry(br).or_insert_with(|| mapf(br)); if let ty::ReLateBound(debruijn1, br) = region { // If the callback returns a late-bound region, @@ -6838,6 +7037,9 @@ impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> { AdjustReifyFnPointer(def_id) => { format!("AdjustReifyFnPointer({})", def_id.repr(tcx)) } + AdjustUnsafeFnPointer => { + format!("AdjustUnsafeFnPointer") + } AdjustDerefRef(ref data) => { data.repr(tcx) } @@ -6851,6 +7053,7 @@ impl<'tcx> Repr<'tcx> for UnsizeKind<'tcx> { UnsizeLength(n) => format!("UnsizeLength({})", n), UnsizeStruct(ref k, n) => format!("UnsizeStruct({},{})", k.repr(tcx), n), UnsizeVtable(ref a, ref b) => format!("UnsizeVtable({},{})", a.repr(tcx), b.repr(tcx)), + UnsizeUpcast(ref a) => format!("UnsizeUpcast({})", a.repr(tcx)), } } } @@ -6951,7 +7154,7 @@ pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref.substs.clone().with_method(meth_tps, meth_regions) } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum CopyImplementationError { FieldDoesNotImplementCopy(ast::Name), VariantDoesNotImplementCopy(ast::Name), @@ -7067,6 +7270,12 @@ impl<'tcx> RegionEscape for Predicate<'tcx> { } } +impl<'tcx,P:RegionEscape> RegionEscape for traits::Obligation<'tcx,P> { + fn has_regions_escaping_depth(&self, depth: u32) -> bool { + self.predicate.has_regions_escaping_depth(depth) + } +} + impl<'tcx> RegionEscape for TraitRef<'tcx> { fn has_regions_escaping_depth(&self, depth: u32) -> bool { self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) || diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 5e46ce08e4..5f77574f65 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -39,6 +39,8 @@ use middle::subst::VecPerParamSpace; use middle::ty::{self, Ty}; use middle::traits; use std::rc::Rc; +use syntax::abi; +use syntax::ast; use syntax::owned_slice::OwnedSlice; use util::ppaux::Repr; @@ -47,7 +49,7 @@ use util::ppaux::Repr; /// The TypeFoldable trait is implemented for every type that can be folded. /// Basically, every type that has a corresponding method in TypeFolder. -pub trait TypeFoldable<'tcx> { +pub trait TypeFoldable<'tcx>: Repr<'tcx> + Clone { fn fold_with>(&self, folder: &mut F) -> Self; } @@ -149,12 +151,20 @@ pub trait TypeFolder<'tcx> : Sized { // can easily refactor the folding into the TypeFolder trait as // needed. -impl<'tcx> TypeFoldable<'tcx> for () { - fn fold_with>(&self, _: &mut F) -> () { - () +macro_rules! CopyImpls { + ($($ty:ty),+) => { + $( + impl<'tcx> TypeFoldable<'tcx> for $ty { + fn fold_with>(&self, _: &mut F) -> $ty { + *self + } + } + )+ } } +CopyImpls! { (), ast::Unsafety, abi::Abi } + impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { fn fold_with>(&self, folder: &mut F) -> (T, U) { (self.0.fold_with(folder), self.1.fold_with(folder)) @@ -377,7 +387,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { def_id: self.def_id, space: self.space, index: self.index, - bounds: self.bounds.fold_with(folder), default: self.default.fold_with(folder), object_lifetime_default: self.object_lifetime_default.fold_with(folder), } @@ -481,6 +490,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnsizeKind<'tcx> { }, self_ty.fold_with(folder)) } + ty::UnsizeUpcast(t) => ty::UnsizeUpcast(t.fold_with(folder)), } } } @@ -507,6 +517,15 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData< } } +impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData { + fn fold_with>(&self, folder: &mut F) -> traits::VtableDefaultImplData { + traits::VtableDefaultImplData { + trait_def_id: self.trait_def_id, + nested: self.nested.fold_with(folder), + } + } +} + impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData { fn fold_with>(&self, folder: &mut F) -> traits::VtableBuiltinData { traits::VtableBuiltinData { @@ -519,6 +538,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> fn fold_with>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> { match *self { traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)), + traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)), traits::VtableClosure(d, ref s) => { traits::VtableClosure(d, s.fold_with(folder)) } @@ -535,7 +555,8 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> { fn fold_with>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> { traits::VtableObjectData { - object_ty: self.object_ty.fold_with(folder) + object_ty: self.object_ty.fold_with(folder), + upcast_trait_ref: self.upcast_trait_ref.fold_with(folder), } } } @@ -616,9 +637,6 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty::ty_vec(typ, sz) => { ty::ty_vec(typ.fold_with(this), sz) } - ty::ty_open(typ) => { - ty::ty_open(typ.fold_with(this)) - } ty::ty_enum(tid, ref substs) => { let substs = substs.fold_with(this); ty::ty_enum(tid, this.tcx().mk_substs(substs)) @@ -644,10 +662,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, let substs = substs.fold_with(this); ty::ty_struct(did, this.tcx().mk_substs(substs)) } - ty::ty_closure(did, ref region, ref substs) => { - let r = region.fold_with(this); + ty::ty_closure(did, ref substs) => { let s = substs.fold_with(this); - ty::ty_closure(did, this.tcx().mk_region(r), this.tcx().mk_substs(s)) + ty::ty_closure(did, this.tcx().mk_substs(s)) } ty::ty_projection(ref data) => { ty::ty_projection(data.fold_with(this)) diff --git a/src/librustc/middle/ty_match.rs b/src/librustc/middle/ty_match.rs new file mode 100644 index 0000000000..bb00fadc39 --- /dev/null +++ b/src/librustc/middle/ty_match.rs @@ -0,0 +1,95 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use middle::ty::{self, Ty}; +use middle::ty_relate::{self, Relate, TypeRelation, RelateResult}; +use util::ppaux::Repr; + +/// A type "A" *matches* "B" if the fresh types in B could be +/// substituted with values so as to make it equal to A. Matching is +/// intended to be used only on freshened types, and it basically +/// indicates if the non-freshened versions of A and B could have been +/// unified. +/// +/// It is only an approximation. If it yields false, unification would +/// definitely fail, but a true result doesn't mean unification would +/// succeed. This is because we don't track the "side-constraints" on +/// type variables, nor do we track if the same freshened type appears +/// more than once. To some extent these approximations could be +/// fixed, given effort. +/// +/// Like subtyping, matching is really a binary relation, so the only +/// important thing about the result is Ok/Err. Also, matching never +/// affects any type variables or unification state. +pub struct Match<'a, 'tcx: 'a> { + tcx: &'a ty::ctxt<'tcx> +} + +impl<'a, 'tcx> Match<'a, 'tcx> { + pub fn new(tcx: &'a ty::ctxt<'tcx>) -> Match<'a, 'tcx> { + Match { tcx: tcx } + } +} + +impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { + fn tag(&self) -> &'static str { "Match" } + fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.tcx } + fn a_is_expected(&self) -> bool { true } // irrelevant + + fn relate_with_variance>(&mut self, + _: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T> + { + self.relate(a, b) + } + + fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + debug!("{}.regions({}, {})", + self.tag(), + a.repr(self.tcx()), + b.repr(self.tcx())); + Ok(a) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + debug!("{}.tys({}, {})", self.tag(), + a.repr(self.tcx()), b.repr(self.tcx())); + if a == b { return Ok(a); } + + match (&a.sty, &b.sty) { + (_, &ty::ty_infer(ty::FreshTy(_))) | + (_, &ty::ty_infer(ty::FreshIntTy(_))) => { + Ok(a) + } + + (&ty::ty_infer(_), _) | + (_, &ty::ty_infer(_)) => { + Err(ty::terr_sorts(ty_relate::expected_found(self, &a, &b))) + } + + (&ty::ty_err, _) | (_, &ty::ty_err) => { + Ok(self.tcx().types.err) + } + + _ => { + ty_relate::super_relate_tys(self, a, b) + } + } + } + + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a,'tcx> + { + Ok(ty::Binder(try!(self.relate(a.skip_binder(), b.skip_binder())))) + } +} diff --git a/src/librustc/middle/ty_relate/mod.rs b/src/librustc/middle/ty_relate/mod.rs new file mode 100644 index 0000000000..1205b7d957 --- /dev/null +++ b/src/librustc/middle/ty_relate/mod.rs @@ -0,0 +1,655 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Generalized type relating mechanism. A type relation R relates a +//! pair of values (A, B). A and B are usually types or regions but +//! can be other things. Examples of type relations are subtyping, +//! type equality, etc. + +use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs}; +use middle::ty::{self, Ty}; +use middle::ty_fold::TypeFoldable; +use std::rc::Rc; +use syntax::abi; +use syntax::ast; +use util::ppaux::Repr; + +pub type RelateResult<'tcx, T> = Result>; + +pub trait TypeRelation<'a,'tcx> : Sized { + fn tcx(&self) -> &'a ty::ctxt<'tcx>; + + /// Returns a static string we can use for printouts. + fn tag(&self) -> &'static str; + + /// Returns true if the value `a` is the "expected" type in the + /// relation. Just affects error messages. + fn a_is_expected(&self) -> bool; + + /// Generic relation routine suitable for most anything. + fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { + Relate::relate(self, a, b) + } + + /// Switch variance for the purpose of relating `a` and `b`. + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T) + -> RelateResult<'tcx, T>; + + // Overrideable relations. You shouldn't typically call these + // directly, instead call `relate()`, which in turn calls + // these. This is both more uniform but also allows us to add + // additional hooks for other types in the future if needed + // without making older code, which called `relate`, obsolete. + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>>; + + fn regions(&mut self, a: ty::Region, b: ty::Region) + -> RelateResult<'tcx, ty::Region>; + + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a,'tcx>; +} + +pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> { + fn relate>(relation: &mut R, + a: &Self, + b: &Self) + -> RelateResult<'tcx, Self>; +} + +/////////////////////////////////////////////////////////////////////////// +// Relate impls + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::mt<'tcx> { + fn relate(relation: &mut R, + a: &ty::mt<'tcx>, + b: &ty::mt<'tcx>) + -> RelateResult<'tcx, ty::mt<'tcx>> + where R: TypeRelation<'a,'tcx> + { + debug!("{}.mts({}, {})", + relation.tag(), + a.repr(relation.tcx()), + b.repr(relation.tcx())); + if a.mutbl != b.mutbl { + Err(ty::terr_mutability) + } else { + let mutbl = a.mutbl; + let variance = match mutbl { + ast::MutImmutable => ty::Covariant, + ast::MutMutable => ty::Invariant, + }; + let ty = try!(relation.relate_with_variance(variance, &a.ty, &b.ty)); + Ok(ty::mt {ty: ty, mutbl: mutbl}) + } + } +} + +// substitutions are not themselves relatable without more context, +// but they is an important subroutine for things that ARE relatable, +// like traits etc. +fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R, + item_def_id: ast::DefId, + a_subst: &Substs<'tcx>, + b_subst: &Substs<'tcx>) + -> RelateResult<'tcx, Substs<'tcx>> + where R: TypeRelation<'a,'tcx> +{ + debug!("substs: item_def_id={} a_subst={} b_subst={}", + item_def_id.repr(relation.tcx()), + a_subst.repr(relation.tcx()), + b_subst.repr(relation.tcx())); + + let variances; + let opt_variances = if relation.tcx().variance_computed.get() { + variances = ty::item_variances(relation.tcx(), item_def_id); + Some(&*variances) + } else { + None + }; + relate_substs(relation, opt_variances, a_subst, b_subst) +} + +fn relate_substs<'a,'tcx,R>(relation: &mut R, + variances: Option<&ty::ItemVariances>, + a_subst: &Substs<'tcx>, + b_subst: &Substs<'tcx>) + -> RelateResult<'tcx, Substs<'tcx>> + where R: TypeRelation<'a,'tcx> +{ + let mut substs = Substs::empty(); + + for &space in &ParamSpace::all() { + let a_tps = a_subst.types.get_slice(space); + let b_tps = b_subst.types.get_slice(space); + let t_variances = variances.map(|v| v.types.get_slice(space)); + let tps = try!(relate_type_params(relation, t_variances, a_tps, b_tps)); + substs.types.replace(space, tps); + } + + match (&a_subst.regions, &b_subst.regions) { + (&ErasedRegions, _) | (_, &ErasedRegions) => { + substs.regions = ErasedRegions; + } + + (&NonerasedRegions(ref a), &NonerasedRegions(ref b)) => { + for &space in &ParamSpace::all() { + let a_regions = a.get_slice(space); + let b_regions = b.get_slice(space); + let r_variances = variances.map(|v| v.regions.get_slice(space)); + let regions = try!(relate_region_params(relation, + r_variances, + a_regions, + b_regions)); + substs.mut_regions().replace(space, regions); + } + } + } + + Ok(substs) +} + +fn relate_type_params<'a,'tcx,R>(relation: &mut R, + variances: Option<&[ty::Variance]>, + a_tys: &[Ty<'tcx>], + b_tys: &[Ty<'tcx>]) + -> RelateResult<'tcx, Vec>> + where R: TypeRelation<'a,'tcx> +{ + if a_tys.len() != b_tys.len() { + return Err(ty::terr_ty_param_size(expected_found(relation, + &a_tys.len(), + &b_tys.len()))); + } + + (0 .. a_tys.len()) + .map(|i| { + let a_ty = a_tys[i]; + let b_ty = b_tys[i]; + let v = variances.map_or(ty::Invariant, |v| v[i]); + relation.relate_with_variance(v, &a_ty, &b_ty) + }) + .collect() +} + +fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R, + variances: Option<&[ty::Variance]>, + a_rs: &[ty::Region], + b_rs: &[ty::Region]) + -> RelateResult<'tcx, Vec> + where R: TypeRelation<'a,'tcx> +{ + let tcx = relation.tcx(); + let num_region_params = a_rs.len(); + + debug!("relate_region_params(a_rs={}, \ + b_rs={}, variances={})", + a_rs.repr(tcx), + b_rs.repr(tcx), + variances.repr(tcx)); + + assert_eq!(num_region_params, + variances.map_or(num_region_params, + |v| v.len())); + + assert_eq!(num_region_params, b_rs.len()); + + (0..a_rs.len()) + .map(|i| { + let a_r = a_rs[i]; + let b_r = b_rs[i]; + let variance = variances.map_or(ty::Invariant, |v| v[i]); + relation.relate_with_variance(variance, &a_r, &b_r) + }) + .collect() +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BareFnTy<'tcx> { + fn relate(relation: &mut R, + a: &ty::BareFnTy<'tcx>, + b: &ty::BareFnTy<'tcx>) + -> RelateResult<'tcx, ty::BareFnTy<'tcx>> + where R: TypeRelation<'a,'tcx> + { + let unsafety = try!(relation.relate(&a.unsafety, &b.unsafety)); + let abi = try!(relation.relate(&a.abi, &b.abi)); + let sig = try!(relation.relate(&a.sig, &b.sig)); + Ok(ty::BareFnTy {unsafety: unsafety, + abi: abi, + sig: sig}) + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> { + fn relate(relation: &mut R, + a: &ty::FnSig<'tcx>, + b: &ty::FnSig<'tcx>) + -> RelateResult<'tcx, ty::FnSig<'tcx>> + where R: TypeRelation<'a,'tcx> + { + if a.variadic != b.variadic { + return Err(ty::terr_variadic_mismatch( + expected_found(relation, &a.variadic, &b.variadic))); + } + + let inputs = try!(relate_arg_vecs(relation, + &a.inputs, + &b.inputs)); + + let output = try!(match (a.output, b.output) { + (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) => + Ok(ty::FnConverging(try!(relation.relate(&a_ty, &b_ty)))), + (ty::FnDiverging, ty::FnDiverging) => + Ok(ty::FnDiverging), + (a, b) => + Err(ty::terr_convergence_mismatch( + expected_found(relation, &(a != ty::FnDiverging), &(b != ty::FnDiverging)))), + }); + + return Ok(ty::FnSig {inputs: inputs, + output: output, + variadic: a.variadic}); + } +} + +fn relate_arg_vecs<'a,'tcx,R>(relation: &mut R, + a_args: &[Ty<'tcx>], + b_args: &[Ty<'tcx>]) + -> RelateResult<'tcx, Vec>> + where R: TypeRelation<'a,'tcx> +{ + if a_args.len() != b_args.len() { + return Err(ty::terr_arg_count); + } + + a_args.iter() + .zip(b_args.iter()) + .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b)) + .collect() +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ast::Unsafety { + fn relate(relation: &mut R, + a: &ast::Unsafety, + b: &ast::Unsafety) + -> RelateResult<'tcx, ast::Unsafety> + where R: TypeRelation<'a,'tcx> + { + if a != b { + Err(ty::terr_unsafety_mismatch(expected_found(relation, a, b))) + } else { + Ok(*a) + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for abi::Abi { + fn relate(relation: &mut R, + a: &abi::Abi, + b: &abi::Abi) + -> RelateResult<'tcx, abi::Abi> + where R: TypeRelation<'a,'tcx> + { + if a == b { + Ok(*a) + } else { + Err(ty::terr_abi_mismatch(expected_found(relation, a, b))) + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionTy<'tcx> { + fn relate(relation: &mut R, + a: &ty::ProjectionTy<'tcx>, + b: &ty::ProjectionTy<'tcx>) + -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> + where R: TypeRelation<'a,'tcx> + { + if a.item_name != b.item_name { + Err(ty::terr_projection_name_mismatched( + expected_found(relation, &a.item_name, &b.item_name))) + } else { + let trait_ref = try!(relation.relate(&*a.trait_ref, &*b.trait_ref)); + Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name }) + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionPredicate<'tcx> { + fn relate(relation: &mut R, + a: &ty::ProjectionPredicate<'tcx>, + b: &ty::ProjectionPredicate<'tcx>) + -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> + where R: TypeRelation<'a,'tcx> + { + let projection_ty = try!(relation.relate(&a.projection_ty, &b.projection_ty)); + let ty = try!(relation.relate(&a.ty, &b.ty)); + Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for Vec> { + fn relate(relation: &mut R, + a: &Vec>, + b: &Vec>) + -> RelateResult<'tcx, Vec>> + where R: TypeRelation<'a,'tcx> + { + // To be compatible, `a` and `b` must be for precisely the + // same set of traits and item names. We always require that + // projection bounds lists are sorted by trait-def-id and item-name, + // so we can just iterate through the lists pairwise, so long as they are the + // same length. + if a.len() != b.len() { + Err(ty::terr_projection_bounds_length(expected_found(relation, &a.len(), &b.len()))) + } else { + a.iter() + .zip(b.iter()) + .map(|(a, b)| relation.relate(a, b)) + .collect() + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> { + fn relate(relation: &mut R, + a: &ty::ExistentialBounds<'tcx>, + b: &ty::ExistentialBounds<'tcx>) + -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>> + where R: TypeRelation<'a,'tcx> + { + let r = try!(relation.relate_with_variance(ty::Contravariant, + &a.region_bound, + &b.region_bound)); + let nb = try!(relation.relate(&a.builtin_bounds, &b.builtin_bounds)); + let pb = try!(relation.relate(&a.projection_bounds, &b.projection_bounds)); + Ok(ty::ExistentialBounds { region_bound: r, + builtin_bounds: nb, + projection_bounds: pb }) + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BuiltinBounds { + fn relate(relation: &mut R, + a: &ty::BuiltinBounds, + b: &ty::BuiltinBounds) + -> RelateResult<'tcx, ty::BuiltinBounds> + where R: TypeRelation<'a,'tcx> + { + // Two sets of builtin bounds are only relatable if they are + // precisely the same (but see the coercion code). + if a != b { + Err(ty::terr_builtin_bounds(expected_found(relation, a, b))) + } else { + Ok(*a) + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TraitRef<'tcx> { + fn relate(relation: &mut R, + a: &ty::TraitRef<'tcx>, + b: &ty::TraitRef<'tcx>) + -> RelateResult<'tcx, ty::TraitRef<'tcx>> + where R: TypeRelation<'a,'tcx> + { + // Different traits cannot be related + if a.def_id != b.def_id { + Err(ty::terr_traits(expected_found(relation, &a.def_id, &b.def_id))) + } else { + let substs = try!(relate_item_substs(relation, a.def_id, a.substs, b.substs)); + Ok(ty::TraitRef { def_id: a.def_id, substs: relation.tcx().mk_substs(substs) }) + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for Ty<'tcx> { + fn relate(relation: &mut R, + a: &Ty<'tcx>, + b: &Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a,'tcx> + { + relation.tys(a, b) + } +} + +/// The main "type relation" routine. Note that this does not handle +/// inference artifacts, so you should filter those out before calling +/// it. +pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, + a: Ty<'tcx>, + b: Ty<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a,'tcx> +{ + let tcx = relation.tcx(); + let a_sty = &a.sty; + let b_sty = &b.sty; + debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty); + match (a_sty, b_sty) { + (&ty::ty_infer(_), _) | + (_, &ty::ty_infer(_)) => + { + // The caller should handle these cases! + tcx.sess.bug("var types encountered in super_relate_tys") + } + + (&ty::ty_err, _) | (_, &ty::ty_err) => + { + Ok(tcx.types.err) + } + + (&ty::ty_char, _) | + (&ty::ty_bool, _) | + (&ty::ty_int(_), _) | + (&ty::ty_uint(_), _) | + (&ty::ty_float(_), _) | + (&ty::ty_str, _) + if a == b => + { + Ok(a) + } + + (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) + if a_p.idx == b_p.idx && a_p.space == b_p.space => + { + Ok(a) + } + + (&ty::ty_enum(a_id, a_substs), &ty::ty_enum(b_id, b_substs)) + if a_id == b_id => + { + let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs)); + Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs))) + } + + (&ty::ty_trait(ref a_), &ty::ty_trait(ref b_)) => + { + let principal = try!(relation.relate(&a_.principal, &b_.principal)); + let bounds = try!(relation.relate(&a_.bounds, &b_.bounds)); + Ok(ty::mk_trait(tcx, principal, bounds)) + } + + (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs)) + if a_id == b_id => + { + let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs)); + Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs))) + } + + (&ty::ty_closure(a_id, a_substs), + &ty::ty_closure(b_id, b_substs)) + if a_id == b_id => + { + // All ty_closure types with the same id represent + // the (anonymous) type of the same closure expression. So + // all of their regions should be equated. + let substs = try!(relate_substs(relation, None, a_substs, b_substs)); + Ok(ty::mk_closure(tcx, a_id, tcx.mk_substs(substs))) + } + + (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => + { + let typ = try!(relation.relate(&a_inner, &b_inner)); + Ok(ty::mk_uniq(tcx, typ)) + } + + (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => + { + let mt = try!(relation.relate(a_mt, b_mt)); + Ok(ty::mk_ptr(tcx, mt)) + } + + (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => + { + let r = try!(relation.relate_with_variance(ty::Contravariant, a_r, b_r)); + let mt = try!(relation.relate(a_mt, b_mt)); + Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt)) + } + + (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => + { + let t = try!(relation.relate(&a_t, &b_t)); + if sz_a == sz_b { + Ok(ty::mk_vec(tcx, t, Some(sz_a))) + } else { + Err(ty::terr_fixed_array_size(expected_found(relation, &sz_a, &sz_b))) + } + } + + (&ty::ty_vec(a_t, None), &ty::ty_vec(b_t, None)) => + { + let t = try!(relation.relate(&a_t, &b_t)); + Ok(ty::mk_vec(tcx, t, None)) + } + + (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => + { + if as_.len() == bs.len() { + let ts = try!(as_.iter() + .zip(bs.iter()) + .map(|(a, b)| relation.relate(a, b)) + .collect::>()); + Ok(ty::mk_tup(tcx, ts)) + } else if as_.len() != 0 && bs.len() != 0 { + Err(ty::terr_tuple_size( + expected_found(relation, &as_.len(), &bs.len()))) + } else { + Err(ty::terr_sorts(expected_found(relation, &a, &b))) + } + } + + (&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty)) + if a_opt_def_id == b_opt_def_id => + { + let fty = try!(relation.relate(a_fty, b_fty)); + Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty))) + } + + (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => + { + let projection_ty = try!(relation.relate(a_data, b_data)); + Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name)) + } + + _ => + { + Err(ty::terr_sorts(expected_found(relation, &a, &b))) + } + } +} + +impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::Region { + fn relate(relation: &mut R, + a: &ty::Region, + b: &ty::Region) + -> RelateResult<'tcx, ty::Region> + where R: TypeRelation<'a,'tcx> + { + relation.regions(*a, *b) + } +} + +impl<'a,'tcx:'a,T> Relate<'a,'tcx> for ty::Binder + where T: Relate<'a,'tcx> +{ + fn relate(relation: &mut R, + a: &ty::Binder, + b: &ty::Binder) + -> RelateResult<'tcx, ty::Binder> + where R: TypeRelation<'a,'tcx> + { + relation.binders(a, b) + } +} + +impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Rc + where T: Relate<'a,'tcx> +{ + fn relate(relation: &mut R, + a: &Rc, + b: &Rc) + -> RelateResult<'tcx, Rc> + where R: TypeRelation<'a,'tcx> + { + let a: &T = a; + let b: &T = b; + Ok(Rc::new(try!(relation.relate(a, b)))) + } +} + +impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Box + where T: Relate<'a,'tcx> +{ + fn relate(relation: &mut R, + a: &Box, + b: &Box) + -> RelateResult<'tcx, Box> + where R: TypeRelation<'a,'tcx> + { + let a: &T = a; + let b: &T = b; + Ok(Box::new(try!(relation.relate(a, b)))) + } +} + +/////////////////////////////////////////////////////////////////////////// +// Error handling + +pub fn expected_found<'a,'tcx,R,T>(relation: &mut R, + a: &T, + b: &T) + -> ty::expected_found + where R: TypeRelation<'a,'tcx>, T: Clone +{ + expected_found_bool(relation.a_is_expected(), a, b) +} + +pub fn expected_found_bool(a_is_expected: bool, + a: &T, + b: &T) + -> ty::expected_found + where T: Clone +{ + let a = a.clone(); + let b = b.clone(); + if a_is_expected { + ty::expected_found {expected: a, found: b} + } else { + ty::expected_found {expected: b, found: a} + } +} + diff --git a/src/librustc/middle/ty_walk.rs b/src/librustc/middle/ty_walk.rs index 40dfd47936..ec09d6dcc1 100644 --- a/src/librustc/middle/ty_walk.rs +++ b/src/librustc/middle/ty_walk.rs @@ -12,10 +12,11 @@ use middle::ty::{self, Ty}; use std::iter::Iterator; +use std::vec::IntoIter; pub struct TypeWalker<'tcx> { stack: Vec>, - last_subtree: uint, + last_subtree: usize, } impl<'tcx> TypeWalker<'tcx> { @@ -23,71 +24,17 @@ impl<'tcx> TypeWalker<'tcx> { TypeWalker { stack: vec!(ty), last_subtree: 1, } } - fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) { - match parent_ty.sty { - ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) | - ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => { - } - ty::ty_uniq(ty) | ty::ty_vec(ty, _) | ty::ty_open(ty) => { - self.stack.push(ty); - } - ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { - self.stack.push(mt.ty); - } - ty::ty_projection(ref data) => { - self.push_reversed(data.trait_ref.substs.types.as_slice()); - } - ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { - self.push_reversed(principal.substs().types.as_slice()); - self.push_reversed(&bounds.projection_bounds.iter().map(|pred| { - pred.0.ty - }).collect::>()); - } - ty::ty_enum(_, ref substs) | - ty::ty_struct(_, ref substs) | - ty::ty_closure(_, _, ref substs) => { - self.push_reversed(substs.types.as_slice()); - } - ty::ty_tup(ref ts) => { - self.push_reversed(ts); - } - ty::ty_bare_fn(_, ref ft) => { - self.push_sig_subtypes(&ft.sig); - } - } - } - - fn push_sig_subtypes(&mut self, sig: &ty::PolyFnSig<'tcx>) { - match sig.0.output { - ty::FnConverging(output) => { self.stack.push(output); } - ty::FnDiverging => { } - } - self.push_reversed(&sig.0.inputs); - } - - fn push_reversed(&mut self, tys: &[Ty<'tcx>]) { - // We push slices on the stack in reverse order so as to - // maintain a pre-order traversal. As of the time of this - // writing, the fact that the traversal is pre-order is not - // known to be significant to any code, but it seems like the - // natural order one would expect (basically, the order of the - // types as they are written). - for &ty in tys.iter().rev() { - self.stack.push(ty); - } - } - /// Skips the subtree of types corresponding to the last type /// returned by `next()`. /// - /// Example: Imagine you are walking `Foo, uint>`. + /// Example: Imagine you are walking `Foo, usize>`. /// - /// ```rust + /// ``` /// let mut iter: TypeWalker = ...; /// iter.next(); // yields Foo /// iter.next(); // yields Bar /// iter.skip_current_subtree(); // skips int - /// iter.next(); // yields uint + /// iter.next(); // yields usize /// ``` pub fn skip_current_subtree(&mut self) { self.stack.truncate(self.last_subtree); @@ -105,10 +52,70 @@ impl<'tcx> Iterator for TypeWalker<'tcx> { } Some(ty) => { self.last_subtree = self.stack.len(); - self.push_subtypes(ty); + push_subtypes(&mut self.stack, ty); debug!("next: stack={:?}", self.stack); Some(ty) } } } } + +pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter> { + let mut stack = vec![]; + push_subtypes(&mut stack, ty); + stack.into_iter() +} + +fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { + match parent_ty.sty { + ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) | + ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => { + } + ty::ty_uniq(ty) | ty::ty_vec(ty, _) => { + stack.push(ty); + } + ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => { + stack.push(mt.ty); + } + ty::ty_projection(ref data) => { + push_reversed(stack, data.trait_ref.substs.types.as_slice()); + } + ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { + push_reversed(stack, principal.substs().types.as_slice()); + push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| { + pred.0.ty + }).collect::>()); + } + ty::ty_enum(_, ref substs) | + ty::ty_struct(_, ref substs) | + ty::ty_closure(_, ref substs) => { + push_reversed(stack, substs.types.as_slice()); + } + ty::ty_tup(ref ts) => { + push_reversed(stack, ts); + } + ty::ty_bare_fn(_, ref ft) => { + push_sig_subtypes(stack, &ft.sig); + } + } +} + +fn push_sig_subtypes<'tcx>(stack: &mut Vec>, sig: &ty::PolyFnSig<'tcx>) { + match sig.0.output { + ty::FnConverging(output) => { stack.push(output); } + ty::FnDiverging => { } + } + push_reversed(stack, &sig.0.inputs); +} + +fn push_reversed<'tcx>(stack: &mut Vec>, tys: &[Ty<'tcx>]) { + // We push slices on the stack in reverse order so as to + // maintain a pre-order traversal. As of the time of this + // writing, the fact that the traversal is pre-order is not + // known to be significant to any code, but it seems like the + // natural order one would expect (basically, the order of the + // types as they are written). + for &ty in tys.iter().rev() { + stack.push(ty); + } +} diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index b3bc898748..752e71bc19 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -14,10 +14,11 @@ use session::Session; use metadata::creader::CrateReader; use plugin::registry::Registry; -use std::mem; -use std::env; -use std::dynamic_lib::DynamicLibrary; use std::borrow::ToOwned; +use std::dynamic_lib::DynamicLibrary; +use std::env; +use std::mem; +use std::path::PathBuf; use syntax::ast; use syntax::codemap::{Span, COMMAND_LINE_SP}; use syntax::ptr::P; @@ -98,9 +99,10 @@ impl<'a> PluginLoader<'a> { } // Dynamically link a registrar function into the compiler process. + #[allow(deprecated)] // until #23197 fn dylink_registrar(&mut self, span: Span, - path: Path, + path: PathBuf, symbol: String) -> PluginRegistrarFun { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(&path); diff --git a/src/librustc/plugin/mod.rs b/src/librustc/plugin/mod.rs index 711ed43fe0..3162c4fc57 100644 --- a/src/librustc/plugin/mod.rs +++ b/src/librustc/plugin/mod.rs @@ -47,7 +47,7 @@ //! #![plugin(myplugin)] //! ``` //! -//! See [the compiler plugin guide](../../guide-plugin.html) +//! See the [Plugins Chapter](../../book/plugins.html) of the book //! for more examples. pub use self::registry::Registry; diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index 12634204f8..a73ed04ac0 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -15,7 +15,7 @@ use session::Session; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT}; -use syntax::ext::base::{MacroExpanderFn}; +use syntax::ext::base::MacroExpanderFn; use syntax::codemap::Span; use syntax::parse::token; use syntax::ptr::P; @@ -81,8 +81,12 @@ impl<'a> Registry<'a> { /// This is the most general hook into `libsyntax`'s expansion behavior. pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) { self.syntax_exts.push((name, match extension { - NormalTT(ext, _) => NormalTT(ext, Some(self.krate_span)), - IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)), + NormalTT(ext, _, allow_internal_unstable) => { + NormalTT(ext, Some(self.krate_span), allow_internal_unstable) + } + IdentTT(ext, _, allow_internal_unstable) => { + IdentTT(ext, Some(self.krate_span), allow_internal_unstable) + } Decorator(ext) => Decorator(ext), Modifier(ext) => Modifier(ext), MultiModifier(ext) => MultiModifier(ext), @@ -99,7 +103,8 @@ impl<'a> Registry<'a> { /// It builds for you a `NormalTT` that calls `expander`, /// and also takes care of interning the macro's name. pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) { - self.register_syntax_extension(token::intern(name), NormalTT(box expander, None)); + self.register_syntax_extension(token::intern(name), + NormalTT(Box::new(expander), None, false)); } /// Register a compiler lint pass. diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 93a25de049..a7d608d2c8 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -35,9 +35,9 @@ use syntax::parse::token::InternedString; use getopts; use std::collections::HashMap; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::env; use std::fmt; +use std::path::PathBuf; use llvm; @@ -80,6 +80,7 @@ pub struct Options { pub gc: bool, pub optimize: OptLevel, + pub debug_assertions: bool, pub debuginfo: DebugInfoLevel, pub lint_opts: Vec<(String, lint::Level)>, pub describe_lints: bool, @@ -89,7 +90,7 @@ pub struct Options { // this. pub search_paths: SearchPaths, pub libs: Vec<(String, cstore::NativeLibraryKind)>, - pub maybe_sysroot: Option, + pub maybe_sysroot: Option, pub target_triple: String, // User-specified cfg meta items. The compiler itself will add additional // items to the crate config, and during parsing the entire crate config @@ -99,10 +100,11 @@ pub struct Options { pub test: bool, pub parse_only: bool, pub no_trans: bool, + pub treat_err_as_bug: bool, pub no_analysis: bool, pub debugging_opts: DebuggingOptions, /// Whether to write dependency files. It's (enabled, optional filename). - pub write_dependency_info: (bool, Option), + pub write_dependency_info: (bool, Option), pub prints: Vec, pub cg: CodegenOptions, pub color: ColorConfig, @@ -141,7 +143,7 @@ pub enum PrintRequest { pub enum Input { /// Load source from file - File(Path), + File(PathBuf), /// The string is the source Str(String) } @@ -149,7 +151,8 @@ pub enum Input { impl Input { pub fn filestem(&self) -> String { match *self { - Input::File(ref ifile) => ifile.filestem_str().unwrap().to_string(), + Input::File(ref ifile) => ifile.file_stem().unwrap() + .to_str().unwrap().to_string(), Input::Str(_) => "rust_out".to_string(), } } @@ -157,14 +160,14 @@ impl Input { #[derive(Clone)] pub struct OutputFilenames { - pub out_directory: Path, + pub out_directory: PathBuf, pub out_filestem: String, - pub single_output_file: Option, + pub single_output_file: Option, pub extra: String, } impl OutputFilenames { - pub fn path(&self, flavor: OutputType) -> Path { + pub fn path(&self, flavor: OutputType) -> PathBuf { match self.single_output_file { Some(ref path) => return path.clone(), None => {} @@ -172,8 +175,8 @@ impl OutputFilenames { self.temp_path(flavor) } - pub fn temp_path(&self, flavor: OutputType) -> Path { - let base = self.out_directory.join(self.filestem()); + pub fn temp_path(&self, flavor: OutputType) -> PathBuf { + let base = self.out_directory.join(&self.filestem()); match flavor { OutputTypeBitcode => base.with_extension("bc"), OutputTypeAssembly => base.with_extension("s"), @@ -184,8 +187,8 @@ impl OutputFilenames { } } - pub fn with_extension(&self, extension: &str) -> Path { - self.out_directory.join(self.filestem()).with_extension(extension) + pub fn with_extension(&self, extension: &str) -> PathBuf { + self.out_directory.join(&self.filestem()).with_extension(extension) } pub fn filestem(&self) -> String { @@ -223,6 +226,7 @@ pub fn basic_options() -> Options { test: false, parse_only: false, no_trans: false, + treat_err_as_bug: false, no_analysis: false, debugging_opts: basic_debugging_options(), write_dependency_info: (false, None), @@ -234,7 +238,8 @@ pub fn basic_options() -> Options { crate_name: None, alt_std_name: None, libs: Vec::new(), - unstable_features: UnstableFeatures::Disallow + unstable_features: UnstableFeatures::Disallow, + debug_assertions: true, } } @@ -242,7 +247,7 @@ pub fn basic_options() -> Options { // users can have their own entry // functions that don't start a // scheduler -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum EntryFnType { EntryMain, EntryStart, @@ -257,7 +262,6 @@ pub enum CrateType { CrateTypeStaticlib, } - #[derive(Clone)] pub enum Passes { SomePasses(Vec), @@ -300,7 +304,7 @@ macro_rules! options { { let mut op = $defaultfn(); for option in matches.opt_strs($prefix) { - let mut iter = option.splitn(1, '='); + let mut iter = option.splitn(2, '='); let key = iter.next().unwrap(); let value = iter.next(); let option_to_lookup = key.replace("-", "_"); @@ -311,19 +315,19 @@ macro_rules! options { match (value, opt_type_desc) { (Some(..), None) => { early_error(&format!("{} option `{}` takes no \ - value", $outputname, key)[]) + value", $outputname, key)) } (None, Some(type_desc)) => { early_error(&format!("{0} option `{1}` requires \ {2} ({3} {1}=)", $outputname, key, - type_desc, $prefix)[]) + type_desc, $prefix)) } (Some(value), Some(type_desc)) => { early_error(&format!("incorrect value `{}` for {} \ option `{}` - {} was expected", value, $outputname, - key, type_desc)[]) + key, type_desc)) } (None, None) => unreachable!() } @@ -333,7 +337,7 @@ macro_rules! options { } if !found { early_error(&format!("unknown {} option: `{}`", - $outputname, key)[]); + $outputname, key)); } } return op; @@ -347,7 +351,8 @@ macro_rules! options { #[allow(non_upper_case_globals, dead_code)] mod $mod_desc { pub const parse_bool: Option<&'static str> = None; - pub const parse_opt_bool: Option<&'static str> = None; + pub const parse_opt_bool: Option<&'static str> = + Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`"); pub const parse_string: Option<&'static str> = Some("a string"); pub const parse_opt_string: Option<&'static str> = Some("a string"); pub const parse_list: Option<&'static str> = Some("a space-separated list of strings"); @@ -378,7 +383,19 @@ macro_rules! options { fn parse_opt_bool(slot: &mut Option, v: Option<&str>) -> bool { match v { - Some(..) => false, + Some(s) => { + match s { + "n" | "no" | "off" => { + *slot = Some(false); + } + "y" | "yes" | "on" => { + *slot = Some(true); + } + _ => { return false; } + } + + true + }, None => { *slot = Some(true); true } } } @@ -422,14 +439,14 @@ macro_rules! options { } } - fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool { + fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool { match v.and_then(|s| s.parse().ok()) { Some(i) => { *slot = i; true }, None => false } } - fn parse_opt_uint(slot: &mut Option, v: Option<&str>) -> bool { + fn parse_opt_uint(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.parse().ok(); slot.is_some() } None => { *slot = None; true } @@ -501,17 +518,19 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "metadata to mangle symbol names with"), extra_filename: String = ("".to_string(), parse_string, "extra data to put in each output filename"), - codegen_units: uint = (1, parse_uint, + codegen_units: usize = (1, parse_uint, "divide crate into N units to optimize in parallel"), remark: Passes = (SomePasses(Vec::new()), parse_passes, "print remarks for these optimization passes (space separated, or \"all\")"), no_stack_check: bool = (false, parse_bool, "disable checks for stack exhaustion (a memory-safety hazard!)"), - debuginfo: Option = (None, parse_opt_uint, + debuginfo: Option = (None, parse_opt_uint, "debug info emission level, 0 = no debug info, 1 = line tables only, \ 2 = full debug info with variable and type information"), - opt_level: Option = (None, parse_opt_uint, + opt_level: Option = (None, parse_opt_uint, "Optimize with possible levels 0-3"), + debug_assertions: Option = (None, parse_opt_bool, + "explicitly enable the cfg(debug_assertions) directive"), } @@ -573,6 +592,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "Parse only; do not compile, assemble, or link"), no_trans: bool = (false, parse_bool, "Run all passes except translation; no output"), + treat_err_as_bug: bool = (false, parse_bool, + "Treat all errors that occur as bugs"), no_analysis: bool = (false, parse_bool, "Parse and expand the source, but run no analysis"), extra_plugins: Vec = (Vec::new(), parse_list, @@ -581,6 +602,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "Adds unstable command line options to rustc interface"), print_enum_sizes: bool = (false, parse_bool, "Print the size of enums and their variants"), + force_overflow_checks: Option = (None, parse_opt_bool, + "Force overflow checks on or off"), + force_dropflag_checks: Option = (None, parse_opt_bool, + "Force drop flag checks on or off"), } pub fn default_lib_output() -> CrateType { @@ -590,10 +615,10 @@ pub fn default_lib_output() -> CrateType { pub fn default_configuration(sess: &Session) -> ast::CrateConfig { use syntax::parse::token::intern_and_get_ident as intern; - let end = &sess.target.target.target_endian[]; - let arch = &sess.target.target.arch[]; - let wordsz = &sess.target.target.target_pointer_width[]; - let os = &sess.target.target.target_os[]; + let end = &sess.target.target.target_endian; + let arch = &sess.target.target.arch; + let wordsz = &sess.target.target.target_pointer_width; + let os = &sess.target.target.target_os; let fam = match sess.target.target.options.is_like_windows { true => InternedString::new("windows"), @@ -601,7 +626,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { }; let mk = attr::mk_name_value_item_str; - return vec!(// Target bindings. + let mut ret = vec![ // Target bindings. attr::mk_word_item(fam.clone()), mk(InternedString::new("target_os"), intern(os)), mk(InternedString::new("target_family"), fam), @@ -609,7 +634,11 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { mk(InternedString::new("target_endian"), intern(end)), mk(InternedString::new("target_pointer_width"), intern(wordsz)) - ); + ]; + if sess.opts.debug_assertions { + ret.push(attr::mk_word_item(InternedString::new("debug_assertions"))); + } + return ret; } pub fn append_configuration(cfg: &mut ast::CrateConfig, @@ -634,18 +663,18 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig { } pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config { - let target = match Target::search(&opts.target_triple[]) { + let target = match Target::search(&opts.target_triple) { Ok(t) => t, Err(e) => { sp.handler().fatal(&format!("Error loading target specification: {}", e)); } }; - let (int_type, uint_type) = match &target.target_pointer_width[] { + let (int_type, uint_type) = match &target.target_pointer_width[..] { "32" => (ast::TyI32, ast::TyU32), "64" => (ast::TyI64, ast::TyU64), w => sp.handler().fatal(&format!("target specification was invalid: unrecognized \ - target-pointer-width {}", w)[]) + target-pointer-width {}", w)) }; Config { @@ -708,8 +737,8 @@ mod opt { use getopts; use super::RustcOptGroup; - type R = RustcOptGroup; - type S<'a> = &'a str; + pub type R = RustcOptGroup; + pub type S<'a> = &'a str; fn stable(g: getopts::OptGroup) -> R { RustcOptGroup::stable(g) } fn unstable(g: getopts::OptGroup) -> R { RustcOptGroup::unstable(g) } @@ -843,6 +872,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let parse_only = debugging_opts.parse_only; let no_trans = debugging_opts.no_trans; + let treat_err_as_bug = debugging_opts.treat_err_as_bug; let no_analysis = debugging_opts.no_analysis; if debugging_opts.debug_llvm { @@ -863,7 +893,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { "dep-info" => OutputTypeDepInfo, _ => { early_error(&format!("unknown emission type: `{}`", - part)[]) + part)) } }; output_types.push(output_type) @@ -878,7 +908,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let cg = build_codegen_options(matches); - let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m)); + let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); let target = matches.opt_str("target").unwrap_or( host_triple().to_string()); let opt_level = { @@ -902,6 +932,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } }; + let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == No); let gc = debugging_opts.gc; let debuginfo = if matches.opt_present("g") { if cg.debuginfo.is_some() { @@ -927,25 +958,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } let libs = matches.opt_strs("l").into_iter().map(|s| { - let mut parts = s.splitn(1, '='); - let kind = parts.next().unwrap(); - if let Some(name) = parts.next() { - let kind = match kind { - "dylib" => cstore::NativeUnknown, - "framework" => cstore::NativeFramework, - "static" => cstore::NativeStatic, - s => { - early_error(&format!("unknown library kind `{}`, expected \ - one of dylib, framework, or static", - s)); - } - }; - return (name.to_string(), kind) - } - - // FIXME(acrichto) remove this once crates have stopped using it, this - // is deprecated behavior now. - let mut parts = s.rsplitn(1, ':'); + let mut parts = s.splitn(2, '='); let kind = parts.next().unwrap(); let (name, kind) = match (parts.next(), kind) { (None, name) | @@ -955,7 +968,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { (_, s) => { early_error(&format!("unknown library kind `{}`, expected \ one of dylib, framework, or static", - s)[]); + s)); } }; (name.to_string(), kind) @@ -991,13 +1004,13 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { Some(arg) => { early_error(&format!("argument for --color must be auto, always \ or never (instead was `{}`)", - arg)[]) + arg)) } }; let mut externs = HashMap::new(); for arg in &matches.opt_strs("extern") { - let mut parts = arg.splitn(1, '='); + let mut parts = arg.splitn(2, '='); let name = match parts.next() { Some(s) => s, None => early_error("--extern value must not be empty"), @@ -1007,10 +1020,7 @@ 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.insert(vec![location.to_string()]); }, - Occupied(mut entry) => { entry.get_mut().push(location.to_string()); }, - } + externs.entry(name.to_string()).or_insert(vec![]).push(location.to_string()); } let crate_name = matches.opt_str("crate-name"); @@ -1030,6 +1040,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { test: test, parse_only: parse_only, no_trans: no_trans, + treat_err_as_bug: treat_err_as_bug, no_analysis: no_analysis, debugging_opts: debugging_opts, write_dependency_info: write_dependency_info, @@ -1042,6 +1053,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { alt_std_name: None, libs: libs, unstable_features: get_unstable_features_setting(), + debug_assertions: debug_assertions, } } @@ -1111,7 +1123,7 @@ mod test { #[test] fn test_switch_implies_cfg_test() { let matches = - &match getopts(&["--test".to_string()], &optgroups()[]) { + &match getopts(&["--test".to_string()], &optgroups()) { Ok(m) => m, Err(f) => panic!("test_switch_implies_cfg_test: {}", f) }; @@ -1128,7 +1140,7 @@ mod test { fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = &match getopts(&["--test".to_string(), "--cfg=test".to_string()], - &optgroups()[]) { + &optgroups()) { Ok(m) => m, Err(f) => { panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f) @@ -1148,7 +1160,7 @@ mod test { { let matches = getopts(&[ "-Awarnings".to_string() - ], &optgroups()[]).unwrap(); + ], &optgroups()).unwrap(); let registry = diagnostics::registry::Registry::new(&[]); let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry); @@ -1159,7 +1171,7 @@ mod test { let matches = getopts(&[ "-Awarnings".to_string(), "-Dwarnings".to_string() - ], &optgroups()[]).unwrap(); + ], &optgroups()).unwrap(); let registry = diagnostics::registry::Registry::new(&[]); let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry); @@ -1169,7 +1181,7 @@ mod test { { let matches = getopts(&[ "-Adead_code".to_string() - ], &optgroups()[]).unwrap(); + ], &optgroups()).unwrap(); let registry = diagnostics::registry::Registry::new(&[]); let sessopts = build_session_options(&matches); let sess = build_session(sessopts, None, registry); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index c1c5518887..3e3e5e1796 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use lint; use metadata::cstore::CStore; use metadata::filesearch; @@ -27,8 +26,9 @@ use syntax::{ast, codemap}; use rustc_back::target::Target; -use std::env; +use std::path::{Path, PathBuf}; use std::cell::{Cell, RefCell}; +use std::env; pub mod config; pub mod search_paths; @@ -45,11 +45,11 @@ pub struct Session { pub entry_fn: RefCell>, pub entry_type: Cell>, pub plugin_registrar_fn: Cell>, - pub default_sysroot: Option, + pub default_sysroot: Option, // The name of the root source file of the crate, in the local file system. The path is always // expected to be absolute. `None` means that there is no source file. - pub local_crate_source_file: Option, - pub working_dir: Path, + pub local_crate_source_file: Option, + pub working_dir: PathBuf, pub lint_store: RefCell, pub lints: RefCell>>, pub crate_types: RefCell>, @@ -58,37 +58,55 @@ pub struct Session { /// The maximum recursion limit for potentially infinitely recursive /// operations such as auto-dereference and monomorphization. - pub recursion_limit: Cell, + pub recursion_limit: Cell, pub can_print_warnings: bool } impl Session { pub fn span_fatal(&self, sp: Span, msg: &str) -> ! { + if self.opts.treat_err_as_bug { + self.span_bug(sp, msg); + } self.diagnostic().span_fatal(sp, msg) } pub fn span_fatal_with_code(&self, sp: Span, msg: &str, code: &str) -> ! { + if self.opts.treat_err_as_bug { + self.span_bug(sp, msg); + } self.diagnostic().span_fatal_with_code(sp, msg, code) } pub fn fatal(&self, msg: &str) -> ! { + if self.opts.treat_err_as_bug { + self.bug(msg); + } self.diagnostic().handler().fatal(msg) } pub fn span_err(&self, sp: Span, msg: &str) { + if self.opts.treat_err_as_bug { + self.span_bug(sp, msg); + } match split_msg_into_multilines(msg) { Some(msg) => self.diagnostic().span_err(sp, &msg[..]), None => self.diagnostic().span_err(sp, msg) } } pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) { + if self.opts.treat_err_as_bug { + self.span_bug(sp, msg); + } match split_msg_into_multilines(msg) { Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code), None => self.diagnostic().span_err_with_code(sp, msg, code) } } pub fn err(&self, msg: &str) { + if self.opts.treat_err_as_bug { + self.bug(msg); + } self.diagnostic().handler().err(msg) } - pub fn err_count(&self) -> uint { + pub fn err_count(&self) -> usize { self.diagnostic().handler().err_count() } pub fn has_errors(&self) -> bool { @@ -186,7 +204,7 @@ impl Session { // cases later on pub fn impossible_case(&self, sp: Span, msg: &str) -> ! { self.span_bug(sp, - &format!("impossible case reached: {}", msg)[]); + &format!("impossible case reached: {}", msg)); } pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } @@ -228,7 +246,7 @@ impl Session { } pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch { filesearch::FileSearch::new(self.sysroot(), - &self.opts.target_triple[], + &self.opts.target_triple, &self.opts.search_paths, kind) } @@ -280,9 +298,9 @@ fn split_msg_into_multilines(msg: &str) -> Option { } let mut tail = &msg[head..]; - let third = tail.find_str("(values differ") - .or(tail.find_str("(lifetime")) - .or(tail.find_str("(cyclic type of infinite size")); + let third = tail.find("(values differ") + .or(tail.find("(lifetime")) + .or(tail.find("(cyclic type of infinite size")); // Insert `\n` before any remaining messages which match. if let Some(pos) = third { // The end of the message may just be wrapped in `()` without @@ -302,7 +320,7 @@ fn split_msg_into_multilines(msg: &str) -> Option { } pub fn build_session(sopts: config::Options, - local_crate_source_file: Option, + local_crate_source_file: Option, registry: diagnostics::registry::Registry) -> Session { // FIXME: This is not general enough to make the warning lint completely override @@ -325,7 +343,7 @@ pub fn build_session(sopts: config::Options, } pub fn build_session_(sopts: config::Options, - local_crate_source_file: Option, + local_crate_source_file: Option, span_diagnostic: diagnostic::SpanHandler) -> Session { let host = match Target::search(config::host_triple()) { @@ -380,7 +398,6 @@ pub fn build_session_(sopts: config::Options, can_print_warnings: can_print_warnings }; - sess.lint_store.borrow_mut().register_builtin(Some(&sess)); sess } diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index c314a999f2..3dc31f9524 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -9,15 +9,17 @@ // except according to those terms. use std::slice; +use std::path::{Path, PathBuf}; +use session::early_error; #[derive(Clone, Debug)] pub struct SearchPaths { - paths: Vec<(PathKind, Path)>, + paths: Vec<(PathKind, PathBuf)>, } pub struct Iter<'a> { kind: PathKind, - iter: slice::Iter<'a, (PathKind, Path)>, + iter: slice::Iter<'a, (PathKind, PathBuf)>, } #[derive(Eq, PartialEq, Clone, Copy, Debug)] @@ -49,7 +51,10 @@ impl SearchPaths { } else { (PathKind::All, path) }; - self.paths.push((kind, Path::new(path))); + if path.is_empty() { + early_error("empty search path given via `-L`"); + } + self.paths.push((kind, PathBuf::from(path))); } pub fn iter(&self, kind: PathKind) -> Iter { diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index c9d50b9cec..d71a68e205 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -12,12 +12,13 @@ use std::cell::{RefCell, Cell}; use std::collections::HashMap; +use std::collections::hash_state::HashState; +use std::ffi::CString; use std::fmt::Debug; use std::hash::Hash; -#[cfg(stage0)] use std::hash::Hasher; use std::iter::repeat; +use std::path::Path; use std::time::Duration; -use std::collections::hash_state::HashState; use syntax::ast; use syntax::visit; @@ -34,7 +35,7 @@ pub struct ErrorReported; pub fn time(do_it: bool, what: &str, u: U, f: F) -> T where F: FnOnce(U) -> T, { - thread_local!(static DEPTH: Cell = Cell::new(0)); + thread_local!(static DEPTH: Cell = Cell::new(0)); if !do_it { return f(u); } let old = DEPTH.with(|slot| { @@ -139,57 +140,13 @@ pub fn block_query

(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) - /// K: Eq + Hash, V, S, H: Hasher /// -/// Determines whether there exists a path from `source` to `destination`. The graph is defined by -/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`. +/// Determines whether there exists a path from `source` to `destination`. The +/// graph is defined by the `edges_map`, which maps from a node `S` to a list of +/// its adjacent nodes `T`. /// -/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on -/// very small graphs. If the graphs become larger, a more efficient graph representation and -/// algorithm would probably be advised. -#[cfg(stage0)] -pub fn can_reach(edges_map: &HashMap, S>, source: T, - destination: T) -> bool - where S: HashState, - ::Hasher: Hasher, - T: Hash<::Hasher> + Eq + Clone, -{ - if source == destination { - return true; - } - - // Do a little breadth-first-search here. The `queue` list - // doubles as a way to detect if we've seen a particular FR - // before. Note that we expect this graph to be an *extremely - // shallow* tree. - let mut queue = vec!(source); - let mut i = 0; - while i < queue.len() { - match edges_map.get(&queue[i]) { - Some(edges) => { - for target in edges { - if *target == destination { - return true; - } - - if !queue.iter().any(|x| x == target) { - queue.push((*target).clone()); - } - } - } - None => {} - } - i += 1; - } - return false; -} -/// K: Eq + Hash, V, S, H: Hasher -/// -/// Determines whether there exists a path from `source` to `destination`. The graph is defined by -/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`. -/// -/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on -/// very small graphs. If the graphs become larger, a more efficient graph representation and -/// algorithm would probably be advised. -#[cfg(not(stage0))] +/// Efficiency note: This is implemented in an inefficient way because it is +/// typically invoked on very small graphs. If the graphs become larger, a more +/// efficient graph representation and algorithm would probably be advised. pub fn can_reach(edges_map: &HashMap, S>, source: T, destination: T) -> bool where S: HashState, T: Hash + Eq + Clone, @@ -236,13 +193,13 @@ pub fn can_reach(edges_map: &HashMap, S>, source: T, /// ``` /// but currently it is not possible. /// -/// # Example +/// # Examples /// ``` /// struct Context { -/// cache: RefCell> +/// cache: RefCell> /// } /// -/// fn factorial(ctxt: &Context, n: uint) -> uint { +/// fn factorial(ctxt: &Context, n: usize) -> usize { /// memoized(&ctxt.cache, n, |n| match n { /// 0 | 1 => n, /// _ => factorial(ctxt, n - 2) + factorial(ctxt, n - 1) @@ -250,12 +207,10 @@ pub fn can_reach(edges_map: &HashMap, S>, source: T, /// } /// ``` #[inline(always)] -#[cfg(stage0)] pub fn memoized(cache: &RefCell>, arg: T, f: F) -> U - where T: Clone + Hash<::Hasher> + Eq, + where T: Clone + Hash + Eq, U: Clone, S: HashState, - ::Hasher: Hasher, F: FnOnce(T) -> U, { let key = arg.clone(); @@ -269,47 +224,15 @@ pub fn memoized(cache: &RefCell>, arg: T, f: F) -> } } } -/// Memoizes a one-argument closure using the given RefCell containing -/// a type implementing MutableMap to serve as a cache. -/// -/// In the future the signature of this function is expected to be: -/// ``` -/// pub fn memoized>( -/// cache: &RefCell, -/// f: &|T| -> U -/// ) -> impl |T| -> U { -/// ``` -/// but currently it is not possible. -/// -/// # Example -/// ``` -/// struct Context { -/// cache: RefCell> -/// } -/// -/// fn factorial(ctxt: &Context, n: uint) -> uint { -/// memoized(&ctxt.cache, n, |n| match n { -/// 0 | 1 => n, -/// _ => factorial(ctxt, n - 2) + factorial(ctxt, n - 1) -/// }) -/// } -/// ``` -#[inline(always)] -#[cfg(not(stage0))] -pub fn memoized(cache: &RefCell>, arg: T, f: F) -> U - where T: Clone + Hash + Eq, - U: Clone, - S: HashState, - F: FnOnce(T) -> U, -{ - let key = arg.clone(); - let result = cache.borrow().get(&key).map(|result| result.clone()); - match result { - Some(result) => result, - None => { - let result = f(arg); - cache.borrow_mut().insert(key, result.clone()); - result - } - } + +#[cfg(unix)] +pub fn path2cstr(p: &Path) -> CString { + use std::os::unix::prelude::*; + use std::ffi::OsStr; + let p: &OsStr = p.as_ref(); + CString::new(p.as_bytes()).unwrap() +} +#[cfg(windows)] +pub fn path2cstr(p: &Path) -> CString { + CString::new(p.to_str().unwrap()).unwrap() } diff --git a/src/librustc/util/lev_distance.rs b/src/librustc/util/lev_distance.rs index 10a7b2abea..28f8510ce3 100644 --- a/src/librustc/util/lev_distance.rs +++ b/src/librustc/util/lev_distance.rs @@ -10,7 +10,7 @@ use std::cmp; -pub fn lev_distance(me: &str, t: &str) -> uint { +pub fn lev_distance(me: &str, t: &str) -> usize { if me.is_empty() { return t.chars().count(); } if t.is_empty() { return me.chars().count(); } @@ -45,7 +45,7 @@ pub fn lev_distance(me: &str, t: &str) -> uint { fn test_lev_distance() { use std::char::{ from_u32, MAX }; // Test bytelength agnosticity - for c in (0u32..MAX as u32) + for c in (0..MAX as u32) .filter_map(|i| from_u32(i)) .map(|i| i.to_string()) { assert_eq!(lev_distance(&c[..], &c[..]), 0); diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index 1b07ce789e..61d28e0ca1 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -12,11 +12,10 @@ #![allow(non_snake_case)] -use std::collections::hash_state::{DefaultState}; +use std::collections::hash_state::DefaultState; use std::collections::{HashMap, HashSet}; use std::default::Default; use std::hash::{Hasher, Hash}; -#[cfg(stage0)] use std::hash::Writer; use syntax::ast; pub type FnvHashMap = HashMap>; @@ -28,19 +27,9 @@ pub type DefIdMap = FnvHashMap; pub type NodeSet = FnvHashSet; pub type DefIdSet = FnvHashSet; -#[cfg(stage0)] -pub fn FnvHashMap + Eq, V>() -> FnvHashMap { - Default::default() -} -#[cfg(stage0)] -pub fn FnvHashSet + Eq>() -> FnvHashSet { - Default::default() -} -#[cfg(not(stage0))] pub fn FnvHashMap() -> FnvHashMap { Default::default() } -#[cfg(not(stage0))] pub fn FnvHashSet() -> FnvHashSet { Default::default() } @@ -63,32 +52,12 @@ impl Default for FnvHasher { fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) } } -#[cfg(stage0)] -impl Hasher for FnvHasher { - type Output = u64; - fn reset(&mut self) { *self = Default::default(); } - fn finish(&self) -> u64 { self.0 } -} - -#[cfg(stage0)] -impl Writer for FnvHasher { - fn write(&mut self, bytes: &[u8]) { - let FnvHasher(mut hash) = *self; - for byte in bytes { - hash = hash ^ (*byte as u64); - hash = hash * 0x100000001b3; - } - *self = FnvHasher(hash); - } -} - -#[cfg(not(stage0))] impl Hasher for FnvHasher { fn write(&mut self, bytes: &[u8]) { let FnvHasher(mut hash) = *self; for byte in bytes { hash = hash ^ (*byte as u64); - hash = hash * 0x100000001b3; + hash = hash.wrapping_mul(0x100000001b3); } *self = FnvHasher(hash); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1d46c011bb..60b422b376 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -20,8 +20,8 @@ use middle::ty::{ReSkolemized, ReVar, BrEnv}; use middle::ty::{mt, Ty, ParamTy}; use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum}; use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn}; -use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open}; -use middle::ty::{ty_closure}; +use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup}; +use middle::ty::ty_closure; use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer}; use middle::ty; use middle::ty_fold::TypeFoldable; @@ -29,7 +29,6 @@ use middle::ty_fold::TypeFoldable; use std::collections::HashMap; use std::collections::hash_state::HashState; use std::hash::Hash; -#[cfg(stage0)] use std::hash::Hasher; use std::rc::Rc; use syntax::abi; use syntax::ast_map; @@ -58,12 +57,12 @@ pub fn note_and_explain_region(cx: &ctxt, (ref str, Some(span)) => { cx.sess.span_note( span, - &format!("{}{}{}", prefix, *str, suffix)[]); + &format!("{}{}{}", prefix, *str, suffix)); Some(span) } (ref str, None) => { cx.sess.note( - &format!("{}{}{}", prefix, *str, suffix)[]); + &format!("{}{}{}", prefix, *str, suffix)); None } } @@ -116,7 +115,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) region::CodeExtent::Misc(_) => tag, region::CodeExtent::DestructionScope(_) => { new_string = format!("destruction scope surrounding {}", tag); - new_string.as_slice() + &*new_string } region::CodeExtent::Remainder(r) => { new_string = format!("block suffix following statement {}", @@ -274,7 +273,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { }; if abi != abi::Rust { - s.push_str(&format!("extern {} ", abi.to_string())[]); + s.push_str(&format!("extern {} ", abi.to_string())); }; s.push_str("fn"); @@ -330,7 +329,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { ty::FnConverging(t) => { if !ty::type_is_nil(t) { s.push_str(" -> "); - s.push_str(&ty_to_string(cx, t)[]); + s.push_str(&ty_to_string(cx, t)); } } ty::FnDiverging => { @@ -367,11 +366,9 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } ty_rptr(r, ref tm) => { let mut buf = region_ptr_to_string(cx, *r); - buf.push_str(&mt_to_string(cx, tm)[]); + buf.push_str(&mt_to_string(cx, tm)); buf } - ty_open(typ) => - format!("opened<{}>", ty_to_string(cx, typ)), ty_tup(ref elems) => { let strs = elems .iter() @@ -387,13 +384,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty), ty_err => "[type error]".to_string(), - ty_param(ref param_ty) => { - if cx.sess.verbose() { - param_ty.repr(cx) - } else { - param_ty.user_string(cx) - } - } + ty_param(ref param_ty) => param_ty.user_string(cx), ty_enum(did, substs) | ty_struct(did, substs) => { let base = ty::item_path_str(cx, did); parameterized(cx, &base, substs, did, &[], @@ -409,7 +400,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { data.item_name.user_string(cx)) } ty_str => "str".to_string(), - ty_closure(ref did, _, substs) => { + ty_closure(ref did, substs) => { let closure_tys = cx.closure_tys.borrow(); closure_tys.get(did).map(|closure_type| { closure_to_string(cx, &closure_type.subst(cx, substs)) @@ -561,7 +552,7 @@ pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>, } else if strs[0].starts_with("(") && strs[0].ends_with(")") { &strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')' } else { - &strs[0][] + &strs[0][..] }, tail) } else if strs.len() > 0 { @@ -823,23 +814,19 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> { impl<'tcx> Repr<'tcx> for ty::TraitDef<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("TraitDef(generics={}, bounds={}, trait_ref={})", + format!("TraitDef(generics={}, trait_ref={})", self.generics.repr(tcx), - self.bounds.repr(tcx), self.trait_ref.repr(tcx)) } } impl<'tcx> Repr<'tcx> for ast::TraitItem { fn repr(&self, _tcx: &ctxt) -> String { - match *self { - ast::RequiredMethod(ref data) => format!("RequiredMethod({}, id={})", - data.ident, data.id), - ast::ProvidedMethod(ref data) => format!("ProvidedMethod(id={})", - data.id), - ast::TypeTraitItem(ref data) => format!("TypeTraitItem({}, id={})", - data.ty_param.ident, data.ty_param.id), - } + let kind = match self.node { + ast::MethodTraitItem(..) => "MethodTraitItem", + ast::TypeTraitItem(..) => "TypeTraitItem", + }; + format!("{}({}, id={})", kind, self.ident, self.id) } } @@ -1060,10 +1047,11 @@ impl<'tcx> Repr<'tcx> for ty::Variance { impl<'tcx> Repr<'tcx> for ty::Method<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("method(name: {}, generics: {}, fty: {}, \ + format!("method(name: {}, generics: {}, predicates: {}, fty: {}, \ explicit_self: {}, vis: {}, def_id: {})", self.name.repr(tcx), self.generics.repr(tcx), + self.predicates.repr(tcx), self.fty.repr(tcx), self.explicit_self.repr(tcx), self.vis.repr(tcx), @@ -1221,17 +1209,17 @@ impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { let mut res = Vec::new(); - let region_str = self.region_bound.user_string(tcx); + let region_str = self.region_bound.repr(tcx); if !region_str.is_empty() { res.push(region_str); } for bound in &self.builtin_bounds { - res.push(bound.user_string(tcx)); + res.push(bound.repr(tcx)); } for projection_bound in &self.projection_bounds { - res.push(projection_bound.user_string(tcx)); + res.push(projection_bound.repr(tcx)); } res.connect("+") @@ -1434,23 +1422,6 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder { } } -#[cfg(stage0)] -impl<'tcx, S, K, V> Repr<'tcx> for HashMap - where K: Hash<::Hasher> + Eq + Repr<'tcx>, - V: Repr<'tcx>, - S: HashState, - ::Hasher: Hasher, -{ - fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("HashMap({})", - self.iter() - .map(|(k,v)| format!("{} => {}", k.repr(tcx), v.repr(tcx))) - .collect::>() - .connect(", ")) - } -} - -#[cfg(not(stage0))] impl<'tcx, S, K, V> Repr<'tcx> for HashMap where K: Hash + Eq + Repr<'tcx>, V: Repr<'tcx>, @@ -1555,3 +1526,9 @@ impl<'tcx> UserString<'tcx> for ty::Predicate<'tcx> { } } } + +impl<'tcx> Repr<'tcx> for ast::Unsafety { + fn repr(&self, _: &ctxt<'tcx>) -> String { + format!("{:?}", *self) + } +} diff --git a/src/librustc/util/snapshot_vec.rs b/src/librustc/util/snapshot_vec.rs index 8fbc682246..d2e0b3aec2 100644 --- a/src/librustc/util/snapshot_vec.rs +++ b/src/librustc/util/snapshot_vec.rs @@ -30,10 +30,10 @@ pub enum UndoLog { CommittedSnapshot, /// New variable with given index was created. - NewElem(uint), + NewElem(usize), /// Variable with given index was changed *from* the given value. - SetElem(uint, D::Value), + SetElem(usize, D::Value), /// Extensible set of actions Other(D::Undo) @@ -48,7 +48,7 @@ pub struct SnapshotVec { // Snapshots are tokens that should be created/consumed linearly. pub struct Snapshot { // Length of the undo log at the time the snapshot was taken. - length: uint, + length: usize, } pub trait SnapshotVecDelegate { @@ -77,7 +77,7 @@ impl SnapshotVec { } } - pub fn push(&mut self, elem: D::Value) -> uint { + pub fn push(&mut self, elem: D::Value) -> usize { let len = self.values.len(); self.values.push(elem); @@ -88,20 +88,20 @@ impl SnapshotVec { len } - pub fn get<'a>(&'a self, index: uint) -> &'a D::Value { + pub fn get<'a>(&'a self, index: usize) -> &'a D::Value { &self.values[index] } /// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone /// automatically, so you should be sure call `record()` with some sort of suitable undo /// action. - pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut D::Value { + pub fn get_mut<'a>(&'a mut self, index: usize) -> &'a mut D::Value { &mut self.values[index] } /// Updates the element at the given index. The old value will saved (and perhaps restored) if /// a snapshot is active. - pub fn set(&mut self, index: uint, new_elem: D::Value) { + pub fn set(&mut self, index: usize, new_elem: D::Value) { let old_elem = mem::replace(&mut self.values[index], new_elem); if self.in_snapshot() { self.undo_log.push(SetElem(index, old_elem)); diff --git a/src/librustc_back/abi.rs b/src/librustc_back/abi.rs index 4b9064aaa0..c3a3a8d582 100644 --- a/src/librustc_back/abi.rs +++ b/src/librustc_back/abi.rs @@ -8,17 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub const BOX_FIELD_DROP_GLUE: uint = 1; -pub const BOX_FIELD_BODY: uint = 4; +pub const BOX_FIELD_DROP_GLUE: usize = 1; +pub const BOX_FIELD_BODY: usize = 4; /// The first half of a fat pointer. /// - For a closure, this is the code address. /// - For an object or trait instance, this is the address of the box. /// - For a slice, this is the base address. -pub const FAT_PTR_ADDR: uint = 0; +pub const FAT_PTR_ADDR: usize = 0; /// The second half of a fat pointer. /// - For a closure, this is the address of the environment. /// - For an object or trait instance, this is the address of the vtable. /// - For a slice, this is the length. -pub const FAT_PTR_EXTRA: uint = 1; +pub const FAT_PTR_EXTRA: usize = 1; diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index c45ee25834..9f5751c421 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -10,20 +10,23 @@ //! A helper class for dealing with static archives -use std::old_io::fs::PathExtensions; -use std::old_io::process::{Command, ProcessOutput}; -use std::old_io::{fs, TempDir}; -use std::old_io; use std::env; +use std::fs; +use std::io::prelude::*; +use std::io; +use std::path::{Path, PathBuf}; +use std::process::{Command, Output, Stdio}; use std::str; use syntax::diagnostic::Handler as ErrorHandler; -pub static METADATA_FILENAME: &'static str = "rust.metadata.bin"; +use tempdir::TempDir; + +pub const METADATA_FILENAME: &'static str = "rust.metadata.bin"; pub struct ArchiveConfig<'a> { pub handler: &'a ErrorHandler, - pub dst: Path, - pub lib_search_paths: Vec, + pub dst: PathBuf, + pub lib_search_paths: Vec, pub slib_prefix: String, pub slib_suffix: String, pub maybe_ar_prog: Option @@ -31,8 +34,8 @@ pub struct ArchiveConfig<'a> { pub struct Archive<'a> { handler: &'a ErrorHandler, - dst: Path, - lib_search_paths: Vec, + dst: PathBuf, + lib_search_paths: Vec, slib_prefix: String, slib_suffix: String, maybe_ar_prog: Option @@ -45,25 +48,25 @@ pub struct ArchiveBuilder<'a> { archive: Archive<'a>, work_dir: TempDir, /// Filename of each member that should be added to the archive. - members: Vec, + members: Vec, should_update_symbols: bool, } fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, args: &str, cwd: Option<&Path>, - paths: &[&Path]) -> ProcessOutput { + paths: &[&Path]) -> Output { let ar = match *maybe_ar_prog { Some(ref ar) => &ar[..], None => "ar" }; let mut cmd = Command::new(ar); - cmd.arg(args).args(paths); + cmd.arg(args).args(paths).stdout(Stdio::piped()).stderr(Stdio::piped()); debug!("{:?}", cmd); match cwd { Some(p) => { - cmd.cwd(p); + cmd.current_dir(p); debug!("inside {:?}", p.display()); } None => {} @@ -73,19 +76,19 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, Ok(prog) => { let o = prog.wait_with_output().unwrap(); if !o.status.success() { - handler.err(&format!("{:?} failed with: {}", cmd, o.status)[]); + handler.err(&format!("{:?} failed with: {}", cmd, o.status)); handler.note(&format!("stdout ---\n{}", - str::from_utf8(&o.output[]).unwrap())[]); + str::from_utf8(&o.stdout).unwrap())); handler.note(&format!("stderr ---\n{}", - str::from_utf8(&o.error[]).unwrap()) - []); + str::from_utf8(&o.stderr).unwrap()) + ); handler.abort_if_errors(); } o }, Err(e) => { handler.err(&format!("could not exec `{}`: {}", &ar[..], - e)[]); + e)); handler.abort_if_errors(); panic!("rustc::back::archive::run_ar() should not reach this point"); } @@ -93,14 +96,15 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, } pub fn find_library(name: &str, osprefix: &str, ossuffix: &str, - search_paths: &[Path], handler: &ErrorHandler) -> Path { + search_paths: &[PathBuf], + handler: &ErrorHandler) -> PathBuf { // On Windows, static libraries sometimes show up as libfoo.a and other // times show up as foo.lib let oslibname = format!("{}{}{}", osprefix, name, ossuffix); let unixlibname = format!("lib{}.a", name); for path in search_paths { - debug!("looking for {} inside {:?}", name, path.display()); + debug!("looking for {} inside {:?}", name, path); let test = path.join(&oslibname[..]); if test.exists() { return test } if oslibname != unixlibname { @@ -110,7 +114,7 @@ pub fn find_library(name: &str, osprefix: &str, ossuffix: &str, } handler.fatal(&format!("could not find native static library `{}`, \ perhaps an -L flag is missing?", - name)[]); + name)); } impl<'a> Archive<'a> { @@ -142,7 +146,7 @@ impl<'a> Archive<'a> { /// Lists all files in an archive pub fn files(&self) -> Vec { let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, &[&self.dst]); - let output = str::from_utf8(&output.output[]).unwrap(); + let output = str::from_utf8(&output.stdout).unwrap(); // use lines_any because windows delimits output with `\r\n` instead of // just `\n` output.lines_any().map(|s| s.to_string()).collect() @@ -172,11 +176,11 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. - pub fn add_native_library(&mut self, name: &str) -> old_io::IoResult<()> { + pub fn add_native_library(&mut self, name: &str) -> io::Result<()> { let location = find_library(name, - &self.archive.slib_prefix[], - &self.archive.slib_suffix[], - &self.archive.lib_search_paths[], + &self.archive.slib_prefix, + &self.archive.slib_suffix, + &self.archive.lib_search_paths, self.archive.handler); self.add_archive(&location, name, |_| false) } @@ -187,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> { /// This ignores adding the bytecode from the rlib, and if LTO is enabled /// then the object file also isn't added. pub fn add_rlib(&mut self, rlib: &Path, name: &str, - lto: bool) -> old_io::IoResult<()> { + lto: bool) -> io::Result<()> { // Ignoring obj file starting with the crate name // as simple comparison is not enough - there // might be also an extra name suffix @@ -205,11 +209,11 @@ impl<'a> ArchiveBuilder<'a> { } /// Adds an arbitrary file to this archive - pub fn add_file(&mut self, file: &Path) -> old_io::IoResult<()> { - let filename = Path::new(file.filename().unwrap()); + pub fn add_file(&mut self, file: &Path) -> io::Result<()> { + let filename = Path::new(file.file_name().unwrap()); let new_file = self.work_dir.path().join(&filename); try!(fs::copy(file, &new_file)); - self.members.push(filename); + self.members.push(filename.to_path_buf()); Ok(()) } @@ -226,8 +230,8 @@ impl<'a> ArchiveBuilder<'a> { // though we run it from `self.work_dir`. let abs_dst = env::current_dir().unwrap().join(&self.archive.dst); assert!(!abs_dst.is_relative()); - let mut args = vec![&abs_dst]; - let mut total_len = abs_dst.as_vec().len(); + let mut args = vec![&*abs_dst]; + let mut total_len = abs_dst.to_string_lossy().len(); if self.members.is_empty() { // OSX `ar` does not allow using `r` with no members, but it does @@ -242,10 +246,10 @@ impl<'a> ArchiveBuilder<'a> { // Don't allow the total size of `args` to grow beyond 32,000 bytes. // Windows will raise an error if the argument string is longer than // 32,768, and we leave a bit of extra space for the program name. - static ARG_LENGTH_LIMIT: uint = 32000; + const ARG_LENGTH_LIMIT: usize = 32_000; for member_name in &self.members { - let len = member_name.as_vec().len(); + let len = member_name.to_string_lossy().len(); // `len + 1` to account for the space that's inserted before each // argument. (Windows passes command-line arguments as a single @@ -258,7 +262,7 @@ impl<'a> ArchiveBuilder<'a> { args.clear(); args.push(&abs_dst); - total_len = abs_dst.as_vec().len(); + total_len = abs_dst.to_string_lossy().len(); } args.push(member_name); @@ -275,7 +279,7 @@ impl<'a> ArchiveBuilder<'a> { } fn add_archive(&mut self, archive: &Path, name: &str, - mut skip: F) -> old_io::IoResult<()> + mut skip: F) -> io::Result<()> where F: FnMut(&str) -> bool, { let loc = TempDir::new("rsar").unwrap(); @@ -296,9 +300,10 @@ impl<'a> ArchiveBuilder<'a> { // We skip any files explicitly desired for skipping, and we also skip // all SYMDEF files as these are just magical placeholders which get // re-created when we make a new archive anyway. - let files = try!(fs::readdir(loc.path())); - for file in &files { - let filename = file.filename_str().unwrap(); + let files = try!(fs::read_dir(loc.path())); + for file in files { + let file = try!(file).path(); + let filename = file.file_name().unwrap().to_str().unwrap(); if skip(filename) { continue } if filename.contains(".SYMDEF") { continue } @@ -313,10 +318,9 @@ impl<'a> ArchiveBuilder<'a> { filename }; let new_filename = self.work_dir.path().join(&filename[..]); - try!(fs::rename(file, &new_filename)); - self.members.push(Path::new(filename)); + try!(fs::rename(&file, &new_filename)); + self.members.push(PathBuf::from(filename)); } Ok(()) } } - diff --git a/src/librustc_back/arm.rs b/src/librustc_back/arm.rs index a4417b49f1..7325e4e7a2 100644 --- a/src/librustc_back/arm.rs +++ b/src/librustc_back/arm.rs @@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a:0:64-n32".to_string() } - abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => { "e-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ -f32:32:32-f64:64:64\ diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs index acf49d1ca4..231f6ee3be 100644 --- a/src/librustc_back/fs.rs +++ b/src/librustc_back/fs.rs @@ -8,15 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io; -use std::old_io::fs; +use std::io; use std::env; +#[allow(deprecated)] use std::old_path::{self, GenericPath}; +#[allow(deprecated)] use std::old_io; +use std::path::{Path, PathBuf}; /// Returns an absolute path in the filesystem that `path` points to. The /// returned path does not contain any symlinks in its hierarchy. -pub fn realpath(original: &Path) -> old_io::IoResult { - static MAX_LINKS_FOLLOWED: uint = 256; - let original = try!(env::current_dir()).join(original); +#[allow(deprecated)] // readlink is deprecated +pub fn realpath(original: &Path) -> io::Result { + let old = old_path::Path::new(original.to_str().unwrap()); + match old_realpath(&old) { + Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())), + Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)) + } +} + +#[allow(deprecated)] +fn old_realpath(original: &old_path::Path) -> old_io::IoResult { + use std::old_io::fs; + const MAX_LINKS_FOLLOWED: usize = 256; + let original = old_path::Path::new(env::current_dir().unwrap() + .to_str().unwrap()).join(original); // Right now lstat on windows doesn't work quite well if cfg!(windows) { @@ -55,8 +69,9 @@ pub fn realpath(original: &Path) -> old_io::IoResult { mod test { use std::old_io; use std::old_io::fs::{File, symlink, mkdir, mkdir_recursive}; - use super::realpath; + use super::old_realpath as realpath; use std::old_io::TempDir; + use std::old_path::{Path, GenericPath}; #[test] fn realpath_works() { diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index d589b06320..7591ebf67f 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -21,6 +21,8 @@ //! one that doesn't; the one that doesn't might get decent parallel //! build speedups. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_back"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -33,14 +35,15 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(hash)] -#![feature(int_uint)] +#![feature(old_fs)] #![feature(old_io)] -#![feature(os)] #![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(env)] +#![feature(rand)] +#![feature(path_ext)] +#![feature(step_by)] +#![cfg_attr(test, feature(test, rand))] extern crate syntax; extern crate serialize; @@ -48,6 +51,7 @@ extern crate serialize; pub mod abi; pub mod archive; +pub mod tempdir; pub mod arm; pub mod fs; pub mod mips; diff --git a/src/librustc_back/mips.rs b/src/librustc_back/mips.rs index cb44fe117f..b46150f75d 100644 --- a/src/librustc_back/mips.rs +++ b/src/librustc_back/mips.rs @@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a:0:64-n32".to_string() } - abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => { "E-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ -f32:32:32-f64:64:64\ diff --git a/src/librustc_back/mipsel.rs b/src/librustc_back/mipsel.rs index 7ee357fb1e..c7fa7aa879 100644 --- a/src/librustc_back/mipsel.rs +++ b/src/librustc_back/mipsel.rs @@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a:0:64-n32".to_string() } - abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => { "e-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ -f32:32:32-f64:64:64\ diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index e7419d4bec..ff3f0b78f9 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -8,28 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use std::collections::HashSet; use std::env; -use std::old_io::IoError; +use std::io; +use std::path::{Path, PathBuf}; use syntax::ast; -pub struct RPathConfig where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result, -{ - pub used_crates: Vec<(ast::CrateNum, Option)>, - pub out_filename: Path, +pub struct RPathConfig<'a> { + pub used_crates: Vec<(ast::CrateNum, Option)>, + pub out_filename: PathBuf, pub is_like_osx: bool, pub has_rpath: bool, - pub get_install_prefix_lib_path: F, - pub realpath: G, + pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf, + pub realpath: &'a mut FnMut(&Path) -> io::Result, } -pub fn get_rpath_flags(config: RPathConfig) -> Vec where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result, -{ +pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec { // No rpath on windows if !config.has_rpath { return Vec::new(); @@ -49,15 +43,12 @@ pub fn get_rpath_flags(config: RPathConfig) -> Vec where fn rpaths_to_flags(rpaths: &[String]) -> Vec { let mut ret = Vec::new(); for rpath in rpaths { - ret.push(format!("-Wl,-rpath,{}", &(*rpath)[])); + ret.push(format!("-Wl,-rpath,{}", &(*rpath))); } return ret; } -fn get_rpaths(mut config: RPathConfig, libs: &[Path]) -> Vec where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result, -{ +fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec { debug!("output: {:?}", config.out_filename.display()); debug!("libs:"); for libpath in libs { @@ -67,7 +58,7 @@ fn get_rpaths(mut config: RPathConfig, libs: &[Path]) -> Vec // Use relative paths to the libraries. Binaries can be moved // as long as they maintain the relative relationship to the // crates they depend on. - let rel_rpaths = get_rpaths_relative_to_output(&mut config, libs); + let rel_rpaths = get_rpaths_relative_to_output(config, libs); // And a final backup rpath to the global library location. let fallback_rpaths = vec!(get_install_prefix_rpath(config)); @@ -90,18 +81,12 @@ fn get_rpaths(mut config: RPathConfig, libs: &[Path]) -> Vec return rpaths; } -fn get_rpaths_relative_to_output(config: &mut RPathConfig, - libs: &[Path]) -> Vec where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result, -{ +fn get_rpaths_relative_to_output(config: &mut RPathConfig, + libs: &[PathBuf]) -> Vec { libs.iter().map(|a| get_rpath_relative_to_output(config, a)).collect() } -fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result, -{ +fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String { // Mac doesn't appear to support $ORIGIN let prefix = if config.is_like_osx { "@loader_path" @@ -114,22 +99,63 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path lib.pop(); let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap(); output.pop(); - let relative = lib.path_relative_from(&output); - let relative = relative.expect("could not create rpath relative to output"); + let relative = path_relative_from(&lib, &output) + .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib)); // FIXME (#9639): This needs to handle non-utf8 paths - format!("{}/{}", - prefix, - relative.as_str().expect("non-utf8 component in path")) + format!("{}/{}", prefix, + relative.to_str().expect("non-utf8 component in path")) } -fn get_install_prefix_rpath(config: RPathConfig) -> String where - F: FnOnce() -> Path, - G: FnMut(&Path) -> Result, -{ +// This routine is adapted from the *old* Path's `path_relative_from` +// function, which works differently from the new `relative_from` function. +// In particular, this handles the case on unix where both paths are +// absolute but with only the root as the common directory. +fn path_relative_from(path: &Path, base: &Path) -> Option { + use std::path::Component; + + if path.is_absolute() != base.is_absolute() { + if path.is_absolute() { + Some(PathBuf::from(path)) + } else { + None + } + } else { + let mut ita = path.components(); + let mut itb = base.components(); + let mut comps: Vec = vec![]; + loop { + match (ita.next(), itb.next()) { + (None, None) => break, + (Some(a), None) => { + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + (None, _) => comps.push(Component::ParentDir), + (Some(a), Some(b)) if comps.is_empty() && a == b => (), + (Some(a), Some(b)) if b == Component::CurDir => comps.push(a), + (Some(_), Some(b)) if b == Component::ParentDir => return None, + (Some(a), Some(_)) => { + comps.push(Component::ParentDir); + for _ in itb { + comps.push(Component::ParentDir); + } + comps.push(a); + comps.extend(ita.by_ref()); + break; + } + } + } + Some(comps.iter().map(|c| c.as_os_str()).collect()) + } +} + + +fn get_install_prefix_rpath(config: &mut RPathConfig) -> String { let path = (config.get_install_prefix_lib_path)(); let path = env::current_dir().unwrap().join(&path); // FIXME (#9639): This needs to handle non-utf8 paths - path.as_str().expect("non-utf8 component in rpath").to_string() + path.to_str().expect("non-utf8 component in rpath").to_string() } fn minimize_rpaths(rpaths: &[String]) -> Vec { @@ -147,6 +173,7 @@ fn minimize_rpaths(rpaths: &[String]) -> Vec { mod test { use super::{RPathConfig}; use super::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output}; + use std::path::{Path, PathBuf}; #[test] fn test_rpaths_to_flags() { @@ -195,49 +222,31 @@ mod test { } #[test] - #[cfg(any(target_os = "linux", target_os = "android"))] fn test_rpath_relative() { - let config = &mut RPathConfig { - used_crates: Vec::new(), - out_filename: Path::new("bin/rustc"), - get_install_prefix_lib_path: || panic!(), - has_rpath: true, - is_like_osx: false, - realpath: |p| Ok(p.clone()) - }; - let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); - assert_eq!(res, "$ORIGIN/../lib"); - } - - #[test] - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd"))] - fn test_rpath_relative() { - let config = &mut RPathConfig { - used_crates: Vec::new(), - has_rpath: true, - is_like_osx: false, - out_filename: Path::new("bin/rustc"), - get_install_prefix_lib_path: || panic!(), - realpath: |p| Ok(p.clone()) - }; - let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); - assert_eq!(res, "$ORIGIN/../lib"); - } - - #[test] - #[cfg(target_os = "macos")] - fn test_rpath_relative() { - let config = &mut RPathConfig { - used_crates: Vec::new(), - has_rpath: true, - is_like_osx: true, - out_filename: Path::new("bin/rustc"), - get_install_prefix_lib_path: || panic!(), - realpath: |p| Ok(p.clone()) - }; - let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); - assert_eq!(res, "@loader_path/../lib"); + if cfg!(target_os = "macos") { + let config = &mut RPathConfig { + used_crates: Vec::new(), + has_rpath: true, + is_like_osx: true, + out_filename: PathBuf::from("bin/rustc"), + get_install_prefix_lib_path: &mut || panic!(), + realpath: &mut |p| Ok(p.to_path_buf()), + }; + let res = get_rpath_relative_to_output(config, + Path::new("lib/libstd.so")); + assert_eq!(res, "@loader_path/../lib"); + } else { + let config = &mut RPathConfig { + used_crates: Vec::new(), + out_filename: PathBuf::from("bin/rustc"), + get_install_prefix_lib_path: &mut || panic!(), + has_rpath: true, + is_like_osx: false, + realpath: &mut |p| Ok(p.to_path_buf()), + }; + let res = get_rpath_relative_to_output(config, + Path::new("lib/libstd.so")); + assert_eq!(res, "$ORIGIN/../lib"); + } } } diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 6654a46f7c..898f20e745 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -14,7 +14,7 @@ #![allow(deprecated)] // to_be32 -use std::iter::{range_step, repeat}; +use std::iter::repeat; use std::num::Int; use std::slice::bytes::{MutableByteVector, copy_memory}; use serialize::hex::ToHex; @@ -64,7 +64,7 @@ impl ToBits for u64 { fn add_bytes_to_bits(bits: T, bytes: T) -> T { let (new_high_bits, new_low_bits) = bytes.to_bits(); - if new_high_bits > Int::zero() { + if new_high_bits > T::zero() { panic!("numeric overflow occurred.") } @@ -90,36 +90,36 @@ trait FixedBuffer { /// Zero the buffer up until the specified index. The buffer position currently must not be /// greater than that index. - fn zero_until(&mut self, idx: uint); + fn zero_until(&mut self, idx: usize); /// Get a slice of the buffer of the specified size. There must be at least that many bytes /// remaining in the buffer. - fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8]; + fn next<'s>(&'s mut self, len: usize) -> &'s mut [u8]; /// Get the current buffer. The buffer must already be full. This clears the buffer as well. fn full_buffer<'s>(&'s mut self) -> &'s [u8]; /// Get the current position of the buffer. - fn position(&self) -> uint; + fn position(&self) -> usize; /// Get the number of bytes remaining in the buffer until it is full. - fn remaining(&self) -> uint; + fn remaining(&self) -> usize; /// Get the size of the buffer - fn size(&self) -> uint; + fn size(&self) -> usize; } /// A FixedBuffer of 64 bytes useful for implementing Sha256 which has a 64 byte blocksize. struct FixedBuffer64 { buffer: [u8; 64], - buffer_idx: uint, + buffer_idx: usize, } impl FixedBuffer64 { /// Create a new FixedBuffer64 fn new() -> FixedBuffer64 { return FixedBuffer64 { - buffer: [0u8; 64], + buffer: [0; 64], buffer_idx: 0 }; } @@ -139,15 +139,15 @@ impl FixedBuffer for FixedBuffer64 { let buffer_remaining = size - self.buffer_idx; if input.len() >= buffer_remaining { copy_memory( - &mut self.buffer[self.buffer_idx..size], - &input[..buffer_remaining]); + &input[..buffer_remaining], + &mut self.buffer[self.buffer_idx..size]); self.buffer_idx = 0; func(&self.buffer); i += buffer_remaining; } else { copy_memory( - &mut self.buffer[self.buffer_idx..self.buffer_idx + input.len()], - input); + input, + &mut self.buffer[self.buffer_idx..self.buffer_idx + input.len()]); self.buffer_idx += input.len(); return; } @@ -165,8 +165,8 @@ impl FixedBuffer for FixedBuffer64 { // be empty. let input_remaining = input.len() - i; copy_memory( - &mut self.buffer[..input_remaining], - &input[i..]); + &input[i..], + &mut self.buffer[..input_remaining]); self.buffer_idx += input_remaining; } @@ -174,13 +174,13 @@ impl FixedBuffer for FixedBuffer64 { self.buffer_idx = 0; } - fn zero_until(&mut self, idx: uint) { + fn zero_until(&mut self, idx: usize) { assert!(idx >= self.buffer_idx); self.buffer[self.buffer_idx..idx].set_memory(0); self.buffer_idx = idx; } - fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] { + fn next<'s>(&'s mut self, len: usize) -> &'s mut [u8] { self.buffer_idx += len; return &mut self.buffer[self.buffer_idx - len..self.buffer_idx]; } @@ -191,11 +191,11 @@ impl FixedBuffer for FixedBuffer64 { return &self.buffer[..64]; } - fn position(&self) -> uint { self.buffer_idx } + fn position(&self) -> usize { self.buffer_idx } - fn remaining(&self) -> uint { 64 - self.buffer_idx } + fn remaining(&self) -> usize { 64 - self.buffer_idx } - fn size(&self) -> uint { 64 } + fn size(&self) -> usize { 64 } } /// The StandardPadding trait adds a method useful for Sha256 to a FixedBuffer struct. @@ -204,11 +204,11 @@ trait StandardPadding { /// guaranteed to have exactly rem remaining bytes when it returns. If there are not at least /// rem bytes available, the buffer will be zero padded, processed, cleared, and then filled /// with zeros again until only rem bytes are remaining. - fn standard_padding(&mut self, rem: uint, func: F) where F: FnMut(&[u8]); + fn standard_padding(&mut self, rem: usize, func: F) where F: FnMut(&[u8]); } impl StandardPadding for T { - fn standard_padding(&mut self, rem: uint, mut func: F) where F: FnMut(&[u8]) { + fn standard_padding(&mut self, rem: usize, mut func: F) where F: FnMut(&[u8]) { let size = self.size(); self.next(1)[0] = 128; @@ -244,7 +244,7 @@ pub trait Digest { fn reset(&mut self); /// Get the output size in bits. - fn output_bits(&self) -> uint; + fn output_bits(&self) -> usize; /// Convenience function that feeds a string into a digest. /// @@ -258,7 +258,7 @@ pub trait Digest { /// Convenience function that retrieves the result of a digest as a /// newly allocated vec of bytes. fn result_bytes(&mut self) -> Vec { - let mut buf: Vec = repeat(0u8).take((self.output_bits()+7)/8).collect(); + let mut buf: Vec = repeat(0).take((self.output_bits()+7)/8).collect(); self.result(&mut buf); buf } @@ -342,22 +342,24 @@ impl Engine256State { let mut g = self.h6; let mut h = self.h7; - let mut w = [0u32; 64]; + let mut w = [0; 64]; // Sha-512 and Sha-256 use basically the same calculations which are implemented // by these macros. Inlining the calculations seems to result in better generated code. macro_rules! schedule_round { ($t:expr) => ( - w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16]; - ) + w[$t] = sigma1(w[$t - 2]).wrapping_add(w[$t - 7]) + .wrapping_add(sigma0(w[$t - 15])).wrapping_add(w[$t - 16]); + ) } macro_rules! sha2_round { ($A:ident, $B:ident, $C:ident, $D:ident, $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => ( { - $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t]; - $D += $H; - $H += sum0($A) + maj($A, $B, $C); + $H = $H.wrapping_add(sum1($E)).wrapping_add(ch($E, $F, $G)) + .wrapping_add($K[$t]).wrapping_add(w[$t]); + $D = $D.wrapping_add($H); + $H = $H.wrapping_add(sum0($A)).wrapping_add(maj($A, $B, $C)); } ) } @@ -366,7 +368,7 @@ impl Engine256State { // Putting the message schedule inside the same loop as the round calculations allows for // the compiler to generate better code. - for t in range_step(0, 48, 8) { + for t in (0..48).step_by(8) { schedule_round!(t + 16); schedule_round!(t + 17); schedule_round!(t + 18); @@ -386,7 +388,7 @@ impl Engine256State { sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7); } - for t in range_step(48, 64, 8) { + for t in (48..64).step_by(8) { sha2_round!(a, b, c, d, e, f, g, h, K32, t); sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1); sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2); @@ -397,14 +399,14 @@ impl Engine256State { sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7); } - self.h0 += a; - self.h1 += b; - self.h2 += c; - self.h3 += d; - self.h4 += e; - self.h5 += f; - self.h6 += g; - self.h7 += h; + self.h0 = self.h0.wrapping_add(a); + self.h1 = self.h1.wrapping_add(b); + self.h2 = self.h2.wrapping_add(c); + self.h3 = self.h3.wrapping_add(d); + self.h4 = self.h4.wrapping_add(e); + self.h5 = self.h5.wrapping_add(f); + self.h6 = self.h6.wrapping_add(g); + self.h7 = self.h7.wrapping_add(h); } } @@ -512,7 +514,7 @@ impl Digest for Sha256 { self.engine.reset(&H256); } - fn output_bits(&self) -> uint { 256 } + fn output_bits(&self) -> usize { 256 } } static H256: [u32; 8] = [ @@ -535,7 +537,7 @@ mod tests { use self::rand::isaac::IsaacRng; use serialize::hex::FromHex; use std::iter::repeat; - use std::num::Int; + use std::u64; use super::{Digest, Sha256, FixedBuffer}; // A normal addition - no overflow occurs @@ -546,9 +548,9 @@ mod tests { // A simple failure case - adding 1 to the max value #[test] - #[should_fail] + #[should_panic] fn test_add_bytes_to_bits_overflow() { - super::add_bytes_to_bits::(Int::max_value(), 1); + super::add_bytes_to_bits::(u64::MAX, 1); } struct Test { @@ -604,14 +606,14 @@ mod tests { let tests = wikipedia_tests; - let mut sh = box Sha256::new(); + let mut sh: Box<_> = box Sha256::new(); test_hash(&mut *sh, &tests); } /// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is /// correct. - fn test_digest_1million_random(digest: &mut D, blocksize: uint, expected: &str) { + fn test_digest_1million_random(digest: &mut D, blocksize: usize, expected: &str) { let total_size = 1000000; let buffer: Vec = repeat('a' as u8).take(blocksize * 2).collect(); let mut rng = IsaacRng::new_unseeded(); @@ -620,7 +622,7 @@ mod tests { digest.reset(); while count < total_size { - let next: uint = rng.gen_range(0, 2 * blocksize + 1); + let next: usize = rng.gen_range(0, 2 * blocksize + 1); let remaining = total_size - count; let size = if next > remaining { remaining } else { next }; digest.input(&buffer[..size]); @@ -658,7 +660,7 @@ mod bench { #[bench] pub fn sha256_10(b: &mut Bencher) { let mut sh = Sha256::new(); - let bytes = [1u8; 10]; + let bytes = [1; 10]; b.iter(|| { sh.input(&bytes); }); @@ -668,7 +670,7 @@ mod bench { #[bench] pub fn sha256_1k(b: &mut Bencher) { let mut sh = Sha256::new(); - let bytes = [1u8; 1024]; + let bytes = [1; 1024]; b.iter(|| { sh.input(&bytes); }); @@ -678,7 +680,7 @@ mod bench { #[bench] pub fn sha256_64k(b: &mut Bencher) { let mut sh = Sha256::new(); - let bytes = [1u8; 65536]; + let bytes = [1; 65536]; b.iter(|| { sh.input(&bytes); }); diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index c33d10bfba..f9416d53a8 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -48,7 +48,6 @@ use std::fmt; use std::hash::{Hash, SipHasher, Hasher}; -use std::iter::range_step; use syntax::ast; use syntax::visit; @@ -64,7 +63,7 @@ impl Svh { } pub fn as_str<'a>(&'a self) -> &'a str { - &self.hash[] + &self.hash } pub fn calculate(metadata: &Vec, krate: &ast::Crate) -> Svh { @@ -103,7 +102,7 @@ impl Svh { let hash = state.finish(); return Svh { - hash: range_step(0, 64, 4).map(|i| hex(hash >> i)).collect() + hash: (0..64).step_by(4).map(|i| hex(hash >> i)).collect() }; fn hex(b: u64) -> char { @@ -188,8 +187,8 @@ mod svh_visitor { SawTy, SawGenerics, SawFn, - SawTyMethod, - SawTraitMethod, + SawTraitItem, + SawImplItem, SawStructField, SawVariant, SawExplicitSelf, @@ -222,7 +221,7 @@ mod svh_visitor { SawExprLoop(Option), SawExprField(token::InternedString), - SawExprTupField(uint), + SawExprTupField(usize), SawExprBreak(Option), SawExprAgain(Option), @@ -244,8 +243,7 @@ mod svh_visitor { SawExprAssignOp(ast::BinOp_), SawExprIndex, SawExprRange, - SawExprPath, - SawExprQPath, + SawExprPath(Option), SawExprAddrOf(ast::Mutability), SawExprRet, SawExprInlineAsm(&'a ast::InlineAsm), @@ -277,8 +275,7 @@ mod svh_visitor { ExprTupField(_, id) => SawExprTupField(id.node), ExprIndex(..) => SawExprIndex, ExprRange(..) => SawExprRange, - ExprPath(..) => SawExprPath, - ExprQPath(..) => SawExprQPath, + ExprPath(ref qself, _) => SawExprPath(qself.as_ref().map(|q| q.position)), ExprAddrOf(m, _) => SawExprAddrOf(m), ExprBreak(id) => SawExprBreak(id.map(content)), ExprAgain(id) => SawExprAgain(id.map(content)), @@ -329,7 +326,7 @@ mod svh_visitor { // macro invocations, namely macro_rules definitions, // *can* appear as items, even in the expanded crate AST. - if ¯o_name(mac)[] == "macro_rules" { + if ¯o_name(mac)[..] == "macro_rules" { // Pretty-printing definition to a string strips out // surface artifacts (currently), such as the span // information, yielding a content-based hash. @@ -356,7 +353,7 @@ mod svh_visitor { fn macro_name(mac: &Mac) -> token::InternedString { match &mac.node { &MacInvocTT(ref path, ref _tts, ref _stx_ctxt) => { - let s = &path.segments[]; + let s = &path.segments; assert_eq!(s.len(), 1); content(s[0].identifier) } @@ -465,12 +462,12 @@ mod svh_visitor { SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s) } - fn visit_ty_method(&mut self, t: &TypeMethod) { - SawTyMethod.hash(self.st); visit::walk_ty_method(self, t) + fn visit_trait_item(&mut self, ti: &TraitItem) { + SawTraitItem.hash(self.st); visit::walk_trait_item(self, ti) } - fn visit_trait_item(&mut self, t: &TraitItem) { - SawTraitMethod.hash(self.st); visit::walk_trait_item(self, t) + fn visit_impl_item(&mut self, ii: &ImplItem) { + SawImplItem.hash(self.st); visit::walk_impl_item(self, ii) } fn visit_struct_field(&mut self, s: &StructField) { diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 904b337c03..7dcd6ba6cd 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::{Command, IoError, OtherIoError}; +use std::io; +use std::process::Command; use target::TargetOptions; use self::Arch::*; #[allow(non_camel_case_types)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Arch { Armv7, Armv7s, @@ -40,16 +41,16 @@ pub fn get_sdk_root(sdk_name: &str) -> String { .arg("--show-sdk-path") .arg("-sdk") .arg(sdk_name) - .spawn() - .and_then(|c| c.wait_with_output()) + .output() .and_then(|output| { if output.status.success() { - Ok(String::from_utf8(output.output).unwrap()) + Ok(String::from_utf8(output.stdout).unwrap()) } else { - Err(IoError { - kind: OtherIoError, - desc: "process exit with error", - detail: String::from_utf8(output.error).ok()}) + let error = String::from_utf8(output.stderr); + let error = format!("process exit with error: {}", + error.unwrap()); + Err(io::Error::new(io::ErrorKind::Other, + &error[..])) } }); diff --git a/src/test/compile-fail/issue-13853-4.rs b/src/librustc_back/target/bitrig_base.rs similarity index 54% rename from src/test/compile-fail/issue-13853-4.rs rename to src/librustc_back/target/bitrig_base.rs index b0db9e58db..6e5a48c0ea 100644 --- a/src/test/compile-fail/issue-13853-4.rs +++ b/src/librustc_back/target/bitrig_base.rs @@ -8,14 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct AutoBuilder<'a> { - context: &'a isize -} +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + linker: "cc".to_string(), + dynamic_linking: true, + executables: true, + morestack: false, + linker_is_gnu: true, + has_rpath: true, + position_independent_executables: true, + pre_link_args: vec!( + ), -impl<'a> Drop for AutoBuilder<'a> { - //~^ ERROR cannot implement a destructor on a structure with type parameters - fn drop(&mut self) { + .. Default::default() } } - -fn main() {} diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_back/target/dragonfly_base.rs index 79d79b7e73..a56621ff97 100644 --- a/src/librustc_back/target/dragonfly_base.rs +++ b/src/librustc_back/target/dragonfly_base.rs @@ -32,4 +32,3 @@ pub fn opts() -> TargetOptions { .. Default::default() } } - diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs index ab8398fc60..dcf1a12f2c 100644 --- a/src/librustc_back/target/freebsd_base.rs +++ b/src/librustc_back/target/freebsd_base.rs @@ -27,4 +27,3 @@ pub fn opts() -> TargetOptions { .. Default::default() } } - diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 01a5f0d6e2..07528df97f 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -48,7 +48,7 @@ use serialize::json::Json; use syntax::{diagnostic, abi}; use std::default::Default; -use std::old_io::fs::PathExtensions; +use std::io::prelude::*; mod windows_base; mod linux_base; @@ -56,6 +56,7 @@ mod apple_base; mod apple_ios_base; mod freebsd_base; mod dragonfly_base; +mod bitrig_base; mod openbsd_base; mod armv7_apple_ios; @@ -80,6 +81,7 @@ mod x86_64_apple_ios; mod x86_64_pc_windows_gnu; mod x86_64_unknown_freebsd; mod x86_64_unknown_dragonfly; +mod x86_64_unknown_bitrig; mod x86_64_unknown_linux_gnu; mod x86_64_unknown_openbsd; @@ -155,7 +157,7 @@ pub struct TargetOptions { /// particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. pub is_like_osx: bool, /// Whether the target toolchain is like Windows'. Only useful for compiling against Windows, - /// only realy used for figuring out how to find libraries, since Windows uses its own + /// only really used for figuring out how to find libraries, since Windows uses its own /// library naming convention. Defaults to false. pub is_like_windows: bool, /// Whether the target toolchain is like Android's. Only useful for compiling against Android. @@ -237,7 +239,7 @@ impl Target { .and_then(|os| os.map(|s| s.to_string())) { Some(val) => val, None => - handler.fatal(&format!("Field {} in target specification is required", name)[]) + handler.fatal(&format!("Field {} in target specification is required", name)) } }; @@ -300,22 +302,26 @@ impl Target { base } - /// Search RUST_TARGET_PATH for a JSON file specifying the given target triple. Note that it - /// could also just be a bare filename already, so also check for that. If one of the hardcoded - /// targets we know about, just return it directly. + /// Search RUST_TARGET_PATH for a JSON file specifying the given target + /// triple. Note that it could also just be a bare filename already, so also + /// check for that. If one of the hardcoded targets we know about, just + /// return it directly. /// - /// The error string could come from any of the APIs called, including filesystem access and - /// JSON decoding. + /// The error string could come from any of the APIs called, including + /// filesystem access and JSON decoding. pub fn search(target: &str) -> Result { use std::env; use std::ffi::OsString; - use std::old_io::File; - use std::old_path::Path; + use std::fs::File; + use std::path::{Path, PathBuf}; use serialize::json; fn load_file(path: &Path) -> Result { - let mut f = try!(File::open(path).map_err(|e| format!("{:?}", e))); - let obj = try!(json::from_reader(&mut f).map_err(|e| format!("{:?}", e))); + let mut f = try!(File::open(path).map_err(|e| e.to_string())); + let mut contents = Vec::new(); + try!(f.read_to_end(&mut contents).map_err(|e| e.to_string())); + let obj = try!(json::from_reader(&mut &contents[..]) + .map_err(|e| e.to_string())); Ok(Target::from_json(obj)) } @@ -361,6 +367,7 @@ impl Target { i686_unknown_dragonfly, x86_64_unknown_dragonfly, + x86_64_unknown_bitrig, x86_64_unknown_openbsd, x86_64_apple_darwin, @@ -386,15 +393,16 @@ impl Target { let path = { let mut target = target.to_string(); target.push_str(".json"); - Path::new(target) + PathBuf::from(target) }; - let target_path = env::var_os("RUST_TARGET_PATH").unwrap_or(OsString::from_str("")); + let target_path = env::var_os("RUST_TARGET_PATH") + .unwrap_or(OsString::new()); // FIXME 16351: add a sane default search path? for dir in env::split_paths(&target_path) { - let p = dir.join(path.clone()); + let p = dir.join(&path); if p.is_file() { return load_file(&p); } diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index 42220a87bd..0f2ab32be2 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -20,9 +20,13 @@ pub fn opts() -> TargetOptions { linker_is_gnu: true, has_rpath: true, pre_link_args: vec!( + // GNU-style linkers will use this to omit linking to libraries + // which don't actually fulfill any relocations, but only for + // libraries which follow this flag. Thus, use it before + // specifying libraries to link to. + "-Wl,--as-needed".to_string(), ), position_independent_executables: true, .. Default::default() } } - diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_back/target/x86_64_unknown_bitrig.rs new file mode 100644 index 0000000000..7b7877c0c6 --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_bitrig.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::bitrig_base::opts(); + base.pre_link_args.push("-m64".to_string()); + + Target { + data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ + f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\ + s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(), + llvm_target: "x86_64-unknown-bitrig".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "bitrig".to_string(), + options: base, + } +} diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs new file mode 100644 index 0000000000..b12732f879 --- /dev/null +++ b/src/librustc_back/tempdir.rs @@ -0,0 +1,120 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::io::{self, Error, ErrorKind}; +use std::fs; +use std::path::{self, PathBuf, Path}; +use std::rand::{thread_rng, Rng}; + +/// A wrapper for a path to temporary directory implementing automatic +/// scope-based deletion. +pub struct TempDir { + path: Option, +} + +// 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: usize = 12; + +impl TempDir { + /// Attempts to make a temporary directory inside of `tmpdir` whose 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. + #[allow(deprecated)] // rand usage + pub fn new_in>(tmpdir: P, prefix: &str) + -> io::Result { + let storage; + let mut tmpdir = tmpdir.as_ref(); + if !tmpdir.is_absolute() { + let cur_dir = try!(env::current_dir()); + storage = cur_dir.join(tmpdir); + tmpdir = &storage; + // return TempDir::new_in(&cur_dir.join(tmpdir), prefix); + } + + let mut rng = thread_rng(); + for _ in 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::create_dir(&path) { + Ok(_) => return Ok(TempDir { path: Some(path) }), + Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {} + Err(e) => return Err(e) + } + } + + Err(Error::new(ErrorKind::AlreadyExists, + "too many temporary directories already exist")) + } + + /// Attempts to make a temporary directory inside of `env::temp_dir()` whose + /// 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. + #[allow(deprecated)] + pub fn new(prefix: &str) -> io::Result { + TempDir::new_in(&env::temp_dir(), prefix) + } + + /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. + /// This discards the wrapper so that the automatic deletion of the + /// temporary directory is prevented. + pub fn into_path(mut self) -> PathBuf { + self.path.take().unwrap() + } + + /// Access the wrapped `std::path::Path` to the temporary directory. + pub fn path(&self) -> &path::Path { + self.path.as_ref().unwrap() + } + + /// Close and remove the temporary directory + /// + /// Although `TempDir` removes the directory on drop, in the destructor + /// any errors are ignored. To detect errors cleaning up the temporary + /// directory, call `close` instead. + pub fn close(mut self) -> io::Result<()> { + self.cleanup_dir() + } + + fn cleanup_dir(&mut self) -> io::Result<()> { + match self.path { + Some(ref p) => fs::remove_dir_all(p), + None => Ok(()) + } + } +} + +impl Drop for TempDir { + fn drop(&mut self) { + let _ = self.cleanup_dir(); + } +} + +// the tests for this module need to change the path using change_dir, +// and this doesn't play nicely with other tests so these unit tests are located +// in src/test/run-pass/tempfile.rs diff --git a/src/librustc_back/x86.rs b/src/librustc_back/x86.rs index 9d1b7347d0..1c6eacc355 100644 --- a/src/librustc_back/x86.rs +++ b/src/librustc_back/x86.rs @@ -45,13 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string() } - abi::OsFreebsd => { - "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string() - } - abi::OsDragonfly => { - "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string() - } - abi::OsOpenbsd => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => { "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string() } diff --git a/src/librustc_back/x86_64.rs b/src/librustc_back/x86_64.rs index 2f13bb3158..d016bd12c6 100644 --- a/src/librustc_back/x86_64.rs +++ b/src/librustc_back/x86_64.rs @@ -47,17 +47,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs s0:64:64-f80:128:128-n8:16:32:64-S128".to_string() } - abi::OsFreebsd => { - "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ - f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ - s0:64:64-f80:128:128-n8:16:32:64-S128".to_string() - } - abi::OsDragonfly => { - "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ - f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ - s0:64:64-f80:128:128-n8:16:32:64-S128".to_string() - } - abi::OsOpenbsd => { + abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => { "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\ s0:64:64-f80:128:128-n8:16:32:64-S128".to_string() diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index 370a5d48de..93a2a5d125 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_bitflags"] #![feature(staged_api)] #![staged_api] @@ -15,6 +18,7 @@ #![feature(no_std)] #![no_std] #![unstable(feature = "rustc_private")] +#![cfg_attr(test, feature(hash))] //! A typesafe bitmask flag generator. @@ -26,9 +30,10 @@ /// The flags should only be defined for integer types, otherwise unexpected /// type errors may occur at compile time. /// -/// # Example +/// # Examples /// /// ```{.rust} +/// # #![feature(rustc_private)] /// #[macro_use] extern crate rustc_bitflags; /// /// bitflags! { @@ -55,6 +60,7 @@ /// The generated `struct`s can also be extended with type and trait implementations: /// /// ```{.rust} +/// # #![feature(rustc_private)] /// #[macro_use] extern crate rustc_bitflags; /// /// use std::fmt; @@ -83,7 +89,7 @@ /// let mut flags = FLAG_A | FLAG_B; /// flags.clear(); /// assert!(flags.is_empty()); -/// assert_eq!(format!("{:?}", flags).as_slice(), "hi!"); +/// assert_eq!(format!("{:?}", flags), "hi!"); /// } /// ``` /// @@ -316,7 +322,7 @@ mod tests { bitflags! { flags AnotherSetOfFlags: i8 { - const AnotherFlag = -1_i8, + const AnotherFlag = -1, } } @@ -327,7 +333,7 @@ mod tests { assert_eq!(FlagABC.bits(), 0b00000111); assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00); - assert_eq!(AnotherFlag.bits(), !0_i8); + assert_eq!(AnotherFlag.bits(), !0); } #[test] @@ -338,7 +344,7 @@ mod tests { assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB)); assert!(Flags::from_bits(0b1000) == None); - assert!(AnotherSetOfFlags::from_bits(!0_i8) == Some(AnotherFlag)); + assert!(AnotherSetOfFlags::from_bits(!0) == Some(AnotherFlag)); } #[test] @@ -350,7 +356,7 @@ mod tests { assert!(Flags::from_bits_truncate(0b1000) == Flags::empty()); assert!(Flags::from_bits_truncate(0b1001) == FlagA); - assert!(AnotherSetOfFlags::from_bits_truncate(0_i8) == AnotherSetOfFlags::empty()); + assert!(AnotherSetOfFlags::from_bits_truncate(0) == AnotherSetOfFlags::empty()); } #[test] diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index c5a3042892..08f0897e76 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -53,8 +53,8 @@ Here `x` represents some variable, `LV.f` is a field reference, and `*LV` is a pointer dereference. There is no auto-deref or other niceties. This means that if you have a type like: -```text -struct S { f: uint } +```rust +struct S { f: i32 } ``` and a variable `a: Box`, then the rust expression `a.f` would correspond @@ -63,8 +63,8 @@ to an `LV` of `(*a).f`. Here is the formal grammar for the types we'll consider: ```text -TY = () | S<'LT...> | Box | & 'LT MQ TY -MQ = mut | imm | const +TY = i32 | bool | S<'LT...> | Box | & 'LT MQ TY +MQ = mut | imm ``` Most of these types should be pretty self explanatory. Here `S` is a @@ -82,13 +82,13 @@ SD = struct S<'LT...> { (f: TY)... } Now, imagine we had a program like this: -```text -struct Foo { f: uint, g: uint } +```rust +struct Foo { f: i32, g: i32 } ... 'a: { - let mut x: Box = ...; - let y = &mut (*x).f; - x = ...; + let mut x: Box = ...; + let y = &mut (*x).f; + x = ...; } ``` @@ -198,7 +198,7 @@ The kinds of expressions which in-scope loans can render illegal are: Now that we hopefully have some kind of intuitive feeling for how the borrow checker works, let's look a bit more closely now at the precise -conditions that it uses. For simplicity I will ignore const loans. +conditions that it uses. I will present the rules in a modified form of standard inference rules, which looks as follows: @@ -261,12 +261,11 @@ that will go into the final loan. We'll discuss in more detail below. ## Checking mutability Checking mutability is fairly straightforward. We just want to prevent -immutable data from being borrowed as mutable. Note that it is ok to -borrow mutable data as immutable, since that is simply a -freeze. Formally we define a predicate `MUTABLE(LV, MQ)` which, if -defined, means that "borrowing `LV` with mutability `MQ` is ok. The -Rust code corresponding to this predicate is the function -`check_mutability` in `middle::borrowck::gather_loans`. +immutable data from being borrowed as mutable. Note that it is ok to borrow +mutable data as immutable, since that is simply a freeze. The judgement +`MUTABILITY(LV, MQ)` means the mutability of `LV` is compatible with a borrow +of mutability `MQ`. The Rust code corresponding to this predicate is the +function `check_mutability` in `middle::borrowck::gather_loans`. ### Checking mutability of variables @@ -275,15 +274,14 @@ but also the code in `mem_categorization`. Let's begin with the rules for variables, which state that if a variable is declared as mutable, it may be borrowed any which way, but -otherwise the variable must be borrowed as immutable or const: +otherwise the variable must be borrowed as immutable: ```text MUTABILITY(X, MQ) // M-Var-Mut DECL(X) = mut -MUTABILITY(X, MQ) // M-Var-Imm +MUTABILITY(X, imm) // M-Var-Imm DECL(X) = imm - MQ = imm | const ``` ### Checking mutability of owned content @@ -304,12 +302,11 @@ MUTABILITY(*LV, MQ) // M-Deref-Unique ### Checking mutability of immutable pointer types Immutable pointer types like `&T` can only -be borrowed if MQ is immutable or const: +be borrowed if MQ is immutable: ```text -MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm +MUTABILITY(*LV, imm) // M-Deref-Borrowed-Imm TYPE(LV) = &Ty - MQ == imm | const ``` ### Checking mutability of mutable pointer types @@ -323,12 +320,11 @@ MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut ## Checking aliasability -The goal of the aliasability check is to ensure that we never permit -`&mut` borrows of aliasable data. Formally we define a predicate -`ALIASABLE(LV, MQ)` which if defined means that -"borrowing `LV` with mutability `MQ` is ok". The -Rust code corresponding to this predicate is the function -`check_aliasability()` in `middle::borrowck::gather_loans`. +The goal of the aliasability check is to ensure that we never permit `&mut` +borrows of aliasable data. The judgement `ALIASABLE(LV, MQ)` means the +aliasability of `LV` is compatible with a borrow of mutability `MQ`. The Rust +code corresponding to this predicate is the function `check_aliasability()` in +`middle::borrowck::gather_loans`. ### Checking aliasability of variables @@ -379,40 +375,6 @@ Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that `MQ`". The Rust code corresponding to this predicate is the module `middle::borrowck::gather_loans::lifetime`. -### The Scope function - -Several of the rules refer to a helper function `SCOPE(LV)=LT`. The -`SCOPE(LV)` yields the lifetime `LT` for which the lvalue `LV` is -guaranteed to exist, presuming that no mutations occur. - -The scope of a local variable is the block where it is declared: - -```text - SCOPE(X) = block where X is declared -``` - -The scope of a field is the scope of the struct: - -```text - SCOPE(LV.f) = SCOPE(LV) -``` - -The scope of a unique referent is the scope of the pointer, since -(barring mutation or moves) the pointer will not be freed until -the pointer itself `LV` goes out of scope: - -```text - SCOPE(*LV) = SCOPE(LV) if LV has type Box -``` - -The scope of a borrowed referent is the scope associated with the -pointer. This is a conservative approximation, since the data that -the pointer points at may actually live longer: - -```text - SCOPE(*LV) = LT if LV has type &'LT T or &'LT mut T -``` - ### Checking lifetime of variables The rule for variables states that a variable can only be borrowed a @@ -420,7 +382,7 @@ lifetime `LT` that is a subregion of the variable's scope: ```text LIFETIME(X, LT, MQ) // L-Local - LT <= SCOPE(X) + LT <= block where X is declared ``` ### Checking lifetime for owned content @@ -466,15 +428,12 @@ are computed based on the kind of borrow: ```text &mut LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE) &LV => RESTRICTIONS(LV, LT, MUTATE|CLAIM) -&const LV => RESTRICTIONS(LV, LT, []) ``` The reasoning here is that a mutable borrow must be the only writer, therefore it prevents other writes (`MUTATE`), mutable borrows (`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow permits other immutable borrows but forbids writes and mutable borrows. -Finally, a const borrow just wants to be sure that the value is not -moved out from under it, so no actions are forbidden. ### Restrictions for loans of a local variable @@ -548,8 +507,8 @@ specify that the lifetime of the loan must be less than the lifetime of the `&Ty` pointer. In simple cases, this clause is redundant, since the `LIFETIME()` function will already enforce the required rule: -``` -fn foo(point: &'a Point) -> &'static f32 { +```rust +fn foo(point: &'a Point) -> &'static i32 { &point.x // Error } ``` @@ -558,8 +517,8 @@ The above example fails to compile both because of clause (1) above but also by the basic `LIFETIME()` check. However, in more advanced examples involving multiple nested pointers, clause (1) is needed: -``` -fn foo(point: &'a &'b mut Point) -> &'b f32 { +```rust +fn foo(point: &'a &'b mut Point) -> &'b i32 { &point.x // Error } ``` @@ -577,8 +536,8 @@ which is only `'a`, not `'b`. Hence this example yields an error. As a final twist, consider the case of two nested *immutable* pointers, rather than a mutable pointer within an immutable one: -``` -fn foo(point: &'a &'b Point) -> &'b f32 { +```rust +fn foo(point: &'a &'b Point) -> &'b i32 { &point.x // OK } ``` @@ -599,8 +558,8 @@ The rules pertaining to `LIFETIME` exist to ensure that we don't create a borrowed pointer that outlives the memory it points at. So `LIFETIME` prevents a function like this: -``` -fn get_1<'a>() -> &'a int { +```rust +fn get_1<'a>() -> &'a i32 { let x = 1; &x } @@ -619,8 +578,8 @@ after we return and hence the remaining code in `'a` cannot possibly mutate it. This distinction is important for type checking functions like this one: -``` -fn inc_and_get<'a>(p: &'a mut Point) -> &'a int { +```rust +fn inc_and_get<'a>(p: &'a mut Point) -> &'a i32 { p.x += 1; &p.x } @@ -641,19 +600,6 @@ in terms of capability, the caller passed in the ability to mutate `*p` is borrowed since that would be a move of `p`, as `&mut` pointers are affine.) -### Restrictions for loans of const aliasable referents - -Freeze pointers are read-only. There may be `&mut` or `&` aliases, and -we can not prevent *anything* but moves in that case. So the -`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. -Because moves from a `&const` lvalue are never legal, it is not -necessary to add any restrictions at all to the final result. - -```text - RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed - TYPE(LV) = &const Ty -``` - ### Restrictions for loans of mutable borrowed referents Mutable borrowed pointers are guaranteed to be the only way to mutate @@ -685,7 +631,7 @@ maximum of `LT'`. Here is a concrete example of a bug this rule prevents: -``` +```rust // Test region-reborrow-from-shorter-mut-ref.rs: fn copy_pointer<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T { &mut **p // ERROR due to clause (1) @@ -713,10 +659,10 @@ ways to violate the rules is to move the base pointer to a new name and access it via that new name, thus bypassing the restrictions on the old name. Here is an example: -``` +```rust // src/test/compile-fail/borrowck-move-mut-base-ptr.rs -fn foo(t0: &mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo(t0: &mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` let t1 = t0; //~ ERROR cannot move out of `t0` *t1 = 22; // OK, not a write through `*t0` } @@ -733,11 +679,11 @@ danger is to mutably borrow the base path. This can lead to two bad scenarios. The most obvious is that the mutable borrow itself becomes another path to access the same data, as shown here: -``` +```rust // src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` let mut t2 = &mut t0; //~ ERROR cannot borrow `t0` **t2 += 1; // Mutates `*t0` } @@ -754,11 +700,11 @@ of `t0`. Hence the claim `&mut t0` is illegal. Another danger with an `&mut` pointer is that we could swap the `t0` value away to create a new path: -``` +```rust // src/test/compile-fail/borrowck-swap-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` *t1 = 22; } @@ -772,37 +718,37 @@ careful to ensure this example is still illegal. referent is claimed, even freezing the base pointer can be dangerous, as shown in the following example: -``` +```rust // src/test/compile-fail/borrowck-borrow-of-mut-base-ptr.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &mut int = &mut *t0; // Claims `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &mut i32 = &mut *t0; // Claims `*t0` let mut t2 = &t0; //~ ERROR cannot borrow `t0` - let q: &int = &*t2; // Freezes `*t0` but not through `*p` + let q: &i32 = &*t2; // Freezes `*t0` but not through `*p` *p += 1; // violates type of `*q` } ``` Here the problem is that `*t0` is claimed by `p`, and hence `p` wants to be the controlling pointer through which mutation or freezes occur. -But `t2` would -- if it were legal -- have the type `& &mut int`, and +But `t2` would -- if it were legal -- have the type `& &mut i32`, and hence would be a mutable pointer in an aliasable location, which is considered frozen (since no one can write to `**t2` as it is not a -unique path). Therefore, we could reasonably create a frozen `&int` +unique path). Therefore, we could reasonably create a frozen `&i32` pointer pointing at `*t0` that coexists with the mutable pointer `p`, which is clearly unsound. However, it is not always unsafe to freeze the base pointer. In particular, if the referent is frozen, there is no harm in it: -``` +```rust // src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +fn foo<'a>(mut t0: &'a mut i32, + mut t1: &'a mut i32) { + let p: &i32 = &*t0; // Freezes `*t0` let mut t2 = &t0; - let q: &int = &*t2; // Freezes `*t0`, but that's ok... - let r: &int = &*t0; // ...after all, could do same thing directly. + let q: &i32 = &*t2; // Freezes `*t0`, but that's ok... + let r: &i32 = &*t0; // ...after all, could do same thing directly. } ``` @@ -811,11 +757,11 @@ thing `t2` can be used for is to further freeze `*t0`, which is already frozen. In particular, we cannot assign to `*t0` through the new alias `t2`, as demonstrated in this test case: -``` +```rust // src/test/run-pass/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs -fn foo(t0: & &mut int) { +fn foo(t0: & &mut i32) { let t1 = t0; - let p: &int = &**t0; + let p: &i32 = &**t0; **t1 = 22; //~ ERROR cannot assign } ``` @@ -855,6 +801,9 @@ prohibited from both freezes and claims. This would avoid the need to prevent `const` borrows of the base pointer when the referent is borrowed. +[ Previous revisions of this document discussed `&const` in more detail. +See the revision history. ] + # Moves and initialization The borrow checker is also in charge of ensuring that: @@ -881,9 +830,9 @@ moves/uninitializations of the variable that is being used. Let's look at a simple example: -``` -fn foo(a: Box) { - let b: Box; // Gen bit 0. +```rust +fn foo(a: Box) { + let b: Box; // Gen bit 0. if cond { // Bits: 0 use(&*a); @@ -897,7 +846,7 @@ fn foo(a: Box) { use(&*b); // Error. } -fn use(a: &int) { } +fn use(a: &i32) { } ``` In this example, the variable `b` is created uninitialized. In one @@ -1028,8 +977,8 @@ not) the destructor invocation for that path. A simple example of this is the following: ```rust -struct D { p: int } -impl D { fn new(x: int) -> D { ... } +struct D { p: i32 } +impl D { fn new(x: i32) -> D { ... } impl Drop for D { ... } fn foo(a: D, b: D, t: || -> bool) { @@ -1142,7 +1091,7 @@ the elements of an array that has been passed by value, such as the following: ```rust -fn foo(a: [D; 10], i: uint) -> D { +fn foo(a: [D; 10], i: i32) -> D { a[i] } ``` @@ -1158,7 +1107,7 @@ all-but-one element of the array. A place where that distinction would arise is the following: ```rust -fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D { +fn foo(a: [D; 10], b: [D; 10], i: i32, t: bool) -> D { if t { a[i] } else { @@ -1173,7 +1122,7 @@ fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D { There are a number of ways that the trans backend could choose to compile this (e.g. a `[bool; 10]` array for each such moved array; -or an `Option` for each moved array). From the viewpoint of the +or an `Option` for each moved array). From the viewpoint of the borrow-checker, the important thing is to record what kind of fragment is implied by the relevant moves. diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index abe01d193b..ce7b492c51 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { return true; } - pub fn loans_generated_by(&self, scope: region::CodeExtent) -> Vec { + pub fn loans_generated_by(&self, scope: region::CodeExtent) -> Vec { //! Returns a vector of the loans that are generated as //! we enter `scope`. @@ -466,7 +466,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.span, &format!("cannot borrow `{}`{} as mutable \ more than once at a time", - nl, new_loan_msg)[]) + nl, new_loan_msg)) } (ty::UniqueImmBorrow, _) => { @@ -474,7 +474,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.span, &format!("closure requires unique access to `{}` \ but {} is already borrowed{}", - nl, ol_pronoun, old_loan_msg)[]); + nl, ol_pronoun, old_loan_msg)); } (_, ty::UniqueImmBorrow) => { @@ -482,7 +482,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.span, &format!("cannot borrow `{}`{} as {} because \ previous closure requires unique access", - nl, new_loan_msg, new_loan.kind.to_user_str())[]); + nl, new_loan_msg, new_loan.kind.to_user_str())); } (_, _) => { @@ -495,7 +495,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { new_loan.kind.to_user_str(), ol_pronoun, old_loan.kind.to_user_str(), - old_loan_msg)[]); + old_loan_msg)); } } @@ -504,7 +504,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_note( span, &format!("borrow occurs due to use of `{}` in closure", - nl)[]); + nl)); } _ => { } } @@ -553,7 +553,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_note( old_loan.span, - &format!("{}; {}", borrow_summary, rule_summary)[]); + &format!("{}; {}", borrow_summary, rule_summary)); let old_loan_span = self.tcx().map.span(old_loan.kill_scope.node_id()); self.bccx.span_end_note(old_loan_span, @@ -623,13 +623,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_err( span, &format!("cannot use `{}` because it was mutably borrowed", - &self.bccx.loan_path_to_string(copy_path)[]) - []); + &self.bccx.loan_path_to_string(copy_path)) + ); self.bccx.span_note( loan_span, &format!("borrow of `{}` occurs here", - &self.bccx.loan_path_to_string(&*loan_path)[]) - []); + &self.bccx.loan_path_to_string(&*loan_path)) + ); } } } @@ -648,20 +648,20 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let err_message = match move_kind { move_data::Captured => format!("cannot move `{}` into closure because it is borrowed", - &self.bccx.loan_path_to_string(move_path)[]), + &self.bccx.loan_path_to_string(move_path)), move_data::Declared | move_data::MoveExpr | move_data::MovePat => format!("cannot move out of `{}` because it is borrowed", - &self.bccx.loan_path_to_string(move_path)[]) + &self.bccx.loan_path_to_string(move_path)) }; self.bccx.span_err(span, &err_message[..]); self.bccx.span_note( loan_span, &format!("borrow of `{}` occurs here", - &self.bccx.loan_path_to_string(&*loan_path)[]) - []); + &self.bccx.loan_path_to_string(&*loan_path)) + ); } } } @@ -727,7 +727,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { /// let a: int; /// a = 10; // ok, even though a is uninitialized /// - /// struct Point { x: uint, y: uint } + /// struct Point { x: usize, y: usize } /// let p: Point; /// p.x = 22; // ok, even though `p` is uninitialized /// @@ -842,7 +842,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_err( assignment_span, &format!("cannot assign to {}", - self.bccx.cmt_to_string(&*assignee_cmt))[]); + self.bccx.cmt_to_string(&*assignee_cmt))); self.bccx.span_help( self.tcx().map.span(upvar_id.closure_expr_id), "consider changing this closure to take self by mutable reference"); @@ -851,7 +851,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { assignment_span, &format!("cannot assign to {} {}", assignee_cmt.mutbl.to_user_str(), - self.bccx.cmt_to_string(&*assignee_cmt))[]); + self.bccx.cmt_to_string(&*assignee_cmt))); } } _ => match opt_loan_path(&assignee_cmt) { @@ -861,14 +861,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { &format!("cannot assign to {} {} `{}`", assignee_cmt.mutbl.to_user_str(), self.bccx.cmt_to_string(&*assignee_cmt), - self.bccx.loan_path_to_string(&*lp))[]); + self.bccx.loan_path_to_string(&*lp))); } None => { self.bccx.span_err( assignment_span, &format!("cannot assign to {} {}", assignee_cmt.mutbl.to_user_str(), - self.bccx.cmt_to_string(&*assignee_cmt))[]); + self.bccx.cmt_to_string(&*assignee_cmt))); } } } @@ -943,13 +943,20 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { cmt: mc::cmt<'tcx>) -> bool { match cmt.freely_aliasable(this.tcx()) { - None => { + mc::Aliasability::NonAliasable => { return true; } - Some(mc::AliasableStaticMut(..)) => { + mc::Aliasability::FreelyAliasable(mc::AliasableStaticMut(..)) => { return true; } - Some(cause) => { + mc::Aliasability::ImmutableUnique(_) => { + this.bccx.report_aliasability_violation( + span, + MutabilityViolation, + mc::AliasableReason::UnaliasableImmutable); + return false; + } + mc::Aliasability::FreelyAliasable(cause) => { this.bccx.report_aliasability_violation( span, MutabilityViolation, @@ -988,10 +995,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.bccx.span_err( span, &format!("cannot assign to `{}` because it is borrowed", - self.bccx.loan_path_to_string(loan_path))[]); + self.bccx.loan_path_to_string(loan_path))); self.bccx.span_note( loan.span, &format!("borrow of `{}` occurs here", - self.bccx.loan_path_to_string(loan_path))[]); + self.bccx.loan_path_to_string(loan_path))); } } diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index c873831cb0..a13d1d1112 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -10,15 +10,15 @@ //! Helper routines used for fragmenting structural paths due to moves for //! tracking drop obligations. Please see the extensive comments in the -//! section "Structural fragments" in `doc.rs`. +//! section "Structural fragments" in `README.md`. use self::Fragment::*; use borrowck::InteriorKind::{InteriorField, InteriorElement}; -use borrowck::{LoanPath}; +use borrowck::LoanPath; use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend}; use borrowck::LoanPathElem::{LpDeref, LpInterior}; -use borrowck::move_data::{InvalidMovePathIndex}; +use borrowck::move_data::InvalidMovePathIndex; use borrowck::move_data::{MoveData, MovePathIndex}; use rustc::middle::ty; use rustc::middle::mem_categorization as mc; @@ -26,7 +26,6 @@ use rustc::util::ppaux::{Repr, UserString}; use std::mem; use std::rc::Rc; use syntax::ast; -use syntax::ast_map; use syntax::attr::AttrMetaMethods; use syntax::codemap::Span; @@ -119,24 +118,9 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>, sp: Span, id: ast::NodeId) { - let (span_err, print) = { - let attrs : &[ast::Attribute]; - attrs = match tcx.map.find(id) { - Some(ast_map::NodeItem(ref item)) => - &item.attrs[], - Some(ast_map::NodeImplItem(&ast::MethodImplItem(ref m))) => - &m.attrs[], - Some(ast_map::NodeTraitItem(&ast::ProvidedMethod(ref m))) => - &m.attrs[], - _ => &[][], - }; - - let span_err = - attrs.iter().any(|a| a.check_name("rustc_move_fragments")); - let print = tcx.sess.opts.debugging_opts.print_move_fragments; - - (span_err, print) - }; + let span_err = tcx.map.attrs(id).iter() + .any(|a| a.check_name("rustc_move_fragments")); + let print = tcx.sess.opts.debugging_opts.print_move_fragments; if !span_err && !print { return; } @@ -144,7 +128,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, for (i, mpi) in vec_rc.iter().enumerate() { let render = || this.path_loan_path(*mpi).user_string(tcx); if span_err { - tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render())[]); + tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render())); } if print { println!("id:{} {}[{}] `{}`", id, kind, i, render()); @@ -156,7 +140,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>, for (i, f) in vec_rc.iter().enumerate() { let render = || f.loan_path_user_string(this, tcx); if span_err { - tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render())[]); + tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render())); } if print { println!("id:{} {}[{}] `{}`", id, kind, i, render()); diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 1c57097ae2..9f7b4cf26e 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -106,8 +106,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { //! lvalue `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. - // See the SCOPE(LV) function in doc.rs - match cmt.cat { mc::cat_rvalue(temp_scope) => { temp_scope diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 4e308c5809..733d486d2d 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -22,7 +22,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::region; use rustc::middle::ty; -use rustc::util::ppaux::{Repr}; +use rustc::util::ppaux::Repr; use syntax::ast; use syntax::codemap::Span; use syntax::visit; @@ -151,10 +151,11 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { assignee_cmt: mc::cmt<'tcx>, mode: euv::MutateMode) { - debug!("mutate(assignment_id={}, assignee_cmt={})", - assignment_id, assignee_cmt.repr(self.tcx())); + let opt_lp = opt_loan_path(&assignee_cmt); + debug!("mutate(assignment_id={}, assignee_cmt={}) opt_lp={:?}", + assignment_id, assignee_cmt.repr(self.tcx()), opt_lp); - match opt_loan_path(&assignee_cmt) { + match opt_lp { Some(lp) => { gather_moves::gather_assignment(self.bccx, &self.move_data, assignment_id, assignment_span, @@ -173,7 +174,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { } } -/// Implements the A-* rules in doc.rs. +/// Implements the A-* rules in README.md. fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, borrow_span: Span, loan_cause: euv::LoanCause, @@ -181,12 +182,16 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, req_kind: ty::BorrowKind) -> Result<(),()> { - match (cmt.freely_aliasable(bccx.tcx), req_kind) { - (None, _) => { + let aliasability = cmt.freely_aliasable(bccx.tcx); + debug!("check_aliasability aliasability={:?} req_kind={:?}", + aliasability, req_kind); + + match (aliasability, req_kind) { + (mc::Aliasability::NonAliasable, _) => { /* Uniquely accessible path -- OK for `&` and `&mut` */ Ok(()) } - (Some(mc::AliasableStatic(safety)), ty::ImmBorrow) => { + (mc::Aliasability::FreelyAliasable(mc::AliasableStatic(safety)), ty::ImmBorrow) => { // Borrow of an immutable static item: match safety { mc::InteriorUnsafe => { @@ -202,13 +207,20 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, } } } - (Some(mc::AliasableStaticMut(..)), _) => { + (mc::Aliasability::FreelyAliasable(mc::AliasableStaticMut(..)), _) => { // Even touching a static mut is considered unsafe. We assume the // user knows what they're doing in these cases. Ok(()) } - (Some(alias_cause), ty::UniqueImmBorrow) | - (Some(alias_cause), ty::MutBorrow) => { + (mc::Aliasability::ImmutableUnique(_), ty::MutBorrow) => { + bccx.report_aliasability_violation( + borrow_span, + BorrowViolation(loan_cause), + mc::AliasableReason::UnaliasableImmutable); + Err(()) + } + (mc::Aliasability::FreelyAliasable(alias_cause), ty::UniqueImmBorrow) | + (mc::Aliasability::FreelyAliasable(alias_cause), ty::MutBorrow) => { bccx.report_aliasability_violation( borrow_span, BorrowViolation(loan_cause), @@ -307,7 +319,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { self.tcx().sess.span_bug( cmt.span, &format!("invalid borrow lifetime: {:?}", - loan_region)[]); + loan_region)); } }; debug!("loan_scope = {:?}", loan_scope); @@ -375,8 +387,9 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { cmt: mc::cmt<'tcx>, req_kind: ty::BorrowKind) -> Result<(),()> { - //! Implements the M-* rules in doc.rs. - + //! Implements the M-* rules in README.md. + debug!("check_mutability(cause={:?} cmt={} req_kind={:?}", + cause, cmt.repr(bccx.tcx), req_kind); match req_kind { ty::UniqueImmBorrow | ty::ImmBorrow => { match cmt.mutbl { @@ -491,7 +504,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { if let ast::ExprAddrOf(mutbl, ref base) = ex.node { let param_env = ty::empty_parameter_environment(self.bccx.tcx); let mc = mc::MemCategorizationContext::new(¶m_env); - let base_cmt = mc.cat_expr(&**base).ok().unwrap(); + let base_cmt = mc.cat_expr(&**base).unwrap(); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); // Check that we don't allow borrows of unsafe static items. if check_aliasability(self.bccx, ex.span, euv::AddrOf, diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index da5c847a04..84636ebaae 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -121,7 +121,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, mc::cat_static_item => { bccx.span_err(move_from.span, &format!("cannot move out of {}", - move_from.descriptive_string(bccx.tcx))[]); + move_from.descriptive_string(bccx.tcx))); } mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => { @@ -130,7 +130,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, bccx.span_err(move_from.span, &format!("cannot move out of type `{}`, \ a non-copy fixed-size array", - b.ty.user_string(bccx.tcx))[]); + b.ty.user_string(bccx.tcx))); } } @@ -143,7 +143,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_from.span, &format!("cannot move out of type `{}`, \ which defines the `Drop` trait", - b.ty.user_string(bccx.tcx))[]); + b.ty.user_string(bccx.tcx))); }, _ => { bccx.span_bug(move_from.span, "this path should not cause illegal move") @@ -165,15 +165,15 @@ fn note_move_destination(bccx: &BorrowckCtxt, bccx.span_note( move_to_span, "attempting to move value to here"); - bccx.span_help( + bccx.fileline_help( move_to_span, &format!("to prevent the move, \ use `ref {0}` or `ref mut {0}` to capture value by \ reference", - pat_name)[]); + pat_name)); } else { bccx.span_note(move_to_span, &format!("and here (use `ref {0}` or `ref mut {0}`)", - pat_name)[]); + pat_name)); } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 518e4bc472..f8da075e4b 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -88,7 +88,7 @@ pub fn check_crate(tcx: &ty::ctxt) { make_stat(&bccx, bccx.stats.stable_paths)); } - fn make_stat(bccx: &BorrowckCtxt, stat: uint) -> String { + fn make_stat(bccx: &BorrowckCtxt, stat: usize) -> String { let total = bccx.stats.guaranteed_paths as f64; let perc = if total == 0.0 { 0.0 } else { stat as f64 * 100.0 / total }; format!("{} ({:.0}%)", stat, perc) @@ -105,10 +105,10 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) { ast::ItemConst(_, ref ex) => { gather_loans::gather_loans_in_static_initializer(this, &**ex); } - _ => { - visit::walk_item(this, item); - } + _ => { } } + + visit::walk_item(this, item); } /// Collection of conclusions determined via borrow checker analyses. @@ -238,10 +238,10 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { } struct BorrowStats { - loaned_paths_same: uint, - loaned_paths_imm: uint, - stable_paths: uint, - guaranteed_paths: uint + loaned_paths_same: usize, + loaned_paths_imm: usize, + stable_paths: usize, + guaranteed_paths: usize } pub type BckResult<'tcx, T> = Result>; @@ -251,7 +251,7 @@ pub type BckResult<'tcx, T> = Result>; /// Record of a loan that was issued. pub struct Loan<'tcx> { - index: uint, + index: usize, loan_path: Rc>, kind: ty::BorrowKind, restricted_paths: Vec>>, @@ -295,7 +295,7 @@ impl<'tcx> PartialEq for LoanPath<'tcx> { #[derive(PartialEq, Eq, Hash, Debug)] pub enum LoanPathKind<'tcx> { - LpVar(ast::NodeId), // `x` in doc.rs + LpVar(ast::NodeId), // `x` in README.md LpUpvar(ty::UpvarId), // `x` captured by-value into closure LpDowncast(Rc>, ast::DefId), // `x` downcast to particular enum variant LpExtend(Rc>, mc::MutabilityCategory, LoanPathElem) @@ -312,7 +312,7 @@ impl<'tcx> LoanPath<'tcx> { // FIXME (pnkfelix): See discussion here // https://github.com/pnkfelix/rust/commit/ // b2b39e8700e37ad32b486b9a8409b50a8a53aa51#commitcomment-7892003 -static DOWNCAST_PRINTED_OPERATOR : &'static str = " as "; +const DOWNCAST_PRINTED_OPERATOR: &'static str = " as "; // A local, "cleaned" version of `mc::InteriorKind` that drops // information that is not relevant to loan-path analysis. (In @@ -334,10 +334,10 @@ impl ToInteriorKind for mc::InteriorKind { } } -#[derive(Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum LoanPathElem { - LpDeref(mc::PointerKind), // `*LV` in doc.rs - LpInterior(InteriorKind), // `LV.f` in doc.rs + LpDeref(mc::PointerKind), // `*LV` in README.md + LpInterior(InteriorKind), // `LV.f` in README.md } pub fn closure_to_block(closure_id: ast::NodeId, @@ -382,7 +382,7 @@ impl<'tcx> LoanPath<'tcx> { } } - fn depth(&self) -> uint { + fn depth(&self) -> usize { match self.kind { LpExtend(ref base, _, LpDeref(_)) => base.depth(), LpExtend(ref base, _, LpInterior(_)) => base.depth() + 1, @@ -500,13 +500,13 @@ pub struct BckError<'tcx> { code: bckerr_code } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AliasableViolationKind { MutabilityViolation, BorrowViolation(euv::LoanCause) } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum MovedValueUseKind { MovedInUse, MovedInCapture, @@ -524,7 +524,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { pub fn report(&self, err: BckError<'tcx>) { self.span_err( err.span, - &self.bckerr_to_string(&err)[]); + &self.bckerr_to_string(&err)); self.note_and_explain_bckerr(err); } @@ -546,7 +546,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { use_span, &format!("{} of possibly uninitialized variable: `{}`", verb, - self.loan_path_to_string(lp))[]); + self.loan_path_to_string(lp))); (self.loan_path_to_string(moved_lp), String::new()) } @@ -588,7 +588,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { &format!("{} of {}moved value: `{}`", verb, msg, - nl)[]); + nl)); (ol, moved_lp_msg) } }; @@ -607,18 +607,31 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.bug(&format!("MoveExpr({}) maps to \ {:?}, not Expr", the_move.id, - r)[]) + r)) } }; let (suggestion, _) = move_suggestion(param_env, expr_span, expr_ty, ("moved by default", "")); - self.tcx.sess.span_note( - expr_span, - &format!("`{}` moved here{} because it has type `{}`, which is {}", - ol, - moved_lp_msg, - expr_ty.user_string(self.tcx), - suggestion)[]); + // If the two spans are the same, it's because the expression will be evaluated + // multiple times. Avoid printing the same span and adjust the wording so it makes + // more sense that it's from multiple evalutations. + if expr_span == use_span { + self.tcx.sess.note( + &format!("`{}` was previously moved here{} because it has type `{}`, \ + which is {}", + ol, + moved_lp_msg, + expr_ty.user_string(self.tcx), + suggestion)); + } else { + self.tcx.sess.span_note( + expr_span, + &format!("`{}` moved here{} because it has type `{}`, which is {}", + ol, + moved_lp_msg, + expr_ty.user_string(self.tcx), + suggestion)); + } } move_data::MovePat => { @@ -629,8 +642,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { which is moved by default", ol, moved_lp_msg, - pat_ty.user_string(self.tcx))[]); - self.tcx.sess.span_help(span, + pat_ty.user_string(self.tcx))); + self.tcx.sess.fileline_help(span, "use `ref` to override"); } @@ -645,7 +658,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.bug(&format!("Captured({}) maps to \ {:?}, not Expr", the_move.id, - r)[]) + r)) } }; let (suggestion, help) = @@ -661,8 +674,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ol, moved_lp_msg, expr_ty.user_string(self.tcx), - suggestion)[]); - self.tcx.sess.span_help(expr_span, help); + suggestion)); + self.tcx.sess.fileline_help(expr_span, help); } } @@ -691,9 +704,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx .sess .span_err(span, - (format!("partial reinitialization of uninitialized \ + &format!("partial reinitialization of uninitialized \ structure `{}`", - self.loan_path_to_string(lp))).as_slice()); + self.loan_path_to_string(lp))); } pub fn report_reassigned_immutable_variable(&self, @@ -704,7 +717,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err( span, &format!("re-assignment of immutable variable `{}`", - self.loan_path_to_string(lp))[]); + self.loan_path_to_string(lp))); self.tcx.sess.span_note(assign.span, "prior assignment occurs here"); } @@ -728,6 +741,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_help(s, m); } + pub fn fileline_help(&self, s: Span, m: &str) { + self.tcx.sess.fileline_help(s, m); + } + pub fn bckerr_to_string(&self, err: &BckError<'tcx>) -> String { match err.code { err_mutbl => { @@ -825,7 +842,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err( span, &format!("{} in an aliasable location", - prefix)[]); + prefix)); + } + mc::AliasableReason::UnaliasableImmutable => { + self.tcx.sess.span_err( + span, + &format!("{} in an immutable container", + prefix)); } mc::AliasableClosure(id) => { self.tcx.sess.span_err(span, @@ -847,17 +870,17 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { mc::AliasableStaticMut(..) => { self.tcx.sess.span_err( span, - &format!("{} in a static location", prefix)[]); + &format!("{} in a static location", prefix)); } mc::AliasableBorrowed => { self.tcx.sess.span_err( span, - &format!("{} in a `&` reference", prefix)[]); + &format!("{} in a `&` reference", prefix)); } } if is_closure { - self.tcx.sess.span_help( + self.tcx.sess.fileline_help( span, "closures behind references must be called via `&mut`"); } @@ -920,12 +943,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { note_and_explain_region( self.tcx, &format!("{} would have to be valid for ", - descr)[], + descr), loan_scope, "..."); note_and_explain_region( self.tcx, - &format!("...but {} is only valid for ", descr)[], + &format!("...but {} is only valid for ", descr), ptr_scope, ""); } @@ -945,7 +968,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out.push('('); self.append_loan_path_to_string(&**lp_base, out); out.push_str(DOWNCAST_PRINTED_OPERATOR); - out.push_str(&ty::item_path_str(self.tcx, variant_def_id)[]); + out.push_str(&ty::item_path_str(self.tcx, variant_def_id)); out.push(')'); } @@ -959,7 +982,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } mc::PositionalField(idx) => { out.push('.'); - out.push_str(&idx.to_string()[]); + out.push_str(&idx.to_string()); } } } @@ -991,7 +1014,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out.push('('); self.append_autoderefd_loan_path_to_string(&**lp_base, out); out.push(':'); - out.push_str(&ty::item_path_str(self.tcx, variant_def_id)[]); + out.push_str(&ty::item_path_str(self.tcx, variant_def_id)); out.push(')'); } @@ -1026,7 +1049,7 @@ fn is_statement_scope(tcx: &ty::ctxt, region: ty::Region) -> bool { impl BitwiseOperator for LoanDataFlowOperator { #[inline] - fn join(&self, succ: uint, pred: uint) -> uint { + fn join(&self, succ: usize, pred: usize) -> usize { succ | pred // loans from both preds are in scope } } diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 9c5ddc0651..2d1b57243d 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -9,7 +9,7 @@ // except according to those terms. //! Data structures used for tracking moves. Please see the extensive -//! comments in the section "Moves and initialization" in `doc.rs`. +//! comments in the section "Moves and initialization" in `README.md`. pub use self::MoveKind::*; @@ -33,7 +33,7 @@ use syntax::codemap::Span; pub mod fragments; pub struct MoveData<'tcx> { - /// Move paths. See section "Move paths" in `doc.rs`. + /// Move paths. See section "Move paths" in `README.md`. pub paths: RefCell>>, /// Cache of loan path to move path index, for easy lookup. @@ -76,10 +76,10 @@ pub struct FlowedMoveData<'a, 'tcx: 'a> { /// Index into `MoveData.paths`, used like a pointer #[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct MovePathIndex(uint); +pub struct MovePathIndex(usize); impl MovePathIndex { - fn get(&self) -> uint { + fn get(&self) -> usize { let MovePathIndex(v) = *self; v } } @@ -91,22 +91,20 @@ impl Clone for MovePathIndex { } #[allow(non_upper_case_globals)] -static InvalidMovePathIndex: MovePathIndex = - MovePathIndex(usize::MAX); +const InvalidMovePathIndex: MovePathIndex = MovePathIndex(usize::MAX); /// Index into `MoveData.moves`, used like a pointer -#[derive(Copy, PartialEq)] -pub struct MoveIndex(uint); +#[derive(Copy, Clone, PartialEq)] +pub struct MoveIndex(usize); impl MoveIndex { - fn get(&self) -> uint { + fn get(&self) -> usize { let MoveIndex(v) = *self; v } } #[allow(non_upper_case_globals)] -static InvalidMoveIndex: MoveIndex = - MoveIndex(usize::MAX); +const InvalidMoveIndex: MoveIndex = MoveIndex(usize::MAX); pub struct MovePath<'tcx> { /// Loan path corresponding to this move path @@ -127,7 +125,7 @@ pub struct MovePath<'tcx> { pub next_sibling: MovePathIndex, } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum MoveKind { Declared, // When declared, variables start out "moved". MoveExpr, // Expression or binding that moves a variable @@ -135,7 +133,7 @@ pub enum MoveKind { Captured // Closure creation that moves a value } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Move { /// Path being moved. pub path: MovePathIndex, @@ -150,7 +148,7 @@ pub struct Move { pub next_move: MoveIndex } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Assignment { /// Path being assigned. pub path: MovePathIndex, @@ -162,7 +160,7 @@ pub struct Assignment { pub span: Span, } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct VariantMatch { /// downcast to the variant. pub path: MovePathIndex, @@ -464,7 +462,7 @@ impl<'tcx> MoveData<'tcx> { /// assignments into the provided data flow contexts. /// Moves are generated by moves and killed by assignments and /// scoping. Assignments are generated by assignment to variables and - /// killed by scoping. See `doc.rs` for more details. + /// killed by scoping. See `README.md` for more details. fn add_gen_kills(&self, tcx: &ty::ctxt<'tcx>, dfcx_moves: &mut MoveDataFlow, @@ -488,7 +486,7 @@ impl<'tcx> MoveData<'tcx> { match path.loan_path.kind { LpVar(..) | LpUpvar(..) | LpDowncast(..) => { let kill_scope = path.loan_path.kill_scope(tcx); - let path = self.path_map.borrow()[path.loan_path]; + let path = *self.path_map.borrow().get(&path.loan_path).unwrap(); self.kill_moves(path, kill_scope.node_id(), dfcx_moves); } LpExtend(..) => {} @@ -742,7 +740,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { impl BitwiseOperator for MoveDataFlowOperator { #[inline] - fn join(&self, succ: uint, pred: uint) -> uint { + fn join(&self, succ: usize, pred: usize) -> usize { succ | pred // moves from both preds are in scope } } @@ -756,7 +754,7 @@ impl DataFlowOperator for MoveDataFlowOperator { impl BitwiseOperator for AssignDataFlowOperator { #[inline] - fn join(&self, succ: uint, pred: uint) -> uint { + fn join(&self, succ: usize, pred: usize) -> usize { succ | pred // moves from both preds are in scope } } diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index 39c9d9ba6a..ade52bfde3 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -20,13 +20,13 @@ use rustc::middle::cfg::graphviz as cfg_dot; use borrowck; use borrowck::{BorrowckCtxt, LoanPath}; use dot; -use rustc::middle::cfg::{CFGIndex}; +use rustc::middle::cfg::CFGIndex; use rustc::middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit}; use rustc::middle::dataflow; use std::rc::Rc; use std::borrow::IntoCow; -#[derive(Debug, Copy)] +#[derive(Debug, Copy, Clone)] pub enum Variant { Loans, Moves, @@ -52,7 +52,7 @@ pub struct DataflowLabeller<'a, 'tcx: 'a> { impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String { - let id = n.1.data.id; + let id = n.1.data.id(); debug!("dataflow_for({:?}, id={}) {:?}", e, id, self.variants); let mut sets = "".to_string(); let mut seen_one = false; @@ -60,7 +60,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { if seen_one { sets.push_str(" "); } else { seen_one = true; } sets.push_str(variant.short_name()); sets.push_str(": "); - sets.push_str(&self.dataflow_for_variant(e, n, variant)[]); + sets.push_str(&self.dataflow_for_variant(e, n, variant)); } sets } @@ -79,7 +79,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { cfgidx: CFGIndex, dfcx: &DataFlowContext<'a, 'tcx, O>, mut to_lp: F) -> String where - F: FnMut(uint) -> Rc>, + F: FnMut(usize) -> Rc>, { let mut saw_some = false; let mut set = "{".to_string(); diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index b7cfda2809..54feed930a 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_borrowck"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -19,20 +21,19 @@ #![allow(non_camel_case_types)] -#![feature(core)] -#![feature(int_uint)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(unsafe_destructor)] +#![feature(into_cow)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; // for "clarity", rename the graphviz crate to dot; graphviz within `borrowck` // refers to the borrowck-specific graphviz adapter traits. -extern crate "graphviz" as dot; +extern crate graphviz as dot; extern crate rustc; pub use borrowck::check_crate; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index a260997f60..fe05b48922 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -33,12 +33,13 @@ use serialize::json; use std::env; use std::ffi::OsString; -use std::old_io::fs; -use std::old_io; +use std::fs; +use std::io::{self, Write}; +use std::path::{Path, PathBuf}; use syntax::ast; use syntax::ast_map; use syntax::attr; -use syntax::attr::{AttrMetaMethods}; +use syntax::attr::AttrMetaMethods; use syntax::diagnostics; use syntax::parse; use syntax::parse::token; @@ -47,8 +48,8 @@ use syntax; pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input, - outdir: &Option, - output: &Option, + outdir: &Option, + output: &Option, addl_plugins: Option>, control: CompileController) { macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({ @@ -77,10 +78,10 @@ pub fn compile_input(sess: Session, let outputs = build_output_filenames(input, outdir, output, - &krate.attrs[], + &krate.attrs, &sess); let id = link::find_crate_name(Some(&sess), - &krate.attrs[], + &krate.attrs, input); let expanded_crate = match phase_2_configure_and_expand(&sess, @@ -112,6 +113,7 @@ pub fn compile_input(sess: Session, &sess, outdir, &ast_map, + &ast_map.krate(), &id[..])); let analysis = phase_3_run_analysis_passes(sess, @@ -164,7 +166,7 @@ pub fn anon_src() -> String { pub fn source_name(input: &Input) -> String { match *input { // FIXME (#9639): This needs to handle non-utf8 paths - Input::File(ref ifile) => ifile.as_str().unwrap().to_string(), + Input::File(ref ifile) => ifile.to_str().unwrap().to_string(), Input::Str(_) => anon_src() } } @@ -241,12 +243,12 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> { impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn empty(input: &'a Input, session: &'a Session, - out_dir: &'a Option) + out_dir: &'a Option) -> CompileState<'a, 'ast, 'tcx> { CompileState { input: input, session: session, - out_dir: out_dir.as_ref(), + out_dir: out_dir.as_ref().map(|s| &**s), cfg: None, krate: None, crate_name: None, @@ -261,7 +263,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_parse(input: &'a Input, session: &'a Session, - out_dir: &'a Option, + out_dir: &'a Option, krate: &'a ast::Crate) -> CompileState<'a, 'ast, 'tcx> { CompileState { @@ -272,7 +274,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_expand(input: &'a Input, session: &'a Session, - out_dir: &'a Option, + out_dir: &'a Option, expanded_crate: &'a ast::Crate, crate_name: &'a str) -> CompileState<'a, 'ast, 'tcx> { @@ -285,28 +287,30 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_write_deps(input: &'a Input, session: &'a Session, - out_dir: &'a Option, + out_dir: &'a Option, ast_map: &'a ast_map::Map<'ast>, + expanded_crate: &'a ast::Crate, crate_name: &'a str) -> CompileState<'a, 'ast, 'tcx> { CompileState { crate_name: Some(crate_name), ast_map: Some(ast_map), + expanded_crate: Some(expanded_crate), .. CompileState::empty(input, session, out_dir) } } fn state_after_analysis(input: &'a Input, session: &'a Session, - out_dir: &'a Option, - krate: &'a ast::Crate, + out_dir: &'a Option, + expanded_crate: &'a ast::Crate, analysis: &'a ty::CrateAnalysis<'tcx>, tcx: &'a ty::ctxt<'tcx>) -> CompileState<'a, 'ast, 'tcx> { CompileState { analysis: Some(analysis), tcx: Some(tcx), - krate: Some(krate), + expanded_crate: Some(expanded_crate), .. CompileState::empty(input, session, out_dir) } } @@ -314,7 +318,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> { fn state_after_llvm(input: &'a Input, session: &'a Session, - out_dir: &'a Option, + out_dir: &'a Option, trans: &'a trans::CrateTranslation) -> CompileState<'a, 'ast, 'tcx> { CompileState { @@ -375,9 +379,9 @@ pub fn phase_2_configure_and_expand(sess: &Session, let time_passes = sess.time_passes(); *sess.crate_types.borrow_mut() = - collect_crate_types(sess, &krate.attrs[]); + collect_crate_types(sess, &krate.attrs); *sess.crate_metadata.borrow_mut() = - collect_crate_metadata(sess, &krate.attrs[]); + collect_crate_metadata(sess, &krate.attrs); time(time_passes, "recursion limit", (), |_| { middle::recursion_limit::update_recursion_limit(sess, &krate); @@ -464,7 +468,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // dependent dlls. Note that this uses cfg!(windows) as opposed to // targ_cfg because syntax extensions are always loaded for the host // compiler, not for the target. - let mut _old_path = OsString::from_str(""); + let mut _old_path = OsString::new(); if cfg!(windows) { _old_path = env::var_os("PATH").unwrap_or(_old_path); let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths(); @@ -489,12 +493,15 @@ pub fn phase_2_configure_and_expand(sess: &Session, } ); - // Needs to go *after* expansion to be able to check the results of macro expansion. - time(time_passes, "complete gated feature checking", (), |_| { + // Needs to go *after* expansion to be able to check the results + // of macro expansion. This runs before #[cfg] to try to catch as + // much as possible (e.g. help the programmer avoid platform + // specific differences) + time(time_passes, "complete gated feature checking 1", (), |_| { let features = syntax::feature_gate::check_crate(sess.codemap(), - &sess.parse_sess.span_diagnostic, - &krate); + &sess.parse_sess.span_diagnostic, + &krate); *sess.features.borrow_mut() = features; sess.abort_if_errors(); }); @@ -517,6 +524,18 @@ pub fn phase_2_configure_and_expand(sess: &Session, time(time_passes, "checking that all macro invocations are gone", &krate, |krate| syntax::ext::expand::check_for_macros(&sess.parse_sess, krate)); + // One final feature gating of the true AST that gets compiled + // later, to make sure we've got everything (e.g. configuration + // can insert new attributes via `cfg_attr`) + time(time_passes, "complete gated feature checking 2", (), |_| { + let features = + syntax::feature_gate::check_crate(sess.codemap(), + &sess.parse_sess.span_diagnostic, + &krate); + *sess.features.borrow_mut() = features; + sess.abort_if_errors(); + }); + Some(krate) } @@ -568,7 +587,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, export_map, trait_map, external_exports, - last_private_map, glob_map, } = time(time_passes, "resolution", (), @@ -617,10 +635,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, time(time_passes, "const checking", (), |_| middle::check_const::check_crate(&ty_cx)); - let maps = (external_exports, last_private_map); let (exported_items, public_items) = - time(time_passes, "privacy checking", maps, |(a, b)| - rustc_privacy::check_crate(&ty_cx, &export_map, a, b)); + time(time_passes, "privacy checking", (), |_| + rustc_privacy::check_crate(&ty_cx, &export_map, external_exports)); // Do not move this check past lint time(time_passes, "stability index", (), |_| @@ -715,13 +732,13 @@ pub fn phase_5_run_llvm_passes(sess: &Session, // Remove assembly source, unless --save-temps was specified if !sess.opts.cg.save_temps { - fs::unlink(&outputs.temp_path(config::OutputTypeAssembly)).unwrap(); + fs::remove_file(&outputs.temp_path(config::OutputTypeAssembly)).unwrap(); } } else { time(sess.time_passes(), "LLVM passes", (), |_| write::run_passes(sess, trans, - &sess.opts.output_types[], + &sess.opts.output_types, outputs)); } @@ -733,7 +750,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, pub fn phase_6_link_output(sess: &Session, trans: &trans::CrateTranslation, outputs: &OutputFilenames) { - let old_path = env::var_os("PATH").unwrap_or(OsString::from_str("")); + let old_path = env::var_os("PATH").unwrap_or(OsString::new()); let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(); new_path.extend(env::split_paths(&old_path)); env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap()); @@ -742,7 +759,7 @@ pub fn phase_6_link_output(sess: &Session, link::link_binary(sess, trans, outputs, - &trans.link.crate_name[])); + &trans.link.crate_name)); env::set_var("PATH", &old_path); } @@ -791,17 +808,19 @@ fn write_out_deps(sess: &Session, _ => return, }; - let result = (|| -> old_io::IoResult<()> { + let result = (|| -> io::Result<()> { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let files: Vec = sess.codemap().files.borrow() - .iter().filter(|fmap| fmap.is_real_file()) - .map(|fmap| escape_dep_filename(&fmap.name[])) + .iter() + .filter(|fmap| fmap.is_real_file()) + .filter(|fmap| !fmap.is_imported()) + .map(|fmap| escape_dep_filename(&fmap.name)) .collect(); - let mut file = try!(old_io::File::create(&deps_filename)); + let mut file = try!(fs::File::create(&deps_filename)); for path in &out_filenames { - try!(write!(&mut file as &mut Writer, - "{}: {}\n\n", path.display(), files.connect(" "))); + try!(write!(&mut file, + "{}: {}\n\n", path.display(), files.connect(" "))); } Ok(()) })(); @@ -810,7 +829,7 @@ fn write_out_deps(sess: &Session, Ok(()) => {} Err(e) => { sess.fatal(&format!("error writing dependencies to `{}`: {}", - deps_filename.display(), e)[]); + deps_filename.display(), e)); } } } @@ -881,7 +900,7 @@ pub fn collect_crate_types(session: &Session, if !res { session.warn(&format!("dropping unsupported crate type `{}` \ for target `{}`", - *crate_type, session.opts.target_triple)[]); + *crate_type, session.opts.target_triple)); } res @@ -894,8 +913,8 @@ pub fn collect_crate_metadata(session: &Session, } pub fn build_output_filenames(input: &Input, - odir: &Option, - ofile: &Option, + odir: &Option, + ofile: &Option, attrs: &[ast::Attribute], sess: &Session) -> OutputFilenames { @@ -906,7 +925,7 @@ pub fn build_output_filenames(input: &Input, // We want to toss everything after the final '.' let dirpath = match *odir { Some(ref d) => d.clone(), - None => Path::new(".") + None => PathBuf::new() }; // If a crate name is present, we use it as the link name @@ -933,9 +952,13 @@ pub fn build_output_filenames(input: &Input, if *odir != None { sess.warn("ignoring --out-dir flag due to -o flag."); } + + let cur_dir = Path::new(""); + OutputFilenames { - out_directory: out_file.dir_path(), - out_filestem: out_file.filestem_str().unwrap().to_string(), + out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(), + out_filestem: out_file.file_stem().unwrap() + .to_str().unwrap().to_string(), single_output_file: ofile, extra: sess.opts.cg.extra_filename.clone(), } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2550432c81..b32c6829a2 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_driver"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -25,18 +27,14 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] -#![feature(env)] -#![feature(int_uint)] -#![feature(old_io)] #![feature(libc)] -#![feature(os)] -#![feature(old_path)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(unsafe_destructor)] #![feature(staged_api)] +#![feature(exit_status)] +#![feature(set_stdio)] #![feature(unicode)] extern crate arena; @@ -47,12 +45,13 @@ extern crate libc; extern crate rustc; extern crate rustc_back; extern crate rustc_borrowck; +extern crate rustc_lint; extern crate rustc_privacy; extern crate rustc_resolve; extern crate rustc_trans; extern crate rustc_typeck; extern crate serialize; -extern crate "rustc_llvm" as llvm; +extern crate rustc_llvm as llvm; #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -72,10 +71,12 @@ use rustc::metadata; use rustc::util::common::time; use std::cmp::Ordering::Equal; -use std::old_io::{self, stdio}; -use std::iter::repeat; use std::env; -use std::sync::mpsc::channel; +use std::io::{self, Read, Write}; +use std::iter::repeat; +use std::path::PathBuf; +use std::str; +use std::sync::{Arc, Mutex}; use std::thread; use rustc::session::early_error; @@ -92,11 +93,11 @@ pub mod driver; pub mod pretty; -static BUG_REPORT_URL: &'static str = +const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports"; -pub fn run(args: Vec) -> int { +pub fn run(args: Vec) -> isize { monitor(move || run_compiler(&args, &mut RustcDefaultCalls)); 0 } @@ -124,7 +125,7 @@ pub fn run_compiler<'a>(args: &[String], let sopts = config::build_session_options(&matches); let (odir, ofile) = make_output(&matches); - let (input, input_file_path) = match make_input(&matches.free[]) { + let (input, input_file_path) = match make_input(&matches.free) { Some((input, input_file_path)) => callbacks.some_input(input, input_file_path), None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) { Some((input, input_file_path)) => (input, input_file_path), @@ -133,6 +134,7 @@ pub fn run_compiler<'a>(args: &[String], }; let mut sess = build_session(sopts, input_file_path, descriptions); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); if sess.unstable_options() { sess.opts.show_span = matches.opt_str("show-span"); } @@ -157,22 +159,22 @@ pub fn run_compiler<'a>(args: &[String], } // Extract output directory and file from matches. -fn make_output(matches: &getopts::Matches) -> (Option, Option) { - let odir = matches.opt_str("out-dir").map(|o| Path::new(o)); - let ofile = matches.opt_str("o").map(|o| Path::new(o)); +fn make_output(matches: &getopts::Matches) -> (Option, Option) { + let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); + let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o)); (odir, ofile) } // Extract input (string or file and optional path) from matches. -fn make_input(free_matches: &[String]) -> Option<(Input, Option)> { +fn make_input(free_matches: &[String]) -> Option<(Input, Option)> { if free_matches.len() == 1 { - let ifile = &free_matches[0][]; + let ifile = &free_matches[0][..]; if ifile == "-" { - let contents = old_io::stdin().read_to_end().unwrap(); - let src = String::from_utf8(contents).unwrap(); + let mut src = String::new(); + io::stdin().read_to_string(&mut src).unwrap(); Some((Input::Str(src), None)) } else { - Some((Input::File(Path::new(ifile)), Some(Path::new(ifile)))) + Some((Input::File(PathBuf::from(ifile)), Some(PathBuf::from(ifile)))) } } else { None @@ -180,7 +182,7 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option)> { } // Whether to stop or continue compilation. -#[derive(Copy, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Compilation { Stop, Continue, @@ -213,14 +215,15 @@ pub trait CompilerCalls<'a> { &getopts::Matches, &Session, &Input, - &Option, - &Option) + &Option, + &Option) -> Compilation; // Called after we extract the input from the arguments. Gives the implementer // an opportunity to change the inputs or to add some custom input handling. // The default behaviour is to simply pass through the inputs. - fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { + fn some_input(&mut self, input: Input, input_path: Option) + -> (Input, Option) { (input, input_path) } @@ -232,10 +235,10 @@ pub trait CompilerCalls<'a> { fn no_input(&mut self, &getopts::Matches, &config::Options, - &Option, - &Option, + &Option, + &Option, &diagnostics::registry::Registry) - -> Option<(Input, Option)>; + -> Option<(Input, Option)>; // Parse pretty printing information from the arguments. The implementer can // choose to ignore this (the default will return None) which will skip pretty @@ -262,7 +265,7 @@ pub trait CompilerCalls<'a> { } // CompilerCalls instance for a regular rustc build. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct RustcDefaultCalls; impl<'a> CompilerCalls<'a> for RustcDefaultCalls { @@ -277,7 +280,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { println!("{}", description); } None => { - early_error(&format!("no extended information for {}", code)[]); + early_error(&format!("no extended information for {}", code)); } } return Compilation::Stop; @@ -291,19 +294,20 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn no_input(&mut self, matches: &getopts::Matches, sopts: &config::Options, - odir: &Option, - ofile: &Option, + odir: &Option, + ofile: &Option, descriptions: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { + -> Option<(Input, Option)> { match matches.free.len() { 0 => { if sopts.describe_lints { let mut ls = lint::LintStore::new(); - ls.register_builtin(None); + rustc_lint::register_builtins(&mut ls, None); describe_lints(&ls, false); return None; } let sess = build_session(sopts.clone(), None, descriptions.clone()); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let should_stop = RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile); if should_stop == Compilation::Stop { return None; @@ -343,8 +347,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { matches: &getopts::Matches, sess: &Session, input: &Input, - odir: &Option, - ofile: &Option) + odir: &Option, + ofile: &Option) -> Compilation { RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile).and_then( || RustcDefaultCalls::list_metadata(sess, matches, input)) @@ -373,11 +377,13 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { if sess.opts.debugging_opts.save_analysis { control.after_analysis.callback = box |state| { - time(state.session.time_passes(), "save analysis", state.krate.unwrap(), |krate| - save::process_crate(state.session, - krate, - state.analysis.unwrap(), - state.out_dir)); + time(state.session.time_passes(), + "save analysis", + state.expanded_crate.unwrap(), + |krate| save::process_crate(state.session, + krate, + state.analysis.unwrap(), + state.out_dir)); }; control.make_glob_map = resolve::MakeGlobMap::Yes; } @@ -395,11 +401,12 @@ impl RustcDefaultCalls { if r.contains(&("ls".to_string())) { match input { &Input::File(ref ifile) => { - let mut stdout = old_io::stdout(); let path = &(*ifile); + let mut v = Vec::new(); metadata::loader::list_file_metadata(sess.target.target.options.is_like_osx, path, - &mut stdout).unwrap(); + &mut v).unwrap(); + println!("{}", String::from_utf8(v).unwrap()); } &Input::Str(_) => { early_error("cannot list metadata for stdin"); @@ -414,8 +421,8 @@ impl RustcDefaultCalls { fn print_crate_info(sess: &Session, input: Option<&Input>, - odir: &Option, - ofile: &Option) + odir: &Option, + ofile: &Option) -> Compilation { if sess.opts.prints.len() == 0 { return Compilation::Continue; @@ -452,7 +459,8 @@ impl RustcDefaultCalls { style, &id, &t_outputs.with_extension("")); - println!("{}", fname.filename_display()); + println!("{}", fname.file_name().unwrap() + .to_string_lossy()); } } } @@ -607,8 +615,7 @@ Available lint options: let print_lint_groups = |lints: Vec<(&'static str, Vec)>| { for (name, to) in lints { - let name = name.chars().map(|x| x.to_lowercase()) - .collect::().replace("_", "-"); + let name = name.to_lowercase().replace("_", "-"); let desc = to.into_iter().map(|x| x.as_str().replace("_", "-")) .collect::>().connect(", "); println!(" {} {}", @@ -677,39 +684,57 @@ pub fn handle_options(mut args: Vec) -> Option { return None; } - let matches = - match getopts::getopts(&args[..], &config::optgroups()[]) { - Ok(m) => m, - Err(f_stable_attempt) => { - // redo option parsing, including unstable options this time, - // in anticipation that the mishandled option was one of the - // unstable ones. - let all_groups : Vec - = config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect(); - match getopts::getopts(&args, &all_groups) { - Ok(m_unstable) => { - let r = m_unstable.opt_strs("Z"); - let include_unstable_options = r.iter().any(|x| *x == "unstable-options"); - if include_unstable_options { - m_unstable + fn allows_unstable_options(matches: &getopts::Matches) -> bool { + let r = matches.opt_strs("Z"); + r.iter().any(|x| *x == "unstable-options") + } + + fn parse_all_options(args: &Vec) -> getopts::Matches { + let all_groups : Vec + = config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect(); + match getopts::getopts(&args[..], &all_groups) { + Ok(m) => { + if !allows_unstable_options(&m) { + // If -Z unstable-options was not specified, verify that + // no unstable options were present. + for opt in config::rustc_optgroups().into_iter().filter(|x| !x.is_stable()) { + let opt_name = if !opt.opt_group.long_name.is_empty() { + &opt.opt_group.long_name } else { - early_error(&f_stable_attempt.to_string()); + &opt.opt_group.short_name + }; + if m.opt_present(opt_name) { + early_error(&format!("use of unstable option '{}' requires \ + -Z unstable-options", opt_name)); } } - Err(_) => { - // ignore the error from the unstable attempt; just - // pass the error we got from the first try. - early_error(&f_stable_attempt.to_string()); - } } + m } - }; + Err(f) => early_error(&f.to_string()) + } + } - let r = matches.opt_strs("Z"); - let include_unstable_options = r.iter().any(|x| *x == "unstable-options"); + // As a speed optimization, first try to parse the command-line using just + // the stable options. + let matches = match getopts::getopts(&args[..], &config::optgroups()) { + Ok(ref m) if allows_unstable_options(m) => { + // If -Z unstable-options was specified, redo parsing with the + // unstable options to ensure that unstable options are defined + // in the returned getopts::Matches. + parse_all_options(&args) + } + Ok(m) => m, + Err(_) => { + // redo option parsing, including unstable options this time, + // in anticipation that the mishandled option was one of the + // unstable ones. + parse_all_options(&args) + } + }; if matches.opt_present("h") || matches.opt_present("help") { - usage(matches.opt_present("verbose"), include_unstable_options); + usage(matches.opt_present("verbose"), allows_unstable_options(&matches)); return None; } @@ -764,12 +789,20 @@ fn parse_crate_attrs(sess: &Session, input: &Input) -> /// /// The diagnostic emitter yielded to the procedure should be used for reporting /// errors of the compiler. +#[allow(deprecated)] pub fn monitor(f: F) { - static STACK_SIZE: uint = 8 * 1024 * 1024; // 8MB + const STACK_SIZE: usize = 8 * 1024 * 1024; // 8MB - let (tx, rx) = channel(); - let w = old_io::ChanWriter::new(tx); - let mut r = old_io::ChanReader::new(rx); + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + + let data = Arc::new(Mutex::new(Vec::new())); + let err = Sink(data.clone()); let mut cfg = thread::Builder::new().name("rustc".to_string()); @@ -779,7 +812,7 @@ pub fn monitor(f: F) { cfg = cfg.stack_size(STACK_SIZE); } - match cfg.spawn(move || { stdio::set_stderr(box w); f() }).unwrap().join() { + match cfg.spawn(move || { io::set_panic(box err); f() }).unwrap().join() { Ok(()) => { /* fallthrough */ } Err(value) => { // Thread panicked without emitting a fatal diagnostic @@ -806,22 +839,13 @@ pub fn monitor(f: F) { emitter.emit(None, ¬e[..], None, diagnostic::Note) } - match r.read_to_string() { - Ok(s) => println!("{}", s), - Err(e) => { - emitter.emit(None, - &format!("failed to read internal \ - stderr: {}", e)[], - None, - diagnostic::Error) - } - } + println!("{}", str::from_utf8(&data.lock().unwrap()).unwrap()); } // Panic so the process returns a failure code, but don't pollute the // output with some unnecessary panic messages, we've already // printed everything that we needed to. - old_io::stdio::set_stderr(box old_io::util::NullWriter); + io::set_panic(box io::sink()); panic!(); } } @@ -831,9 +855,9 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry { use syntax::diagnostics::registry::Registry; let all_errors = Vec::new() + - rustc::diagnostics::DIAGNOSTICS.as_slice() + - rustc_typeck::diagnostics::DIAGNOSTICS.as_slice() + - rustc_resolve::diagnostics::DIAGNOSTICS.as_slice(); + &rustc::diagnostics::DIAGNOSTICS[..] + + &rustc_typeck::diagnostics::DIAGNOSTICS[..] + + &rustc_resolve::diagnostics::DIAGNOSTICS[..]; Registry::new(&*all_errors) } @@ -842,4 +866,3 @@ pub fn main() { let result = run(env::args().collect()); std::env::set_exit_status(result as i32); } - diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 0fbfa5fd89..410f31e090 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -38,11 +38,13 @@ use syntax::ptr::P; use graphviz as dot; -use std::old_io::{self, MemReader}; +use std::fs::File; +use std::io::{self, Write}; use std::option; +use std::path::PathBuf; use std::str::FromStr; -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum PpSourceMode { PpmNormal, PpmEveryBodyLoops, @@ -54,7 +56,7 @@ pub enum PpSourceMode { } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum PpFlowGraphMode { Default, /// Drops the labels from the edges in the flowgraph output. This @@ -63,7 +65,7 @@ pub enum PpFlowGraphMode { /// have become a pain to maintain. UnlabelledEdges, } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum PpMode { PpmSource(PpSourceMode), PpmFlowGraph(PpFlowGraphMode), @@ -72,7 +74,7 @@ pub enum PpMode { pub fn parse_pretty(sess: &Session, name: &str, extended: bool) -> (PpMode, Option) { - let mut split = name.splitn(1, '='); + let mut split = name.splitn(2, '='); let first = split.next().unwrap(); let opt_second = split.next(); let first = match (first, extended) { @@ -208,7 +210,7 @@ impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> { impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { fn pre(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> old_io::IoResult<()> { + node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeExpr(_) => s.popen(), _ => Ok(()) @@ -216,7 +218,7 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { } fn post(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> old_io::IoResult<()> { + node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeIdent(_) | pprust::NodeName(_) => Ok(()), @@ -224,6 +226,10 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> { try!(pp::space(&mut s.s)); s.synth_comment(item.id.to_string()) } + pprust::NodeSubItem(id) => { + try!(pp::space(&mut s.s)); + s.synth_comment(id.to_string()) + } pprust::NodeBlock(blk) => { try!(pp::space(&mut s.s)); s.synth_comment(format!("block {}", blk.id)) @@ -259,7 +265,7 @@ impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { fn post(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> old_io::IoResult<()> { + node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => { try!(pp::space(&mut s.s)); @@ -294,7 +300,7 @@ impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> { impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { fn pre(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> old_io::IoResult<()> { + node: pprust::AnnNode) -> io::Result<()> { match node { pprust::NodeExpr(_) => s.popen(), _ => Ok(()) @@ -302,7 +308,7 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { } fn post(&self, s: &mut pprust::State, - node: pprust::AnnNode) -> old_io::IoResult<()> { + node: pprust::AnnNode) -> io::Result<()> { let tcx = &self.analysis.ty_cx; match node { pprust::NodeExpr(expr) => { @@ -312,7 +318,7 @@ impl<'tcx> pprust::PpAnn for TypedAnnotation<'tcx> { try!(pp::word(&mut s.s, &ppaux::ty_to_string( tcx, - ty::expr_ty(tcx, expr))[])); + ty::expr_ty(tcx, expr)))); s.pclose() } _ => Ok(()) @@ -348,7 +354,7 @@ impl FromStr for UserIdentifiedItem { type Err = (); fn from_str(s: &str) -> Result { Ok(s.parse().map(ItemViaNode).unwrap_or_else(|_| { - ItemViaPath(s.split_str("::").map(|s| s.to_string()).collect()) + ItemViaPath(s.split("::").map(|s| s.to_string()).collect()) })) } } @@ -507,7 +513,7 @@ pub fn pretty_print_input(sess: Session, input: &Input, ppm: PpMode, opt_uii: Option, - ofile: Option) { + ofile: Option) { let krate = driver::phase_1_parse_input(&sess, cfg, input); let krate = if let PpmSource(PpmEveryBodyLoops) = ppm { @@ -542,25 +548,20 @@ pub fn pretty_print_input(sess: Session, let src_name = driver::source_name(input); let src = sess.codemap().get_filemap(&src_name[..]) - .src.as_bytes().to_vec(); - let mut rdr = MemReader::new(src); + .src + .as_ref() + .unwrap() + .as_bytes() + .to_vec(); + let mut rdr = &src[..]; - let out = match ofile { - None => box old_io::stdout() as Box, - Some(p) => { - let r = old_io::File::create(&p); - match r { - Ok(w) => box w as Box, - Err(e) => panic!("print-print failed to open {} due to {}", - p.display(), e), - } - } - }; + let mut out = Vec::new(); match (ppm, opt_uii) { - (PpmSource(s), None) => + (PpmSource(s), None) => { + let out: &mut Write = &mut out; s.call_with_pp_support( - sess, ast_map, &arenas, id, out, |annotation, out| { + sess, ast_map, &arenas, id, box out, |annotation, out| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust::print_crate(sess.codemap(), @@ -571,9 +572,11 @@ pub fn pretty_print_input(sess: Session, out, annotation.pp_ann(), is_expanded) - }), + }) + } - (PpmSource(s), Some(uii)) => + (PpmSource(s), Some(uii)) => { + let out: &mut Write = &mut out; s.call_with_pp_support( sess, ast_map, &arenas, id, (out,uii), |annotation, (out,uii)| { debug!("pretty printing source code {:?}", s); @@ -585,7 +588,7 @@ pub fn pretty_print_input(sess: Session, sess.diagnostic(), src_name.to_string(), &mut rdr, - out, + box out, annotation.pp_ann(), is_expanded); for node_id in uii.all_matching_node_ids(ast_map) { @@ -596,13 +599,14 @@ pub fn pretty_print_input(sess: Session, try!(pp::hardbreak(&mut pp_state.s)); } pp::eof(&mut pp_state.s) - }), + }) + } (PpmFlowGraph(mode), opt_uii) => { debug!("pretty printing flow graph for {:?}", opt_uii); let uii = opt_uii.unwrap_or_else(|| { sess.fatal(&format!("`pretty flowgraph=..` needs NodeId (int) or - unique path suffix (b::c::d)")[]) + unique path suffix (b::c::d)")) }); let ast_map = ast_map.expect("--pretty flowgraph missing ast_map"); @@ -610,10 +614,11 @@ pub fn pretty_print_input(sess: Session, let node = ast_map.find(nodeid).unwrap_or_else(|| { sess.fatal(&format!("--pretty flowgraph couldn't find id: {}", - nodeid)[]) + nodeid)) }); let code = blocks::Code::from_node(node); + let out: &mut Write = &mut out; match code { Some(code) => { let variants = gather_flowgraph_variants(&sess); @@ -638,14 +643,25 @@ pub fn pretty_print_input(sess: Session, } } } - }.unwrap() + }.unwrap(); + + match ofile { + None => print!("{}", String::from_utf8(out).unwrap()), + Some(p) => { + match File::create(&p) { + Ok(mut w) => w.write_all(&out).unwrap(), + Err(e) => panic!("print-print failed to open {} due to {}", + p.display(), e), + } + } + } } -fn print_flowgraph(variants: Vec, - analysis: ty::CrateAnalysis, - code: blocks::Code, - mode: PpFlowGraphMode, - mut out: W) -> old_io::IoResult<()> { +fn print_flowgraph(variants: Vec, + analysis: ty::CrateAnalysis, + code: blocks::Code, + mode: PpFlowGraphMode, + mut out: W) -> io::Result<()> { let ty_cx = &analysis.ty_cx; let cfg = match code { blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block), @@ -685,17 +701,10 @@ fn print_flowgraph(variants: Vec, } } - fn expand_err_details(r: old_io::IoResult<()>) -> old_io::IoResult<()> { + fn expand_err_details(r: io::Result<()>) -> io::Result<()> { r.map_err(|ioerr| { - let orig_detail = ioerr.detail.clone(); - let m = "graphviz::render failed"; - old_io::IoError { - detail: Some(match orig_detail { - None => m.to_string(), - Some(d) => format!("{}: {}", m, d) - }), - ..ioerr - } + io::Error::new(io::ErrorKind::Other, + &format!("graphviz::render failed: {}", ioerr)[..]) }) } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index fbbd72e2c7..f9be71561e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -13,6 +13,7 @@ use diagnostic; use diagnostic::Emitter; use driver; +use rustc_lint; use rustc_resolve as resolve; use rustc_typeck::middle::lang_items; use rustc_typeck::middle::region::{self, CodeExtent, DestructionScopeData}; @@ -21,7 +22,7 @@ use rustc_typeck::middle::stability; use rustc_typeck::middle::subst; use rustc_typeck::middle::subst::Subst; use rustc_typeck::middle::ty::{self, Ty}; -use rustc_typeck::middle::infer::combine::Combine; +use rustc_typeck::middle::ty_relate::TypeRelation; use rustc_typeck::middle::infer; use rustc_typeck::middle::infer::lub::Lub; use rustc_typeck::middle::infer::glb::Glb; @@ -43,7 +44,7 @@ struct RH<'a> { sub: &'a [RH<'a>] } -static EMPTY_SOURCE_STR: &'static str = "#![feature(no_std)] #![no_std]"; +const EMPTY_SOURCE_STR: &'static str = "#![feature(no_std)] #![no_std]"; struct ExpectErrorEmitter { messages: Vec @@ -87,13 +88,13 @@ impl Emitter for ExpectErrorEmitter { } } -fn errors(msgs: &[&str]) -> (Box, uint) { +fn errors(msgs: &[&str]) -> (Box, usize) { let v = msgs.iter().map(|m| m.to_string()).collect(); (box ExpectErrorEmitter { messages: v } as Box, msgs.len()) } fn test_env(source_string: &str, - (emitter, expected_err_count): (Box, uint), + (emitter, expected_err_count): (Box, usize), body: F) where F: FnOnce(Env), { @@ -108,6 +109,7 @@ fn test_env(source_string: &str, diagnostic::mk_span_handler(diagnostic_handler, codemap); let sess = session::build_session_(options, None, span_diagnostic_handler); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let krate_config = Vec::new(); let input = config::Input::Str(source_string.to_string()); let krate = driver::phase_1_parse_input(&sess, krate_config, &input); @@ -176,7 +178,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { fn search_mod(this: &Env, m: &ast::Mod, - idx: uint, + idx: usize, names: &[String]) -> Option { assert!(idx < names.len()); @@ -190,7 +192,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { fn search(this: &Env, it: &ast::Item, - idx: uint, + idx: usize, names: &[String]) -> Option { if idx == names.len() { @@ -206,7 +208,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { ast::ItemEnum(..) | ast::ItemStruct(..) | ast::ItemTrait(..) | ast::ItemImpl(..) | - ast::ItemMac(..) => { + ast::ItemMac(..) | ast::ItemDefaultImpl(..) => { None } @@ -298,14 +300,14 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn t_rptr(&self, r: ty::Region) -> Ty<'tcx> { ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - self.tcx().types.int) + self.tcx().types.isize) } pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> { let r = self.re_late_bound_with_debruijn(id, ty::DebruijnIndex::new(1)); ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - self.tcx().types.int) + self.tcx().types.isize) } pub fn t_rptr_late_bound_with_debruijn(&self, @@ -315,13 +317,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> { let r = self.re_late_bound_with_debruijn(id, debruijn); ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - self.tcx().types.int) + self.tcx().types.isize) } pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> { let r = ty::ReScope(CodeExtent::from_node_id(id)); ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - self.tcx().types.int) + self.tcx().types.isize) } pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region { @@ -333,13 +335,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> { let r = self.re_free(nid, id); ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), - self.tcx().types.int) + self.tcx().types.isize) } pub fn t_rptr_static(&self) -> Ty<'tcx> { ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(ty::ReStatic), - self.tcx().types.int) + self.tcx().types.isize) } pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> { @@ -348,21 +350,21 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn sub(&self) -> Sub<'a, 'tcx> { let trace = self.dummy_type_trace(); - Sub(self.infcx.combine_fields(true, trace)) + self.infcx.sub(true, trace) } pub fn lub(&self) -> Lub<'a, 'tcx> { let trace = self.dummy_type_trace(); - Lub(self.infcx.combine_fields(true, trace)) + self.infcx.lub(true, trace) } pub fn glb(&self) -> Glb<'a, 'tcx> { let trace = self.dummy_type_trace(); - Glb(self.infcx.combine_fields(true, trace)) + self.infcx.glb(true, trace) } pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> { - match self.lub().tys(t1, t2) { + match self.lub().relate(&t1, &t2) { Ok(t) => t, Err(ref e) => panic!("unexpected error computing LUB: {}", ty::type_err_to_str(self.infcx.tcx, e)) @@ -372,7 +374,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// Checks that `t1 <: t2` is true (this may register additional /// region checks). pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { - match self.sub().tys(t1, t2) { + match self.sub().relate(&t1, &t2) { Ok(_) => { } Err(ref e) => { panic!("unexpected error computing sub({},{}): {}", @@ -386,7 +388,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// Checks that `t1 <: t2` is false (this may register additional /// region checks). pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { - match self.sub().tys(t1, t2) { + match self.sub().relate(&t1, &t2) { Err(_) => { } Ok(_) => { panic!("unexpected success computing sub({},{})", @@ -398,7 +400,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// Checks that `LUB(t1,t2) == t_lub` pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) { - match self.lub().tys(t1, t2) { + match self.lub().relate(&t1, &t2) { Ok(t) => { self.assert_eq(t, t_lub); } @@ -415,7 +417,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { self.ty_to_string(t1), self.ty_to_string(t2), self.ty_to_string(t_glb)); - match self.glb().tys(t1, t2) { + match self.glb().relate(&t1, &t2) { Err(e) => { panic!("unexpected error computing LUB: {:?}", e) } @@ -462,15 +464,15 @@ fn contravariant_region_ptr_err() { fn sub_free_bound_false() { //! Test that: //! - //! fn(&'a int) <: for<'b> fn(&'b int) + //! fn(&'a isize) <: for<'b> fn(&'b isize) //! //! does NOT hold. test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); }) } @@ -478,15 +480,15 @@ fn sub_free_bound_false() { fn sub_bound_free_true() { //! Test that: //! - //! for<'a> fn(&'a int) <: fn(&'b int) + //! for<'a> fn(&'a isize) <: fn(&'b isize) //! //! DOES hold. test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_free1], env.tcx().types.int)); + env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free1], env.tcx().types.isize)); }) } @@ -494,15 +496,15 @@ fn sub_bound_free_true() { fn sub_free_bound_false_infer() { //! Test that: //! - //! fn(_#1) <: for<'b> fn(&'b int) + //! fn(_#1) <: for<'b> fn(&'b isize) //! //! does NOT hold for any instantiation of `_#1`. test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_infer1 = env.infcx.next_ty_var(); let t_rptr_bound1 = env.t_rptr_late_bound(1); - env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); }) } @@ -510,19 +512,19 @@ fn sub_free_bound_false_infer() { fn lub_free_bound_infer() { //! Test result of: //! - //! LUB(fn(_#1), for<'b> fn(&'b int)) + //! LUB(fn(_#1), for<'b> fn(&'b isize)) //! - //! This should yield `fn(&'_ int)`. We check - //! that it yields `fn(&'x int)` for some free `'x`, + //! This should yield `fn(&'_ isize)`. We check + //! that it yields `fn(&'x isize)` for some free `'x`, //! anyhow. test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_infer1 = env.infcx.next_ty_var(); let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_free1], env.tcx().types.int)); + env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free1], env.tcx().types.isize)); }); } @@ -531,9 +533,9 @@ fn lub_bound_bound() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_bound2 = env.t_rptr_late_bound(2); - env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound2], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound2], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); }) } @@ -542,9 +544,9 @@ fn lub_bound_free() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_free1], env.tcx().types.int), - env.t_fn(&[t_rptr_free1], env.tcx().types.int)); + env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free1], env.tcx().types.isize)); }) } @@ -553,9 +555,9 @@ fn lub_bound_static() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_static = env.t_rptr_static(); - env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_static], env.tcx().types.int), - env.t_fn(&[t_rptr_static], env.tcx().types.int)); + env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_static], env.tcx().types.isize), + env.t_fn(&[t_rptr_static], env.tcx().types.isize)); }) } @@ -576,9 +578,9 @@ fn lub_free_free() { let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_free2 = env.t_rptr_free(0, 2); let t_rptr_static = env.t_rptr_static(); - env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.int), - env.t_fn(&[t_rptr_free2], env.tcx().types.int), - env.t_fn(&[t_rptr_static], env.tcx().types.int)); + env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free2], env.tcx().types.isize), + env.t_fn(&[t_rptr_static], env.tcx().types.isize)); }) } @@ -586,6 +588,7 @@ fn lub_free_free() { fn lub_returning_scope() { test_env(EMPTY_SOURCE_STR, errors(&["cannot infer an appropriate lifetime"]), |env| { + env.create_simple_region_hierarchy(); let t_rptr_scope10 = env.t_rptr_scope(10); let t_rptr_scope11 = env.t_rptr_scope(11); @@ -601,9 +604,9 @@ fn glb_free_free_with_common_scope() { let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_free2 = env.t_rptr_free(0, 2); let t_rptr_scope = env.t_rptr_scope(0); - env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.int), - env.t_fn(&[t_rptr_free2], env.tcx().types.int), - env.t_fn(&[t_rptr_scope], env.tcx().types.int)); + env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free2], env.tcx().types.isize), + env.t_fn(&[t_rptr_scope], env.tcx().types.isize)); }) } @@ -612,9 +615,9 @@ fn glb_bound_bound() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_bound2 = env.t_rptr_late_bound(2); - env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound2], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound2], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); }) } @@ -623,9 +626,9 @@ fn glb_bound_free() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); - env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_free1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_free1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); }) } @@ -635,14 +638,14 @@ fn glb_bound_free_infer() { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_infer1 = env.infcx.next_ty_var(); - // compute GLB(fn(_) -> int, for<'b> fn(&'b int) -> int), - // which should yield for<'b> fn(&'b int) -> int - env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_infer1], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + // compute GLB(fn(_) -> isize, for<'b> fn(&'b isize) -> isize), + // which should yield for<'b> fn(&'b isize) -> isize + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_infer1], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); // as a side-effect, computing GLB should unify `_` with - // `&'_ int` + // `&'_ isize` let t_resolve1 = env.infcx.shallow_resolve(t_infer1); match t_resolve1.sty { ty::ty_rptr(..) => { } @@ -656,9 +659,9 @@ fn glb_bound_static() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let t_rptr_bound1 = env.t_rptr_late_bound(1); let t_rptr_static = env.t_rptr_static(); - env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int), - env.t_fn(&[t_rptr_static], env.tcx().types.int), - env.t_fn(&[t_rptr_bound1], env.tcx().types.int)); + env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.isize), + env.t_fn(&[t_rptr_static], env.tcx().types.isize), + env.t_fn(&[t_rptr_bound1], env.tcx().types.isize)); }) } @@ -682,7 +685,7 @@ fn subst_ty_renumber_bound() { let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]); let t_substituted = t_source.subst(env.infcx.tcx, &substs); - // t_expected = fn(&'a int) + // t_expected = fn(&'a isize) let t_expected = { let t_ptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(2)); env.t_fn(&[t_ptr_bound2], env.t_nil()) @@ -717,7 +720,7 @@ fn subst_ty_renumber_some_bounds() { let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]); let t_substituted = t_source.subst(env.infcx.tcx, &substs); - // t_expected = (&'a int, fn(&'a int)) + // t_expected = (&'a isize, fn(&'a isize)) // // but not that the Debruijn index is different in the different cases. let t_expected = { @@ -769,7 +772,7 @@ fn subst_region_renumber_region() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let re_bound1 = env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1)); - // type t_source<'a> = fn(&'a int) + // type t_source<'a> = fn(&'a isize) let t_source = { let re_early = env.re_early_bound(subst::TypeSpace, 0, "'a"); env.t_fn(&[env.t_rptr(re_early)], env.t_nil()) @@ -778,7 +781,7 @@ fn subst_region_renumber_region() { let substs = subst::Substs::new_type(vec![], vec![re_bound1]); let t_substituted = t_source.subst(env.infcx.tcx, &substs); - // t_expected = fn(&'a int) + // t_expected = fn(&'a isize) // // but not that the Debruijn index is different in the different cases. let t_expected = { @@ -800,18 +803,17 @@ fn subst_region_renumber_region() { fn walk_ty() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let tcx = env.infcx.tcx; - let int_ty = tcx.types.int; - let uint_ty = tcx.types.uint; + let int_ty = tcx.types.isize; + let uint_ty = tcx.types.usize; let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty)); let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty)); let uniq_ty = ty::mk_uniq(tcx, tup2_ty); let walked: Vec<_> = uniq_ty.walk().collect(); - assert_eq!(vec!(uniq_ty, - tup2_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - tup1_ty, int_ty, uint_ty, int_ty, uint_ty, - uint_ty), - walked); + assert_eq!(walked, [uniq_ty, + tup2_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + tup1_ty, int_ty, uint_ty, int_ty, uint_ty, + uint_ty]); }) } @@ -819,8 +821,8 @@ fn walk_ty() { fn walk_ty_skip_subtree() { test_env(EMPTY_SOURCE_STR, errors(&[]), |env| { let tcx = env.infcx.tcx; - let int_ty = tcx.types.int; - let uint_ty = tcx.types.uint; + let int_ty = tcx.types.isize; + let uint_ty = tcx.types.usize; let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty)); let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty)); let uniq_ty = ty::mk_uniq(tcx, tup2_ty); @@ -834,7 +836,7 @@ fn walk_ty_skip_subtree() { (uint_ty, false), (int_ty, false), (uint_ty, false), - (tup1_ty, true), // skip the int/uint/int/uint + (tup1_ty, true), // skip the isize/usize/isize/usize (uint_ty, false)); expected.reverse(); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs new file mode 100644 index 0000000000..3bb737ddc1 --- /dev/null +++ b/src/librustc_lint/builtin.rs @@ -0,0 +1,2109 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Lints in the Rust compiler. +//! +//! This contains lints which can feasibly be implemented as their own +//! AST visitor. Also see `rustc::lint::builtin`, which contains the +//! definitions of lints that are emitted directly inside the main +//! compiler. +//! +//! To add a new lint to rustc, declare it here using `declare_lint!()`. +//! Then add code to emit the new lint in the appropriate circumstances. +//! You can do that in an existing `LintPass` if it makes sense, or in a +//! new `LintPass`, or using `Session::add_lint` elsewhere in the +//! compiler. Only do the latter if the check can't be written cleanly as a +//! `LintPass` (also, note that such lints will need to be defined in +//! `rustc::lint::builtin`, not here). +//! +//! If you define a new `LintPass`, you will also need to add it to the +//! `add_builtin!` or `add_builtin_with_new!` invocation in `lib.rs`. +//! Use the former for unit-like structs and the latter for structs with +//! a `pub fn new()`. + +use metadata::{csearch, decoder}; +use middle::def::*; +use middle::subst::Substs; +use middle::ty::{self, Ty}; +use middle::{def, pat_util, stability}; +use middle::const_eval::{eval_const_expr_partial, const_int, const_uint}; +use middle::cfg; +use util::ppaux::ty_to_string; +use util::nodemap::{FnvHashMap, NodeSet}; +use lint::{Level, Context, LintPass, LintArray, Lint}; + +use std::collections::{HashSet, BitSet}; +use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::{cmp, slice}; +use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; + +use syntax::{abi, ast, ast_map}; +use syntax::ast_util::{self, is_shift_binop, local_def}; +use syntax::attr::{self, AttrMetaMethods}; +use syntax::codemap::{self, Span}; +use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType}; +use syntax::parse::token; +use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; +use syntax::ptr::P; +use syntax::visit::{self, Visitor}; + +// hardwired lints from librustc +pub use lint::builtin::*; + +declare_lint! { + WHILE_TRUE, + Warn, + "suggest using `loop { }` instead of `while true { }`" +} + +#[derive(Copy, Clone)] +pub struct WhileTrue; + +impl LintPass for WhileTrue { + fn get_lints(&self) -> LintArray { + lint_array!(WHILE_TRUE) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + if let ast::ExprWhile(ref cond, _, _) = e.node { + if let ast::ExprLit(ref lit) = cond.node { + if let ast::LitBool(true) = lit.node { + cx.span_lint(WHILE_TRUE, e.span, + "denote infinite loops with loop { ... }"); + } + } + } + } +} + +declare_lint! { + UNSIGNED_NEGATION, + Warn, + "using an unary minus operator on unsigned type" +} + +declare_lint! { + UNUSED_COMPARISONS, + Warn, + "comparisons made useless by limits of the types involved" +} + +declare_lint! { + OVERFLOWING_LITERALS, + Warn, + "literal out of range for its type" +} + +declare_lint! { + EXCEEDING_BITSHIFTS, + Deny, + "shift exceeds the type's number of bits" +} + +#[derive(Copy, Clone)] +pub struct TypeLimits { + /// Id of the last visited negated expression + negated_expr_id: ast::NodeId, +} + +impl TypeLimits { + pub fn new() -> TypeLimits { + TypeLimits { + negated_expr_id: !0, + } + } +} + +impl LintPass for TypeLimits { + fn get_lints(&self) -> LintArray { + lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS, + EXCEEDING_BITSHIFTS) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + match e.node { + ast::ExprUnary(ast::UnNeg, ref expr) => { + match expr.node { + ast::ExprLit(ref lit) => { + match lit.node { + ast::LitInt(_, ast::UnsignedIntLit(_)) => { + cx.span_lint(UNSIGNED_NEGATION, e.span, + "negation of unsigned int literal may \ + be unintentional"); + }, + _ => () + } + }, + _ => { + let t = ty::expr_ty(cx.tcx, &**expr); + match t.sty { + ty::ty_uint(_) => { + cx.span_lint(UNSIGNED_NEGATION, e.span, + "negation of unsigned int variable may \ + be unintentional"); + }, + _ => () + } + } + }; + // propagate negation, if the negation itself isn't negated + if self.negated_expr_id != e.id { + self.negated_expr_id = expr.id; + } + }, + ast::ExprParen(ref expr) if self.negated_expr_id == e.id => { + self.negated_expr_id = expr.id; + }, + ast::ExprBinary(binop, ref l, ref r) => { + if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) { + cx.span_lint(UNUSED_COMPARISONS, e.span, + "comparison is useless due to type limits"); + } + + if is_shift_binop(binop.node) { + let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty { + ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), + ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), + _ => None + }; + + if let Some(bits) = opt_ty_bits { + let exceeding = if let ast::ExprLit(ref lit) = r.node { + if let ast::LitInt(shift, _) = lit.node { shift >= bits } + else { false } + } else { + match eval_const_expr_partial(cx.tcx, &**r, Some(cx.tcx.types.usize)) { + Ok(const_int(shift)) => { shift as u64 >= bits }, + Ok(const_uint(shift)) => { shift >= bits }, + _ => { false } + } + }; + if exceeding { + cx.span_lint(EXCEEDING_BITSHIFTS, e.span, + "bitshift exceeds the type's number of bits"); + } + }; + } + }, + ast::ExprLit(ref lit) => { + match ty::expr_ty(cx.tcx, e).sty { + ty::ty_int(t) => { + match lit.node { + ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | + ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => { + let int_type = if let ast::TyIs = t { + cx.sess().target.int_type + } else { + t + }; + let (min, max) = int_ty_range(int_type); + let negative = self.negated_expr_id == e.id; + + if (negative && v > (min.abs() as u64)) || + (!negative && v > (max.abs() as u64)) { + cx.span_lint(OVERFLOWING_LITERALS, e.span, + &*format!("literal out of range for {:?}", t)); + return; + } + } + _ => panic!() + }; + }, + ty::ty_uint(t) => { + let uint_type = if let ast::TyUs = t { + cx.sess().target.uint_type + } else { + t + }; + let (min, max) = uint_ty_range(uint_type); + let lit_val: u64 = match lit.node { + ast::LitByte(_v) => return, // _v is u8, within range by definition + ast::LitInt(v, _) => v, + _ => panic!() + }; + if lit_val < min || lit_val > max { + cx.span_lint(OVERFLOWING_LITERALS, e.span, + &*format!("literal out of range for {:?}", t)); + } + }, + ty::ty_float(t) => { + let (min, max) = float_ty_range(t); + let lit_val: f64 = match lit.node { + ast::LitFloat(ref v, _) | + ast::LitFloatUnsuffixed(ref v) => { + match v.parse() { + Ok(f) => f, + Err(_) => return + } + } + _ => panic!() + }; + if lit_val < min || lit_val > max { + cx.span_lint(OVERFLOWING_LITERALS, e.span, + &*format!("literal out of range for {:?}", t)); + } + }, + _ => () + }; + }, + _ => () + }; + + fn is_valid(binop: ast::BinOp, v: T, + min: T, max: T) -> bool { + match binop.node { + ast::BiLt => v > min && v <= max, + ast::BiLe => v >= min && v < max, + ast::BiGt => v >= min && v < max, + ast::BiGe => v > min && v <= max, + ast::BiEq | ast::BiNe => v >= min && v <= max, + _ => panic!() + } + } + + fn rev_binop(binop: ast::BinOp) -> ast::BinOp { + codemap::respan(binop.span, match binop.node { + ast::BiLt => ast::BiGt, + ast::BiLe => ast::BiGe, + ast::BiGt => ast::BiLt, + ast::BiGe => ast::BiLe, + _ => return binop + }) + } + + // for isize & usize, be conservative with the warnings, so that the + // warnings are consistent between 32- and 64-bit platforms + fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) { + match int_ty { + ast::TyIs => (i64::MIN, i64::MAX), + ast::TyI8 => (i8::MIN as i64, i8::MAX as i64), + ast::TyI16 => (i16::MIN as i64, i16::MAX as i64), + ast::TyI32 => (i32::MIN as i64, i32::MAX as i64), + ast::TyI64 => (i64::MIN, i64::MAX) + } + } + + fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) { + match uint_ty { + ast::TyUs => (u64::MIN, u64::MAX), + ast::TyU8 => (u8::MIN as u64, u8::MAX as u64), + ast::TyU16 => (u16::MIN as u64, u16::MAX as u64), + ast::TyU32 => (u32::MIN as u64, u32::MAX as u64), + ast::TyU64 => (u64::MIN, u64::MAX) + } + } + + fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) { + match float_ty { + ast::TyF32 => (f32::MIN as f64, f32::MAX as f64), + ast::TyF64 => (f64::MIN, f64::MAX) + } + } + + fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 { + match int_ty { + ast::TyIs => int_ty_bits(target_int_ty, target_int_ty), + ast::TyI8 => i8::BITS as u64, + ast::TyI16 => i16::BITS as u64, + ast::TyI32 => i32::BITS as u64, + ast::TyI64 => i64::BITS as u64 + } + } + + fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 { + match uint_ty { + ast::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty), + ast::TyU8 => u8::BITS as u64, + ast::TyU16 => u16::BITS as u64, + ast::TyU32 => u32::BITS as u64, + ast::TyU64 => u64::BITS as u64 + } + } + + fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp, + l: &ast::Expr, r: &ast::Expr) -> bool { + let (lit, expr, swap) = match (&l.node, &r.node) { + (&ast::ExprLit(_), _) => (l, r, true), + (_, &ast::ExprLit(_)) => (r, l, false), + _ => return true + }; + // Normalize the binop so that the literal is always on the RHS in + // the comparison + let norm_binop = if swap { + rev_binop(binop) + } else { + binop + }; + match ty::expr_ty(tcx, expr).sty { + ty::ty_int(int_ty) => { + let (min, max) = int_ty_range(int_ty); + let lit_val: i64 = match lit.node { + ast::ExprLit(ref li) => match li.node { + ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | + ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64, + ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) | + ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64), + _ => return true + }, + _ => panic!() + }; + is_valid(norm_binop, lit_val, min, max) + } + ty::ty_uint(uint_ty) => { + let (min, max): (u64, u64) = uint_ty_range(uint_ty); + let lit_val: u64 = match lit.node { + ast::ExprLit(ref li) => match li.node { + ast::LitInt(v, _) => v, + _ => return true + }, + _ => panic!() + }; + is_valid(norm_binop, lit_val, min, max) + } + _ => true + } + } + + fn is_comparison(binop: ast::BinOp) -> bool { + match binop.node { + ast::BiEq | ast::BiLt | ast::BiLe | + ast::BiNe | ast::BiGe | ast::BiGt => true, + _ => false + } + } + } +} + +declare_lint! { + IMPROPER_CTYPES, + Warn, + "proper use of libc types in foreign modules" +} + +struct ImproperCTypesVisitor<'a, 'tcx: 'a> { + cx: &'a Context<'a, 'tcx> +} + +impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { + fn check_def(&mut self, sp: Span, id: ast::NodeId) { + match self.cx.tcx.def_map.borrow().get(&id).unwrap().full_def() { + def::DefPrimTy(ast::TyInt(ast::TyIs)) => { + self.cx.span_lint(IMPROPER_CTYPES, sp, + "found rust type `isize` in foreign module, while \ + libc::c_int or libc::c_long should be used"); + } + def::DefPrimTy(ast::TyUint(ast::TyUs)) => { + self.cx.span_lint(IMPROPER_CTYPES, sp, + "found rust type `usize` in foreign module, while \ + libc::c_uint or libc::c_ulong should be used"); + } + def::DefTy(..) => { + let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) { + Some(&t) => t, + None => panic!("ast_ty_to_ty_cache was incomplete after typeck!") + }; + + if !ty::is_ffi_safe(self.cx.tcx, tty) { + self.cx.span_lint(IMPROPER_CTYPES, sp, + "found type without foreign-function-safe \ + representation annotation in foreign module, consider \ + adding a #[repr(...)] attribute to the type"); + } + } + _ => () + } + } +} + +impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { + fn visit_ty(&mut self, ty: &ast::Ty) { + if let ast::TyPath(..) = ty.node { + self.check_def(ty.span, ty.id); + } + visit::walk_ty(self, ty); + } +} + +#[derive(Copy, Clone)] +pub struct ImproperCTypes; + +impl LintPass for ImproperCTypes { + fn get_lints(&self) -> LintArray { + lint_array!(IMPROPER_CTYPES) + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + fn check_ty(cx: &Context, ty: &ast::Ty) { + let mut vis = ImproperCTypesVisitor { cx: cx }; + vis.visit_ty(ty); + } + + fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) { + for input in &decl.inputs { + check_ty(cx, &*input.ty); + } + if let ast::Return(ref ret_ty) = decl.output { + check_ty(cx, &**ret_ty); + } + } + + match it.node { + ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => { + for ni in &nmod.items { + match ni.node { + ast::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl), + ast::ForeignItemStatic(ref t, _) => check_ty(cx, &**t) + } + } + } + _ => (), + } + } +} + +declare_lint! { + BOX_POINTERS, + Allow, + "use of owned (Box type) heap memory" +} + +#[derive(Copy, Clone)] +pub struct BoxPointers; + +impl BoxPointers { + fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>, + span: Span, ty: Ty<'tcx>) { + let mut n_uniq: usize = 0; + ty::fold_ty(cx.tcx, ty, |t| { + match t.sty { + ty::ty_uniq(_) => { + n_uniq += 1; + } + _ => () + }; + t + }); + + if n_uniq > 0 { + let s = ty_to_string(cx.tcx, ty); + let m = format!("type uses owned (Box type) pointers: {}", s); + cx.span_lint(BOX_POINTERS, span, &m[..]); + } + } +} + +impl LintPass for BoxPointers { + fn get_lints(&self) -> LintArray { + lint_array!(BOX_POINTERS) + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + match it.node { + ast::ItemFn(..) | + ast::ItemTy(..) | + ast::ItemEnum(..) | + ast::ItemStruct(..) => + self.check_heap_type(cx, it.span, + ty::node_id_to_type(cx.tcx, it.id)), + _ => () + } + + // If it's a struct, we also have to check the fields' types + match it.node { + ast::ItemStruct(ref struct_def, _) => { + for struct_field in &struct_def.fields { + self.check_heap_type(cx, struct_field.span, + ty::node_id_to_type(cx.tcx, struct_field.node.id)); + } + } + _ => () + } + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + let ty = ty::expr_ty(cx.tcx, e); + self.check_heap_type(cx, e.span, ty); + } +} + +declare_lint! { + RAW_POINTER_DERIVE, + Warn, + "uses of #[derive] with raw pointers are rarely correct" +} + +struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { + cx: &'a Context<'a, 'tcx> +} + +impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { + fn visit_ty(&mut self, ty: &ast::Ty) { + const MSG: &'static str = "use of `#[derive]` with a raw pointer"; + if let ast::TyPtr(..) = ty.node { + self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG); + } + visit::walk_ty(self, ty); + } + // explicit override to a no-op to reduce code bloat + fn visit_expr(&mut self, _: &ast::Expr) {} + fn visit_block(&mut self, _: &ast::Block) {} +} + +pub struct RawPointerDerive { + checked_raw_pointers: NodeSet, +} + +impl RawPointerDerive { + pub fn new() -> RawPointerDerive { + RawPointerDerive { + checked_raw_pointers: NodeSet(), + } + } +} + +impl LintPass for RawPointerDerive { + fn get_lints(&self) -> LintArray { + lint_array!(RAW_POINTER_DERIVE) + } + + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + if !attr::contains_name(&item.attrs, "automatically_derived") { + return; + } + let did = match item.node { + ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { + // Deriving the Copy trait does not cause a warning + if let &Some(ref trait_ref) = t_ref_opt { + let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref); + if Some(def_id) == cx.tcx.lang_items.copy_trait() { + return; + } + } + + match ty::node_id_to_type(cx.tcx, item.id).sty { + ty::ty_enum(did, _) => did, + ty::ty_struct(did, _) => did, + _ => return, + } + } + _ => return, + }; + if !ast_util::is_local(did) { + return; + } + let item = match cx.tcx.map.find(did.node) { + Some(ast_map::NodeItem(item)) => item, + _ => return, + }; + if !self.checked_raw_pointers.insert(item.id) { + return; + } + match item.node { + ast::ItemStruct(..) | ast::ItemEnum(..) => { + let mut visitor = RawPtrDeriveVisitor { cx: cx }; + visit::walk_item(&mut visitor, &*item); + } + _ => {} + } + } +} + +declare_lint! { + UNUSED_ATTRIBUTES, + Warn, + "detects attributes that were not used by the compiler" +} + +#[derive(Copy, Clone)] +pub struct UnusedAttributes; + +impl LintPass for UnusedAttributes { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_ATTRIBUTES) + } + + fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) { + // Note that check_name() marks the attribute as used if it matches. + for &(ref name, ty) in KNOWN_ATTRIBUTES { + match ty { + AttributeType::Whitelisted + | AttributeType::Gated(_, _) if attr.check_name(name) => { + break; + }, + _ => () + } + } + + if !attr::is_used(attr) { + cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); + if KNOWN_ATTRIBUTES.contains(&(&attr.name(), AttributeType::CrateLevel)) { + let msg = match attr.node.style { + ast::AttrOuter => "crate-level attribute should be an inner \ + attribute: add an exclamation mark: #![foo]", + ast::AttrInner => "crate-level attribute should be in the \ + root module", + }; + cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg); + } + } + } +} + +declare_lint! { + pub PATH_STATEMENTS, + Warn, + "path statements with no effect" +} + +#[derive(Copy, Clone)] +pub struct PathStatements; + +impl LintPass for PathStatements { + fn get_lints(&self) -> LintArray { + lint_array!(PATH_STATEMENTS) + } + + fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { + match s.node { + ast::StmtSemi(ref expr, _) => { + match expr.node { + ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span, + "path statement with no effect"), + _ => () + } + } + _ => () + } + } +} + +declare_lint! { + pub UNUSED_MUST_USE, + Warn, + "unused result of a type flagged as #[must_use]" +} + +declare_lint! { + pub UNUSED_RESULTS, + Allow, + "unused result of an expression in a statement" +} + +#[derive(Copy, Clone)] +pub struct UnusedResults; + +impl LintPass for UnusedResults { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) + } + + fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { + let expr = match s.node { + ast::StmtSemi(ref expr, _) => &**expr, + _ => return + }; + + if let ast::ExprRet(..) = expr.node { + return; + } + + let t = ty::expr_ty(cx.tcx, expr); + let warned = match t.sty { + ty::ty_tup(ref tys) if tys.is_empty() => return, + ty::ty_bool => return, + ty::ty_struct(did, _) | + ty::ty_enum(did, _) => { + if ast_util::is_local(did) { + if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) { + check_must_use(cx, &it.attrs, s.span) + } else { + false + } + } else { + let attrs = csearch::get_item_attrs(&cx.sess().cstore, did); + check_must_use(cx, &attrs[..], s.span) + } + } + _ => false, + }; + if !warned { + cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); + } + + fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool { + for attr in attrs { + if attr.check_name("must_use") { + let mut msg = "unused result which must be used".to_string(); + // check for #[must_use="..."] + match attr.value_str() { + None => {} + Some(s) => { + msg.push_str(": "); + msg.push_str(&s); + } + } + cx.span_lint(UNUSED_MUST_USE, sp, &msg); + return true; + } + } + false + } + } +} + +declare_lint! { + pub NON_CAMEL_CASE_TYPES, + Warn, + "types, variants, traits and type parameters should have camel case names" +} + +#[derive(Copy, Clone)] +pub struct NonCamelCaseTypes; + +impl NonCamelCaseTypes { + fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + fn is_camel_case(ident: ast::Ident) -> bool { + let ident = token::get_ident(ident); + if ident.is_empty() { + return true; + } + let ident = ident.trim_matches('_'); + + // start with a non-lowercase letter rather than non-uppercase + // ones (some scripts don't have a concept of upper/lowercase) + ident.len() > 0 && !ident.char_at(0).is_lowercase() && !ident.contains('_') + } + + fn to_camel_case(s: &str) -> String { + s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)| + if i == 0 { + c.to_uppercase().collect::() + } else { + c.to_lowercase().collect() + } + )).collect::>().concat() + } + + let s = token::get_ident(ident); + + if !is_camel_case(ident) { + let c = to_camel_case(&s); + let m = if c.is_empty() { + format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s) + } else { + format!("{} `{}` should have a camel case name such as `{}`", sort, s, c) + }; + cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]); + } + } +} + +impl LintPass for NonCamelCaseTypes { + fn get_lints(&self) -> LintArray { + lint_array!(NON_CAMEL_CASE_TYPES) + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + let has_extern_repr = it.attrs.iter().any(|attr| { + attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter() + .any(|r| r == &attr::ReprExtern) + }); + if has_extern_repr { + return; + } + + match it.node { + ast::ItemTy(..) | ast::ItemStruct(..) => { + self.check_case(cx, "type", it.ident, it.span) + } + ast::ItemTrait(..) => { + self.check_case(cx, "trait", it.ident, it.span) + } + ast::ItemEnum(ref enum_definition, _) => { + if has_extern_repr { + return; + } + self.check_case(cx, "type", it.ident, it.span); + for variant in &enum_definition.variants { + self.check_case(cx, "variant", variant.node.name, variant.span); + } + } + _ => () + } + } + + fn check_generics(&mut self, cx: &Context, it: &ast::Generics) { + for gen in &*it.ty_params { + self.check_case(cx, "type parameter", gen.ident, gen.span); + } + } +} + +#[derive(PartialEq)] +enum MethodContext { + TraitDefaultImpl, + TraitImpl, + PlainImpl +} + +fn method_context(cx: &Context, id: ast::NodeId, span: Span) -> MethodContext { + match cx.tcx.impl_or_trait_items.borrow().get(&local_def(id)) { + None => cx.sess().span_bug(span, "missing method descriptor?!"), + Some(item) => match item.container() { + ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, + ty::ImplContainer(cid) => { + match ty::impl_trait_ref(cx.tcx, cid) { + Some(_) => MethodContext::TraitImpl, + None => MethodContext::PlainImpl + } + } + } + } +} + +declare_lint! { + pub NON_SNAKE_CASE, + Warn, + "methods, functions, lifetime parameters and modules should have snake case names" +} + +#[derive(Copy, Clone)] +pub struct NonSnakeCase; + +impl NonSnakeCase { + fn to_snake_case(mut str: &str) -> String { + let mut words = vec![]; + // Preserve leading underscores + str = str.trim_left_matches(|c: char| { + if c == '_' { + words.push(String::new()); + true + } else { + false + } + }); + for s in str.split('_') { + let mut last_upper = false; + let mut buf = String::new(); + if s.is_empty() { + continue; + } + for ch in s.chars() { + if !buf.is_empty() && buf != "'" + && ch.is_uppercase() + && !last_upper { + words.push(buf); + buf = String::new(); + } + last_upper = ch.is_uppercase(); + buf.extend(ch.to_lowercase()); + } + words.push(buf); + } + words.connect("_") + } + + fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + fn is_snake_case(ident: ast::Ident) -> bool { + let ident = token::get_ident(ident); + if ident.is_empty() { + return true; + } + let ident = ident.trim_left_matches('\''); + let ident = ident.trim_matches('_'); + + let mut allow_underscore = true; + ident.chars().all(|c| { + allow_underscore = match c { + '_' if !allow_underscore => return false, + '_' => false, + c if !c.is_uppercase() => true, + _ => return false, + }; + true + }) + } + + let s = token::get_ident(ident); + + if !is_snake_case(ident) { + let sc = NonSnakeCase::to_snake_case(&s); + if sc != &s[..] { + cx.span_lint(NON_SNAKE_CASE, span, + &*format!("{} `{}` should have a snake case name such as `{}`", + sort, s, sc)); + } else { + cx.span_lint(NON_SNAKE_CASE, span, + &*format!("{} `{}` should have a snake case name", + sort, s)); + } + } + } +} + +impl LintPass for NonSnakeCase { + fn get_lints(&self) -> LintArray { + lint_array!(NON_SNAKE_CASE) + } + + fn check_fn(&mut self, cx: &Context, + fk: visit::FnKind, _: &ast::FnDecl, + _: &ast::Block, span: Span, id: ast::NodeId) { + match fk { + visit::FkMethod(ident, _) => match method_context(cx, id, span) { + MethodContext::PlainImpl => { + self.check_snake_case(cx, "method", ident, span) + }, + MethodContext::TraitDefaultImpl => { + self.check_snake_case(cx, "trait method", ident, span) + }, + _ => (), + }, + visit::FkItemFn(ident, _, _, _) => { + self.check_snake_case(cx, "function", ident, span) + }, + _ => (), + } + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + if let ast::ItemMod(_) = it.node { + self.check_snake_case(cx, "module", it.ident, it.span); + } + } + + fn check_trait_item(&mut self, cx: &Context, trait_item: &ast::TraitItem) { + if let ast::MethodTraitItem(_, None) = trait_item.node { + self.check_snake_case(cx, "trait method", trait_item.ident, trait_item.span); + } + } + + fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) { + self.check_snake_case(cx, "lifetime", t.lifetime.name.ident(), t.lifetime.span); + } + + fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { + if let &ast::PatIdent(_, ref path1, _) = &p.node { + let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); + if let Some(def::DefLocal(_)) = def { + self.check_snake_case(cx, "variable", path1.node, p.span); + } + } + } + + fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef, + _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { + for sf in &s.fields { + if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node { + self.check_snake_case(cx, "structure field", ident, sf.span); + } + } + } +} + +declare_lint! { + pub NON_UPPER_CASE_GLOBALS, + Warn, + "static constants should have uppercase identifiers" +} + +#[derive(Copy, Clone)] +pub struct NonUpperCaseGlobals; + +impl NonUpperCaseGlobals { + fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + let s = token::get_ident(ident); + + if s.chars().any(|c| c.is_lowercase()) { + let uc = NonSnakeCase::to_snake_case(&s).to_uppercase(); + if uc != &s[..] { + cx.span_lint(NON_UPPER_CASE_GLOBALS, span, + &format!("{} `{}` should have an upper case name such as `{}`", + sort, s, uc)); + } else { + cx.span_lint(NON_UPPER_CASE_GLOBALS, span, + &format!("{} `{}` should have an upper case name", + sort, s)); + } + } + } +} + +impl LintPass for NonUpperCaseGlobals { + fn get_lints(&self) -> LintArray { + lint_array!(NON_UPPER_CASE_GLOBALS) + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + match it.node { + // only check static constants + ast::ItemStatic(_, ast::MutImmutable, _) => { + NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span); + } + ast::ItemConst(..) => { + NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.span); + } + _ => {} + } + } + + fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { + // Lint for constants that look like binding identifiers (#7526) + match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) { + (&ast::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => { + NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", + path1.node, p.span); + } + _ => {} + } + } +} + +declare_lint! { + UNUSED_PARENS, + Warn, + "`if`, `match`, `while` and `return` do not need parentheses" +} + +#[derive(Copy, Clone)] +pub struct UnusedParens; + +impl UnusedParens { + fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str, + struct_lit_needs_parens: bool) { + if let ast::ExprParen(ref inner) = value.node { + let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); + if !necessary { + cx.span_lint(UNUSED_PARENS, value.span, + &format!("unnecessary parentheses around {}", msg)) + } + } + + /// Expressions that syntactically contain an "exterior" struct + /// literal i.e. not surrounded by any parens or other + /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo + /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X { + /// y: 1 }) == foo` does not. + fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { + match value.node { + ast::ExprStruct(..) => true, + + ast::ExprAssign(ref lhs, ref rhs) | + ast::ExprAssignOp(_, ref lhs, ref rhs) | + ast::ExprBinary(_, ref lhs, ref rhs) => { + // X { y: 1 } + X { y: 2 } + contains_exterior_struct_lit(&**lhs) || + contains_exterior_struct_lit(&**rhs) + } + ast::ExprUnary(_, ref x) | + ast::ExprCast(ref x, _) | + ast::ExprField(ref x, _) | + ast::ExprTupField(ref x, _) | + ast::ExprIndex(ref x, _) => { + // &X { y: 1 }, X { y: 1 }.y + contains_exterior_struct_lit(&**x) + } + + ast::ExprMethodCall(_, _, ref exprs) => { + // X { y: 1 }.bar(...) + contains_exterior_struct_lit(&*exprs[0]) + } + + _ => false + } + } + } +} + +impl LintPass for UnusedParens { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_PARENS) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + let (value, msg, struct_lit_needs_parens) = match e.node { + ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), + ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), + ast::ExprMatch(ref head, _, source) => match source { + ast::MatchSource::Normal => (head, "`match` head expression", true), + ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), + ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), + ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true), + }, + ast::ExprRet(Some(ref value)) => (value, "`return` value", false), + ast::ExprAssign(_, ref value) => (value, "assigned value", false), + ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false), + _ => return + }; + self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); + } + + fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { + let (value, msg) = match s.node { + ast::StmtDecl(ref decl, _) => match decl.node { + ast::DeclLocal(ref local) => match local.init { + Some(ref value) => (value, "assigned value"), + None => return + }, + _ => return + }, + _ => return + }; + self.check_unused_parens_core(cx, &**value, msg, false); + } +} + +declare_lint! { + UNUSED_IMPORT_BRACES, + Allow, + "unnecessary braces around an imported item" +} + +#[derive(Copy, Clone)] +pub struct UnusedImportBraces; + +impl LintPass for UnusedImportBraces { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_IMPORT_BRACES) + } + + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + if let ast::ItemUse(ref view_path) = item.node { + if let ast::ViewPathList(_, ref items) = view_path.node { + if items.len() == 1 { + if let ast::PathListIdent {ref name, ..} = items[0].node { + let m = format!("braces around {} is unnecessary", + &token::get_ident(*name)); + cx.span_lint(UNUSED_IMPORT_BRACES, item.span, + &m[..]); + } + } + } + } + } +} + +declare_lint! { + NON_SHORTHAND_FIELD_PATTERNS, + Warn, + "using `Struct { x: x }` instead of `Struct { x }`" +} + +#[derive(Copy, Clone)] +pub struct NonShorthandFieldPatterns; + +impl LintPass for NonShorthandFieldPatterns { + fn get_lints(&self) -> LintArray { + lint_array!(NON_SHORTHAND_FIELD_PATTERNS) + } + + fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { + let def_map = cx.tcx.def_map.borrow(); + if let ast::PatStruct(_, ref v, _) = pat.node { + let field_pats = v.iter().filter(|fieldpat| { + if fieldpat.node.is_shorthand { + return false; + } + let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def()); + def == Some(def::DefLocal(fieldpat.node.pat.id)) + }); + for fieldpat in field_pats { + if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node { + if ident.node.as_str() == fieldpat.node.ident.as_str() { + cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, + &format!("the `{}:` in this pattern is redundant and can \ + be removed", ident.node.as_str())) + } + } + } + } + } +} + +declare_lint! { + pub UNUSED_UNSAFE, + Warn, + "unnecessary use of an `unsafe` block" +} + +#[derive(Copy, Clone)] +pub struct UnusedUnsafe; + +impl LintPass for UnusedUnsafe { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_UNSAFE) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + if let ast::ExprBlock(ref blk) = e.node { + // Don't warn about generated blocks, that'll just pollute the output. + if blk.rules == ast::UnsafeBlock(ast::UserProvided) && + !cx.tcx.used_unsafe.borrow().contains(&blk.id) { + cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block"); + } + } + } +} + +declare_lint! { + UNSAFE_CODE, + Allow, + "usage of `unsafe` code" +} + +#[derive(Copy, Clone)] +pub struct UnsafeCode; + +impl LintPass for UnsafeCode { + fn get_lints(&self) -> LintArray { + lint_array!(UNSAFE_CODE) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + if let ast::ExprBlock(ref blk) = e.node { + // Don't warn about generated blocks, that'll just pollute the output. + if blk.rules == ast::UnsafeBlock(ast::UserProvided) { + cx.span_lint(UNSAFE_CODE, blk.span, "usage of an `unsafe` block"); + } + } + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + match it.node { + ast::ItemTrait(ast::Unsafety::Unsafe, _, _, _) => + cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"), + + ast::ItemImpl(ast::Unsafety::Unsafe, _, _, _, _, _) => + cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"), + + _ => return, + } + } + + fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl, + _: &ast::Block, span: Span, _: ast::NodeId) { + match fk { + visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _) => + cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"), + + visit::FkMethod(_, sig) => { + if sig.unsafety == ast::Unsafety::Unsafe { + cx.span_lint(UNSAFE_CODE, span, "implementation of an `unsafe` method") + } + }, + + _ => (), + } + } + + fn check_trait_item(&mut self, cx: &Context, trait_item: &ast::TraitItem) { + if let ast::MethodTraitItem(ref sig, None) = trait_item.node { + if sig.unsafety == ast::Unsafety::Unsafe { + cx.span_lint(UNSAFE_CODE, trait_item.span, + "declaration of an `unsafe` method") + } + } + } +} + +declare_lint! { + pub UNUSED_MUT, + Warn, + "detect mut variables which don't need to be mutable" +} + +#[derive(Copy, Clone)] +pub struct UnusedMut; + +impl UnusedMut { + fn check_unused_mut_pat(&self, cx: &Context, pats: &[P]) { + // collect all mutable pattern and group their NodeIDs by their Identifier to + // avoid false warnings in match arms with multiple patterns + + let mut mutables = FnvHashMap(); + for p in pats { + pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| { + let ident = path1.node; + if let ast::BindByValue(ast::MutMutable) = mode { + if !token::get_ident(ident).starts_with("_") { + match mutables.entry(ident.name.usize()) { + Vacant(entry) => { entry.insert(vec![id]); }, + Occupied(mut entry) => { entry.get_mut().push(id); }, + } + } + } + }); + } + + let used_mutables = cx.tcx.used_mut_nodes.borrow(); + for (_, v) in &mutables { + if !v.iter().any(|e| used_mutables.contains(e)) { + cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]), + "variable does not need to be mutable"); + } + } + } +} + +impl LintPass for UnusedMut { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_MUT) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + if let ast::ExprMatch(_, ref arms, _) = e.node { + for a in arms { + self.check_unused_mut_pat(cx, &a.pats) + } + } + } + + fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { + if let ast::StmtDecl(ref d, _) = s.node { + if let ast::DeclLocal(ref l) = d.node { + self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); + } + } + } + + fn check_fn(&mut self, cx: &Context, + _: visit::FnKind, decl: &ast::FnDecl, + _: &ast::Block, _: Span, _: ast::NodeId) { + for a in &decl.inputs { + self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat)); + } + } +} + +declare_lint! { + UNUSED_ALLOCATION, + Warn, + "detects unnecessary allocations that can be eliminated" +} + +#[derive(Copy, Clone)] +pub struct UnusedAllocation; + +impl LintPass for UnusedAllocation { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_ALLOCATION) + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + match e.node { + ast::ExprUnary(ast::UnUniq, _) => (), + _ => return + } + + if let Some(adjustment) = cx.tcx.adjustments.borrow().get(&e.id) { + if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment { + match autoref { + &Some(ty::AutoPtr(_, ast::MutImmutable, None)) => { + cx.span_lint(UNUSED_ALLOCATION, e.span, + "unnecessary allocation, use & instead"); + } + &Some(ty::AutoPtr(_, ast::MutMutable, None)) => { + cx.span_lint(UNUSED_ALLOCATION, e.span, + "unnecessary allocation, use &mut instead"); + } + _ => () + } + } + } + } +} + +declare_lint! { + MISSING_DOCS, + Allow, + "detects missing documentation for public members" +} + +pub struct MissingDoc { + /// Stack of IDs of struct definitions. + struct_def_stack: Vec, + + /// True if inside variant definition + in_variant: bool, + + /// Stack of whether #[doc(hidden)] is set + /// at each level which has lint attributes. + doc_hidden_stack: Vec, + + /// Private traits or trait items that leaked through. Don't check their methods. + private_traits: HashSet, +} + +impl MissingDoc { + pub fn new() -> MissingDoc { + MissingDoc { + struct_def_stack: vec!(), + in_variant: false, + doc_hidden_stack: vec!(false), + private_traits: HashSet::new(), + } + } + + fn doc_hidden(&self) -> bool { + *self.doc_hidden_stack.last().expect("empty doc_hidden_stack") + } + + fn check_missing_docs_attrs(&self, + cx: &Context, + id: Option, + attrs: &[ast::Attribute], + sp: Span, + desc: &'static str) { + // If we're building a test harness, then warning about + // documentation is probably not really relevant right now. + if cx.sess().opts.test { + return; + } + + // `#[doc(hidden)]` disables missing_docs check. + if self.doc_hidden() { + return; + } + + // Only check publicly-visible items, using the result from the privacy pass. + // It's an option so the crate root can also use this function (it doesn't + // have a NodeId). + if let Some(ref id) = id { + if !cx.exported_items.contains(id) { + return; + } + } + + let has_doc = attrs.iter().any(|a| { + match a.node.value.node { + ast::MetaNameValue(ref name, _) if *name == "doc" => true, + _ => false + } + }); + if !has_doc { + cx.span_lint(MISSING_DOCS, sp, + &format!("missing documentation for {}", desc)); + } + } +} + +impl LintPass for MissingDoc { + fn get_lints(&self) -> LintArray { + lint_array!(MISSING_DOCS) + } + + fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) { + let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { + attr.check_name("doc") && match attr.meta_item_list() { + None => false, + Some(l) => attr::contains_name(&l[..], "hidden"), + } + }); + self.doc_hidden_stack.push(doc_hidden); + } + + fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { + self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); + } + + fn check_struct_def(&mut self, _: &Context, _: &ast::StructDef, + _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { + self.struct_def_stack.push(id); + } + + fn check_struct_def_post(&mut self, _: &Context, _: &ast::StructDef, + _: ast::Ident, _: &ast::Generics, id: ast::NodeId) { + let popped = self.struct_def_stack.pop().expect("empty struct_def_stack"); + assert!(popped == id); + } + + fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) { + self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + let desc = match it.node { + ast::ItemFn(..) => "a function", + ast::ItemMod(..) => "a module", + ast::ItemEnum(..) => "an enum", + ast::ItemStruct(..) => "a struct", + ast::ItemTrait(_, _, _, ref items) => { + // Issue #11592, traits are always considered exported, even when private. + if it.vis == ast::Visibility::Inherited { + self.private_traits.insert(it.id); + for itm in items { + self.private_traits.insert(itm.id); + } + return + } + "a trait" + }, + ast::ItemTy(..) => "a type alias", + ast::ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) => { + // If the trait is private, add the impl items to private_traits so they don't get + // reported for missing docs. + let real_trait = ty::trait_ref_to_def_id(cx.tcx, trait_ref); + match cx.tcx.map.find(real_trait.node) { + Some(ast_map::NodeItem(item)) => if item.vis == ast::Visibility::Inherited { + for itm in impl_items { + self.private_traits.insert(itm.id); + } + }, + _ => { } + } + return + }, + _ => return + }; + + self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc); + } + + fn check_trait_item(&mut self, cx: &Context, trait_item: &ast::TraitItem) { + if self.private_traits.contains(&trait_item.id) { return } + + let desc = match trait_item.node { + ast::MethodTraitItem(..) => "a trait method", + ast::TypeTraitItem(..) => "an associated type" + }; + + self.check_missing_docs_attrs(cx, Some(trait_item.id), + &trait_item.attrs, + trait_item.span, desc); + } + + fn check_impl_item(&mut self, cx: &Context, impl_item: &ast::ImplItem) { + // If the method is an impl for a trait, don't doc. + if method_context(cx, impl_item.id, impl_item.span) == MethodContext::TraitImpl { + return; + } + + let desc = match impl_item.node { + ast::MethodImplItem(..) => "a method", + ast::TypeImplItem(_) => "an associated type", + ast::MacImplItem(_) => "an impl item macro" + }; + self.check_missing_docs_attrs(cx, Some(impl_item.id), + &impl_item.attrs, + impl_item.span, desc); + } + + fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) { + if let ast::NamedField(_, vis) = sf.node.kind { + if vis == ast::Public || self.in_variant { + let cur_struct_def = *self.struct_def_stack.last() + .expect("empty struct_def_stack"); + self.check_missing_docs_attrs(cx, Some(cur_struct_def), + &sf.node.attrs, sf.span, + "a struct field") + } + } + } + + fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) { + self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, v.span, "a variant"); + assert!(!self.in_variant); + self.in_variant = true; + } + + fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { + assert!(self.in_variant); + self.in_variant = false; + } +} + +declare_lint! { + pub MISSING_COPY_IMPLEMENTATIONS, + Allow, + "detects potentially-forgotten implementations of `Copy`" +} + +#[derive(Copy, Clone)] +pub struct MissingCopyImplementations; + +impl LintPass for MissingCopyImplementations { + fn get_lints(&self) -> LintArray { + lint_array!(MISSING_COPY_IMPLEMENTATIONS) + } + + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + if !cx.exported_items.contains(&item.id) { + return; + } + if cx.tcx.destructor_for_type.borrow().contains_key(&local_def(item.id)) { + return; + } + let ty = match item.node { + ast::ItemStruct(_, ref ast_generics) => { + if ast_generics.is_parameterized() { + return; + } + ty::mk_struct(cx.tcx, local_def(item.id), + cx.tcx.mk_substs(Substs::empty())) + } + ast::ItemEnum(_, ref ast_generics) => { + if ast_generics.is_parameterized() { + return; + } + ty::mk_enum(cx.tcx, local_def(item.id), + cx.tcx.mk_substs(Substs::empty())) + } + _ => return, + }; + let parameter_environment = ty::empty_parameter_environment(cx.tcx); + if !ty::type_moves_by_default(¶meter_environment, item.span, ty) { + return; + } + if ty::can_type_implement_copy(¶meter_environment, item.span, ty).is_ok() { + cx.span_lint(MISSING_COPY_IMPLEMENTATIONS, + item.span, + "type could implement `Copy`; consider adding `impl \ + Copy`") + } + } +} + +declare_lint! { + MISSING_DEBUG_IMPLEMENTATIONS, + Allow, + "detects missing implementations of fmt::Debug" +} + +pub struct MissingDebugImplementations { + impling_types: Option, +} + +impl MissingDebugImplementations { + pub fn new() -> MissingDebugImplementations { + MissingDebugImplementations { + impling_types: None, + } + } +} + +impl LintPass for MissingDebugImplementations { + fn get_lints(&self) -> LintArray { + lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) + } + + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + if !cx.exported_items.contains(&item.id) { + return; + } + + match item.node { + ast::ItemStruct(..) | ast::ItemEnum(..) => {}, + _ => return, + } + + let debug = match cx.tcx.lang_items.debug_trait() { + Some(debug) => debug, + None => return, + }; + + if self.impling_types.is_none() { + let impls = cx.tcx.trait_impls.borrow(); + let impls = match impls.get(&debug) { + Some(impls) => { + impls.borrow().iter() + .filter(|d| d.krate == ast::LOCAL_CRATE) + .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node))) + .map(|d| d.node) + .collect() + } + None => NodeSet(), + }; + self.impling_types = Some(impls); + debug!("{:?}", self.impling_types); + } + + if !self.impling_types.as_ref().unwrap().contains(&item.id) { + cx.span_lint(MISSING_DEBUG_IMPLEMENTATIONS, + item.span, + "type does not implement `fmt::Debug`; consider adding #[derive(Debug)] \ + or a manual implementation") + } + } +} + +declare_lint! { + DEPRECATED, + Warn, + "detects use of #[deprecated] items" +} + +/// Checks for use of items with `#[deprecated]` attributes +#[derive(Copy, Clone)] +pub struct Stability; + +impl Stability { + fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option) { + // Deprecated attributes apply in-crate and cross-crate. + let (lint, label) = match *stability { + Some(attr::Stability { deprecated_since: Some(_), .. }) => + (DEPRECATED, "deprecated"), + _ => return + }; + + output(cx, span, stability, lint, label); + + fn output(cx: &Context, span: Span, stability: &Option, + lint: &'static Lint, label: &'static str) { + let msg = match *stability { + Some(attr::Stability { reason: Some(ref s), .. }) => { + format!("use of {} item: {}", label, *s) + } + _ => format!("use of {} item", label) + }; + + cx.span_lint(lint, span, &msg[..]); + } + } +} + +impl LintPass for Stability { + fn get_lints(&self) -> LintArray { + lint_array!(DEPRECATED) + } + + fn check_item(&mut self, cx: &Context, item: &ast::Item) { + stability::check_item(cx.tcx, item, false, + &mut |id, sp, stab| self.lint(cx, id, sp, stab)); + } + + fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { + stability::check_expr(cx.tcx, e, + &mut |id, sp, stab| self.lint(cx, id, sp, stab)); + } + + fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) { + stability::check_path(cx.tcx, path, id, + &mut |id, sp, stab| self.lint(cx, id, sp, stab)); + } + + fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { + stability::check_pat(cx.tcx, pat, + &mut |id, sp, stab| self.lint(cx, id, sp, stab)) + } +} + +declare_lint! { + pub UNCONDITIONAL_RECURSION, + Warn, + "functions that cannot return without calling themselves" +} + +#[derive(Copy, Clone)] +pub struct UnconditionalRecursion; + + +impl LintPass for UnconditionalRecursion { + fn get_lints(&self) -> LintArray { + lint_array![UNCONDITIONAL_RECURSION] + } + + fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl, + blk: &ast::Block, sp: Span, id: ast::NodeId) { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] + + type F = for<'tcx> fn(&ty::ctxt<'tcx>, + ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool; + + let (name, checker) = match fn_kind { + visit::FkItemFn(name, _, _, _) => (name, id_refers_to_this_fn as F), + visit::FkMethod(name, _) => (name, id_refers_to_this_method as F), + // closures can't recur, so they don't matter. + visit::FkFnBlock => return + }; + + let impl_def_id = ty::impl_of_method(cx.tcx, local_def(id)) + .unwrap_or(local_def(ast::DUMMY_NODE_ID)); + assert!(ast_util::is_local(impl_def_id)); + let impl_node_id = impl_def_id.node; + + // Walk through this function (say `f`) looking to see if + // every possible path references itself, i.e. the function is + // called recursively unconditionally. This is done by trying + // to find a path from the entry node to the exit node that + // *doesn't* call `f` by traversing from the entry while + // pretending that calls of `f` are sinks (i.e. ignoring any + // exit edges from them). + // + // NB. this has an edge case with non-returning statements, + // like `loop {}` or `panic!()`: control flow never reaches + // the exit node through these, so one can have a function + // that never actually calls itselfs but is still picked up by + // this lint: + // + // fn f(cond: bool) { + // if !cond { panic!() } // could come from `assert!(cond)` + // f(false) + // } + // + // In general, functions of that form may be able to call + // itself a finite number of times and then diverge. The lint + // considers this to be an error for two reasons, (a) it is + // easier to implement, and (b) it seems rare to actually want + // to have behaviour like the above, rather than + // e.g. accidentally recurring after an assert. + + let cfg = cfg::CFG::new(cx.tcx, blk); + + let mut work_queue = vec![cfg.entry]; + let mut reached_exit_without_self_call = false; + let mut self_call_spans = vec![]; + let mut visited = BitSet::new(); + + while let Some(idx) = work_queue.pop() { + if idx == cfg.exit { + // found a path! + reached_exit_without_self_call = true; + break; + } + + let cfg_id = idx.node_id(); + if visited.contains(&cfg_id) { + // already done + continue; + } + visited.insert(cfg_id); + + let node_id = cfg.graph.node_data(idx).id(); + + // is this a recursive call? + if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) { + self_call_spans.push(cx.tcx.map.span(node_id)); + // this is a self call, so we shouldn't explore past + // this node in the CFG. + continue; + } + // add the successors of this node to explore the graph further. + cfg.graph.each_outgoing_edge(idx, |_, edge| { + let target_idx = edge.target(); + let target_cfg_id = target_idx.node_id(); + if !visited.contains(&target_cfg_id) { + work_queue.push(target_idx) + } + true + }); + } + + // Check the number of self calls because a function that + // doesn't return (e.g. calls a `-> !` function or `loop { /* + // no break */ }`) shouldn't be linted unless it actually + // recurs. + if !reached_exit_without_self_call && self_call_spans.len() > 0 { + cx.span_lint(UNCONDITIONAL_RECURSION, sp, + "function cannot return without recurring"); + + // FIXME #19668: these could be span_lint_note's instead of this manual guard. + if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow { + let sess = cx.sess(); + // offer some help to the programmer. + for call in &self_call_spans { + sess.span_note(*call, "recursive call site") + } + sess.fileline_help(sp, "a `loop` may express intention \ + better if this is on purpose") + } + } + + // all done + return; + + // Functions for identifying if the given NodeId `id` + // represents a call to the function `fn_id`/method + // `method_id`. + + fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>, + _: ast::NodeId, + fn_id: ast::NodeId, + _: ast::Ident, + id: ast::NodeId) -> bool { + tcx.def_map.borrow().get(&id) + .map_or(false, |def| def.def_id() == local_def(fn_id)) + } + + // check if the method call `id` refers to method `method_id` + // (with name `method_name` contained in impl `impl_id`). + fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>, + impl_id: ast::NodeId, + method_id: ast::NodeId, + method_name: ast::Ident, + id: ast::NodeId) -> bool { + let did = match tcx.method_map.borrow().get(&ty::MethodCall::expr(id)) { + None => return false, + Some(m) => match m.origin { + // There's no way to know if a method call via a + // vtable is recursion, so we assume it's not. + ty::MethodTraitObject(_) => return false, + + // This `did` refers directly to the method definition. + ty::MethodStatic(did) | ty::MethodStaticClosure(did) => did, + + // MethodTypeParam are methods from traits: + + // The `impl ... for ...` of this method call + // isn't known, e.g. it might be a default method + // in a trait, so we get the def-id of the trait + // method instead. + ty::MethodTypeParam( + ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => { + ty::trait_item(tcx, trait_ref.def_id, method_num).def_id() + } + + // The `impl` is known, so we check that with a + // special case: + ty::MethodTypeParam( + ty::MethodParam { impl_def_id: Some(impl_def_id), .. }) => { + + let name = match tcx.map.expect_expr(id).node { + ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node, + _ => tcx.sess.span_bug( + tcx.map.span(id), + "non-method call expr behaving like a method call?") + }; + // It matches if it comes from the same impl, + // and has the same method name. + return ast_util::is_local(impl_def_id) + && impl_def_id.node == impl_id + && method_name.name == name.name + } + } + }; + + ast_util::is_local(did) && did.node == method_id + } + } +} + +declare_lint! { + PLUGIN_AS_LIBRARY, + Warn, + "compiler plugin used as ordinary library in non-plugin crate" +} + +#[derive(Copy, Clone)] +pub struct PluginAsLibrary; + +impl LintPass for PluginAsLibrary { + fn get_lints(&self) -> LintArray { + lint_array![PLUGIN_AS_LIBRARY] + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + if cx.sess().plugin_registrar_fn.get().is_some() { + // We're compiling a plugin; it's fine to link other plugins. + return; + } + + match it.node { + ast::ItemExternCrate(..) => (), + _ => return, + }; + + let md = match cx.sess().cstore.find_extern_mod_stmt_cnum(it.id) { + Some(cnum) => cx.sess().cstore.get_crate_data(cnum), + None => { + // Probably means we aren't linking the crate for some reason. + // + // Not sure if / when this could happen. + return; + } + }; + + if decoder::get_plugin_registrar_fn(md.data()).is_some() { + cx.span_lint(PLUGIN_AS_LIBRARY, it.span, + "compiler plugin used as an ordinary library"); + } + } +} + +declare_lint! { + PRIVATE_NO_MANGLE_FNS, + Warn, + "functions marked #[no_mangle] should be exported" +} + +declare_lint! { + PRIVATE_NO_MANGLE_STATICS, + Warn, + "statics marked #[no_mangle] should be exported" +} + +declare_lint! { + NO_MANGLE_CONST_ITEMS, + Deny, + "const items will not have their symbols exported" +} + +#[derive(Copy, Clone)] +pub struct InvalidNoMangleItems; + +impl LintPass for InvalidNoMangleItems { + fn get_lints(&self) -> LintArray { + lint_array!(PRIVATE_NO_MANGLE_FNS, + PRIVATE_NO_MANGLE_STATICS, + NO_MANGLE_CONST_ITEMS) + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + match it.node { + ast::ItemFn(..) => { + if attr::contains_name(&it.attrs, "no_mangle") && + !cx.exported_items.contains(&it.id) { + let msg = format!("function {} is marked #[no_mangle], but not exported", + it.ident); + cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg); + } + }, + ast::ItemStatic(..) => { + if attr::contains_name(&it.attrs, "no_mangle") && + !cx.exported_items.contains(&it.id) { + let msg = format!("static {} is marked #[no_mangle], but not exported", + it.ident); + cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg); + } + }, + ast::ItemConst(..) => { + if attr::contains_name(&it.attrs, "no_mangle") { + // Const items do not refer to a particular location in memory, and therefore + // don't have anything to attach a symbol to + let msg = "const items should never be #[no_mangle], consider instead using \ + `pub static`"; + cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg); + } + } + _ => {}, + } + } +} + +/// Forbids using the `#[feature(...)]` attribute +#[derive(Copy, Clone)] +pub struct UnstableFeatures; + +declare_lint! { + UNSTABLE_FEATURES, + Allow, + "enabling unstable features" +} + +impl LintPass for UnstableFeatures { + fn get_lints(&self) -> LintArray { + lint_array!(UNSTABLE_FEATURES) + } + fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) { + if attr::contains_name(&[attr.node.value.clone()], "feature") { + ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature"); + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs new file mode 100644 index 0000000000..34f7436d0c --- /dev/null +++ b/src/librustc_lint/lib.rs @@ -0,0 +1,136 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Lints in the Rust compiler. +//! +//! This currently only contains the definitions and implementations +//! of most of the lints that `rustc` supports directly, it does not +//! contain the infrastructure for defining/registering lints. That is +//! available in `rustc::lint` and `rustc::plugin` respectively. +//! +//! # Note +//! +//! This API is completely unstable and subject to change. + +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] +#![crate_name = "rustc_lint"] +#![unstable(feature = "rustc_private")] +#![staged_api] +#![crate_type = "dylib"] +#![crate_type = "rlib"] +#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "http://www.rust-lang.org/favicon.ico", + html_root_url = "http://doc.rust-lang.org/nightly/")] + +#![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(collections)] +#![feature(core)] +#![feature(quote)] +#![feature(rustc_diagnostic_macros)] +#![feature(rustc_private)] +#![feature(unsafe_destructor)] +#![feature(staged_api)] +#![feature(str_char)] +#![cfg_attr(test, feature(test))] + +extern crate syntax; +#[macro_use] +extern crate rustc; +#[macro_use] +extern crate log; + +pub use rustc::lint as lint; +pub use rustc::metadata as metadata; +pub use rustc::middle as middle; +pub use rustc::session as session; +pub use rustc::util as util; + +use session::Session; +use lint::LintId; + +mod builtin; + +/// Tell the `LintStore` about all the built-in lints (the ones +/// defined in this crate and the ones defined in +/// `rustc::lint::builtin`). +pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { + macro_rules! add_builtin { + ($sess:ident, $($name:ident),*,) => ( + {$( + store.register_pass($sess, false, box builtin::$name); + )*} + ) + } + + macro_rules! add_builtin_with_new { + ($sess:ident, $($name:ident),*,) => ( + {$( + store.register_pass($sess, false, box builtin::$name::new()); + )*} + ) + } + + macro_rules! add_lint_group { + ($sess:ident, $name:expr, $($lint:ident),*) => ( + store.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]); + ) + } + + add_builtin!(sess, + HardwiredLints, + WhileTrue, + ImproperCTypes, + BoxPointers, + UnusedAttributes, + PathStatements, + UnusedResults, + NonCamelCaseTypes, + NonSnakeCase, + NonUpperCaseGlobals, + UnusedParens, + UnusedImportBraces, + NonShorthandFieldPatterns, + UnusedUnsafe, + UnsafeCode, + UnusedMut, + UnusedAllocation, + MissingCopyImplementations, + UnstableFeatures, + Stability, + UnconditionalRecursion, + InvalidNoMangleItems, + PluginAsLibrary, + ); + + add_builtin_with_new!(sess, + TypeLimits, + RawPointerDerive, + MissingDoc, + MissingDebugImplementations, + ); + + add_lint_group!(sess, "bad_style", + NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS); + + add_lint_group!(sess, "unused", + UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE, + UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE, + UNUSED_UNSAFE, PATH_STATEMENTS); + + // We have one lint pass defined specially + store.register_pass(sess, false, box lint::GatherNodeLevels); + + // Insert temporary renamings for a one-time deprecation + store.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); + + store.register_renamed("unknown_features", "unused_features"); +} diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index 14a99026aa..647f4bc6a4 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -14,8 +14,8 @@ use libc; use ArchiveRef; use std::ffi::CString; -use std::mem; -use std::raw; +use std::slice; +use std::path::Path; pub struct ArchiveRO { ptr: ArchiveRef, @@ -29,14 +29,26 @@ impl ArchiveRO { /// If this archive is used with a mutable method, then an error will be /// raised. pub fn open(dst: &Path) -> Option { - unsafe { - let s = CString::new(dst.as_vec()).unwrap(); + return unsafe { + let s = path2cstr(dst); let ar = ::LLVMRustOpenArchive(s.as_ptr()); if ar.is_null() { None } else { Some(ArchiveRO { ptr: ar }) } + }; + + #[cfg(unix)] + fn path2cstr(p: &Path) -> CString { + use std::os::unix::prelude::*; + use std::ffi::OsStr; + let p: &OsStr = p.as_ref(); + CString::new(p.as_bytes()).unwrap() + } + #[cfg(windows)] + fn path2cstr(p: &Path) -> CString { + CString::new(p.to_str().unwrap()).unwrap() } } @@ -50,10 +62,7 @@ impl ArchiveRO { if ptr.is_null() { None } else { - Some(mem::transmute(raw::Slice { - data: ptr, - len: size as uint, - })) + Some(slice::from_raw_parts(ptr as *const u8, size as usize)) } } } diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index aca4d265bc..e6350ae44d 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -18,7 +18,7 @@ use std::ptr; use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef}; -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum OptimizationDiagnosticKind { OptimizationRemark, OptimizationMissed, @@ -38,7 +38,7 @@ impl OptimizationDiagnosticKind { } #[allow(raw_pointer_derive)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct OptimizationDiagnostic { pub kind: OptimizationDiagnosticKind, pub pass_name: *const c_char, @@ -69,14 +69,13 @@ impl OptimizationDiagnostic { } } +#[derive(Copy, Clone)] pub struct InlineAsmDiagnostic { pub cookie: c_uint, pub message: TwineRef, pub instruction: ValueRef, } -impl Copy for InlineAsmDiagnostic {} - impl InlineAsmDiagnostic { unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic { @@ -96,7 +95,7 @@ impl InlineAsmDiagnostic { } } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Diagnostic { Optimization(OptimizationDiagnostic), InlineAsm(InlineAsmDiagnostic), diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 09a187befb..9b0ae2e9ef 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(dead_code)] +#![allow(trivial_casts)] #![crate_name = "rustc_llvm"] #![unstable(feature = "rustc_private")] @@ -24,13 +27,9 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] -#![feature(int_uint)] #![feature(libc)] #![feature(link_args)] -#![feature(old_path)] #![feature(staged_api)] -#![feature(std_misc)] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -57,7 +56,7 @@ pub use self::Linkage::*; use std::ffi::CString; use std::cell::RefCell; -use std::{raw, mem}; +use std::{slice, mem}; use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char}; use libc::{c_longlong, c_ulonglong, c_void}; use debuginfo::{DIBuilderRef, DIDescriptor, @@ -75,9 +74,9 @@ pub type Bool = c_uint; pub const True: Bool = 1 as Bool; pub const False: Bool = 0 as Bool; -// Consts for the LLVM CallConv type, pre-cast to uint. +// Consts for the LLVM CallConv type, pre-cast to usize. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum CallConv { CCallConv = 0, FastCallConv = 8, @@ -87,7 +86,7 @@ pub enum CallConv { X86_64_Win64 = 79, } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Visibility { LLVMDefaultVisibility = 0, HiddenVisibility = 1, @@ -98,7 +97,7 @@ pub enum Visibility { // DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage. // LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either; // they've been removed in upstream LLVM commit r203866. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Linkage { ExternalLinkage = 0, AvailableExternallyLinkage = 1, @@ -114,7 +113,7 @@ pub enum Linkage { } #[repr(C)] -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum DiagnosticSeverity { Error, Warning, @@ -155,7 +154,7 @@ bitflags! { #[repr(u64)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum OtherAttribute { // The following are not really exposed in // the LLVM c api so instead to add these @@ -176,13 +175,13 @@ pub enum OtherAttribute { NonNullAttribute = 1 << 44, } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum SpecialAttribute { DereferenceableAttribute(u64) } #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AttributeSet { ReturnIndex = 0, FunctionIndex = !0 @@ -240,7 +239,7 @@ impl AttrHelper for SpecialAttribute { } pub struct AttrBuilder { - attrs: Vec<(uint, Box)> + attrs: Vec<(usize, Box)> } impl AttrBuilder { @@ -250,13 +249,13 @@ impl AttrBuilder { } } - pub fn arg<'a, T: AttrHelper + 'static>(&'a mut self, idx: uint, a: T) -> &'a mut AttrBuilder { + pub fn arg<'a, T: AttrHelper + 'static>(&'a mut self, idx: usize, a: T) -> &'a mut AttrBuilder { self.attrs.push((idx, box a as Box)); self } pub fn ret<'a, T: AttrHelper + 'static>(&'a mut self, a: T) -> &'a mut AttrBuilder { - self.attrs.push((ReturnIndex as uint, box a as Box)); + self.attrs.push((ReturnIndex as usize, box a as Box)); self } @@ -274,7 +273,7 @@ impl AttrBuilder { } // enum for the LLVM IntPredicate type -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum IntPredicate { IntEQ = 32, IntNE = 33, @@ -289,7 +288,7 @@ pub enum IntPredicate { } // enum for the LLVM RealPredicate type -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum RealPredicate { RealPredicateFalse = 0, RealOEQ = 1, @@ -311,7 +310,7 @@ pub enum RealPredicate { // The LLVM TypeKind type - must stay in sync with the def of // LLVMTypeKind in llvm/include/llvm-c/Core.h -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] pub enum TypeKind { Void = 0, @@ -333,7 +332,7 @@ pub enum TypeKind { } #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AtomicBinOp { AtomicXchg = 0, AtomicAdd = 1, @@ -349,7 +348,7 @@ pub enum AtomicBinOp { } #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AtomicOrdering { NotAtomic = 0, Unordered = 1, @@ -363,13 +362,13 @@ pub enum AtomicOrdering { // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h) #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum FileType { AssemblyFileType = 0, ObjectFileType = 1 } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum MetadataType { MD_dbg = 0, MD_tbaa = 1, @@ -386,13 +385,13 @@ pub enum MetadataType { } // Inline Asm Dialect -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AsmDialect { AD_ATT = 0, AD_Intel = 1 } -#[derive(Copy, PartialEq, Clone)] +#[derive(Copy, Clone, PartialEq)] #[repr(C)] pub enum CodeGenOptLevel { CodeGenLevelNone = 0, @@ -401,7 +400,7 @@ pub enum CodeGenOptLevel { CodeGenLevelAggressive = 3, } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] #[repr(C)] pub enum RelocMode { RelocDefault = 0, @@ -411,7 +410,7 @@ pub enum RelocMode { } #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum CodeGenModel { CodeModelDefault = 0, CodeModelJITDefault = 1, @@ -422,7 +421,7 @@ pub enum CodeGenModel { } #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum DiagnosticKind { DK_InlineAsm = 0, DK_StackSize, @@ -534,7 +533,7 @@ pub mod debuginfo { pub type DIEnumerator = DIDescriptor; pub type DITemplateTypeParameter = DIDescriptor; - #[derive(Copy)] + #[derive(Copy, Clone)] pub enum DIDescriptorFlags { FlagPrivate = 1 << 0, FlagProtected = 1 << 1, @@ -691,7 +690,7 @@ extern { -> ValueRef; pub fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; - /* only for int/vector */ + /* only for isize/vector */ pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; pub fn LLVMIsConstant(Val: ValueRef) -> Bool; pub fn LLVMIsNull(Val: ValueRef) -> Bool; @@ -1976,6 +1975,7 @@ extern { pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef; pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef; + pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; pub fn LLVMInitializeX86TargetInfo(); pub fn LLVMInitializeX86Target(); @@ -2165,7 +2165,7 @@ impl ObjectFile { pub fn new(llmb: MemoryBufferRef) -> Option { unsafe { let llof = LLVMCreateObjectFile(llmb); - if llof as int == 0 { + if llof as isize == 0 { // LLVMCreateObjectFile took ownership of llmb return None } @@ -2225,10 +2225,7 @@ type RustStringRepr = *mut RefCell>; pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef, ptr: *const c_char, size: size_t) { - let slice: &[u8] = mem::transmute(raw::Slice { - data: ptr as *const u8, - len: size as uint, - }); + let slice = slice::from_raw_parts(ptr as *const u8, size as usize); let sr: RustStringRepr = mem::transmute(sr); (*sr).borrow_mut().push_all(slice); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 5662a74a53..44ab096281 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_privacy"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -17,8 +19,6 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/")] -#![feature(core)] -#![feature(int_uint)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] @@ -38,17 +38,16 @@ use rustc::middle::def; use rustc::middle::privacy::ImportUse::*; use rustc::middle::privacy::LastPrivate::*; use rustc::middle::privacy::PrivateDep::*; -use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap}; -use rustc::middle::privacy::{ExternalExports}; +use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems}; use rustc::middle::ty::{MethodTypeParam, MethodStatic}; use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam}; use rustc::middle::ty::{MethodStaticClosure, MethodObject}; -use rustc::middle::ty::{MethodTraitObject}; +use rustc::middle::ty::MethodTraitObject; use rustc::middle::ty::{self, Ty}; use rustc::util::nodemap::{NodeMap, NodeSet}; use syntax::{ast, ast_map}; -use syntax::ast_util::{is_local, local_def, PostExpansionMethod}; +use syntax::ast_util::{is_local, local_def}; use syntax::codemap::Span; use syntax::parse::token; use syntax::visit::{self, Visitor}; @@ -92,17 +91,9 @@ impl<'v> Visitor<'v> for ParentVisitor { // method to the root. In this case, if the trait is private, then // parent all the methods to the trait to indicate that they're // private. - ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => { - for m in methods { - match *m { - ast::ProvidedMethod(ref m) => { - self.parents.insert(m.id, item.id); - } - ast::RequiredMethod(ref m) => { - self.parents.insert(m.id, item.id); - } - ast::TypeTraitItem(_) => {} - }; + ast::ItemTrait(_, _, _, ref trait_items) if item.vis != ast::Public => { + for trait_item in trait_items { + self.parents.insert(trait_item.id, item.id); } } @@ -209,7 +200,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { match item.node { // impls/extern blocks do not break the "public chain" because they // cannot have visibility qualifiers on them anyway - ast::ItemImpl(..) | ast::ItemForeignMod(..) => {} + ast::ItemImpl(..) | ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) => {} // Traits are a little special in that even if they themselves are // not public they may still be exported. @@ -235,6 +226,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { ast::ItemEnum(ref def, _) if public_first => { for variant in &def.variants { self.exported_items.insert(variant.node.id); + self.public_items.insert(variant.node.id); } } @@ -259,8 +251,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // * Private trait impls for private types can be completely ignored ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => { let public_ty = match ty.node { - ast::TyPath(_, id) => { - match self.tcx.def_map.borrow()[id].clone() { + ast::TyPath(..) => { + match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { def::DefPrimTy(..) => true, def => { let did = def.def_id(); @@ -279,18 +271,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { if public_ty || public_trait { for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - let meth_public = - match method.pe_explicit_self().node { - ast::SelfStatic => public_ty, - _ => true, - } && method.pe_vis() == ast::Public; + match impl_item.node { + ast::MethodImplItem(ref sig, _) => { + let meth_public = match sig.explicit_self.node { + ast::SelfStatic => public_ty, + _ => true, + } && impl_item.vis == ast::Public; if meth_public || tr.is_some() { - self.exported_items.insert(method.id); + self.exported_items.insert(impl_item.id); } } - ast::TypeImplItem(_) => {} + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} } } } @@ -298,22 +290,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // Default methods on traits are all public so long as the trait // is public - ast::ItemTrait(_, _, _, ref methods) if public_first => { - for method in methods { - match *method { - ast::ProvidedMethod(ref m) => { - debug!("provided {}", m.id); - self.exported_items.insert(m.id); - } - ast::RequiredMethod(ref m) => { - debug!("required {}", m.id); - self.exported_items.insert(m.id); - } - ast::TypeTraitItem(ref t) => { - debug!("typedef {}", t.ty_param.id); - self.exported_items.insert(t.ty_param.id); - } - } + ast::ItemTrait(_, _, _, ref trait_items) if public_first => { + for trait_item in trait_items { + debug!("trait item {}", trait_item.id); + self.exported_items.insert(trait_item.id); } } @@ -323,11 +303,20 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { Some(id) => { self.exported_items.insert(id); } None => {} } + // fields can be public or private, so lets check + for field in &def.fields { + let vis = match field.node.kind { + ast::NamedField(_, vis) | ast::UnnamedField(vis) => vis + }; + if vis == ast::Public { + self.public_items.insert(field.node.id); + } + } } ast::ItemTy(ref ty, _) if public_first => { - if let ast::TyPath(_, id) = ty.node { - match self.tcx.def_map.borrow()[id].clone() { + if let ast::TyPath(..) = ty.node { + match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { let did = def.def_id(); @@ -359,7 +348,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // crate module gets processed as well. if self.prev_exported { assert!(self.export_map.contains_key(&id), "wut {}", id); - for export in &self.export_map[id] { + for export in self.export_map.get(&id).unwrap() { if is_local(export.def_id) { self.reexports.insert(export.def_id.node); } @@ -379,7 +368,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> { in_foreign: bool, parents: NodeMap, external_exports: ExternalExports, - last_private_map: LastPrivateMap, } enum PrivacyResult { @@ -389,7 +377,7 @@ enum PrivacyResult { } enum FieldName { - UnnamedField(uint), // index + UnnamedField(usize), // index // (Name, not Ident, because struct fields are not macro-hygienic) NamedField(ast::Name), } @@ -501,19 +489,20 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // FIXME(#10573) is this the right behavior? Why not consider // where the method was defined? Some(ast_map::NodeImplItem(ii)) => { - match *ii { - ast::MethodImplItem(ref m) => { + match ii.node { + ast::MethodImplItem(..) => { let imp = self.tcx.map .get_parent_did(closest_private_id); match ty::impl_trait_ref(self.tcx, imp) { Some(..) => return Allowable, - _ if m.pe_vis() == ast::Public => { + _ if ii.vis == ast::Public => { return Allowable } - _ => m.pe_vis() + _ => ii.vis } } - ast::TypeImplItem(_) => return Allowable, + ast::TypeImplItem(_) | + ast::MacImplItem(_) => return Allowable, } } Some(ast_map::NodeTraitItem(_)) => { @@ -535,7 +524,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // if we've reached the root, then everything was allowable and this // access is public. if closest_private_id == ast::CRATE_NODE_ID { return Allowable } - closest_private_id = self.parents[closest_private_id]; + closest_private_id = *self.parents.get(&closest_private_id).unwrap(); // If we reached the top, then we were public all the way down and // we can allow this access. @@ -553,7 +542,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { /// whether the node is accessible by the current module that iteration is /// inside. fn private_accessible(&self, id: ast::NodeId) -> bool { - let parent = self.parents[id]; + let parent = *self.parents.get(&id).unwrap(); debug!("privacy - accessible parent {}", self.nodestr(parent)); // After finding `did`'s closest private member, we roll ourselves back @@ -577,7 +566,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { _ => {} } - cur = self.parents[cur]; + cur = *self.parents.get(&cur).unwrap(); } } @@ -628,11 +617,11 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // back up the chains to find the relevant struct/enum that // was private. ast::ItemImpl(_, _, _, _, ref ty, _) => { - let id = match ty.node { - ast::TyPath(_, id) => id, + match ty.node { + ast::TyPath(..) => {} _ => return Some((err_span, err_msg, None)), }; - let def = self.tcx.def_map.borrow()[id].clone(); + let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def(); let did = def.def_id(); assert!(is_local(did)); match self.tcx.map.get(did.node) { @@ -712,25 +701,25 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { method_id, None, &format!("method `{}`", - string)[])); + string))); } // Checks that a path is in scope. - fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) { + fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) { debug!("privacy - path {}", self.nodestr(path_id)); - let orig_def = self.tcx.def_map.borrow()[path_id].clone(); + let path_res = *self.tcx.def_map.borrow().get(&path_id).unwrap(); let ck = |tyname: &str| { let ck_public = |def: ast::DefId| { debug!("privacy - ck_public {:?}", def); - let name = token::get_ident(path.segments.last().unwrap().identifier); - let origdid = orig_def.def_id(); + let name = token::get_ident(last); + let origdid = path_res.def_id(); self.ensure_public(span, def, Some(origdid), - &format!("{} `{}`", tyname, name)[]) + &format!("{} `{}`", tyname, name)) }; - match self.last_private_map[path_id] { + match path_res.last_private { LastMod(AllPublic) => {}, LastMod(DependsOn(def)) => { self.report_error(ck_public(def)); @@ -794,8 +783,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // def map is not. Therefore the names we work out below will not always // be accurate and we can get slightly wonky error messages (but type // checking is always correct). - match self.tcx.def_map.borrow()[path_id].clone() { - def::DefStaticMethod(..) => ck("static method"), + match path_res.full_def() { def::DefFn(..) => ck("function"), def::DefStatic(..) => ck("static"), def::DefConst(..) => ck("const"), @@ -804,7 +792,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { def::DefTy(_, true) => ck("enum"), def::DefTrait(..) => ck("trait"), def::DefStruct(..) => ck("struct"), - def::DefMethod(_, Some(..), _) => ck("trait method"), def::DefMethod(..) => ck("method"), def::DefMod(..) => ck("module"), _ => {} @@ -832,37 +819,22 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { - match item.node { - ast::ItemUse(ref vpath) => { - match vpath.node { - ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {} - ast::ViewPathList(ref prefix, ref list) => { - for pid in list { - match pid.node { - ast::PathListIdent { id, name } => { - debug!("privacy - ident item {}", id); - let seg = ast::PathSegment { - identifier: name, - parameters: ast::PathParameters::none(), - }; - let segs = vec![seg]; - let path = ast::Path { - global: false, - span: pid.span, - segments: segs, - }; - self.check_path(pid.span, id, &path); - } - ast::PathListMod { id } => { - debug!("privacy - mod item {}", id); - self.check_path(pid.span, id, prefix); - } - } + if let ast::ItemUse(ref vpath) = item.node { + if let ast::ViewPathList(ref prefix, ref list) = vpath.node { + for pid in list { + match pid.node { + ast::PathListIdent { id, name } => { + debug!("privacy - ident item {}", id); + self.check_path(pid.span, id, name); + } + ast::PathListMod { id } => { + debug!("privacy - mod item {}", id); + let name = prefix.segments.last().unwrap().identifier; + self.check_path(pid.span, id, name); } } } } - _ => {} } let orig_curitem = replace(&mut self.curitem, item.id); visit::walk_item(self, item); @@ -908,7 +880,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } } ty::ty_enum(_, _) => { - match self.tcx.def_map.borrow()[expr.id].clone() { + match self.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() { def::DefVariant(_, variant_id, _) => { for field in fields { self.check_field(expr.span, variant_id, @@ -927,7 +899,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { struct type?!"), } } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { let guard = |did: ast::DefId| { let fields = ty::lookup_struct_fields(self.tcx, did); let any_priv = fields.iter().any(|f| { @@ -941,8 +913,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { with private fields"); } }; - match self.tcx.def_map.borrow().get(&expr.id) { - Some(&def::DefStruct(did)) => { + match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { + Some(def::DefStruct(did)) => { guard(if is_local(did) { local_def(self.tcx.map.get_parent(did.node)) } else { @@ -981,8 +953,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } } ty::ty_enum(_, _) => { - match self.tcx.def_map.borrow().get(&pattern.id) { - Some(&def::DefVariant(_, variant_id, _)) => { + match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) { + Some(def::DefVariant(_, variant_id, _)) => { for field in fields { self.check_field(pattern.span, variant_id, NamedField(field.node.ident.name)); @@ -1033,7 +1005,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { } fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) { - self.check_path(path.span, id, path); + self.check_path(path.span, id, path.segments.last().unwrap().identifier); visit::walk_path(self, path); } } @@ -1096,12 +1068,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { "visibility qualifiers have no effect on trait \ impls"); for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref m) => { - check_inherited(m.span, m.pe_vis(), ""); - } - ast::TypeImplItem(_) => {} - } + check_inherited(impl_item.span, impl_item.vis, ""); } } @@ -1129,22 +1096,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemTrait(_, _, _, ref methods) => { - for m in methods { - match *m { - ast::ProvidedMethod(ref m) => { - check_inherited(m.span, m.pe_vis(), - "unnecessary visibility"); - } - ast::RequiredMethod(ref m) => { - check_inherited(m.span, m.vis, - "unnecessary visibility"); - } - ast::TypeTraitItem(_) => {} - } - } - } - + ast::ItemTrait(..) | ast::ItemDefaultImpl(..) | ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {} @@ -1172,11 +1124,12 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { match item.node { ast::ItemImpl(_, _, _, _, _, ref impl_items) => { for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref m) => { - check_inherited(tcx, m.span, m.pe_vis()); + match impl_item.node { + ast::MethodImplItem(..) => { + check_inherited(tcx, impl_item.span, impl_item.vis); } - ast::TypeImplItem(_) => {} + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} } } } @@ -1193,18 +1146,8 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::ItemStruct(ref def, _) => check_struct(&**def), - ast::ItemTrait(_, _, _, ref methods) => { - for m in methods { - match *m { - ast::RequiredMethod(..) => {} - ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span, - m.pe_vis()), - ast::TypeTraitItem(_) => {} - } - } - } - ast::ItemExternCrate(_) | ast::ItemUse(_) | + ast::ItemTrait(..) | ast::ItemDefaultImpl(..) | ast::ItemStatic(..) | ast::ItemConst(..) | ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) | ast::ItemMac(..) => {} @@ -1232,7 +1175,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> { impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { fn path_is_private_type(&self, path_id: ast::NodeId) -> bool { - let did = match self.tcx.def_map.borrow().get(&path_id).cloned() { + let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) { // `int` etc. (None doesn't seem to occur.) None | Some(def::DefPrimTy(..)) => return false, Some(def) => def.def_id() @@ -1242,6 +1185,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { if !is_local(did) { return false } + // .. and it corresponds to a private type in the AST (this returns // None for type parameters) match self.tcx.map.find(did.node) { @@ -1262,18 +1206,21 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(trait_ref.trait_ref.ref_id) { let span = trait_ref.trait_ref.path.span; - self.tcx.sess.span_err(span, - "private trait in exported type \ - parameter bound"); + self.tcx.sess.span_err(span, "private trait in exported type \ + parameter bound"); } } } + + fn item_is_public(&self, id: &ast::NodeId, vis: ast::Visibility) -> bool { + self.exported_items.contains(id) || vis == ast::Public + } } impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { - if let ast::TyPath(_, path_id) = ty.node { - if self.inner.path_is_private_type(path_id) { + if let ast::TyPath(..) = ty.node { + if self.inner.path_is_private_type(ty.id) { self.contains_private = true; // found what we're looking for so let's stop // working. @@ -1315,7 +1262,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // error messages without (too many) false positives // (i.e. we could just return here to not check them at // all, or some worse estimation of whether an impl is - // publicly visible. + // publicly visible). ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => { // `impl [... for] Private` is never visible. let self_contains_private; @@ -1359,11 +1306,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { trait_ref.is_some() || impl_items.iter() .any(|impl_item| { - match *impl_item { - ast::MethodImplItem(ref m) => { - self.exported_items.contains(&m.id) + match impl_item.node { + ast::MethodImplItem(..) => { + self.exported_items.contains(&impl_item.id) } - ast::TypeImplItem(_) => false, + ast::TypeImplItem(_) | + ast::MacImplItem(_) => false, } }); @@ -1376,19 +1324,30 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { match *trait_ref { None => { for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - visit::walk_method_helper(self, &**method) + // This is where we choose whether to walk down + // further into the impl to check its items. We + // should only walk into public items so that we + // don't erroneously report errors for private + // types in private items. + match impl_item.node { + ast::MethodImplItem(..) + if self.item_is_public(&impl_item.id, impl_item.vis) => + { + visit::walk_impl_item(self, impl_item) + } + ast::TypeImplItem(..) => { + visit::walk_impl_item(self, impl_item) } - ast::TypeImplItem(_) => {} + _ => {} } } } Some(ref tr) => { - // Any private types in a trait impl fall into two + // Any private types in a trait impl fall into three // categories. // 1. mentioned in the trait definition // 2. mentioned in the type params/generics + // 3. mentioned in the associated types of the impl // // Those in 1. can only occur if the trait is in // this crate and will've been warned about on the @@ -1397,7 +1356,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // // Those in 2. are warned via walk_generics and this // call here. - self.visit_trait_ref(tr) + visit::walk_path(self, &tr.path); + + // Those in 3. are warned with this call. + for impl_item in impl_items { + match impl_item.node { + ast::TypeImplItem(ref ty) => { + self.visit_ty(ty); + } + ast::MethodImplItem(..) | + ast::MacImplItem(_) => {}, + } + } } } } else if trait_ref.is_none() && self_is_public_path { @@ -1405,17 +1375,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - if method.pe_explicit_self().node == - ast::SelfStatic && - self.exported_items - .contains(&method.id) { + match impl_item.node { + ast::MethodImplItem(ref sig, _) => { + if sig.explicit_self.node == ast::SelfStatic && + self.item_is_public(&impl_item.id, impl_item.vis) { found_pub_static = true; - visit::walk_method_helper(self, &**method); + visit::walk_impl_item(self, impl_item); } } - ast::TypeImplItem(_) => {} + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} } } if found_pub_static { @@ -1430,15 +1399,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { ast::ItemTy(..) => return, // not at all public, so we don't care - _ if !self.exported_items.contains(&item.id) => return, + _ if !self.item_is_public(&item.id, item.vis) => { + return; + } _ => {} } - // we've carefully constructed it so that if we're here, then + // We've carefully constructed it so that if we're here, then // any `visit_ty`'s will be called on things that are in // public signatures, i.e. things that we're interested in for // this visitor. + debug!("VisiblePrivateTypesVisitor entering item {:?}", item); visit::walk_item(self, item); } @@ -1469,20 +1441,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { } } - fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, - b: &'v ast::Block, s: Span, id: ast::NodeId) { - // needs special handling for methods. - if self.exported_items.contains(&id) { - visit::walk_fn(self, fk, fd, b, s); - } - } - fn visit_ty(&mut self, t: &ast::Ty) { - if let ast::TyPath(ref p, path_id) = t.node { + debug!("VisiblePrivateTypesVisitor checking ty {:?}", t); + if let ast::TyPath(_, ref p) = t.node { if !self.tcx.sess.features.borrow().visible_private_types && - self.path_is_private_type(path_id) { - self.tcx.sess.span_err(p.span, - "private type in exported type signature"); + self.path_is_private_type(t.id) { + self.tcx.sess.span_err(p.span, "private type in exported type signature"); } } visit::walk_ty(self, t) @@ -1516,8 +1480,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { pub fn check_crate(tcx: &ty::ctxt, export_map: &def::ExportMap, - external_exports: ExternalExports, - last_private_map: LastPrivateMap) + external_exports: ExternalExports) -> (ExportedItems, PublicItems) { let krate = tcx.map.krate(); @@ -1535,7 +1498,6 @@ pub fn check_crate(tcx: &ty::ctxt, tcx: tcx, parents: visitor.parents, external_exports: external_exports, - last_private_map: last_private_map, }; visit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 2f25f34a92..52db6013f4 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -14,19 +14,18 @@ //! any imports resolved. use {DefModifiers, PUBLIC, IMPORTABLE}; -use ImportDirective; -use ImportDirectiveSubclass::{self, SingleImport, GlobImport}; -use ImportResolution; +use resolve_imports::ImportDirective; +use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport}; +use resolve_imports::ImportResolution; use Module; use ModuleKind::*; use Namespace::{TypeNS, ValueNS}; use NameBindings; +use {names_to_string, module_to_string}; use ParentLink::{self, ModuleParentLink, BlockParentLink}; use Resolver; -use RibKind::*; -use Shadowable; +use resolve_imports::Shadowable; use TypeNsDef; -use TypeParameters::HasTypeParameters; use self::DuplicateCheckingMode::*; use self::NamespaceError::*; @@ -34,27 +33,23 @@ use self::NamespaceError::*; use rustc::metadata::csearch; use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; use rustc::middle::def::*; -use rustc::middle::subst::FnSpace; use syntax::ast::{Block, Crate}; use syntax::ast::{DeclItem, DefId}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn}; -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; -use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; -use syntax::ast::{PathListIdent, PathListMod}; -use syntax::ast::{Public, SelfStatic}; +use syntax::ast::{Name, NamedField, NodeId}; +use syntax::ast::{PathListIdent, PathListMod, Public}; use syntax::ast::StmtDecl; use syntax::ast::StructVariantKind; use syntax::ast::TupleVariantKind; -use syntax::ast::TyObjectSum; -use syntax::ast::{TypeImplItem, UnnamedField}; +use syntax::ast::UnnamedField; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; -use syntax::ast::{Visibility}; -use syntax::ast::TyPath; +use syntax::ast::Visibility; use syntax::ast; -use syntax::ast_util::{self, PostExpansionMethod, local_def}; +use syntax::ast_util::local_def; use syntax::attr::AttrMetaMethods; use syntax::parse::token::{self, special_idents}; use syntax::codemap::{Span, DUMMY_SP}; @@ -66,7 +61,7 @@ use std::rc::Rc; // Specifies how duplicates should be handled when adding a child item if // another item exists with the same name in some namespace. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum DuplicateCheckingMode { ForbidDuplicateModules, ForbidDuplicateTypesAndModules, @@ -75,7 +70,7 @@ enum DuplicateCheckingMode { OverwriteDuplicates } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum NamespaceError { NoError, ModuleError, @@ -181,12 +176,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(TypeNS) } ForbidDuplicateTypesAndModules => { - match child.def_for_namespace(TypeNS) { - None => {} - Some(_) if child.get_module_if_available() - .map(|m| m.kind.get()) == - Some(ImplModuleKind) => {} - Some(_) => duplicate_type = TypeError + if child.defined_in_namespace(TypeNS) { + duplicate_type = TypeError; } Some(TypeNS) } @@ -220,14 +211,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.resolve_error(sp, &format!("duplicate definition of {} `{}`", namespace_error_to_string(duplicate_type), - token::get_name(name))[]); + token::get_name(name))); { let r = child.span_for_namespace(ns); if let Some(sp) = r { self.session.span_note(sp, &format!("first definition of {} `{}` here", namespace_error_to_string(duplicate_type), - token::get_name(name))[]); + token::get_name(name))); } } } @@ -307,8 +298,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ViewPathSimple(binding, ref full_path) => { let source_name = full_path.segments.last().unwrap().identifier.name; - if &token::get_name(source_name)[] == "mod" || - &token::get_name(source_name)[] == "self" { + if &token::get_name(source_name)[..] == "mod" || + &token::get_name(source_name)[..] == "self" { self.resolve_error(view_path.span, "`self` imports are only allowed within a { } list"); } @@ -381,8 +372,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { ItemExternCrate(_) => { // n.b. we don't need to look at the path option here, because cstore already did - for &crate_id in self.session.cstore - .find_extern_mod_stmt_cnum(item.id).iter() { + if let Some(crate_id) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) { let def_id = DefId { krate: crate_id, node: 0 }; self.external_exports.insert(def_id); let parent_link = ModuleParentLink(parent.downgrade(), name); @@ -392,7 +382,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { false, true)); debug!("(build reduced graph for item) found extern `{}`", - self.module_to_string(&*external_module)); + module_to_string(&*external_module)); self.check_for_conflicts_between_external_crates(&**parent, name, sp); parent.external_module_children.borrow_mut() .insert(name, external_module.clone()); @@ -410,7 +400,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(def_id), NormalModuleKind, false, - item.vis == ast::Public, + is_public, sp); name_bindings.get_module() @@ -442,8 +432,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // These items live in the type namespace. ItemTy(..) => { let name_bindings = - self.add_child(name, parent, ForbidDuplicateTypesAndModules, - sp); + self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp); name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers); @@ -465,9 +454,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers); let parent_link = self.get_parent_link(parent, name); - // We want to make sure the module type is EnumModuleKind - // even if there's already an ImplModuleKind module defined, - // since that's how we prevent duplicate enum definitions name_bindings.set_module_kind(parent_link, Some(local_def(item.id)), EnumModuleKind, @@ -517,146 +503,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { parent.clone() } - 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. - - let mod_name = match ty.node { - TyPath(ref path, _) if path.segments.len() == 1 => { - // FIXME(18446) we should distinguish between the name of - // a trait and the name of an impl of that trait. - Some(path.segments.last().unwrap().identifier.name) - } - TyObjectSum(ref lhs_ty, _) => { - match lhs_ty.node { - TyPath(ref path, _) if path.segments.len() == 1 => { - Some(path.segments.last().unwrap().identifier.name) - } - _ => { - None - } - } - } - _ => { - None - } - }; - - let mod_name = match mod_name { - Some(mod_name) => mod_name, - None => { - self.resolve_error(ty.span, - "inherent implementations may \ - only be implemented in the same \ - module as the type they are \ - implemented for"); - return parent.clone(); - } - }; - // Create the module and add all methods. - let child_opt = parent.children.borrow().get(&mod_name) - .and_then(|m| m.get_module_if_available()); - let new_parent = match child_opt { - // It already exists - Some(ref child) if (child.kind.get() == ImplModuleKind || - child.kind.get() == TraitModuleKind) => { - child.clone() - } - Some(ref child) if child.kind.get() == EnumModuleKind || - child.kind.get() == TypeModuleKind => { - child.clone() - } - // Create the module - _ => { - let name_bindings = - self.add_child(mod_name, parent, ForbidDuplicateModules, sp); - - let parent_link = self.get_parent_link(parent, name); - let def_id = local_def(item.id); - let ns = TypeNS; - let is_public = - !name_bindings.defined_in_namespace(ns) || - name_bindings.defined_in_public_namespace(ns); - - name_bindings.define_module(parent_link, - Some(def_id), - ImplModuleKind, - false, - is_public, - sp); - - name_bindings.get_module() - } - }; - - // For each implementation item... - for impl_item in impl_items { - match *impl_item { - MethodImplItem(ref method) => { - // Add the method to the module. - let name = method.pe_ident().name; - let method_name_bindings = - self.add_child(name, - &new_parent, - ForbidDuplicateValues, - method.span); - let def = match method.pe_explicit_self() - .node { - SelfStatic => { - // Static methods become - // `DefStaticMethod`s. - DefStaticMethod(local_def(method.id), - FromImpl(local_def(item.id))) - } - _ => { - // Non-static methods become - // `DefMethod`s. - DefMethod(local_def(method.id), - None, - FromImpl(local_def(item.id))) - } - }; - - // NB: not IMPORTABLE - let modifiers = if method.pe_vis() == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - method_name_bindings.define_value( - def, - method.span, - modifiers); - } - TypeImplItem(ref typedef) => { - // Add the typedef to the module. - let name = typedef.ident.name; - let typedef_name_bindings = - self.add_child( - name, - &new_parent, - ForbidDuplicateTypesAndModules, - typedef.span); - let def = DefAssociatedTy(local_def( - typedef.id)); - // NB: not IMPORTABLE - let modifiers = if typedef.vis == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - typedef_name_bindings.define_type( - def, - typedef.span, - modifiers); - } - } - } - parent.clone() - } - - ItemImpl(_, _, _, Some(_), _, _) => parent.clone(), + ItemDefaultImpl(_, _) | + ItemImpl(..) => parent.clone(), ItemTrait(_, _, _, ref items) => { let name_bindings = @@ -668,7 +516,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(local_def(item.id)), TraitModuleKind, false, - item.vis == ast::Public, + is_public, sp); let module_parent = name_bindings.get_module(); @@ -676,63 +524,28 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // Add the names of all the items to the trait info. for trait_item in items { - let (name, kind) = match *trait_item { - ast::RequiredMethod(_) | - ast::ProvidedMethod(_) => { - let ty_m = ast_util::trait_item_to_ty_method(trait_item); - - let name = ty_m.ident.name; - - // Add it as a name in the trait module. - let (def, static_flag) = match ty_m.explicit_self - .node { - SelfStatic => { - // Static methods become `DefStaticMethod`s. - (DefStaticMethod( - local_def(ty_m.id), - FromTrait(local_def(item.id))), - StaticMethodTraitItemKind) - } - _ => { - // Non-static methods become `DefMethod`s. - (DefMethod(local_def(ty_m.id), - Some(local_def(item.id)), - FromTrait(local_def(item.id))), - NonstaticMethodTraitItemKind) - } - }; - - let method_name_bindings = - self.add_child(name, - &module_parent, - ForbidDuplicateTypesAndValues, - ty_m.span); + let name_bindings = self.add_child(trait_item.ident.name, + &module_parent, + ForbidDuplicateTypesAndValues, + trait_item.span); + + match trait_item.node { + ast::MethodTraitItem(..) => { + let def = DefMethod(local_def(trait_item.id), + FromTrait(local_def(item.id))); // NB: not IMPORTABLE - method_name_bindings.define_value(def, - ty_m.span, - PUBLIC); - - (name, static_flag) + name_bindings.define_value(def, trait_item.span, PUBLIC); } - ast::TypeTraitItem(ref associated_type) => { - let def = DefAssociatedTy(local_def( - associated_type.ty_param.id)); - - let name_bindings = - self.add_child(associated_type.ty_param.ident.name, - &module_parent, - ForbidDuplicateTypesAndValues, - associated_type.ty_param.span); + ast::TypeTraitItem(..) => { + let def = DefAssociatedTy(local_def(item.id), + local_def(trait_item.id)); // NB: not IMPORTABLE - name_bindings.define_type(def, - associated_type.ty_param.span, - PUBLIC); - - (associated_type.ty_param.ident.name, TypeTraitItemKind) + name_bindings.define_type(def, trait_item.span, PUBLIC); } - }; + } - self.trait_item_map.insert((name, def_id), kind); + self.trait_item_map.insert((trait_item.ident.name, def_id), + local_def(trait_item.id)); } name_bindings.define_type(DefTrait(def_id), sp, modifiers); @@ -772,12 +585,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, - foreign_item: &ForeignItem, - parent: &Rc, - f: F) where - F: FnOnce(&mut Resolver), - { + fn build_reduced_graph_for_foreign_item(&mut self, + foreign_item: &ForeignItem, + parent: &Rc) { let name = foreign_item.ident.name; let is_public = foreign_item.vis == ast::Public; let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; @@ -785,25 +595,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { self.add_child(name, parent, ForbidDuplicateValues, foreign_item.span); - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - let def = DefFn(local_def(foreign_item.id), false); - name_bindings.define_value(def, foreign_item.span, modifiers); - - self.with_type_parameter_rib( - HasTypeParameters(generics, - FnSpace, - foreign_item.id, - NormalRibKind), - f); + let def = match foreign_item.node { + ForeignItemFn(..) => { + DefFn(local_def(foreign_item.id), false) } ForeignItemStatic(_, m) => { - let def = DefStatic(local_def(foreign_item.id), m); - name_bindings.define_value(def, foreign_item.span, modifiers); - - f(self.resolver) + DefStatic(local_def(foreign_item.id), m) } - } + }; + name_bindings.define_value(def, foreign_item.span, modifiers); } fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc) -> Rc { @@ -835,8 +635,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { name: Name, new_parent: &Rc) { debug!("(building reduced graph for \ - external crate) building external def, priv {:?}", - vis); + external crate) building external def {}, priv {:?}", + final_ident, vis); let is_public = vis == ast::Public; let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; let is_exported = is_public && match new_parent.def_id.get() { @@ -849,8 +649,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let kind = match def { DefTy(_, true) => EnumModuleKind, - DefTy(_, false) => TypeModuleKind, - DefStruct(..) => ImplModuleKind, + DefTy(_, false) | DefStruct(..) => TypeModuleKind, _ => NormalModuleKind }; @@ -867,7 +666,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(_) | None => { debug!("(building reduced graph for \ external crate) building module \ - {}", final_ident); + {} {}", final_ident, is_public); let parent_link = self.get_parent_link(new_parent, name); child_name_bindings.define_module(parent_link, @@ -904,7 +703,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers); } - DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { + DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { debug!("(building reduced graph for external \ crate) building value (fn/static) {}", final_ident); // impl methods have already been defined with the correct importability modifier @@ -926,21 +725,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let trait_item_def_ids = csearch::get_trait_item_def_ids(&self.session.cstore, def_id); - for trait_item_def_id in &trait_item_def_ids { - let (trait_item_name, trait_item_kind) = - csearch::get_trait_item_name_and_kind( - &self.session.cstore, - trait_item_def_id.def_id()); + for trait_item_def in &trait_item_def_ids { + let trait_item_name = csearch::get_trait_name(&self.session.cstore, + trait_item_def.def_id()); debug!("(building reduced graph for external crate) ... \ adding trait item '{}'", token::get_name(trait_item_name)); - self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind); + self.trait_item_map.insert((trait_item_name, def_id), + trait_item_def.def_id()); if is_exported { - self.external_exports - .insert(trait_item_def_id.def_id()); + self.external_exports.insert(trait_item_def.def_id()); } } @@ -955,7 +752,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { is_public, DUMMY_SP) } - DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => { + DefTy(..) | DefAssociatedTy(..) => { debug!("(building reduced graph for external \ crate) building type {}", final_ident); @@ -979,7 +776,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | DefUse(..) | DefUpvar(..) | DefRegion(..) | - DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => { + DefLabel(..) | DefSelfTy(..) => { panic!("didn't expect `{:?}`", def); } } @@ -1026,92 +823,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { } } } - DlImpl(def) => { - match csearch::get_type_name_if_impl(&self.session.cstore, def) { - None => {} - Some(final_name) => { - let methods_opt = - csearch::get_methods_if_impl(&self.session.cstore, def); - match methods_opt { - Some(ref methods) if - methods.len() >= 1 => { - debug!("(building reduced graph for \ - external crate) processing \ - static methods for type name {}", - token::get_name(final_name)); - - let child_name_bindings = - self.add_child( - final_name, - root, - OverwriteDuplicates, - DUMMY_SP); - - // Process the static methods. First, - // create the module. - let type_module; - let type_def = child_name_bindings.type_def.borrow().clone(); - match type_def { - Some(TypeNsDef { - module_def: Some(module_def), - .. - }) => { - // We already have a module. This - // is OK. - type_module = module_def; - - // Mark it as an impl module if - // necessary. - type_module.kind.set(ImplModuleKind); - } - Some(_) | None => { - let parent_link = - self.get_parent_link(root, final_name); - child_name_bindings.define_module( - parent_link, - Some(def), - ImplModuleKind, - true, - true, - DUMMY_SP); - type_module = - child_name_bindings. - get_module(); - } - } - - // Add each static method to the module. - let new_parent = type_module; - for method_info in methods { - let name = method_info.name; - debug!("(building reduced graph for \ - external crate) creating \ - static method '{}'", - token::get_name(name)); - - let method_name_bindings = - self.add_child(name, - &new_parent, - OverwriteDuplicates, - DUMMY_SP); - let def = DefFn(method_info.def_id, false); - - // NB: not IMPORTABLE - let modifiers = if method_info.vis == ast::Public { - PUBLIC - } else { - DefModifiers::empty() - }; - method_name_bindings.define_value( - def, DUMMY_SP, modifiers); - } - } - - // Otherwise, do nothing. - Some(_) | None => {} - } - } - } + DlImpl(_) => { + debug!("(building reduced graph for external crate) \ + ignoring impl"); } DlField => { debug!("(building reduced graph for external crate) \ @@ -1123,7 +837,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { /// Builds the reduced graph rooted at the given external module. fn populate_external_module(&mut self, module: &Rc) { debug!("(populating external module) attempting to populate {}", - self.module_to_string(&**module)); + module_to_string(&**module)); let def_id = match module.def_id.get() { None => { @@ -1189,18 +903,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { match subclass { SingleImport(target, _) => { - debug!("(building import directive) building import \ - directive: {}::{}", - self.names_to_string(&module_.imports.borrow().last().unwrap(). - module_path[]), + debug!("(building import directive) building import directive: {}::{}", + names_to_string(&module_.imports.borrow().last().unwrap().module_path), token::get_name(target)); - let mut import_resolutions = module_.import_resolutions - .borrow_mut(); + let mut import_resolutions = module_.import_resolutions.borrow_mut(); match import_resolutions.get_mut(&target) { Some(resolution) => { - debug!("(building import directive) bumping \ - reference"); + debug!("(building import directive) bumping reference"); resolution.outstanding_references += 1; // the source of this name is different now @@ -1240,16 +950,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { - let parent = &self.parent; - self.builder.build_reduced_graph_for_foreign_item(foreign_item, - parent, - |r| { - let mut v = BuildReducedGraphVisitor { - builder: GraphBuilder { resolver: r }, - parent: parent.clone() - }; - visit::walk_foreign_item(&mut v, foreign_item); - }) + self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent); } fn visit_block(&mut self, block: &Block) { diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index a239c73c11..aebbe14407 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -68,17 +68,17 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { "unused import".to_string()); } - let (v_priv, t_priv) = match self.last_private.get(&id) { - Some(&LastImport { - value_priv: v, - value_used: _, - type_priv: t, - type_used: _ - }) => (v, t), - Some(_) => { + let mut def_map = self.def_map.borrow_mut(); + let path_res = if let Some(r) = def_map.get_mut(&id) { + r + } else { + return; + }; + let (v_priv, t_priv) = match path_res.last_private { + LastImport { value_priv, type_priv, .. } => (value_priv, type_priv), + _ => { panic!("we should only have LastImport for `use` directives") } - _ => return, }; let mut v_used = if self.used_imports.contains(&(id, ValueNS)) { @@ -100,10 +100,12 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { _ => {}, } - self.last_private.insert(id, LastImport{value_priv: v_priv, - value_used: v_used, - type_priv: t_priv, - type_used: t_used}); + path_res.last_private = LastImport { + value_priv: v_priv, + value_used: v_used, + type_priv: t_priv, + type_used: t_used + }; } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 124aa39243..c586faae6e 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -24,7 +24,9 @@ register_diagnostics! { E0258, // import conflicts with existing submodule E0259, // an extern crate has already been imported into this module E0260, // name conflicts with an external crate that has been imported into this module - E0317 // user-defined types or type parameters cannot shadow the primitive types + E0317, // user-defined types or type parameters cannot shadow the primitive types + E0364, // item is private + E0365 // item is private } __build_diagnostic_array! { DIAGNOSTICS } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 333d32d76b..045320e4fa 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_resolve"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -19,12 +21,9 @@ #![feature(alloc)] #![feature(collections)] -#![feature(core)] -#![feature(int_uint)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(std_misc)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; @@ -36,19 +35,16 @@ use self::PatternBindingMode::*; use self::Namespace::*; use self::NamespaceResult::*; use self::NameDefinition::*; -use self::ImportDirectiveSubclass::*; use self::ResolveResult::*; use self::FallbackSuggestion::*; use self::TypeParameters::*; use self::RibKind::*; -use self::MethodSort::*; use self::UseLexicalScopeFlag::*; use self::ModulePrefixResult::*; use self::NameSearchType::*; use self::BareIdentifierPatternResolution::*; use self::ParentLink::*; use self::ModuleKind::*; -use self::TraitReferenceType::*; use self::FallbackChecks::*; use rustc::session::Session; @@ -66,31 +62,28 @@ use rustc::util::lev_distance::lev_distance; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField}; -use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall}; -use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl}; +use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall}; +use syntax::ast::{ExprPath, ExprStruct, FnDecl}; use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; -use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse}; -use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId}; +use syntax::ast::{Local, MethodImplItem, Name, NodeId}; use syntax::ast::{Pat, PatEnum, PatIdent, PatLit}; -use syntax::ast::{PatRange, PatStruct, Path}; -use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit}; -use syntax::ast::{RegionTyParamBound, StructField}; -use syntax::ast::{TraitRef, TraitTyParamBound}; -use syntax::ast::{Ty, TyBool, TyChar, TyF32}; -use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum}; -use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath}; +use syntax::ast::{PatRange, PatStruct, Path, PrimTy}; +use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32}; +use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt}; +use syntax::ast::{TyPath, TyPtr}; use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint}; -use syntax::ast::{TypeImplItem}; +use syntax::ast::TypeImplItem; use syntax::ast; use syntax::ast_map; -use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat}; +use syntax::ast_util::{local_def, walk_pat}; use syntax::attr::AttrMetaMethods; use syntax::ext::mtwt; use syntax::parse::token::{self, special_names, special_idents}; -use syntax::codemap::{Span, Pos}; -use syntax::owned_slice::OwnedSlice; +use syntax::ptr::P; +use syntax::codemap::{self, Span, Pos}; use syntax::visit::{self, Visitor}; use std::collections::{HashMap, HashSet}; @@ -101,6 +94,10 @@ use std::mem::replace; use std::rc::{Rc, Weak}; use std::usize; +use resolve_imports::{Target, ImportDirective, ImportResolution}; +use resolve_imports::Shadowable; + + // NB: This module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; @@ -108,8 +105,9 @@ pub mod diagnostics; mod check_unused; mod record_exports; mod build_reduced_graph; +mod resolve_imports; -#[derive(Copy)] +#[derive(Copy, Clone)] struct BindingInfo { span: Span, binding_mode: BindingMode, @@ -118,14 +116,14 @@ struct BindingInfo { // Map from the name in a pattern to its binding mode. type BindingMap = HashMap; -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum PatternBindingMode { RefutableMode, LocalIrrefutableMode, ArgumentIrrefutableMode, } -#[derive(Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] enum Namespace { TypeNS, ValueNS @@ -164,9 +162,12 @@ impl NamespaceResult { } enum NameDefinition { - NoNameDefinition, //< The name was unbound. - ChildNameDefinition(Def, LastPrivate), //< The name identifies an immediate child. - ImportNameDefinition(Def, LastPrivate) //< The name identifies an import. + // The name was unbound. + NoNameDefinition, + // The name identifies an immediate child. + ChildNameDefinition(Def, LastPrivate), + // The name identifies an import. + ImportNameDefinition(Def, LastPrivate), } impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { @@ -188,13 +189,72 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_ty(&mut self, ty: &Ty) { self.resolve_type(ty); } -} + fn visit_generics(&mut self, generics: &Generics) { + self.resolve_generics(generics); + } + fn visit_poly_trait_ref(&mut self, + tref: &ast::PolyTraitRef, + m: &ast::TraitBoundModifier) { + match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) { + Ok(def) => self.record_def(tref.trait_ref.ref_id, def), + Err(_) => { /* error already reported */ } + } + visit::walk_poly_trait_ref(self, tref, m); + } + fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) { + if let Some(ref dis_expr) = variant.node.disr_expr { + // resolve the discriminator expr as a constant + self.with_constant_rib(|this| { + this.visit_expr(&**dis_expr); + }); + } -/// Contains data for specific types of import directives. -#[derive(Copy,Debug)] -enum ImportDirectiveSubclass { - SingleImport(Name /* target */, Name /* source */), - GlobImport + // `visit::walk_variant` without the discriminant expression. + match variant.node.kind { + ast::TupleVariantKind(ref variant_arguments) => { + for variant_argument in variant_arguments.iter() { + self.visit_ty(&*variant_argument.ty); + } + } + ast::StructVariantKind(ref struct_definition) => { + self.visit_struct_def(&**struct_definition, + variant.node.name, + generics, + variant.node.id); + } + } + } + fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) { + let type_parameters = match foreign_item.node { + ForeignItemFn(_, ref generics) => { + HasTypeParameters(generics, FnSpace, ItemRibKind) + } + ForeignItemStatic(..) => NoTypeParameters + }; + self.with_type_parameter_rib(type_parameters, |this| { + visit::walk_foreign_item(this, foreign_item); + }); + } + fn visit_fn(&mut self, + function_kind: visit::FnKind<'v>, + declaration: &'v FnDecl, + block: &'v Block, + _: Span, + node_id: NodeId) { + let rib_kind = match function_kind { + visit::FkItemFn(_, generics, _, _) => { + self.visit_generics(generics); + ItemRibKind + } + visit::FkMethod(_, sig) => { + self.visit_generics(&sig.generics); + self.visit_explicit_self(&sig.explicit_self); + MethodRibKind + } + visit::FkFnBlock(..) => ClosureRibKind(node_id) + }; + self.resolve_function(rib_kind, declaration, block); + } } type ErrorMessage = Option<(Span, String)>; @@ -220,7 +280,7 @@ enum FallbackSuggestion { TraitMethod(String), } -#[derive(Copy)] +#[derive(Copy, Clone)] enum TypeParameters<'a> { NoTypeParameters, HasTypeParameters( @@ -231,16 +291,13 @@ enum TypeParameters<'a> { // were declared on (type, fn, etc) ParamSpace, - // ID of the enclosing item. - NodeId, - // The kind of the rib used for type parameters. RibKind) } // The rib kind controls the translation of local // definitions (`DefLocal`) to upvars (`DefUpvar`). -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum RibKind { // No translation needs to be applied. NormalRibKind, @@ -253,8 +310,7 @@ enum RibKind { // methods. Allow references to ty params that impl or trait // binds. Disallow any other upvars (including other ty params that are // upvars). - // parent; method itself - MethodRibKind(NodeId, MethodSort), + MethodRibKind, // We passed through an item scope. Disallow upvars. ItemRibKind, @@ -263,14 +319,7 @@ enum RibKind { ConstantItemRibKind } -// Methods can be required or provided. RequiredMethod methods only occur in traits. -#[derive(Copy, Debug)] -enum MethodSort { - RequiredMethod, - ProvidedMethod(NodeId) -} - -#[derive(Copy)] +#[derive(Copy, Clone)] enum UseLexicalScopeFlag { DontUseLexicalScope, UseLexicalScope @@ -278,10 +327,10 @@ enum UseLexicalScopeFlag { enum ModulePrefixResult { NoPrefixFound, - PrefixFound(Rc, uint) + PrefixFound(Rc, usize) } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum NameSearchType { /// We're doing a name search in order to resolve a `use` directive. ImportSearch, @@ -291,7 +340,7 @@ enum NameSearchType { PathSearch, } -#[derive(Copy)] +#[derive(Copy, Clone)] enum BareIdentifierPatternResolution { FoundStructOrEnumVariant(Def, LastPrivate), FoundConst(Def, LastPrivate), @@ -314,144 +363,6 @@ impl Rib { } } -/// Whether an import can be shadowed by another import. -#[derive(Debug,PartialEq,Clone,Copy)] -enum Shadowable { - Always, - Never -} - -/// One import directive. -#[derive(Debug)] -struct ImportDirective { - module_path: Vec, - subclass: ImportDirectiveSubclass, - span: Span, - id: NodeId, - is_public: bool, // see note in ImportResolution about how to use this - shadowable: Shadowable, -} - -impl ImportDirective { - fn new(module_path: Vec , - subclass: ImportDirectiveSubclass, - span: Span, - id: NodeId, - is_public: bool, - shadowable: Shadowable) - -> ImportDirective { - ImportDirective { - module_path: module_path, - subclass: subclass, - span: span, - id: id, - is_public: is_public, - shadowable: shadowable, - } - } -} - -/// The item that an import resolves to. -#[derive(Clone,Debug)] -struct Target { - target_module: Rc, - bindings: Rc, - shadowable: Shadowable, -} - -impl Target { - fn new(target_module: Rc, - bindings: Rc, - shadowable: Shadowable) - -> Target { - Target { - target_module: target_module, - bindings: bindings, - shadowable: shadowable, - } - } -} - -/// An ImportResolution represents a particular `use` directive. -#[derive(Debug)] -struct ImportResolution { - /// Whether this resolution came from a `use` or a `pub use`. Note that this - /// should *not* be used whenever resolution is being performed, this is - /// only looked at for glob imports statements currently. Privacy testing - /// occurs during a later phase of compilation. - is_public: bool, - - // The number of outstanding references to this name. When this reaches - // zero, outside modules can count on the targets being correct. Before - // then, all bets are off; future imports could override this name. - outstanding_references: uint, - - /// The value that this `use` directive names, if there is one. - value_target: Option, - /// The source node of the `use` directive leading to the value target - /// being non-none - value_id: NodeId, - - /// The type that this `use` directive names, if there is one. - type_target: Option, - /// The source node of the `use` directive leading to the type target - /// being non-none - type_id: NodeId, -} - -impl ImportResolution { - fn new(id: NodeId, is_public: bool) -> ImportResolution { - ImportResolution { - type_id: id, - value_id: id, - outstanding_references: 0, - value_target: None, - type_target: None, - is_public: is_public, - } - } - - fn target_for_namespace(&self, namespace: Namespace) - -> Option { - match namespace { - TypeNS => self.type_target.clone(), - ValueNS => self.value_target.clone(), - } - } - - fn id(&self, namespace: Namespace) -> NodeId { - match namespace { - TypeNS => self.type_id, - ValueNS => self.value_id, - } - } - - fn shadowable(&self, namespace: Namespace) -> Shadowable { - let target = self.target_for_namespace(namespace); - if target.is_none() { - return Shadowable::Always; - } - - target.unwrap().shadowable - } - - fn set_target_and_id(&mut self, - namespace: Namespace, - target: Option, - id: NodeId) { - match namespace { - TypeNS => { - self.type_target = target; - self.type_id = id; - } - ValueNS => { - self.value_target = target; - self.value_id = id; - } - } - } -} - /// The link from a module up to its nearest parent node. #[derive(Clone,Debug)] enum ParentLink { @@ -461,18 +372,17 @@ enum ParentLink { } /// The type of module this is. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum ModuleKind { NormalModuleKind, TraitModuleKind, - ImplModuleKind, EnumModuleKind, TypeModuleKind, AnonymousModuleKind, } /// One node in the tree of modules. -struct Module { +pub struct Module { parent_link: ParentLink, def_id: Cell>, kind: Cell, @@ -505,10 +415,10 @@ struct Module { import_resolutions: RefCell>, // The number of unresolved globs that this module exports. - glob_count: Cell, + glob_count: Cell, // The index of the import we're resolving. - resolved_import_count: Cell, + resolved_import_count: Cell, // Whether this module is populated. If not populated, any attempt to // access the children must be preceded with a @@ -581,21 +491,11 @@ struct ValueNsDef { // Records the definitions (at most one for each namespace) that a name is // bound to. #[derive(Debug)] -struct NameBindings { +pub struct NameBindings { type_def: RefCell>, //< Meaning in type namespace. value_def: RefCell>, //< Meaning in value namespace. } -/// Ways in which a trait can be referenced -#[derive(Copy)] -enum TraitReferenceType { - TraitImplementation, // impl SomeTrait for T { ... } - TraitDerivation, // trait T : SomeTrait { ... } - TraitBoundingTypeParameter, // fn f() { ... } - TraitObject, // Box SomeTrait> - TraitQPath, // :: -} - impl NameBindings { fn new() -> NameBindings { NameBindings { @@ -814,6 +714,19 @@ impl NameBindings { None } } + + fn is_public(&self, namespace: Namespace) -> bool { + match namespace { + TypeNS => { + let type_def = self.type_def.borrow(); + type_def.as_ref().unwrap().modifiers.contains(PUBLIC) + } + ValueNS => { + let value_def = self.value_def.borrow(); + value_def.as_ref().unwrap().modifiers.contains(PUBLIC) + } + } + } } /// Interns the names of the primitive types. @@ -831,15 +744,13 @@ impl PrimitiveTypeTable { table.intern("char", TyChar); table.intern("f32", TyFloat(TyF32)); table.intern("f64", TyFloat(TyF64)); - table.intern("int", TyInt(TyIs(true))); - table.intern("isize", TyInt(TyIs(false))); + table.intern("isize", TyInt(TyIs)); table.intern("i8", TyInt(TyI8)); table.intern("i16", TyInt(TyI16)); table.intern("i32", TyInt(TyI32)); table.intern("i64", TyInt(TyI64)); table.intern("str", TyStr); - table.intern("uint", TyUint(TyUs(true))); - table.intern("usize", TyUint(TyUs(false))); + table.intern("usize", TyUint(TyUs)); table.intern("u8", TyUint(TyU8)); table.intern("u16", TyUint(TyU16)); table.intern("u32", TyUint(TyU32)); @@ -854,19 +765,19 @@ impl PrimitiveTypeTable { } /// The main resolver class. -struct Resolver<'a, 'tcx:'a> { +pub struct Resolver<'a, 'tcx:'a> { session: &'a Session, ast_map: &'a ast_map::Map<'tcx>, graph_root: NameBindings, - trait_item_map: FnvHashMap<(Name, DefId), TraitItemKind>, + trait_item_map: FnvHashMap<(Name, DefId), DefId>, structs: FnvHashMap>, // The number of imports that are currently unresolved. - unresolved_imports: uint, + unresolved_imports: usize, // The module that represents the current item scope. current_module: Rc, @@ -887,11 +798,6 @@ struct Resolver<'a, 'tcx:'a> { // The current self type if inside an impl (used for better errors). current_self_type: Option, - // The ident for the keyword "self". - self_name: Name, - // The ident for the non-keyword "Self". - type_self_name: Name, - // The idents for the primitive types. primitive_type_table: PrimitiveTypeTable, @@ -901,7 +807,6 @@ struct Resolver<'a, 'tcx:'a> { export_map: ExportMap, trait_map: TraitMap, external_exports: ExternalExports, - last_private: LastPrivateMap, // Whether or not to print error messages. Can be set to true // when getting additional info for error message suggestions, @@ -923,7 +828,6 @@ enum FallbackChecks { OnlyTraitAndStatics } - impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new(session: &'a Session, ast_map: &'a ast_map::Map<'tcx>, @@ -963,9 +867,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { current_trait_ref: None, current_self_type: None, - self_name: special_names::self_, - type_self_name: special_names::type_self, - primitive_type_table: PrimitiveTypeTable::new(), def_map: RefCell::new(NodeMap()), @@ -976,7 +877,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { used_imports: HashSet::new(), used_crates: HashSet::new(), external_exports: DefIdSet(), - last_private: NodeMap(), emit_errors: true, make_glob_map: make_glob_map == MakeGlobMap::Yes, @@ -984,158 +884,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - // Import resolution - // - // This is a fixed-point algorithm. We resolve imports until our efforts - // are stymied by an unresolved import; then we bail out of the current - // module and continue. We terminate successfully once no more imports - // remain or unsuccessfully when no forward progress in resolving imports - // is made. - - /// Resolves all imports for the crate. This method performs the fixed- - /// point iteration. - fn resolve_imports(&mut self) { - let mut i = 0; - let mut prev_unresolved_imports = 0; - loop { - debug!("(resolving imports) iteration {}, {} imports left", - i, self.unresolved_imports); - - let module_root = self.graph_root.get_module(); - self.resolve_imports_for_module_subtree(module_root.clone()); - - if self.unresolved_imports == 0 { - debug!("(resolving imports) success"); - break; - } - - if self.unresolved_imports == prev_unresolved_imports { - self.report_unresolved_imports(module_root); - break; - } - - i += 1; - prev_unresolved_imports = self.unresolved_imports; - } - } - - /// Attempts to resolve imports for the given module and all of its - /// submodules. - fn resolve_imports_for_module_subtree(&mut self, module_: Rc) { - debug!("(resolving imports for module subtree) resolving {}", - self.module_to_string(&*module_)); - let orig_module = replace(&mut self.current_module, module_.clone()); - self.resolve_imports_for_module(module_.clone()); - self.current_module = orig_module; - - build_reduced_graph::populate_module_if_necessary(self, &module_); - for (_, child_node) in &*module_.children.borrow() { - match child_node.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.resolve_imports_for_module_subtree(child_module); - } - } - } - - for (_, child_module) in &*module_.anonymous_children.borrow() { - self.resolve_imports_for_module_subtree(child_module.clone()); - } - } - - /// Attempts to resolve imports for the given module only. - fn resolve_imports_for_module(&mut self, module: Rc) { - if module.all_imports_resolved() { - debug!("(resolving imports for module) all imports resolved for \ - {}", - self.module_to_string(&*module)); - return; - } - - let imports = module.imports.borrow(); - let import_count = imports.len(); - while module.resolved_import_count.get() < import_count { - let import_index = module.resolved_import_count.get(); - let import_directive = &(*imports)[import_index]; - match self.resolve_import_for_module(module.clone(), - import_directive) { - Failed(err) => { - let (span, help) = match err { - Some((span, msg)) => (span, format!(". {}", msg)), - None => (import_directive.span, String::new()) - }; - let msg = format!("unresolved import `{}`{}", - self.import_path_to_string( - &import_directive.module_path[], - import_directive.subclass), - help); - self.resolve_error(span, &msg[..]); - } - Indeterminate => break, // Bail out. We'll come around next time. - Success(()) => () // Good. Continue. - } - - module.resolved_import_count - .set(module.resolved_import_count.get() + 1); - } - } - - fn names_to_string(&self, names: &[Name]) -> String { - let mut first = true; - let mut result = String::new(); - for name in names { - if first { - first = false - } else { - result.push_str("::") - } - result.push_str(&token::get_name(*name)); - }; - result - } - - fn path_names_to_string(&self, path: &Path) -> String { - let names: Vec = path.segments - .iter() - .map(|seg| seg.identifier.name) - .collect(); - self.names_to_string(&names[..]) - } - - fn import_directive_subclass_to_string(&mut self, - subclass: ImportDirectiveSubclass) - -> String { - match subclass { - SingleImport(_, source) => { - token::get_name(source).to_string() - } - GlobImport => "*".to_string() - } - } - - fn import_path_to_string(&mut self, - names: &[Name], - subclass: ImportDirectiveSubclass) - -> String { - if names.is_empty() { - self.import_directive_subclass_to_string(subclass) - } else { - (format!("{}::{}", - self.names_to_string(names), - self.import_directive_subclass_to_string( - subclass))).to_string() - } - } - #[inline] fn record_import_use(&mut self, import_id: NodeId, name: Name) { if !self.make_glob_map { return; } if self.glob_map.contains_key(&import_id) { - self.glob_map[import_id].insert(name); + self.glob_map.get_mut(&import_id).unwrap().insert(name); return; } @@ -1152,102 +907,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - /// Attempts to resolve the given import. The return value indicates - /// failure if we're certain the name does not exist, indeterminate if we - /// don't know whether the name exists at the moment due to other - /// currently-unresolved imports, or success if we know the name exists. - /// If successful, the resolved bindings are written into the module. - fn resolve_import_for_module(&mut self, - module_: Rc, - import_directive: &ImportDirective) - -> ResolveResult<()> { - let mut resolution_result = Failed(None); - let module_path = &import_directive.module_path; - - debug!("(resolving import for module) resolving import `{}::...` in `{}`", - self.names_to_string(&module_path[..]), - self.module_to_string(&*module_)); - - // First, resolve the module path for the directive, if necessary. - let container = if module_path.len() == 0 { - // Use the crate root. - Some((self.graph_root.get_module(), LastMod(AllPublic))) - } else { - match self.resolve_module_path(module_.clone(), - &module_path[..], - DontUseLexicalScope, - import_directive.span, - ImportSearch) { - Failed(err) => { - resolution_result = Failed(err); - None - }, - Indeterminate => { - resolution_result = Indeterminate; - None - } - Success(container) => Some(container), - } - }; - - match container { - None => {} - Some((containing_module, lp)) => { - // We found the module that the target is contained - // within. Attempt to resolve the import within it. - - match import_directive.subclass { - SingleImport(target, source) => { - resolution_result = - self.resolve_single_import(&*module_, - containing_module, - target, - source, - import_directive, - lp); - } - GlobImport => { - resolution_result = - self.resolve_glob_import(&*module_, - containing_module, - import_directive, - lp); - } - } - } - } - - // Decrement the count of unresolved imports. - match resolution_result { - Success(()) => { - assert!(self.unresolved_imports >= 1); - self.unresolved_imports -= 1; - } - _ => { - // Nothing to do here; just return the error. - } - } - - // Decrement the count of unresolved globs if necessary. But only if - // the resolution result is indeterminate -- otherwise we'll stop - // processing imports here. (See the loop in - // resolve_imports_for_module.) - - if !resolution_result.indeterminate() { - match import_directive.subclass { - GlobImport => { - assert!(module_.glob_count.get() >= 1); - module_.glob_count.set(module_.glob_count.get() - 1); - } - SingleImport(..) => { - // Ignore. - } - } - } - - return resolution_result; - } - fn create_name_bindings_from_module(module: Rc) -> NameBindings { NameBindings { type_def: RefCell::new(Some(TypeNsDef { @@ -1260,626 +919,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_single_import(&mut self, - module_: &Module, - containing_module: Rc, - target: Name, - source: Name, - directive: &ImportDirective, - lp: LastPrivate) - -> ResolveResult<()> { - debug!("(resolving single import) resolving `{}` = `{}::{}` from \ - `{}` id {}, last private {:?}", - token::get_name(target), - self.module_to_string(&*containing_module), - token::get_name(source), - self.module_to_string(module_), - directive.id, - lp); - - let lp = match lp { - LastMod(lp) => lp, - LastImport {..} => { - self.session - .span_bug(directive.span, - "not expecting Import here, must be LastMod") - } - }; - - // We need to resolve both namespaces for this to succeed. - // - - let mut value_result = UnknownResult; - let mut type_result = UnknownResult; - - // Search for direct children of the containing module. - build_reduced_graph::populate_module_if_necessary(self, &containing_module); - - match containing_module.children.borrow().get(&source) { - None => { - // Continue. - } - Some(ref child_name_bindings) => { - if child_name_bindings.defined_in_namespace(ValueNS) { - debug!("(resolving single import) found value binding"); - value_result = BoundResult(containing_module.clone(), - (*child_name_bindings).clone()); - } - if child_name_bindings.defined_in_namespace(TypeNS) { - debug!("(resolving single import) found type binding"); - type_result = BoundResult(containing_module.clone(), - (*child_name_bindings).clone()); - } - } - } - - // Unless we managed to find a result in both namespaces (unlikely), - // search imports as well. - let mut value_used_reexport = false; - let mut type_used_reexport = false; - match (value_result.clone(), type_result.clone()) { - (BoundResult(..), BoundResult(..)) => {} // Continue. - _ => { - // If there is an unresolved glob at this point in the - // containing module, bail out. We don't know enough to be - // able to resolve this import. - - if containing_module.glob_count.get() > 0 { - debug!("(resolving single import) unresolved glob; \ - bailing out"); - return Indeterminate; - } - - // Now search the exported imports within the containing module. - match containing_module.import_resolutions.borrow().get(&source) { - None => { - debug!("(resolving single import) no import"); - // The containing module definitely doesn't have an - // exported import with the name in question. We can - // therefore accurately report that the names are - // unbound. - - if value_result.is_unknown() { - value_result = UnboundResult; - } - if type_result.is_unknown() { - type_result = UnboundResult; - } - } - Some(import_resolution) - if import_resolution.outstanding_references == 0 => { - - fn get_binding(this: &mut Resolver, - import_resolution: &ImportResolution, - namespace: Namespace, - source: &Name) - -> NamespaceResult { - - // Import resolutions must be declared with "pub" - // in order to be exported. - if !import_resolution.is_public { - return UnboundResult; - } - - match import_resolution. - target_for_namespace(namespace) { - None => { - return UnboundResult; - } - Some(Target { - target_module, - bindings, - shadowable: _ - }) => { - debug!("(resolving single import) found \ - import in ns {:?}", namespace); - let id = import_resolution.id(namespace); - // track used imports and extern crates as well - this.used_imports.insert((id, namespace)); - this.record_import_use(id, *source); - match target_module.def_id.get() { - Some(DefId{krate: kid, ..}) => { - this.used_crates.insert(kid); - }, - _ => {} - } - return BoundResult(target_module, bindings); - } - } - } - - // The name is an import which has been fully - // resolved. We can, therefore, just follow it. - if value_result.is_unknown() { - value_result = get_binding(self, - import_resolution, - ValueNS, - &source); - value_used_reexport = import_resolution.is_public; - } - if type_result.is_unknown() { - type_result = get_binding(self, - import_resolution, - TypeNS, - &source); - type_used_reexport = import_resolution.is_public; - } - - } - Some(_) => { - // If containing_module is the same module whose import we are resolving - // and there it has an unresolved import with the same name as `source`, - // then the user is actually trying to import an item that is declared - // in the same scope - // - // e.g - // use self::submodule; - // pub mod submodule; - // - // In this case we continue as if we resolved the import and let the - // check_for_conflicts_between_imports_and_items call below handle - // the conflict - match (module_.def_id.get(), containing_module.def_id.get()) { - (Some(id1), Some(id2)) if id1 == id2 => { - if value_result.is_unknown() { - value_result = UnboundResult; - } - if type_result.is_unknown() { - type_result = UnboundResult; - } - } - _ => { - // The import is unresolved. Bail out. - debug!("(resolving single import) unresolved import; \ - bailing out"); - return Indeterminate; - } - } - } - } - } - } - - // If we didn't find a result in the type namespace, search the - // external modules. - let mut value_used_public = false; - let mut type_used_public = false; - match type_result { - BoundResult(..) => {} - _ => { - match containing_module.external_module_children.borrow_mut() - .get(&source).cloned() { - None => {} // Continue. - Some(module) => { - debug!("(resolving single import) found external \ - module"); - // track the module as used. - match module.def_id.get() { - Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); }, - _ => {} - } - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module( - module)); - type_result = BoundResult(containing_module.clone(), - name_bindings); - type_used_public = true; - } - } - } - } - - // We've successfully resolved the import. Write the results in. - let mut import_resolutions = module_.import_resolutions.borrow_mut(); - let import_resolution = &mut (*import_resolutions)[target]; - { - let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| { - let namespace_name = match namespace { - TypeNS => "type", - ValueNS => "value", - }; - - match *result { - BoundResult(ref target_module, ref name_bindings) => { - debug!("(resolving single import) found {:?} target: {:?}", - namespace_name, - name_bindings.def_for_namespace(namespace)); - self.check_for_conflicting_import( - &import_resolution.target_for_namespace(namespace), - directive.span, - target, - namespace); - - self.check_that_import_is_importable( - &**name_bindings, - directive.span, - target, - namespace); - - let target = Some(Target::new(target_module.clone(), - name_bindings.clone(), - directive.shadowable)); - import_resolution.set_target_and_id(namespace, target, directive.id); - import_resolution.is_public = directive.is_public; - *used_public = name_bindings.defined_in_public_namespace(namespace); - } - UnboundResult => { /* Continue. */ } - UnknownResult => { - panic!("{:?} result should be known at this point", namespace_name); - } - } - }; - check_and_write_import(ValueNS, &value_result, &mut value_used_public); - check_and_write_import(TypeNS, &type_result, &mut type_used_public); - } - - self.check_for_conflicts_between_imports_and_items( - module_, - import_resolution, - directive.span, - target); - - if value_result.is_unbound() && type_result.is_unbound() { - let msg = format!("There is no `{}` in `{}`", - token::get_name(source), - self.module_to_string(&*containing_module)); - return Failed(Some((directive.span, msg))); - } - let value_used_public = value_used_reexport || value_used_public; - let type_used_public = type_used_reexport || type_used_public; - - assert!(import_resolution.outstanding_references >= 1); - import_resolution.outstanding_references -= 1; - - // record what this import resolves to for later uses in documentation, - // this may resolve to either a value or a type, but for documentation - // purposes it's good enough to just favor one over the other. - let value_private = match import_resolution.value_target { - Some(ref target) => { - let def = target.bindings.def_for_namespace(ValueNS).unwrap(); - self.def_map.borrow_mut().insert(directive.id, def); - let did = def.def_id(); - if value_used_public {Some(lp)} else {Some(DependsOn(did))} - }, - // AllPublic here and below is a dummy value, it should never be used because - // _exists is false. - None => None, - }; - let type_private = match import_resolution.type_target { - Some(ref target) => { - let def = target.bindings.def_for_namespace(TypeNS).unwrap(); - self.def_map.borrow_mut().insert(directive.id, def); - let did = def.def_id(); - if type_used_public {Some(lp)} else {Some(DependsOn(did))} - }, - None => None, - }; - - self.last_private.insert(directive.id, LastImport{value_priv: value_private, - value_used: Used, - type_priv: type_private, - type_used: Used}); - - debug!("(resolving single import) successfully resolved import"); - return Success(()); - } - - // Resolves a glob import. Note that this function cannot fail; it either - // succeeds or bails out (as importing * from an empty module or a module - // that exports nothing is valid). containing_module is the module we are - // actually importing, i.e., `foo` in `use foo::*`. - fn resolve_glob_import(&mut self, - module_: &Module, - containing_module: Rc, - import_directive: &ImportDirective, - lp: LastPrivate) - -> ResolveResult<()> { - let id = import_directive.id; - let is_public = import_directive.is_public; - - // This function works in a highly imperative manner; it eagerly adds - // everything it can to the list of import resolutions of the module - // node. - debug!("(resolving glob import) resolving glob import {}", id); - - // We must bail out if the node has unresolved imports of any kind - // (including globs). - if !(*containing_module).all_imports_resolved() { - debug!("(resolving glob import) target module has unresolved \ - imports; bailing out"); - return Indeterminate; - } - - assert_eq!(containing_module.glob_count.get(), 0); - - // Add all resolved imports from the containing module. - let import_resolutions = containing_module.import_resolutions.borrow(); - for (ident, target_import_resolution) in &*import_resolutions { - debug!("(resolving glob import) writing module resolution \ - {} into `{}`", - token::get_name(*ident), - self.module_to_string(module_)); - - if !target_import_resolution.is_public { - debug!("(resolving glob import) nevermind, just kidding"); - continue - } - - // Here we merge two import resolutions. - let mut import_resolutions = module_.import_resolutions.borrow_mut(); - match import_resolutions.get_mut(ident) { - Some(dest_import_resolution) => { - // Merge the two import resolutions at a finer-grained - // level. - - match target_import_resolution.value_target { - None => { - // Continue. - } - Some(ref value_target) => { - self.check_for_conflicting_import(&dest_import_resolution.value_target, - import_directive.span, - *ident, - ValueNS); - dest_import_resolution.value_target = Some(value_target.clone()); - } - } - match target_import_resolution.type_target { - None => { - // Continue. - } - Some(ref type_target) => { - self.check_for_conflicting_import(&dest_import_resolution.type_target, - import_directive.span, - *ident, - TypeNS); - dest_import_resolution.type_target = Some(type_target.clone()); - } - } - dest_import_resolution.is_public = is_public; - continue; - } - None => {} - } - - // Simple: just copy the old import resolution. - let mut new_import_resolution = ImportResolution::new(id, is_public); - new_import_resolution.value_target = - target_import_resolution.value_target.clone(); - new_import_resolution.type_target = - target_import_resolution.type_target.clone(); - - import_resolutions.insert(*ident, new_import_resolution); - } - - // Add all children from the containing module. - build_reduced_graph::populate_module_if_necessary(self, &containing_module); - - for (&name, name_bindings) in &*containing_module.children.borrow() { - self.merge_import_resolution(module_, - containing_module.clone(), - import_directive, - name, - name_bindings.clone()); - - } - - // Add external module children from the containing module. - for (&name, module) in &*containing_module.external_module_children.borrow() { - let name_bindings = - Rc::new(Resolver::create_name_bindings_from_module(module.clone())); - self.merge_import_resolution(module_, - containing_module.clone(), - import_directive, - name, - name_bindings); - } - - // Record the destination of this import - match containing_module.def_id.get() { - Some(did) => { - self.def_map.borrow_mut().insert(id, DefMod(did)); - self.last_private.insert(id, lp); - } - None => {} - } - - debug!("(resolving glob import) successfully resolved import"); - return Success(()); - } - - fn merge_import_resolution(&mut self, - module_: &Module, - containing_module: Rc, - import_directive: &ImportDirective, - name: Name, - name_bindings: Rc) { - let id = import_directive.id; - let is_public = import_directive.is_public; - - let mut import_resolutions = module_.import_resolutions.borrow_mut(); - let dest_import_resolution = import_resolutions.entry(name).get().unwrap_or_else( - |vacant_entry| { - // Create a new import resolution from this child. - vacant_entry.insert(ImportResolution::new(id, is_public)) - }); - - debug!("(resolving glob import) writing resolution `{}` in `{}` \ - to `{}`", - &token::get_name(name), - self.module_to_string(&*containing_module), - self.module_to_string(module_)); - - // Merge the child item into the import resolution. - { - let mut merge_child_item = |namespace| { - if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) { - let namespace_name = match namespace { - TypeNS => "type", - ValueNS => "value", - }; - debug!("(resolving glob import) ... for {} target", namespace_name); - if dest_import_resolution.shadowable(namespace) == Shadowable::Never { - let msg = format!("a {} named `{}` has already been imported \ - in this module", - namespace_name, - &token::get_name(name)); - span_err!(self.session, import_directive.span, E0251, "{}", msg); - } else { - let target = Target::new(containing_module.clone(), - name_bindings.clone(), - import_directive.shadowable); - dest_import_resolution.set_target_and_id(namespace, - Some(target), - id); - } - } - }; - merge_child_item(ValueNS); - merge_child_item(TypeNS); - } - - dest_import_resolution.is_public = is_public; - - self.check_for_conflicts_between_imports_and_items( - module_, - dest_import_resolution, - import_directive.span, - name); - } - - /// Checks that imported names and items don't have the same name. - fn check_for_conflicting_import(&mut self, - target: &Option, - import_span: Span, - name: Name, - namespace: Namespace) { - debug!("check_for_conflicting_import: {}; target exists: {}", - &token::get_name(name), - target.is_some()); - - match *target { - Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("a {} named `{}` has already been imported \ - in this module", - match namespace { - TypeNS => "type", - ValueNS => "value", - }, - &token::get_name(name)); - span_err!(self.session, import_span, E0252, "{}", &msg[..]); - } - Some(_) | None => {} - } - } - - /// Checks that an import is actually importable - fn check_that_import_is_importable(&mut self, - name_bindings: &NameBindings, - import_span: Span, - name: Name, - namespace: Namespace) { - if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) { - let msg = format!("`{}` is not directly importable", - token::get_name(name)); - span_err!(self.session, import_span, E0253, "{}", &msg[..]); - } - } - - /// Checks that imported names and items don't have the same name. - fn check_for_conflicts_between_imports_and_items(&mut self, - module: &Module, - import_resolution: - &ImportResolution, - import_span: Span, - name: Name) { - // First, check for conflicts between imports and `extern crate`s. - if module.external_module_children - .borrow() - .contains_key(&name) { - match import_resolution.type_target { - Some(ref target) if target.shadowable != Shadowable::Always => { - let msg = format!("import `{0}` conflicts with imported \ - crate in this module \ - (maybe you meant `use {0}::*`?)", - &token::get_name(name)); - span_err!(self.session, import_span, E0254, "{}", &msg[..]); - } - Some(_) | None => {} - } - } - - // Check for item conflicts. - let children = module.children.borrow(); - let name_bindings = match children.get(&name) { - None => { - // There can't be any conflicts. - return - } - Some(ref name_bindings) => (*name_bindings).clone(), - }; - - match import_resolution.value_target { - Some(ref target) if target.shadowable != Shadowable::Always => { - if let Some(ref value) = *name_bindings.value_def.borrow() { - let msg = format!("import `{}` conflicts with value \ - in this module", - &token::get_name(name)); - span_err!(self.session, import_span, E0255, "{}", &msg[..]); - if let Some(span) = value.value_span { - self.session.span_note(span, - "conflicting value here"); - } - } - } - Some(_) | None => {} - } - - match import_resolution.type_target { - Some(ref target) if target.shadowable != Shadowable::Always => { - if let Some(ref ty) = *name_bindings.type_def.borrow() { - match ty.module_def { - None => { - let msg = format!("import `{}` conflicts with type in \ - this module", - &token::get_name(name)); - span_err!(self.session, import_span, E0256, "{}", &msg[..]); - if let Some(span) = ty.type_span { - self.session.span_note(span, - "note conflicting type here") - } - } - Some(ref module_def) => { - match module_def.kind.get() { - ImplModuleKind => { - if let Some(span) = ty.type_span { - let msg = format!("inherent implementations \ - are only allowed on types \ - defined in the current module"); - span_err!(self.session, span, E0257, "{}", &msg[..]); - self.session.span_note(import_span, - "import from other module here") - } - } - _ => { - let msg = format!("import `{}` conflicts with existing \ - submodule", - &token::get_name(name)); - span_err!(self.session, import_span, E0258, "{}", &msg[..]); - if let Some(span) = ty.type_span { - self.session.span_note(span, - "note conflicting module here") - } - } - } - } - } - } - } - Some(_) | None => {} - } - } - /// Checks that the names of external crates don't collide with other /// external crates. fn check_for_conflicts_between_external_crates(&self, @@ -1912,7 +951,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_module_path_from_root(&mut self, module_: Rc, module_path: &[Name], - index: uint, + index: usize, span: Span, name_search_type: NameSearchType, lp: LastPrivate) @@ -1947,7 +986,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false) { Failed(None) => { let segment_name = token::get_name(name); - let module_name = self.module_to_string(&*search_module); + let module_name = module_to_string(&*search_module); let mut span = span; let msg = if "???" == &module_name[..] { span.hi = span.lo + Pos::from_usize(segment_name.len()); @@ -1955,10 +994,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match search_parent_externals(name, &self.current_module) { Some(module) => { - let path_str = self.names_to_string(module_path); - let target_mod_str = self.module_to_string(&*module); + let path_str = names_to_string(module_path); + let target_mod_str = module_to_string(&*module); let current_mod_str = - self.module_to_string(&*self.current_module); + module_to_string(&*self.current_module); let prefix = if target_mod_str == current_mod_str { "self::".to_string() @@ -2049,8 +1088,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { assert!(module_path_len > 0); debug!("(resolving module path for import) processing `{}` rooted at `{}`", - self.names_to_string(module_path), - self.module_to_string(&*module_)); + names_to_string(module_path), + module_to_string(&*module_)); // Resolve the module prefix, if any. let module_prefix_result = self.resolve_module_prefix(module_.clone(), @@ -2061,7 +1100,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let last_private; match module_prefix_result { Failed(None) => { - let mpath = self.names_to_string(module_path); + let mpath = names_to_string(module_path); let mpath = &mpath[..]; match mpath.rfind(':') { Some(idx) => { @@ -2144,7 +1183,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { namespace {:?} in `{}`", token::get_name(name), namespace, - self.module_to_string(&*module_)); + module_to_string(&*module_)); // The current module node is handled specially. First, check for // its immediate children. @@ -2226,7 +1265,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Failed(None); } TraitModuleKind | - ImplModuleKind | EnumModuleKind | TypeModuleKind | AnonymousModuleKind => { @@ -2247,7 +1285,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { true) { Failed(Some((span, msg))) => self.resolve_error(span, &format!("failed to resolve. {}", - msg)[]), + msg)), Failed(None) => (), // Continue up the search chain. Indeterminate => { // We couldn't see through the higher scope because of an @@ -2324,7 +1362,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match new_module.kind.get() { NormalModuleKind => return Some(new_module), TraitModuleKind | - ImplModuleKind | EnumModuleKind | TypeModuleKind | AnonymousModuleKind => module_ = new_module, @@ -2341,7 +1378,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match module_.kind.get() { NormalModuleKind => return module_, TraitModuleKind | - ImplModuleKind | EnumModuleKind | TypeModuleKind | AnonymousModuleKind => { @@ -2384,7 +1420,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { break } debug!("(resolving module prefix) resolving `super` at {}", - self.module_to_string(&*containing_module)); + module_to_string(&*containing_module)); match self.get_nearest_normal_module_parent(containing_module) { None => return Failed(None), Some(new_module) => { @@ -2395,7 +1431,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } debug!("(resolving module prefix) finished resolving prefix at {}", - self.module_to_string(&*containing_module)); + module_to_string(&*containing_module)); return Success(PrefixFound(containing_module, i)); } @@ -2415,7 +1451,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { -> ResolveResult<(Target, bool)> { debug!("(resolving name in module) resolving `{}` in `{}`", &token::get_name(name), - self.module_to_string(&*module_)); + module_to_string(&*module_)); // First, check the direct children of the module. build_reduced_graph::populate_module_if_necessary(self, &module_); @@ -2569,7 +1605,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { debug!("!!! (with scope) didn't find `{}` in `{}`", token::get_name(name), - self.module_to_string(&*orig_module)); + module_to_string(&*orig_module)); } Some(name_bindings) => { match (*name_bindings).get_module_if_available() { @@ -2577,7 +1613,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("!!! (with scope) didn't find module \ for `{}` in `{}`", token::get_name(name), - self.module_to_string(&*orig_module)); + module_to_string(&*orig_module)); } Some(module_) => { self.current_module = module_; @@ -2600,14 +1636,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { def_like: DefLike, span: Span) -> Option { - match def_like { - DlDef(d @ DefUpvar(..)) => { + let mut def = match def_like { + DlDef(def) => def, + _ => return Some(def_like) + }; + match def { + DefUpvar(..) => { self.session.span_bug(span, - &format!("unexpected {:?} in bindings", d)[]) + &format!("unexpected {:?} in bindings", def)) } - DlDef(d @ DefLocal(_)) => { - let node_id = d.def_id().node; - let mut def = d; + DefLocal(node_id) => { for rib in ribs { match rib.kind { NormalRibKind => { @@ -2631,39 +1669,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }.push(Freevar { def: prev_def, span: span }); seen.insert(node_id); } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, _, did, _) if { - self.def_map.borrow().get(&did.node).cloned() - == Some(DefTyParamBinder(item_id)) - } => {} // ok - DefSelfTy(did) if did == item_id => {} // ok - _ => { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. - - self.resolve_error( - span, - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - - return None; - } - } - } - ItemRibKind => { + ItemRibKind | MethodRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - self.resolve_error( - span, + self.resolve_error(span, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - + use the || { ... } closure form instead"); return None; } ConstantItemRibKind => { @@ -2671,42 +1684,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(span, "attempt to use a non-constant \ value in a constant"); - + return None; } } } - Some(DlDef(def)) } - DlDef(def @ DefTyParam(..)) | - DlDef(def @ DefSelfTy(..)) => { + DefTyParam(..) | DefSelfTy(_) => { for rib in ribs { match rib.kind { - NormalRibKind | ClosureRibKind(..) => { + NormalRibKind | MethodRibKind | ClosureRibKind(..) => { // Nothing to do. Continue. } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, _, did, _) if { - self.def_map.borrow().get(&did.node).cloned() - == Some(DefTyParamBinder(item_id)) - } => {} // ok - DefSelfTy(did) if did == item_id => {} // ok - - _ => { - // This was an attempt to use a type parameter outside - // its scope. - - self.resolve_error(span, - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); - - return None; - } - } - } ItemRibKind => { // This was an attempt to use a type parameter outside // its scope. @@ -2715,7 +1703,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "can't use type parameters from \ outer function; try using a local \ type parameter instead"); - return None; } ConstantItemRibKind => { @@ -2723,14 +1710,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(span, "cannot use an outer type \ parameter in this context"); - + return None; } } } - Some(DlDef(def)) } - _ => Some(def_like) + _ => {} } + Some(DlDef(def)) } /// Searches the current set of local scopes and @@ -2743,13 +1730,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // FIXME #4950: Try caching? for (i, rib) in ribs.iter().enumerate().rev() { - match rib.bindings.get(&name).cloned() { - Some(def_like) => { - return self.upvarify(&ribs[i + 1..], def_like, span); - } - None => { - // Continue. - } + if let Some(def_like) = rib.bindings.get(&name).cloned() { + return self.upvarify(&ribs[i + 1..], def_like, span); } } @@ -2797,56 +1779,32 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { token::get_name(name)); match item.node { - - // enum item: resolve all the variants' discrs, - // then resolve the ty params - ItemEnum(ref enum_def, ref generics) => { + ItemEnum(_, ref generics) | + ItemTy(_, ref generics) | + ItemStruct(_, ref generics) => { self.check_if_primitive_type_name(name, item.span); - for variant in &(*enum_def).variants { - if let Some(ref dis_expr) = variant.node.disr_expr { - // resolve the discriminator expr - // as a constant - self.with_constant_rib(|this| { - this.resolve_expr(&**dis_expr); - }); - } - } - - // n.b. the discr expr gets visited twice. - // but maybe it's okay since the first time will signal an - // error if there is one? -- tjc self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - item.id, ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - visit::walk_item(this, item); - }); + |this| visit::walk_item(this, item)); } - - ItemTy(_, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - + ItemFn(_, _, _, ref generics, _) => { self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - item.id, + FnSpace, ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - visit::walk_item(this, item); - }); + |this| visit::walk_item(this, item)); } + ItemDefaultImpl(_, ref trait_ref) => { + self.with_optional_trait_ref(Some(trait_ref), |_| {}); + } ItemImpl(_, _, ref generics, ref implemented_traits, ref self_type, ref impl_items) => { - self.resolve_implementation(item.id, - generics, + self.resolve_implementation(generics, implemented_traits, &**self_type, &impl_items[..]); @@ -2859,123 +1817,51 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut self_type_rib = Rib::new(ItemRibKind); // plain insert (no renaming, types are not currently hygienic....) - let name = self.type_self_name; + let name = special_names::type_self; self_type_rib.bindings.insert(name, DlDef(DefSelfTy(item.id))); self.type_ribs.push(self_type_rib); // Create a new rib for the trait-wide type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - item.id, NormalRibKind), |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); + this.visit_generics(generics); + visit::walk_ty_param_bounds_helper(this, bounds); - this.resolve_type_parameter_bounds(item.id, bounds, - TraitDerivation); - - for trait_item in &(*trait_items) { + for trait_item in trait_items { // Create a new rib for the trait_item-specific type // parameters. // // FIXME #4951: Do we need a node ID here? - match *trait_item { - ast::RequiredMethod(ref ty_m) => { - this.with_type_parameter_rib - (HasTypeParameters(&ty_m.generics, - FnSpace, - item.id, - MethodRibKind(item.id, RequiredMethod)), - |this| { - - // Resolve the method-specific type - // parameters. - this.resolve_type_parameters( - &ty_m.generics.ty_params); - this.resolve_where_clause(&ty_m.generics - .where_clause); - - for argument in &ty_m.decl.inputs { - this.resolve_type(&*argument.ty); - } - - if let SelfExplicit(ref typ, _) = ty_m.explicit_self.node { - this.resolve_type(&**typ) - } - - if let ast::Return(ref ret_ty) = ty_m.decl.output { - this.resolve_type(&**ret_ty); - } - }); - } - ast::ProvidedMethod(ref m) => { - this.resolve_method(MethodRibKind(item.id, - ProvidedMethod(m.id)), - &**m) - } - ast::TypeTraitItem(ref data) => { - this.resolve_type_parameter(&data.ty_param); - visit::walk_trait_item(this, trait_item); - } - } + let type_parameters = match trait_item.node { + ast::MethodTraitItem(ref sig, _) => { + HasTypeParameters(&sig.generics, + FnSpace, + MethodRibKind) + } + ast::TypeTraitItem(..) => { + this.check_if_primitive_type_name(trait_item.ident.name, + trait_item.span); + NoTypeParameters + } + }; + this.with_type_parameter_rib(type_parameters, |this| { + visit::walk_trait_item(this, trait_item) + }); } }); self.type_ribs.pop(); } - ItemStruct(ref struct_def, ref generics) => { - self.check_if_primitive_type_name(name, item.span); - - self.resolve_struct(item.id, - generics, - &struct_def.fields[]); - } - - ItemMod(ref module_) => { + ItemMod(_) | ItemForeignMod(_) => { self.with_scope(Some(name), |this| { - this.resolve_module(module_, item.span, name, - item.id); - }); - } - - ItemForeignMod(ref foreign_module) => { - self.with_scope(Some(name), |this| { - for foreign_item in &foreign_module.items { - match foreign_item.node { - ForeignItemFn(_, ref generics) => { - this.with_type_parameter_rib( - HasTypeParameters( - generics, FnSpace, foreign_item.id, - ItemRibKind), - |this| { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - visit::walk_foreign_item(this, &**foreign_item) - }); - } - ForeignItemStatic(..) => { - visit::walk_foreign_item(this, - &**foreign_item); - } - } - } + visit::walk_item(this, item); }); } - ItemFn(ref fn_decl, _, _, ref generics, ref block) => { - self.resolve_function(ItemRibKind, - Some(&**fn_decl), - HasTypeParameters - (generics, - FnSpace, - item.id, - ItemRibKind), - &**block); - } - ItemConst(..) | ItemStatic(..) => { self.with_constant_rib(|this| { visit::walk_item(this, item); @@ -2985,8 +1871,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ItemUse(ref view_path) => { // check for imports shadowing primitive types if let ast::ViewPathSimple(ident, _) = view_path.node { - match self.def_map.borrow().get(&item.id) { - Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => { + match self.def_map.borrow().get(&item.id).map(|d| d.full_def()) { + Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => { self.check_if_primitive_type_name(ident.name, item.span); } _ => {} @@ -3004,35 +1890,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { F: FnOnce(&mut Resolver), { match type_parameters { - HasTypeParameters(generics, space, node_id, rib_kind) => { + HasTypeParameters(generics, space, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = HashSet::new(); for (index, type_parameter) in generics.ty_params.iter().enumerate() { let name = type_parameter.ident.name; - debug!("with_type_parameter_rib: {} {}", node_id, - type_parameter.id); + debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { self.resolve_error(type_parameter.span, &format!("the name `{}` is already \ - used for a type \ - parameter in this type \ - parameter list", - token::get_name( - name))[]) + used for a type \ + parameter in this type \ + parameter list", + token::get_name(name))) } seen_bindings.insert(name); - let def_like = DlDef(DefTyParam(space, - index as u32, - local_def(type_parameter.id), - name)); - // Associate this type parameter with - // the item that bound it - self.record_def(type_parameter.id, - (DefTyParamBinder(node_id), LastMod(AllPublic))); // plain insert (no renaming) - function_type_rib.bindings.insert(name, def_like); + function_type_rib.bindings.insert(name, + DlDef(DefTyParam(space, + index as u32, + local_def(type_parameter.id), + name))); } self.type_ribs.push(function_type_rib); } @@ -3054,240 +1934,100 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { F: FnOnce(&mut Resolver), { self.label_ribs.push(Rib::new(NormalRibKind)); - f(self); - self.label_ribs.pop(); - } - - fn with_constant_rib(&mut self, f: F) where - F: FnOnce(&mut Resolver), - { - self.value_ribs.push(Rib::new(ConstantItemRibKind)); - self.type_ribs.push(Rib::new(ConstantItemRibKind)); - f(self); - self.type_ribs.pop(); - self.value_ribs.pop(); - } - - fn resolve_function(&mut self, - rib_kind: RibKind, - optional_declaration: Option<&FnDecl>, - type_parameters: TypeParameters, - block: &Block) { - // Create a value rib for the function. - let function_value_rib = Rib::new(rib_kind); - self.value_ribs.push(function_value_rib); - - // Create a label rib for the function. - let function_label_rib = Rib::new(rib_kind); - self.label_ribs.push(function_label_rib); - - // If this function has type parameters, add them now. - self.with_type_parameter_rib(type_parameters, |this| { - // Resolve the type parameters. - match type_parameters { - NoTypeParameters => { - // Continue. - } - HasTypeParameters(ref generics, _, _, _) => { - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - } - } - - // Add each argument to the rib. - match optional_declaration { - None => { - // Nothing to do. - } - Some(declaration) => { - let mut bindings_list = HashMap::new(); - for argument in &declaration.inputs { - this.resolve_pattern(&*argument.pat, - ArgumentIrrefutableMode, - &mut bindings_list); - - this.resolve_type(&*argument.ty); - - debug!("(resolving function) recorded argument"); - } - - if let ast::Return(ref ret_ty) = declaration.output { - this.resolve_type(&**ret_ty); - } - } - } - - // Resolve the function body. - this.resolve_block(&*block); - - debug!("(resolving function) leaving function"); - }); - + f(self); self.label_ribs.pop(); - self.value_ribs.pop(); } - fn resolve_type_parameters(&mut self, - type_parameters: &OwnedSlice) { - for type_parameter in &**type_parameters { - self.resolve_type_parameter(type_parameter); - } + fn with_constant_rib(&mut self, f: F) where + F: FnOnce(&mut Resolver), + { + self.value_ribs.push(Rib::new(ConstantItemRibKind)); + self.type_ribs.push(Rib::new(ConstantItemRibKind)); + f(self); + self.type_ribs.pop(); + self.value_ribs.pop(); } - fn resolve_type_parameter(&mut self, - type_parameter: &TyParam) { - self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); - for bound in &*type_parameter.bounds { - self.resolve_type_parameter_bound(type_parameter.id, bound, - TraitBoundingTypeParameter); - } - match type_parameter.default { - Some(ref ty) => self.resolve_type(&**ty), - None => {} - } - } + fn resolve_function(&mut self, + rib_kind: RibKind, + declaration: &FnDecl, + block: &Block) { + // Create a value rib for the function. + self.value_ribs.push(Rib::new(rib_kind)); - fn resolve_type_parameter_bounds(&mut self, - id: NodeId, - type_parameter_bounds: &OwnedSlice, - reference_type: TraitReferenceType) { - for type_parameter_bound in &**type_parameter_bounds { - self.resolve_type_parameter_bound(id, type_parameter_bound, - reference_type); - } - } + // Create a label rib for the function. + self.label_ribs.push(Rib::new(rib_kind)); - fn resolve_type_parameter_bound(&mut self, - id: NodeId, - type_parameter_bound: &TyParamBound, - reference_type: TraitReferenceType) { - match *type_parameter_bound { - TraitTyParamBound(ref tref, _) => { - self.resolve_poly_trait_reference(id, tref, reference_type) - } - RegionTyParamBound(..) => {} + // Add each argument to the rib. + let mut bindings_list = HashMap::new(); + for argument in &declaration.inputs { + self.resolve_pattern(&*argument.pat, + ArgumentIrrefutableMode, + &mut bindings_list); + + self.visit_ty(&*argument.ty); + + debug!("(resolving function) recorded argument"); } - } + visit::walk_fn_ret_ty(self, &declaration.output); + + // Resolve the function body. + self.visit_block(&*block); - fn resolve_poly_trait_reference(&mut self, - id: NodeId, - poly_trait_reference: &PolyTraitRef, - reference_type: TraitReferenceType) { - self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type) + debug!("(resolving function) leaving function"); + + self.label_ribs.pop(); + self.value_ribs.pop(); } fn resolve_trait_reference(&mut self, id: NodeId, - trait_reference: &TraitRef, - reference_type: TraitReferenceType) { - match self.resolve_path(id, &trait_reference.path, TypeNS, true) { - None => { - let path_str = self.path_names_to_string(&trait_reference.path); - let usage_str = match reference_type { - TraitBoundingTypeParameter => "bound type parameter with", - TraitImplementation => "implement", - TraitDerivation => "derive", - TraitObject => "reference", - TraitQPath => "extract an associated item from", - }; + trait_path: &Path, + path_depth: usize) + -> Result { + if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) { + if let DefTrait(_) = path_res.base_def { + debug!("(resolving trait) found trait def: {:?}", path_res); + Ok(path_res) + } else { + self.resolve_error(trait_path.span, + &format!("`{}` is not a trait", + path_names_to_string(trait_path, path_depth))); - let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_reference.path.span, &msg[..]); - } - Some(def) => { - match def { - (DefTrait(_), _) => { - debug!("(resolving trait) found trait def: {:?}", def); - self.record_def(trait_reference.ref_id, def); - } - (def, _) => { - self.resolve_error(trait_reference.path.span, - &format!("`{}` is not a trait", - self.path_names_to_string( - &trait_reference.path))[]); - - // If it's a typedef, give a note - if let DefTy(..) = def { - self.session.span_note( - trait_reference.path.span, - &format!("`type` aliases cannot be used for traits") - []); - } - } + // If it's a typedef, give a note + if let DefTy(..) = path_res.base_def { + self.session.span_note(trait_path.span, + "`type` aliases cannot be used for traits"); } + Err(()) } + } else { + let msg = format!("use of undeclared trait name `{}`", + path_names_to_string(trait_path, path_depth)); + self.resolve_error(trait_path.span, &msg); + Err(()) } } - fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) { - for predicate in &where_clause.predicates { + fn resolve_generics(&mut self, generics: &Generics) { + for type_parameter in &*generics.ty_params { + self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); + } + for predicate in &generics.where_clause.predicates { match predicate { - &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - self.resolve_type(&*bound_pred.bounded_ty); - - for bound in &*bound_pred.bounds { - self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound, - TraitBoundingTypeParameter); - } - } + &ast::WherePredicate::BoundPredicate(_) | &ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::EqPredicate(ref eq_pred) => { - match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) { - Some((def @ DefTyParam(..), last_private)) => { - self.record_def(eq_pred.id, (def, last_private)); - } - _ => { - self.resolve_error(eq_pred.path.span, - "undeclared associated type"); - } + let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true); + if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res { + self.record_def(eq_pred.id, path_res.unwrap()); + } else { + self.resolve_error(eq_pred.path.span, "undeclared associated type"); } - - self.resolve_type(&*eq_pred.ty); } } } - } - - fn resolve_struct(&mut self, - id: NodeId, - generics: &Generics, - fields: &[StructField]) { - // If applicable, create a rib for the type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - id, - ItemRibKind), - |this| { - // Resolve the type parameters. - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); - - // Resolve fields. - for field in fields { - this.resolve_type(&*field.node.ty); - } - }); - } - - // Does this really need to take a RibKind or is it always going - // to be NormalRibKind? - fn resolve_method(&mut self, - rib_kind: RibKind, - method: &ast::Method) { - let method_generics = method.pe_generics(); - let type_parameters = HasTypeParameters(method_generics, - FnSpace, - method.id, - rib_kind); - - if let SelfExplicit(ref typ, _) = method.pe_explicit_self().node { - self.resolve_type(&**typ); - } - - self.resolve_function(rib_kind, - Some(method.pe_fn_decl()), - type_parameters, - method.pe_body()); + visit::walk_generics(self, generics); } fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T where @@ -3300,25 +2040,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result } - fn with_optional_trait_ref(&mut self, id: NodeId, - opt_trait_ref: &Option, - f: F) -> T where - F: FnOnce(&mut Resolver) -> T, + fn with_optional_trait_ref(&mut self, + opt_trait_ref: Option<&TraitRef>, + f: F) + -> T + where F: FnOnce(&mut Resolver) -> T, { - let new_val = match *opt_trait_ref { - Some(ref trait_ref) => { - self.resolve_trait_reference(id, trait_ref, TraitImplementation); - - match self.def_map.borrow().get(&trait_ref.ref_id) { - Some(def) => { - let did = def.def_id(); - Some((did, trait_ref.clone())) - } - None => None + let mut new_val = None; + if let Some(trait_ref) = opt_trait_ref { + match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) { + Ok(path_res) => { + self.record_def(trait_ref.ref_id, path_res); + new_val = Some((path_res.base_def.def_id(), trait_ref.clone())); } + Err(_) => { /* error was already reported */ } } - None => None - }; + visit::walk_trait_ref(self, trait_ref); + } let original_trait_ref = replace(&mut self.current_trait_ref, new_val); let result = f(self); self.current_trait_ref = original_trait_ref; @@ -3326,121 +2064,82 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } fn resolve_implementation(&mut self, - id: NodeId, generics: &Generics, opt_trait_reference: &Option, self_type: &Ty, - impl_items: &[ImplItem]) { + impl_items: &[P]) { // If applicable, create a rib for the type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, - id, - NormalRibKind), + ItemRibKind), |this| { // Resolve the type parameters. - this.resolve_type_parameters(&generics.ty_params); - this.resolve_where_clause(&generics.where_clause); + this.visit_generics(generics); // Resolve the trait reference, if necessary. - this.with_optional_trait_ref(id, opt_trait_reference, |this| { + this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this| { // Resolve the self type. - this.resolve_type(self_type); + this.visit_ty(self_type); this.with_current_self_type(self_type, |this| { for impl_item in impl_items { - match *impl_item { - MethodImplItem(ref method) => { + match impl_item.node { + MethodImplItem(ref sig, _) => { // If this is a trait impl, ensure the method // exists in trait - this.check_trait_item(method.pe_ident().name, - method.span); + this.check_trait_item(impl_item.ident.name, + impl_item.span); // We also need a new scope for the method- // specific type parameters. - this.resolve_method( - MethodRibKind(id, ProvidedMethod(method.id)), - &**method); + let type_parameters = + HasTypeParameters(&sig.generics, + FnSpace, + MethodRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + visit::walk_impl_item(this, impl_item); + }); } - TypeImplItem(ref typedef) => { + TypeImplItem(ref ty) => { // If this is a trait impl, ensure the method // exists in trait - this.check_trait_item(typedef.ident.name, - typedef.span); + this.check_trait_item(impl_item.ident.name, + impl_item.span); - this.resolve_type(&*typedef.typ); + this.visit_ty(ty); } + ast::MacImplItem(_) => {} } } }); }); }); - - // Check that the current type is indeed a type, if we have an anonymous impl - if opt_trait_reference.is_none() { - match self_type.node { - // TyPath is the only thing that we handled in `build_reduced_graph_for_item`, - // where we created a module with the name of the type in order to implement - // an anonymous trait. In the case that the path does not resolve to an actual - // type, the result will be that the type name resolves to a module but not - // a type (shadowing any imported modules or types with this name), leading - // to weird user-visible bugs. So we ward this off here. See #15060. - TyPath(ref path, path_id) => { - match self.def_map.borrow().get(&path_id) { - // FIXME: should we catch other options and give more precise errors? - Some(&DefMod(_)) => { - self.resolve_error(path.span, "inherent implementations are not \ - allowed for types not defined in \ - the current module"); - } - _ => {} - } - } - _ => { } - } - } } fn check_trait_item(&self, name: Name, span: Span) { // If there is a TraitRef in scope for an impl, then the method must be in the trait. if let Some((did, ref trait_ref)) = self.current_trait_ref { - if self.trait_item_map.get(&(name, did)).is_none() { - let path_str = self.path_names_to_string(&trait_ref.path); + if !self.trait_item_map.contains_key(&(name, did)) { + let path_str = path_names_to_string(&trait_ref.path, 0); self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", token::get_name(name), - path_str)[]); + path_str)); } } } - fn resolve_module(&mut self, module: &Mod, _span: Span, - _name: Name, id: NodeId) { - // Write the implementations in scope into the module metadata. - debug!("(resolving module) resolving module ID {}", id); - visit::walk_mod(self, module); - } - fn resolve_local(&mut self, local: &Local) { // Resolve the type. - if let Some(ref ty) = local.ty { - self.resolve_type(&**ty); - } + visit::walk_ty_opt(self, &local.ty); - // Resolve the initializer, if necessary. - match local.init { - None => { - // Nothing to do. - } - Some(ref initializer) => { - self.resolve_expr(&**initializer); - } - } + // Resolve the initializer. + visit::walk_expr_opt(self, &local.init); // Resolve the pattern. - let mut bindings_list = HashMap::new(); self.resolve_pattern(&*local.pat, LocalIrrefutableMode, - &mut bindings_list); + &mut HashMap::new()); } // build a map from pattern identifiers to binding-info's. @@ -3477,7 +2176,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("variable `{}` from pattern #1 is \ not bound in pattern #{}", token::get_name(key), - i + 1)[]); + i + 1)); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { @@ -3486,7 +2185,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", token::get_name(key), - i + 1)[]); + i + 1)); } } } @@ -3499,7 +2198,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("variable `{}` from pattern {}{} is \ not bound in pattern {}1", token::get_name(key), - "#", i + 1, "#")[]); + "#", i + 1, "#")); } } } @@ -3518,7 +2217,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.check_consistent_bindings(arm); visit::walk_expr_opt(self, &arm.guard); - self.resolve_expr(&*arm.body); + self.visit_expr(&*arm.body); self.value_ribs.pop(); } @@ -3570,90 +2269,63 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_type(&mut self, ty: &Ty) { match ty.node { - // Like path expressions, the interpretation of path types depends - // on whether the path has multiple elements in it or not. + // `::a::b::c` is resolved by typeck alone. + TyPath(Some(ast::QSelf { position: 0, .. }), _) => {} + + TyPath(ref maybe_qself, ref path) => { + let max_assoc_types = if let Some(ref qself) = *maybe_qself { + // Make sure the trait is valid. + let _ = self.resolve_trait_reference(ty.id, path, 1); + path.segments.len() - qself.position + } else { + path.segments.len() + }; - TyPath(ref path, path_id) => { - // This is a path in the type namespace. Walk through scopes - // looking for it. - let mut result_def = None; - - // First, check to see whether the name is a primitive type. - if path.segments.len() == 1 { - let id = path.segments.last().unwrap().identifier; - - match self.primitive_type_table - .primitive_types - .get(&id.name) { - - Some(&primitive_type) => { - result_def = - Some((DefPrimTy(primitive_type), LastMod(AllPublic))); - - if path.segments[0].parameters.has_lifetimes() { - span_err!(self.session, path.span, E0157, - "lifetime parameters are not allowed on this type"); - } else if !path.segments[0].parameters.is_empty() { - span_err!(self.session, path.span, E0153, - "type parameters are not allowed on this type"); - } - } - None => { - // Continue. - } + let mut resolution = None; + for depth in 0..max_assoc_types { + self.with_no_errors(|this| { + resolution = this.resolve_path(ty.id, path, depth, TypeNS, true); + }); + if resolution.is_some() { + break; } } - - if let None = result_def { - result_def = self.resolve_path(ty.id, path, TypeNS, true); + if let Some(DefMod(_)) = resolution.map(|r| r.base_def) { + // A module is not a valid type. + resolution = None; } - match result_def { + // This is a path in the type namespace. Walk through scopes + // looking for it. + match resolution { Some(def) => { // Write the result into the def map. debug!("(resolving type) writing resolution for `{}` \ (id {}) = {:?}", - self.path_names_to_string(path), - path_id, def); - self.record_def(path_id, def); + path_names_to_string(path, 0), + ty.id, def); + self.record_def(ty.id, def); } None => { - let msg = format!("use of undeclared type name `{}`", - self.path_names_to_string(path)); - self.resolve_error(ty.span, &msg[..]); - } - } - } + // Keep reporting some errors even if they're ignored above. + self.resolve_path(ty.id, path, 0, TypeNS, true); - TyObjectSum(ref ty, ref bound_vec) => { - self.resolve_type(&**ty); - self.resolve_type_parameter_bounds(ty.id, bound_vec, - TraitBoundingTypeParameter); - } + let kind = if maybe_qself.is_some() { + "associated type" + } else { + "type name" + }; - TyQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath); - for ty in qpath.item_path.parameters.types() { - self.resolve_type(&**ty); - } - for binding in qpath.item_path.parameters.bindings() { - self.resolve_type(&*binding.ty); + let msg = format!("use of undeclared {} `{}`", kind, + path_names_to_string(path, 0)); + self.resolve_error(ty.span, &msg[..]); + } } } - - TyPolyTraitRef(ref bounds) => { - self.resolve_type_parameter_bounds( - ty.id, - bounds, - TraitObject); - visit::walk_ty(self, ty); - } - _ => { - // Just resolve embedded types. - visit::walk_ty(self, ty); - } + _ => {} } + // Resolve embedded types. + visit::walk_ty(self, ty); } fn resolve_pattern(&mut self, @@ -3680,7 +2352,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(ident); match self.resolve_bare_identifier_pattern(ident.name, pattern.span) { - FoundStructOrEnumVariant(ref def, lp) + FoundStructOrEnumVariant(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ struct or enum variant", @@ -3690,7 +2362,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "an enum variant"); - self.record_def(pattern.id, (def.clone(), lp)); + self.record_def(pattern.id, PathResolution { + base_def: def, + last_private: lp, + depth: 0 + }); } FoundStructOrEnumVariant(..) => { self.resolve_error( @@ -3698,9 +2374,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("declaration of `{}` shadows an enum \ variant or unit-like struct in \ scope", - token::get_name(renamed))[]); + token::get_name(renamed))); } - FoundConst(ref def, lp) if mode == RefutableMode => { + FoundConst(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ constant", token::get_name(renamed)); @@ -3709,7 +2385,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pattern, binding_mode, "a constant"); - self.record_def(pattern.id, (def.clone(), lp)); + self.record_def(pattern.id, PathResolution { + base_def: def, + last_private: lp, + depth: 0 + }); } FoundConst(..) => { self.resolve_error(pattern.span, @@ -3726,7 +2406,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // will be able to distinguish variants from // locals in patterns. - self.record_def(pattern.id, (def, LastMod(AllPublic))); + self.record_def(pattern.id, PathResolution { + base_def: def, + last_private: LastMod(AllPublic), + depth: 0 + }); // Add the binding to the local ribs, if it // doesn't already exist in the bindings list. (We @@ -3750,7 +2434,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { list", token::get_ident( ident)) - []) + ) } else if bindings_list.get(&renamed) == Some(&pat_id) { // Then this is a duplicate variable in the @@ -3759,7 +2443,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("identifier `{}` is bound \ more than once in the same \ pattern", - token::get_ident(ident))[]); + token::get_ident(ident))); } // Else, not bound in the same pattern: do // nothing. @@ -3769,50 +2453,34 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatEnum(ref path, _) => { // This must be an enum variant, struct or const. - match self.resolve_path(pat_id, path, ValueNS, false) { - Some(def @ (DefVariant(..), _)) | - Some(def @ (DefStruct(..), _)) | - Some(def @ (DefConst(..), _)) => { - self.record_def(pattern.id, def); - } - Some((DefStatic(..), _)) => { - self.resolve_error(path.span, - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); - } - Some(_) => { - self.resolve_error(path.span, - &format!("`{}` is not an enum variant, struct or const", - token::get_ident( - path.segments.last().unwrap().identifier))); - } - None => { - self.resolve_error(path.span, - &format!("unresolved enum variant, struct or const `{}`", - token::get_ident(path.segments.last().unwrap().identifier))); + if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) { + match path_res.base_def { + DefVariant(..) | DefStruct(..) | DefConst(..) => { + self.record_def(pattern.id, path_res); + } + DefStatic(..) => { + self.resolve_error(path.span, + "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); + } + _ => { + self.resolve_error(path.span, + &format!("`{}` is not an enum variant, struct or const", + token::get_ident( + path.segments.last().unwrap().identifier))); + } } + } else { + self.resolve_error(path.span, + &format!("unresolved enum variant, struct or const `{}`", + token::get_ident(path.segments.last().unwrap().identifier))); } - - // Check the types in the path pattern. - for ty in path.segments - .iter() - .flat_map(|s| s.parameters.types().into_iter()) { - self.resolve_type(&**ty); - } - } - - PatLit(ref expr) => { - self.resolve_expr(&**expr); - } - - PatRange(ref first_expr, ref last_expr) => { - self.resolve_expr(&**first_expr); - self.resolve_expr(&**last_expr); + visit::walk_path(self, path); } PatStruct(ref path, _, _) => { - match self.resolve_path(pat_id, path, TypeNS, false) { + match self.resolve_path(pat_id, path, 0, TypeNS, false) { Some(definition) => { self.record_def(pattern.id, definition); } @@ -3820,10 +2488,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path)); + path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } + visit::walk_path(self, path); + } + + PatLit(_) | PatRange(..) => { + visit::walk_pat(self, pattern); } _ => { @@ -3883,7 +2556,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match err { Some((span, msg)) => { self.resolve_error(span, &format!("failed to resolve: {}", - msg)[]); + msg)); } None => () } @@ -3897,98 +2570,74 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// If `check_ribs` is true, checks the local definitions first; i.e. /// doesn't skip straight to the containing module. + /// Skips `path_depth` trailing segments, which is also reflected in the + /// returned value. See `middle::def::PathResolution` for more info. fn resolve_path(&mut self, id: NodeId, path: &Path, + path_depth: usize, namespace: Namespace, - check_ribs: bool) -> Option<(Def, LastPrivate)> { - // First, resolve the types and associated type bindings. - for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) { - self.resolve_type(&**ty); - } - for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) { - self.resolve_type(&*binding.ty); - } + check_ribs: bool) -> Option { + let span = path.span; + let segments = &path.segments[..path.segments.len()-path_depth]; - // A special case for sugared associated type paths `T::A` where `T` is - // a type parameter and `A` is an associated type on some bound of `T`. - if namespace == TypeNS && path.segments.len() == 2 { - match self.resolve_identifier(path.segments[0].identifier, - TypeNS, - true, - path.span) { - Some((def, last_private)) => { - match def { - DefTyParam(_, _, did, _) => { - let def = DefAssociatedPath(TyParamProvenance::FromParam(did), - path.segments.last() - .unwrap().identifier); - return Some((def, last_private)); - } - DefSelfTy(nid) => { - let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)), - path.segments.last() - .unwrap().identifier); - return Some((def, last_private)); - } - _ => {} - } - } - _ => {} - } - } + let mk_res = |(def, lp)| PathResolution::new(def, lp, path_depth); if path.global { - return self.resolve_crate_relative_path(path, namespace); + let def = self.resolve_crate_relative_path(span, segments, namespace); + return def.map(mk_res); } // Try to find a path to an item in a module. let unqualified_def = - self.resolve_identifier(path.segments.last().unwrap().identifier, + self.resolve_identifier(segments.last().unwrap().identifier, namespace, check_ribs, - path.span); - - if path.segments.len() > 1 { - let def = self.resolve_module_relative_path(path, namespace); - match (def, unqualified_def) { - (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => { - self.session - .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, - id, - path.span, - "unnecessary qualification".to_string()); - } - _ => () - } + span); + + if segments.len() <= 1 { + return unqualified_def.map(mk_res); + } - return def; + let def = self.resolve_module_relative_path(span, segments, namespace); + match (def, unqualified_def) { + (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => { + self.session + .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, + id, span, + "unnecessary qualification".to_string()); + } + _ => {} } - return unqualified_def; + def.map(mk_res) } - // resolve a single identifier (used as a varref) + // Resolve a single identifier. fn resolve_identifier(&mut self, identifier: Ident, namespace: Namespace, check_ribs: bool, span: Span) -> Option<(Def, LastPrivate)> { + // First, check to see whether the name is a primitive type. + if namespace == TypeNS { + if let Some(&prim_ty) = self.primitive_type_table + .primitive_types + .get(&identifier.name) { + return Some((DefPrimTy(prim_ty), LastMod(AllPublic))); + } + } + if check_ribs { - match self.resolve_identifier_in_local_ribs(identifier, - namespace, - span) { - Some(def) => { - return Some((def, LastMod(AllPublic))); - } - None => { - // Continue. - } + if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, + namespace, + span) { + return Some((def, LastMod(AllPublic))); } } - return self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace); + self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace) } // FIXME #4952: Merge me with resolve_name_in_module? @@ -4005,8 +2654,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match child_name_bindings.def_for_namespace(namespace) { Some(def) => { // Found it. Stop the search here. - let p = child_name_bindings.defined_in_public_namespace( - namespace); + let p = child_name_bindings.defined_in_public_namespace(namespace); let lp = if p {LastMod(AllPublic)} else { LastMod(DependsOn(def.def_id())) }; @@ -4067,33 +2715,34 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // resolve a "module-relative" path, e.g. a::b::c fn resolve_module_relative_path(&mut self, - path: &Path, + span: Span, + segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = path.segments.init().iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.init().iter() + .map(|ps| ps.identifier.name) + .collect::>(); let containing_module; let last_private; - let module = self.current_module.clone(); - match self.resolve_module_path(module, + let current_module = self.current_module.clone(); + match self.resolve_module_path(current_module, &module_path[..], UseLexicalScope, - path.span, + span, PathSearch) { Failed(err) => { let (span, msg) = match err { Some((span, msg)) => (span, msg), None => { let msg = format!("Use of undeclared type or module `{}`", - self.names_to_string(&module_path)); - (path.span, msg) + names_to_string(&module_path)); + (span, msg) } }; self.resolve_error(span, &format!("failed to resolve. {}", - msg)[]); + msg)); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -4103,7 +2752,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = path.segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().identifier.name; let def = match self.resolve_definition_of_name_in_module(containing_module.clone(), name, namespace) { @@ -4124,12 +2773,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Invariant: This must be called only during main resolution, not during /// import resolution. fn resolve_crate_relative_path(&mut self, - path: &Path, + span: Span, + segments: &[ast::PathSegment], namespace: Namespace) -> Option<(Def, LastPrivate)> { - let module_path = path.segments.init().iter() - .map(|ps| ps.identifier.name) - .collect::>(); + let module_path = segments.init().iter() + .map(|ps| ps.identifier.name) + .collect::>(); let root_module = self.graph_root.get_module(); @@ -4138,7 +2788,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_module_path_from_root(root_module, &module_path[..], 0, - path.span, + span, PathSearch, LastMod(AllPublic)) { Failed(err) => { @@ -4146,13 +2796,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some((span, msg)) => (span, msg), None => { let msg = format!("Use of undeclared module `::{}`", - self.names_to_string(&module_path[..])); - (path.span, msg) + names_to_string(&module_path[..])); + (span, msg) } }; self.resolve_error(span, &format!("failed to resolve. {}", - msg)[]); + msg)); return None; } @@ -4166,7 +2816,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = path.segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().identifier.name; match self.resolve_definition_of_name_in_module(containing_module, name, namespace) { @@ -4193,20 +2843,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } TypeNS => { let name = ident.name; - self.search_ribs(&self.type_ribs[], name, span) + self.search_ribs(&self.type_ribs, name, span) } }; match search_result { Some(DlDef(def)) => { - debug!("(resolving path in local ribs) resolved `{}` to \ - local: {:?}", + debug!("(resolving path in local ribs) resolved `{}` to local: {:?}", token::get_ident(ident), def); - return Some(def); + Some(def) } Some(DlField) | Some(DlImpl(_)) | None => { - return None; + None } } } @@ -4245,15 +2894,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { panic!("unexpected indeterminate result"); } Failed(err) => { - match err { - Some((span, msg)) => - self.resolve_error(span, &format!("failed to resolve. {}", - msg)[]), - None => () - } - debug!("(resolving item path by identifier in lexical scope) \ failed to resolve {}", token::get_name(name)); + + if let Some((span, msg)) = err { + self.resolve_error(span, &format!("failed to resolve. {}", msg)) + } + return None; } } @@ -4278,7 +2925,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) -> Option<(Path, NodeId, FallbackChecks)> { match t.node { - TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)), + TyPath(None, ref path) => Some((path.clone(), t.id, allow)), TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics), TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow), // This doesn't handle the remaining `Ty` variants as they are not @@ -4305,16 +2952,35 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } else { match this.resolve_module_path(root, - &name_path[..], - UseLexicalScope, - span, - PathSearch) { + &name_path[..], + UseLexicalScope, + span, + PathSearch) { Success((module, _)) => Some(module), _ => None } } } + fn is_static_method(this: &Resolver, did: DefId) -> bool { + if did.krate == ast::LOCAL_CRATE { + let sig = match this.ast_map.get(did.node) { + ast_map::NodeTraitItem(trait_item) => match trait_item.node { + ast::MethodTraitItem(ref sig, _) => sig, + _ => return false + }, + ast_map::NodeImplItem(impl_item) => match impl_item.node { + ast::MethodImplItem(ref sig, _) => sig, + _ => return false + }, + _ => return false + }; + sig.explicit_self.node == ast::SelfStatic + } else { + csearch::is_static_method(&this.session.cstore, did) + } + } + let (path, node_id, allowed) = match self.current_self_type { Some(ref ty) => match extract_path_and_node_id(ty, Everything) { Some(x) => x, @@ -4325,10 +2991,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if allowed == Everything { // Look for a field with the same name in the current self_type. - match self.def_map.borrow().get(&node_id) { - Some(&DefTy(did, _)) - | Some(&DefStruct(did)) - | Some(&DefVariant(_, did, _)) => match self.structs.get(&did) { + match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) { + Some(DefTy(did, _)) | + Some(DefStruct(did)) | + Some(DefVariant(_, did, _)) => match self.structs.get(&did) { None => {} Some(fields) => { if fields.iter().any(|&field_name| name == field_name) { @@ -4343,52 +3009,41 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::>(); // Look for a method in the current self type's impl module. - match get_module(self, path.span, &name_path[..]) { - Some(module) => match module.children.borrow().get(&name) { - Some(binding) => { - let p_str = self.path_names_to_string(&path); - match binding.def_for_namespace(ValueNS) { - Some(DefStaticMethod(_, provenance)) => { - match provenance { - FromImpl(_) => return StaticMethod(p_str), - FromTrait(_) => unreachable!() - } - } - Some(DefMethod(_, None, _)) if allowed == Everything => return Method, - Some(DefMethod(_, Some(_), _)) => return TraitItem, - _ => () + if let Some(module) = get_module(self, path.span, &name_path) { + if let Some(binding) = module.children.borrow().get(&name) { + if let Some(DefMethod(did, _)) = binding.def_for_namespace(ValueNS) { + if is_static_method(self, did) { + return StaticMethod(path_names_to_string(&path, 0)) + } + if self.current_trait_ref.is_some() { + return TraitItem; + } else if allowed == Everything { + return Method; } } - None => {} - }, - None => {} + } } // Look for a method in the current trait. - match self.current_trait_ref { - Some((did, ref trait_ref)) => { - let path_str = self.path_names_to_string(&trait_ref.path); - - match self.trait_item_map.get(&(name, did)) { - Some(&StaticMethodTraitItemKind) => { - return TraitMethod(path_str) - } - Some(_) => return TraitItem, - None => {} + if let Some((trait_did, ref trait_ref)) = self.current_trait_ref { + if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) { + if is_static_method(self, did) { + return TraitMethod(path_names_to_string(&trait_ref.path, 0)); + } else { + return TraitItem; } } - None => {} } NoSuggestion } - fn find_best_match_for_name(&mut self, name: &str, max_distance: uint) + fn find_best_match_for_name(&mut self, name: &str, max_distance: usize) -> Option { let this = &mut *self; let mut maybes: Vec = Vec::new(); - let mut values: Vec = Vec::new(); + let mut values: Vec = Vec::new(); for rib in this.value_ribs.iter().rev() { for (&k, _) in &rib.bindings { @@ -4410,7 +3065,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { values[smallest] != usize::MAX && values[smallest] < name.len() + 2 && values[smallest] <= max_distance && - name != &maybes[smallest][] { + name != &maybes[smallest][..] { Some(maybes[smallest].to_string()) @@ -4427,118 +3082,149 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Next, resolve the node. match expr.node { - // The interpretation of paths depends on whether the path has - // multiple elements in it or not. - - ExprPath(_) | ExprQPath(_) => { - let mut path_from_qpath; - let path = match expr.node { - ExprPath(ref path) => path, - ExprQPath(ref qpath) => { - self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath); - path_from_qpath = qpath.trait_ref.path.clone(); - path_from_qpath.segments.push(qpath.item_path.clone()); - &path_from_qpath - } - _ => unreachable!() + // `::a::b::c` is resolved by typeck alone. + ExprPath(Some(ast::QSelf { position: 0, .. }), ref path) => { + let method_name = path.segments.last().unwrap().identifier.name; + let traits = self.search_for_traits_containing_method(method_name); + self.trait_map.insert(expr.id, traits); + visit::walk_expr(self, expr); + } + + ExprPath(ref maybe_qself, ref path) => { + let max_assoc_types = if let Some(ref qself) = *maybe_qself { + // Make sure the trait is valid. + let _ = self.resolve_trait_reference(expr.id, path, 1); + path.segments.len() - qself.position + } else { + path.segments.len() }; + + let mut resolution = self.with_no_errors(|this| { + this.resolve_path(expr.id, path, 0, ValueNS, true) + }); + for depth in 1..max_assoc_types { + if resolution.is_some() { + break; + } + self.with_no_errors(|this| { + resolution = this.resolve_path(expr.id, path, depth, TypeNS, true); + }); + } + if let Some(DefMod(_)) = resolution.map(|r| r.base_def) { + // A module is not a valid type or value. + resolution = None; + } + // This is a local path in the value namespace. Walk through // scopes looking for it. - match self.resolve_path(expr.id, path, ValueNS, true) { + if let Some(path_res) = resolution { // Check if struct variant - Some((DefVariant(_, _, true), _)) => { - let path_name = self.path_names_to_string(path); + if let DefVariant(_, _, true) = path_res.base_def { + let path_name = path_names_to_string(path, 0); self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ this expression \ uses it like a function name", path_name)); - self.session.span_help(expr.span, - &format!("Did you mean to write: \ - `{} {{ /* fields */ }}`?", - path_name)); - } - Some(def) => { + let msg = format!("Did you mean to write: \ + `{} {{ /* fields */ }}`?", + path_name); + if self.emit_errors { + self.session.fileline_help(expr.span, &msg); + } else { + self.session.span_help(expr.span, &msg); + } + } else { // Write the result into the def map. debug!("(resolving expr) resolved `{}`", - self.path_names_to_string(path)); + path_names_to_string(path, 0)); + + // Partial resolutions will need the set of traits in scope, + // so they can be completed during typeck. + if path_res.depth != 0 { + let method_name = path.segments.last().unwrap().identifier.name; + let traits = self.search_for_traits_containing_method(method_name); + self.trait_map.insert(expr.id, traits); + } - self.record_def(expr.id, def); + self.record_def(expr.id, path_res); } - None => { - // Be helpful if the name refers to a struct - // (The pattern matching def_tys where the id is in self.structs - // matches on regular structs while excluding tuple- and enum-like - // structs, which wouldn't result in this error.) - let path_name = self.path_names_to_string(path); - match self.with_no_errors(|this| - this.resolve_path(expr.id, path, TypeNS, false)) { - Some((DefTy(struct_id, _), _)) - if self.structs.contains_key(&struct_id) => { + } else { + // Be helpful if the name refers to a struct + // (The pattern matching def_tys where the id is in self.structs + // matches on regular structs while excluding tuple- and enum-like + // structs, which wouldn't result in this error.) + let path_name = path_names_to_string(path, 0); + let type_res = self.with_no_errors(|this| { + this.resolve_path(expr.id, path, 0, TypeNS, false) + }); + match type_res.map(|r| r.base_def) { + Some(DefTy(struct_id, _)) + if self.structs.contains_key(&struct_id) => { self.resolve_error(expr.span, - &format!("`{}` is a structure name, but \ - this expression \ - uses it like a function name", - path_name)); - - self.session.span_help(expr.span, - &format!("Did you mean to write: \ - `{} {{ /* fields */ }}`?", - path_name)); - - } - _ => { - let mut method_scope = false; - self.value_ribs.iter().rev().all(|rib| { - let res = match *rib { - Rib { bindings: _, kind: MethodRibKind(_, _) } => true, - Rib { bindings: _, kind: ItemRibKind } => false, - _ => return true, // Keep advancing - }; - - method_scope = res; - false // Stop advancing - }); - - if method_scope && &token::get_name(self.self_name)[] - == path_name { - self.resolve_error( - expr.span, - "`self` is not available \ - in a static method. Maybe a \ - `self` argument is missing?"); + &format!("`{}` is a structure name, but \ + this expression \ + uses it like a function name", + path_name)); + + let msg = format!("Did you mean to write: \ + `{} {{ /* fields */ }}`?", + path_name); + if self.emit_errors { + self.session.fileline_help(expr.span, &msg); } else { - let last_name = path.segments.last().unwrap().identifier.name; - let mut msg = match self.find_fallback_in_self_type(last_name) { - NoSuggestion => { - // limit search to 5 to reduce the number - // of stupid suggestions - self.find_best_match_for_name(&path_name, 5) - .map_or("".to_string(), - |x| format!("`{}`", x)) - } - Field => - format!("`self.{}`", path_name), - Method - | TraitItem => - format!("to call `self.{}`", path_name), - TraitMethod(path_str) - | StaticMethod(path_str) => - format!("to call `{}::{}`", path_str, path_name) - }; - - if msg.len() > 0 { - msg = format!(". Did you mean {}?", msg) - } + self.session.span_help(expr.span, &msg); + } + } + _ => { + // Keep reporting some errors even if they're ignored above. + self.resolve_path(expr.id, path, 0, ValueNS, true); + + let mut method_scope = false; + self.value_ribs.iter().rev().all(|rib| { + method_scope = match rib.kind { + MethodRibKind => true, + ItemRibKind | ConstantItemRibKind => false, + _ => return true, // Keep advancing + }; + false // Stop advancing + }); + if method_scope && + &token::get_name(special_names::self_)[..] == path_name { self.resolve_error( expr.span, - &format!("unresolved name `{}`{}", - path_name, - msg)); + "`self` is not available \ + in a static method. Maybe a \ + `self` argument is missing?"); + } else { + let last_name = path.segments.last().unwrap().identifier.name; + let mut msg = match self.find_fallback_in_self_type(last_name) { + NoSuggestion => { + // limit search to 5 to reduce the number + // of stupid suggestions + self.find_best_match_for_name(&path_name, 5) + .map_or("".to_string(), + |x| format!("`{}`", x)) + } + Field => format!("`self.{}`", path_name), + Method | + TraitItem => + format!("to call `self.{}`", path_name), + TraitMethod(path_str) | + StaticMethod(path_str) => + format!("to call `{}::{}`", path_str, path_name) + }; + + if msg.len() > 0 { + msg = format!(". Did you mean {}?", msg) } + + self.resolve_error( + expr.span, + &format!("unresolved name `{}`{}", + path_name, msg)); } } } @@ -4547,23 +3233,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { visit::walk_expr(self, expr); } - ExprClosure(_, ref fn_decl, ref block) => { - self.resolve_function(ClosureRibKind(expr.id), - Some(&**fn_decl), NoTypeParameters, - &**block); - } - ExprStruct(ref path, _, _) => { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. - match self.resolve_path(expr.id, path, TypeNS, false) { + match self.resolve_path(expr.id, path, 0, TypeNS, false) { Some(definition) => self.record_def(expr.id, definition), - result => { - debug!("(resolving expression) didn't find struct \ - def: {:?}", result); + None => { + debug!("(resolving expression) didn't find struct def",); let msg = format!("`{}` does not name a structure", - self.path_names_to_string(path)); + path_names_to_string(path, 0)); self.resolve_error(path.span, &msg[..]); } } @@ -4592,11 +3271,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error( expr.span, &format!("use of undeclared label `{}`", - token::get_ident(label))[]) + token::get_ident(label))) } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. - self.record_def(expr.id, (def, LastMod(AllPublic))) + self.record_def(expr.id, PathResolution { + base_def: def, + last_private: LastMod(AllPublic), + depth: 0 + }) } Some(_) => { self.session.span_bug(expr.span, @@ -4714,26 +3397,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { found_traits } - fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) { - debug!("(recording def) recording {:?} for {}, last private {:?}", - def, node_id, lp); - assert!(match lp {LastImport{..} => false, _ => true}, + fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { + debug!("(recording def) recording {:?} for {}", resolution, node_id); + assert!(match resolution.last_private {LastImport{..} => false, _ => true}, "Import should only be used for `use` directives"); - self.last_private.insert(node_id, lp); - 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 - Occupied(entry) => if def != *entry.get() { - self.session - .bug(&format!("node_id {} resolved first to {:?} and \ - then {:?}", - node_id, - *entry.get(), - def)[]); - }, - Vacant(entry) => { entry.insert(def); }, + if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) { + let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); + self.session.span_bug(span, &format!("path resolved multiple times \ + ({:?} before, {:?} now)", + prev_res, resolution)); } } @@ -4747,7 +3420,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.resolve_error(pat.span, &format!("cannot use `ref` binding mode \ with {}", - descr)[]); + descr)); } } } @@ -4759,36 +3432,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // hit. // - /// A somewhat inefficient routine to obtain the name of a module. - fn module_to_string(&self, module: &Module) -> String { - let mut names = Vec::new(); - - fn collect_mod(names: &mut Vec, module: &Module) { - match module.parent_link { - NoParentLink => {} - ModuleParentLink(ref module, name) => { - names.push(name); - collect_mod(names, &*module.upgrade().unwrap()); - } - BlockParentLink(ref module, _) => { - // danger, shouldn't be ident? - names.push(special_idents::opaque.name); - collect_mod(names, &*module.upgrade().unwrap()); - } - } - } - collect_mod(&mut names, module); - - if names.len() == 0 { - return "???".to_string(); - } - self.names_to_string(&names.into_iter().rev() - .collect::>()[]) - } - #[allow(dead_code)] // useful for debugging fn dump_module(&mut self, module_: Rc) { - debug!("Dump of module `{}`:", self.module_to_string(&*module_)); + debug!("Dump of module `{}`:", module_to_string(&*module_)); debug!("Children:"); build_reduced_graph::populate_module_if_necessary(self, &module_); @@ -4822,17 +3468,66 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } + +fn names_to_string(names: &[Name]) -> String { + let mut first = true; + let mut result = String::new(); + for name in names { + if first { + first = false + } else { + result.push_str("::") + } + result.push_str(&token::get_name(*name)); + }; + result +} + +fn path_names_to_string(path: &Path, depth: usize) -> String { + let names: Vec = path.segments[..path.segments.len()-depth] + .iter() + .map(|seg| seg.identifier.name) + .collect(); + names_to_string(&names[..]) +} + +/// A somewhat inefficient routine to obtain the name of a module. +fn module_to_string(module: &Module) -> String { + let mut names = Vec::new(); + + fn collect_mod(names: &mut Vec, module: &Module) { + match module.parent_link { + NoParentLink => {} + ModuleParentLink(ref module, name) => { + names.push(name); + collect_mod(names, &*module.upgrade().unwrap()); + } + BlockParentLink(ref module, _) => { + // danger, shouldn't be ident? + names.push(special_idents::opaque.name); + collect_mod(names, &*module.upgrade().unwrap()); + } + } + } + collect_mod(&mut names, module); + + if names.len() == 0 { + return "???".to_string(); + } + names_to_string(&names.into_iter().rev().collect::>()) +} + + pub struct CrateMap { pub def_map: DefMap, pub freevars: RefCell, pub export_map: ExportMap, pub trait_map: TraitMap, pub external_exports: ExternalExports, - pub last_private_map: LastPrivateMap, pub glob_map: Option } -#[derive(PartialEq,Copy)] +#[derive(PartialEq,Copy, Clone)] pub enum MakeGlobMap { Yes, No @@ -4850,7 +3545,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, build_reduced_graph::build_reduced_graph(&mut resolver, krate); session.abort_if_errors(); - resolver.resolve_imports(); + resolve_imports::resolve_imports(&mut resolver); session.abort_if_errors(); record_exports::record(&mut resolver); @@ -4867,7 +3562,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, export_map: resolver.export_map, trait_map: resolver.trait_map, external_exports: resolver.external_exports, - last_private_map: resolver.last_private, glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 5d025f40d3..e953b6398f 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -22,6 +22,7 @@ use {Module, NameBindings, Resolver}; use Namespace::{self, TypeNS, ValueNS}; use build_reduced_graph; +use module_to_string; use rustc::middle::def::Export; use syntax::ast; @@ -60,19 +61,19 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { // OK. Continue. debug!("(recording exports for module subtree) recording \ exports for local module `{}`", - self.module_to_string(&*module_)); + module_to_string(&*module_)); } None => { // Record exports for the root module. debug!("(recording exports for module subtree) recording \ exports for root module `{}`", - self.module_to_string(&*module_)); + module_to_string(&*module_)); } Some(_) => { // Bail out. debug!("(recording exports for module subtree) not recording \ exports for `{}`", - self.module_to_string(&*module_)); + module_to_string(&*module_)); return; } } @@ -133,13 +134,13 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { fn add_exports_for_module(&mut self, exports: &mut Vec, module_: &Module) { - for (name, importresolution) in &*module_.import_resolutions.borrow() { - if !importresolution.is_public { + for (name, import_resolution) in &*module_.import_resolutions.borrow() { + if !import_resolution.is_public { continue } let xs = [TypeNS, ValueNS]; for &ns in &xs { - match importresolution.target_for_namespace(ns) { + match import_resolution.target_for_namespace(ns) { Some(target) => { debug!("(computing exports) maybe export '{}'", token::get_name(*name)); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs new file mode 100644 index 0000000000..f1a8507b17 --- /dev/null +++ b/src/librustc_resolve/resolve_imports.rs @@ -0,0 +1,1018 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use self::ImportDirectiveSubclass::*; + +use {PUBLIC, IMPORTABLE}; +use Module; +use Namespace::{self, TypeNS, ValueNS}; +use NameBindings; +use NamespaceResult::{BoundResult, UnboundResult, UnknownResult}; +use NamespaceResult; +use NameSearchType; +use ResolveResult; +use Resolver; +use UseLexicalScopeFlag; +use {names_to_string, module_to_string}; + +use build_reduced_graph; + +use rustc::middle::def::*; +use rustc::middle::privacy::*; + +use syntax::ast::{DefId, NodeId, Name}; +use syntax::attr::AttrMetaMethods; +use syntax::parse::token; +use syntax::codemap::Span; + +use std::mem::replace; +use std::rc::Rc; + + +/// Contains data for specific types of import directives. +#[derive(Copy, Clone,Debug)] +pub enum ImportDirectiveSubclass { + SingleImport(Name /* target */, Name /* source */), + GlobImport +} + +/// Whether an import can be shadowed by another import. +#[derive(Debug,PartialEq,Clone,Copy)] +pub enum Shadowable { + Always, + Never +} + +/// One import directive. +#[derive(Debug)] +pub struct ImportDirective { + pub module_path: Vec, + pub subclass: ImportDirectiveSubclass, + pub span: Span, + pub id: NodeId, + pub is_public: bool, // see note in ImportResolution about how to use this + pub shadowable: Shadowable, +} + +impl ImportDirective { + pub fn new(module_path: Vec , + subclass: ImportDirectiveSubclass, + span: Span, + id: NodeId, + is_public: bool, + shadowable: Shadowable) + -> ImportDirective { + ImportDirective { + module_path: module_path, + subclass: subclass, + span: span, + id: id, + is_public: is_public, + shadowable: shadowable, + } + } +} + +/// The item that an import resolves to. +#[derive(Clone,Debug)] +pub struct Target { + pub target_module: Rc, + pub bindings: Rc, + pub shadowable: Shadowable, +} + +impl Target { + pub fn new(target_module: Rc, + bindings: Rc, + shadowable: Shadowable) + -> Target { + Target { + target_module: target_module, + bindings: bindings, + shadowable: shadowable, + } + } +} + +/// An ImportResolution represents a particular `use` directive. +#[derive(Debug)] +pub struct ImportResolution { + /// Whether this resolution came from a `use` or a `pub use`. Note that this + /// should *not* be used whenever resolution is being performed. Privacy + /// testing occurs during a later phase of compilation. + pub is_public: bool, + + // The number of outstanding references to this name. When this reaches + // zero, outside modules can count on the targets being correct. Before + // then, all bets are off; future imports could override this name. + // Note that this is usually either 0 or 1 - shadowing is forbidden the only + // way outstanding_references is > 1 in a legal program is if the name is + // used in both namespaces. + pub outstanding_references: usize, + + /// The value that this `use` directive names, if there is one. + pub value_target: Option, + /// The source node of the `use` directive leading to the value target + /// being non-none + pub value_id: NodeId, + + /// The type that this `use` directive names, if there is one. + pub type_target: Option, + /// The source node of the `use` directive leading to the type target + /// being non-none + pub type_id: NodeId, +} + +impl ImportResolution { + pub fn new(id: NodeId, is_public: bool) -> ImportResolution { + ImportResolution { + type_id: id, + value_id: id, + outstanding_references: 0, + value_target: None, + type_target: None, + is_public: is_public, + } + } + + pub fn target_for_namespace(&self, namespace: Namespace) + -> Option { + match namespace { + TypeNS => self.type_target.clone(), + ValueNS => self.value_target.clone(), + } + } + + pub fn id(&self, namespace: Namespace) -> NodeId { + match namespace { + TypeNS => self.type_id, + ValueNS => self.value_id, + } + } + + pub fn shadowable(&self, namespace: Namespace) -> Shadowable { + let target = self.target_for_namespace(namespace); + if target.is_none() { + return Shadowable::Always; + } + + target.unwrap().shadowable + } + + pub fn set_target_and_id(&mut self, + namespace: Namespace, + target: Option, + id: NodeId) { + match namespace { + TypeNS => { + self.type_target = target; + self.type_id = id; + } + ValueNS => { + self.value_target = target; + self.value_id = id; + } + } + } +} + + +struct ImportResolver<'a, 'b:'a, 'tcx:'b> { + resolver: &'a mut Resolver<'b, 'tcx> +} + +impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { + // Import resolution + // + // This is a fixed-point algorithm. We resolve imports until our efforts + // are stymied by an unresolved import; then we bail out of the current + // module and continue. We terminate successfully once no more imports + // remain or unsuccessfully when no forward progress in resolving imports + // is made. + + /// Resolves all imports for the crate. This method performs the fixed- + /// point iteration. + fn resolve_imports(&mut self) { + let mut i = 0; + let mut prev_unresolved_imports = 0; + loop { + debug!("(resolving imports) iteration {}, {} imports left", + i, self.resolver.unresolved_imports); + + let module_root = self.resolver.graph_root.get_module(); + self.resolve_imports_for_module_subtree(module_root.clone()); + + if self.resolver.unresolved_imports == 0 { + debug!("(resolving imports) success"); + break; + } + + if self.resolver.unresolved_imports == prev_unresolved_imports { + self.resolver.report_unresolved_imports(module_root); + break; + } + + i += 1; + prev_unresolved_imports = self.resolver.unresolved_imports; + } + } + + /// Attempts to resolve imports for the given module and all of its + /// submodules. + fn resolve_imports_for_module_subtree(&mut self, module_: Rc) { + debug!("(resolving imports for module subtree) resolving {}", + module_to_string(&*module_)); + let orig_module = replace(&mut self.resolver.current_module, module_.clone()); + self.resolve_imports_for_module(module_.clone()); + self.resolver.current_module = orig_module; + + build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); + for (_, child_node) in &*module_.children.borrow() { + match child_node.get_module_if_available() { + None => { + // Nothing to do. + } + Some(child_module) => { + self.resolve_imports_for_module_subtree(child_module); + } + } + } + + for (_, child_module) in &*module_.anonymous_children.borrow() { + self.resolve_imports_for_module_subtree(child_module.clone()); + } + } + + /// Attempts to resolve imports for the given module only. + fn resolve_imports_for_module(&mut self, module: Rc) { + if module.all_imports_resolved() { + debug!("(resolving imports for module) all imports resolved for \ + {}", + module_to_string(&*module)); + return; + } + + let imports = module.imports.borrow(); + let import_count = imports.len(); + while module.resolved_import_count.get() < import_count { + let import_index = module.resolved_import_count.get(); + let import_directive = &(*imports)[import_index]; + match self.resolve_import_for_module(module.clone(), + import_directive) { + ResolveResult::Failed(err) => { + let (span, help) = match err { + Some((span, msg)) => (span, format!(". {}", msg)), + None => (import_directive.span, String::new()) + }; + let msg = format!("unresolved import `{}`{}", + import_path_to_string( + &import_directive.module_path, + import_directive.subclass), + help); + self.resolver.resolve_error(span, &msg[..]); + } + ResolveResult::Indeterminate => break, // Bail out. We'll come around next time. + ResolveResult::Success(()) => () // Good. Continue. + } + + module.resolved_import_count + .set(module.resolved_import_count.get() + 1); + } + } + + /// Attempts to resolve the given import. The return value indicates + /// failure if we're certain the name does not exist, indeterminate if we + /// don't know whether the name exists at the moment due to other + /// currently-unresolved imports, or success if we know the name exists. + /// If successful, the resolved bindings are written into the module. + fn resolve_import_for_module(&mut self, + module_: Rc, + import_directive: &ImportDirective) + -> ResolveResult<()> { + let mut resolution_result = ResolveResult::Failed(None); + let module_path = &import_directive.module_path; + + debug!("(resolving import for module) resolving import `{}::...` in `{}`", + names_to_string(&module_path[..]), + module_to_string(&*module_)); + + // First, resolve the module path for the directive, if necessary. + let container = if module_path.len() == 0 { + // Use the crate root. + Some((self.resolver.graph_root.get_module(), LastMod(AllPublic))) + } else { + match self.resolver.resolve_module_path(module_.clone(), + &module_path[..], + UseLexicalScopeFlag::DontUseLexicalScope, + import_directive.span, + NameSearchType::ImportSearch) { + ResolveResult::Failed(err) => { + resolution_result = ResolveResult::Failed(err); + None + }, + ResolveResult::Indeterminate => { + resolution_result = ResolveResult::Indeterminate; + None + } + ResolveResult::Success(container) => Some(container), + } + }; + + match container { + None => {} + Some((containing_module, lp)) => { + // We found the module that the target is contained + // within. Attempt to resolve the import within it. + + match import_directive.subclass { + SingleImport(target, source) => { + resolution_result = + self.resolve_single_import(&module_, + containing_module, + target, + source, + import_directive, + lp); + } + GlobImport => { + resolution_result = + self.resolve_glob_import(&module_, + containing_module, + import_directive, + lp); + } + } + } + } + + // Decrement the count of unresolved imports. + match resolution_result { + ResolveResult::Success(()) => { + assert!(self.resolver.unresolved_imports >= 1); + self.resolver.unresolved_imports -= 1; + } + _ => { + // Nothing to do here; just return the error. + } + } + + // Decrement the count of unresolved globs if necessary. But only if + // the resolution result is indeterminate -- otherwise we'll stop + // processing imports here. (See the loop in + // resolve_imports_for_module). + + if !resolution_result.indeterminate() { + match import_directive.subclass { + GlobImport => { + assert!(module_.glob_count.get() >= 1); + module_.glob_count.set(module_.glob_count.get() - 1); + } + SingleImport(..) => { + // Ignore. + } + } + } + + return resolution_result; + } + + fn resolve_single_import(&mut self, + module_: &Module, + target_module: Rc, + target: Name, + source: Name, + directive: &ImportDirective, + lp: LastPrivate) + -> ResolveResult<()> { + debug!("(resolving single import) resolving `{}` = `{}::{}` from \ + `{}` id {}, last private {:?}", + token::get_name(target), + module_to_string(&*target_module), + token::get_name(source), + module_to_string(module_), + directive.id, + lp); + + let lp = match lp { + LastMod(lp) => lp, + LastImport {..} => { + self.resolver.session + .span_bug(directive.span, + "not expecting Import here, must be LastMod") + } + }; + + // We need to resolve both namespaces for this to succeed. + // + + let mut value_result = UnknownResult; + let mut type_result = UnknownResult; + + // Search for direct children of the containing module. + build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); + + match target_module.children.borrow().get(&source) { + None => { + // Continue. + } + Some(ref child_name_bindings) => { + // pub_err makes sure we don't give the same error twice. + let mut pub_err = false; + if child_name_bindings.defined_in_namespace(ValueNS) { + debug!("(resolving single import) found value binding"); + value_result = BoundResult(target_module.clone(), + (*child_name_bindings).clone()); + if directive.is_public && !child_name_bindings.is_public(ValueNS) { + let msg = format!("`{}` is private", token::get_name(source)); + span_err!(self.resolver.session, directive.span, E0364, "{}", &msg); + pub_err = true; + } + } + if child_name_bindings.defined_in_namespace(TypeNS) { + debug!("(resolving single import) found type binding"); + type_result = BoundResult(target_module.clone(), + (*child_name_bindings).clone()); + if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) { + let msg = format!("`{}` is private", token::get_name(source)); + span_err!(self.resolver.session, directive.span, E0365, "{}", &msg); + } + } + } + } + + // Unless we managed to find a result in both namespaces (unlikely), + // search imports as well. + let mut value_used_reexport = false; + let mut type_used_reexport = false; + match (value_result.clone(), type_result.clone()) { + (BoundResult(..), BoundResult(..)) => {} // Continue. + _ => { + // If there is an unresolved glob at this point in the + // containing module, bail out. We don't know enough to be + // able to resolve this import. + + if target_module.glob_count.get() > 0 { + debug!("(resolving single import) unresolved glob; \ + bailing out"); + return ResolveResult::Indeterminate; + } + + // Now search the exported imports within the containing module. + match target_module.import_resolutions.borrow().get(&source) { + None => { + debug!("(resolving single import) no import"); + // The containing module definitely doesn't have an + // exported import with the name in question. We can + // therefore accurately report that the names are + // unbound. + + if value_result.is_unknown() { + value_result = UnboundResult; + } + if type_result.is_unknown() { + type_result = UnboundResult; + } + } + Some(import_resolution) + if import_resolution.outstanding_references == 0 => { + + fn get_binding(this: &mut Resolver, + import_resolution: &ImportResolution, + namespace: Namespace, + source: &Name) + -> NamespaceResult { + + // Import resolutions must be declared with "pub" + // in order to be exported. + if !import_resolution.is_public { + return UnboundResult; + } + + match import_resolution.target_for_namespace(namespace) { + None => { + return UnboundResult; + } + Some(Target { + target_module, + bindings, + shadowable: _ + }) => { + debug!("(resolving single import) found \ + import in ns {:?}", namespace); + let id = import_resolution.id(namespace); + // track used imports and extern crates as well + this.used_imports.insert((id, namespace)); + this.record_import_use(id, *source); + match target_module.def_id.get() { + Some(DefId{krate: kid, ..}) => { + this.used_crates.insert(kid); + }, + _ => {} + } + return BoundResult(target_module, bindings); + } + } + } + + // The name is an import which has been fully + // resolved. We can, therefore, just follow it. + if value_result.is_unknown() { + value_result = get_binding(self.resolver, + import_resolution, + ValueNS, + &source); + value_used_reexport = import_resolution.is_public; + } + if type_result.is_unknown() { + type_result = get_binding(self.resolver, + import_resolution, + TypeNS, + &source); + type_used_reexport = import_resolution.is_public; + } + + } + Some(_) => { + // If target_module is the same module whose import we are resolving + // and there it has an unresolved import with the same name as `source`, + // then the user is actually trying to import an item that is declared + // in the same scope + // + // e.g + // use self::submodule; + // pub mod submodule; + // + // In this case we continue as if we resolved the import and let the + // check_for_conflicts_between_imports_and_items call below handle + // the conflict + match (module_.def_id.get(), target_module.def_id.get()) { + (Some(id1), Some(id2)) if id1 == id2 => { + if value_result.is_unknown() { + value_result = UnboundResult; + } + if type_result.is_unknown() { + type_result = UnboundResult; + } + } + _ => { + // The import is unresolved. Bail out. + debug!("(resolving single import) unresolved import; \ + bailing out"); + return ResolveResult::Indeterminate; + } + } + } + } + } + } + + let mut value_used_public = false; + let mut type_used_public = false; + + // If we didn't find a result in the type namespace, search the + // external modules. + match type_result { + BoundResult(..) => {} + _ => { + match target_module.external_module_children.borrow_mut().get(&source).cloned() { + None => {} // Continue. + Some(module) => { + debug!("(resolving single import) found external module"); + // track the module as used. + match module.def_id.get() { + Some(DefId{krate: kid, ..}) => { + self.resolver.used_crates.insert(kid); + } + _ => {} + } + let name_bindings = + Rc::new(Resolver::create_name_bindings_from_module(module)); + type_result = BoundResult(target_module.clone(), name_bindings); + type_used_public = true; + } + } + } + } + + // We've successfully resolved the import. Write the results in. + let mut import_resolutions = module_.import_resolutions.borrow_mut(); + let import_resolution = import_resolutions.get_mut(&target).unwrap(); + + { + let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| { + let namespace_name = match namespace { + TypeNS => "type", + ValueNS => "value", + }; + + match *result { + BoundResult(ref target_module, ref name_bindings) => { + debug!("(resolving single import) found {:?} target: {:?}", + namespace_name, + name_bindings.def_for_namespace(namespace)); + self.check_for_conflicting_import( + &import_resolution.target_for_namespace(namespace), + directive.span, + target, + namespace); + + self.check_that_import_is_importable( + &**name_bindings, + directive.span, + target, + namespace); + + let target = Some(Target::new(target_module.clone(), + name_bindings.clone(), + directive.shadowable)); + import_resolution.set_target_and_id(namespace, target, directive.id); + import_resolution.is_public = directive.is_public; + *used_public = name_bindings.defined_in_public_namespace(namespace); + } + UnboundResult => { /* Continue. */ } + UnknownResult => { + panic!("{:?} result should be known at this point", namespace_name); + } + } + }; + check_and_write_import(ValueNS, &value_result, &mut value_used_public); + check_and_write_import(TypeNS, &type_result, &mut type_used_public); + } + + self.check_for_conflicts_between_imports_and_items( + module_, + import_resolution, + directive.span, + target); + + if value_result.is_unbound() && type_result.is_unbound() { + let msg = format!("There is no `{}` in `{}`", + token::get_name(source), + module_to_string(&target_module)); + return ResolveResult::Failed(Some((directive.span, msg))); + } + let value_used_public = value_used_reexport || value_used_public; + let type_used_public = type_used_reexport || type_used_public; + + assert!(import_resolution.outstanding_references >= 1); + import_resolution.outstanding_references -= 1; + + // Record what this import resolves to for later uses in documentation, + // this may resolve to either a value or a type, but for documentation + // purposes it's good enough to just favor one over the other. + let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| { + let def = target.bindings.def_for_namespace(ValueNS).unwrap(); + (def, if value_used_public { lp } else { DependsOn(def.def_id()) }) + }); + let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| { + let def = target.bindings.def_for_namespace(TypeNS).unwrap(); + (def, if type_used_public { lp } else { DependsOn(def.def_id()) }) + }); + + let import_lp = LastImport { + value_priv: value_def_and_priv.map(|(_, p)| p), + value_used: Used, + type_priv: type_def_and_priv.map(|(_, p)| p), + type_used: Used + }; + + if let Some((def, _)) = value_def_and_priv { + self.resolver.def_map.borrow_mut().insert(directive.id, PathResolution { + base_def: def, + last_private: import_lp, + depth: 0 + }); + } + if let Some((def, _)) = type_def_and_priv { + self.resolver.def_map.borrow_mut().insert(directive.id, PathResolution { + base_def: def, + last_private: import_lp, + depth: 0 + }); + } + + debug!("(resolving single import) successfully resolved import"); + return ResolveResult::Success(()); + } + + // Resolves a glob import. Note that this function cannot fail; it either + // succeeds or bails out (as importing * from an empty module or a module + // that exports nothing is valid). target_module is the module we are + // actually importing, i.e., `foo` in `use foo::*`. + fn resolve_glob_import(&mut self, + module_: &Module, + target_module: Rc, + import_directive: &ImportDirective, + lp: LastPrivate) + -> ResolveResult<()> { + let id = import_directive.id; + let is_public = import_directive.is_public; + + // This function works in a highly imperative manner; it eagerly adds + // everything it can to the list of import resolutions of the module + // node. + debug!("(resolving glob import) resolving glob import {}", id); + + // We must bail out if the node has unresolved imports of any kind + // (including globs). + if !(*target_module).all_imports_resolved() { + debug!("(resolving glob import) target module has unresolved \ + imports; bailing out"); + return ResolveResult::Indeterminate; + } + + assert_eq!(target_module.glob_count.get(), 0); + + // Add all resolved imports from the containing module. + let import_resolutions = target_module.import_resolutions.borrow(); + for (ident, target_import_resolution) in &*import_resolutions { + debug!("(resolving glob import) writing module resolution \ + {} into `{}`", + token::get_name(*ident), + module_to_string(module_)); + + if !target_import_resolution.is_public { + debug!("(resolving glob import) nevermind, just kidding"); + continue + } + + // Here we merge two import resolutions. + let mut import_resolutions = module_.import_resolutions.borrow_mut(); + match import_resolutions.get_mut(ident) { + Some(dest_import_resolution) => { + // Merge the two import resolutions at a finer-grained + // level. + + match target_import_resolution.value_target { + None => { + // Continue. + } + Some(ref value_target) => { + self.check_for_conflicting_import(&dest_import_resolution.value_target, + import_directive.span, + *ident, + ValueNS); + dest_import_resolution.value_target = Some(value_target.clone()); + } + } + match target_import_resolution.type_target { + None => { + // Continue. + } + Some(ref type_target) => { + self.check_for_conflicting_import(&dest_import_resolution.type_target, + import_directive.span, + *ident, + TypeNS); + dest_import_resolution.type_target = Some(type_target.clone()); + } + } + dest_import_resolution.is_public = is_public; + continue; + } + None => {} + } + + // Simple: just copy the old import resolution. + let mut new_import_resolution = ImportResolution::new(id, is_public); + new_import_resolution.value_target = + target_import_resolution.value_target.clone(); + new_import_resolution.type_target = + target_import_resolution.type_target.clone(); + + import_resolutions.insert(*ident, new_import_resolution); + } + + // Add all children from the containing module. + build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); + + for (&name, name_bindings) in &*target_module.children.borrow() { + self.merge_import_resolution(module_, + target_module.clone(), + import_directive, + name, + name_bindings.clone()); + + } + + // Add external module children from the containing module. + for (&name, module) in &*target_module.external_module_children.borrow() { + let name_bindings = + Rc::new(Resolver::create_name_bindings_from_module(module.clone())); + self.merge_import_resolution(module_, + target_module.clone(), + import_directive, + name, + name_bindings); + } + + // Record the destination of this import + if let Some(did) = target_module.def_id.get() { + self.resolver.def_map.borrow_mut().insert(id, PathResolution { + base_def: DefMod(did), + last_private: lp, + depth: 0 + }); + } + + debug!("(resolving glob import) successfully resolved import"); + return ResolveResult::Success(()); + } + + fn merge_import_resolution(&mut self, + module_: &Module, + containing_module: Rc, + import_directive: &ImportDirective, + name: Name, + name_bindings: Rc) { + let id = import_directive.id; + let is_public = import_directive.is_public; + + let mut import_resolutions = module_.import_resolutions.borrow_mut(); + let dest_import_resolution = import_resolutions.entry(name) + .or_insert_with(|| ImportResolution::new(id, is_public)); + + debug!("(resolving glob import) writing resolution `{}` in `{}` \ + to `{}`", + &token::get_name(name), + module_to_string(&*containing_module), + module_to_string(module_)); + + // Merge the child item into the import resolution. + { + let mut merge_child_item = |namespace| { + if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) { + let namespace_name = match namespace { + TypeNS => "type", + ValueNS => "value", + }; + debug!("(resolving glob import) ... for {} target", namespace_name); + if dest_import_resolution.shadowable(namespace) == Shadowable::Never { + let msg = format!("a {} named `{}` has already been imported \ + in this module", + namespace_name, + &token::get_name(name)); + span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg); + } else { + let target = Target::new(containing_module.clone(), + name_bindings.clone(), + import_directive.shadowable); + dest_import_resolution.set_target_and_id(namespace, + Some(target), + id); + } + } + }; + merge_child_item(ValueNS); + merge_child_item(TypeNS); + } + + dest_import_resolution.is_public = is_public; + + self.check_for_conflicts_between_imports_and_items( + module_, + dest_import_resolution, + import_directive.span, + name); + } + + /// Checks that imported names and items don't have the same name. + fn check_for_conflicting_import(&mut self, + target: &Option, + import_span: Span, + name: Name, + namespace: Namespace) { + debug!("check_for_conflicting_import: {}; target exists: {}", + &token::get_name(name), + target.is_some()); + + match *target { + Some(ref target) if target.shadowable != Shadowable::Always => { + let msg = format!("a {} named `{}` has already been imported \ + in this module", + match namespace { + TypeNS => "type", + ValueNS => "value", + }, + &token::get_name(name)); + span_err!(self.resolver.session, import_span, E0252, "{}", &msg[..]); + } + Some(_) | None => {} + } + } + + /// Checks that an import is actually importable + fn check_that_import_is_importable(&mut self, + name_bindings: &NameBindings, + import_span: Span, + name: Name, + namespace: Namespace) { + if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) { + let msg = format!("`{}` is not directly importable", + token::get_name(name)); + span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]); + } + } + + /// Checks that imported names and items don't have the same name. + fn check_for_conflicts_between_imports_and_items(&mut self, + module: &Module, + import_resolution: + &ImportResolution, + import_span: Span, + name: Name) { + // First, check for conflicts between imports and `extern crate`s. + if module.external_module_children + .borrow() + .contains_key(&name) { + match import_resolution.type_target { + Some(ref target) if target.shadowable != Shadowable::Always => { + let msg = format!("import `{0}` conflicts with imported \ + crate in this module \ + (maybe you meant `use {0}::*`?)", + &token::get_name(name)); + span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); + } + Some(_) | None => {} + } + } + + // Check for item conflicts. + let children = module.children.borrow(); + let name_bindings = match children.get(&name) { + None => { + // There can't be any conflicts. + return + } + Some(ref name_bindings) => (*name_bindings).clone(), + }; + + match import_resolution.value_target { + Some(ref target) if target.shadowable != Shadowable::Always => { + if let Some(ref value) = *name_bindings.value_def.borrow() { + span_err!(self.resolver.session, import_span, E0255, + "import `{}` conflicts with value in this module", + &token::get_name(name)); + if let Some(span) = value.value_span { + self.resolver.session.span_note(span, "conflicting value here"); + } + } + } + Some(_) | None => {} + } + + match import_resolution.type_target { + Some(ref target) if target.shadowable != Shadowable::Always => { + if let Some(ref ty) = *name_bindings.type_def.borrow() { + let (what, note) = if ty.module_def.is_some() { + ("existing submodule", "note conflicting module here") + } else { + ("type in this module", "note conflicting type here") + }; + span_err!(self.resolver.session, import_span, E0256, + "import `{}` conflicts with {}", + &token::get_name(name), what); + if let Some(span) = ty.type_span { + self.resolver.session.span_note(span, note); + } + } + } + Some(_) | None => {} + } + } +} + +fn import_path_to_string(names: &[Name], + subclass: ImportDirectiveSubclass) + -> String { + if names.is_empty() { + import_directive_subclass_to_string(subclass) + } else { + (format!("{}::{}", + names_to_string(names), + import_directive_subclass_to_string(subclass))).to_string() + } +} + +fn import_directive_subclass_to_string(subclass: ImportDirectiveSubclass) -> String { + match subclass { + SingleImport(_, source) => { + token::get_name(source).to_string() + } + GlobImport => "*".to_string() + } +} + +pub fn resolve_imports(resolver: &mut Resolver) { + let mut import_resolver = ImportResolver { + resolver: resolver, + }; + import_resolver.resolve_imports(); +} diff --git a/src/librustc_trans/README.txt b/src/librustc_trans/README.txt index 3904db4433..1f416d5404 100644 --- a/src/librustc_trans/README.txt +++ b/src/librustc_trans/README.txt @@ -1 +1 @@ -See the README.txt in ../librustc. +See the README.md in ../librustc. diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index ef849bb3dc..ad77735189 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -26,13 +26,15 @@ use middle::ty::{self, Ty}; use util::common::time; use util::ppaux; use util::sha2::{Digest, Sha256}; +use rustc_back::tempdir::TempDir; -use std::old_io::fs::PathExtensions; -use std::old_io::{fs, TempDir, Command}; -use std::old_io; +use std::ffi::OsString; +use std::fs::{self, PathExt}; +use std::io::{self, Read, Write}; use std::mem; +use std::path::{Path, PathBuf}; +use std::process::Command; use std::str; -use std::string::String; use flate; use serialize::hex::ToHex; use syntax::ast; @@ -58,16 +60,16 @@ pub const RLIB_BYTECODE_OBJECT_MAGIC: &'static [u8] = b"RUST_OBJECT"; pub const RLIB_BYTECODE_OBJECT_VERSION: u32 = 1; // The offset in bytes the bytecode object format version number can be found at -pub const RLIB_BYTECODE_OBJECT_VERSION_OFFSET: uint = 11; +pub const RLIB_BYTECODE_OBJECT_VERSION_OFFSET: usize = 11; // The offset in bytes the size of the compressed bytecode can be found at in // format version 1 -pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: uint = +pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize = RLIB_BYTECODE_OBJECT_VERSION_OFFSET + 4; // The offset in bytes the compressed LLVM bytecode can be found at in format // version 1 -pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: uint = +pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize = RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8; @@ -156,12 +158,20 @@ pub fn find_crate_name(sess: Option<&Session>, return validate(s.to_string(), Some(attr.span)); } if let Input::File(ref path) = *input { - if let Some(s) = path.filestem_str() { - return validate(s.to_string(), None); + if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { + if s.starts_with("-") { + let msg = format!("crate names cannot start with a `-`, but \ + `{}` has a leading hyphen", s); + if let Some(sess) = sess { + sess.err(&msg); + } + } else { + return validate(s.replace("-", "_"), None); + } } } - "rust-out".to_string() + "rust_out".to_string() } pub fn build_link_meta(sess: &Session, krate: &ast::Crate, @@ -191,17 +201,17 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>, // to be independent of one another in the crate. symbol_hasher.reset(); - symbol_hasher.input_str(&link_meta.crate_name[]); + symbol_hasher.input_str(&link_meta.crate_name); symbol_hasher.input_str("-"); symbol_hasher.input_str(link_meta.crate_hash.as_str()); for meta in &*tcx.sess.crate_metadata.borrow() { symbol_hasher.input_str(&meta[..]); } symbol_hasher.input_str("-"); - symbol_hasher.input_str(&encoder::encoded_ty(tcx, t)[]); + symbol_hasher.input_str(&encoder::encoded_ty(tcx, t)); // Prefix with 'h' so that it never blends into adjacent digits let mut hash = String::from_str("h"); - hash.push_str(&truncated_hash_result(symbol_hasher)[]); + hash.push_str(&truncated_hash_result(symbol_hasher)); hash } @@ -288,7 +298,7 @@ pub fn mangle>(path: PI, fn push(n: &mut String, s: &str) { let sani = sanitize(s); - n.push_str(&format!("{}{}", sani.len(), sani)[]); + n.push_str(&format!("{}{}", sani.len(), sani)); } // First, connect each component with pairs. @@ -317,11 +327,11 @@ pub fn mangle_exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, path: PathEl // e.g. `fn foo() { { fn a() {} } { fn a() {} } }`, so we // generate unique characters from the node id. For now // hopefully 3 characters is enough to avoid collisions. - static EXTRA_CHARS: &'static str = + const EXTRA_CHARS: &'static str = "abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ 0123456789"; - let id = id as uint; + let id = id as usize; let extra1 = id % EXTRA_CHARS.len(); let id = id / EXTRA_CHARS.len(); let extra2 = id % EXTRA_CHARS.len(); @@ -356,12 +366,12 @@ pub fn get_cc_prog(sess: &Session) -> String { } pub fn remove(sess: &Session, path: &Path) { - match fs::unlink(path) { + match fs::remove_file(path) { Ok(..) => {} Err(e) => { sess.err(&format!("failed to remove {}: {}", path.display(), - e)[]); + e)); } } } @@ -371,12 +381,12 @@ pub fn remove(sess: &Session, path: &Path) { pub fn link_binary(sess: &Session, trans: &CrateTranslation, outputs: &OutputFilenames, - crate_name: &str) -> Vec { + crate_name: &str) -> Vec { let mut out_filenames = Vec::new(); for &crate_type in &*sess.crate_types.borrow() { if invalid_output_for_target(sess, crate_type) { sess.bug(&format!("invalid output type `{:?}` for target os `{}`", - crate_type, sess.opts.target_triple)[]); + crate_type, sess.opts.target_triple)); } let out_file = link_binary_output(sess, trans, crate_type, outputs, crate_name); @@ -425,35 +435,39 @@ pub fn invalid_output_for_target(sess: &Session, } fn is_writeable(p: &Path) -> bool { - match p.stat() { + match p.metadata() { Err(..) => true, - Ok(m) => m.perm & old_io::USER_WRITE == old_io::USER_WRITE + Ok(m) => !m.permissions().readonly() } } pub fn filename_for_input(sess: &Session, crate_type: config::CrateType, name: &str, - out_filename: &Path) -> Path { + out_filename: &Path) -> PathBuf { let libname = format!("{}{}", name, sess.opts.cg.extra_filename); match crate_type { config::CrateTypeRlib => { - out_filename.with_filename(format!("lib{}.rlib", libname)) + out_filename.with_file_name(&format!("lib{}.rlib", libname)) } config::CrateTypeDylib => { - let (prefix, suffix) = (&sess.target.target.options.dll_prefix[], - &sess.target.target.options.dll_suffix[]); - out_filename.with_filename(format!("{}{}{}", - prefix, - libname, - suffix)) + let (prefix, suffix) = (&sess.target.target.options.dll_prefix, + &sess.target.target.options.dll_suffix); + out_filename.with_file_name(&format!("{}{}{}", + prefix, + libname, + suffix)) } config::CrateTypeStaticlib => { - out_filename.with_filename(format!("lib{}.a", libname)) + out_filename.with_file_name(&format!("lib{}.a", libname)) } config::CrateTypeExecutable => { - let suffix = &sess.target.target.options.exe_suffix[]; - out_filename.with_filename(format!("{}{}", libname, suffix)) + let suffix = &sess.target.target.options.exe_suffix; + if suffix.len() == 0 { + out_filename.to_path_buf() + } else { + out_filename.with_extension(&suffix[1..]) + } } } } @@ -462,7 +476,7 @@ fn link_binary_output(sess: &Session, trans: &CrateTranslation, crate_type: config::CrateType, outputs: &OutputFilenames, - crate_name: &str) -> Path { + crate_name: &str) -> PathBuf { let obj_filename = outputs.temp_path(OutputTypeObject); let out_filename = match outputs.single_output_file { Some(ref file) => file.clone(), @@ -481,12 +495,12 @@ fn link_binary_output(sess: &Session, if !out_is_writeable { sess.fatal(&format!("output file {} is not writeable -- check its \ permissions.", - out_filename.display())[]); + out_filename.display())); } else if !obj_is_writeable { sess.fatal(&format!("object file {} is not writeable -- check its \ permissions.", - obj_filename.display())[]); + obj_filename.display())); } match crate_type { @@ -507,10 +521,10 @@ fn link_binary_output(sess: &Session, out_filename } -fn archive_search_paths(sess: &Session) -> Vec { +fn archive_search_paths(sess: &Session) -> Vec { let mut search = Vec::new(); sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| { - search.push(path.clone()); + search.push(path.to_path_buf()); FileDoesntMatch }); return search; @@ -529,7 +543,7 @@ fn link_rlib<'a>(sess: &'a Session, let handler = &sess.diagnostic().handler; let config = ArchiveConfig { handler: handler, - dst: out_filename.clone(), + dst: out_filename.to_path_buf(), lib_search_paths: archive_search_paths(sess), slib_prefix: sess.target.target.options.staticlib_prefix.clone(), slib_suffix: sess.target.target.options.staticlib_suffix.clone(), @@ -588,12 +602,14 @@ fn link_rlib<'a>(sess: &'a Session, // the same filename for metadata (stomping over one another) let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir"); let metadata = tmpdir.path().join(METADATA_FILENAME); - match fs::File::create(&metadata).write_all(&trans.metadata[]) { + match fs::File::create(&metadata).and_then(|mut f| { + f.write_all(&trans.metadata) + }) { Ok(..) => {} Err(e) => { sess.err(&format!("failed to write {}: {}", metadata.display(), - e)[]); + e)); sess.abort_if_errors(); } } @@ -611,34 +627,33 @@ fn link_rlib<'a>(sess: &'a Session, // was exactly 16 bytes. let bc_filename = obj_filename.with_extension(&format!("{}.bc", i)); let bc_deflated_filename = obj_filename.with_extension( - &format!("{}.bytecode.deflate", i)[]); + &format!("{}.bytecode.deflate", i)); - let bc_data = match fs::File::open(&bc_filename).read_to_end() { - Ok(buffer) => buffer, + let mut bc_data = Vec::new(); + match fs::File::open(&bc_filename).and_then(|mut f| { + f.read_to_end(&mut bc_data) + }) { + Ok(..) => {} Err(e) => sess.fatal(&format!("failed to read bytecode: {}", - e)[]) - }; + e)) + } - let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) { - Some(compressed) => compressed, - None => sess.fatal(&format!("failed to compress bytecode from {}", - bc_filename.display())[]) - }; + let bc_data_deflated = flate::deflate_bytes(&bc_data[..]); let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { Ok(file) => file, Err(e) => { - sess.fatal(&format!("failed to create compressed bytecode \ - file: {}", e)[]) + sess.fatal(&format!("failed to create compressed \ + bytecode file: {}", e)) } }; match write_rlib_bytecode_object_v1(&mut bc_file_deflated, - bc_data_deflated.as_slice()) { + &bc_data_deflated) { Ok(()) => {} Err(e) => { sess.err(&format!("failed to write compressed bytecode: \ - {}", e)[]); + {}", e)); sess.abort_if_errors() } }; @@ -670,27 +685,35 @@ fn link_rlib<'a>(sess: &'a Session, ab } -fn write_rlib_bytecode_object_v1(writer: &mut T, - bc_data_deflated: &[u8]) - -> ::std::old_io::IoResult<()> { +fn write_rlib_bytecode_object_v1(writer: &mut Write, + bc_data_deflated: &[u8]) -> io::Result<()> { let bc_data_deflated_size: u64 = bc_data_deflated.len() as u64; - try! { writer.write_all(RLIB_BYTECODE_OBJECT_MAGIC) }; - try! { writer.write_le_u32(1) }; - try! { writer.write_le_u64(bc_data_deflated_size) }; - try! { writer.write_all(&bc_data_deflated[..]) }; + try!(writer.write_all(RLIB_BYTECODE_OBJECT_MAGIC)); + try!(writer.write_all(&[1, 0, 0, 0])); + try!(writer.write_all(&[ + (bc_data_deflated_size >> 0) as u8, + (bc_data_deflated_size >> 8) as u8, + (bc_data_deflated_size >> 16) as u8, + (bc_data_deflated_size >> 24) as u8, + (bc_data_deflated_size >> 32) as u8, + (bc_data_deflated_size >> 40) as u8, + (bc_data_deflated_size >> 48) as u8, + (bc_data_deflated_size >> 56) as u8, + ])); + try!(writer.write_all(&bc_data_deflated)); let number_of_bytes_written_so_far = RLIB_BYTECODE_OBJECT_MAGIC.len() + // magic id mem::size_of_val(&RLIB_BYTECODE_OBJECT_VERSION) + // version mem::size_of_val(&bc_data_deflated_size) + // data size field - bc_data_deflated_size as uint; // actual data + bc_data_deflated_size as usize; // actual data // If the number of bytes written to the object so far is odd, add a // padding byte to make it even. This works around a crash bug in LLDB // (see issue #15950) if number_of_bytes_written_so_far % 2 == 1 { - try! { writer.write_u8(0) }; + try!(writer.write_all(&[0])); } return Ok(()); @@ -729,7 +752,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { let p = match *path { Some(ref p) => p.clone(), None => { sess.err(&format!("could not find rlib for: `{}`", - name)[]); + name)); continue } }; @@ -755,7 +778,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { cstore::NativeUnknown => "library", cstore::NativeFramework => "framework", }; - sess.note(&format!("{}: {}", name, *lib)[]); + sess.note(&format!("{}: {}", name, *lib)); } } @@ -771,10 +794,10 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, let pname = get_cc_prog(sess); let mut cmd = Command::new(&pname[..]); - cmd.args(&sess.target.target.options.pre_link_args[]); + cmd.args(&sess.target.target.options.pre_link_args); link_args(&mut cmd, sess, dylib, tmpdir.path(), trans, obj_filename, out_filename); - cmd.args(&sess.target.target.options.post_link_args[]); + cmd.args(&sess.target.target.options.post_link_args); if !sess.target.target.options.no_compiler_rt { cmd.arg("-lcompiler-rt"); } @@ -794,20 +817,20 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, if !prog.status.success() { sess.err(&format!("linking with `{}` failed: {}", pname, - prog.status)[]); - sess.note(&format!("{:?}", &cmd)[]); - let mut output = prog.error.clone(); - output.push_all(&prog.output[]); + prog.status)); + sess.note(&format!("{:?}", &cmd)); + let mut output = prog.stderr.clone(); + output.push_all(&prog.stdout); sess.note(str::from_utf8(&output[..]).unwrap()); sess.abort_if_errors(); } - debug!("linker stderr:\n{}", String::from_utf8(prog.error).unwrap()); - debug!("linker stdout:\n{}", String::from_utf8(prog.output).unwrap()); + debug!("linker stderr:\n{}", String::from_utf8(prog.stderr).unwrap()); + debug!("linker stdout:\n{}", String::from_utf8(prog.stdout).unwrap()); }, Err(e) => { sess.err(&format!("could not exec the linker `{}`: {}", pname, - e)[]); + e)); sess.abort_if_errors(); } } @@ -819,7 +842,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, match Command::new("dsymutil").arg(out_filename).output() { Ok(..) => {} Err(e) => { - sess.err(&format!("failed to run dsymutil: {}", e)[]); + sess.err(&format!("failed to run dsymutil: {}", e)); sess.abort_if_errors(); } } @@ -866,9 +889,9 @@ fn link_args(cmd: &mut Command, if t.options.is_like_osx { let morestack = lib_path.join("libmorestack.a"); - let mut v = b"-Wl,-force_load,".to_vec(); - v.push_all(morestack.as_vec()); - cmd.arg(&v[..]); + let mut v = OsString::from("-Wl,-force_load,"); + v.push(&morestack); + cmd.arg(&v); } else { cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]); } @@ -878,7 +901,7 @@ fn link_args(cmd: &mut Command, // executable. This metadata is in a separate object file from the main // object file, so we link that in here. if dylib { - cmd.arg(obj_filename.with_extension("metadata.o")); + cmd.arg(&obj_filename.with_extension("metadata.o")); } if t.options.is_like_osx { @@ -991,9 +1014,9 @@ fn link_args(cmd: &mut Command, cmd.args(&["-dynamiclib", "-Wl,-dylib"]); if sess.opts.cg.rpath { - let mut v = "-Wl,-install_name,@rpath/".as_bytes().to_vec(); - v.push_all(out_filename.filename().unwrap()); - cmd.arg(&v[..]); + let mut v = OsString::from("-Wl,-install_name,@rpath/"); + v.push(out_filename.file_name().unwrap()); + cmd.arg(&v); } } else { cmd.arg("-shared"); @@ -1005,30 +1028,30 @@ fn link_args(cmd: &mut Command, // addl_lib_search_paths if sess.opts.cg.rpath { let sysroot = sess.sysroot(); - let target_triple = &sess.opts.target_triple[]; - let get_install_prefix_lib_path = || { + let target_triple = &sess.opts.target_triple; + let mut get_install_prefix_lib_path = || { let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX"); let tlib = filesearch::relative_target_lib_path(sysroot, target_triple); - let mut path = Path::new(install_prefix); + let mut path = PathBuf::from(install_prefix); path.push(&tlib); path }; - let rpath_config = RPathConfig { + let mut rpath_config = RPathConfig { used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic), - out_filename: out_filename.clone(), + out_filename: out_filename.to_path_buf(), has_rpath: sess.target.target.options.has_rpath, is_like_osx: sess.target.target.options.is_like_osx, - get_install_prefix_lib_path: get_install_prefix_lib_path, - realpath: ::util::fs::realpath + get_install_prefix_lib_path: &mut get_install_prefix_lib_path, + realpath: &mut ::util::fs::realpath }; - cmd.args(&rpath::get_rpath_flags(rpath_config)[]); + cmd.args(&rpath::get_rpath_flags(&mut rpath_config)); } // Finally add all the linker arguments provided on the command line along // with any #[link_args] attributes found inside the crate let empty = Vec::new(); - cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty)[]); + cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty)); cmd.args(&used_link_args[..]); } @@ -1082,7 +1105,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { let search_path = archive_search_paths(sess); for l in staticlibs { if takes_hints { - cmd.arg(format!("-l{}", l)); + cmd.arg(&format!("-l{}", l)); } else { // -force_load is the OSX equivalent of --whole-archive, but it // involves passing the full path to the library to link. @@ -1091,9 +1114,9 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { &sess.target.target.options.staticlib_suffix, &search_path[..], &sess.diagnostic().handler); - let mut v = b"-Wl,-force_load,".to_vec(); - v.push_all(lib.as_vec()); - cmd.arg(&v[..]); + let mut v = OsString::from("-Wl,-force_load,"); + v.push(&lib); + cmd.arg(&v); } } if takes_hints { @@ -1103,7 +1126,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { for &(ref l, kind) in others { match kind { cstore::NativeUnknown => { - cmd.arg(format!("-l{}", l)); + cmd.arg(&format!("-l{}", l)); } cstore::NativeFramework => { cmd.arg("-framework").arg(&l[..]); @@ -1130,9 +1153,9 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // involves just passing the right -l flag. let data = if dylib { - &trans.crate_formats[config::CrateTypeDylib] + trans.crate_formats.get(&config::CrateTypeDylib).unwrap() } else { - &trans.crate_formats[config::CrateTypeExecutable] + trans.crate_formats.get(&config::CrateTypeExecutable).unwrap() }; // Invoke get_used_crates to ensure that we get a topological sorting of @@ -1143,25 +1166,25 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // We may not pass all crates through to the linker. Some crates may // appear statically in an existing dylib, meaning we'll pick up all the // symbols from the dylib. - let kind = match data[cnum as uint - 1] { + let kind = match data[cnum as usize - 1] { Some(t) => t, None => continue }; let src = sess.cstore.get_used_crate_source(cnum).unwrap(); match kind { cstore::RequireDynamic => { - add_dynamic_crate(cmd, sess, src.dylib.unwrap().0) + add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0) } cstore::RequireStatic => { - add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap().0) + add_static_crate(cmd, sess, tmpdir, &src.rlib.unwrap().0) } } } // Converts a library file-stem into a cc -l argument - fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] { - if stem.starts_with("lib".as_bytes()) && !config.target.options.is_like_windows { + fn unlib<'a>(config: &config::Config, stem: &'a str) -> &'a str { + if stem.starts_with("lib") && !config.target.options.is_like_windows { &stem[3..] } else { stem @@ -1170,7 +1193,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // Adds the static "rlib" versions of all crates to the command line. fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path, - cratepath: Path) { + cratepath: &Path) { // When performing LTO on an executable output, all of the // bytecode from the upstream libraries has already been // included in our object file output. We need to modify all of @@ -1186,31 +1209,35 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // If we're not doing LTO, then our job is simply to just link // against the archive. if sess.lto() { - let name = cratepath.filename_str().unwrap(); + let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib time(sess.time_passes(), - &format!("altering {}.rlib", name)[], + &format!("altering {}.rlib", name), (), |()| { - let dst = tmpdir.join(cratepath.filename().unwrap()); + let dst = tmpdir.join(cratepath.file_name().unwrap()); match fs::copy(&cratepath, &dst) { Ok(..) => {} Err(e) => { sess.err(&format!("failed to copy {} to {}: {}", cratepath.display(), dst.display(), - e)[]); + e)); sess.abort_if_errors(); } } // Fix up permissions of the copy, as fs::copy() preserves // permissions, but the original file may have been installed // by a package manager and may be read-only. - match fs::chmod(&dst, old_io::USER_READ | old_io::USER_WRITE) { + match fs::metadata(&dst).and_then(|m| { + let mut perms = m.permissions(); + perms.set_readonly(false); + fs::set_permissions(&dst, perms) + }) { Ok(..) => {} Err(e) => { sess.err(&format!("failed to chmod {} when preparing \ for LTO: {}", dst.display(), - e)[]); + e)); sess.abort_if_errors(); } } @@ -1224,10 +1251,10 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, maybe_ar_prog: sess.opts.cg.ar.clone() }; let mut archive = Archive::open(config); - archive.remove_file(&format!("{}.o", name)[]); + archive.remove_file(&format!("{}.o", name)); let files = archive.files(); - if files.iter().any(|s| s[].ends_with(".o")) { - cmd.arg(dst); + if files.iter().any(|s| s.ends_with(".o")) { + cmd.arg(&dst); } }); } else { @@ -1236,19 +1263,18 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, } // Same thing as above, but for dynamic crates instead of static crates. - fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: Path) { + fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: &Path) { // If we're performing LTO, then it should have been previously required // that all upstream rust dependencies were available in an rlib format. assert!(!sess.lto()); // Just need to tell the linker about where the library lives and // what its name is - let dir = cratepath.dirname(); - if !dir.is_empty() { cmd.arg("-L").arg(dir); } - - let mut v = "-l".as_bytes().to_vec(); - v.push_all(unlib(&sess.target, cratepath.filestem().unwrap())); - cmd.arg(&v[..]); + if let Some(dir) = cratepath.parent() { + cmd.arg("-L").arg(dir); + } + let filestem = cratepath.file_stem().unwrap().to_str().unwrap(); + cmd.arg(&format!("-l{}", unlib(&sess.target, filestem))); } } @@ -1286,7 +1312,7 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) { for &(kind, ref lib) in &libs { match kind { cstore::NativeUnknown => { - cmd.arg(format!("-l{}", *lib)); + cmd.arg(&format!("-l{}", *lib)); } cstore::NativeFramework => { cmd.arg("-framework"); diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 0a0f2a9c18..4e099a4ca8 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -21,8 +21,8 @@ use libc; use flate; use std::ffi::CString; -use std::iter; use std::mem; +#[allow(deprecated)] use std::num::Int; pub fn run(sess: &session::Session, llmod: ModuleRef, @@ -54,21 +54,21 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, Some(p) => p, None => { sess.fatal(&format!("could not find rlib for: `{}`", - name)[]); + name)); } }; let archive = ArchiveRO::open(&path).expect("wanted an rlib"); - let file = path.filename_str().unwrap(); + let file = path.file_name().unwrap().to_str().unwrap(); let file = &file[3..file.len() - 5]; // chop off lib/.rlib debug!("reading {}", file); - for i in iter::count(0, 1) { + for i in 0.. { let bc_encoded = time(sess.time_passes(), &format!("check for {}.{}.bytecode.deflate", name, i), (), |_| { archive.read(&format!("{}.{}.bytecode.deflate", - file, i)[]) + file, i)) }); let bc_encoded = match bc_encoded { Some(data) => data, @@ -76,7 +76,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, if i == 0 { // No bitcode was found at all. sess.fatal(&format!("missing compressed bytecode in {}", - path.display())[]); + path.display())); } // No more bitcode files to read. break; @@ -93,18 +93,18 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let data_size = extract_compressed_bytecode_size_v1(bc_encoded); let compressed_data = &bc_encoded[ link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET.. - (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)]; + (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as usize)]; match flate::inflate_bytes(compressed_data) { - Some(inflated) => inflated, - None => { + Ok(inflated) => inflated, + Err(_) => { sess.fatal(&format!("failed to decompress bc of `{}`", - name)[]) + name)) } } } else { sess.fatal(&format!("Unsupported bytecode format version {}", - version)[]) + version)) } }) } else { @@ -112,10 +112,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // the object must be in the old, pre-versioning format, so simply // inflate everything and let LLVM decide if it can make sense of it match flate::inflate_bytes(bc_encoded) { - Some(bc) => bc, - None => { + Ok(bc) => bc, + Err(_) => { sess.fatal(&format!("failed to decompress bc of `{}`", - name)[]) + name)) } } }) @@ -124,7 +124,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let ptr = bc_decoded.as_ptr(); debug!("linking {}, part {}", name, i); time(sess.time_passes(), - &format!("ll link {}.{}", name, i)[], + &format!("ll link {}.{}", name, i), (), |()| unsafe { if !llvm::LLVMRustLinkInExternalBitcode(llmod, @@ -167,7 +167,12 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod); llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _); - let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint; + let opt = match sess.opts.optimize { + config::No => 0, + config::Less => 1, + config::Default => 2, + config::Aggressive => 3, + }; let builder = llvm::LLVMPassManagerBuilderCreate(); llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt); @@ -200,7 +205,8 @@ fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 { return read_from_le_bytes::(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET); } -fn read_from_le_bytes(bytes: &[u8], position_in_bytes: uint) -> T { +#[allow(deprecated)] +fn read_from_le_bytes(bytes: &[u8], position_in_bytes: usize) -> T { let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::()]; let data = unsafe { *(byte_data.as_ptr() as *const T) @@ -208,4 +214,3 @@ fn read_from_le_bytes(bytes: &[u8], position_in_bytes: uint) -> T { Int::from_le(data) } - diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 86b720d3fc..cc588a365f 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -18,17 +18,19 @@ use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, Conte use llvm::SMDiagnosticRef; use trans::{CrateTranslation, ModuleTranslation}; use util::common::time; +use util::common::path2cstr; use syntax::codemap; use syntax::diagnostic; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; use std::ffi::{CStr, CString}; -use std::old_io::Command; -use std::old_io::fs; +use std::fs; use std::iter::Unfold; +use std::mem; +use std::path::Path; +use std::process::{Command, Stdio}; use std::ptr; use std::str; -use std::mem; use std::sync::{Arc, Mutex}; use std::sync::mpsc::channel; use std::thread; @@ -54,7 +56,7 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { libc::free(cstr as *mut _); handler.fatal(&format!("{}: {}", &msg[..], - &err[..])[]); + &err[..])); } } } @@ -67,7 +69,7 @@ pub fn write_output_file( output: &Path, file_type: llvm::FileType) { unsafe { - let output_c = CString::new(output.as_vec()).unwrap(); + let output_c = path2cstr(output); let result = llvm::LLVMRustWriteOutputFile( target, pm, m, output_c.as_ptr(), file_type); if !result { @@ -104,13 +106,13 @@ impl SharedEmitter { match diag.code { Some(ref code) => { handler.emit_with_code(None, - &diag.msg[], + &diag.msg, &code[..], diag.lvl); }, None => { handler.emit(None, - &diag.msg[], + &diag.msg, diag.lvl); }, } @@ -166,7 +168,7 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { fn create_target_machine(sess: &Session) -> TargetMachineRef { let reloc_model_arg = match sess.opts.cg.relocation_model { Some(ref s) => &s[..], - None => &sess.target.target.options.relocation_model[] + None => &sess.target.target.options.relocation_model[..], }; let reloc_model = match reloc_model_arg { "pic" => llvm::RelocPIC, @@ -177,7 +179,7 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { sess.err(&format!("{:?} is not a valid relocation mode", sess.opts .cg - .relocation_model)[]); + .relocation_model)); sess.abort_if_errors(); unreachable!(); } @@ -199,7 +201,7 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { let code_model_arg = match sess.opts.cg.code_model { Some(ref s) => &s[..], - None => &sess.target.target.options.code_model[] + None => &sess.target.target.options.code_model[..], }; let code_model = match code_model_arg { @@ -212,13 +214,13 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { sess.err(&format!("{:?} is not a valid code model", sess.opts .cg - .code_model)[]); + .code_model)); sess.abort_if_errors(); unreachable!(); } }; - let triple = &sess.target.target.llvm_target[]; + let triple = &sess.target.target.llvm_target; let tm = unsafe { let triple = CString::new(triple.as_bytes()).unwrap(); @@ -424,7 +426,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_no_opt_bc { let ext = format!("{}.no-opt.bc", name_extra); let out = output_names.with_extension(&ext); - let out = CString::new(out.as_vec()).unwrap(); + let out = path2cstr(&out); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } @@ -477,7 +479,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_lto_bc { let name = format!("{}.lto.bc", name_extra); let out = output_names.with_extension(&name); - let out = CString::new(out.as_vec()).unwrap(); + let out = path2cstr(&out); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } }, @@ -511,7 +513,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_bc { let ext = format!("{}.bc", name_extra); let out = output_names.with_extension(&ext); - let out = CString::new(out.as_vec()).unwrap(); + let out = path2cstr(&out); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); } @@ -519,21 +521,21 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, if config.emit_ir { let ext = format!("{}.ll", name_extra); let out = output_names.with_extension(&ext); - let out = CString::new(out.as_vec()).unwrap(); + let out = path2cstr(&out); with_codegen(tm, llmod, config.no_builtins, |cpm| { llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr()); }) } if config.emit_asm { - let path = output_names.with_extension(&format!("{}.s", name_extra)[]); + let path = output_names.with_extension(&format!("{}.s", name_extra)); with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType); }); } if config.emit_obj { - let path = output_names.with_extension(&format!("{}.o", name_extra)[]); + let path = output_names.with_extension(&format!("{}.o", name_extra)); with_codegen(tm, llmod, config.no_builtins, |cpm| { write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType); }); @@ -647,7 +649,7 @@ pub fn run_passes(sess: &Session, // Process the work items, optionally using worker threads. if sess.opts.cg.codegen_units == 1 { - run_work_singlethreaded(sess, &trans.reachable[], work_items); + run_work_singlethreaded(sess, &trans.reachable, work_items); } else { run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units); } @@ -679,7 +681,7 @@ pub fn run_passes(sess: &Session, // 2) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. sess.warn(&format!("ignoring -o because multiple .{} files were produced", - ext)[]); + ext)); } else { // 3) Multiple codegen units, but no `-o some_name`. We // just leave the `foo.0.x` files in place. @@ -713,38 +715,35 @@ pub fn run_passes(sess: &Session, let pname = get_cc_prog(sess); let mut cmd = Command::new(&pname[..]); - cmd.args(&sess.target.target.options.pre_link_args[]); + cmd.args(&sess.target.target.options.pre_link_args); cmd.arg("-nostdlib"); for index in 0..trans.modules.len() { - cmd.arg(crate_output.with_extension(&format!("{}.o", index)[])); + cmd.arg(&crate_output.with_extension(&format!("{}.o", index))); } - cmd.arg("-r") - .arg("-o") - .arg(windows_output_path.as_ref().unwrap_or(output_path)); + cmd.arg("-r").arg("-o") + .arg(windows_output_path.as_ref().map(|s| &**s).unwrap_or(output_path)); - cmd.args(&sess.target.target.options.post_link_args[]); + cmd.args(&sess.target.target.options.post_link_args); if sess.opts.debugging_opts.print_link_args { println!("{:?}", &cmd); } - cmd.stdin(::std::old_io::process::Ignored) - .stdout(::std::old_io::process::InheritFd(1)) - .stderr(::std::old_io::process::InheritFd(2)); + cmd.stdin(Stdio::null()); match cmd.status() { Ok(status) => { if !status.success() { sess.err(&format!("linking of {} with `{:?}` failed", - output_path.display(), cmd)[]); + output_path.display(), cmd)); sess.abort_if_errors(); } }, Err(e) => { sess.err(&format!("could not exec the linker `{}`: {}", pname, - e)[]); + e)); sess.abort_if_errors(); }, } @@ -851,7 +850,9 @@ pub fn run_passes(sess: &Session, // FIXME: time_llvm_passes support - does this use a global context or // something? - //if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); } + if sess.opts.cg.codegen_units == 1 && sess.time_llvm_passes() { + unsafe { llvm::LLVMRustPrintPassTimings(); } + } } struct WorkItem { @@ -897,7 +898,7 @@ fn run_work_singlethreaded(sess: &Session, fn run_work_multithreaded(sess: &Session, work_items: Vec, - num_workers: uint) { + num_workers: usize) { // Run some workers to process the work items. let work_items_arc = Arc::new(Mutex::new(work_items)); let mut diag_emitter = SharedEmitter::new(); @@ -962,19 +963,19 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { let pname = get_cc_prog(sess); let mut cmd = Command::new(&pname[..]); - cmd.arg("-c").arg("-o").arg(outputs.path(config::OutputTypeObject)) - .arg(outputs.temp_path(config::OutputTypeAssembly)); - debug!("{:?}", &cmd); + cmd.arg("-c").arg("-o").arg(&outputs.path(config::OutputTypeObject)) + .arg(&outputs.temp_path(config::OutputTypeAssembly)); + debug!("{:?}", cmd); match cmd.output() { Ok(prog) => { if !prog.status.success() { sess.err(&format!("linking with `{}` failed: {}", pname, - prog.status)[]); - sess.note(&format!("{:?}", &cmd)[]); - let mut note = prog.error.clone(); - note.push_all(&prog.output[]); + prog.status)); + sess.note(&format!("{:?}", &cmd)); + let mut note = prog.stderr.clone(); + note.push_all(&prog.stdout); sess.note(str::from_utf8(¬e[..]).unwrap()); sess.abort_if_errors(); } @@ -982,7 +983,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { Err(e) => { sess.err(&format!("could not exec the linker `{}`: {}", pname, - e)[]); + e)); sess.abort_if_errors(); } } @@ -1018,7 +1019,7 @@ unsafe fn configure_llvm(sess: &Session) { if sess.target.target.arch == "aarch64" { add("-fast-isel=0"); } for arg in &sess.opts.cg.llvm_args { - add(&(*arg)[]); + add(&(*arg)); } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 3deca436a1..b0eacd1a55 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_trans"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -28,18 +30,18 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(int_uint)] -#![feature(old_io)] -#![feature(env)] #![feature(libc)] -#![feature(old_path)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(unsafe_destructor)] #![feature(staged_api)] -#![feature(std_misc)] #![feature(unicode)] +#![feature(path_ext)] +#![feature(fs)] +#![feature(path_relative_from)] + +#![allow(trivial_casts)] extern crate arena; extern crate flate; @@ -49,7 +51,7 @@ extern crate libc; extern crate rustc; extern crate rustc_back; extern crate serialize; -extern crate "rustc_llvm" as llvm; +extern crate rustc_llvm as llvm; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 8d2a2d51ee..26fcf947e4 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -33,10 +33,11 @@ use middle::def; use middle::ty::{self, Ty}; use std::cell::Cell; -use std::old_io::{self, File, fs}; use std::env; +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; -use syntax::ast_util::{self, PostExpansionMethod}; +use syntax::ast_util; use syntax::ast::{self, NodeId, DefId}; use syntax::ast_map::NodeItem; use syntax::attr; @@ -94,7 +95,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // dump info about all the external crates referenced from this crate self.sess.cstore.iter_crate_data(|n, cmd| { - self.fmt.external_crate_str(krate.span, &cmd.name[], n); + self.fmt.external_crate_str(krate.span, &cmd.name, n); }); self.fmt.recorder.record("end_external_crates\n"); } @@ -216,9 +217,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { fn lookup_type_ref(&self, ref_id: NodeId) -> Option { if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) { self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref", - ref_id)[]); + ref_id)); } - let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id]; + let def = self.analysis.ty_cx.def_map.borrow().get(&ref_id).unwrap().full_def(); match def { def::DefPrimTy(_) => None, _ => Some(def.def_id()), @@ -229,16 +230,15 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let def_map = self.analysis.ty_cx.def_map.borrow(); if !def_map.contains_key(&ref_id) { self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind", - ref_id)[]); + ref_id)); } - let def = (*def_map)[ref_id]; + let def = def_map.get(&ref_id).unwrap().full_def(); match def { def::DefMod(_) | def::DefForeignMod(_) => Some(recorder::ModRef), def::DefStruct(_) => Some(recorder::StructRef), def::DefTy(..) | def::DefAssociatedTy(..) | - def::DefAssociatedPath(..) | def::DefTrait(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | def::DefConst(_) | @@ -250,15 +250,13 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefSelfTy(_) | def::DefRegion(_) | - def::DefTyParamBinder(_) | def::DefLabel(_) | - def::DefStaticMethod(..) | def::DefTyParam(..) | def::DefUse(_) | def::DefMethod(..) | def::DefPrimTy(_) => { self.sess.span_bug(span, &format!("lookup_def_kind for unexpected item: {:?}", - def)[]); + def)); }, } } @@ -271,23 +269,28 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.collecting = false; let span_utils = self.span.clone(); for &(id, ref p, _, _) in &self.collected_paths { - let typ = ppaux::ty_to_string(&self.analysis.ty_cx, - (*self.analysis.ty_cx.node_types.borrow())[id]); + let typ = + ppaux::ty_to_string( + &self.analysis.ty_cx, + *self.analysis.ty_cx.node_types().get(&id).unwrap()); // get the span only for the name of the variable (I hope the path is only ever a // variable name, but who knows?) self.fmt.formal_str(p.span, span_utils.span_for_last_ident(p.span), id, qualname, - &path_to_string(p)[], + &path_to_string(p), &typ[..]); } self.collected_paths.clear(); } } - fn process_method(&mut self, method: &ast::Method) { - if generated_code(method.span) { + fn process_method(&mut self, sig: &ast::MethodSig, + body: Option<&ast::Block>, + id: ast::NodeId, ident: ast::Ident, + span: Span) { + if generated_code(span) { return; } @@ -295,17 +298,17 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. let qualname = match ty::impl_of_method(&self.analysis.ty_cx, - ast_util::local_def(method.id)) { + ast_util::local_def(id)) { Some(impl_id) => match self.analysis.ty_cx.map.get(impl_id.node) { NodeItem(item) => { scope_id = item.id; match item.node { ast::ItemImpl(_, _, _, _, ref ty, _) => { let mut result = String::from_str("<"); - result.push_str(&ty_to_string(&**ty)[]); + result.push_str(&ty_to_string(&**ty)); match ty::trait_of_item(&self.analysis.ty_cx, - ast_util::local_def(method.id)) { + ast_util::local_def(id)) { Some(def_id) => { result.push_str(" as "); result.push_str( @@ -317,23 +320,20 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { result } _ => { - self.sess.span_bug(method.span, - &format!("Container {} for method {} not an impl?", - impl_id.node, method.id)[]); + self.sess.span_bug(span, + &format!("Container {} for method {} not an impl?", + impl_id.node, id)); }, } }, _ => { - self.sess.span_bug(method.span, - &format!( - "Container {} for method {} is not a node item {:?}", - impl_id.node, - method.id, - self.analysis.ty_cx.map.get(impl_id.node))[]); + self.sess.span_bug(span, + &format!("Container {} for method {} is not a node item {:?}", + impl_id.node, id, self.analysis.ty_cx.map.get(impl_id.node))); }, }, None => match ty::trait_of_item(&self.analysis.ty_cx, - ast_util::local_def(method.id)) { + ast_util::local_def(id)) { Some(def_id) => { scope_id = def_id.node; match self.analysis.ty_cx.map.get(def_id.node) { @@ -341,69 +341,72 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { format!("::{}", ty::item_path_str(&self.analysis.ty_cx, def_id)) } _ => { - self.sess.span_bug(method.span, - &format!("Could not find container {} for method {}", - def_id.node, method.id)[]); + self.sess.span_bug(span, + &format!("Could not find container {} for method {}", + def_id.node, id)); } } }, None => { - self.sess.span_bug(method.span, - &format!("Could not find container for method {}", - method.id)[]); + self.sess.span_bug(span, + &format!("Could not find container for method {}", id)); }, }, }; - let qualname = format!("{}::{}", qualname, &get_ident(method.pe_ident())); - let qualname = &qualname[..]; + let qualname = &format!("{}::{}", qualname, &get_ident(ident)); // record the decl for this def (if it has one) let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx, - ast_util::local_def(method.id)) + ast_util::local_def(id)) .and_then(|def_id| { if match def_id { ty::MethodTraitItemId(def_id) => { - def_id.node != 0 && def_id != ast_util::local_def(method.id) + def_id.node != 0 && def_id != ast_util::local_def(id) } ty::TypeTraitItemId(_) => false, } { - Some(def_id) + Some(def_id.def_id()) } else { None } }); - let decl_id = match decl_id { - None => None, - Some(id) => Some(id.def_id()), - }; - let sub_span = self.span.sub_span_after_keyword(method.span, keywords::Fn); - self.fmt.method_str(method.span, - sub_span, - method.id, - qualname, - decl_id, - scope_id); - - self.process_formals(&method.pe_fn_decl().inputs, qualname); + let sub_span = self.span.sub_span_after_keyword(span, keywords::Fn); + if body.is_some() { + self.fmt.method_str(span, + sub_span, + id, + qualname, + decl_id, + scope_id); + self.process_formals(&sig.decl.inputs, qualname); + } else { + self.fmt.method_decl_str(span, + sub_span, + id, + qualname, + scope_id); + } // walk arg and return types - for arg in &method.pe_fn_decl().inputs { - self.visit_ty(&*arg.ty); + for arg in &sig.decl.inputs { + self.visit_ty(&arg.ty); } - if let ast::Return(ref ret_ty) = method.pe_fn_decl().output { - self.visit_ty(&**ret_ty); + if let ast::Return(ref ret_ty) = sig.decl.output { + self.visit_ty(ret_ty); } // walk the fn body - self.nest(method.id, |v| v.visit_block(&*method.pe_body())); + if let Some(body) = body { + self.nest(id, |v| v.visit_block(body)); + } - self.process_generic_params(method.pe_generics(), - method.span, + self.process_generic_params(&sig.generics, + span, qualname, - method.id); + id); } fn process_trait_ref(&mut self, @@ -430,8 +433,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { ast::NamedField(ident, _) => { let name = get_ident(ident); let qualname = format!("{}::{}", qualname, name); - let typ = ppaux::ty_to_string(&self.analysis.ty_cx, - (*self.analysis.ty_cx.node_types.borrow())[field.node.id]); + let typ = + ppaux::ty_to_string( + &self.analysis.ty_cx, + *self.analysis.ty_cx.node_types().get(&field.node.id).unwrap()); match self.span.sub_span_before_token(field.span, token::Colon) { Some(sub_span) => self.fmt.field_str(field.span, Some(sub_span), @@ -442,7 +447,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { scope_id), None => self.sess.span_bug(field.span, &format!("Could not find sub-span for field {}", - qualname)[]), + qualname)), } }, _ => (), @@ -460,7 +465,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { // However full span is the entire enum/fn/struct block, so we only want // the first few to match the number of generics we're looking for. let param_sub_spans = self.span.spans_for_ty_params(full_span, - (generics.ty_params.len() as int)); + (generics.ty_params.len() as isize)); for (param, param_ss) in generics.ty_params.iter().zip(param_sub_spans.iter()) { // Append $id to name to make sure each one is unique let name = format!("{}::{}${}", @@ -528,7 +533,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { &get_ident(item.ident), &qualname[..], &value[..], - &ty_to_string(&*typ)[], + &ty_to_string(&*typ), self.cur_scope); // walk type and init value @@ -551,7 +556,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { &get_ident(item.ident), &qualname[..], "", - &ty_to_string(&*typ)[], + &ty_to_string(&*typ), self.cur_scope); // walk type and init value @@ -603,7 +608,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { &val[..]), None => self.sess.span_bug(item.span, &format!("Could not find subspan for enum {}", - enum_name)[]), + enum_name)), } for variant in &enum_definition.variants { let name = get_ident(variant.node.name); @@ -658,28 +663,26 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { type_parameters: &ast::Generics, trait_ref: &Option, typ: &ast::Ty, - impl_items: &Vec) { + impl_items: &[P]) { let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id)); match typ.node { // Common case impl for a struct or something basic. - ast::TyPath(ref path, id) => { - match self.lookup_type_ref(id) { - Some(id) => { - let sub_span = self.span.sub_span_for_type_name(path.span); - self.fmt.ref_str(recorder::TypeRef, - path.span, - sub_span, - id, - self.cur_scope); - self.fmt.impl_str(path.span, - sub_span, - item.id, - Some(id), - trait_id, - self.cur_scope); - }, - None => () - } + ast::TyPath(None, ref path) => { + let sub_span = self.span.sub_span_for_type_name(path.span); + let self_id = self.lookup_type_ref(typ.id).map(|id| { + self.fmt.ref_str(recorder::TypeRef, + path.span, + sub_span, + id, + self.cur_scope); + id + }); + self.fmt.impl_str(path.span, + sub_span, + item.id, + self_id, + trait_id, + self.cur_scope); }, _ => { // Less useful case, impl for a compound type. @@ -702,14 +705,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.process_generic_params(type_parameters, item.span, "", item.id); for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - visit::walk_method_helper(self, &**method) - } - ast::TypeImplItem(ref typedef) => { - visit::walk_ty(self, &*typedef.typ) - } - } + visit::walk_impl_item(self, impl_item); } } @@ -717,7 +713,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { item: &ast::Item, generics: &ast::Generics, trait_refs: &OwnedSlice, - methods: &Vec) { + methods: &[P]) { let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id)); let val = self.span.snippet(item.span); let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait); @@ -797,9 +793,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { self.sess.span_bug(span, &format!("def_map has no key for {} in visit_expr", id)); } - let def = &(*def_map)[id]; + let def = def_map.get(&id).unwrap().full_def(); let sub_span = self.span.span_for_last_ident(span); - match *def { + match def { def::DefUpvar(..) | def::DefLocal(..) | def::DefStatic(..) | @@ -819,8 +815,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { sub_span, def_id, self.cur_scope), - def::DefStaticMethod(declid, provenence) | - def::DefMethod(declid, _, provenence) => { + def::DefMethod(declid, provenence) => { let sub_span = self.span.sub_span_for_meth_name(span); let defid = if declid.krate == ast::LOCAL_CRATE { let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, @@ -841,7 +836,8 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { .ty_cx .impl_items .borrow(); - Some((*impl_items)[def_id] + Some(impl_items.get(&def_id) + .unwrap() .iter() .find(|mr| { ty::impl_or_trait_item( @@ -872,11 +868,18 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { &format!("Unexpected def kind while looking \ up path in `{}`: `{:?}`", self.span.snippet(span), - *def)[]), + def)), } // modules or types in the path prefix - match *def { - def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path), + match def { + def::DefMethod(did, _) => { + let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did); + if let ty::MethodTraitItem(m) = ti { + if m.explicit_self == ty::StaticExplicitSelfCategory { + self.write_sub_path_trait_truncated(path); + } + } + } def::DefLocal(_) | def::DefStatic(_,_) | def::DefConst(..) | @@ -943,7 +946,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { ex: &ast::Expr, args: &Vec>) { let method_map = self.analysis.ty_cx.method_map.borrow(); - let method_callee = &(*method_map)[ty::MethodCall::expr(ex.id)]; + let method_callee = method_map.get(&ty::MethodCall::expr(ex.id)).unwrap(); let (def_id, decl_id) = match method_callee.origin { ty::MethodStatic(def_id) | ty::MethodStaticClosure(def_id) => { @@ -1002,28 +1005,39 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { ast::PatStruct(ref path, ref fields, _) => { self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef)); visit::walk_path(self, path); - let struct_def = match self.lookup_type_ref(p.id) { - Some(sd) => sd, - None => { - self.sess.span_bug(p.span, - &format!("Could not find struct_def for `{}`", - self.span.snippet(p.span))[]); + + let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def(); + let struct_def = match def { + def::DefConst(..) => None, + def::DefVariant(_, variant_id, _) => Some(variant_id), + _ => { + match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) { + None => { + self.sess.span_bug(p.span, + &format!("Could not find struct_def for `{}`", + self.span.snippet(p.span))); + } + Some(def_id) => Some(def_id), + } } }; - for &Spanned { node: ref field, span } in fields { - let sub_span = self.span.span_for_first_ident(span); - let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def); - for f in fields { - if f.name == field.ident.name { - self.fmt.ref_str(recorder::VarRef, - span, - sub_span, - f.id, - self.cur_scope); - break; + + if let Some(struct_def) = struct_def { + let struct_fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def); + for &Spanned { node: ref field, span } in fields { + let sub_span = self.span.span_for_first_ident(span); + for f in &struct_fields { + if f.name == field.ident.name { + self.fmt.ref_str(recorder::VarRef, + span, + sub_span, + f.id, + self.cur_scope); + break; + } } + self.visit_pat(&*field.pat); } - self.visit_pat(&*field.pat); } } ast::PatEnum(ref path, _) => { @@ -1104,7 +1118,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { let glob_map = &self.analysis.glob_map; let glob_map = glob_map.as_ref().unwrap(); if glob_map.contains_key(&item.id) { - for n in &glob_map[item.id] { + for n in glob_map.get(&item.id).unwrap() { if name_string.len() > 0 { name_string.push_str(", "); } @@ -1151,7 +1165,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { let name = get_ident(item.ident); let name = &name; let location = match *s { - Some((ref s, _)) => s.to_string(), + Some(s) => s.to_string(), None => name.to_string(), }; let alias_span = self.span.span_for_last_ident(item.span); @@ -1220,71 +1234,24 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } } - // We don't actually index functions here, that is done in visit_item/ItemFn. - // Here we just visit methods. - fn visit_fn(&mut self, - fk: visit::FnKind<'v>, - fd: &'v ast::FnDecl, - b: &'v ast::Block, - s: Span, - _: ast::NodeId) { - if generated_code(s) { - return; - } - - match fk { - visit::FkMethod(_, _, method) => self.process_method(method), - _ => visit::walk_fn(self, fk, fd, b, s), + fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + match trait_item.node { + ast::MethodTraitItem(ref sig, ref body) => { + self.process_method(sig, body.as_ref().map(|x| &**x), + trait_item.id, trait_item.ident, trait_item.span); + } + ast::TypeTraitItem(..) => {} } } - fn visit_trait_item(&mut self, tm: &ast::TraitItem) { - match *tm { - ast::RequiredMethod(ref method_type) => { - if generated_code(method_type.span) { - return; - } - - let mut scope_id; - let mut qualname = match ty::trait_of_item(&self.analysis.ty_cx, - ast_util::local_def(method_type.id)) { - Some(def_id) => { - scope_id = def_id.node; - format!("::{}::", ty::item_path_str(&self.analysis.ty_cx, def_id)) - }, - None => { - self.sess.span_bug(method_type.span, - &format!("Could not find trait for method {}", - method_type.id)[]); - }, - }; - - qualname.push_str(&get_ident(method_type.ident)); - let qualname = &qualname[..]; - - let sub_span = self.span.sub_span_after_keyword(method_type.span, keywords::Fn); - self.fmt.method_decl_str(method_type.span, - sub_span, - method_type.id, - qualname, - scope_id); - - // walk arg and return types - for arg in &method_type.decl.inputs { - self.visit_ty(&*arg.ty); - } - - if let ast::Return(ref ret_ty) = method_type.decl.output { - self.visit_ty(&**ret_ty); - } - - self.process_generic_params(&method_type.generics, - method_type.span, - qualname, - method_type.id); + fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + self.process_method(sig, Some(body), impl_item.id, + impl_item.ident, impl_item.span); } - ast::ProvidedMethod(ref method) => self.process_method(&**method), - ast::TypeTraitItem(_) => {} + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} } } @@ -1294,8 +1261,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } match t.node { - ast::TyPath(ref path, id) => { - match self.lookup_type_ref(id) { + ast::TyPath(_, ref path) => { + match self.lookup_type_ref(t.id) { Some(id) => { let sub_span = self.span.sub_span_for_type_name(t.span); self.fmt.ref_str(recorder::TypeRef, @@ -1325,16 +1292,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { // Don't need to do anything for function calls, // because just walking the callee path does what we want. visit::walk_expr(self, ex); - }, - ast::ExprPath(ref path) => { - self.process_path(ex.id, path.span, path, None); - visit::walk_path(self, path); } - ast::ExprQPath(ref qpath) => { - let mut path = qpath.trait_ref.path.clone(); - path.segments.push(qpath.item_path.clone()); - self.process_path(ex.id, ex.span, &path, None); - visit::walk_qpath(self, ex.span, &**qpath); + ast::ExprPath(_, ref path) => { + self.process_path(ex.id, path.span, path, None); + visit::walk_expr(self, ex); } ast::ExprStruct(ref path, ref fields, ref base) => self.process_struct_lit(ex, path, fields, base), @@ -1362,7 +1323,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } } _ => self.sess.span_bug(ex.span, - &format!("Expected struct type, found {:?}", ty)[]), + &format!("Expected struct type, found {:?}", ty)), } }, ast::ExprTupField(ref sub_ex, idx) => { @@ -1391,7 +1352,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { ty::ty_tup(_) => {} _ => self.sess.span_bug(ex.span, &format!("Expected struct or tuple \ - type, found {:?}", ty)[]), + type, found {:?}", ty)), } }, ast::ExprClosure(_, ref decl, ref body) => { @@ -1400,7 +1361,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } let mut id = String::from_str("$"); - id.push_str(&ex.id.to_string()[]); + id.push_str(&ex.id.to_string()); self.process_formals(&decl.inputs, &id[..]); // walk arg and return types @@ -1448,10 +1409,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { if !def_map.contains_key(&id) { self.sess.span_bug(p.span, &format!("def_map has no key for {} in visit_arm", - id)[]); + id)); } - let def = &(*def_map)[id]; - match *def { + let def = def_map.get(&id).unwrap().full_def(); + match def { def::DefLocal(id) => { let value = if *immut { self.span.snippet(p.span).to_string() @@ -1463,7 +1424,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { self.fmt.variable_str(p.span, Some(p.span), id, - &path_to_string(p)[], + &path_to_string(p), &value[..], "") } @@ -1474,7 +1435,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { def::DefStatic(_, _) => {} def::DefConst(..) => {} _ => error!("unexpected definition kind when processing collected paths: {:?}", - *def) + def) } } for &(id, ref path, ref_kind) in &paths_to_process { @@ -1510,8 +1471,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { for &(id, ref p, ref immut, _) in &self.collected_paths { let value = if *immut { value.to_string() } else { "".to_string() }; - let types = self.analysis.ty_cx.node_types.borrow(); - let typ = ppaux::ty_to_string(&self.analysis.ty_cx, (*types)[id]); + let types = self.analysis.ty_cx.node_types(); + let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap()); // Get the span only for the name of the variable (I hope the path // is only ever a variable name, but who knows?). let sub_span = self.span.span_for_last_ident(p.span); @@ -1519,7 +1480,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { self.fmt.variable_str(p.span, sub_span, id, - &path_to_string(p)[], + &path_to_string(p), &value[..], &typ[..]); } @@ -1531,6 +1492,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } } +#[allow(deprecated)] pub fn process_crate(sess: &Session, krate: &ast::Crate, analysis: &ty::CrateAnalysis, @@ -1540,7 +1502,7 @@ pub fn process_crate(sess: &Session, } assert!(analysis.glob_map.is_some()); - let cratename = match attr::find_crate_name(&krate.attrs[]) { + let cratename = match attr::find_crate_name(&krate.attrs) { Some(name) => name.to_string(), None => { info!("Could not find crate name, using 'unknown_crate'"); @@ -1551,17 +1513,17 @@ pub fn process_crate(sess: &Session, info!("Dumping crate {}", cratename); // find a path to dump our data to - let mut root_path = match env::var("DXR_RUST_TEMP_FOLDER") { - Ok(val) => Path::new(val), - Err(..) => match odir { + let mut root_path = match env::var_os("DXR_RUST_TEMP_FOLDER") { + Some(val) => PathBuf::from(val), + None => match odir { Some(val) => val.join("dxr"), - None => Path::new("dxr-temp"), + None => PathBuf::from("dxr-temp"), }, }; - match fs::mkdir_recursive(&root_path, old_io::USER_RWX) { + match fs::create_dir_all(&root_path) { Err(e) => sess.err(&format!("Could not create directory {}: {}", - root_path.display(), e)[]), + root_path.display(), e)), _ => (), } @@ -1573,12 +1535,12 @@ pub fn process_crate(sess: &Session, // Create output file. let mut out_name = cratename.clone(); out_name.push_str(".csv"); - root_path.push(out_name); + root_path.push(&out_name); let output_file = match File::create(&root_path) { Ok(f) => box f, Err(e) => { let disp = root_path.display(); - sess.fatal(&format!("Could not open {}: {}", disp, e)[]); + sess.fatal(&format!("Could not open {}: {}", disp, e)); } }; root_path.pop(); @@ -1589,7 +1551,7 @@ pub fn process_crate(sess: &Session, collected_paths: vec!(), collecting: false, fmt: FmtStrs::new(box Recorder { - out: output_file as Box, + out: output_file, dump_spans: false, }, SpanUtils { diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index 08e36bb1d8..db724b0ef6 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -13,7 +13,7 @@ pub use self::Row::*; use super::escape; use super::span_utils::SpanUtils; -use std::vec::Vec; +use std::io::Write; use syntax::ast; use syntax::ast::{NodeId,DefId}; @@ -23,7 +23,7 @@ const ZERO_DEF_ID: DefId = DefId { node: 0, krate: 0 }; pub struct Recorder { // output file - pub out: Box, + pub out: Box, pub dump_spans: bool, } @@ -62,7 +62,7 @@ macro_rules! svec { }) } -#[derive(Copy, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Row { Variable, Enum, @@ -162,7 +162,7 @@ impl<'a> FmtStrs<'a> { if values.len() != fields.len() { self.span.sess.span_bug(span, &format!( "Mismatch between length of fields for '{}', expected '{}', found '{}'", - kind, fields.len(), values.len())[]); + kind, fields.len(), values.len())); } let values = values.iter().map(|s| { @@ -191,7 +191,7 @@ impl<'a> FmtStrs<'a> { if needs_span { self.span.sess.span_bug(span, &format!( "Called record_without_span for '{}' which does requires a span", - label)[]); + label)); } assert!(!dump_spans); @@ -268,7 +268,7 @@ impl<'a> FmtStrs<'a> { // variable def's node id let mut qualname = String::from_str(name); qualname.push_str("$"); - qualname.push_str(&id.to_string()[]); + qualname.push_str(&id.to_string()); self.check_and_record(Variable, span, sub_span, diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index 223d46e4e4..84a7678959 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -24,7 +24,7 @@ use syntax::parse::token::{keywords, Token}; #[derive(Clone)] pub struct SpanUtils<'a> { pub sess: &'a Session, - pub err_count: Cell, + pub err_count: Cell, } impl<'a> SpanUtils<'a> { @@ -219,7 +219,7 @@ impl<'a> SpanUtils<'a> { let loc = self.sess.codemap().lookup_char_pos(span.lo); self.sess.span_bug(span, &format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", - self.snippet(span), loc.file.name, loc.line)[]); + self.snippet(span), loc.file.name, loc.line)); } if result.is_none() && prev.tok.is_ident() && bracket_count == 0 { return self.make_sub_span(span, Some(prev.sp)); @@ -232,12 +232,13 @@ impl<'a> SpanUtils<'a> { // example with Foo, Bar> // Nesting = 0: all idents outside of brackets: ~[Foo] // Nesting = 1: idents within one level of brackets: ~[Bar, Bar] - pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec { + pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> Vec { let mut result: Vec = vec!(); let mut toks = self.retokenise_span(span); // We keep track of how many brackets we're nested in let mut bracket_count = 0; + let mut found_ufcs_sep = false; loop { let ts = toks.real_token(); if ts.tok == token::Eof { @@ -245,22 +246,29 @@ impl<'a> SpanUtils<'a> { let loc = self.sess.codemap().lookup_char_pos(span.lo); self.sess.span_bug(span, &format!( "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", - self.snippet(span), loc.file.name, loc.line)[]); + self.snippet(span), loc.file.name, loc.line)); } return result } - if (result.len() as int) == limit { + if (result.len() as isize) == limit { return result; } bracket_count += match ts.tok { token::Lt => 1, - token::Gt => -1, + token::Gt => { + // Ignore the `>::` in `::AssocTy`. + if !found_ufcs_sep && bracket_count == 0 { + found_ufcs_sep = true; + 0 + } else { + -1 + } + } token::BinOp(token::Shl) => 2, token::BinOp(token::Shr) => -2, _ => 0 }; - if ts.tok.is_ident() && - bracket_count == nesting { + if ts.tok.is_ident() && bracket_count == nesting { result.push(self.make_sub_span(span, Some(ts.sp)).unwrap()); } } @@ -339,7 +347,7 @@ impl<'a> SpanUtils<'a> { // Return an owned vector of the subspans of the param identifier // tokens found in span. - pub fn spans_for_ty_params(&self, span: Span, number: int) -> Vec { + pub fn spans_for_ty_params(&self, span: Span, number: isize) -> Vec { if generated_code(span) { return vec!(); } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 2826afb71a..ef599a01e7 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -28,7 +28,7 @@ //! constituent pattern. N here is usually the number of arms but may be //! greater, if some arms have multiple alternatives. For example, here: //! -//! enum Foo { A, B(int), C(uint, uint) } +//! enum Foo { A, B(int), C(usize, usize) } //! match foo { //! A => ..., //! B(x) => ..., @@ -200,7 +200,7 @@ use middle::mem_categorization as mc; use middle::pat_util::*; use trans::adt; use trans::base::*; -use trans::build::{AddCase, And, BitCast, Br, CondBr, GEPi, InBoundsGEP, Load}; +use trans::build::{AddCase, And, Br, CondBr, GEPi, InBoundsGEP, Load, PointerCast}; use trans::build::{Not, Store, Sub, add_comment}; use trans::build; use trans::callee; @@ -228,7 +228,7 @@ use syntax::codemap::Span; use syntax::fold::Folder; use syntax::ptr::P; -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] struct ConstantExpr<'a>(&'a ast::Expr); impl<'a> ConstantExpr<'a> { @@ -246,9 +246,9 @@ enum Opt<'a, 'tcx> { ConstantValue(ConstantExpr<'a>, DebugLoc), ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>, DebugLoc), Variant(ty::Disr, Rc>, ast::DefId, DebugLoc), - SliceLengthEqual(uint, DebugLoc), - SliceLengthGreaterOrEqual(/* prefix length */ uint, - /* suffix length */ uint, + SliceLengthEqual(usize, DebugLoc), + SliceLengthGreaterOrEqual(/* prefix length */ usize, + /* suffix length */ usize, DebugLoc), } @@ -311,7 +311,7 @@ impl<'a, 'tcx> Opt<'a, 'tcx> { } } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum BranchKind { NoBranch, Single, @@ -326,7 +326,7 @@ pub enum OptResult<'blk, 'tcx: 'blk> { LowerBound(Result<'blk, 'tcx>) } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub enum TransBindingMode { TrByCopy(/* llbinding */ ValueRef), TrByMove, @@ -381,7 +381,7 @@ impl<'a, 'p, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'blk, 'tcx> { } } -fn has_nested_bindings(m: &[Match], col: uint) -> bool { +fn has_nested_bindings(m: &[Match], col: usize) -> bool { for br in m { match br.pats[col].node { ast::PatIdent(_, _, Some(_)) => return true, @@ -393,7 +393,7 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool { fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, m: &[Match<'a, 'p, 'blk, 'tcx>], - col: uint, + col: usize, val: ValueRef) -> Vec> { debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})", @@ -430,7 +430,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, dm: &DefMap, m: &[Match<'a, 'p, 'blk, 'tcx>], - col: uint, + col: usize, val: ValueRef, mut e: F) -> Vec> where @@ -444,7 +444,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let _indenter = indenter(); m.iter().filter_map(|br| { - e(&br.pats[]).map(|pats| { + e(&br.pats).map(|pats| { let this = br.pats[col]; let mut bound_ptrs = br.bound_ptrs.clone(); match this.node { @@ -476,7 +476,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dm: &DefMap, m: &[Match<'a, 'p, 'blk, 'tcx>], - col: uint, + col: usize, val: ValueRef) -> Vec> { debug!("enter_default(bcx={}, m={}, col={}, val={})", @@ -532,8 +532,8 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( dm: &DefMap, m: &[Match<'a, 'p, 'blk, 'tcx>], opt: &Opt, - col: uint, - variant_size: uint, + col: usize, + variant_size: usize, val: ValueRef) -> Vec> { debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})", @@ -575,7 +575,7 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( // on a set of enum variants or a literal. fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, m: &[Match<'a, 'p, 'blk, 'tcx>], - col: uint) + col: usize) -> Vec> { let tcx = bcx.tcx(); @@ -598,7 +598,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => { // This is either an enum variant or a variable binding. - let opt_def = tcx.def_map.borrow().get(&cur.id).cloned(); + let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def()); match opt_def { Some(def::DefVariant(enum_id, var_id, _)) => { let variant = ty::enum_variant_with_id(tcx, enum_id, var_id); @@ -656,11 +656,11 @@ fn match_datum<'tcx>(val: ValueRef, left_ty: Ty<'tcx>) -> Datum<'tcx, Lvalue> { fn bind_subslice_pat(bcx: Block, pat_id: ast::NodeId, val: ValueRef, - offset_left: uint, - offset_right: uint) -> ValueRef { + offset_left: usize, + offset_right: usize) -> ValueRef { let _icx = push_ctxt("match::bind_subslice_pat"); let vec_ty = node_id_type(bcx, pat_id); - let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), ty::type_content(vec_ty))); + let unit_ty = ty::sequence_element_type(bcx.tcx(), ty::type_content(vec_ty)); let vec_datum = match_datum(val, vec_ty); let (base, len) = vec_datum.get_vec_base_and_len(bcx); @@ -669,7 +669,7 @@ fn bind_subslice_pat(bcx: Block, let slice_len = Sub(bcx, len, slice_len_offset, DebugLoc::None); let slice_ty = ty::mk_slice(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), - ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable}); + ty::mt {ty: unit_ty, mutbl: ast::MutImmutable}); let scratch = rvalue_scratch_datum(bcx, slice_ty, ""); Store(bcx, slice_begin, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR])); @@ -678,9 +678,9 @@ fn bind_subslice_pat(bcx: Block, } fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - left_ty: Ty, - before: uint, - after: uint, + left_ty: Ty<'tcx>, + before: usize, + after: usize, val: ValueRef) -> ExtractedBlock<'blk, 'tcx> { let _icx = push_ctxt("match::extract_vec_elems"); @@ -711,28 +711,28 @@ macro_rules! any_pat { ) } -fn any_uniq_pat(m: &[Match], col: uint) -> bool { +fn any_uniq_pat(m: &[Match], col: usize) -> bool { any_pat!(m, col, ast::PatBox(_)) } -fn any_region_pat(m: &[Match], col: uint) -> bool { +fn any_region_pat(m: &[Match], col: usize) -> bool { any_pat!(m, col, ast::PatRegion(..)) } -fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool { +fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: usize) -> bool { m.iter().any(|br| { let pat = br.pats[col]; match pat.node { ast::PatTup(_) => true, ast::PatStruct(..) => { - match tcx.def_map.borrow().get(&pat.id) { - Some(&def::DefVariant(..)) => false, + match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(def::DefVariant(..)) => false, _ => true, } } ast::PatEnum(..) | ast::PatIdent(_, _, None) => { - match tcx.def_map.borrow().get(&pat.id) { - Some(&def::DefStruct(..)) => true, + match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { + Some(def::DefStruct(..)) => true, _ => false } } @@ -772,8 +772,8 @@ impl FailureHandler { } } -fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { - fn pat_score(def_map: &DefMap, pat: &ast::Pat) -> uint { +fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { + fn pat_score(def_map: &DefMap, pat: &ast::Pat) -> usize { match pat.node { ast::PatIdent(_, _, Some(ref inner)) => pat_score(def_map, &**inner), _ if pat_is_refutable(def_map, pat) => 1, @@ -781,7 +781,7 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { } } - let column_score = |m: &[Match], col: uint| -> uint { + let column_score = |m: &[Match], col: usize| -> usize { let total_score = m.iter() .map(|row| row.pats[col]) .map(|pat| pat_score(def_map, pat)) @@ -789,13 +789,13 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { // Irrefutable columns always go first, they'd only be duplicated in the branches. if total_score == 0 { - std::uint::MAX + std::usize::MAX } else { total_score } }; - let column_contains_any_nonwild_patterns = |&col: &uint| -> bool { + let column_contains_any_nonwild_patterns = |&col: &usize| -> bool { m.iter().any(|row| match row.pats[col].node { ast::PatWild(_) => false, _ => true @@ -825,7 +825,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, let did = langcall(cx, None, &format!("comparison of `{}`", - cx.ty_to_string(rhs_t))[], + cx.ty_to_string(rhs_t)), StrEqFnLangItem); let t = ty::mk_str_slice(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ast::MutImmutable); // The comparison function gets the slices by value, so we have to make copies here. Even @@ -853,14 +853,31 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty::ty_str => compare_str(cx, lhs, rhs, rhs_t, debug_loc), ty::ty_vec(ty, _) => match ty.sty { ty::ty_uint(ast::TyU8) => { - // NOTE: cast &[u8] to &str and abuse the str_eq lang item, + // NOTE: cast &[u8] and &[u8; N] to &str and abuse the str_eq lang item, // which calls memcmp(). - let t = ty::mk_str_slice(cx.tcx(), - cx.tcx().mk_region(ty::ReStatic), - ast::MutImmutable); - let lhs = BitCast(cx, lhs, type_of::type_of(cx.ccx(), t).ptr_to()); - let rhs = BitCast(cx, rhs, type_of::type_of(cx.ccx(), t).ptr_to()); - compare_str(cx, lhs, rhs, rhs_t, debug_loc) + let pat_len = val_ty(rhs).element_type().array_length(); + let ty_str_slice = ty::mk_str_slice(cx.tcx(), + cx.tcx().mk_region(ty::ReStatic), + ast::MutImmutable); + + let rhs_str = alloc_ty(cx, ty_str_slice, "rhs_str"); + Store(cx, GEPi(cx, rhs, &[0, 0]), expr::get_dataptr(cx, rhs_str)); + Store(cx, C_uint(cx.ccx(), pat_len), expr::get_len(cx, rhs_str)); + + let lhs_str; + if val_ty(lhs) == val_ty(rhs) { + // Both the discriminant and the pattern are thin pointers + lhs_str = alloc_ty(cx, ty_str_slice, "lhs_str"); + Store(cx, GEPi(cx, lhs, &[0, 0]), expr::get_dataptr(cx, lhs_str)); + Store(cx, C_uint(cx.ccx(), pat_len), expr::get_len(cx, lhs_str)); + } + else { + // The discriminant is a fat pointer + let llty_str_slice = type_of::type_of(cx.ccx(), ty_str_slice).ptr_to(); + lhs_str = PointerCast(cx, lhs, llty_str_slice); + } + + compare_str(cx, lhs_str, rhs_str, rhs_t, debug_loc) }, _ => cx.sess().bug("only byte strings supported in compare_values"), }, @@ -1000,9 +1017,14 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, None => { let data = &m[0].data; for &(ref ident, ref value_ptr) in &m[0].bound_ptrs { - let llmatch = data.bindings_map[*ident].llmatch; - call_lifetime_start(bcx, llmatch); - Store(bcx, *value_ptr, llmatch); + let binfo = *data.bindings_map.get(ident).unwrap(); + call_lifetime_start(bcx, binfo.llmatch); + if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) { + expr::copy_fat_ptr(bcx, *value_ptr, binfo.llmatch); + } + else { + Store(bcx, *value_ptr, binfo.llmatch); + } } match data.arm.guard { Some(ref guard_expr) => { @@ -1025,7 +1047,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, m: &[Match<'a, 'p, 'blk, 'tcx>], vals: &[ValueRef], chk: &FailureHandler, - col: uint, + col: usize, val: ValueRef, has_genuine_default: bool) { let fcx = bcx.fcx; @@ -1070,7 +1092,6 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => None } }; - match adt_vals { Some(field_vals) => { let pats = enter_match(bcx, dm, m, col, val, |pats| @@ -1166,7 +1187,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let t = if kind == Compare { left_ty } else { - tcx.types.uint // vector length + tcx.types.usize // vector length }; let Result { bcx: after_cx, val: matches } = { match opt.trans(bcx) { @@ -1277,20 +1298,20 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body` fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool { let (vid, field) = match discr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) { + ast::ExprPath(..) => match bcx.def(discr.id) { def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None), _ => return false }, ast::ExprField(ref base, field) => { - let vid = match bcx.tcx().def_map.borrow().get(&base.id) { - Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid, + let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) { + Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid, _ => return false }; (vid, Some(mc::NamedField(field.node.name))) }, ast::ExprTupField(ref base, field) => { - let vid = match bcx.tcx().def_map.borrow().get(&base.id) { - Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid, + let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) { + Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid, _ => return false }; (vid, Some(mc::PositionalField(field.node))) @@ -1331,12 +1352,12 @@ impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker { fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) { match cmt.cat { mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) | - mc::cat_local(vid) => self.reassigned = self.node == vid, + mc::cat_local(vid) => self.reassigned |= self.node == vid, mc::cat_interior(ref base_cmt, mc::InteriorField(field)) => { match base_cmt.cat { mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) | mc::cat_local(vid) => { - self.reassigned = self.node == vid && Some(field) == self.field + self.reassigned |= self.node == vid && Some(field) == self.field }, _ => {} } @@ -1375,7 +1396,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, "__llmatch"); trmode = TrByCopy(alloca_no_lifetime(bcx, llvariable_ty, - &bcx.ident(ident)[])); + &bcx.ident(ident))); } ast::BindByValue(_) => { // in this case, the final type of the variable will be T, @@ -1383,13 +1404,13 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, // above llmatch = alloca_no_lifetime(bcx, llvariable_ty.ptr_to(), - &bcx.ident(ident)[]); + &bcx.ident(ident)); trmode = TrByMove; } ast::BindByRef(_) => { llmatch = alloca_no_lifetime(bcx, llvariable_ty, - &bcx.ident(ident)[]); + &bcx.ident(ident)); trmode = TrByRef; } }; @@ -1499,6 +1520,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, pat: &ast::Pat) -> Block<'blk, 'tcx> { + let _icx = push_ctxt("create_dummy_locals"); // create dummy memory for the variables if we have no // value to store into them immediately let tcx = bcx.tcx(); @@ -1506,7 +1528,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let scope = cleanup::var_scope(tcx, p_id); bcx = mk_binding_alloca( bcx, p_id, &path1.node, scope, (), - |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx }); + |(), bcx, llval, ty| { drop_done_fill_mem(bcx, llval, ty); bcx }); }); bcx } @@ -1610,7 +1632,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>, let var_ty = node_id_type(bcx, p_id); // Allocate memory on stack for the binding. - let llval = alloc_ty(bcx, var_ty, &bcx.ident(*ident)[]); + let llval = alloc_ty(bcx, var_ty, &bcx.ident(*ident)); // Subtle: be sure that we *populate* the memory *before* // we schedule the cleanup. @@ -1648,7 +1670,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if bcx.sess().asm_comments() { add_comment(bcx, &format!("bind_irrefutable_pat(pat={})", - pat.repr(bcx.tcx()))[]); + pat.repr(bcx.tcx()))); } let _indenter = indenter(); @@ -1676,8 +1698,14 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::BindByRef(_) => { // By ref binding: the value of the variable - // is the pointer `val` itself. - Store(bcx, val, llval); + // is the pointer `val` itself or fat pointer referenced by `val` + if type_is_fat_ptr(bcx.tcx(), ty) { + expr::copy_fat_ptr(bcx, val, llval); + } + else { + Store(bcx, val, llval); + } + bcx } } @@ -1689,7 +1717,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } ast::PatEnum(_, ref sub_pats) => { - let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).cloned(); + let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def()); match opt_def { Some(def::DefVariant(enum_id, var_id, _)) => { let repr = adt::represent_node(bcx, pat.id); diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index eaf6eaa2f0..fd1fff308d 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -45,6 +45,7 @@ pub use self::Repr::*; +#[allow(deprecated)] use std::num::Int; use std::rc::Rc; @@ -81,14 +82,18 @@ pub enum Repr<'tcx> { /// Structs with destructors need a dynamic destroyedness flag to /// avoid running the destructor too many times; this is included /// in the `Struct` if present. - Univariant(Struct<'tcx>, bool), + /// (The flag if nonzero, represents the initialization value to use; + /// if zero, then use no flag at all.) + Univariant(Struct<'tcx>, u8), /// General-case enums: for each case there is a struct, and they /// all start with a field for the discriminant. /// /// Types with destructors need a dynamic destroyedness flag to /// avoid running the destructor too many times; the last argument /// indicates whether such a flag is present. - General(IntType, Vec>, bool), + /// (The flag, if nonzero, represents the initialization value to use; + /// if zero, then use no flag at all.) + General(IntType, Vec>, u8), /// Two cases distinguished by a nullable pointer: the case with discriminant /// `nndiscr` must have single field which is known to be nonnull due to its type. /// The other case is known to be zero sized. Hence we represent the enum @@ -151,11 +156,59 @@ pub fn represent_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, repr } +macro_rules! repeat_u8_as_u32 { + ($name:expr) => { (($name as u32) << 24 | + ($name as u32) << 16 | + ($name as u32) << 8 | + ($name as u32)) } +} +macro_rules! repeat_u8_as_u64 { + ($name:expr) => { ((repeat_u8_as_u32!($name) as u64) << 32 | + (repeat_u8_as_u32!($name) as u64)) } +} + +pub const DTOR_NEEDED: u8 = 0xd4; +pub const DTOR_NEEDED_U32: u32 = repeat_u8_as_u32!(DTOR_NEEDED); +pub const DTOR_NEEDED_U64: u64 = repeat_u8_as_u64!(DTOR_NEEDED); +#[allow(dead_code)] +pub fn dtor_needed_usize(ccx: &CrateContext) -> usize { + match &ccx.tcx().sess.target.target.target_pointer_width[..] { + "32" => DTOR_NEEDED_U32 as usize, + "64" => DTOR_NEEDED_U64 as usize, + tws => panic!("Unsupported target word size for int: {}", tws), + } +} + +pub const DTOR_DONE: u8 = 0x1d; +pub const DTOR_DONE_U32: u32 = repeat_u8_as_u32!(DTOR_DONE); +pub const DTOR_DONE_U64: u64 = repeat_u8_as_u64!(DTOR_DONE); +#[allow(dead_code)] +pub fn dtor_done_usize(ccx: &CrateContext) -> usize { + match &ccx.tcx().sess.target.target.target_pointer_width[..] { + "32" => DTOR_DONE_U32 as usize, + "64" => DTOR_DONE_U64 as usize, + tws => panic!("Unsupported target word size for int: {}", tws), + } +} + +fn dtor_to_init_u8(dtor: bool) -> u8 { + if dtor { DTOR_NEEDED } else { 0 } +} + +pub trait GetDtorType<'tcx> { fn dtor_type(&self) -> Ty<'tcx>; } +impl<'tcx> GetDtorType<'tcx> for ty::ctxt<'tcx> { + fn dtor_type(&self) -> Ty<'tcx> { self.types.u8 } +} + +fn dtor_active(flag: u8) -> bool { + flag != 0 +} + fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Repr<'tcx> { match t.sty { ty::ty_tup(ref elems) => { - Univariant(mk_struct(cx, &elems[..], false, t), false) + Univariant(mk_struct(cx, &elems[..], false, t), 0) } ty::ty_struct(def_id, substs) => { let fields = ty::lookup_struct_fields(cx.tcx(), def_id); @@ -165,19 +218,19 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }).collect::>(); let packed = ty::lookup_packed(cx.tcx(), def_id); let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag(); - if dtor { ftys.push(cx.tcx().types.bool); } + if dtor { ftys.push(cx.tcx().dtor_type()); } - Univariant(mk_struct(cx, &ftys[..], packed, t), dtor) + Univariant(mk_struct(cx, &ftys[..], packed, t), dtor_to_init_u8(dtor)) } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let typer = NormalizingClosureTyper::new(cx.tcx()); let upvars = typer.closure_upvars(def_id, substs).unwrap(); let upvar_types = upvars.iter().map(|u| u.ty).collect::>(); - Univariant(mk_struct(cx, &upvar_types[..], false, t), false) + Univariant(mk_struct(cx, &upvar_types[..], false, t), 0) } ty::ty_enum(def_id, substs) => { let cases = get_cases(cx.tcx(), def_id, substs); - let hint = *ty::lookup_repr_hints(cx.tcx(), def_id)[].get(0) + let hint = *ty::lookup_repr_hints(cx.tcx(), def_id).get(0) .unwrap_or(&attr::ReprAny); let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag(); @@ -186,9 +239,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Uninhabitable; represent as unit // (Typechecking will reject discriminant-sizing attrs.) assert_eq!(hint, attr::ReprAny); - let ftys = if dtor { vec!(cx.tcx().types.bool) } else { vec!() }; + let ftys = if dtor { vec!(cx.tcx().dtor_type()) } else { vec!() }; return Univariant(mk_struct(cx, &ftys[..], false, t), - dtor); + dtor_to_init_u8(dtor)); } if !dtor && cases.iter().all(|c| c.tys.len() == 0) { @@ -210,7 +263,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, cx.sess().bug(&format!("non-C-like enum {} with specified \ discriminants", ty::item_path_str(cx.tcx(), - def_id))[]); + def_id))); } if cases.len() == 1 { @@ -218,9 +271,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // (Typechecking will reject discriminant-sizing attrs.) assert_eq!(hint, attr::ReprAny); let mut ftys = cases[0].tys.clone(); - if dtor { ftys.push(cx.tcx().types.bool); } + if dtor { ftys.push(cx.tcx().dtor_type()); } return Univariant(mk_struct(cx, &ftys[..], false, t), - dtor); + dtor_to_init_u8(dtor)); } if !dtor && cases.len() == 2 && hint == attr::ReprAny { @@ -228,7 +281,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut discr = 0; while discr < 2 { if cases[1 - discr].is_zerolen(cx, t) { - let st = mk_struct(cx, &cases[discr].tys[], + let st = mk_struct(cx, &cases[discr].tys, false, t); match cases[discr].find_ptr(cx) { Some(ref df) if df.len() == 1 && st.fields.len() == 1 => { @@ -266,7 +319,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let fields : Vec<_> = cases.iter().map(|c| { let mut ftys = vec!(ty_of_inttype(cx.tcx(), min_ity)); ftys.push_all(&c.tys); - if dtor { ftys.push(cx.tcx().types.bool); } + if dtor { ftys.push(cx.tcx().dtor_type()); } mk_struct(cx, &ftys, false, t) }).collect(); @@ -318,17 +371,17 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let fields : Vec<_> = cases.iter().map(|c| { let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity)); - ftys.push_all(&c.tys[]); - if dtor { ftys.push(cx.tcx().types.bool); } + ftys.push_all(&c.tys); + if dtor { ftys.push(cx.tcx().dtor_type()); } mk_struct(cx, &ftys[..], false, t) }).collect(); ensure_enum_fits_in_address_space(cx, &fields[..], t); - General(ity, fields, dtor) + General(ity, fields, dtor_to_init_u8(dtor)) } _ => cx.sess().bug(&format!("adt::represent_type called on non-ADT type: {}", - ty_to_string(cx.tcx(), t))[]) + ty_to_string(cx.tcx(), t))) } } @@ -339,7 +392,7 @@ struct Case<'tcx> { } /// This represents the (GEP) indices to follow to get to the discriminant field -pub type DiscrField = Vec; +pub type DiscrField = Vec; fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, @@ -414,7 +467,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>, impl<'tcx> Case<'tcx> { fn is_zerolen<'a>(&self, cx: &CrateContext<'a, 'tcx>, scapegoat: Ty<'tcx>) -> bool { - mk_struct(cx, &self.tys[], false, scapegoat).size == 0 + mk_struct(cx, &self.tys, false, scapegoat).size == 0 } fn find_ptr<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Option { @@ -487,12 +540,12 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp debug!("range_to_inttype: {:?} {:?}", hint, bounds); // Lists of sizes to try. u64 is always allowed as a fallback. #[allow(non_upper_case_globals)] - static choose_shortest: &'static[IntType] = &[ + const choose_shortest: &'static [IntType] = &[ attr::UnsignedInt(ast::TyU8), attr::SignedInt(ast::TyI8), attr::UnsignedInt(ast::TyU16), attr::SignedInt(ast::TyI16), attr::UnsignedInt(ast::TyU32), attr::SignedInt(ast::TyI32)]; #[allow(non_upper_case_globals)] - static at_least_32: &'static[IntType] = &[ + const at_least_32: &'static [IntType] = &[ attr::UnsignedInt(ast::TyU32), attr::SignedInt(ast::TyI32)]; let attempts; @@ -504,7 +557,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp return ity; } attr::ReprExtern => { - attempts = match &cx.sess().target.target.arch[] { + attempts = match &cx.sess().target.target.arch[..] { // WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32` // appears to be used on Linux and NetBSD, but some systems may use the variant // corresponding to `choose_shortest`. However, we don't run on those yet...? @@ -624,7 +677,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, match *r { CEnum(..) | General(..) | RawNullablePointer { .. } => { } Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => - llty.set_struct_body(&struct_llfields(cx, st, false, false)[], + llty.set_struct_body(&struct_llfields(cx, st, false, false), st.packed) } } @@ -640,7 +693,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => { match name { None => { - Type::struct_(cx, &struct_llfields(cx, st, sizing, dst)[], + Type::struct_(cx, &struct_llfields(cx, st, sizing, dst), st.packed) } Some(name) => { assert_eq!(sizing, false); Type::named_struct(cx, name) } @@ -699,7 +752,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>, st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty)) .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { - st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect() + st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect() } } @@ -776,9 +829,11 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) assert_eq!(val_ty(ptr), llty.ptr_to()); let bits = machine::llbitsize_of_real(bcx.ccx(), llty); assert!(bits <= 64); - let bits = bits as uint; - let mask = (-1u64 >> (64 - bits)) as Disr; - if (max + 1) & mask == min & mask { + let bits = bits as usize; + let mask = (!0u64 >> (64 - bits)) as Disr; + // For a (max) discr of -1, max will be `-1 as usize`, which overflows. + // However, that is fine here (it would still represent the full range), + if (max.wrapping_add(1)) & mask == min & mask { // i.e., if the range is everything. The lo==hi case would be // rejected by the LLVM verifier (it would mean either an // empty set, which is impossible, or the entire range of the @@ -787,7 +842,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) } else { // llvm::ConstantRange can deal with ranges that wrap around, // so an overflow on (max + 1) is fine. - LoadRangeAssert(bcx, ptr, min, (max+1), /* signed: */ True) + LoadRangeAssert(bcx, ptr, min, (max.wrapping_add(1)), /* signed: */ True) } } @@ -828,18 +883,18 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val) } General(ity, ref cases, dtor) => { - if dtor { + if dtor_active(dtor) { let ptr = trans_field_ptr(bcx, r, val, discr, - cases[discr as uint].fields.len() - 2); - Store(bcx, C_u8(bcx.ccx(), 1), ptr); + cases[discr as usize].fields.len() - 2); + Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED as usize), ptr); } Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true), GEPi(bcx, val, &[0, 0])) } Univariant(ref st, dtor) => { assert_eq!(discr, 0); - if dtor { - Store(bcx, C_u8(bcx.ccx(), 1), + if dtor_active(dtor) { + Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED as usize), GEPi(bcx, val, &[0, st.fields.len() - 1])); } } @@ -868,15 +923,15 @@ fn assert_discr_in_range(ity: IntType, min: Disr, max: Disr, discr: Disr) { /// The number of fields in a given case; for use when obtaining this /// information from the type or definition is less convenient. -pub fn num_args(r: &Repr, discr: Disr) -> uint { +pub fn num_args(r: &Repr, discr: Disr) -> usize { match *r { CEnum(..) => 0, Univariant(ref st, dtor) => { assert_eq!(discr, 0); - st.fields.len() - (if dtor { 1 } else { 0 }) + st.fields.len() - (if dtor_active(dtor) { 1 } else { 0 }) } General(_, ref cases, dtor) => { - cases[discr as uint].fields.len() - 1 - (if dtor { 1 } else { 0 }) + cases[discr as usize].fields.len() - 1 - (if dtor_active(dtor) { 1 } else { 0 }) } RawNullablePointer { nndiscr, ref nullfields, .. } => { if discr == nndiscr { 1 } else { nullfields.len() } @@ -890,7 +945,7 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint { /// Access a field, at a point when the value's case is known. pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, - val: ValueRef, discr: Disr, ix: uint) -> ValueRef { + val: ValueRef, discr: Disr, ix: usize) -> ValueRef { // Note: if this ever needs to generate conditionals (e.g., if we // decide to do some kind of cdr-coding-like non-unique repr // someday), it will need to return a possibly-new bcx as well. @@ -903,7 +958,7 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, struct_field_ptr(bcx, st, val, ix, false) } General(_, ref cases, _) => { - struct_field_ptr(bcx, &cases[discr as uint], val, ix + 1, true) + struct_field_ptr(bcx, &cases[discr as usize], val, ix + 1, true) } RawNullablePointer { nndiscr, ref nullfields, .. } | StructWrappedNullablePointer { nndiscr, ref nullfields, .. } if discr != nndiscr => { @@ -929,7 +984,7 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, } pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, val: ValueRef, - ix: uint, needs_cast: bool) -> ValueRef { + ix: usize, needs_cast: bool) -> ValueRef { let val = if needs_cast { let ccx = bcx.ccx(); let fields = st.fields.iter().map(|&ty| type_of::type_of(ccx, ty)).collect::>(); @@ -965,7 +1020,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, for (discr, case) in cases.iter().enumerate() { let mut variant_cx = fcx.new_temp_block( - &format!("enum-variant-iter-{}", &discr.to_string())[] + &format!("enum-variant-iter-{}", &discr.to_string()) ); let rhs_val = C_integral(ll_inttype(ccx, ity), discr as u64, true); AddCase(llswitch, rhs_val, variant_cx.llbb); @@ -990,17 +1045,17 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx -> datum::DatumBlock<'blk, 'tcx, datum::Expr> { let tcx = bcx.tcx(); - let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.types.bool); + let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.dtor_type()); match *r { - Univariant(ref st, true) => { + Univariant(ref st, dtor) if dtor_active(dtor) => { let flag_ptr = GEPi(bcx, val, &[0, st.fields.len() - 1]); datum::immediate_rvalue_bcx(bcx, flag_ptr, ptr_ty).to_expr_datumblock() } - General(_, _, true) => { + General(_, _, dtor) if dtor_active(dtor) => { let fcx = bcx.fcx; let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum( - bcx, tcx.types.bool, "drop_flag", false, + bcx, tcx.dtor_type(), "drop_flag", cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx )); bcx = fold_variants(bcx, r, val, |variant_cx, st, value| { @@ -1044,7 +1099,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr C_integral(ll_inttype(ccx, ity), discr as u64, true) } General(ity, ref cases, _) => { - let case = &cases[discr as uint]; + let case = &cases[discr as usize]; let (max_sz, _) = union_size_and_align(&cases[..]); let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true); let mut f = vec![lldiscr]; @@ -1070,7 +1125,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr if discr == nndiscr { C_struct(ccx, &build_const_struct(ccx, nonnull, - vals)[], + vals), false) } else { let vals = nonnull.fields.iter().map(|&ty| { @@ -1080,7 +1135,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr }).collect::>(); C_struct(ccx, &build_const_struct(ccx, nonnull, - &vals[..])[], + &vals[..]), false) } } @@ -1182,7 +1237,7 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef) -> Disr { /// (Not to be confused with `common::const_get_elt`, which operates on /// raw LLVM-level structs and arrays.) pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef, - _discr: Disr, ix: uint) -> ValueRef { + _discr: Disr, ix: usize) -> ValueRef { match *r { CEnum(..) => ccx.sess().bug("element access in C-like enum const"), Univariant(..) => const_struct_field(ccx, val, ix), @@ -1196,7 +1251,7 @@ pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef, } /// Extract field of struct-like const, skipping our alignment padding. -fn const_struct_field(ccx: &CrateContext, val: ValueRef, ix: uint) -> ValueRef { +fn const_struct_field(ccx: &CrateContext, val: ValueRef, ix: usize) -> ValueRef { // Get the ix-th non-undef element of the struct. let mut real_ix = 0; // actual position in the struct let mut ix = ix; // logical index relative to real_ix diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index a3bd0cf6b1..d6c85e8b17 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -76,43 +76,33 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) // no failure occurred preparing operands, no need to cleanup fcx.pop_custom_cleanup_scope(temp_scope); - let mut constraints = constraints.iter() - .map(|s| s.to_string()) - .chain(ext_constraints.into_iter()) - .collect::>() - .connect(","); - - let mut clobbers = ia.clobbers.iter() - .map(|s| format!("~{{{}}}", &s)) - .collect::>() - .connect(","); - let more_clobbers = get_clobbers(); - if !more_clobbers.is_empty() { - if !clobbers.is_empty() { - clobbers.push(','); - } - clobbers.push_str(&more_clobbers[..]); - } - - // Add the clobbers to our constraints list - if clobbers.len() != 0 && constraints.len() != 0 { - constraints.push(','); - constraints.push_str(&clobbers[..]); - } else { - constraints.push_str(&clobbers[..]); - } + let clobbers = ia.clobbers.iter() + .map(|s| format!("~{{{}}}", &s)); + + // Default per-arch clobbers + // Basically what clang does + let arch_clobbers = match &bcx.sess().target.target.arch[..] { + "x86" | "x86_64" => vec!("~{dirflag}", "~{fpsr}", "~{flags}"), + _ => Vec::new() + }; - debug!("Asm Constraints: {}", &constraints[..]); + let all_constraints= constraints.iter() + .map(|s| s.to_string()) + .chain(ext_constraints.into_iter()) + .chain(clobbers) + .chain(arch_clobbers.iter() + .map(|s| s.to_string())) + .collect::>() + .connect(","); - let num_outputs = outputs.len(); + debug!("Asm Constraints: {}", &all_constraints[..]); // Depending on how many outputs we have, the return type is different - let output_type = if num_outputs == 0 { - Type::void(bcx.ccx()) - } else if num_outputs == 1 { - output_types[0] - } else { - Type::struct_(bcx.ccx(), &output_types[..], false) + let num_outputs = outputs.len(); + let output_type = match num_outputs { + 0 => Type::void(bcx.ccx()), + 1 => output_types[0], + _ => Type::struct_(bcx.ccx(), &output_types[..], false) }; let dialect = match ia.dialect { @@ -121,10 +111,10 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) }; let asm = CString::new(ia.asm.as_bytes()).unwrap(); - let constraints = CString::new(constraints).unwrap(); + let constraint_cstr = CString::new(all_constraints).unwrap(); let r = InlineAsmCall(bcx, asm.as_ptr(), - constraints.as_ptr(), + constraint_cstr.as_ptr(), &inputs, output_type, ia.volatile, @@ -158,15 +148,3 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) } -// Default per-arch clobbers -// Basically what clang does - -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn get_clobbers() -> String { - "".to_string() -} - -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn get_clobbers() -> String { - "~{dirflag},~{fpsr},~{flags}".to_string() -} diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 3091c852f5..05c366a645 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -30,10 +30,10 @@ pub use self::ValueOrigin::*; use super::CrateTranslation; use super::ModuleTranslation; -use back::link::{mangle_exported_name}; +use back::link::mangle_exported_name; use back::{link, abi}; use lint; -use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param}; +use llvm::{AttrHelper, BasicBlockRef, Linkage, ValueRef, Vector, get_param}; use llvm; use metadata::{csearch, encoder, loader}; use middle::astencode; @@ -41,7 +41,7 @@ use middle::cfg; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use middle::weak_lang_items; use middle::subst::{Subst, Substs}; -use middle::ty::{self, Ty, ClosureTyper}; +use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size}; use session::config::{self, NoDebugInfo}; use session::Session; use trans::_match; @@ -52,13 +52,12 @@ use trans::callee; use trans::cleanup::CleanupMethods; use trans::cleanup; use trans::closure; -use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral}; +use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral}; use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef}; use trans::common::{CrateContext, ExternMap, FunctionContext}; use trans::common::{Result, NodeIdAndSpan}; use trans::common::{node_id_type, return_type_is_void}; -use trans::common::{tydesc_info, type_is_immediate}; -use trans::common::{type_is_zero_size, val_ty}; +use trans::common::{type_is_immediate, type_is_zero_size, val_ty}; use trans::common; use trans::consts; use trans::context::SharedCrateContext; @@ -90,7 +89,6 @@ use std::ffi::{CStr, 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}; @@ -153,7 +151,7 @@ pub fn push_ctxt(s: &'static str) -> _InsnCtxt { pub struct StatRecorder<'a, 'tcx: 'a> { ccx: &'a CrateContext<'a, 'tcx>, name: Option, - istart: uint, + istart: usize, } impl<'a, 'tcx> StatRecorder<'a, 'tcx> { @@ -271,7 +269,7 @@ pub fn self_type_for_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } pub fn kind_for_closure(ccx: &CrateContext, closure_id: ast::DefId) -> ty::ClosureKind { - ccx.tcx().closure_kinds.borrow()[closure_id] + *ccx.tcx().closure_kinds.borrow().get(&closure_id).unwrap() } pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, @@ -291,7 +289,7 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::ty_bare_fn(_, ref f) => { (&f.sig, f.abi, None) } - ty::ty_closure(closure_did, _, substs) => { + ty::ty_closure(closure_did, substs) => { let typer = common::NormalizingClosureTyper::new(ccx.tcx()); function_type = typer.closure_type(closure_did, substs); let self_type = self_type_for_closure(ccx, closure_did, fn_ty); @@ -301,7 +299,7 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, self_type.repr(ccx.tcx())); (&function_type.sig, RustCall, Some(llenvironment_type)) } - _ => panic!("expected closure or fn") + _ => ccx.sess().bug("expected closure or fn") }; let sig = ty::erase_late_bound_regions(ccx.tcx(), sig); @@ -365,7 +363,7 @@ fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Err(s) => { bcx.sess().fatal(&format!("allocation of `{}` {}", bcx.ty_to_string(info_ty), - s)[]); + s)); } } } @@ -392,22 +390,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) } -// Type descriptor and type glue stuff - -pub fn get_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - t: Ty<'tcx>) -> Rc> { - match ccx.tydescs().borrow().get(&t) { - Some(inf) => return inf.clone(), - _ => { } - } - - ccx.stats().n_static_tydescs.set(ccx.stats().n_static_tydescs.get() + 1); - let inf = Rc::new(glue::declare_tydesc(ccx, t)); - - ccx.tydescs().borrow_mut().insert(t, inf.clone()); - inf -} - #[allow(dead_code)] // useful pub fn set_optimize_for_size(f: ValueRef) { llvm::SetFunctionAttribute(f, llvm::OptimizeForSizeAttribute) @@ -433,29 +415,27 @@ pub fn set_inline_hint(f: ValueRef) { } pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) { - use syntax::attr::*; + use syntax::attr::{find_inline_attr, InlineAttr}; // Set the inline hint if there is one - match find_inline_attr(attrs) { - InlineHint => set_inline_hint(llfn), - InlineAlways => set_always_inline(llfn), - InlineNever => set_no_inline(llfn), - InlineNone => { /* fallthrough */ } + match find_inline_attr(Some(ccx.sess().diagnostic()), attrs) { + InlineAttr::Hint => set_inline_hint(llfn), + InlineAttr::Always => set_always_inline(llfn), + InlineAttr::Never => set_no_inline(llfn), + InlineAttr::None => { /* fallthrough */ } } for attr in attrs { let mut used = true; - match &attr.name()[] { + match &attr.name()[..] { "no_stack_check" => unset_split_stack(llfn), - "no_split_stack" => { - unset_split_stack(llfn); - ccx.sess().span_warn(attr.span, - "no_split_stack is a deprecated synonym for no_stack_check"); - } "cold" => unsafe { llvm::LLVMAddFunctionAttribute(llfn, llvm::FunctionIndex as c_uint, llvm::ColdAttribute as uint64_t) }, + "allocator" => { + llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn); + } _ => used = false, } if used { @@ -486,7 +466,7 @@ pub fn unset_split_stack(f: ValueRef) { // silently mangles such symbols, breaking our linkage model. pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: String) { if ccx.all_llvm_symbols().borrow().contains(&sym) { - ccx.sess().bug(&format!("duplicate LLVM symbol: {}", sym)[]); + ccx.sess().bug(&format!("duplicate LLVM symbol: {}", sym)); } ccx.all_llvm_symbols().borrow_mut().insert(sym); } @@ -541,7 +521,7 @@ pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: ast::BinOp_, signed: boo ast::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE }, op => { ccx.sess().bug(&format!("comparison_op_to_icmp_predicate: expected \ - comparison operator, found {:?}", op)[]); + comparison operator, found {:?}", op)); } } } @@ -557,7 +537,7 @@ pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: ast::BinOp_) ast::BiGe => llvm::RealOGE, op => { ccx.sess().bug(&format!("comparison_op_to_fcmp_predicate: expected \ - comparison operator, found {:?}", op)[]); + comparison operator, found {:?}", op)); } } } @@ -580,7 +560,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator") } } - ty::ty_bool | ty::ty_uint(_) | ty::ty_char => { + ty::ty_bare_fn(..) | ty::ty_bool | ty::ty_uint(_) | ty::ty_char => { ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc) } ty::ty_ptr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => { @@ -676,8 +656,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, let val = if common::type_is_sized(cx.tcx(), field_ty) { llfld_a } else { - let boxed_ty = ty::mk_open(cx.tcx(), field_ty); - let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter"); + let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter"); Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR])); Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA])); scratch.val @@ -686,7 +665,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, } }) } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let repr = adt::represent_type(cx.ccx(), t); let typer = common::NormalizingClosureTyper::new(cx.tcx()); let upvars = typer.closure_upvars(def_id, substs).unwrap(); @@ -700,6 +679,10 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, let unit_ty = ty::sequence_element_type(cx.tcx(), t); cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f); } + ty::ty_vec(_, None) | ty::ty_str => { + let unit_ty = ty::sequence_element_type(cx.tcx(), t); + cx = tvec::iter_vec_raw(cx, data_ptr, unit_ty, info.unwrap(), f); + } ty::ty_tup(ref args) => { let repr = adt::represent_type(cx.ccx(), t); for (i, arg) in args.iter().enumerate() { @@ -724,7 +707,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, substs, &mut f); } (_match::Switch, Some(lldiscrim_a)) => { - cx = f(cx, lldiscrim_a, cx.tcx().types.int); + cx = f(cx, lldiscrim_a, cx.tcx().types.isize); let unr_cx = fcx.new_temp_block("enum-iter-unr"); Unreachable(unr_cx); let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, @@ -735,8 +718,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, let variant_cx = fcx.new_temp_block( &format!("enum-iter-variant-{}", - &variant.disr_val.to_string()[]) - []); + &variant.disr_val.to_string()) + ); match adt::trans_case(cx, &*repr, variant.disr_val) { _match::SingleResult(r) => { AddCase(llswitch, r.val, variant_cx.llbb) @@ -761,14 +744,14 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, } _ => { cx.sess().unimpl(&format!("type in iter_structural_ty: {}", - ty_to_string(cx.tcx(), t))[]) + ty_to_string(cx.tcx(), t))) } } return cx; } pub fn cast_shift_expr_rhs(cx: Block, - op: ast::BinOp, + op: ast::BinOp_, lhs: ValueRef, rhs: ValueRef) -> ValueRef { @@ -777,24 +760,24 @@ pub fn cast_shift_expr_rhs(cx: Block, |a,b| ZExt(cx, a, b)) } -pub fn cast_shift_const_rhs(op: ast::BinOp, +pub fn cast_shift_const_rhs(op: ast::BinOp_, lhs: ValueRef, rhs: ValueRef) -> ValueRef { cast_shift_rhs(op, lhs, rhs, |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) }, |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) }) } -pub fn cast_shift_rhs(op: ast::BinOp, - lhs: ValueRef, - rhs: ValueRef, - trunc: F, - zext: G) - -> ValueRef where +fn cast_shift_rhs(op: ast::BinOp_, + lhs: ValueRef, + rhs: ValueRef, + trunc: F, + zext: G) + -> ValueRef where F: FnOnce(ValueRef, Type) -> ValueRef, G: FnOnce(ValueRef, Type) -> ValueRef, { // Shifts may have any size int on the rhs - if ast_util::is_shift_binop(op.node) { + if ast_util::is_shift_binop(op) { let mut rhs_llty = val_ty(rhs); let mut lhs_llty = val_ty(lhs); if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() } @@ -834,16 +817,25 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( let (is_zero, is_signed) = match rhs_t.sty { ty::ty_int(t) => { - let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0u64, false); + let zero = C_integral(Type::int_from_ty(cx.ccx(), t), 0, false); (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), true) } ty::ty_uint(t) => { - let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0u64, false); + let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false); (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false) } + ty::ty_struct(_, _) if type_is_simd(cx.tcx(), rhs_t) => { + let mut res = C_bool(cx.ccx(), false); + for i in 0 .. simd_size(cx.tcx(), rhs_t) { + res = Or(cx, res, + IsNull(cx, + ExtractElement(cx, rhs, C_int(cx.ccx(), i as i64))), debug_loc); + } + (res, false) + } _ => { cx.sess().bug(&format!("fail-if-zero on unexpected type: {}", - ty_to_string(cx.tcx(), rhs_t))[]); + ty_to_string(cx.tcx(), rhs_t))); } }; let bcx = with_cond(cx, is_zero, |bcx| { @@ -864,8 +856,8 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( ty::ty_int(t) => { let llty = Type::int_from_ty(cx.ccx(), t); let min = match t { - ast::TyIs(_) if llty == Type::i32(cx.ccx()) => i32::MIN as u64, - ast::TyIs(_) => i64::MIN as u64, + ast::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64, + ast::TyIs => i64::MIN as u64, ast::TyI8 => i8::MIN as u64, ast::TyI16 => i16::MIN as u64, ast::TyI32 => i32::MIN as u64, @@ -876,7 +868,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>( _ => unreachable!(), }; let minus_one = ICmp(bcx, llvm::IntEQ, rhs, - C_integral(llty, -1, false), debug_loc); + C_integral(llty, !0, false), debug_loc); with_cond(bcx, minus_one, |bcx| { let is_min = ICmp(bcx, llvm::IntEQ, lhs, C_integral(llty, min, true), debug_loc); @@ -904,8 +896,10 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.sess().bug("unexpected intrinsic in trans_external_path") } _ => { - foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, - &name[..]) + let llfn = foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, &name[..]); + let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did); + set_llvm_fn_attrs(ccx, &attrs, llfn); + llfn } } } @@ -993,56 +987,72 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, /// gives us better information about what we are loading. pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { - if type_is_zero_size(cx.ccx(), t) { - C_undef(type_of::type_of(cx.ccx(), t)) - } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { - // We want to pass small aggregates as immediate values, but using an aggregate LLVM type - // for this leads to bad optimizations, so its arg type is an appropriately sized integer - // and we have to convert it - Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to())) - } else { - unsafe { - let global = llvm::LLVMIsAGlobalVariable(ptr); - if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { - let val = llvm::LLVMGetInitializer(global); - if !val.is_null() { - // This could go into its own function, for DRY. - // (something like "pre-store packing/post-load unpacking") - if ty::type_is_bool(t) { - return Trunc(cx, val, Type::i1(cx.ccx())); - } else { - return val; - } - } + if cx.unreachable.get() || type_is_zero_size(cx.ccx(), t) { + return C_undef(type_of::type_of(cx.ccx(), t)); + } + + let ptr = to_arg_ty_ptr(cx, ptr, t); + + if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { + return Load(cx, ptr); + } + + unsafe { + let global = llvm::LLVMIsAGlobalVariable(ptr); + if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { + let val = llvm::LLVMGetInitializer(global); + if !val.is_null() { + return from_arg_ty(cx, val, t); } } - if ty::type_is_bool(t) { - Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx())) - } else if ty::type_is_char(t) { - // a char is a Unicode codepoint, and so takes values from 0 - // to 0x10FFFF inclusive only. - LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False) - } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t)) - && !common::type_is_fat_ptr(cx.tcx(), t) { - LoadNonNull(cx, ptr) - } else { - Load(cx, ptr) - } } + + let val = if ty::type_is_bool(t) { + LoadRangeAssert(cx, ptr, 0, 2, llvm::False) + } else if ty::type_is_char(t) { + // a char is a Unicode codepoint, and so takes values from 0 + // to 0x10FFFF inclusive only. + LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False) + } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t)) + && !common::type_is_fat_ptr(cx.tcx(), t) { + LoadNonNull(cx, ptr) + } else { + Load(cx, ptr) + }; + + from_arg_ty(cx, val, t) } /// Helper for storing values in memory. Does the necessary conversion if the in-memory type /// differs from the type used for SSA values. pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) { - if ty::type_is_bool(t) { - Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst); - } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { + Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t)); +} + +pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef { + if ty::type_is_bool(ty) { + ZExt(bcx, val, Type::i8(bcx.ccx())) + } else { + val + } +} + +pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef { + if ty::type_is_bool(ty) { + Trunc(bcx, val, Type::i1(bcx.ccx())) + } else { + val + } +} + +pub fn to_arg_ty_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, ty: Ty<'tcx>) -> ValueRef { + if type_is_immediate(bcx.ccx(), ty) && type_of::type_of(bcx.ccx(), ty).is_aggregate() { // We want to pass small aggregates as immediate values, but using an aggregate LLVM type // for this leads to bad optimizations, so its arg type is an appropriately sized integer // and we have to convert it - Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to())); + BitCast(bcx, ptr, type_of::arg_type_of(bcx.ccx(), ty).ptr_to()) } else { - Store(cx, v, dst); + ptr } } @@ -1116,7 +1126,7 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) { pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { let _icx = push_ctxt("call_memcpy"); let ccx = cx.ccx(); - let key = match &ccx.sess().target.target.target_pointer_width[] { + let key = match &ccx.sess().target.target.target_pointer_width[..] { "32" => "llvm.memcpy.p0i8.p0i8.i32", "64" => "llvm.memcpy.p0i8.p0i8.i64", tws => panic!("Unsupported target word size for memcpy: {}", tws), @@ -1145,25 +1155,32 @@ pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -pub fn zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) { +pub fn drop_done_fill_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) { + if cx.unreachable.get() { return; } + let _icx = push_ctxt("drop_done_fill_mem"); + let bcx = cx; + memfill(&B(bcx), llptr, t, adt::DTOR_DONE); +} + +pub fn init_zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) { if cx.unreachable.get() { return; } - let _icx = push_ctxt("zero_mem"); + let _icx = push_ctxt("init_zero_mem"); let bcx = cx; - memzero(&B(bcx), llptr, t); + memfill(&B(bcx), llptr, t, 0); } -// Always use this function instead of storing a zero constant to the memory -// in question. If you store a zero constant, LLVM will drown in vreg +// Always use this function instead of storing a constant byte to the memory +// in question. e.g. if you store a zero constant, LLVM will drown in vreg // allocation for large data structures, and the generated code will be // awful. (A telltale sign of this is large quantities of // `mov [byte ptr foo],0` in the generated code.) -fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) { - let _icx = push_ctxt("memzero"); +fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte: u8) { + let _icx = push_ctxt("memfill"); let ccx = b.ccx; let llty = type_of::type_of(ccx, ty); - let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[] { + let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[..] { "32" => "llvm.memset.p0i8.i32", "64" => "llvm.memset.p0i8.i64", tws => panic!("Unsupported target word size for memset: {}", tws), @@ -1171,7 +1188,7 @@ fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) { let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key); let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to()); - let llzeroval = C_u8(ccx, 0); + let llzeroval = C_u8(ccx, byte as usize); let size = machine::llsize_of(ccx, llty); let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32); let volatile = C_bool(ccx, false); @@ -1204,21 +1221,6 @@ pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef { Alloca(cx, ty, name) } -pub fn alloca_zeroed<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty: Ty<'tcx>, - name: &str) -> ValueRef { - let llty = type_of::type_of(cx.ccx(), ty); - if cx.unreachable.get() { - unsafe { - return llvm::LLVMGetUndef(llty.ptr_to().to_ref()); - } - } - let p = alloca_no_lifetime(cx, llty, name); - let b = cx.fcx.ccx.builder(); - b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); - memzero(&b, p, ty); - p -} - // Creates the alloca slot which holds the pointer to the slot for the final return value pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, output_type: Ty<'tcx>) -> ValueRef { @@ -1284,47 +1286,35 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option) _ => tcx.sess.bug("unexpected item variant in has_nested_returns") } } - Some(ast_map::NodeTraitItem(trait_method)) => { - match *trait_method { - ast::ProvidedMethod(ref m) => { - match m.node { - ast::MethDecl(_, _, _, _, _, _, ref blk, _) => { - blk - } - ast::MethMac(_) => tcx.sess.bug("unexpanded macro") - } - } - ast::RequiredMethod(_) => { + Some(ast_map::NodeTraitItem(trait_item)) => { + match trait_item.node { + ast::MethodTraitItem(_, Some(ref body)) => body, + ast::MethodTraitItem(_, None) => { tcx.sess.bug("unexpected variant: required trait method \ in has_nested_returns") } - ast::TypeTraitItem(_) => { - tcx.sess.bug("unexpected variant: type trait item in \ + ast::TypeTraitItem(..) => { + tcx.sess.bug("unexpected variant: associated type trait item in \ has_nested_returns") } } } - Some(ast_map::NodeImplItem(ii)) => { - match *ii { - ast::MethodImplItem(ref m) => { - match m.node { - ast::MethDecl(_, _, _, _, _, _, ref blk, _) => { - blk - } - ast::MethMac(_) => tcx.sess.bug("unexpanded macro") - } - } + Some(ast_map::NodeImplItem(impl_item)) => { + match impl_item.node { + ast::MethodImplItem(_, ref body) => body, ast::TypeImplItem(_) => { - tcx.sess.bug("unexpected variant: type impl item in \ + tcx.sess.bug("unexpected variant: associated type impl item in \ + has_nested_returns") + } + ast::MacImplItem(_) => { + tcx.sess.bug("unexpected variant: unexpanded macro impl item in \ has_nested_returns") } } } Some(ast_map::NodeExpr(e)) => { match e.node { - ast::ExprClosure(_, _, ref blk) => { - blk - } + ast::ExprClosure(_, _, ref blk) => blk, _ => tcx.sess.bug("unexpected expr variant in has_nested_returns") } } @@ -1338,7 +1328,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option) tcx.map.path_to_string(id))) }; - (blk.id, Some(cfg::CFG::new(tcx, &**blk))) + (blk.id, Some(cfg::CFG::new(tcx, blk))) } // Checks for the presence of "nested returns" in a function. @@ -1353,7 +1343,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option) // the clobbering of the existing value in the return slot. fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool { for n in cfg.graph.depth_traverse(cfg.entry) { - match tcx.map.find(n.id) { + match tcx.map.find(n.id()) { Some(ast_map::NodeExpr(ex)) => { if let ast::ExprRet(Some(ref ret_expr)) = ex.node { let mut visitor = FindNestedReturn::new(); @@ -1398,7 +1388,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, common::validate_substs(param_substs); debug!("new_fn_ctxt(path={}, id={}, param_substs={})", - if id == -1 { + if id == !0 { "".to_string() } else { ccx.tcx().map.path_to_string(id).to_string() @@ -1501,7 +1491,7 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>) } // work around bizarre resolve errors -type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; +pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; // create_datums_for_fn_args: creates rvalue datums for each of the // incoming function arguments. These will later be stored into @@ -1548,7 +1538,6 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>( datum::lvalue_scratch_datum(bcx, arg_ty, "tupled_args", - false, tuple_args_scope_id, (), |(), @@ -1613,55 +1602,6 @@ fn copy_args_to_allocas<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx } -fn copy_closure_args_to_allocas<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, - arg_scope: cleanup::CustomScopeIndex, - args: &[ast::Arg], - arg_datums: Vec>, - monomorphized_arg_types: &[Ty<'tcx>]) - -> Block<'blk, 'tcx> { - let _icx = push_ctxt("copy_closure_args_to_allocas"); - let arg_scope_id = cleanup::CustomScope(arg_scope); - - assert_eq!(arg_datums.len(), 1); - - let arg_datum = arg_datums.into_iter().next().unwrap(); - - // Untuple the rest of the arguments. - let tuple_datum = - unpack_datum!(bcx, - arg_datum.to_lvalue_datum_in_scope(bcx, - "argtuple", - arg_scope_id)); - let untupled_arg_types = match monomorphized_arg_types[0].sty { - ty::ty_tup(ref types) => &types[..], - _ => { - bcx.tcx().sess.span_bug(args[0].pat.span, - "first arg to `rust-call` ABI function \ - wasn't a tuple?!") - } - }; - for j in 0..args.len() { - let tuple_element_type = untupled_arg_types[j]; - let tuple_element_datum = - tuple_datum.get_element(bcx, - tuple_element_type, - |llval| GEPi(bcx, llval, &[0, j])); - let tuple_element_datum = tuple_element_datum.to_expr_datum(); - let tuple_element_datum = - unpack_datum!(bcx, - tuple_element_datum.to_rvalue_datum(bcx, - "arg")); - bcx = _match::store_arg(bcx, - &*args[j].pat, - tuple_element_datum, - arg_scope_id); - - debuginfo::create_argument_metadata(bcx, &args[j]); - } - - bcx -} - // Ties up the llstaticallocas -> llloadenv -> lltop edges, // and builds the return block. pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, @@ -1819,33 +1759,18 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("trans_closure: function lltype: {}", bcx.fcx.ccx.tn().val_to_string(bcx.fcx.llfn)); - let arg_datums = if abi != RustCall { - create_datums_for_fn_args(&fcx, - &monomorphized_arg_types[..]) - } else { - create_datums_for_fn_args_under_call_abi( - bcx, - arg_scope, - &monomorphized_arg_types[..]) - }; - - bcx = match closure_env { - closure::ClosureEnv::NotClosure => { - copy_args_to_allocas(bcx, - arg_scope, - &decl.inputs[], - arg_datums) + let arg_datums = match closure_env { + closure::ClosureEnv::NotClosure if abi == RustCall => { + create_datums_for_fn_args_under_call_abi(bcx, arg_scope, &monomorphized_arg_types[..]) } - closure::ClosureEnv::Closure(_) => { - copy_closure_args_to_allocas( - bcx, - arg_scope, - &decl.inputs[], - arg_datums, - &monomorphized_arg_types[..]) + _ => { + let arg_tys = untuple_arguments_if_necessary(ccx, &monomorphized_arg_types, abi); + create_datums_for_fn_args(&fcx, &arg_tys) } }; + bcx = copy_args_to_allocas(bcx, arg_scope, &decl.inputs, arg_datums); + bcx = closure_env.load(bcx, cleanup::CustomScope(arg_scope)); // Up until here, IR instructions for this function have explicitly not been annotated with @@ -1964,7 +1889,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().bug( &format!("trans_enum_variant_constructor: \ unexpected ctor return type {}", - ctor_ty.repr(tcx))[]) + ctor_ty.repr(tcx))) }; // Get location to store the result. If the user does not care about @@ -2042,7 +1967,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx _ => ccx.sess().bug( &format!("trans_enum_variant_or_tuple_like_struct: \ unexpected ctor return type {}", - ty_to_string(ccx.tcx(), ctor_ty))[]) + ty_to_string(ccx.tcx(), ctor_ty))) }; let (arena, fcx): (TypedArena<_>, FunctionContext); @@ -2143,7 +2068,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, *lvlsrc.unwrap(), Some(sp), &format!("enum variant is more than three times larger \ ({} bytes) than the next largest (ignoring padding)", - largest)[]); + largest)); ccx.sess().span_note(enum_def.variants[largest_index].span, "this variant is the largest"); @@ -2187,7 +2112,7 @@ pub fn llvm_linkage_by_name(name: &str) -> Option { /// Enum describing the origin of an LLVM `Value`, for linkage purposes. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum ValueOrigin { /// The LLVM `Value` is in this context because the corresponding item was /// assigned to the current compilation unit. @@ -2261,7 +2186,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { match item.node { ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => { if !generics.is_type_parameterized() { - let trans_everywhere = attr::requests_inline(&item.attrs[]); + let trans_everywhere = attr::requests_inline(&item.attrs); // Ignore `trans_everywhere` for cross-crate inlined items // (`from_external`). `trans_item` will be called once for each // compilation unit that references the item, so it will still get @@ -2273,7 +2198,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { foreign::trans_rust_fn_with_foreign_abi(ccx, &**decl, &**body, - &item.attrs[], + &item.attrs, llfn, empty_substs, item.id, @@ -2285,7 +2210,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { llfn, empty_substs, item.id, - &item.attrs[]); + &item.attrs); } update_linkage(ccx, llfn, @@ -2332,14 +2257,19 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { // Do static_assert checking. It can't really be done much earlier // because we need to get the value of the bool out of LLVM - if attr::contains_name(&item.attrs[], "static_assert") { + if attr::contains_name(&item.attrs, "static_assert") { + if !ty::type_is_bool(ty::expr_ty(ccx.tcx(), expr)) { + ccx.sess().span_fatal(expr.span, + "can only have static_assert on a static \ + with type `bool`"); + } if m == ast::MutMutable { ccx.sess().span_fatal(expr.span, "cannot have static_assert on a mutable \ static"); } - let v = ccx.static_values().borrow()[item.id].clone(); + let v = ccx.static_values().borrow().get(&item.id).unwrap().clone(); unsafe { if !(llvm::LLVMConstIntGetZExtValue(v) != 0) { ccx.sess().span_fatal(expr.span, "static assertion failed"); @@ -2410,12 +2340,15 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, node_id: ast::NodeId, node_type: Ty<'tcx>) -> ValueRef { - match node_type.sty { - ty::ty_bare_fn(_, ref f) => { - assert!(f.abi == Rust || f.abi == RustCall); + if let ty::ty_bare_fn(_, ref f) = node_type.sty { + if f.abi != Rust && f.abi != RustCall { + ccx.sess().span_bug(sp, &format!("only the `{}` or `{}` calling conventions are valid \ + for this function; `{}` was specified", + Rust.name(), RustCall.name(), f.abi.name())); } - _ => panic!("expected bare rust fn") - }; + } else { + ccx.sess().span_bug(sp, "expected bare rust function") + } let llfn = decl_rust_fn(ccx, node_type, &sym[..]); finish_register_fn(ccx, sp, sym, node_id, llfn); @@ -2428,32 +2361,34 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< use middle::ty::{BrAnon, ReLateBound}; let function_type; - let (fn_sig, abi, has_env) = match fn_ty.sty { - ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, false), - ty::ty_closure(closure_did, _, substs) => { + let (fn_sig, abi, env_ty) = match fn_ty.sty { + ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, None), + ty::ty_closure(closure_did, substs) => { let typer = common::NormalizingClosureTyper::new(ccx.tcx()); function_type = typer.closure_type(closure_did, substs); - (&function_type.sig, RustCall, true) + let self_type = self_type_for_closure(ccx, closure_did, fn_ty); + (&function_type.sig, RustCall, Some(self_type)) } _ => ccx.sess().bug("expected closure or function.") }; let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig); - // Since index 0 is the return value of the llvm func, we start - // at either 1 or 2 depending on whether there's an env slot or not - let mut first_arg_offset = if has_env { 2 } else { 1 }; let mut attrs = llvm::AttrBuilder::new(); let ret_ty = fn_sig.output; // These have an odd calling convention, so we need to manually // unpack the input ty's let input_tys = match fn_ty.sty { - ty::ty_closure(_, _, _) => { + ty::ty_closure(..) => { assert!(abi == RustCall); match fn_sig.inputs[0].sty { - ty::ty_tup(ref inputs) => inputs.clone(), + ty::ty_tup(ref inputs) => { + let mut full_inputs = vec![env_ty.expect("Missing closure environment")]; + full_inputs.push_all(inputs); + full_inputs + } _ => ccx.sess().bug("expected tuple'd inputs") } }, @@ -2471,6 +2406,8 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< _ => fn_sig.inputs.clone() }; + // Index 0 is the return value of the llvm func, so we start at 1 + let mut first_arg_offset = 1; if let ty::FnConverging(ret_ty) = ret_ty { // A function pointer is called without the declaration // available, so we have to apply any attributes with ABI @@ -2746,7 +2683,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let val = match item { ast_map::NodeItem(i) => { let ty = ty::node_id_to_type(ccx.tcx(), i.id); - let sym = || exported_name(ccx, id, ty, &i.attrs[]); + let sym = || exported_name(ccx, id, ty, &i.attrs); let v = match i.node { ast::ItemStatic(_, _, ref expr) => { @@ -2773,13 +2710,13 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { if contains_null(&sym[..]) { ccx.sess().fatal( &format!("Illegal null byte in export_name \ - value: `{}`", sym)[]); + value: `{}`", sym)); } let buf = CString::new(sym.clone()).unwrap(); let g = llvm::LLVMAddGlobal(ccx.llmod(), llty, buf.as_ptr()); - if attr::contains_name(&i.attrs[], + if attr::contains_name(&i.attrs, "thread_local") { llvm::set_thread_local(g, true); } @@ -2798,19 +2735,19 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { sym, i.id) }; - set_llvm_fn_attrs(ccx, &i.attrs[], llfn); + set_llvm_fn_attrs(ccx, &i.attrs, llfn); llfn } - _ => panic!("get_item_val: weird result in table") + _ => ccx.sess().bug("get_item_val: weird result in table") }; - match attr::first_attr_value_str_by_name(&i.attrs[], + match attr::first_attr_value_str_by_name(&i.attrs, "link_section") { Some(sect) => { if contains_null(§) { ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", - §)[]); + §)); } unsafe { let buf = CString::new(sect.as_bytes()).unwrap(); @@ -2823,26 +2760,31 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { v } - ast_map::NodeTraitItem(trait_method) => { + ast_map::NodeTraitItem(trait_item) => { debug!("get_item_val(): processing a NodeTraitItem"); - match *trait_method { - ast::RequiredMethod(_) | ast::TypeTraitItem(_) => { - ccx.sess().bug("unexpected variant: required trait \ - method in get_item_val()"); + match trait_item.node { + ast::MethodTraitItem(_, None) | ast::TypeTraitItem(..) => { + ccx.sess().span_bug(trait_item.span, + "unexpected variant: required trait method in get_item_val()"); } - ast::ProvidedMethod(ref m) => { - register_method(ccx, id, &**m) + ast::MethodTraitItem(_, Some(_)) => { + register_method(ccx, id, &trait_item.attrs, trait_item.span) } } } - ast_map::NodeImplItem(ii) => { - match *ii { - ast::MethodImplItem(ref m) => register_method(ccx, id, &**m), - ast::TypeImplItem(ref typedef) => { - ccx.sess().span_bug(typedef.span, - "unexpected variant: required impl \ - method in get_item_val()") + ast_map::NodeImplItem(impl_item) => { + match impl_item.node { + ast::MethodImplItem(..) => { + register_method(ccx, id, &impl_item.attrs, impl_item.span) + } + ast::TypeImplItem(_) => { + ccx.sess().span_bug(impl_item.span, + "unexpected variant: associated type in get_item_val()") + } + ast::MacImplItem(_) => { + ccx.sess().span_bug(impl_item.span, + "unexpected variant: unexpanded macro in get_item_val()") } } } @@ -2853,7 +2795,9 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let abi = ccx.tcx().map.get_foreign_abi(id); let ty = ty::node_id_to_type(ccx.tcx(), ni.id); let name = foreign::link_name(&*ni); - foreign::register_foreign_item_fn(ccx, abi, ty, &name) + let llfn = foreign::register_foreign_item_fn(ccx, abi, ty, &name); + set_llvm_fn_attrs(ccx, &ni.attrs, llfn); + llfn } ast::ForeignItemStatic(..) => { foreign::register_static(ccx, &*ni) @@ -2866,7 +2810,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let args = match v.node.kind { ast::TupleVariantKind(ref args) => args, ast::StructVariantKind(_) => { - panic!("struct variant kind unexpected in get_item_val") + ccx.sess().bug("struct variant kind unexpected in get_item_val") } }; assert!(args.len() != 0); @@ -2876,13 +2820,13 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let sym = exported_name(ccx, id, ty, - &enm.attrs[]); + &enm.attrs); llfn = match enm.node { ast::ItemEnum(_, _) => { register_fn(ccx, (*v).span, sym, id, ty) } - _ => panic!("NodeVariant, shouldn't happen") + _ => ccx.sess().bug("NodeVariant, shouldn't happen") }; set_inline_hint(llfn); llfn @@ -2903,7 +2847,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let sym = exported_name(ccx, id, ty, - &struct_item.attrs[]); + &struct_item.attrs); let llfn = register_fn(ccx, struct_item.span, sym, ctor_id, ty); set_inline_hint(llfn); @@ -2912,7 +2856,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { ref variant => { ccx.sess().bug(&format!("get_item_val(): unexpected variant: {:?}", - variant)[]) + variant)) } }; @@ -2930,14 +2874,22 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { } fn register_method(ccx: &CrateContext, id: ast::NodeId, - m: &ast::Method) -> ValueRef { + attrs: &[ast::Attribute], span: Span) -> ValueRef { let mty = ty::node_id_to_type(ccx.tcx(), id); - let sym = exported_name(ccx, id, mty, &m.attrs[]); + let sym = exported_name(ccx, id, mty, &attrs); - let llfn = register_fn(ccx, m.span, sym, id, mty); - set_llvm_fn_attrs(ccx, &m.attrs[], llfn); - llfn + if let ty::ty_bare_fn(_, ref f) = mty.sty { + let llfn = if f.abi == Rust || f.abi == RustCall { + register_fn(ccx, span, sym, id, mty) + } else { + foreign::register_rust_fn_with_foreign_abi(ccx, span, sym, id) + }; + set_llvm_fn_attrs(ccx, &attrs, llfn); + return llfn; + } else { + ccx.sess().span_bug(span, "expected bare rust function"); + } } pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>, @@ -2966,15 +2918,12 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { } let encode_inlined_item: encoder::EncodeInlinedItem = - box |ecx, rbml_w, ii| astencode::encode_inlined_item(ecx, rbml_w, ii); + Box::new(|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); let mut compressed = encoder::metadata_encoding_version.to_vec(); - compressed.push_all(&match flate::deflate_bytes(&metadata) { - Some(compressed) => compressed, - None => cx.sess().fatal("failed to compress metadata"), - }); + compressed.push_all(&flate::deflate_bytes(&metadata)); let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]); let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false); let name = format!("rust_metadata_{}_{}", @@ -3083,6 +3032,18 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) let ty::CrateAnalysis { ty_cx: tcx, export_map, reachable, name, .. } = analysis; let krate = tcx.map.krate(); + let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks { + v + } else { + tcx.sess.opts.debug_assertions + }; + + let check_dropflag = if let Some(v) = tcx.sess.opts.debugging_opts.force_dropflag_checks { + v + } else { + tcx.sess.opts.debug_assertions + }; + // Before we touch LLVM, make sure that multithreading is enabled. unsafe { use std::sync::{Once, ONCE_INIT}; @@ -3104,13 +3065,15 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) let link_meta = link::build_link_meta(&tcx.sess, krate, name); let codegen_units = tcx.sess.opts.cg.codegen_units; - let shared_ccx = SharedCrateContext::new(&link_meta.crate_name[], + let shared_ccx = SharedCrateContext::new(&link_meta.crate_name, codegen_units, tcx, export_map, Sha256::new(), link_meta.clone(), - reachable); + reachable, + check_overflow, + check_dropflag); { let ccx = shared_ccx.get_ccx(0); @@ -3126,7 +3089,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) } for ccx in shared_ccx.iter() { - glue::emit_tydescs(&ccx); if ccx.sess().opts.debuginfo != NoDebugInfo { debuginfo::finalize(&ccx); } @@ -3138,7 +3100,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); println!("--- trans stats ---"); - println!("n_static_tydescs: {}", stats.n_static_tydescs.get()); println!("n_glues_created: {}", stats.n_glues_created.get()); println!("n_null_glues: {}", stats.n_null_glues.get()); println!("n_real_glues: {}", stats.n_real_glues.get()); @@ -3206,7 +3167,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) llmod: shared_ccx.metadata_llmod(), }; let formats = shared_ccx.tcx().dependency_formats.borrow().clone(); - let no_builtins = attr::contains_name(&krate.attrs[], "no_builtins"); + let no_builtins = attr::contains_name(&krate.attrs, "no_builtins"); let translation = CrateTranslation { modules: modules, diff --git a/src/librustc_trans/trans/basic_block.rs b/src/librustc_trans/trans/basic_block.rs index f11c315427..d3d055cda1 100644 --- a/src/librustc_trans/trans/basic_block.rs +++ b/src/librustc_trans/trans/basic_block.rs @@ -9,11 +9,11 @@ // except according to those terms. use llvm; -use llvm::{BasicBlockRef}; +use llvm::BasicBlockRef; use trans::value::{Users, Value}; use std::iter::{Filter, Map}; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct BasicBlock(pub BasicBlockRef); pub type Preds = Map bool>, fn(Value) -> BasicBlock>; diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs index 2fcfc5e439..a16c4d6c2c 100644 --- a/src/librustc_trans/trans/build.rs +++ b/src/librustc_trans/trans/build.rs @@ -105,7 +105,7 @@ pub fn CondBr(cx: Block, B(cx).cond_br(if_, then, else_); } -pub fn Switch(cx: Block, v: ValueRef, else_: BasicBlockRef, num_cases: uint) +pub fn Switch(cx: Block, v: ValueRef, else_: BasicBlockRef, num_cases: usize) -> ValueRef { if cx.unreachable.get() { return _Undef(v); } check_not_terminated(cx); @@ -122,7 +122,7 @@ pub fn AddCase(s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) { pub fn IndirectBr(cx: Block, addr: ValueRef, - num_dests: uint, + num_dests: usize, debug_loc: DebugLoc) { if cx.unreachable.get() { return; @@ -673,7 +673,7 @@ pub fn GEP(cx: Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef { // Simple wrapper around GEP that takes an array of ints and wraps them // in C_i32() #[inline] -pub fn GEPi(cx: Block, base: ValueRef, ixs: &[uint]) -> ValueRef { +pub fn GEPi(cx: Block, base: ValueRef, ixs: &[usize]) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref()); @@ -691,7 +691,7 @@ pub fn InBoundsGEP(cx: Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueR } } -pub fn StructGEP(cx: Block, pointer: ValueRef, idx: uint) -> ValueRef { +pub fn StructGEP(cx: Block, pointer: ValueRef, idx: usize) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref()); @@ -1011,7 +1011,7 @@ pub fn ShuffleVector(cx: Block, v1: ValueRef, v2: ValueRef, } } -pub fn VectorSplat(cx: Block, num_elts: uint, elt_val: ValueRef) -> ValueRef { +pub fn VectorSplat(cx: Block, num_elts: usize, elt_val: ValueRef) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); @@ -1020,7 +1020,7 @@ pub fn VectorSplat(cx: Block, num_elts: uint, elt_val: ValueRef) -> ValueRef { } } -pub fn ExtractValue(cx: Block, agg_val: ValueRef, index: uint) -> ValueRef { +pub fn ExtractValue(cx: Block, agg_val: ValueRef, index: usize) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); @@ -1029,7 +1029,7 @@ pub fn ExtractValue(cx: Block, agg_val: ValueRef, index: uint) -> ValueRef { } } -pub fn InsertValue(cx: Block, agg_val: ValueRef, elt_val: ValueRef, index: uint) -> ValueRef { +pub fn InsertValue(cx: Block, agg_val: ValueRef, elt_val: ValueRef, index: usize) -> ValueRef { unsafe { if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); @@ -1070,7 +1070,7 @@ pub fn Trap(cx: Block) { } pub fn LandingPad(cx: Block, ty: Type, pers_fn: ValueRef, - num_clauses: uint) -> ValueRef { + num_clauses: usize) -> ValueRef { check_not_terminated(cx); assert!(!cx.unreachable.get()); B(cx).landing_pad(ty, pers_fn, num_clauses) diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs index 8199e6189c..92bc20bafc 100644 --- a/src/librustc_trans/trans/builder.rs +++ b/src/librustc_trans/trans/builder.rs @@ -140,13 +140,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: uint) -> ValueRef { + pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: usize) -> ValueRef { unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint) } } - pub fn indirect_br(&self, addr: ValueRef, num_dests: uint) { + pub fn indirect_br(&self, addr: ValueRef, num_dests: usize) { self.count_insn("indirectbr"); unsafe { llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint); @@ -555,7 +555,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Simple wrapper around GEP that takes an array of ints and wraps them // in C_i32() #[inline] - pub fn gepi(&self, base: ValueRef, ixs: &[uint]) -> ValueRef { + pub fn gepi(&self, base: ValueRef, ixs: &[usize]) -> ValueRef { // Small vector optimization. This should catch 100% of the cases that // we care about. if ixs.len() < 16 { @@ -579,7 +579,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn struct_gep(&self, ptr: ValueRef, idx: uint) -> ValueRef { + pub fn struct_gep(&self, ptr: ValueRef, idx: usize) -> ValueRef { self.count_insn("structgep"); unsafe { llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname()) @@ -886,7 +886,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn vector_splat(&self, num_elts: uint, elt: ValueRef) -> ValueRef { + pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef { unsafe { let elt_ty = val_ty(elt); let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref()); @@ -896,7 +896,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn extract_value(&self, agg_val: ValueRef, idx: uint) -> ValueRef { + pub fn extract_value(&self, agg_val: ValueRef, idx: usize) -> ValueRef { self.count_insn("extractvalue"); unsafe { llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname()) @@ -904,7 +904,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef, - idx: uint) -> ValueRef { + idx: usize) -> ValueRef { self.count_insn("insertvalue"); unsafe { llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, @@ -940,7 +940,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_); let p = "llvm.trap\0".as_ptr(); let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _); - assert!((t as int != 0)); + assert!((t as isize != 0)); let args: &[ValueRef] = &[]; self.count_insn("trap"); llvm::LLVMBuildCall( @@ -948,7 +948,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef, num_clauses: uint) -> ValueRef { + pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef, num_clauses: usize) -> ValueRef { self.count_insn("landingpad"); unsafe { llvm::LLVMBuildLandingPad( diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs index 7abcdd07cc..0ff5264c00 100644 --- a/src/librustc_trans/trans/cabi.rs +++ b/src/librustc_trans/trans/cabi.rs @@ -109,7 +109,7 @@ pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { - match &ccx.sess().target.target.arch[] { + match &ccx.sess().target.target.arch[..] { "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), "x86_64" => if ccx.sess().target.target.options.is_like_windows { cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) @@ -128,6 +128,6 @@ pub fn compute_abi_info(ccx: &CrateContext, "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def), a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a) - []), + ), } } diff --git a/src/librustc_trans/trans/cabi_aarch64.rs b/src/librustc_trans/trans/cabi_aarch64.rs index 5d1e6d2c9e..8ac4f84d6e 100644 --- a/src/librustc_trans/trans/cabi_aarch64.rs +++ b/src/librustc_trans/trans/cabi_aarch64.rs @@ -18,18 +18,18 @@ use trans::type_::Type; use std::cmp; -fn align_up_to(off: uint, a: uint) -> uint { +fn align_up_to(off: usize, a: usize) -> usize { return (off + a - 1) / a * a; } -fn align(off: uint, ty: Type) -> uint { +fn align(off: usize, ty: Type) -> usize { let a = ty_align(ty); return align_up_to(off, a); } -fn ty_align(ty: Type) -> uint { +fn ty_align(ty: Type) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 8, Float => 4, Double => 8, @@ -54,9 +54,9 @@ fn ty_align(ty: Type) -> uint { } } -fn ty_size(ty: Type) -> uint { +fn ty_size(ty: Type) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 8, Float => 4, Double => 8, @@ -117,7 +117,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType { let size = ty_size(ty); if size <= 16 { let llty = if size == 0 { - Type::array(&Type::i64(ccx), 0u64) + Type::array(&Type::i64(ccx), 0) } else if size == 1 { Type::i8(ccx) } else if size == 2 { diff --git a/src/librustc_trans/trans/cabi_arm.rs b/src/librustc_trans/trans/cabi_arm.rs index 50014230df..941c065e3d 100644 --- a/src/librustc_trans/trans/cabi_arm.rs +++ b/src/librustc_trans/trans/cabi_arm.rs @@ -23,20 +23,20 @@ pub enum Flavor { Ios } -type TyAlignFn = fn(ty: Type) -> uint; +type TyAlignFn = fn(ty: Type) -> usize; -fn align_up_to(off: uint, a: uint) -> uint { +fn align_up_to(off: usize, a: usize) -> usize { return (off + a - 1) / a * a; } -fn align(off: uint, ty: Type, align_fn: TyAlignFn) -> uint { +fn align(off: usize, ty: Type, align_fn: TyAlignFn) -> usize { let a = align_fn(ty); return align_up_to(off, a); } -fn general_ty_align(ty: Type) -> uint { +fn general_ty_align(ty: Type) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 4, Float => 4, Double => 8, @@ -68,9 +68,9 @@ fn general_ty_align(ty: Type) -> uint { // ARMv6 // https://developer.apple.com/library/ios/documentation/Xcode/Conceptual // /iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html -fn ios_ty_align(ty: Type) -> uint { +fn ios_ty_align(ty: Type) -> usize { match ty.kind() { - Integer => cmp::min(4, ((ty.int_width() as uint) + 7) / 8), + Integer => cmp::min(4, ((ty.int_width() as usize) + 7) / 8), Pointer => 4, Float => 4, Double => 4, @@ -95,9 +95,9 @@ fn ios_ty_align(ty: Type) -> uint { } } -fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint { +fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 4, Float => 4, Double => 8, diff --git a/src/librustc_trans/trans/cabi_mips.rs b/src/librustc_trans/trans/cabi_mips.rs index bc171e3ae4..2d7fdd2f2e 100644 --- a/src/librustc_trans/trans/cabi_mips.rs +++ b/src/librustc_trans/trans/cabi_mips.rs @@ -19,18 +19,18 @@ use trans::cabi::{ArgType, FnType}; use trans::context::CrateContext; use trans::type_::Type; -fn align_up_to(off: uint, a: uint) -> uint { +fn align_up_to(off: usize, a: usize) -> usize { return (off + a - 1) / a * a; } -fn align(off: uint, ty: Type) -> uint { +fn align(off: usize, ty: Type) -> usize { let a = ty_align(ty); return align_up_to(off, a); } -fn ty_align(ty: Type) -> uint { +fn ty_align(ty: Type) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 4, Float => 4, Double => 8, @@ -55,9 +55,9 @@ fn ty_align(ty: Type) -> uint { } } -fn ty_size(ty: Type) -> uint { +fn ty_size(ty: Type) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 4, Float => 4, Double => 8, @@ -96,7 +96,7 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { } } -fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType { +fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType { let orig_offset = *offset; let size = ty_size(ty) * 8; let mut align = ty_align(ty); @@ -129,7 +129,7 @@ fn is_reg_ty(ty: Type) -> bool { }; } -fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option { +fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option { if ((align - 1 ) & offset) > 0 { Some(Type::i32(ccx)) } else { @@ -137,7 +137,7 @@ fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option { } } -fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec { +fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec { let int_ty = Type::i32(ccx); let mut args = Vec::new(); diff --git a/src/librustc_trans/trans/cabi_powerpc.rs b/src/librustc_trans/trans/cabi_powerpc.rs index 4871617e89..8c30d4fcc2 100644 --- a/src/librustc_trans/trans/cabi_powerpc.rs +++ b/src/librustc_trans/trans/cabi_powerpc.rs @@ -18,20 +18,20 @@ use trans::type_::Type; use std::cmp; -fn align_up_to(off: uint, a: uint) -> uint { +fn align_up_to(off: usize, a: usize) -> usize { return (off + a - 1) / a * a; } -fn align(off: uint, ty: Type) -> uint { +fn align(off: usize, ty: Type) -> usize { let a = ty_align(ty); return align_up_to(off, a); } -fn ty_align(ty: Type) -> uint { +fn ty_align(ty: Type) -> usize { match ty.kind() { Integer => { unsafe { - ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8 + ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as usize) + 7) / 8 } } Pointer => 4, @@ -53,11 +53,11 @@ fn ty_align(ty: Type) -> uint { } } -fn ty_size(ty: Type) -> uint { +fn ty_size(ty: Type) -> usize { match ty.kind() { Integer => { unsafe { - ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8 + ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as usize) + 7) / 8 } } Pointer => 4, @@ -92,7 +92,7 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType { } } -fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType { +fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType { let orig_offset = *offset; let size = ty_size(ty) * 8; let mut align = ty_align(ty); @@ -124,7 +124,7 @@ fn is_reg_ty(ty: Type) -> bool { }; } -fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option { +fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option { if ((align - 1 ) & offset) > 0 { Some(Type::i32(ccx)) } else { @@ -132,7 +132,7 @@ fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option { } } -fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec { +fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec { let int_ty = Type::i32(ccx); let mut args = Vec::new(); diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs index ab41fe31a6..754b7ee5cf 100644 --- a/src/librustc_trans/trans/cabi_x86_64.rs +++ b/src/librustc_trans/trans/cabi_x86_64.rs @@ -86,14 +86,14 @@ impl ClassList for [RegClass] { } fn classify_ty(ty: Type) -> Vec { - fn align(off: uint, ty: Type) -> uint { + fn align(off: usize, ty: Type) -> usize { let a = ty_align(ty); return (off + a - 1) / a * a; } - fn ty_align(ty: Type) -> uint { + fn ty_align(ty: Type) -> usize { match ty.kind() { - Integer => ((ty.int_width() as uint) + 7) / 8, + Integer => ((ty.int_width() as usize) + 7) / 8, Pointer => 8, Float => 4, Double => 8, @@ -118,9 +118,9 @@ fn classify_ty(ty: Type) -> Vec { } } - fn ty_size(ty: Type) -> uint { + fn ty_size(ty: Type) -> usize { match ty.kind() { - Integer => (ty.int_width() as uint + 7) / 8, + Integer => (ty.int_width() as usize + 7) / 8, Pointer => 8, Float => 4, Double => 8, @@ -157,7 +157,7 @@ fn classify_ty(ty: Type) -> Vec { } fn unify(cls: &mut [RegClass], - i: uint, + i: usize, newv: RegClass) { if cls[i] == newv { return } @@ -191,8 +191,8 @@ fn classify_ty(ty: Type) -> Vec { fn classify_struct(tys: &[Type], cls: &mut [RegClass], - i: uint, - off: uint, + i: usize, + off: usize, packed: bool) { let mut field_off = off; for ty in tys { @@ -205,8 +205,8 @@ fn classify_ty(ty: Type) -> Vec { } fn classify(ty: Type, - cls: &mut [RegClass], ix: uint, - off: uint) { + cls: &mut [RegClass], ix: usize, + off: usize) { let t_align = ty_align(ty); let t_size = ty_size(ty); @@ -331,7 +331,7 @@ fn classify_ty(ty: Type) -> Vec { } fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type { - fn llvec_len(cls: &[RegClass]) -> uint { + fn llvec_len(cls: &[RegClass]) -> usize { let mut len = 1; for c in cls { if *c != SSEUp { diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 3d3e35cd77..9eb46d3ff5 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -21,7 +21,7 @@ pub use self::CallArgs::*; use arena::TypedArena; use back::link; use session; -use llvm::{ValueRef}; +use llvm::ValueRef; use llvm::get_param; use llvm; use metadata::csearch; @@ -60,7 +60,7 @@ use syntax::ast; use syntax::ast_map; use syntax::ptr::P; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct MethodData { pub llfn: ValueRef, pub llself: ValueRef, @@ -93,7 +93,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) // pick out special kinds of expressions that can be called: match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { return trans_def(bcx, bcx.def(expr.id), expr); } _ => {} @@ -118,7 +118,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) expr.span, &format!("type of callee is neither bare-fn nor closure: \ {}", - bcx.ty_to_string(datum.ty))[]); + bcx.ty_to_string(datum.ty))); } } } @@ -165,13 +165,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) 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(_)) => { + def::DefFn(did, _) | def::DefMethod(did, def::FromImpl(_)) => { 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)) => { + def::DefMethod(meth_did, def::FromTrait(trait_did)) => { fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(), meth_did, trait_did, @@ -209,13 +207,12 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) | def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) | - def::DefUse(..) | def::DefTyParamBinder(..) | - def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) | - def::DefSelfTy(..) | def::DefAssociatedPath(..) => { + def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) | + def::DefTyParam(..) | def::DefSelfTy(..) => { bcx.tcx().sess.span_bug( ref_expr.span, &format!("cannot translate def {:?} \ - to a callable thing!", def)[]); + to a callable thing!", def)); } } } @@ -256,7 +253,7 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Translates an adapter that implements the `Fn` trait for a fn /// pointer. This is basically the equivalent of something like: /// -/// ```rust +/// ``` /// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int { /// extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int { /// (*self)(args.0) @@ -267,14 +264,29 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// but for the bare function type given. pub fn trans_fn_pointer_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, + closure_kind: ty::ClosureKind, bare_fn_ty: Ty<'tcx>) -> ValueRef { let _icx = push_ctxt("trans_fn_pointer_shim"); let tcx = ccx.tcx(); + // Normalize the type for better caching. let bare_fn_ty = common::erase_regions(tcx, &bare_fn_ty); - match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty) { + + // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`. + let is_by_ref = match closure_kind { + ty::FnClosureKind | ty::FnMutClosureKind => true, + ty::FnOnceClosureKind => false, + }; + let bare_fn_ty_maybe_ref = if is_by_ref { + ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty) + } else { + bare_fn_ty + }; + + // Check if we already trans'd this shim. + match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) { Some(&llval) => { return llval; } None => { } } @@ -282,9 +294,6 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( debug!("trans_fn_pointer_shim(bare_fn_ty={})", bare_fn_ty.repr(tcx)); - // This is an impl of `Fn` trait, so receiver is `&self`. - let bare_fn_ty_ref = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty); - // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`, // which is the fn pointer, and `args`, which is the arguments tuple. let (opt_def_id, sig) = @@ -298,7 +307,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( _ => { tcx.sess.bug(&format!("trans_fn_pointer_shim invoked on invalid type: {}", - bare_fn_ty.repr(tcx))[]); + bare_fn_ty.repr(tcx))); } }; let sig = ty::erase_late_bound_regions(tcx, sig); @@ -309,7 +318,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( unsafety: ast::Unsafety::Normal, abi: synabi::RustCall, sig: ty::Binder(ty::FnSig { - inputs: vec![bare_fn_ty_ref, + inputs: vec![bare_fn_ty_maybe_ref, tuple_input_ty], output: sig.output, variadic: false @@ -340,8 +349,11 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( let mut bcx = init_function(&fcx, false, sig.output); // the first argument (`self`) will be ptr to the the fn pointer - let llfnpointer = - Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32)); + let llfnpointer = if is_by_ref { + Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32)) + } else { + get_param(fcx.llfn, fcx.arg_pos(0) as u32) + }; // the remaining arguments will be the untupled values let llargs: Vec<_> = @@ -364,7 +376,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( finish_fn(&fcx, bcx, sig.output, DebugLoc::None); - ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty, llfn); + ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn); llfn } @@ -514,7 +526,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( let ref_ty = match node { ExprId(id) => ty::node_id_to_type(tcx, id), MethodCallKey(method_call) => { - (*tcx.method_map.borrow())[method_call].ty + tcx.method_map.borrow().get(&method_call).unwrap().ty } }; let ref_ty = monomorphize::apply_param_substs(tcx, @@ -606,7 +618,18 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx())); let method_call = MethodCall::expr(call_expr.id); - let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; + let method_ty = match bcx.tcx().method_map.borrow().get(&method_call) { + Some(method) => match method.origin { + ty::MethodTraitObject(_) => match method.ty.sty { + ty::ty_bare_fn(_, ref fty) => { + ty::mk_bare_fn(bcx.tcx(), None, meth::opaque_method_ty(bcx.tcx(), fty)) + } + _ => method.ty + }, + _ => method.ty + }, + None => panic!("method not found in trans_method_call") + }; trans_call_inner( bcx, call_expr.debug_loc(), @@ -737,7 +760,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; if !is_rust_fn || type_of::return_uses_outptr(ccx, ret_ty) || - common::type_needs_drop(bcx.tcx(), ret_ty) { + bcx.fcx.type_needs_drop(ret_ty) { // Push the out-pointer if we use an out-pointer for this // return type, otherwise push "undef". if common::type_is_zero_size(ccx, ret_ty) { @@ -765,8 +788,16 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, if is_rust_fn { let mut llargs = Vec::new(); - if let (ty::FnConverging(ret_ty), Some(llretslot)) = (ret_ty, opt_llretslot) { + if let (ty::FnConverging(ret_ty), Some(mut llretslot)) = (ret_ty, opt_llretslot) { if type_of::return_uses_outptr(ccx, ret_ty) { + let llformal_ret_ty = type_of::type_of(ccx, ret_ty).ptr_to(); + let llret_ty = common::val_ty(llretslot); + if llformal_ret_ty != llret_ty { + // this could happen due to e.g. subtyping + debug!("casting actual return type ({}) to match formal ({})", + bcx.llty_str(llret_ty), bcx.llty_str(llformal_ret_ty)); + llretslot = PointerCast(bcx, llretslot, llformal_ret_ty); + } llargs.push(llretslot); } } @@ -922,20 +953,21 @@ fn trans_args_under_call_abi<'blk, 'tcx>( tuple_expr.id)); let repr = adt::represent_type(bcx.ccx(), tuple_type); let repr_ptr = &*repr; - for i in 0..field_types.len() { + llargs.extend(field_types.iter().enumerate().map(|(i, field_type)| { let arg_datum = tuple_lvalue_datum.get_element( bcx, - field_types[i], + field_type, |srcval| { adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i) - }); - let arg_datum = arg_datum.to_expr_datum(); - let arg_datum = - unpack_datum!(bcx, arg_datum.to_rvalue_datum(bcx, "arg")); - let arg_datum = - unpack_datum!(bcx, arg_datum.to_appropriate_datum(bcx)); - llargs.push(arg_datum.add_clean(bcx.fcx, arg_cleanup_scope)); - } + }).to_expr_datum(); + unpack_result!(bcx, trans_arg_datum( + bcx, + field_type, + arg_datum, + arg_cleanup_scope, + DontAutorefArg) + ) + })); } _ => { bcx.sess().span_bug(tuple_expr.span, @@ -1078,7 +1110,7 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, bcx } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AutorefArg { DontAutorefArg, DoAutorefArg(ast::NodeId) diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 85e53618f6..19891e9307 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -153,14 +153,14 @@ pub struct CleanupScope<'blk, 'tcx: 'blk> { cached_landing_pad: Option, } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub struct CustomScopeIndex { - index: uint + index: usize } -pub const EXIT_BREAK: uint = 0; -pub const EXIT_LOOP: uint = 1; -pub const EXIT_MAX: uint = 2; +pub const EXIT_BREAK: usize = 0; +pub const EXIT_LOOP: usize = 1; +pub const EXIT_MAX: usize = 2; pub enum CleanupScopeKind<'blk, 'tcx: 'blk> { CustomScopeKind, @@ -184,14 +184,14 @@ impl<'blk, 'tcx: 'blk> fmt::Debug for CleanupScopeKind<'blk, 'tcx> { } } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum EarlyExitLabel { UnwindExit, ReturnExit, - LoopExit(ast::NodeId, uint) + LoopExit(ast::NodeId, usize) } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct CachedEarlyExit { label: EarlyExitLabel, cleanup_block: BasicBlockRef, @@ -209,7 +209,7 @@ pub trait Cleanup<'tcx> { pub type CleanupObj<'tcx> = Box+'tcx>; -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum ScopeId { AstScope(ast::NodeId), CustomScope(CustomScopeIndex) @@ -357,7 +357,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// break/continue (depending on `exit`) out of the loop with id `cleanup_scope` fn normal_exit_block(&'blk self, cleanup_scope: ast::NodeId, - exit: uint) -> BasicBlockRef { + exit: usize) -> BasicBlockRef { self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit)) } @@ -386,7 +386,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !self.type_needs_drop(ty) { return; } let drop = box DropValue { is_immediate: false, must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), @@ -408,7 +408,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { cleanup_scope: ScopeId, val: ValueRef, ty: Ty<'tcx>) { - if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !self.type_needs_drop(ty) { return; } + let drop = box DropValue { is_immediate: false, must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), @@ -432,7 +433,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { val: ValueRef, ty: Ty<'tcx>) { - if !common::type_needs_drop(self.ccx.tcx(), ty) { return; } + if !self.type_needs_drop(ty) { return; } let drop = box DropValue { is_immediate: true, must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty), @@ -513,7 +514,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.ccx.sess().bug( &format!("no cleanup scope {} found", - self.ccx.tcx().map.node_to_string(cleanup_scope))[]); + self.ccx.tcx().map.node_to_string(cleanup_scope))); } /// Schedules a cleanup to occur in the top-most scope, which must be a temporary scope. @@ -584,7 +585,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx None } - fn top_nonempty_cleanup_scope(&self) -> Option { + fn top_nonempty_cleanup_scope(&self) -> Option { self.scopes.borrow().iter().rev().position(|s| !s.cleanups.is_empty()) } @@ -613,7 +614,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx bcx } - fn scopes_len(&self) -> uint { + fn scopes_len(&self) -> usize { self.scopes.borrow().len() } @@ -695,7 +696,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx LoopExit(id, _) => { self.ccx.sess().bug(&format!( "cannot exit from scope {}, \ - not in scope", id)[]); + not in scope", id)); } } } @@ -961,7 +962,7 @@ impl<'blk, 'tcx> CleanupScopeKind<'blk, 'tcx> { /// If this is a loop scope with id `id`, return the early exit block `exit`, else `None` fn early_exit_block(&self, id: ast::NodeId, - exit: uint) -> Option { + exit: usize) -> Option { match *self { LoopScopeKind(i, ref exits) if id == i => Some(exits[exit].llbb), _ => None, @@ -981,7 +982,7 @@ impl EarlyExitLabel { /////////////////////////////////////////////////////////////////////////// // Cleanup types -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct DropValue<'tcx> { is_immediate: bool, must_unwind: bool, @@ -1007,24 +1008,25 @@ impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> { bcx: Block<'blk, 'tcx>, debug_loc: DebugLoc) -> Block<'blk, 'tcx> { + let _icx = base::push_ctxt("::trans"); let bcx = if self.is_immediate { glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc) } else { glue::drop_ty(bcx, self.val, self.ty, debug_loc) }; if self.zero { - base::zero_mem(bcx, self.val, self.ty); + base::drop_done_fill_mem(bcx, self.val, self.ty); } bcx } } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum Heap { HeapExchange } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct FreeValue<'tcx> { ptr: ValueRef, heap: Heap, @@ -1059,7 +1061,7 @@ impl<'tcx> Cleanup<'tcx> for FreeValue<'tcx> { } } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct FreeSlice { ptr: ValueRef, size: ValueRef, @@ -1096,7 +1098,7 @@ impl<'tcx> Cleanup<'tcx> for FreeSlice { } } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct LifetimeEnd { ptr: ValueRef, } @@ -1135,7 +1137,7 @@ pub fn temporary_scope(tcx: &ty::ctxt, } None => { tcx.sess.bug(&format!("no temporary scope available for expr {}", - id)[]) + id)) } } } @@ -1180,7 +1182,7 @@ pub trait CleanupMethods<'blk, 'tcx> { fn top_loop_scope(&self) -> ast::NodeId; fn normal_exit_block(&'blk self, cleanup_scope: ast::NodeId, - exit: uint) -> BasicBlockRef; + exit: usize) -> BasicBlockRef; fn return_exit_block(&'blk self) -> BasicBlockRef; fn schedule_lifetime_end(&self, cleanup_scope: ScopeId, @@ -1223,7 +1225,7 @@ pub trait CleanupMethods<'blk, 'tcx> { trait CleanupHelperMethods<'blk, 'tcx> { fn top_ast_scope(&self) -> Option; - fn top_nonempty_cleanup_scope(&self) -> Option; + fn top_nonempty_cleanup_scope(&self) -> Option; fn is_valid_to_pop_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool; fn is_valid_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool; fn trans_scope_cleanups(&self, @@ -1233,7 +1235,7 @@ trait CleanupHelperMethods<'blk, 'tcx> { label: EarlyExitLabel) -> BasicBlockRef; fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef; - fn scopes_len(&self) -> uint; + fn scopes_len(&self) -> usize; fn push_scope(&self, scope: CleanupScope<'blk, 'tcx>); fn pop_scope(&self) -> CleanupScope<'blk, 'tcx>; fn top_scope(&self, f: F) -> R where F: FnOnce(&CleanupScope<'blk, 'tcx>) -> R; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 1d4bbd79d7..c1aade3663 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -8,24 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use back::link::mangle_internal_name_by_path_and_seq; -use llvm::ValueRef; +use arena::TypedArena; +use back::link::{self, mangle_internal_name_by_path_and_seq}; +use llvm::{ValueRef, get_param}; use middle::mem_categorization::Typer; use trans::adt; use trans::base::*; use trans::build::*; -use trans::cleanup::{CleanupMethods, ScopeId}; +use trans::callee::{self, ArgVals, Callee, TraitItem, MethodData}; +use trans::cleanup::{CleanupMethods, CustomScope, ScopeId}; use trans::common::*; -use trans::datum::{Datum, rvalue_scratch_datum}; -use trans::datum::{Rvalue, ByValue}; -use trans::debuginfo; +use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue}; +use trans::debuginfo::{self, DebugLoc}; use trans::expr; use trans::monomorphize::{self, MonoId}; use trans::type_of::*; use middle::ty::{self, ClosureTyper}; -use middle::subst::{Substs}; +use middle::subst::Substs; use session::config::FullDebugInfo; +use util::ppaux::Repr; +use syntax::abi::RustCall; use syntax::ast; use syntax::ast_util; @@ -138,7 +141,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc // duplicate declarations let function_type = erase_regions(ccx.tcx(), &function_type); let params = match function_type.sty { - ty::ty_closure(_, _, substs) => &substs.types, + ty::ty_closure(_, substs) => &substs.types, _ => unreachable!() }; let mono_id = MonoId { @@ -239,11 +242,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, // Create the closure. for (i, freevar) in freevars.iter().enumerate() { let datum = expr::trans_local_var(bcx, freevar.def); - let upvar_slot_dest = adt::trans_field_ptr(bcx, - &*repr, - dest_addr, - 0, - i); + let upvar_slot_dest = adt::trans_field_ptr(bcx, &*repr, dest_addr, 0, i); let upvar_id = ty::UpvarId { var_id: freevar.def.local_node_id(), closure_expr_id: id }; match tcx.upvar_capture(upvar_id).unwrap() { @@ -260,3 +259,185 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, Some(bcx) } +pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, + closure_def_id: ast::DefId, + substs: Substs<'tcx>, + node: ExprOrMethodCall, + param_substs: &'tcx Substs<'tcx>, + trait_closure_kind: ty::ClosureKind) + -> ValueRef +{ + // The substitutions should have no type parameters remaining + // after passing through fulfill_obligation + let llfn = callee::trans_fn_ref_with_substs(ccx, + closure_def_id, + node, + param_substs, + substs.clone()).val; + + // If the closure is a Fn closure, but a FnOnce is needed (etc), + // then adapt the self type + let closure_kind = ccx.tcx().closure_kind(closure_def_id); + trans_closure_adapter_shim(ccx, + closure_def_id, + substs, + closure_kind, + trait_closure_kind, + llfn) +} + +fn trans_closure_adapter_shim<'a, 'tcx>( + ccx: &'a CrateContext<'a, 'tcx>, + closure_def_id: ast::DefId, + substs: Substs<'tcx>, + llfn_closure_kind: ty::ClosureKind, + trait_closure_kind: ty::ClosureKind, + llfn: ValueRef) + -> ValueRef +{ + let _icx = push_ctxt("trans_closure_adapter_shim"); + let tcx = ccx.tcx(); + + debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \ + trait_closure_kind={:?}, \ + llfn={})", + llfn_closure_kind, + trait_closure_kind, + ccx.tn().val_to_string(llfn)); + + match (llfn_closure_kind, trait_closure_kind) { + (ty::FnClosureKind, ty::FnClosureKind) | + (ty::FnMutClosureKind, ty::FnMutClosureKind) | + (ty::FnOnceClosureKind, ty::FnOnceClosureKind) => { + // No adapter needed. + llfn + } + (ty::FnClosureKind, ty::FnMutClosureKind) => { + // The closure fn `llfn` is a `fn(&self, ...)`. We want a + // `fn(&mut self, ...)`. In fact, at trans time, these are + // basically the same thing, so we can just return llfn. + llfn + } + (ty::FnClosureKind, ty::FnOnceClosureKind) | + (ty::FnMutClosureKind, ty::FnOnceClosureKind) => { + // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut + // self, ...)`. We want a `fn(self, ...)`. We can produce + // this by doing something like: + // + // fn call_once(self, ...) { call_mut(&self, ...) } + // fn call_once(mut self, ...) { call_mut(&mut self, ...) } + // + // These are both the same at trans time. + trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn) + } + _ => { + tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}", + llfn_closure_kind, + trait_closure_kind)); + } + } +} + +fn trans_fn_once_adapter_shim<'a, 'tcx>( + ccx: &'a CrateContext<'a, 'tcx>, + closure_def_id: ast::DefId, + substs: Substs<'tcx>, + llreffn: ValueRef) + -> ValueRef +{ + debug!("trans_fn_once_adapter_shim(closure_def_id={}, substs={}, llreffn={})", + closure_def_id.repr(ccx.tcx()), + substs.repr(ccx.tcx()), + ccx.tn().val_to_string(llreffn)); + + let tcx = ccx.tcx(); + let typer = NormalizingClosureTyper::new(tcx); + + // Find a version of the closure type. Substitute static for the + // region since it doesn't really matter. + let substs = tcx.mk_substs(substs); + let closure_ty = ty::mk_closure(tcx, closure_def_id, substs); + let ref_closure_ty = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), closure_ty); + + // Make a version with the type of by-ref closure. + let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs); + sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet + let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety, + abi: abi, + sig: sig.clone() }); + let llref_fn_ty = ty::mk_bare_fn(tcx, None, llref_bare_fn_ty); + debug!("trans_fn_once_adapter_shim: llref_fn_ty={}", + llref_fn_ty.repr(tcx)); + + // Make a version of the closure type with the same arguments, but + // with argument #0 being by value. + assert_eq!(abi, RustCall); + sig.0.inputs[0] = closure_ty; + let llonce_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety, + abi: abi, + sig: sig }); + let llonce_fn_ty = ty::mk_bare_fn(tcx, None, llonce_bare_fn_ty); + + // Create the by-value helper. + let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim"); + let lloncefn = decl_internal_rust_fn(ccx, llonce_fn_ty, &function_name); + + let sig = ty::erase_late_bound_regions(tcx, &llonce_bare_fn_ty.sig); + let (block_arena, fcx): (TypedArena<_>, FunctionContext); + block_arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, + lloncefn, + ast::DUMMY_NODE_ID, + false, + sig.output, + substs, + None, + &block_arena); + let mut bcx = init_function(&fcx, false, sig.output); + + // the first argument (`self`) will be the (by value) closure env. + let self_scope = fcx.push_custom_cleanup_scope(); + let self_scope_id = CustomScope(self_scope); + let rvalue_mode = datum::appropriate_rvalue_mode(ccx, closure_ty); + let llself = get_param(lloncefn, fcx.arg_pos(0) as u32); + let env_datum = Datum::new(llself, closure_ty, Rvalue::new(rvalue_mode)); + let env_datum = unpack_datum!(bcx, + env_datum.to_lvalue_datum_in_scope(bcx, "self", + self_scope_id)); + + debug!("trans_fn_once_adapter_shim: env_datum={}", + bcx.val_to_string(env_datum.val)); + + // the remaining arguments will be packed up in a tuple. + let input_tys = match sig.inputs[1].sty { + ty::ty_tup(ref tys) => &**tys, + _ => bcx.sess().bug(&format!("trans_fn_once_adapter_shim: not rust-call! \ + closure_def_id={}", + closure_def_id.repr(tcx))) + }; + let llargs: Vec<_> = + input_tys.iter() + .enumerate() + .map(|(i, _)| get_param(lloncefn, fcx.arg_pos(i+1) as u32)) + .collect(); + + let dest = + fcx.llretslotptr.get().map( + |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot"))); + + let callee_data = TraitItem(MethodData { llfn: llreffn, + llself: env_datum.val }); + + bcx = callee::trans_call_inner(bcx, + DebugLoc::None, + llref_fn_ty, + |bcx, _| Callee { bcx: bcx, data: callee_data }, + ArgVals(&llargs), + dest).bcx; + + fcx.pop_custom_cleanup_scope(self_scope); + + finish_fn(&fcx, bcx, sig.output, DebugLoc::None); + + lloncefn +} diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index a9cda94beb..c5985e930e 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -46,6 +46,7 @@ use arena::TypedArena; use libc::{c_uint, c_char}; use std::ffi::CString; use std::cell::{Cell, RefCell}; +use std::result::Result as StdResult; use std::vec::Vec; use syntax::ast::Ident; use syntax::ast; @@ -120,14 +121,16 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T // Is the type's representation size known at compile time? pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { let param_env = ty::empty_parameter_environment(tcx); - ty::type_is_sized(¶m_env, DUMMY_SP, ty) -} - -pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::ty_open(_) => true, - _ => type_is_sized(cx, ty), + // FIXME(#4287) This can cause errors due to polymorphic recursion, + // a better span should be provided, if available. + let err_count = tcx.sess.err_count(); + let is_sized = ty::type_is_sized(¶m_env, DUMMY_SP, ty); + // Those errors aren't fatal, but an incorrect result can later + // trip over asserts in both rustc's trans and LLVM. + if err_count < tcx.sess.err_count() { + tcx.sess.abort_if_errors(); } + is_sized } pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { @@ -211,10 +214,43 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty< } } -pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, - ty: Ty<'tcx>) - -> bool { - ty::type_contents(cx, ty).needs_drop(cx) +/// If `type_needs_drop` returns true, then `ty` is definitely +/// non-copy and *might* have a destructor attached; if it returns +/// false, then `ty` definitely has no destructor (i.e. no drop glue). +/// +/// (Note that this implies that if `ty` has a destructor attached, +/// then `type_needs_drop` will definitely return `true` for `ty`.) +pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + type_needs_drop_given_env(cx, ty, &ty::empty_parameter_environment(cx)) +} + +/// Core implementation of type_needs_drop, potentially making use of +/// and/or updating caches held in the `param_env`. +fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ty::ParameterEnvironment<'a,'tcx>) -> bool { + // Issue #22536: We first query type_moves_by_default. It sees a + // normalized version of the type, and therefore will definitely + // know whether the type implements Copy (and thus needs no + // cleanup/drop/zeroing) ... + let implements_copy = !ty::type_moves_by_default(¶m_env, DUMMY_SP, ty); + + if implements_copy { return false; } + + // ... (issue #22536 continued) but as an optimization, still use + // prior logic of asking if the `needs_drop` bit is set; we need + // not zero non-Copy types if they have no destructor. + + // FIXME(#22815): Note that calling `ty::type_contents` is a + // conservative heuristic; it may report that `needs_drop` is set + // when actual type does not actually have a destructor associated + // with it. But since `ty` absolutely did not have the `Copy` + // bound attached (see above), it is sound to treat it as having a + // destructor (e.g. zero its memory on move). + + let contents = ty::type_contents(cx, ty); + debug!("type_needs_drop ty={} contents={:?}", ty.repr(cx), contents); + contents.needs_drop(cx) } fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { @@ -278,16 +314,7 @@ pub fn gensym_name(name: &str) -> PathElem { let num = token::gensym(name).usize(); // use one colon which will get translated to a period by the mangler, and // we're guaranteed that `num` is globally unique for this crate. - PathName(token::gensym(&format!("{}:{}", name, num)[])) -} - -#[derive(Copy)] -pub struct tydesc_info<'tcx> { - pub ty: Ty<'tcx>, - pub tydesc: ValueRef, - pub size: ValueRef, - pub align: ValueRef, - pub name: ValueRef, + PathName(token::gensym(&format!("{}:{}", name, num))) } /* @@ -316,7 +343,7 @@ pub struct tydesc_info<'tcx> { * */ -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct NodeIdAndSpan { pub id: ast::NodeId, pub span: Span, @@ -352,7 +379,7 @@ pub fn validate_substs(substs: &Substs) { // work around bizarre resolve errors type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>; -type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>; +pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>; // Function context. Every LLVM function we create will have one of // these. @@ -432,7 +459,7 @@ pub struct FunctionContext<'a, 'tcx: 'a> { } impl<'a, 'tcx> FunctionContext<'a, 'tcx> { - pub fn arg_pos(&self, arg: uint) -> uint { + pub fn arg_pos(&self, arg: usize) -> usize { let arg = self.env_arg_pos() + arg; if self.llenv.is_some() { arg + 1 @@ -441,7 +468,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { } } - pub fn env_arg_pos(&self) -> uint { + pub fn env_arg_pos(&self) -> usize { if self.caller_expects_out_pointer { 1 } else { @@ -534,6 +561,12 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { self.param_substs, value) } + + /// This is the same as `common::type_needs_drop`, except that it + /// may use or update caches within this `FunctionContext`. + pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { + type_needs_drop_given_env(self.ccx.tcx(), ty, &self.param_env) + } } // Basic block context. We create a block context for each basic block @@ -603,10 +636,10 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { pub fn def(&self, nid: ast::NodeId) -> def::Def { match self.tcx().def_map.borrow().get(&nid) { - Some(v) => v.clone(), + Some(v) => v.full_def(), None => { self.tcx().sess.bug(&format!( - "no def associated with node id {}", nid)[]); + "no def associated with node id {}", nid)); } } } @@ -676,7 +709,7 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { } fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option { - Some(self.tcx().upvar_capture_map.borrow()[upvar_id].clone()) + Some(self.tcx().upvar_capture_map.borrow().get(&upvar_id).unwrap().clone()) } fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool { @@ -774,6 +807,10 @@ pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef { C_integral(Type::i32(ccx), i as u64, true) } +pub fn C_u32(ccx: &CrateContext, i: u32) -> ValueRef { + C_integral(Type::i32(ccx), i as u64, false) +} + pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef { C_integral(Type::i64(ccx), i, false) } @@ -809,13 +846,13 @@ pub trait AsU64 { fn as_u64(self) -> u64; } // are host-architecture-dependent impl AsI64 for i64 { fn as_i64(self) -> i64 { self as i64 }} impl AsI64 for i32 { fn as_i64(self) -> i64 { self as i64 }} -impl AsI64 for int { fn as_i64(self) -> i64 { self as i64 }} +impl AsI64 for isize { fn as_i64(self) -> i64 { self as i64 }} impl AsU64 for u64 { fn as_u64(self) -> u64 { self as u64 }} impl AsU64 for u32 { fn as_u64(self) -> u64 { self as u64 }} -impl AsU64 for uint { fn as_u64(self) -> u64 { self as u64 }} +impl AsU64 for usize { fn as_u64(self) -> u64 { self as u64 }} -pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef { +pub fn C_u8(ccx: &CrateContext, i: usize) -> ValueRef { C_integral(Type::i8(ccx), i as u64, false) } @@ -926,6 +963,32 @@ pub fn const_to_uint(v: ValueRef) -> u64 { } } +fn is_const_integral(v: ValueRef) -> bool { + unsafe { + !llvm::LLVMIsAConstantInt(v).is_null() + } +} + +pub fn const_to_opt_int(v: ValueRef) -> Option { + unsafe { + if is_const_integral(v) { + Some(llvm::LLVMConstIntGetSExtValue(v)) + } else { + None + } + } +} + +pub fn const_to_opt_uint(v: ValueRef) -> Option { + unsafe { + if is_const_integral(v) { + Some(llvm::LLVMConstIntGetZExtValue(v)) + } else { + None + } + } +} + pub fn is_undef(val: ValueRef) -> bool { unsafe { llvm::LLVMIsUndef(val) != False @@ -961,9 +1024,9 @@ pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> /// do not (necessarily) resolve all nested obligations on the impl. Note that type check should /// guarantee to us that all nested obligations *could be* resolved if we wanted to. pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - span: Span, - trait_ref: ty::PolyTraitRef<'tcx>) - -> traits::Vtable<'tcx, ()> + span: Span, + trait_ref: ty::PolyTraitRef<'tcx>) + -> traits::Vtable<'tcx, ()> { let tcx = ccx.tcx(); @@ -988,8 +1051,9 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // shallow result we are looking for -- that is, what specific impl. let typer = NormalizingClosureTyper::new(tcx); let mut selcx = traits::SelectionContext::new(&infcx, &typer); - let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), - trait_ref.to_poly_trait_predicate()); + let obligation = + traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID), + trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, Ok(None) => { @@ -1011,7 +1075,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, span, &format!("Encountered error `{}` selecting `{}` during trans", e.repr(tcx), - trait_ref.repr(tcx))[]) + trait_ref.repr(tcx))) } }; @@ -1022,7 +1086,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let vtable = selection.map_move_nested(|predicate| { fulfill_cx.register_predicate_obligation(&infcx, predicate); }); - let vtable = drain_fulfillment_cx(span, &infcx, &mut fulfill_cx, &vtable); + let vtable = drain_fulfillment_cx_or_panic(span, &infcx, &mut fulfill_cx, &vtable); info!("Cache miss: {}", trait_ref.repr(ccx.tcx())); ccx.trait_cache().borrow_mut().insert(trait_ref, @@ -1031,6 +1095,35 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, vtable } +/// Normalizes the predicates and checks whether they hold. If this +/// returns false, then either normalize encountered an error or one +/// of the predicates did not hold. Used when creating vtables to +/// check for unsatisfiable methods. +pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + predicates: Vec>) + -> bool +{ + debug!("normalize_and_test_predicates(predicates={})", + predicates.repr(ccx.tcx())); + + let tcx = ccx.tcx(); + let infcx = infer::new_infer_ctxt(tcx); + let typer = NormalizingClosureTyper::new(tcx); + let mut selcx = traits::SelectionContext::new(&infcx, &typer); + let mut fulfill_cx = traits::FulfillmentContext::new(); + let cause = traits::ObligationCause::dummy(); + let traits::Normalized { value: predicates, obligations } = + traits::normalize(&mut selcx, cause.clone(), &predicates); + for obligation in obligations { + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + for predicate in predicates { + let obligation = traits::Obligation::new(cause.clone(), predicate); + fulfill_cx.register_predicate_obligation(&infcx, obligation); + } + drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok() +} + pub struct NormalizingClosureTyper<'a,'tcx:'a> { param_env: ty::ParameterEnvironment<'a, 'tcx> } @@ -1078,11 +1171,35 @@ impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> { } } -pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span, - infcx: &infer::InferCtxt<'a,'tcx>, - fulfill_cx: &mut traits::FulfillmentContext<'tcx>, - result: &T) - -> T +pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span, + infcx: &infer::InferCtxt<'a,'tcx>, + fulfill_cx: &mut traits::FulfillmentContext<'tcx>, + result: &T) + -> T + where T : TypeFoldable<'tcx> + Repr<'tcx> +{ + match drain_fulfillment_cx(infcx, fulfill_cx, result) { + Ok(v) => v, + Err(errors) => { + infcx.tcx.sess.span_bug( + span, + &format!("Encountered errors `{}` fulfilling during trans", + errors.repr(infcx.tcx))); + } + } +} + +/// Finishes processes any obligations that remain in the fulfillment +/// context, and then "freshens" and returns `result`. This is +/// primarily used during normalization and other cases where +/// processing the obligations in `fulfill_cx` may cause type +/// inference variables that appear in `result` to be unified, and +/// hence we need to process those obligations to get the complete +/// picture of the type. +pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>, + fulfill_cx: &mut traits::FulfillmentContext<'tcx>, + result: &T) + -> StdResult>> where T : TypeFoldable<'tcx> + Repr<'tcx> { debug!("drain_fulfillment_cx(result={})", @@ -1095,17 +1212,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span, match fulfill_cx.select_all_or_error(infcx, &typer) { Ok(()) => { } Err(errors) => { - if errors.iter().all(|e| e.is_overflow()) { - // See Ok(None) case above. - infcx.tcx.sess.span_fatal( - span, - "reached the recursion limit during monomorphization"); - } else { - infcx.tcx.sess.span_bug( - span, - &format!("Encountered errors `{}` fulfilling during trans", - errors.repr(infcx.tcx))[]); - } + return Err(errors); } } @@ -1114,11 +1221,11 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span, // sort of overkill because we do not expect there to be any // unbound type variables, hence no `TyFresh` types should ever be // inserted. - result.fold_with(&mut infcx.freshener()) + Ok(result.fold_with(&mut infcx.freshener())) } // Key used to lookup values supplied for type parameters in an expr. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum ExprOrMethodCall { // Type parameters for a path like `None::` ExprId(ast::NodeId), @@ -1138,13 +1245,13 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::node_id_item_substs(tcx, id).substs } MethodCallKey(method_call) => { - (*tcx.method_map.borrow())[method_call].substs.clone() + tcx.method_map.borrow().get(&method_call).unwrap().substs.clone() } }; if substs.types.any(|t| ty::type_needs_infer(*t)) { tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}", - node, substs.repr(tcx))[]); + node, substs.repr(tcx))); } monomorphize::apply_param_substs(tcx, diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 7705b53ee3..c32cb28ec7 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -14,6 +14,14 @@ use llvm; use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr}; use llvm::{InternalLinkage, ValueRef, Bool, True}; use middle::{check_const, const_eval, def}; +use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg}; +use middle::const_eval::{const_int_checked_add, const_uint_checked_add}; +use middle::const_eval::{const_int_checked_sub, const_uint_checked_sub}; +use middle::const_eval::{const_int_checked_mul, const_uint_checked_mul}; +use middle::const_eval::{const_int_checked_div, const_uint_checked_div}; +use middle::const_eval::{const_int_checked_rem, const_uint_checked_rem}; +use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl}; +use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr}; use trans::{adt, closure, debuginfo, expr, inline, machine}; use trans::base::{self, push_ctxt}; use trans::common::*; @@ -53,8 +61,8 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit) } _ => cx.sess().span_bug(lit.span, &format!("integer literal has type {} (expected int \ - or uint)", - ty_to_string(cx.tcx(), lit_int_ty))[]) + or usize)", + ty_to_string(cx.tcx(), lit_int_ty))) } } ast::LitFloat(ref fs, t) => { @@ -75,14 +83,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit) ast::LitBool(b) => C_bool(cx, b), ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()), ast::LitBinary(ref data) => { - let g = addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id); - let base = ptrcast(g, Type::i8p(cx)); - let prev_const = cx.const_unsized().borrow_mut() - .insert(base, g); - assert!(prev_const.is_none() || prev_const == Some(g)); - assert_eq!(abi::FAT_PTR_ADDR, 0); - assert_eq!(abi::FAT_PTR_EXTRA, 1); - C_struct(cx, &[base, C_uint(cx, data.len())], false) + addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id) } } } @@ -146,13 +147,13 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, (const_deref_ptr(cx, v), mt.ty) } else { // Derefing a fat pointer does not change the representation, - // just the type to ty_open. - (v, ty::mk_open(cx.tcx(), mt.ty)) + // just the type to the unsized contents. + (v, mt.ty) } } None => { cx.sess().bug(&format!("unexpected dereferenceable type {}", - ty_to_string(cx.tcx(), ty))[]) + ty_to_string(cx.tcx(), ty))) } } } @@ -173,8 +174,8 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, &**expr } else { ccx.sess().span_bug(ref_expr.span, - &format!("get_const_val given non-constant item {}", - item.repr(ccx.tcx()))[]); + &format!("get_const_expr given non-constant item {}", + item.repr(ccx.tcx()))); } } @@ -193,8 +194,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, -> ValueRef { // Special-case constants to cache a common global for all uses. match expr.node { - ast::ExprPath(_) => { - let def = ccx.tcx().def_map.borrow()[expr.id]; + ast::ExprPath(..) => { + let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def(); match def { def::DefConst(def_id) => { if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) { @@ -253,6 +254,9 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // FIXME(#19925) once fn item types are // zero-sized, we'll need to do something here } + Some(ty::AdjustUnsafeFnPointer) => { + // purely a type-level thing + } Some(ty::AdjustDerefRef(adj)) => { let mut ty = ety; // Save the last autoderef in case we can avoid it. @@ -290,18 +294,10 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // an optimisation, it is necessary for mutable vectors to // work properly. ty = match ty::deref(ty, true) { - Some(mt) => { - if type_is_sized(cx.tcx(), mt.ty) { - mt.ty - } else { - // Derefing a fat pointer does not change the representation, - // just the type to ty_open. - ty::mk_open(cx.tcx(), mt.ty) - } - } + Some(mt) => mt.ty, None => { cx.sess().bug(&format!("unexpected dereferenceable type {}", - ty_to_string(cx.tcx(), ty))[]) + ty_to_string(cx.tcx(), ty))) } } } @@ -309,7 +305,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } Some(autoref) => { cx.sess().span_bug(e.span, - &format!("unimplemented const first autoref {:?}", autoref)[]) + &format!("unimplemented const first autoref {:?}", autoref)) } }; match second_autoref { @@ -319,11 +315,15 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llconst = addr_of(cx, llconst, "autoref", e.id); } Some(box ty::AutoUnsize(ref k)) => { + let info = + expr::unsized_info( + cx, k, e.id, ty, param_substs, + || const_get_elt(cx, llconst, &[abi::FAT_PTR_EXTRA as u32])); + let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span); - let info = expr::unsized_info(cx, k, e.id, ty, param_substs, - |t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t)); + let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to(); + let base = ptrcast(llconst, ptr_ty); - let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to()); let prev_const = cx.const_unsized().borrow_mut() .insert(base, llconst); assert!(prev_const.is_none() || prev_const == Some(llconst)); @@ -333,7 +333,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } Some(autoref) => { cx.sess().span_bug(e.span, - &format!("unimplemented const second autoref {:?}", autoref)[]) + &format!("unimplemented const second autoref {:?}", autoref)) } } } @@ -344,6 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let csize = machine::llsize_of_alloc(cx, val_ty(llconst)); let tsize = machine::llsize_of_alloc(cx, llty); if csize != tsize { + cx.sess().abort_if_errors(); unsafe { // FIXME these values could use some context llvm::LLVMDumpValue(llconst); @@ -351,22 +352,123 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } cx.sess().bug(&format!("const {} of type {} has size {} instead of {}", e.repr(cx.tcx()), ty_to_string(cx.tcx(), ety_adjusted), - csize, tsize)[]); + csize, tsize)); } (llconst, ety_adjusted) } +fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty, + te: ValueRef) { + // The only kind of unary expression that we check for validity + // here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`). + if let ast::ExprUnary(ast::UnNeg, ref inner_e) = e.node { + + // An unfortunate special case: we parse e.g. -128 as a + // negation of the literal 128, which means if we're expecting + // a i8 (or if it was already suffixed, e.g. `-128_i8`), then + // 128 will have already overflowed to -128, and so then the + // constant evaluator thinks we're trying to negate -128. + // + // Catch this up front by looking for ExprLit directly, + // and just accepting it. + if let ast::ExprLit(_) = inner_e.node { return; } + + let result = match t.sty { + ty::ty_int(int_type) => { + let input = match const_to_opt_int(te) { + Some(v) => v, + None => return, + }; + const_int_checked_neg( + input, e, Some(const_eval::IntTy::from(cx.tcx(), int_type))) + } + ty::ty_uint(uint_type) => { + let input = match const_to_opt_uint(te) { + Some(v) => v, + None => return, + }; + const_uint_checked_neg( + input, e, Some(const_eval::UintTy::from(cx.tcx(), uint_type))) + } + _ => return, + }; + + // We do not actually care about a successful result. + if let Err(err) = result { + cx.tcx().sess.span_err(e.span, &err.description()); + } + } +} + +fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty, + te1: ValueRef, te2: ValueRef) { + let b = if let ast::ExprBinary(b, _, _) = e.node { b } else { return }; + + let result = match t.sty { + ty::ty_int(int_type) => { + let (lhs, rhs) = match (const_to_opt_int(te1), + const_to_opt_int(te2)) { + (Some(v1), Some(v2)) => (v1, v2), + _ => return, + }; + + let opt_ety = Some(const_eval::IntTy::from(cx.tcx(), int_type)); + match b.node { + ast::BiAdd => const_int_checked_add(lhs, rhs, e, opt_ety), + ast::BiSub => const_int_checked_sub(lhs, rhs, e, opt_ety), + ast::BiMul => const_int_checked_mul(lhs, rhs, e, opt_ety), + ast::BiDiv => const_int_checked_div(lhs, rhs, e, opt_ety), + ast::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety), + ast::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety), + ast::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety), + _ => return, + } + } + ty::ty_uint(uint_type) => { + let (lhs, rhs) = match (const_to_opt_uint(te1), + const_to_opt_uint(te2)) { + (Some(v1), Some(v2)) => (v1, v2), + _ => return, + }; + + let opt_ety = Some(const_eval::UintTy::from(cx.tcx(), uint_type)); + match b.node { + ast::BiAdd => const_uint_checked_add(lhs, rhs, e, opt_ety), + ast::BiSub => const_uint_checked_sub(lhs, rhs, e, opt_ety), + ast::BiMul => const_uint_checked_mul(lhs, rhs, e, opt_ety), + ast::BiDiv => const_uint_checked_div(lhs, rhs, e, opt_ety), + ast::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety), + ast::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety), + ast::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety), + _ => return, + } + } + _ => return, + }; + // We do not actually care about a successful result. + if let Err(err) = result { + cx.tcx().sess.span_err(e.span, &err.description()); + } +} + fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr, ety: Ty<'tcx>, - param_substs: &'tcx Substs<'tcx>) -> ValueRef { + param_substs: &'tcx Substs<'tcx>) + -> ValueRef +{ + debug!("const_expr_unadjusted(e={}, ety={}, param_substs={})", + e.repr(cx.tcx()), + ety.repr(cx.tcx()), + param_substs.repr(cx.tcx())); + let map_list = |exprs: &[P]| { exprs.iter().map(|e| const_expr(cx, &**e, param_substs).0) .fold(Vec::new(), |mut l, val| { l.push(val); l }) }; unsafe { let _icx = push_ctxt("const_expr"); - return match e.node { + match e.node { ast::ExprLit(ref lit) => { const_lit(cx, e, &**lit) } @@ -374,6 +476,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, /* Neither type is bottom, and we expect them to be unified * already, so the following is safe. */ let (te1, ty) = const_expr(cx, &**e1, param_substs); + debug!("const_expr_unadjusted: te1={}, ty={}", + cx.tn().val_to_string(te1), + ty.repr(cx.tcx())); let is_simd = ty::type_is_simd(cx.tcx(), ty); let intype = if is_simd { ty::simd_type(cx.tcx(), ty) @@ -384,9 +489,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let signed = ty::type_is_signed(intype); let (te2, _) = const_expr(cx, &**e2, param_substs); - let te2 = base::cast_shift_const_rhs(b, te1, te2); - return match b.node { + check_binary_expr_validity(cx, e, ty, te1, te2); + + match b.node { ast::BiAdd => { if is_float { llvm::LLVMConstFAdd(te1, te2) } else { llvm::LLVMConstAdd(te1, te2) } @@ -414,8 +520,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::BiBitXor => llvm::LLVMConstXor(te1, te2), ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2), ast::BiBitOr => llvm::LLVMConstOr(te1, te2), - ast::BiShl => llvm::LLVMConstShl(te1, te2), + ast::BiShl => { + let te2 = base::cast_shift_const_rhs(b.node, te1, te2); + llvm::LLVMConstShl(te1, te2) + } ast::BiShr => { + let te2 = base::cast_shift_const_rhs(b.node, te1, te2); if signed { llvm::LLVMConstAShr(te1, te2) } else { llvm::LLVMConstLShr(te1, te2) } } @@ -437,10 +547,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } }, - ast::ExprUnary(u, ref e) => { - let (te, ty) = const_expr(cx, &**e, param_substs); + ast::ExprUnary(u, ref inner_e) => { + let (te, ty) = const_expr(cx, &**inner_e, param_substs); + + check_unary_expr_validity(cx, e, ty, te); + let is_float = ty::type_is_fp(ty); - return match u { + match u { ast::UnUniq | ast::UnDeref => { const_deref(cx, te, ty).0 } @@ -469,24 +582,18 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprIndex(ref base, ref index) => { let (bv, bt) = const_expr(cx, &**base, param_substs); - let iv = match const_eval::eval_const_expr(cx.tcx(), &**index) { - const_eval::const_int(i) => i as u64, - const_eval::const_uint(u) => u, + let iv = match const_eval::eval_const_expr_partial(cx.tcx(), &**index, None) { + Ok(const_eval::const_int(i)) => i as u64, + Ok(const_eval::const_uint(u)) => u, _ => cx.sess().span_bug(index.span, "index is not an integer-constant expression") }; let (arr, len) = match bt.sty { ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)), - ty::ty_open(ty) => match ty.sty { - ty::ty_vec(_, None) | ty::ty_str => { - let e1 = const_get_elt(cx, bv, &[0]); - (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1])) - }, - _ => cx.sess().span_bug(base.span, - &format!("index-expr base must be a vector \ - or string type, found {}", - ty_to_string(cx.tcx(), bt))[]) - }, + ty::ty_vec(_, None) | ty::ty_str => { + let e1 = const_get_elt(cx, bv, &[0]); + (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1])) + } ty::ty_rptr(_, mt) => match mt.ty.sty { ty::ty_vec(_, Some(u)) => { (const_deref_ptr(cx, bv), C_uint(cx, u)) @@ -494,12 +601,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => cx.sess().span_bug(base.span, &format!("index-expr base must be a vector \ or string type, found {}", - ty_to_string(cx.tcx(), bt))[]) + ty_to_string(cx.tcx(), bt))) }, _ => cx.sess().span_bug(base.span, &format!("index-expr base must be a vector \ or string type, found {}", - ty_to_string(cx.tcx(), bt))[]) + ty_to_string(cx.tcx(), bt))) }; let len = llvm::LLVMConstIntGetZExtValue(len) as u64; @@ -518,8 +625,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // pass. Reporting here is a bit late. cx.sess().span_err(e.span, "const index-expr is out of bounds"); + C_undef(type_of::type_of(cx, bt).element_type()) + } else { + const_get_elt(cx, arr, &[iv as c_uint]) } - const_get_elt(cx, arr, &[iv as c_uint]) } ast::ExprCast(ref base, _) => { let llty = type_of::type_of(cx, ety); @@ -527,8 +636,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if expr::cast_is_noop(basety, ety) { return v; } - return match (expr::cast_type_kind(cx.tcx(), basety), - expr::cast_type_kind(cx.tcx(), ety)) { + match (expr::cast_type_kind(cx.tcx(), basety), + expr::cast_type_kind(cx.tcx(), ety)) { (expr::cast_integral, expr::cast_integral) => { let s = ty::type_is_signed(basety) as Bool; @@ -595,15 +704,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, _ => break, } } - let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned(); + let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); if let Some(def::DefStatic(def_id, _)) = opt_def { - return get_static_val(cx, def_id, ety); + get_static_val(cx, def_id, ety) + } else { + // If this isn't the address of a static, then keep going through + // normal constant evaluation. + let (v, _) = const_expr(cx, &**sub, param_substs); + addr_of(cx, v, "ref", e.id) } - - // If this isn't the address of a static, then keep going through - // normal constant evaluation. - let (v, _) = const_expr(cx, &**sub, param_substs); - addr_of(cx, v, "ref", e.id) } ast::ExprAddrOf(ast::MutMutable, ref sub) => { let (v, _) = const_expr(cx, &**sub, param_substs); @@ -663,11 +772,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprRepeat(ref elem, ref count) => { let unit_ty = ty::sequence_element_type(cx.tcx(), ety); let llunitty = type_of::type_of(cx, unit_ty); - let n = match const_eval::eval_const_expr(cx.tcx(), &**count) { - const_eval::const_int(i) => i as uint, - const_eval::const_uint(i) => i as uint, - _ => cx.sess().span_bug(count.span, "count must be integral const expression.") - }; + let n = ty::eval_repeat_count(cx.tcx(), count); let unit_val = const_expr(cx, &**elem, param_substs).0; let vs: Vec<_> = repeat(unit_val).take(n).collect(); if val_ty(unit_val) != llunitty { @@ -676,10 +781,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, C_array(llunitty, &vs[..]) } } - ast::ExprPath(_) | ast::ExprQPath(_) => { - let def = cx.tcx().def_map.borrow()[e.id]; + ast::ExprPath(..) => { + let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def(); match def { - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => { + def::DefFn(..) | def::DefMethod(..) => { expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val } def::DefConst(def_id) => { @@ -714,7 +819,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } ast::ExprCall(ref callee, ref args) => { - let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned(); + let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def()); let arg_vals = map_list(&args[..]); match opt_def { Some(def::DefStruct(_)) => { @@ -753,7 +858,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } _ => cx.sess().span_bug(e.span, "bad constant expression type in consts::const_expr") - }; + } } } @@ -763,7 +868,7 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) { let g = base::get_item_val(ccx, id); // At this point, get_item_val has already translated the // constant's initializer to determine its LLVM type. - let v = ccx.static_values().borrow()[id].clone(); + let v = ccx.static_values().borrow().get(&id).unwrap().clone(); // boolean SSA values are i1, but they have to be stored in i8 slots, // otherwise some LLVM optimization passes don't work as expected let v = if llvm::LLVMTypeOf(v) == Type::i1(ccx).to_ref() { diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index eb07bdb7ba..8919a386a4 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -10,7 +10,7 @@ use llvm; use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef}; -use llvm::{TargetData}; +use llvm::TargetData; use llvm::mk_target_data; use metadata::common::LinkMeta; use middle::def::ExportMap; @@ -18,7 +18,7 @@ use middle::traits; use trans::adt; use trans::base; use trans::builder::Builder; -use trans::common::{ExternMap,tydesc_info,BuilderRef_res}; +use trans::common::{ExternMap,BuilderRef_res}; use trans::debuginfo; use trans::monomorphize::MonoId; use trans::type_::{Type, TypeNames}; @@ -38,18 +38,17 @@ use syntax::ast; use syntax::parse::token::InternedString; pub struct Stats { - pub n_static_tydescs: Cell, - pub n_glues_created: Cell, - pub n_null_glues: Cell, - pub n_real_glues: Cell, - pub n_fns: Cell, - pub n_monos: Cell, - pub n_inlines: Cell, - pub n_closures: Cell, - pub n_llvm_insns: Cell, - pub llvm_insns: RefCell>, + pub n_glues_created: Cell, + pub n_null_glues: Cell, + pub n_real_glues: Cell, + pub n_fns: Cell, + pub n_monos: Cell, + pub n_inlines: Cell, + pub n_closures: Cell, + pub n_llvm_insns: Cell, + pub llvm_insns: RefCell>, // (ident, llvm-instructions) - pub fn_stats: RefCell >, + pub fn_stats: RefCell >, } /// The shared portion of a `CrateContext`. There is one `SharedCrateContext` @@ -69,6 +68,8 @@ pub struct SharedCrateContext<'tcx> { symbol_hasher: RefCell, tcx: ty::ctxt<'tcx>, stats: Stats, + check_overflow: bool, + check_drop_flag_for_sanity: bool, available_monomorphizations: RefCell>, available_drop_glues: RefCell, String>>, @@ -88,10 +89,6 @@ pub struct LocalCrateContext<'tcx> { needs_unwind_cleanup_cache: RefCell, bool>>, fn_pointer_shims: RefCell, ValueRef>>, drop_glues: RefCell, ValueRef>>, - tydescs: RefCell, Rc>>>, - /// Set when running emit_tydescs to enforce that no more tydescs are - /// created. - finished_tydescs: Cell, /// Track mapping of external ids to local items imported for inlining external: RefCell>>, /// Backwards version of the `external` map (inlined items to where they @@ -99,9 +96,9 @@ pub struct LocalCrateContext<'tcx> { external_srcs: RefCell>, /// Cache instances of monomorphized functions monomorphized: RefCell, ValueRef>>, - monomorphizing: RefCell>, + monomorphizing: RefCell>, /// Cache generated vtables - vtables: RefCell, ty::PolyTraitRef<'tcx>), ValueRef>>, + vtables: RefCell, ValueRef>>, /// Cache of constant strings, const_cstr_cache: RefCell>, @@ -153,7 +150,7 @@ pub struct LocalCrateContext<'tcx> { /// Number of LLVM instructions translated into this `LocalCrateContext`. /// This is used to perform some basic load-balancing to keep all LLVM /// contexts around the same size. - n_llvm_insns: Cell, + n_llvm_insns: Cell, trait_cache: RefCell, traits::Vtable<'tcx, ()>>>, @@ -164,12 +161,12 @@ pub struct CrateContext<'a, 'tcx: 'a> { local: &'a LocalCrateContext<'tcx>, /// The index of `local` in `shared.local_ccxs`. This is used in /// `maybe_iter(true)` to identify the original `LocalCrateContext`. - index: uint, + index: usize, } pub struct CrateContextIterator<'a, 'tcx: 'a> { shared: &'a SharedCrateContext<'tcx>, - index: uint, + index: usize, } impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> { @@ -194,9 +191,9 @@ impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> { /// The iterator produced by `CrateContext::maybe_iter`. pub struct CrateContextMaybeIterator<'a, 'tcx: 'a> { shared: &'a SharedCrateContext<'tcx>, - index: uint, + index: usize, single: bool, - origin: uint, + origin: usize, } impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> { @@ -240,12 +237,14 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR impl<'tcx> SharedCrateContext<'tcx> { pub fn new(crate_name: &str, - local_count: uint, + local_count: usize, tcx: ty::ctxt<'tcx>, export_map: ExportMap, symbol_hasher: Sha256, link_meta: LinkMeta, - reachable: NodeSet) + reachable: NodeSet, + check_overflow: bool, + check_drop_flag_for_sanity: bool) -> SharedCrateContext<'tcx> { let (metadata_llcx, metadata_llmod) = unsafe { create_context_and_module(&tcx.sess, "metadata") @@ -262,7 +261,6 @@ impl<'tcx> SharedCrateContext<'tcx> { symbol_hasher: RefCell::new(symbol_hasher), tcx: tcx, stats: Stats { - n_static_tydescs: Cell::new(0), n_glues_created: Cell::new(0), n_null_glues: Cell::new(0), n_real_glues: Cell::new(0), @@ -274,6 +272,8 @@ impl<'tcx> SharedCrateContext<'tcx> { llvm_insns: RefCell::new(FnvHashMap()), fn_stats: RefCell::new(Vec::new()), }, + check_overflow: check_overflow, + check_drop_flag_for_sanity: check_drop_flag_for_sanity, available_monomorphizations: RefCell::new(FnvHashSet()), available_drop_glues: RefCell::new(FnvHashMap()), }; @@ -302,7 +302,7 @@ impl<'tcx> SharedCrateContext<'tcx> { } } - pub fn get_ccx<'a>(&'a self, index: uint) -> CrateContext<'a, 'tcx> { + pub fn get_ccx<'a>(&'a self, index: usize) -> CrateContext<'a, 'tcx> { CrateContext { shared: self, local: &self.local_ccxs[index], @@ -378,7 +378,7 @@ impl<'tcx> LocalCrateContext<'tcx> { .target .target .data_layout - []); + ); let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo { Some(debuginfo::CrateDebugContext::new(llmod)) @@ -396,8 +396,6 @@ impl<'tcx> LocalCrateContext<'tcx> { needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()), fn_pointer_shims: RefCell::new(FnvHashMap()), drop_glues: RefCell::new(FnvHashMap()), - tydescs: RefCell::new(FnvHashMap()), - finished_tydescs: Cell::new(false), external: RefCell::new(DefIdMap()), external_srcs: RefCell::new(NodeMap()), monomorphized: RefCell::new(FnvHashMap()), @@ -439,8 +437,6 @@ impl<'tcx> LocalCrateContext<'tcx> { str_slice_ty.set_struct_body(&[Type::i8p(&ccx), ccx.int_type()], false); ccx.tn().associate_type("str_slice", &str_slice_ty); - ccx.tn().associate_type("tydesc", &Type::tydesc(&ccx, str_slice_ty)); - if ccx.sess().count_llvm_insns() { base::init_insn_ctxt() } @@ -463,7 +459,7 @@ impl<'tcx> LocalCrateContext<'tcx> { CrateContext { shared: shared, local: self, - index: -1 as uint, + index: !0 as usize, } } } @@ -516,10 +512,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.local.builder.b } - pub fn tydesc_type(&self) -> Type { - self.local.tn.find_type("tydesc").unwrap() - } - pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef { if let Some(v) = self.intrinsics().borrow().get(key).cloned() { return v; @@ -587,14 +579,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local.drop_glues } - pub fn tydescs<'a>(&'a self) -> &'a RefCell, Rc>>> { - &self.local.tydescs - } - - pub fn finished_tydescs<'a>(&'a self) -> &'a Cell { - &self.local.finished_tydescs - } - pub fn external<'a>(&'a self) -> &'a RefCell>> { &self.local.external } @@ -607,12 +591,11 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local.monomorphized } - pub fn monomorphizing<'a>(&'a self) -> &'a RefCell> { + pub fn monomorphizing<'a>(&'a self) -> &'a RefCell> { &self.local.monomorphizing } - pub fn vtables<'a>(&'a self) -> &'a RefCell, ty::PolyTraitRef<'tcx>), - ValueRef>> { + pub fn vtables<'a>(&'a self) -> &'a RefCell, ValueRef>> { &self.local.vtables } @@ -731,7 +714,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable /// address space on 64-bit ARMv8 and x86_64. pub fn obj_size_bound(&self) -> u64 { - match &self.sess().target.target.target_pointer_width[] { + match &self.sess().target.target.target_pointer_width[..] { "32" => 1 << 31, "64" => 1 << 47, _ => unreachable!() // error handled by config::build_target_config @@ -741,7 +724,18 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! { self.sess().fatal( &format!("the type `{}` is too big for the current architecture", - obj.repr(self.tcx()))[]) + obj.repr(self.tcx()))) + } + + pub fn check_overflow(&self) -> bool { + self.shared.check_overflow + } + + pub fn check_drop_flag_for_sanity(&self) -> bool { + // This controls whether we emit a conditional llvm.debugtrap + // guarded on whether the dropflag is one of its (two) valid + // values. + self.shared.check_drop_flag_for_sanity } } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 26e12a1af4..5b1ac88c20 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -12,6 +12,7 @@ use llvm::ValueRef; use middle::def; use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem}; use trans::base::*; +use trans::basic_block::BasicBlock; use trans::build::*; use trans::callee; use trans::cleanup::CleanupMethods; @@ -39,8 +40,12 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>, let fcx = cx.fcx; debug!("trans_stmt({})", s.repr(cx.tcx())); + if cx.unreachable.get() { + return cx; + } + if cx.sess().asm_comments() { - add_span_comment(cx, s.span, &s.repr(cx.tcx())[]); + add_span_comment(cx, s.span, &s.repr(cx.tcx())); } let mut bcx = cx; @@ -75,8 +80,13 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>, pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_stmt_semi"); + + if cx.unreachable.get() { + return cx; + } + let ty = expr_ty(cx, e); - if type_needs_drop(cx.tcx(), ty) { + if cx.fcx.type_needs_drop(ty) { expr::trans_to_lvalue(cx, e, "stmt").bcx } else { expr::trans_into(cx, e, expr::Ignore) @@ -88,6 +98,11 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, mut dest: expr::Dest) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_block"); + + if bcx.unreachable.get() { + return bcx; + } + let fcx = bcx.fcx; let mut bcx = bcx; @@ -140,6 +155,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.to_str(), if_id, bcx.expr_to_string(cond), thn.id, dest.to_string(bcx.ccx())); let _icx = push_ctxt("trans_if"); + + if bcx.unreachable.get() { + return bcx; + } + let mut bcx = bcx; let cond_val = unpack_result!(bcx, expr::trans(bcx, cond).to_llbool()); @@ -213,6 +233,11 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, body: &ast::Block) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_while"); + + if bcx.unreachable.get() { + return bcx; + } + let fcx = bcx.fcx; // bcx @@ -256,6 +281,11 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, body: &ast::Block) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_loop"); + + if bcx.unreachable.get() { + return bcx; + } + let fcx = bcx.fcx; // bcx @@ -280,30 +310,36 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fcx.pop_loop_cleanup_scope(loop_expr.id); + // If there are no predecessors for the next block, we just translated an endless loop and the + // next block is unreachable + if BasicBlock(next_bcx_in.llbb).pred_iter().next().is_none() { + Unreachable(next_bcx_in); + } + return next_bcx_in; } pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, opt_label: Option, - exit: uint) + exit: usize) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_break_cont"); - let fcx = bcx.fcx; if bcx.unreachable.get() { return bcx; } + let fcx = bcx.fcx; + // Locate loop that we will break to let loop_id = match opt_label { None => fcx.top_loop_scope(), Some(_) => { - match bcx.tcx().def_map.borrow().get(&expr.id) { - Some(&def::DefLabel(loop_id)) => loop_id, - ref r => { - bcx.tcx().sess.bug(&format!("{:?} in def-map for label", - r)[]) + match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def()) { + Some(def::DefLabel(loop_id)) => loop_id, + r => { + bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r)) } } } @@ -335,6 +371,11 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, retval_expr: Option<&ast::Expr>) -> Block<'blk, 'tcx> { let _icx = push_ctxt("trans_ret"); + + if bcx.unreachable.get() { + return bcx; + } + let fcx = bcx.fcx; let mut bcx = bcx; let dest = match (fcx.llretslotptr.get(), retval_expr) { @@ -366,11 +407,15 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_value"); + if bcx.unreachable.get() { + return bcx; + } + let v_str = C_str_slice(ccx, fail_str); let loc = bcx.sess().codemap().lookup_char_pos(call_info.span.lo); - let filename = token::intern_and_get_ident(&loc.file.name[]); + let filename = token::intern_and_get_ident(&loc.file.name); let filename = C_str_slice(ccx, filename); - let line = C_uint(ccx, loc.line); + let line = C_u32(ccx, loc.line as u32); let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc", call_info.id); @@ -393,13 +438,17 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_bounds_check"); + if bcx.unreachable.get() { + return bcx; + } + // Extract the file/line from the span let loc = bcx.sess().codemap().lookup_char_pos(call_info.span.lo); - let filename = token::intern_and_get_ident(&loc.file.name[]); + let filename = token::intern_and_get_ident(&loc.file.name); // Invoke the lang item let filename = C_str_slice(ccx, filename); - let line = C_uint(ccx, loc.line); + let line = C_u32(ccx, loc.line as u32); let file_line_const = C_struct(ccx, &[filename, line], false); let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc", call_info.id); diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index f4a5ba98b6..a736a9fe88 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -113,7 +113,7 @@ use trans::expr; use trans::tvec; use trans::type_of; use middle::ty::{self, Ty}; -use util::ppaux::{ty_to_string}; +use util::ppaux::ty_to_string; use std::fmt; use syntax::ast; @@ -122,7 +122,7 @@ use syntax::codemap::DUMMY_SP; /// A `Datum` encapsulates the result of evaluating an expression. It /// describes where the value is stored, what Rust type the value has, /// whether it is addressed by reference, and so forth. Please refer -/// the section on datums in `doc.rs` for more details. +/// the section on datums in `README.md` for more details. #[derive(Clone, Copy)] pub struct Datum<'tcx, K> { /// The llvm value. This is either a pointer to the Rust value or @@ -172,7 +172,7 @@ impl Drop for Rvalue { fn drop(&mut self) { } } -#[derive(Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum RvalueMode { /// `val` is a pointer to the actual value (and thus has type *T) ByRef, @@ -195,24 +195,18 @@ pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Allocates temporary space on the stack using alloca() and returns a by-ref Datum pointing to /// it. The memory will be dropped upon exit from `scope`. The callback `populate` should -/// initialize the memory. If `zero` is true, the space will be zeroed when it is allocated; this -/// is not necessary unless `bcx` does not dominate the end of `scope`. +/// initialize the memory. pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>, name: &str, - zero: bool, scope: cleanup::ScopeId, arg: A, populate: F) -> DatumBlock<'blk, 'tcx, Lvalue> where F: FnOnce(A, Block<'blk, 'tcx>, ValueRef) -> Block<'blk, 'tcx>, { - let scratch = if zero { - alloca_zeroed(bcx, ty, name) - } else { - let llty = type_of::type_of(bcx.ccx(), ty); - alloca(bcx, llty, name) - }; + let llty = type_of::type_of(bcx.ccx(), ty); + let scratch = alloca(bcx, llty, name); // Subtle. Populate the scratch memory *before* scheduling cleanup. let bcx = populate(arg, bcx, scratch); @@ -311,9 +305,10 @@ impl KindOps for Lvalue { val: ValueRef, ty: Ty<'tcx>) -> Block<'blk, 'tcx> { - if type_needs_drop(bcx.tcx(), ty) { - // cancel cleanup of affine values by zeroing out - let () = zero_mem(bcx, val, ty); + let _icx = push_ctxt("::post_store"); + if bcx.fcx.type_needs_drop(ty) { + // cancel cleanup of affine values by drop-filling the memory + let () = drop_done_fill_mem(bcx, val, ty); bcx } else { bcx @@ -382,7 +377,7 @@ impl<'tcx> Datum<'tcx, Rvalue> { ByValue => { lvalue_scratch_datum( - bcx, self.ty, name, false, scope, self, + bcx, self.ty, name, scope, self, |this, bcx, llval| this.store_to(bcx, llval)) } } @@ -476,15 +471,6 @@ impl<'tcx> Datum<'tcx, Expr> { }) } - /// Ensures that `self` will get cleaned up, if it is not an lvalue already. - pub fn clean<'blk>(self, - bcx: Block<'blk, 'tcx>, - name: &'static str, - expr_id: ast::NodeId) - -> Block<'blk, 'tcx> { - self.to_lvalue_datum(bcx, name, expr_id).bcx - } - pub fn to_lvalue_datum<'blk>(self, bcx: Block<'blk, 'tcx>, name: &str, @@ -492,8 +478,6 @@ impl<'tcx> Datum<'tcx, Expr> { -> DatumBlock<'blk, 'tcx, Lvalue> { debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx())); - assert!(lltype_is_sized(bcx.tcx(), self.ty), - "Trying to convert unsized value to lval"); self.match_kind( |l| DatumBlock::new(bcx, l), |r| { @@ -549,15 +533,10 @@ impl<'tcx> Datum<'tcx, Lvalue> { -> Datum<'tcx, Lvalue> where F: FnOnce(ValueRef) -> ValueRef, { - let val = match self.ty.sty { - _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val), - ty::ty_open(_) => { - let base = Load(bcx, expr::get_dataptr(bcx, self.val)); - gep(base) - } - _ => bcx.tcx().sess.bug( - &format!("Unexpected unsized type in get_element: {}", - bcx.ty_to_string(self.ty))[]) + let val = if type_is_sized(bcx.tcx(), self.ty) { + gep(self.val) + } else { + gep(Load(bcx, expr::get_dataptr(bcx, self.val))) }; Datum { val: val, @@ -566,7 +545,8 @@ impl<'tcx> Datum<'tcx, Lvalue> { } } - pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) { + pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>) + -> (ValueRef, ValueRef) { //! Converts a vector into the slice pair. tvec::get_base_and_len(bcx, self.val, self.ty) @@ -662,7 +642,7 @@ impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> { /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is /// naturally passed around by value, and not by reference. pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { - assert!(!type_needs_drop(bcx.tcx(), self.ty)); + assert!(!bcx.fcx.type_needs_drop(self.ty)); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); if self.kind.is_by_ref() { load_ty(bcx, self.val, self.ty) diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index fc0129239a..2747288b60 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -206,16 +206,17 @@ use middle::pat_util; use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet}; use util::ppaux; +use util::common::path2cstr; use libc::{c_uint, c_longlong}; -use std::ffi::CString; use std::cell::{Cell, RefCell}; +use std::ffi::CString; +use std::path::Path; use std::ptr; use std::rc::{Rc, Weak}; use syntax::util::interner::Interner; use syntax::codemap::{Span, Pos}; use syntax::{ast, codemap, ast_util, ast_map, attr}; -use syntax::ast_util::PostExpansionMethod; use syntax::parse::token::{self, special_idents}; const DW_LANG_RUST: c_uint = 0x9000; @@ -286,7 +287,7 @@ impl<'tcx> TypeMap<'tcx> { metadata: DIType) { if self.type_to_metadata.insert(type_, metadata).is_some() { cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!", - ppaux::ty_to_string(cx.tcx(), type_))[]); + ppaux::ty_to_string(cx.tcx(), type_))); } } @@ -299,7 +300,7 @@ impl<'tcx> TypeMap<'tcx> { if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id); cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!", - &unique_type_id_str[..])[]); + &unique_type_id_str[..])); } } @@ -412,7 +413,7 @@ impl<'tcx> TypeMap<'tcx> { ty::ty_vec(inner_type, optional_length) => { match optional_length { Some(len) => { - unique_type_id.push_str(&format!("[{}]", len)[]); + unique_type_id.push_str(&format!("[{}]", len)); } None => { unique_type_id.push_str("[]"); @@ -472,7 +473,7 @@ impl<'tcx> TypeMap<'tcx> { } } }, - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let typer = NormalizingClosureTyper::new(cx.tcx()); let closure_ty = typer.closure_type(def_id, substs); self.get_unique_type_id_of_closure_type(cx, @@ -481,8 +482,8 @@ impl<'tcx> TypeMap<'tcx> { }, _ => { cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}", - &ppaux::ty_to_string(cx.tcx(), type_)[], - type_.sty)[]) + &ppaux::ty_to_string(cx.tcx(), type_), + type_.sty)) } }; @@ -525,7 +526,7 @@ impl<'tcx> TypeMap<'tcx> { output.push_str(crate_hash.as_str()); output.push_str("/"); - output.push_str(&format!("{:x}", def_id.node)[]); + output.push_str(&format!("{:x}", def_id.node)); // Maybe check that there is no self type here. @@ -600,7 +601,7 @@ impl<'tcx> TypeMap<'tcx> { -> UniqueTypeId { let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type); let enum_variant_type_id = format!("{}::{}", - &self.get_unique_type_id_as_string(enum_type_id)[], + &self.get_unique_type_id_as_string(enum_type_id), variant_name); let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id)); UniqueTypeId(interner_key) @@ -693,8 +694,9 @@ impl FunctionDebugContext { struct FunctionDebugContextData { scope_map: RefCell>, fn_metadata: DISubprogram, - argument_counter: Cell, + argument_counter: Cell, source_locations_enabled: Cell, + source_location_override: Cell, } enum VariableAccess<'a> { @@ -706,7 +708,7 @@ enum VariableAccess<'a> { } enum VariableKind { - ArgumentVariable(uint /*index*/), + ArgumentVariable(usize /*index*/), LocalVariable, CapturedVariable, } @@ -783,19 +785,19 @@ pub fn create_global_var_metadata(cx: &CrateContext, create_global_var_metadata() - Captured var-id refers to \ unexpected ast_item variant: {:?}", - var_item)[]) + var_item)) } } }, _ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \ - Captured var-id refers to unexpected \ ast_map variant: {:?}", - var_item)[]) + var_item)) }; let (file_metadata, line_number) = if span != codemap::DUMMY_SP { let loc = span_start(cx, span); - (file_metadata(cx, &loc.file.name[]), loc.line as c_uint) + (file_metadata(cx, &loc.file.name), loc.line as c_uint) } else { (UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER) }; @@ -847,7 +849,7 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { None => { bcx.sess().span_bug(span, &format!("no entry in lllocals table for {}", - node_id)[]); + node_id)); } }; @@ -874,7 +876,7 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, node_id: ast::NodeId, env_pointer: ValueRef, - env_index: uint, + env_index: usize, captured_by_ref: bool, span: Span) { if bcx.unreachable.get() || @@ -903,7 +905,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, "debuginfo::create_captured_var_metadata() - \ Captured var-id refers to unexpected \ ast_map variant: {:?}", - ast_item)[]); + ast_item)); } } } @@ -913,7 +915,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, &format!("debuginfo::create_captured_var_metadata() - \ Captured var-id refers to unexpected \ ast_map variant: {:?}", - ast_item)[]); + ast_item)); } }; @@ -1025,7 +1027,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { None => { bcx.sess().span_bug(span, &format!("no entry in lllocals table for {}", - node_id)[]); + node_id)); } }; @@ -1174,6 +1176,12 @@ pub fn set_source_location(fcx: &FunctionContext, return; } FunctionDebugContext::RegularContext(box ref function_debug_context) => { + if function_debug_context.source_location_override.get() { + // Just ignore any attempts to set a new debug location while + // the override is active. + return; + } + let cx = fcx.ccx; debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span)); @@ -1192,6 +1200,35 @@ pub fn set_source_location(fcx: &FunctionContext, } } +/// This function makes sure that all debug locations emitted while executing +/// `wrapped_function` are set to the given `debug_loc`. +pub fn with_source_location_override(fcx: &FunctionContext, + debug_loc: DebugLoc, + wrapped_function: F) -> R + where F: FnOnce() -> R +{ + match fcx.debug_context { + FunctionDebugContext::DebugInfoDisabled => { + wrapped_function() + } + FunctionDebugContext::FunctionWithoutDebugInfo => { + set_debug_location(fcx.ccx, UnknownLocation); + wrapped_function() + } + FunctionDebugContext::RegularContext(box ref function_debug_context) => { + if function_debug_context.source_location_override.get() { + wrapped_function() + } else { + debug_loc.apply(fcx); + function_debug_context.source_location_override.set(true); + let result = wrapped_function(); + function_debug_context.source_location_override.set(false); + result + } + } + } +} + /// Clears the current debug location. /// /// Instructions generated hereafter won't be assigned a source location. @@ -1254,7 +1291,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, match item.node { ast::ItemFn(ref fn_decl, _, _, ref generics, ref top_level_block) => { - (item.ident, &**fn_decl, generics, &**top_level_block, item.span, true) + (item.ident, fn_decl, generics, top_level_block, item.span, true) } _ => { cx.sess().span_bug(item.span, @@ -1262,25 +1299,30 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } } - ast_map::NodeImplItem(ref item) => { - match **item { - ast::MethodImplItem(ref method) => { - if contains_nodebug_attribute(&method.attrs) { + ast_map::NodeImplItem(impl_item) => { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + if contains_nodebug_attribute(&impl_item.attrs) { return FunctionDebugContext::FunctionWithoutDebugInfo; } - (method.pe_ident(), - method.pe_fn_decl(), - method.pe_generics(), - method.pe_body(), - method.span, + (impl_item.ident, + &sig.decl, + &sig.generics, + body, + impl_item.span, true) } - ast::TypeImplItem(ref typedef) => { - cx.sess().span_bug(typedef.span, + ast::TypeImplItem(_) => { + cx.sess().span_bug(impl_item.span, "create_function_debug_context() \ called on associated type?!") } + ast::MacImplItem(_) => { + cx.sess().span_bug(impl_item.span, + "create_function_debug_context() \ + called on unexpanded macro?!") + } } } ast_map::NodeExpr(ref expr) => { @@ -1288,11 +1330,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprClosure(_, ref fn_decl, ref top_level_block) => { let name = format!("fn{}", token::gensym("fn")); let name = token::str_to_ident(&name[..]); - (name, &**fn_decl, + (name, fn_decl, // This is not quite right. It should actually inherit // the generics of the enclosing function. &empty_generics, - &**top_level_block, + top_level_block, expr.span, // Don't try to lookup the item path: false) @@ -1301,25 +1343,25 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, "create_function_debug_context: expected an expr_fn_block here") } } - ast_map::NodeTraitItem(ref trait_method) => { - match **trait_method { - ast::ProvidedMethod(ref method) => { - if contains_nodebug_attribute(&method.attrs) { + ast_map::NodeTraitItem(trait_item) => { + match trait_item.node { + ast::MethodTraitItem(ref sig, Some(ref body)) => { + if contains_nodebug_attribute(&trait_item.attrs) { return FunctionDebugContext::FunctionWithoutDebugInfo; } - (method.pe_ident(), - method.pe_fn_decl(), - method.pe_generics(), - method.pe_body(), - method.span, + (trait_item.ident, + &sig.decl, + &sig.generics, + body, + trait_item.span, true) } _ => { cx.sess() .bug(&format!("create_function_debug_context: \ unexpected sort of node: {:?}", - fnitem)[]) + fnitem)) } } } @@ -1330,7 +1372,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } _ => cx.sess().bug(&format!("create_function_debug_context: \ unexpected sort of node: {:?}", - fnitem)[]) + fnitem)) }; // This can be the case for functions inlined from another crate @@ -1339,7 +1381,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } let loc = span_start(cx, span); - let file_metadata = file_metadata(cx, &loc.file.name[]); + let file_metadata = file_metadata(cx, &loc.file.name); let function_type_metadata = unsafe { let fn_signature = get_function_signature(cx, @@ -1412,6 +1454,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn_metadata: fn_metadata, argument_counter: Cell::new(1), source_locations_enabled: Cell::new(false), + source_location_override: Cell::new(false), }; @@ -1588,20 +1631,13 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { cx.sess().warn("debuginfo: Invalid path to crate's local root source file!"); fallback_path(cx) } else { - match abs_path.path_relative_from(work_dir) { + match abs_path.relative_from(work_dir) { Some(ref p) if p.is_relative() => { - // prepend "./" if necessary - let dotdot = b".."; - let prefix: &[u8] = &[dotdot[0], ::std::old_path::SEP_BYTE]; - let mut path_bytes = p.as_vec().to_vec(); - - if &path_bytes[..2] != prefix && - &path_bytes[..2] != dotdot { - path_bytes.insert(0, prefix[0]); - path_bytes.insert(1, prefix[1]); + if p.starts_with(Path::new("./")) { + path2cstr(p) + } else { + path2cstr(&Path::new(".").join(p)) } - - CString::new(path_bytes).unwrap() } _ => fallback_path(cx) } @@ -1614,7 +1650,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { (option_env!("CFG_VERSION")).expect("CFG_VERSION")); let compile_unit_name = compile_unit_name.as_ptr(); - let work_dir = CString::new(work_dir.as_vec()).unwrap(); + let work_dir = path2cstr(&work_dir); let producer = CString::new(producer).unwrap(); let flags = "\0"; let split_name = "\0"; @@ -1659,7 +1695,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; let name = CString::new(name.as_bytes()).unwrap(); - match (variable_access, [].as_slice()) { + match (variable_access, &[][..]) { (DirectVariable { alloca }, address_operations) | (IndirectVariable {alloca, address_operations}, _) => { let metadata = unsafe { @@ -1716,7 +1752,7 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { debug!("file_metadata: {}", full_path); // FIXME (#9639): This needs to handle non-utf8 paths - let work_dir = cx.sess().working_dir.as_str().unwrap(); + let work_dir = cx.sess().working_dir.to_str().unwrap(); let file_name = if full_path.starts_with(work_dir) { &full_path[work_dir.len() + 1..full_path.len()] @@ -1751,7 +1787,7 @@ fn scope_metadata(fcx: &FunctionContext, fcx.ccx.sess().span_bug(error_reporting_span, &format!("debuginfo: Could not find scope info for node {:?}", - node)[]); + node)); } } } @@ -1778,14 +1814,14 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_bool => ("bool".to_string(), DW_ATE_boolean), ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char), ty::ty_int(int_ty) => match int_ty { - ast::TyIs(_) => ("isize".to_string(), DW_ATE_signed), + ast::TyIs => ("isize".to_string(), DW_ATE_signed), ast::TyI8 => ("i8".to_string(), DW_ATE_signed), ast::TyI16 => ("i16".to_string(), DW_ATE_signed), ast::TyI32 => ("i32".to_string(), DW_ATE_signed), ast::TyI64 => ("i64".to_string(), DW_ATE_signed) }, ty::ty_uint(uint_ty) => match uint_ty { - ast::TyUs(_) => ("usize".to_string(), DW_ATE_unsigned), + ast::TyUs => ("usize".to_string(), DW_ATE_unsigned), ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned), ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned), ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned), @@ -1837,7 +1873,7 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, //=----------------------------------------------------------------------------- enum MemberOffset { - FixedMemberOffset { bytes: uint }, + FixedMemberOffset { bytes: usize }, // For ComputedMemberOffset, the offset is read from the llvm type definition ComputedMemberOffset } @@ -1947,7 +1983,7 @@ impl<'tcx> RecursiveTypeDescription<'tcx> { cx.sess().bug(&format!("Forward declaration of potentially recursive type \ '{}' was not found in TypeMap!", ppaux::ty_to_string(cx.tcx(), unfinished_type)) - []); + ); } } @@ -1986,7 +2022,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { } let field_size = if self.is_simd { - machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields[0].mt.ty)) as uint + machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields[0].mt.ty)) as usize } else { 0xdeadbeef }; @@ -2209,7 +2245,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { // DWARF representation of enums uniform. // First create a description of the artificial wrapper struct: - let non_null_variant = &(*self.variants)[non_null_variant_index as uint]; + let non_null_variant = &(*self.variants)[non_null_variant_index as usize]; let non_null_variant_name = token::get_name(non_null_variant.name); // The llvm type and metadata of the pointer @@ -2254,7 +2290,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { // Encode the information about the null variant in the union // member's name. - let null_variant_index = (1 - non_null_variant_index) as uint; + let null_variant_index = (1 - non_null_variant_index) as usize; let null_variant_name = token::get_name((*self.variants)[null_variant_index].name); let union_member_name = format!("RUST$ENCODED$ENUM${}${}", 0, @@ -2280,7 +2316,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { describe_enum_variant(cx, self.enum_type, struct_def, - &*(*self.variants)[nndiscr as uint], + &*(*self.variants)[nndiscr as usize], OptimizedDiscriminant, self.containing_scope, self.span); @@ -2295,7 +2331,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { // Encode the information about the null variant in the union // member's name. - let null_variant_index = (1 - nndiscr) as uint; + let null_variant_index = (1 - nndiscr) as usize; let null_variant_name = token::get_name((*self.variants)[null_variant_index].name); let discrfield = discrfield.iter() .skip(1) @@ -2346,7 +2382,7 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> { } } -#[derive(Copy)] +#[derive(Copy, Clone)] enum EnumDiscriminantInfo { RegularDiscriminant(DIType), OptimizedDiscriminant, @@ -2370,7 +2406,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .iter() .map(|&t| type_of::type_of(cx, t)) .collect::>() - [], + , struct_def.packed); // Could do some consistency checks here: size, align, field count, discr type @@ -2437,7 +2473,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id); let loc = span_start(cx, definition_span); - let file_metadata = file_metadata(cx, &loc.file.name[]); + let file_metadata = file_metadata(cx, &loc.file.name); let variants = ty::enum_variants(cx.tcx(), enum_def_id); @@ -2624,7 +2660,7 @@ fn set_members_of_composite_type(cx: &CrateContext, Please use a rustc built with anewer \ version of LLVM.", llvm_version_major, - llvm_version_minor)[]); + llvm_version_minor)); } else { cx.sess().bug("debuginfo::set_members_of_composite_type() - \ Already completed forward declaration re-encountered."); @@ -2777,7 +2813,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, MemberDescription { name: "length".to_string(), llvm_type: member_llvm_types[1], - type_metadata: type_metadata(cx, cx.tcx().types.uint, span), + type_metadata: type_metadata(cx, cx.tcx().types.usize, span), offset: ComputedMemberOffset, flags: FLAGS_NONE }, @@ -2786,7 +2822,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, assert!(member_descriptions.len() == member_llvm_types.len()); let loc = span_start(cx, span); - let file_metadata = file_metadata(cx, &loc.file.name[]); + let file_metadata = file_metadata(cx, &loc.file.name); let metadata = composite_type_metadata(cx, slice_llvm_type, @@ -2865,7 +2901,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type); cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {}", - &pp_type_name[..])[]); + &pp_type_name[..])); } }; @@ -2983,7 +3019,7 @@ 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(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { let typer = NormalizingClosureTyper::new(cx.tcx()); let sig = typer.closure_type(def_id, substs).sig; subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span) @@ -3005,7 +3041,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } _ => { cx.sess().bug(&format!("debuginfo: unexpected type in type_metadata: {:?}", - sty)[]) + sty)) } }; @@ -3070,14 +3106,14 @@ impl MetadataCreationResult { } } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum InternalDebugLocation { - KnownLocation { scope: DIScope, line: uint, col: uint }, + KnownLocation { scope: DIScope, line: usize, col: usize }, UnknownLocation } impl InternalDebugLocation { - fn new(scope: DIScope, line: uint, col: uint) -> InternalDebugLocation { + fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation { KnownLocation { scope: scope, line: line, @@ -3171,7 +3207,7 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool { fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_reporting_span: Span) { - if !cx.tcx().node_types.borrow().contains_key(&node_id) { + if !cx.tcx().node_types().contains_key(&node_id) { cx.sess().span_bug(error_reporting_span, "debuginfo: Could not find type for node id!"); } @@ -3248,7 +3284,7 @@ fn create_scope_map(cx: &CrateContext, { // Create a new lexical scope and push it onto the stack let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo); - let file_metadata = file_metadata(cx, &loc.file.name[]); + let file_metadata = file_metadata(cx, &loc.file.name); let parent_scope = scope_stack.last().unwrap().scope_metadata; let scope_metadata = unsafe { @@ -3370,7 +3406,7 @@ fn create_scope_map(cx: &CrateContext, if need_new_scope { // Create a new lexical scope and push it onto the stack let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo); - let file_metadata = file_metadata(cx, &loc.file.name[]); + let file_metadata = file_metadata(cx, &loc.file.name); let parent_scope = scope_stack.last().unwrap().scope_metadata; let scope_metadata = unsafe { @@ -3487,8 +3523,7 @@ fn create_scope_map(cx: &CrateContext, ast::ExprLit(_) | ast::ExprBreak(_) | ast::ExprAgain(_) | - ast::ExprPath(_) | - ast::ExprQPath(_) => {} + ast::ExprPath(..) => {} ast::ExprCast(ref sub_exp, _) | ast::ExprAddrOf(_, ref sub_exp) | @@ -3710,12 +3745,12 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_bool => output.push_str("bool"), ty::ty_char => output.push_str("char"), ty::ty_str => output.push_str("str"), - ty::ty_int(ast::TyIs(_)) => output.push_str("isize"), + ty::ty_int(ast::TyIs) => output.push_str("isize"), ty::ty_int(ast::TyI8) => output.push_str("i8"), ty::ty_int(ast::TyI16) => output.push_str("i16"), ty::ty_int(ast::TyI32) => output.push_str("i32"), ty::ty_int(ast::TyI64) => output.push_str("i64"), - ty::ty_uint(ast::TyUs(_)) => output.push_str("usize"), + ty::ty_uint(ast::TyUs) => output.push_str("usize"), ty::ty_uint(ast::TyU8) => output.push_str("u8"), ty::ty_uint(ast::TyU16) => output.push_str("u16"), ty::ty_uint(ast::TyU32) => output.push_str("u32"), @@ -3828,11 +3863,10 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ty::ty_err | ty::ty_infer(_) | - ty::ty_open(_) | ty::ty_projection(..) | ty::ty_param(_) => { cx.sess().bug(&format!("debuginfo: Trying to create type name for \ - unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]); + unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))); } } @@ -3915,13 +3949,13 @@ impl NamespaceTreeNode { None => {} } let string = token::get_name(node.name); - output.push_str(&format!("{}", string.len())[]); + output.push_str(&format!("{}", string.len())); output.push_str(&string); } let mut name = String::from_str("_ZN"); fill_nested(self, &mut name); - name.push_str(&format!("{}", item_name.len())[]); + name.push_str(&format!("{}", item_name.len())); name.push_str(item_name); name.push('E'); name @@ -3929,7 +3963,7 @@ impl NamespaceTreeNode { } fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str { - &cx.link_meta().crate_name[] + &cx.link_meta().crate_name } fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc { @@ -4005,7 +4039,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc { cx.sess().bug(&format!("debuginfo::namespace_for_item(): \ path too short for {:?}", - def_id)[]); + def_id)); } } }) @@ -4020,7 +4054,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc(bcx: Block<'blk, 'tcx>, return datum.store_to_dest(bcx, dest, expr.id); } - let qualif = bcx.tcx().const_qualif_map.borrow()[expr.id]; + let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap(); if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) { if !qualif.intersects(check_const::PREFER_IN_PLACE) { if let SaveIn(lldest) = dest { @@ -143,10 +144,10 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // it prefers in-place instantiation, likely because it contains // `[x; N]` somewhere within. match expr.node { - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { match bcx.def(expr.id) { def::DefConst(did) => { - let expr = consts::get_const_expr(bcx.ccx(), did, expr); + let const_expr = consts::get_const_expr(bcx.ccx(), did, expr); // Temporarily get cleanup scopes out of the way, // as they require sub-expressions to be contained // inside the current AST scope. @@ -154,7 +155,13 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // can't have destructors. let scopes = mem::replace(&mut *bcx.fcx.scopes.borrow_mut(), vec![]); - bcx = trans_into(bcx, expr, dest); + // Lock emitted debug locations to the location of + // the constant reference expression. + debuginfo::with_source_location_override(bcx.fcx, + expr.debug_loc(), + || { + bcx = trans_into(bcx, const_expr, dest) + }); let scopes = mem::replace(&mut *bcx.fcx.scopes.borrow_mut(), scopes); assert!(scopes.is_empty()); @@ -202,7 +209,7 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let mut bcx = bcx; let fcx = bcx.fcx; - let qualif = bcx.tcx().const_qualif_map.borrow()[expr.id]; + let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap(); let adjusted_global = !qualif.intersects(check_const::NON_STATIC_BORROWS); let global = if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) { let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif, @@ -278,24 +285,46 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef { GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR]) } +pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) { + Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr)); + Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr)); +} + // Retrieve the information we are losing (making dynamic) in an unsizing // adjustment. -// When making a dtor, we need to do different things depending on the -// ownership of the object.. mk_ty is a function for turning `unadjusted_ty` -// into a type to be destructed. If we want to end up with a Box pointer, -// then mk_ty should make a Box pointer (T -> Box), if we want a -// borrowed reference then it should be T -> &T. -pub fn unsized_info<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, - kind: &ty::UnsizeKind<'tcx>, - id: ast::NodeId, - unadjusted_ty: Ty<'tcx>, - param_substs: &'tcx subst::Substs<'tcx>, - mk_ty: F) -> ValueRef where - F: FnOnce(Ty<'tcx>) -> Ty<'tcx>, -{ - // FIXME(#19596) workaround: `|t| t` causes monomorphization recursion - fn identity(t: T) -> T { t } +// +// The `unadjusted_val` argument is a bit funny. It is intended +// for use in an upcast, where the new vtable for an object will +// be drived from the old one. Hence it is a pointer to the fat +// pointer. +pub fn unsized_info_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + kind: &ty::UnsizeKind<'tcx>, + id: ast::NodeId, + unadjusted_ty: Ty<'tcx>, + unadjusted_val: ValueRef, // see above (*) + param_substs: &'tcx subst::Substs<'tcx>) + -> ValueRef { + unsized_info( + bcx.ccx(), + kind, + id, + unadjusted_ty, + param_substs, + || Load(bcx, GEPi(bcx, unadjusted_val, &[0, abi::FAT_PTR_EXTRA]))) +} +// Same as `unsize_info_bcx`, but does not require a bcx -- instead it +// takes an extra closure to compute the upcast vtable. +pub fn unsized_info<'ccx, 'tcx, MK_UPCAST_VTABLE>( + ccx: &CrateContext<'ccx, 'tcx>, + kind: &ty::UnsizeKind<'tcx>, + id: ast::NodeId, + unadjusted_ty: Ty<'tcx>, + param_substs: &'tcx subst::Substs<'tcx>, + mk_upcast_vtable: MK_UPCAST_VTABLE) // see notes above + -> ValueRef + where MK_UPCAST_VTABLE: FnOnce() -> ValueRef +{ debug!("unsized_info(kind={:?}, id={}, unadjusted_ty={})", kind, id, unadjusted_ty.repr(ccx.tcx())); match kind { @@ -303,12 +332,11 @@ pub fn unsized_info<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, &ty::UnsizeStruct(box ref k, tp_index) => match unadjusted_ty.sty { ty::ty_struct(_, ref substs) => { let ty_substs = substs.types.get_slice(subst::TypeSpace); - // The dtor for a field treats it like a value, so mk_ty - // should just be the identity function. - unsized_info(ccx, k, id, ty_substs[tp_index], param_substs, identity) + unsized_info(ccx, k, id, ty_substs[tp_index], param_substs, + mk_upcast_vtable) } _ => ccx.sess().bug(&format!("UnsizeStruct with bad sty: {}", - unadjusted_ty.repr(ccx.tcx()))[]) + unadjusted_ty.repr(ccx.tcx()))) }, &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => { // Note that we preserve binding levels here: @@ -319,10 +347,15 @@ pub fn unsized_info<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, let trait_ref = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &trait_ref); - let box_ty = mk_ty(unadjusted_ty); - consts::ptrcast(meth::get_vtable(ccx, box_ty, trait_ref, param_substs), + consts::ptrcast(meth::get_vtable(ccx, trait_ref, param_substs), Type::vtable_ptr(ccx)) } + &ty::UnsizeUpcast(_) => { + // For now, upcasts are limited to changes in marker + // traits, and hence never actually require an actual + // change to the vtable. + mk_upcast_vtable() + } } } @@ -331,7 +364,8 @@ pub fn unsized_info<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'blk, 'tcx, Expr> +{ let mut bcx = bcx; let mut datum = datum; let adjustment = match bcx.tcx().adjustments.borrow().get(&expr.id).cloned() { @@ -340,15 +374,18 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } Some(adj) => { adj } }; - debug!("unadjusted datum for expr {}: {}, adjustment={}", + debug!("unadjusted datum for expr {}: {} adjustment={:?}", expr.repr(bcx.tcx()), datum.to_string(bcx.ccx()), - adjustment.repr(bcx.tcx())); + adjustment); match adjustment { AdjustReifyFnPointer(_def_id) => { // FIXME(#19925) once fn item types are // zero-sized, we'll need to do something here } + AdjustUnsafeFnPointer => { + // purely a type-level thing + } AdjustDerefRef(ref adj) => { let (autoderefs, use_autoref) = match adj.autoref { // Extracting a value from a box counts as a deref, but if we are @@ -427,7 +464,6 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!(" AutoUnsize"); unpack_datum!(bcx, unsize_expr(bcx, expr, datum, k)) } - &ty::AutoUnsizeUniq(ty::UnsizeLength(len)) => { debug!(" AutoUnsizeUniq(UnsizeLength)"); unpack_datum!(bcx, unsize_unique_vec(bcx, expr, datum, len)) @@ -451,37 +487,41 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let datum_ty = datum.ty; let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span); debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx())); - let dest_ty = ty::mk_open(tcx, unsized_ty); - debug!("dest_ty={}", unsized_ty.repr(bcx.tcx())); - let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs, - |t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t)); + let info = unsized_info_bcx(bcx, k, expr.id, datum_ty, datum.val, bcx.fcx.param_substs); // Arrange cleanup - let lval = unpack_datum!(bcx, - datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id)); + let lval = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id)); + // Compute the base pointer. This doesn't change the pointer value, // but merely its type. - let base = match *k { - ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => { - PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to()) - } - ty::UnsizeLength(..) => { - GEPi(bcx, lval.val, &[0, 0]) - } + let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to(); + let base = if !type_is_sized(bcx.tcx(), lval.ty) { + // Normally, the source is a thin pointer and we are + // adding extra info to make a fat pointer. The exception + // is when we are upcasting an existing object fat pointer + // to use a different vtable. In that case, we want to + // load out the original data pointer so we can repackage + // it. + Load(bcx, get_dataptr(bcx, lval.val)) + } else { + lval.val }; + let base = PointerCast(bcx, base, ptr_ty); - let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr"); - Store(bcx, base, get_dataptr(bcx, scratch.val)); - Store(bcx, info, get_len(bcx, scratch.val)); + let llty = type_of::type_of(bcx.ccx(), unsized_ty); + // HACK(eddyb) get around issues with lifetime intrinsics. + let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr"); + Store(bcx, base, get_dataptr(bcx, scratch)); + Store(bcx, info, get_len(bcx, scratch)); - DatumBlock::new(bcx, scratch.to_expr_datum()) + DatumBlock::new(bcx, Datum::new(scratch, unsized_ty, LvalueExpr)) } fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, - len: uint) + len: usize) -> DatumBlock<'blk, 'tcx, Expr> { let mut bcx = bcx; let tcx = bcx.tcx(); @@ -524,7 +564,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let unboxed_ty = match datum_ty.sty { ty::ty_uniq(t) => t, _ => bcx.sess().bug(&format!("Expected ty_uniq, found {}", - bcx.ty_to_string(datum_ty))[]) + bcx.ty_to_string(datum_ty))) }; let result_ty = ty::mk_uniq(tcx, ty::unsize_ty(tcx, unboxed_ty, k, expr.span)); @@ -539,8 +579,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let base = PointerCast(bcx, get_dataptr(bcx, scratch.val), llbox_ty.ptr_to()); bcx = datum.store_to(bcx, base); - let info = unsized_info(bcx.ccx(), k, expr.id, unboxed_ty, bcx.fcx.param_substs, - |t| ty::mk_uniq(tcx, t)); + let info = unsized_info_bcx(bcx, k, expr.id, unboxed_ty, base, bcx.fcx.param_substs); Store(bcx, info, get_len(bcx, scratch.val)); DatumBlock::new(bcx, scratch.to_expr_datum()) @@ -635,7 +674,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprParen(ref e) => { trans(bcx, &**e) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { trans_def(bcx, expr, bcx.def(expr.id)) } ast::ExprField(ref base, ident) => { @@ -696,7 +735,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.span, &format!("trans_rvalue_datum_unadjusted reached \ fall-through case: {:?}", - expr.node)[]); + expr.node)); } } } @@ -705,13 +744,13 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, base: &ast::Expr, get_idx: F) -> DatumBlock<'blk, 'tcx, Expr> where - F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]) -> uint, + F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]) -> usize, { let mut bcx = bcx; let _icx = push_ctxt("trans_rec_field"); let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field")); - let bare_ty = ty::unopen_type(base_datum.ty); + let bare_ty = base_datum.ty; let repr = adt::represent_type(bcx.ccx(), bare_ty); with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| { let ix = get_idx(bcx.tcx(), field_tys); @@ -723,7 +762,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, if type_is_sized(bcx.tcx(), d.ty) { DatumBlock { datum: d.to_expr_datum(), bcx: bcx } } else { - let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), ""); + let scratch = rvalue_scratch_datum(bcx, d.ty, ""); Store(bcx, d.val, get_dataptr(bcx, scratch.val)); let info = Load(bcx, get_len(bcx, base_datum.val)); Store(bcx, info, get_len(bcx, scratch.val)); @@ -746,7 +785,7 @@ fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Translates `base.`. fn trans_rec_tup_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, base: &ast::Expr, - idx: uint) + idx: usize) -> DatumBlock<'blk, 'tcx, Expr> { trans_field(bcx, base, |_, _| idx) } @@ -804,12 +843,12 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, base_datum, vec![(ix_datum, idx.id)], Some(SaveIn(scratch.val)), - true)); + false)); let datum = scratch.to_expr_datum(); if type_is_sized(bcx.tcx(), elt_ty) { Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr) } else { - Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr) + Datum::new(datum.val, elt_ty, LvalueExpr) } } None => { @@ -837,10 +876,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } }; - let vt = - tvec::vec_types(bcx, - ty::sequence_element_type(bcx.tcx(), - base_datum.ty)); + let unit_ty = ty::sequence_element_type(bcx.tcx(), base_datum.ty); let (base, len) = base_datum.get_vec_base_and_len(bcx); @@ -865,8 +901,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, len) }); let elt = InBoundsGEP(bcx, base, &[ix_val]); - let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to()); - Datum::new(elt, vt.unit_ty, LvalueExpr) + let elt = PointerCast(bcx, elt, type_of::type_of(ccx, unit_ty).ptr_to()); + Datum::new(elt, unit_ty, LvalueExpr) } }; @@ -881,7 +917,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_def_lvalue"); match def { - def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) | + def::DefFn(..) | def::DefMethod(..) | def::DefStruct(_) | def::DefVariant(..) => { let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def, bcx.fcx.param_substs); @@ -980,7 +1016,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let src_datum = unpack_datum!(bcx, trans(bcx, &**src)); let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign")); - if type_needs_drop(bcx.tcx(), dst_datum.ty) { + if bcx.fcx.type_needs_drop(dst_datum.ty) { // If there are destructors involved, make sure we // are copying from an rvalue, since that cannot possible // alias an lvalue. We are concerned about code like: @@ -1020,7 +1056,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.span, &format!("trans_rvalue_stmt_unadjusted reached \ fall-through case: {:?}", - expr.node)[]); + expr.node)); } } } @@ -1039,7 +1075,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprParen(ref e) => { trans_into(bcx, &**e, dest) } - ast::ExprPath(_) | ast::ExprQPath(_) => { + ast::ExprPath(..) => { trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest) } ast::ExprIf(ref cond, ref thn, ref els) => { @@ -1113,7 +1149,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } ast::ExprTup(ref args) => { - let numbered_fields: Vec<(uint, &ast::Expr)> = + let numbered_fields: Vec<(usize, &ast::Expr)> = args.iter().enumerate().map(|(i, arg)| (i, &**arg)).collect(); trans_adt(bcx, expr_ty(bcx, expr), @@ -1191,22 +1227,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base, vec![(idx_datum, idx.id)], Some(dest), true).bcx } - ast::ExprCast(ref val, _) => { - // DPS output mode means this is a trait cast: - if ty::type_is_trait(node_id_type(bcx, expr.id)) { - let trait_ref = - bcx.tcx().object_cast_map.borrow() - .get(&expr.id) - .cloned() - .unwrap(); - let trait_ref = bcx.monomorphize(&trait_ref); - let datum = unpack_datum!(bcx, trans(bcx, &**val)); - meth::trans_trait_cast(bcx, datum, expr.id, - trait_ref, dest) - } else { - bcx.tcx().sess.span_bug(expr.span, - "expr_cast of non-trait"); - } + ast::ExprCast(..) => { + // Trait casts used to come this way, now they should be coercions. + bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)") } ast::ExprAssignOp(op, ref dst, ref src) => { trans_assign_op(bcx, expr, op, &**dst, &**src) @@ -1216,7 +1239,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.span, &format!("trans_rvalue_dps_unadjusted reached fall-through \ case: {:?}", - expr.node)[]); + expr.node)); } } } @@ -1266,7 +1289,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => { bcx.tcx().sess.span_bug(ref_expr.span, &format!( "Non-DPS def {:?} referened by {}", - def, bcx.node_id_to_string(ref_expr.id))[]); + def, bcx.node_id_to_string(ref_expr.id))); } } } @@ -1281,12 +1304,10 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, match def { def::DefFn(did, _) | def::DefStruct(did) | def::DefVariant(_, did, _) | - def::DefStaticMethod(did, def::FromImpl(_)) | - def::DefMethod(did, _, def::FromImpl(_)) => { + def::DefMethod(did, def::FromImpl(_)) => { 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)) => { + def::DefMethod(impl_did, def::FromTrait(trait_did)) => { meth::trans_static_method_callee(ccx, impl_did, trait_did, ref_expr.id, param_substs) @@ -1295,7 +1316,7 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.tcx().sess.span_bug(ref_expr.span, &format!( "trans_def_fn_unadjusted invoked on: {:?} for {}", def, - ref_expr.repr(ccx.tcx()))[]); + ref_expr.repr(ccx.tcx()))); } } } @@ -1315,7 +1336,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, None => { bcx.sess().bug(&format!( "trans_local_var: no llval for upvar {} found", - nid)[]); + nid)); } } } @@ -1325,7 +1346,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, None => { bcx.sess().bug(&format!( "trans_local_var: no datum for local/arg {} found", - nid)[]); + nid)); } }; debug!("take_local(nid={}, v={}, ty={})", @@ -1335,7 +1356,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => { bcx.sess().unimpl(&format!( "unsupported def type in trans_local_var: {:?}", - def)[]); + def)); } } } @@ -1358,7 +1379,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, } ty::ty_tup(ref v) => { - op(0, &tup_fields(&v[..])[]) + op(0, &tup_fields(&v[..])) } ty::ty_enum(_, substs) => { @@ -1368,14 +1389,13 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, tcx.sess.bug(&format!( "cannot get field types from the enum type {} \ without a node ID", - ty.repr(tcx))[]); + ty.repr(tcx))); } Some(node_id) => { - let def = tcx.def_map.borrow()[node_id].clone(); + let def = tcx.def_map.borrow().get(&node_id).unwrap().full_def(); match def { def::DefVariant(enum_id, variant_id, _) => { - let variant_info = ty::enum_variant_with_id( - tcx, enum_id, variant_id); + let variant_info = ty::enum_variant_with_id(tcx, enum_id, variant_id); let fields = struct_fields(tcx, variant_id, substs); let fields = monomorphize::normalize_associated_type(tcx, &fields); op(variant_info.disr_val, &fields[..]) @@ -1392,7 +1412,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, _ => { tcx.sess.bug(&format!( "cannot get field types from the type {}", - ty.repr(tcx))[]); + ty.repr(tcx))); } } } @@ -1465,7 +1485,7 @@ pub struct StructBaseInfo<'a, 'tcx> { /// The base expression; will be evaluated after all explicit fields. expr: &'a ast::Expr, /// The indices of fields to copy paired with their types. - fields: Vec<(uint, Ty<'tcx>)> + fields: Vec<(usize, Ty<'tcx>)> } /// Constructs an ADT instance: @@ -1479,7 +1499,7 @@ pub struct StructBaseInfo<'a, 'tcx> { pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>, discr: ty::Disr, - fields: &[(uint, &ast::Expr)], + fields: &[(usize, &ast::Expr)], optbase: Option>, dest: Dest, debug_location: DebugLoc) @@ -1501,31 +1521,14 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // panic occur before the ADT as a whole is ready. let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); - // First we trans the base, if we have one, to the dest - if let Some(base) = optbase { - assert_eq!(discr, 0); - - match ty::expr_kind(bcx.tcx(), &*base.expr) { - ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => { - bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); - }, - ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), - _ => { - let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base")); - for &(i, t) in &base.fields { - let datum = base_datum.get_element( - bcx, t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i)); - assert!(type_is_sized(bcx.tcx(), datum.ty)); - let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); - bcx = datum.store_to(bcx, dest); - } - } - } - } - - debug_location.apply(bcx.fcx); - if ty::type_is_simd(bcx.tcx(), ty) { + // Issue 23112: The original logic appeared vulnerable to same + // order-of-eval bug. But, SIMD values are tuple-structs; + // i.e. functional record update (FRU) syntax is unavailable. + // + // To be safe, double-check that we did not get here via FRU. + assert!(optbase.is_none()); + // This is the constructor of a SIMD type, such types are // always primitive machine types and so do not have a // destructor or require any clean-up. @@ -1544,8 +1547,45 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, vec_val = InsertElement(bcx, vec_val, value, position); } Store(bcx, vec_val, addr); + } else if let Some(base) = optbase { + // Issue 23112: If there is a base, then order-of-eval + // requires field expressions eval'ed before base expression. + + // First, trans field expressions to temporary scratch values. + let scratch_vals: Vec<_> = fields.iter().map(|&(i, ref e)| { + let datum = unpack_datum!(bcx, trans(bcx, &**e)); + (i, datum) + }).collect(); + + debug_location.apply(bcx.fcx); + + // Second, trans the base to the dest. + assert_eq!(discr, 0); + + match ty::expr_kind(bcx.tcx(), &*base.expr) { + ty::RvalueDpsExpr | ty::RvalueDatumExpr if !bcx.fcx.type_needs_drop(ty) => { + bcx = trans_into(bcx, &*base.expr, SaveIn(addr)); + }, + ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"), + _ => { + let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base")); + for &(i, t) in &base.fields { + let datum = base_datum.get_element( + bcx, t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i)); + assert!(type_is_sized(bcx.tcx(), datum.ty)); + let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); + bcx = datum.store_to(bcx, dest); + } + } + } + + // Finally, move scratch field values into actual field locations + for (i, datum) in scratch_vals.into_iter() { + let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); + bcx = datum.store_to(bcx, dest); + } } else { - // Now, we just overwrite the fields we've explicitly specified + // No base means we can write all fields directly in place. for &(i, ref e) in fields { let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); let e_ty = expr_ty_adjusted(bcx, &**e); @@ -1671,7 +1711,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, lval: Datum<'tcx, Lvalue>) -> DatumBlock<'blk, 'tcx, Expr> { - let dest_ty = ty::close_type(bcx.tcx(), lval.ty); + let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty); let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr"); memcpy_ty(bcx, scratch.val, lval.val, scratch.ty); @@ -1685,16 +1725,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_addr_of"); let mut bcx = bcx; let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of")); - match sub_datum.ty.sty { - ty::ty_open(_) => { - // Opened DST value, close to a fat pointer - ref_fat_ptr(bcx, sub_datum) - } - _ => { - // Sized value, ref to a thin pointer - let ty = expr_ty(bcx, expr); - immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock() - } + if !type_is_sized(bcx.tcx(), sub_datum.ty) { + // DST lvalue, close to a fat pointer + ref_fat_ptr(bcx, sub_datum) + } else { + // Sized value, ref to a thin pointer + let ty = expr_ty(bcx, expr); + immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock() } } @@ -1720,8 +1757,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; let is_float = ty::type_is_fp(intype); let is_signed = ty::type_is_signed(intype); - - let rhs = base::cast_shift_expr_rhs(bcx, op, lhs, rhs); + let info = expr_info(binop_expr); let binop_debug_loc = binop_expr.debug_loc(); @@ -1730,22 +1766,37 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::BiAdd => { if is_float { FAdd(bcx, lhs, rhs, binop_debug_loc) - } else { + } else if is_simd { Add(bcx, lhs, rhs, binop_debug_loc) + } else { + let (newbcx, res) = with_overflow_check( + bcx, OverflowOp::Add, info, lhs_t, lhs, rhs, binop_debug_loc); + bcx = newbcx; + res } } ast::BiSub => { if is_float { FSub(bcx, lhs, rhs, binop_debug_loc) - } else { + } else if is_simd { Sub(bcx, lhs, rhs, binop_debug_loc) + } else { + let (newbcx, res) = with_overflow_check( + bcx, OverflowOp::Sub, info, lhs_t, lhs, rhs, binop_debug_loc); + bcx = newbcx; + res } } ast::BiMul => { if is_float { FMul(bcx, lhs, rhs, binop_debug_loc) - } else { + } else if is_simd { Mul(bcx, lhs, rhs, binop_debug_loc) + } else { + let (newbcx, res) = with_overflow_check( + bcx, OverflowOp::Mul, info, lhs_t, lhs, rhs, binop_debug_loc); + bcx = newbcx; + res } } ast::BiDiv => { @@ -1784,13 +1835,17 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::BiBitOr => Or(bcx, lhs, rhs, binop_debug_loc), ast::BiBitAnd => And(bcx, lhs, rhs, binop_debug_loc), ast::BiBitXor => Xor(bcx, lhs, rhs, binop_debug_loc), - ast::BiShl => Shl(bcx, lhs, rhs, binop_debug_loc), + ast::BiShl => { + let (newbcx, res) = with_overflow_check( + bcx, OverflowOp::Shl, info, lhs_t, lhs, rhs, binop_debug_loc); + bcx = newbcx; + res + } ast::BiShr => { - if is_signed { - AShr(bcx, lhs, rhs, binop_debug_loc) - } else { - LShr(bcx, lhs, rhs, binop_debug_loc) - } + let (newbcx, res) = with_overflow_check( + bcx, OverflowOp::Shr, info, lhs_t, lhs, rhs, binop_debug_loc); + bcx = newbcx; + res } ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => { if is_simd { @@ -1902,7 +1957,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest: Option, autoref: bool) -> Result<'blk, 'tcx> { - let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; + let method_ty = bcx.tcx().method_map.borrow().get(&method_call).unwrap().ty; callee::trans_call_inner(bcx, expr.debug_loc(), monomorphize_type(bcx, method_ty), @@ -1923,10 +1978,12 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, dest: Option) -> Block<'blk, 'tcx> { let method_call = MethodCall::expr(expr.id); - let method_type = (*bcx.tcx() - .method_map - .borrow())[method_call] - .ty; + let method_type = bcx.tcx() + .method_map + .borrow() + .get(&method_call) + .unwrap() + .ty; let mut all_args = vec!(callee); all_args.extend(args.iter().map(|e| &**e)); unpack_result!(bcx, @@ -1981,7 +2038,7 @@ fn float_cast(bcx: Block, } else { llsrc }; } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum cast_kind { cast_pointer, cast_integral, @@ -2027,7 +2084,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let mut bcx = bcx; let ccx = bcx.ccx(); - let t_in = expr_ty(bcx, expr); + let t_in = expr_ty_adjusted(bcx, expr); let t_out = node_id_type(bcx, id); let k_in = cast_type_kind(bcx.tcx(), t_in); let k_out = cast_type_kind(bcx.tcx(), t_out); @@ -2039,7 +2096,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // by-value as appropriate given its type: let mut datum = unpack_datum!(bcx, trans(bcx, expr)); - if cast_is_noop(datum.ty, t_out) { + let datum_ty = monomorphize_type(bcx, datum.ty); + if cast_is_noop(datum_ty, t_out) { datum.ty = t_out; return DatumBlock::new(bcx, datum); } @@ -2097,7 +2155,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t_in.repr(bcx.tcx()), k_in, t_out.repr(bcx.tcx()), - k_out)[]) + k_out)) } } } @@ -2106,7 +2164,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t_in.repr(bcx.tcx()), k_in, t_out.repr(bcx.tcx()), - k_out)[]) + k_out)) }; return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock(); } @@ -2127,7 +2185,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Evaluate LHS (destination), which should be an lvalue let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op")); - assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty)); + assert!(!bcx.fcx.type_needs_drop(dst_datum.ty)); let dst_ty = dst_datum.ty; let dst = load_ty(bcx, dst_datum.val, dst_datum.ty); @@ -2170,7 +2228,7 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, - times: uint) + times: usize) -> DatumBlock<'blk, 'tcx, Expr> { let mut bcx = bcx; let mut datum = datum; @@ -2234,16 +2292,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if type_is_sized(bcx.tcx(), content_ty) { deref_owned_pointer(bcx, expr, datum, content_ty) } else { - // A fat pointer and an opened DST value have the same - // representation just different types. Since there is no - // temporary for `*e` here (because it is unsized), we cannot - // emulate the sized object code path for running drop glue and - // free. Instead, we schedule cleanup for `e`, turning it into - // an lvalue. + // A fat pointer and a DST lvalue have the same representation + // just different types. Since there is no temporary for `*e` + // here (because it is unsized), we cannot emulate the sized + // object code path for running drop glue and free. Instead, + // we schedule cleanup for `e`, turning it into an lvalue. let datum = unpack_datum!( bcx, datum.to_lvalue_datum(bcx, "deref", expr.id)); - let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr); + let datum = Datum::new(datum.val, content_ty, LvalueExpr); DatumBlock::new(bcx, datum) } } @@ -2260,11 +2317,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // owner (or, in the case of *T, by the user). DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr)) } else { - // A fat pointer and an opened DST value have the same representation + // A fat pointer and a DST lvalue have the same representation // just different types. - DatumBlock::new(bcx, Datum::new(datum.val, - ty::mk_open(bcx.tcx(), content_ty), - LvalueExpr)) + DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr)) } } @@ -2272,7 +2327,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.tcx().sess.span_bug( expr.span, &format!("deref invoked on expr of illegal type {}", - datum.ty.repr(bcx.tcx()))[]); + datum.ty.repr(bcx.tcx()))); } }; @@ -2328,3 +2383,247 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock { bcx: bcx, datum: datum } } } + +#[derive(Debug)] +enum OverflowOp { + Add, + Sub, + Mul, + Shl, + Shr, +} + +impl OverflowOp { + fn codegen_strategy(&self) -> OverflowCodegen { + use self::OverflowCodegen::{ViaIntrinsic, ViaInputCheck}; + match *self { + OverflowOp::Add => ViaIntrinsic(OverflowOpViaIntrinsic::Add), + OverflowOp::Sub => ViaIntrinsic(OverflowOpViaIntrinsic::Sub), + OverflowOp::Mul => ViaIntrinsic(OverflowOpViaIntrinsic::Mul), + + OverflowOp::Shl => ViaInputCheck(OverflowOpViaInputCheck::Shl), + OverflowOp::Shr => ViaInputCheck(OverflowOpViaInputCheck::Shr), + } + } +} + +enum OverflowCodegen { + ViaIntrinsic(OverflowOpViaIntrinsic), + ViaInputCheck(OverflowOpViaInputCheck), +} + +enum OverflowOpViaInputCheck { Shl, Shr, } + +#[derive(Debug)] +enum OverflowOpViaIntrinsic { Add, Sub, Mul, } + +impl OverflowOpViaIntrinsic { + fn to_intrinsic<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, lhs_ty: Ty) -> ValueRef { + let name = self.to_intrinsic_name(bcx.tcx(), lhs_ty); + bcx.ccx().get_intrinsic(&name) + } + fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str { + use syntax::ast::IntTy::*; + use syntax::ast::UintTy::*; + use middle::ty::{ty_int, ty_uint}; + + let new_sty = match ty.sty { + ty_int(TyIs) => match &tcx.sess.target.target.target_pointer_width[..] { + "32" => ty_int(TyI32), + "64" => ty_int(TyI64), + _ => panic!("unsupported target word size") + }, + ty_uint(TyUs) => match &tcx.sess.target.target.target_pointer_width[..] { + "32" => ty_uint(TyU32), + "64" => ty_uint(TyU64), + _ => panic!("unsupported target word size") + }, + ref t @ ty_uint(_) | ref t @ ty_int(_) => t.clone(), + _ => panic!("tried to get overflow intrinsic for {:?} applied to non-int type", + *self) + }; + + match *self { + OverflowOpViaIntrinsic::Add => match new_sty { + ty_int(TyI8) => "llvm.sadd.with.overflow.i8", + ty_int(TyI16) => "llvm.sadd.with.overflow.i16", + ty_int(TyI32) => "llvm.sadd.with.overflow.i32", + ty_int(TyI64) => "llvm.sadd.with.overflow.i64", + + ty_uint(TyU8) => "llvm.uadd.with.overflow.i8", + ty_uint(TyU16) => "llvm.uadd.with.overflow.i16", + ty_uint(TyU32) => "llvm.uadd.with.overflow.i32", + ty_uint(TyU64) => "llvm.uadd.with.overflow.i64", + + _ => unreachable!(), + }, + OverflowOpViaIntrinsic::Sub => match new_sty { + ty_int(TyI8) => "llvm.ssub.with.overflow.i8", + ty_int(TyI16) => "llvm.ssub.with.overflow.i16", + ty_int(TyI32) => "llvm.ssub.with.overflow.i32", + ty_int(TyI64) => "llvm.ssub.with.overflow.i64", + + ty_uint(TyU8) => "llvm.usub.with.overflow.i8", + ty_uint(TyU16) => "llvm.usub.with.overflow.i16", + ty_uint(TyU32) => "llvm.usub.with.overflow.i32", + ty_uint(TyU64) => "llvm.usub.with.overflow.i64", + + _ => unreachable!(), + }, + OverflowOpViaIntrinsic::Mul => match new_sty { + ty_int(TyI8) => "llvm.smul.with.overflow.i8", + ty_int(TyI16) => "llvm.smul.with.overflow.i16", + ty_int(TyI32) => "llvm.smul.with.overflow.i32", + ty_int(TyI64) => "llvm.smul.with.overflow.i64", + + ty_uint(TyU8) => "llvm.umul.with.overflow.i8", + ty_uint(TyU16) => "llvm.umul.with.overflow.i16", + ty_uint(TyU32) => "llvm.umul.with.overflow.i32", + ty_uint(TyU64) => "llvm.umul.with.overflow.i64", + + _ => unreachable!(), + }, + } + } + + fn build_intrinsic_call<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, + info: NodeIdAndSpan, + lhs_t: Ty<'tcx>, lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) + -> (Block<'blk, 'tcx>, ValueRef) { + let llfn = self.to_intrinsic(bcx, lhs_t); + + let val = Call(bcx, llfn, &[lhs, rhs], None, binop_debug_loc); + let result = ExtractValue(bcx, val, 0); // iN operation result + let overflow = ExtractValue(bcx, val, 1); // i1 "did it overflow?" + + let cond = ICmp(bcx, llvm::IntEQ, overflow, C_integral(Type::i1(bcx.ccx()), 1, false), + binop_debug_loc); + + let expect = bcx.ccx().get_intrinsic(&"llvm.expect.i1"); + Call(bcx, expect, &[cond, C_integral(Type::i1(bcx.ccx()), 0, false)], + None, binop_debug_loc); + + let bcx = + base::with_cond(bcx, cond, |bcx| + controlflow::trans_fail(bcx, info, + InternedString::new("arithmetic operation overflowed"))); + + (bcx, result) + } +} + +impl OverflowOpViaInputCheck { + fn build_with_input_check<'blk, 'tcx>(&self, + bcx: Block<'blk, 'tcx>, + info: NodeIdAndSpan, + lhs_t: Ty<'tcx>, + lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) + -> (Block<'blk, 'tcx>, ValueRef) + { + let lhs_llty = val_ty(lhs); + let rhs_llty = val_ty(rhs); + + // Panic if any bits are set outside of bits that we always + // mask in. + // + // Note that the mask's value is derived from the LHS type + // (since that is where the 32/64 distinction is relevant) but + // the mask's type must match the RHS type (since they will + // both be fed into a and-binop) + let invert_mask = !shift_mask_val(lhs_llty); + let invert_mask = C_integral(rhs_llty, invert_mask, true); + + let outer_bits = And(bcx, rhs, invert_mask, binop_debug_loc); + let cond = ICmp(bcx, llvm::IntNE, outer_bits, + C_integral(rhs_llty, 0, false), binop_debug_loc); + let result = match *self { + OverflowOpViaInputCheck::Shl => + build_unchecked_lshift(bcx, lhs, rhs, binop_debug_loc), + OverflowOpViaInputCheck::Shr => + build_unchecked_rshift(bcx, lhs_t, lhs, rhs, binop_debug_loc), + }; + let bcx = + base::with_cond(bcx, cond, |bcx| + controlflow::trans_fail(bcx, info, + InternedString::new("shift operation overflowed"))); + + (bcx, result) + } +} + +fn shift_mask_val(llty: Type) -> u64 { + // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc. + llty.int_width() - 1 +} + +// To avoid UB from LLVM, these two functions mask RHS with an +// appropriate mask unconditionally (i.e. the fallback behavior for +// all shifts). For 32- and 64-bit types, this matches the semantics +// of Java. (See related discussion on #1877 and #10183.) + +fn build_unchecked_lshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) -> ValueRef { + let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShl, lhs, rhs); + // #1877, #10183: Ensure that input is always valid + let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc); + Shl(bcx, lhs, rhs, binop_debug_loc) +} + +fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + lhs_t: Ty<'tcx>, + lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) -> ValueRef { + let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShr, lhs, rhs); + // #1877, #10183: Ensure that input is always valid + let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc); + let is_signed = ty::type_is_signed(lhs_t); + if is_signed { + AShr(bcx, lhs, rhs, binop_debug_loc) + } else { + LShr(bcx, lhs, rhs, binop_debug_loc) + } +} + +fn shift_mask_rhs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + rhs: ValueRef, + debug_loc: DebugLoc) -> ValueRef { + let rhs_llty = val_ty(rhs); + let mask = shift_mask_val(rhs_llty); + And(bcx, rhs, C_integral(rhs_llty, mask, false), debug_loc) +} + +fn with_overflow_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, oop: OverflowOp, info: NodeIdAndSpan, + lhs_t: Ty<'tcx>, lhs: ValueRef, + rhs: ValueRef, + binop_debug_loc: DebugLoc) + -> (Block<'blk, 'tcx>, ValueRef) { + if bcx.unreachable.get() { return (bcx, _Undef(lhs)); } + if bcx.ccx().check_overflow() { + + match oop.codegen_strategy() { + OverflowCodegen::ViaIntrinsic(oop) => + oop.build_intrinsic_call(bcx, info, lhs_t, lhs, rhs, binop_debug_loc), + OverflowCodegen::ViaInputCheck(oop) => + oop.build_with_input_check(bcx, info, lhs_t, lhs, rhs, binop_debug_loc), + } + } else { + let res = match oop { + OverflowOp::Add => Add(bcx, lhs, rhs, binop_debug_loc), + OverflowOp::Sub => Sub(bcx, lhs, rhs, binop_debug_loc), + OverflowOp::Mul => Mul(bcx, lhs, rhs, binop_debug_loc), + + OverflowOp::Shl => + build_unchecked_lshift(bcx, lhs, rhs, binop_debug_loc), + OverflowOp::Shr => + build_unchecked_rshift(bcx, lhs_t, lhs, rhs, binop_debug_loc), + }; + (bcx, res) + } +} diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 4508fe21a6..e87a5865df 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -9,7 +9,7 @@ // except according to those terms. -use back::{link}; +use back::link; use llvm::{ValueRef, CallConv, get_param}; use llvm; use middle::weak_lang_items; @@ -35,7 +35,7 @@ use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System}; use syntax::codemap::Span; use syntax::parse::token::{InternedString, special_idents}; use syntax::parse::token; -use syntax::{ast}; +use syntax::ast; use syntax::{attr, ast_map}; use syntax::print::pprust; use util::ppaux::Repr; @@ -111,7 +111,7 @@ pub fn register_static(ccx: &CrateContext, let llty = type_of::type_of(ccx, ty); let ident = link_name(foreign_item); - match attr::first_attr_value_str_by_name(&foreign_item.attrs[], + match attr::first_attr_value_str_by_name(&foreign_item.attrs, "linkage") { // If this is a static with a linkage specified, then we need to handle // it a little specially. The typesystem prevents things like &T and @@ -240,11 +240,11 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig); let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]); let fn_type = cabi::compute_abi_info(ccx, - &llsig.llarg_tys[], + &llsig.llarg_tys, llsig.llret_ty, llsig.ret_def); - let arg_tys: &[cabi::ArgType] = &fn_type.arg_tys[]; + let arg_tys: &[cabi::ArgType] = &fn_type.arg_tys; let mut llargs_foreign = Vec::new(); @@ -439,8 +439,8 @@ fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) { tcx.sess.span_err(ast_ty.span, &format!("use of SIMD type `{}` in FFI is highly experimental and \ may result in invalid code", - pprust::ty_to_string(ast_ty))[]); - tcx.sess.span_help(ast_ty.span, + pprust::ty_to_string(ast_ty))); + tcx.sess.fileline_help(ast_ty.span, "add #![feature(simd_ffi)] to the crate attributes to enable"); } }; @@ -470,8 +470,8 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) { "foreign fn's sty isn't a bare_fn_ty?") } - register_foreign_item_fn(ccx, abi, ty, - &lname); + let llfn = register_foreign_item_fn(ccx, abi, ty, &lname); + base::set_llvm_fn_attrs(ccx, &foreign_item.attrs, llfn); // Unlike for other items, we shouldn't call // `base::update_linkage` here. Foreign items have // special linkage requirements, which are handled @@ -603,7 +603,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ccx.sess().bug(&format!("build_rust_fn: extern fn {} has ty {}, \ expected a bare fn ty", ccx.tcx().map.path_to_string(id), - t.repr(tcx))[]); + t.repr(tcx))); } }; @@ -868,9 +868,9 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // the massive simplifications that have occurred. pub fn link_name(i: &ast::ForeignItem) -> InternedString { - match attr::first_attr_value_str_by_name(&i.attrs[], "link_name") { + match attr::first_attr_value_str_by_name(&i.attrs, "link_name") { Some(ln) => ln.clone(), - None => match weak_lang_items::link_name(&i.attrs[]) { + None => match weak_lang_items::link_name(&i.attrs) { Some(name) => name, None => token::get_ident(i.ident), } @@ -913,7 +913,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig); let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs); let fn_ty = cabi::compute_abi_info(ccx, - &llsig.llarg_tys[], + &llsig.llarg_tys, llsig.llret_ty, llsig.ret_def); debug!("foreign_types_for_fn_ty(\ @@ -922,7 +922,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty={} -> {}, \ ret_def={}", ty.repr(ccx.tcx()), - ccx.tn().types_to_str(&llsig.llarg_tys[]), + ccx.tn().types_to_str(&llsig.llarg_tys), ccx.tn().type_to_string(llsig.llret_ty), ccx.tn().types_to_str(&fn_ty.arg_tys.iter().map(|t| t.ty).collect::>()), ccx.tn().type_to_string(fn_ty.ret_ty.ty), diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 268b65c6ce..32b4d14177 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -10,29 +10,28 @@ //! // -// Code relating to taking, dropping, etc as well as type descriptors. +// Code relating to drop glue. use back::abi; use back::link::*; -use llvm::{ValueRef, True, get_param}; +use llvm::{ValueRef, get_param}; use llvm; use middle::lang_items::ExchangeFreeFnLangItem; use middle::subst; use middle::subst::{Subst, Substs}; use trans::adt; +use trans::adt::GetDtorType; // for tcx.dtor_type() use trans::base::*; use trans::build::*; use trans::callee; use trans::cleanup; use trans::cleanup::CleanupMethods; -use trans::consts; use trans::common::*; use trans::datum; use trans::debuginfo::DebugLoc; use trans::expr; use trans::machine::*; -use trans::tvec; use trans::type_::Type; use trans::type_of::{type_of, sizing_type_of, align_of}; use middle::ty::{self, Ty}; @@ -41,9 +40,7 @@ use util::ppaux; use arena::TypedArena; use libc::c_uint; -use std::ffi::CString; use syntax::ast; -use syntax::parse::token; pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, @@ -99,6 +96,16 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, if !type_is_sized(tcx, t) { return t } + + // FIXME (#22815): note that type_needs_drop conservatively + // approximates in some cases and may say a type expression + // requires drop glue when it actually does not. + // + // (In this case it is not clear whether any harm is done, i.e. + // erroneously returning `t` in some cases where we could have + // returned `tcx.types.i8` does not appear unsound. The impact on + // code quality is unknown at this time.) + if !type_needs_drop(tcx, t) { return tcx.types.i8; } @@ -125,7 +132,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // NB: v is an *alias* of type t here, not a direct value. debug!("drop_ty(t={})", t.repr(bcx.tcx())); let _icx = push_ctxt("drop_ty"); - if type_needs_drop(bcx.tcx(), t) { + if bcx.fcx.type_needs_drop(t) { let ccx = bcx.ccx(); let glue = get_drop_glue(ccx, t); let glue_type = get_drop_glue_type(ccx, t); @@ -168,31 +175,46 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val let llfnty = Type::glue_fn(ccx, llty); - let (glue, new_sym) = match ccx.available_drop_glues().borrow().get(&t) { - Some(old_sym) => { - let glue = decl_cdecl_fn(ccx, &old_sym[..], llfnty, ty::mk_nil(ccx.tcx())); - (glue, None) - }, - None => { - let (sym, glue) = declare_generic_glue(ccx, t, llfnty, "drop"); - (glue, Some(sym)) - }, + // To avoid infinite recursion, don't `make_drop_glue` until after we've + // added the entry to the `drop_glues` cache. + if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&t) { + let llfn = decl_cdecl_fn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx())); + ccx.drop_glues().borrow_mut().insert(t, llfn); + return llfn; }; - ccx.drop_glues().borrow_mut().insert(t, glue); + let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, "drop"); + let llfn = decl_cdecl_fn(ccx, &fn_nm, llfnty, ty::mk_nil(ccx.tcx())); + note_unique_llvm_symbol(ccx, fn_nm.clone()); + ccx.available_drop_glues().borrow_mut().insert(t, fn_nm); - // To avoid infinite recursion, don't `make_drop_glue` until after we've - // added the entry to the `drop_glues` cache. - match new_sym { - Some(sym) => { - ccx.available_drop_glues().borrow_mut().insert(t, sym); - // We're creating a new drop glue, so also generate a body. - make_generic_glue(ccx, t, glue, make_drop_glue, "drop"); - }, - None => {}, - } + let _s = StatRecorder::new(ccx, format!("drop {}", ty_to_short_str(ccx.tcx(), t))); - glue + let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty()); + let (arena, fcx): (TypedArena<_>, FunctionContext); + arena = TypedArena::new(); + fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, + ty::FnConverging(ty::mk_nil(ccx.tcx())), + empty_substs, None, &arena); + + let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx()))); + + update_linkage(ccx, llfn, None, OriginalTranslation); + + ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1); + // All glue functions take values passed *by alias*; this is a + // requirement since in many contexts glue is invoked indirectly and + // the caller has no idea if it's dealing with something that can be + // passed by value. + // + // llfn is expected be declared to take a parameter of the appropriate + // type, so we don't need to explicitly cast the function parameter. + + let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint); + let bcx = make_drop_glue(bcx, llrawptr0, t); + finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None); + + llfn } fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, @@ -210,9 +232,31 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Load(bcx, llval) }; let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, struct_data)); - with_cond(bcx, load_ty(bcx, drop_flag.val, bcx.tcx().types.bool), |cx| { + let loaded = load_ty(bcx, drop_flag.val, bcx.tcx().dtor_type()); + let drop_flag_llty = type_of(bcx.fcx.ccx, bcx.tcx().dtor_type()); + let init_val = C_integral(drop_flag_llty, adt::DTOR_NEEDED as u64, false); + + let bcx = if !bcx.ccx().check_drop_flag_for_sanity() { + bcx + } else { + let drop_flag_llty = type_of(bcx.fcx.ccx, bcx.tcx().dtor_type()); + let done_val = C_integral(drop_flag_llty, adt::DTOR_DONE as u64, false); + let not_init = ICmp(bcx, llvm::IntNE, loaded, init_val, DebugLoc::None); + let not_done = ICmp(bcx, llvm::IntNE, loaded, done_val, DebugLoc::None); + let drop_flag_neither_initialized_nor_cleared = + And(bcx, not_init, not_done, DebugLoc::None); + with_cond(bcx, drop_flag_neither_initialized_nor_cleared, |cx| { + let llfn = cx.ccx().get_intrinsic(&("llvm.debugtrap")); + Call(cx, llfn, &[], None, DebugLoc::None); + cx + }) + }; + + let drop_flag_dtor_needed = ICmp(bcx, llvm::IntEQ, loaded, init_val, DebugLoc::None); + with_cond(bcx, drop_flag_dtor_needed, |cx| { trans_struct_drop(cx, t, v0, dtor_did, class_did, substs) }) + } fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, @@ -243,7 +287,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, sig.inputs[0] } _ => bcx.sess().bug(&format!("Expected function type, found {}", - bcx.ty_to_string(fty))[]) + bcx.ty_to_string(fty))) }; let (struct_data, info) = if type_is_sized(bcx.tcx(), t) { @@ -265,8 +309,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, assert_eq!(params.len(), 1); let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) { // The dtor expects a fat pointer, so make one, even if we have to fake it. - let boxed_ty = ty::mk_open(bcx.tcx(), t); - let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self"); + let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self"); Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR])); Store(bcx, // If we just had a thin pointer, make a fat pointer by sticking @@ -284,20 +327,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Add all the fields as a value which needs to be cleaned at the end of // this scope. Iterate in reverse order so a Drop impl doesn't reverse // the order in which fields get dropped. - for (i, ty) in st.fields.iter().enumerate().rev() { + for (i, &ty) in st.fields.iter().enumerate().rev() { let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false); - let val = if type_is_sized(bcx.tcx(), *ty) { + let val = if type_is_sized(bcx.tcx(), ty) { llfld_a } else { - let boxed_ty = ty::mk_open(bcx.tcx(), *ty); - let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field"); + let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field"); Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR])); Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA])); scratch.val }; - variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), - val, *ty); + variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty); } let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), @@ -306,8 +347,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::mk_nil(bcx.tcx())); let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[..], dtor_ty, DebugLoc::None); - variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope); - variant_cx + variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope) }) } @@ -370,7 +410,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: C_uint(bcx.ccx(), unit_align)) } _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}", - bcx.ty_to_string(t))[]) + bcx.ty_to_string(t))) } } @@ -378,53 +418,49 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) -> Block<'blk, 'tcx> { // NB: v0 is an *alias* of type t here, not a direct value. let _icx = push_ctxt("make_drop_glue"); + + // Only drop the value when it ... well, we used to check for + // non-null, (and maybe we need to continue doing so), but we now + // must definitely check for special bit-patterns corresponding to + // the special dtor markings. + + let inttype = Type::int(bcx.ccx()); + let dropped_pattern = C_integral(inttype, adt::dtor_done_usize(bcx.fcx.ccx) as u64, false); + match t.sty { ty::ty_uniq(content_ty) => { - match content_ty.sty { - ty::ty_vec(ty, None) => { - tvec::make_drop_glue_unboxed(bcx, v0, ty, true) - } - ty::ty_str => { - let unit_ty = ty::sequence_element_type(bcx.tcx(), content_ty); - tvec::make_drop_glue_unboxed(bcx, v0, unit_ty, true) - } - ty::ty_trait(..) => { - let lluniquevalue = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); - // Only drop the value when it is non-null - let concrete_ptr = Load(bcx, lluniquevalue); - with_cond(bcx, IsNotNull(bcx, concrete_ptr), |bcx| { - let dtor_ptr = Load(bcx, GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA])); - let dtor = Load(bcx, dtor_ptr); - Call(bcx, - dtor, - &[PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))], - None, - DebugLoc::None); - bcx - }) - } - ty::ty_struct(..) if !type_is_sized(bcx.tcx(), content_ty) => { - let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); - let llbox = Load(bcx, llval); - let not_null = IsNotNull(bcx, llbox); - with_cond(bcx, not_null, |bcx| { - let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None); - let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]); - let info = Load(bcx, info); - let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); + if !type_is_sized(bcx.tcx(), content_ty) { + let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); + let llbox = Load(bcx, llval); + let llbox_as_usize = PtrToInt(bcx, llbox, Type::int(bcx.ccx())); + let drop_flag_not_dropped_already = + ICmp(bcx, llvm::IntNE, llbox_as_usize, dropped_pattern, DebugLoc::None); + with_cond(bcx, drop_flag_not_dropped_already, |bcx| { + let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None); + let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]); + let info = Load(bcx, info); + let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); + + // `Box` does not allocate. + let needs_free = ICmp(bcx, + llvm::IntNE, + llsize, + C_uint(bcx.ccx(), 0u64), + DebugLoc::None); + with_cond(bcx, needs_free, |bcx| { trans_exchange_free_dyn(bcx, llbox, llsize, llalign, DebugLoc::None) }) - } - _ => { - assert!(type_is_sized(bcx.tcx(), content_ty)); - let llval = v0; - let llbox = Load(bcx, llval); - let not_null = IsNotNull(bcx, llbox); - with_cond(bcx, not_null, |bcx| { - let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None); - trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None) - }) - } + }) + } else { + let llval = v0; + let llbox = Load(bcx, llval); + let llbox_as_usize = PtrToInt(bcx, llbox, inttype); + let drop_flag_not_dropped_already = + ICmp(bcx, llvm::IntNE, llbox_as_usize, dropped_pattern, DebugLoc::None); + with_cond(bcx, drop_flag_not_dropped_already, |bcx| { + let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None); + trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None) + }) } } ty::ty_struct(did, substs) | ty::ty_enum(did, substs) => { @@ -443,7 +479,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) bcx.sess().warn(&format!("Ignoring drop flag in destructor for {}\ because the struct is unsized. See issue\ #16758", - bcx.ty_to_string(t))[]); + bcx.ty_to_string(t))); trans_struct_drop(bcx, t, v0, dtor, did, substs) } } @@ -456,34 +492,19 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) } } } - ty::ty_closure(..) => { - iter_structural_ty(bcx, - v0, - t, - |bb, vv, tt| drop_ty(bb, vv, tt, DebugLoc::None)) - } ty::ty_trait(..) => { - // No need to do a null check here (as opposed to the Box { - let unit_ty = ty::sequence_element_type(bcx.tcx(), t); - tvec::make_drop_glue_unboxed(bcx, v0, unit_ty, false) - }, + } _ => { - assert!(type_is_sized(bcx.tcx(), t)); - if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { + if bcx.fcx.type_needs_drop(t) { iter_structural_ty(bcx, v0, t, @@ -494,121 +515,3 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) } } } - -// Generates the declaration for (but doesn't emit) a type descriptor. -pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) - -> tydesc_info<'tcx> { - // If emit_tydescs already ran, then we shouldn't be creating any new - // tydescs. - assert!(!ccx.finished_tydescs().get()); - - let llty = type_of(ccx, t); - - if ccx.sess().count_type_sizes() { - println!("{}\t{}", llsize_of_real(ccx, llty), - ppaux::ty_to_string(ccx.tcx(), t)); - } - - let llsize = llsize_of(ccx, llty); - 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 buf = CString::new(name.clone()).unwrap(); - 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( - &ppaux::ty_to_string(ccx.tcx(), t)[]); - let ty_name = C_str_slice(ccx, ty_name); - - debug!("--- declare_tydesc {}", ppaux::ty_to_string(ccx.tcx(), t)); - tydesc_info { - ty: t, - tydesc: gvar, - size: llsize, - align: llalign, - name: ty_name, - } -} - -fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, - llfnty: Type, name: &str) -> (String, ValueRef) { - let _icx = push_ctxt("declare_generic_glue"); - let fn_nm = mangle_internal_name_by_type_and_seq( - ccx, - t, - &format!("glue_{}", name)[]); - let llfn = decl_cdecl_fn(ccx, &fn_nm[..], llfnty, ty::mk_nil(ccx.tcx())); - note_unique_llvm_symbol(ccx, fn_nm.clone()); - return (fn_nm, llfn); -} - -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); - - let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty()); - let (arena, fcx): (TypedArena<_>, FunctionContext); - arena = TypedArena::new(); - fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, - ty::FnConverging(ty::mk_nil(ccx.tcx())), - empty_substs, None, &arena); - - let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx()))); - - update_linkage(ccx, llfn, None, OriginalTranslation); - - ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1); - // All glue functions take values passed *by alias*; this is a - // requirement since in many contexts glue is invoked indirectly and - // the caller has no idea if it's dealing with something that can be - // passed by value. - // - // llfn is expected be declared to take a parameter of the appropriate - // type, so we don't need to explicitly cast the function parameter. - - let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint); - let bcx = helper(bcx, llrawptr0, t); - finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None); - - llfn -} - -pub fn emit_tydescs(ccx: &CrateContext) { - let _icx = push_ctxt("emit_tydescs"); - // As of this point, allow no more tydescs to be created. - ccx.finished_tydescs().set(true); - let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to(); - for (_, ti) in &*ccx.tydescs().borrow() { - // Each of the glue functions needs to be cast to a generic type - // 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 = 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(), - &[ti.size, // size - ti.align, // align - drop_glue, // drop_glue - ti.name]); // name - - unsafe { - let gvar = ti.tydesc; - llvm::LLVMSetInitializer(gvar, tydesc); - llvm::LLVMSetGlobalConstant(gvar, True); - llvm::SetLinkage(gvar, llvm::InternalLinkage); - } - }; -} diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs index 56fda20e0e..2034c6223c 100644 --- a/src/librustc_trans/trans/inline.rs +++ b/src/librustc_trans/trans/inline.rs @@ -17,7 +17,7 @@ use trans::common::*; use middle::ty; use syntax::ast; -use syntax::ast_util::{local_def, PostExpansionMethod}; +use syntax::ast_util::local_def; fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) -> Option { @@ -40,9 +40,9 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) let csearch_result = csearch::maybe_get_item_ast( ccx.tcx(), fn_id, - box |a,b,c,d| astencode::decode_inlined_item(a, b, c, d)); + Box::new(|a,b,c,d| astencode::decode_inlined_item(a, b, c, d))); - let inline_def = match csearch_result { + let inline_id = match csearch_result { csearch::FoundAst::NotFound => { ccx.external().borrow_mut().insert(fn_id, None); return None; @@ -88,12 +88,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) None => {} } - local_def(item.id) + item.id } csearch::FoundAst::Found(&ast::IIForeign(ref item)) => { ccx.external().borrow_mut().insert(fn_id, Some(item.id)); ccx.external_srcs().borrow_mut().insert(item.id, fn_id); - local_def(item.id) + item.id } csearch::FoundAst::FoundParent(parent_id, &ast::IIItem(ref item)) => { ccx.external().borrow_mut().insert(parent_id, Some(item.id)); @@ -122,67 +122,53 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) non-enum, non-struct parent") } trans_item(ccx, &**item); - local_def(my_id) + my_id } csearch::FoundAst::FoundParent(_, _) => { ccx.sess().bug("maybe_get_item_ast returned a FoundParent \ with a non-item parent"); } csearch::FoundAst::Found(&ast::IITraitItem(_, ref trait_item)) => { - match *trait_item { - ast::RequiredMethod(_) => ccx.sess().bug("found RequiredMethod IITraitItem"), - ast::ProvidedMethod(ref mth) => { - ccx.external().borrow_mut().insert(fn_id, Some(mth.id)); - ccx.external_srcs().borrow_mut().insert(mth.id, fn_id); - - ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1); - - // If this is a default method, we can't look up the - // impl type. But we aren't going to translate anyways, so - // don't. - local_def(mth.id) - } - ast::TypeTraitItem(_) => { - ccx.sess().bug("found TypeTraitItem IITraitItem") - } - } + ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id)); + ccx.external_srcs().borrow_mut().insert(trait_item.id, fn_id); + + ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1); + + // If this is a default method, we can't look up the + // impl type. But we aren't going to translate anyways, so + // don't. + trait_item.id } csearch::FoundAst::Found(&ast::IIImplItem(impl_did, ref impl_item)) => { - match *impl_item { - ast::MethodImplItem(ref mth) => { - ccx.external().borrow_mut().insert(fn_id, Some(mth.id)); - ccx.external_srcs().borrow_mut().insert(mth.id, fn_id); + ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id)); + ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id); - ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1); - - let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did); - let unparameterized = impl_tpt.generics.types.is_empty() && - mth.pe_generics().ty_params.is_empty(); + ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1); + // Translate monomorphic impl methods immediately. + if let ast::MethodImplItem(ref sig, ref body) = impl_item.node { + let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did); + if impl_tpt.generics.types.is_empty() && + sig.generics.ty_params.is_empty() { let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty()); - if unparameterized { - let llfn = get_item_val(ccx, mth.id); - trans_fn(ccx, - &*mth.pe_fn_decl(), - &*mth.pe_body(), - llfn, - empty_substs, - mth.id, - &[]); - // Use InternalLinkage so LLVM can optimize more - // aggressively. - SetLinkage(llfn, InternalLinkage); - } - local_def(mth.id) - } - ast::TypeImplItem(_) => { - ccx.sess().bug("found TypeImplItem IIImplItem") + let llfn = get_item_val(ccx, impl_item.id); + trans_fn(ccx, + &sig.decl, + body, + llfn, + empty_substs, + impl_item.id, + &[]); + // Use InternalLinkage so LLVM can optimize more aggressively. + SetLinkage(llfn, InternalLinkage); } } + + impl_item.id } }; - return Some(inline_def); + Some(local_def(inline_id)) } pub fn get_local_instance(ccx: &CrateContext, fn_id: ast::DefId) diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index a1b66ed94f..62a6ede4c2 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -36,7 +36,7 @@ use syntax::parse::token; use util::ppaux::{Repr, ty_to_string}; pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option { - let name = match &token::get_ident(item.ident)[] { + let name = match &token::get_ident(item.ident)[..] { "sqrtf32" => "llvm.sqrt.f32", "sqrtf64" => "llvm.sqrt.f64", "powif32" => "llvm.powi.f32", @@ -121,10 +121,10 @@ pub fn check_intrinsics(ccx: &CrateContext) { &format!("transmute called on types with potentially different sizes: \ {} (could be {} bit{}) to {} (could be {} bit{})", ty_to_string(ccx.tcx(), transmute_restriction.original_from), - from_type_size as uint, + from_type_size as usize, if from_type_size == 1 {""} else {"s"}, ty_to_string(ccx.tcx(), transmute_restriction.original_to), - to_type_size as uint, + to_type_size as usize, if to_type_size == 1 {""} else {"s"})); } else { ccx.sess().span_err( @@ -132,10 +132,10 @@ pub fn check_intrinsics(ccx: &CrateContext) { &format!("transmute called on types with different sizes: \ {} ({} bit{}) to {} ({} bit{})", ty_to_string(ccx.tcx(), transmute_restriction.original_from), - from_type_size as uint, + from_type_size as usize, if from_type_size == 1 {""} else {"s"}, ty_to_string(ccx.tcx(), transmute_restriction.original_to), - to_type_size as uint, + to_type_size as usize, if to_type_size == 1 {""} else {"s"})); } } @@ -156,6 +156,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let ccx = fcx.ccx; let tcx = bcx.tcx(); + let _icx = push_ctxt("trans_intrinsic_call"); + let ret_ty = match callee_ty.sty { ty::ty_bare_fn(_, ref f) => { ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output()) @@ -345,15 +347,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, bcx = src.store_to(bcx, llargs[0]); C_nil(ccx) } - (_, "get_tydesc") => { + (_, "type_name") => { let tp_ty = *substs.types.get(FnSpace, 0); - let static_ti = get_tydesc(ccx, tp_ty); - - // FIXME (#3730): ideally this shouldn't need a cast, - // but there's a circularity between translating rust types to llvm - // types and having a tydesc type available. So I can't directly access - // the llvm type of intrinsic::TyDesc struct. - PointerCast(bcx, static_ti.tydesc, llret_ty) + let ty_name = token::intern_and_get_ident(&ty_to_string(ccx.tcx(), tp_ty)); + C_str_slice(ccx, ty_name) } (_, "type_id") => { let hash = ty::hash_crate_independent( @@ -362,11 +359,18 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, &ccx.link_meta().crate_hash); C_u64(ccx, hash) } + (_, "init_dropped") => { + let tp_ty = *substs.types.get(FnSpace, 0); + if !return_type_is_void(ccx, tp_ty) { + drop_done_fill_mem(bcx, llresult, tp_ty); + } + C_nil(ccx) + } (_, "init") => { let tp_ty = *substs.types.get(FnSpace, 0); if !return_type_is_void(ccx, tp_ty) { // Just zero out the stack slot. (See comment on base::memzero for explanation) - zero_mem(bcx, llresult, tp_ty); + init_zero_mem(bcx, llresult, tp_ty); } C_nil(ccx) } @@ -376,7 +380,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } (_, "needs_drop") => { let tp_ty = *substs.types.get(FnSpace, 0); - C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty)) + + C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty)) } (_, "owns_managed") => { let tp_ty = *substs.types.get(FnSpace, 0); @@ -388,27 +393,27 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, InBoundsGEP(bcx, ptr, &[offset]) } - (_, "copy_nonoverlapping_memory") => { + (_, "copy_nonoverlapping") => { copy_intrinsic(bcx, false, false, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], + llargs[0], llargs[2], call_debug_location) } - (_, "copy_memory") => { + (_, "copy") => { copy_intrinsic(bcx, true, false, *substs.types.get(FnSpace, 0), - llargs[0], llargs[1], + llargs[0], llargs[2], call_debug_location) } - (_, "set_memory") => { + (_, "write_bytes") => { memset_intrinsic(bcx, false, *substs.types.get(FnSpace, 0), @@ -448,10 +453,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, call_debug_location) } (_, "volatile_load") => { - VolatileLoad(bcx, llargs[0]) + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty) }, (_, "volatile_store") => { - VolatileStore(bcx, llargs[1], llargs[0]); + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let val = to_arg_ty(bcx, llargs[1], tp_ty); + VolatileStore(bcx, val, ptr); C_nil(ccx) }, @@ -657,6 +667,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, llargs[0], llargs[1], call_debug_location), + + (_, "overflowing_add") => Add(bcx, llargs[0], llargs[1], call_debug_location), + (_, "overflowing_sub") => Sub(bcx, llargs[0], llargs[1], call_debug_location), + (_, "overflowing_mul") => Mul(bcx, llargs[0], llargs[1], call_debug_location), + (_, "return_address") => { if !fcx.caller_expects_out_pointer { tcx.sess.span_err(call_info.span, @@ -706,8 +721,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, llvm::SequentiallyConsistent }; - let res = AtomicCmpXchg(bcx, llargs[0], llargs[1], - llargs[2], order, + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let cmp = to_arg_ty(bcx, llargs[1], tp_ty); + let src = to_arg_ty(bcx, llargs[2], tp_ty); + let res = AtomicCmpXchg(bcx, ptr, cmp, src, order, strongest_failure_ordering); if unsafe { llvm::LLVMVersionMinor() >= 5 } { ExtractValue(bcx, res, 0) @@ -717,10 +735,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "load" => { - AtomicLoad(bcx, llargs[0], order) + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + from_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty) } "store" => { - AtomicStore(bcx, llargs[1], llargs[0], order); + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let val = to_arg_ty(bcx, llargs[1], tp_ty); + AtomicStore(bcx, val, ptr, order); C_nil(ccx) } @@ -746,7 +769,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().fatal("unknown atomic operation") }; - AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order) + let tp_ty = *substs.types.get(FnSpace, 0); + let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty); + let val = to_arg_ty(bcx, llargs[1], tp_ty); + AtomicRMW(bcx, atom_op, ptr, val, order) } } diff --git a/src/librustc_trans/trans/llrepr.rs b/src/librustc_trans/trans/llrepr.rs index de0f714276..6dd5667979 100644 --- a/src/librustc_trans/trans/llrepr.rs +++ b/src/librustc_trans/trans/llrepr.rs @@ -34,5 +34,3 @@ impl LlvmRepr for ValueRef { ccx.tn().val_to_string(*self) } } - - diff --git a/src/librustc_trans/trans/machine.rs b/src/librustc_trans/trans/machine.rs index 1552ac0bea..ce37d38dc8 100644 --- a/src/librustc_trans/trans/machine.rs +++ b/src/librustc_trans/trans/machine.rs @@ -12,9 +12,7 @@ #![allow(non_camel_case_types)] -use llvm; -use llvm::{ValueRef}; -use llvm::False; +use llvm::{self, ValueRef}; use trans::common::*; use trans::type_::Type; @@ -101,17 +99,7 @@ pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> llalign { } } -// Returns the "default" alignment of t, which is calculated by casting -// null to a record containing a single-bit followed by a t value, then -// doing gep(0,1) to get at the trailing (and presumably padded) t cell. -pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef { - unsafe { - return llvm::LLVMConstIntCast( - llvm::LLVMAlignOf(ty.to_ref()), cx.int_type().to_ref(), False); - } -} - -pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> u64 { +pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: usize) -> u64 { unsafe { return llvm::LLVMOffsetOfElement(cx.td().lltd, struct_ty.to_ref(), element as u32); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 1d5d24a640..190e44c967 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -13,20 +13,22 @@ use back::abi; use back::link; use llvm::{ValueRef, get_param}; use metadata::csearch; -use middle::subst::Substs; +use middle::subst::{Subst, Substs}; use middle::subst::VecPerParamSpace; use middle::subst; use middle::traits; +use middle::ty::ClosureTyper; use trans::base::*; use trans::build::*; use trans::callee::*; use trans::callee; use trans::cleanup; +use trans::closure; use trans::common::*; use trans::consts; use trans::datum::*; use trans::debuginfo::DebugLoc; -use trans::expr::{SaveIn, Ignore}; +use trans::expr::SaveIn; use trans::expr; use trans::glue; use trans::machine; @@ -41,11 +43,11 @@ use std::rc::Rc; use syntax::abi::{Rust, RustCall}; use syntax::parse::token; use syntax::{ast, ast_map, attr, visit}; -use syntax::ast_util::PostExpansionMethod; use syntax::codemap::DUMMY_SP; +use syntax::ptr::P; // drop_glue pointer, size, align. -static VTABLE_OFFSET: uint = 3; +const VTABLE_OFFSET: usize = 3; /// The main "translation" pass for methods. Generates code /// for non-monomorphized methods only. Other methods will @@ -53,7 +55,7 @@ static VTABLE_OFFSET: uint = 3; /// see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. pub fn trans_impl(ccx: &CrateContext, name: ast::Ident, - impl_items: &[ast::ImplItem], + impl_items: &[P], generics: &ast::Generics, id: ast::NodeId) { let _icx = push_ctxt("meth::trans_impl"); @@ -61,47 +63,42 @@ pub fn trans_impl(ccx: &CrateContext, debug!("trans_impl(name={}, id={})", name.repr(tcx), id); + let mut v = TransItemVisitor { ccx: ccx }; + // Both here and below with generic methods, be sure to recurse and look for // items that we need to translate. if !generics.ty_params.is_empty() { - let mut v = TransItemVisitor{ ccx: ccx }; for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - visit::walk_method_helper(&mut v, &**method); + match impl_item.node { + ast::MethodImplItem(..) => { + visit::walk_impl_item(&mut v, impl_item); } - ast::TypeImplItem(_) => {} + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} } } return; } for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - if method.pe_generics().ty_params.len() == 0 { - let trans_everywhere = attr::requests_inline(&method.attrs[]); + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + if sig.generics.ty_params.len() == 0 { + let trans_everywhere = attr::requests_inline(&impl_item.attrs); for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) { - let llfn = get_item_val(ccx, method.id); + let llfn = get_item_val(ccx, impl_item.id); let empty_substs = tcx.mk_substs(Substs::trans_empty()); - trans_fn(ccx, - method.pe_fn_decl(), - method.pe_body(), - llfn, - empty_substs, - method.id, - &[]); + trans_fn(ccx, &sig.decl, body, llfn, + empty_substs, impl_item.id, &[]); update_linkage(ccx, llfn, - Some(method.id), + Some(impl_item.id), if is_origin { OriginalTranslation } else { InlinedCopy }); } } - let mut v = TransItemVisitor { - ccx: ccx, - }; - visit::walk_method_helper(&mut v, &**method); + visit::walk_impl_item(&mut v, impl_item); } - ast::TypeImplItem(_) => {} + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} } } } @@ -189,17 +186,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let mname = if method_id.krate == ast::LOCAL_CRATE { 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(_) => { - tcx.sess.bug("trans_static_method_callee() on \ - an associated type?!") - } - }; - ident.name - } + ast_map::NodeTraitItem(trait_item) => trait_item.ident.name, _ => panic!("callee is not a trait method") } } else { @@ -300,12 +287,15 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, .position(|item| item.def_id() == method_id) .unwrap(); let (llfn, ty) = - trans_object_shim(ccx, data.object_ty, trait_id, method_offset_in_trait); + trans_object_shim(ccx, + data.object_ty, + data.upcast_trait_ref.clone(), + method_offset_in_trait); immediate_rvalue(llfn, ty) } _ => { tcx.sess.bug(&format!("static call to invalid vtable: {}", - vtbl.repr(tcx))[]); + vtbl.repr(tcx))); } } } @@ -335,7 +325,7 @@ fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name) fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, method_call: MethodCall, trait_id: ast::DefId, - n_method: uint, + n_method: usize, vtable: traits::Vtable<'tcx, ()>) -> Callee<'blk, 'tcx> { let _icx = push_ctxt("meth::trans_monomorphized_callee"); @@ -370,30 +360,36 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, traits::VtableClosure(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.ccx(), - closure_def_id, - MethodCallKey(method_call), - bcx.fcx.param_substs, - substs).val; - + let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap(); + let llfn = closure::trans_closure_method(bcx.ccx(), + closure_def_id, + substs, + MethodCallKey(method_call), + bcx.fcx.param_substs, + trait_closure_kind); Callee { bcx: bcx, data: Fn(llfn), } } traits::VtableFnPointer(fn_ty) => { - let llfn = trans_fn_pointer_shim(bcx.ccx(), fn_ty); + let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap(); + let llfn = trans_fn_pointer_shim(bcx.ccx(), trait_closure_kind, fn_ty); Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableObject(ref data) => { - let (llfn, _) = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method); + let (llfn, _) = trans_object_shim(bcx.ccx(), + data.object_ty, + data.upcast_trait_ref.clone(), + n_method); Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableBuiltin(..) | + traits::VtableDefaultImpl(..) | traits::VtableParam(..) => { bcx.sess().bug( &format!("resolved vtable bad vtable {} in trans", - vtable.repr(bcx.tcx()))[]); + vtable.repr(bcx.tcx()))); } } } @@ -441,7 +437,7 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// extract the self data and vtable out of the pair. fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, method_ty: Ty<'tcx>, - vtable_index: uint, + vtable_index: usize, self_expr: &ast::Expr, arg_cleanup_scope: cleanup::ScopeId) -> Callee<'blk, 'tcx> { @@ -453,7 +449,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let self_datum = unpack_datum!( bcx, expr::trans(bcx, self_expr)); - let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) { + let llval = if bcx.fcx.type_needs_drop(self_datum.ty) { let self_datum = unpack_datum!( bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); @@ -478,7 +474,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// pair. pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, callee_ty: Ty<'tcx>, - vtable_index: uint, + vtable_index: usize, llpair: ValueRef) -> Callee<'blk, 'tcx> { let _icx = push_ctxt("meth::trans_trait_callee"); @@ -550,16 +546,17 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pub fn trans_object_shim<'a, 'tcx>( ccx: &'a CrateContext<'a, 'tcx>, object_ty: Ty<'tcx>, - trait_id: ast::DefId, - method_offset_in_trait: uint) + upcast_trait_ref: ty::PolyTraitRef<'tcx>, + method_offset_in_trait: usize) -> (ValueRef, Ty<'tcx>) { let _icx = push_ctxt("trans_object_shim"); let tcx = ccx.tcx(); + let trait_id = upcast_trait_ref.def_id(); - debug!("trans_object_shim(object_ty={}, trait_id={}, method_offset_in_trait={})", + debug!("trans_object_shim(object_ty={}, upcast_trait_ref={}, method_offset_in_trait={})", object_ty.repr(tcx), - trait_id.repr(tcx), + upcast_trait_ref.repr(tcx), method_offset_in_trait); let object_trait_ref = @@ -574,7 +571,6 @@ pub fn trans_object_shim<'a, 'tcx>( }; // Upcast to the trait in question and extract out the substitutions. - let upcast_trait_ref = traits::upcast(ccx.tcx(), object_trait_ref.clone(), trait_id).unwrap(); let upcast_trait_ref = ty::erase_late_bound_regions(tcx, &upcast_trait_ref); let object_substs = upcast_trait_ref.substs.clone().erase_regions(); debug!("trans_object_shim: object_substs={}", object_substs.repr(tcx)); @@ -588,15 +584,16 @@ pub fn trans_object_shim<'a, 'tcx>( }; let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty); let fty = tcx.mk_bare_fn(fty); - debug!("trans_object_shim: fty={}", fty.repr(tcx)); + let method_ty = opaque_method_ty(tcx, fty); + debug!("trans_object_shim: fty={} method_ty={}", fty.repr(tcx), method_ty.repr(tcx)); // - let method_bare_fn_ty = - ty::mk_bare_fn(tcx, None, fty); + let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty); + let method_bare_fn_ty = ty::mk_bare_fn(tcx, None, method_ty); let function_name = - link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim"); + link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim"); let llfn = - decl_internal_rust_fn(ccx, method_bare_fn_ty, &function_name); + decl_internal_rust_fn(ccx, shim_fn_ty, &function_name); let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig); @@ -652,9 +649,6 @@ pub fn trans_object_shim<'a, 'tcx>( assert!(!fcx.needs_ret_allocas); - let sig = - ty::erase_late_bound_regions(bcx.tcx(), &fty.sig); - let dest = fcx.llretslotptr.get().map( |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot"))); @@ -687,11 +681,8 @@ pub fn trans_object_shim<'a, 'tcx>( /// /// The `trait_ref` encodes the erased self type. Hence if we are /// making an object `Foo` from a value of type `Foo`, then -/// `trait_ref` would map `T:Trait`, but `box_ty` would be -/// `Foo`. This `box_ty` is primarily used to encode the destructor. -/// This will hopefully change now that DST is underway. +/// `trait_ref` would map `T:Trait`. pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - box_ty: Ty<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, param_substs: &'tcx subst::Substs<'tcx>) -> ValueRef @@ -699,13 +690,10 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let tcx = ccx.tcx(); let _icx = push_ctxt("meth::get_vtable"); - debug!("get_vtable(box_ty={}, trait_ref={})", - box_ty.repr(tcx), - trait_ref.repr(tcx)); + debug!("get_vtable(trait_ref={})", trait_ref.repr(tcx)); // Check the cache. - let cache_key = (box_ty, trait_ref.clone()); - match ccx.vtables().borrow().get(&cache_key) { + match ccx.vtables().borrow().get(&trait_ref) { Some(&val) => { return val } None => { } } @@ -714,6 +702,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let methods = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| { let vtable = fulfill_obligation(ccx, DUMMY_SP, trait_ref.clone()); match vtable { + // Should default trait error here? + traits::VtableDefaultImpl(_) | traits::VtableBuiltin(_) => { Vec::new().into_iter() } @@ -725,17 +715,18 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, emit_vtable_methods(ccx, id, substs, param_substs).into_iter() } traits::VtableClosure(closure_def_id, substs) => { - let llfn = trans_fn_ref_with_substs( - ccx, - closure_def_id, - ExprId(0), - param_substs, - substs).val; - + let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); + let llfn = closure::trans_closure_method(ccx, + closure_def_id, + substs, + ExprId(0), + param_substs, + trait_closure_kind); vec![llfn].into_iter() } traits::VtableFnPointer(bare_fn_ty) => { - vec![trans_fn_pointer_shim(ccx, bare_fn_ty)].into_iter() + let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); + vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter() } traits::VtableObject(ref data) => { // this would imply that the Self type being erased is @@ -749,7 +740,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, tcx.sess.bug( &format!("resolved vtable for {} to bad vtable {} in trans", trait_ref.repr(tcx), - vtable.repr(tcx))[]); + vtable.repr(tcx))); } } }); @@ -760,7 +751,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let components: Vec<_> = vec![ // Generate a destructor for the vtable. - glue::get_drop_glue(ccx, box_ty), + glue::get_drop_glue(ccx, trait_ref.self_ty()), C_uint(ccx, size), C_uint(ccx, align) ].into_iter().chain(methods).collect(); @@ -768,7 +759,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let vtable = consts::addr_of(ccx, C_struct(ccx, &components, false), "vtable", trait_ref.def_id().node); - ccx.vtables().borrow_mut().insert(cache_key, vtable); + ccx.vtables().borrow_mut().insert(trait_ref, vtable); vtable } @@ -776,9 +767,15 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, impl_id: ast::DefId, substs: subst::Substs<'tcx>, param_substs: &'tcx subst::Substs<'tcx>) - -> Vec { + -> Vec +{ let tcx = ccx.tcx(); + debug!("emit_vtable_methods(impl_id={}, substs={}, param_substs={})", + impl_id.repr(tcx), + substs.repr(tcx), + param_substs.repr(tcx)); + let trt_id = match ty::impl_trait_ref(tcx, impl_id) { Some(t_id) => t_id.def_id, None => ccx.sess().bug("make_impl_vtable: don't know how to \ @@ -787,82 +784,87 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::populate_implementations_for_trait_if_necessary(tcx, trt_id); + let nullptr = C_null(Type::nil(ccx).ptr_to()); let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id); - trait_item_def_ids.iter().flat_map(|method_def_id| { - let method_def_id = method_def_id.def_id(); - let name = ty::impl_or_trait_item(tcx, method_def_id).name(); - // The substitutions we have are on the impl, so we grab - // the method type from the impl to substitute into. - let m_id = method_with_name(ccx, impl_id, name); - let ti = ty::impl_or_trait_item(tcx, m_id); - match ti { - ty::MethodTraitItem(m) => { - debug!("(making impl vtable) emitting method {} at subst {}", - m.repr(tcx), - substs.repr(tcx)); - if m.generics.has_type_params(subst::FnSpace) || - ty::type_has_self(ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(m.fty.clone()))) - { - debug!("(making impl vtable) method has self or type \ - params: {}", - token::get_name(name)); - Some(C_null(Type::nil(ccx).ptr_to())).into_iter() - } else { - let fn_ref = trans_fn_ref_with_substs( - ccx, - m_id, - ExprId(0), - param_substs, - substs.clone()).val; - - // currently, at least, by-value self is not object safe - assert!(m.explicit_self != ty::ByValueExplicitSelfCategory); - - Some(fn_ref).into_iter() - } - } - ty::TypeTraitItem(_) => { - None.into_iter() + trait_item_def_ids + .iter() + + // Filter out the associated types. + .filter_map(|item_def_id| { + match *item_def_id { + ty::MethodTraitItemId(def_id) => Some(def_id), + ty::TypeTraitItemId(_) => None, } - } - }).collect() -} + }) -/// Generates the code to convert from a pointer (`Box`, `&T`, etc) into an object -/// (`Box`, `&Trait`, etc). This means creating a pair where the first word is the vtable -/// and the second word is the pointer. -pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - datum: Datum<'tcx, Expr>, - id: ast::NodeId, - trait_ref: ty::PolyTraitRef<'tcx>, - dest: expr::Dest) - -> Block<'blk, 'tcx> { - let mut bcx = bcx; - let _icx = push_ctxt("meth::trans_trait_cast"); + // Now produce pointers for each remaining method. If the + // method could never be called from this object, just supply + // null. + .map(|trait_method_def_id| { + debug!("emit_vtable_methods: trait_method_def_id={}", + trait_method_def_id.repr(tcx)); - let lldest = match dest { - Ignore => { - return datum.clean(bcx, "trait_trait_cast", id); - } - SaveIn(dest) => dest - }; + let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) { + ty::MethodTraitItem(m) => m, + ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type") + }; + let name = trait_method_type.name; + + // Some methods cannot be called on an object; skip those. + if !traits::is_vtable_safe_method(tcx, trt_id, &trait_method_type) { + debug!("emit_vtable_methods: not vtable safe"); + return nullptr; + } - debug!("trans_trait_cast: trait_ref={}", - trait_ref.repr(bcx.tcx())); + debug!("emit_vtable_methods: trait_method_type={}", + trait_method_type.repr(tcx)); - let datum_ty = datum.ty; - let llbox_ty = type_of(bcx.ccx(), datum_ty); + // The substitutions we have are on the impl, so we grab + // the method type from the impl to substitute into. + let impl_method_def_id = method_with_name(ccx, impl_id, name); + let impl_method_type = match ty::impl_or_trait_item(tcx, impl_method_def_id) { + ty::MethodTraitItem(m) => m, + ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type") + }; - // Store the pointer into the first half of pair. - let llboxdest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_ADDR]); - let llboxdest = PointerCast(bcx, llboxdest, llbox_ty.ptr_to()); - bcx = datum.store_to(bcx, llboxdest); + debug!("emit_vtable_methods: impl_method_type={}", + impl_method_type.repr(tcx)); + + // If this is a default method, it's possible that it + // relies on where clauses that do not hold for this + // particular set of type parameters. Note that this + // method could then never be called, so we do not want to + // try and trans it, in that case. Issue #23435. + if ty::provided_source(tcx, impl_method_def_id).is_some() { + let predicates = impl_method_type.predicates.predicates.subst(tcx, &substs); + if !normalize_and_test_predicates(ccx, predicates.into_vec()) { + debug!("emit_vtable_methods: predicates do not hold"); + return nullptr; + } + } - // Store the vtable into the second half of pair. - let vtable = get_vtable(bcx.ccx(), datum_ty, trait_ref, bcx.fcx.param_substs); - let llvtabledest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_EXTRA]); - let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to()); - Store(bcx, vtable, llvtabledest); + trans_fn_ref_with_substs(ccx, + impl_method_def_id, + ExprId(0), + param_substs, + substs.clone()).val + }) + .collect() +} - bcx +/// Replace the self type (&Self or Box) with an opaque pointer. +pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>) + -> &'tcx ty::BareFnTy<'tcx> { + let mut inputs = method_ty.sig.0.inputs.clone(); + inputs[0] = ty::mk_mut_ptr(tcx, ty::mk_mach_int(tcx, ast::TyI8)); + + tcx.mk_bare_fn(ty::BareFnTy { + unsafety: method_ty.unsafety, + abi: method_ty.abi, + sig: ty::Binder(ty::FnSig { + inputs: inputs, + output: method_ty.sig.0.output, + variadic: method_ty.sig.0.variadic, + }), + }) } diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index f7433e6a77..c7857d6a77 100644 --- a/src/librustc_trans/trans/mod.rs +++ b/src/librustc_trans/trans/mod.rs @@ -57,7 +57,7 @@ mod basic_block; mod llrepr; mod cleanup; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct ModuleTranslation { pub llcx: ContextRef, pub llmod: ModuleRef, diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index ec48ab0d34..dcb21c5cd9 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -29,7 +29,7 @@ use util::ppaux::Repr; use syntax::abi; use syntax::ast; use syntax::ast_map; -use syntax::ast_util::{local_def, PostExpansionMethod}; +use syntax::ast_util::local_def; use syntax::attr; use syntax::codemap::DUMMY_SP; use std::hash::{Hasher, Hash, SipHasher}; @@ -177,7 +177,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, .. } => { let d = mk_lldecl(abi); - let needs_body = setup_lldecl(d, &i.attrs[]); + let needs_body = setup_lldecl(d, &i.attrs); if needs_body { if abi != abi::Rust { foreign::trans_rust_fn_with_foreign_abi( @@ -216,18 +216,18 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } d } - ast_map::NodeImplItem(ii) => { - match *ii { - ast::MethodImplItem(ref mth) => { + ast_map::NodeImplItem(impl_item) => { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { let d = mk_lldecl(abi::Rust); - let needs_body = setup_lldecl(d, &mth.attrs[]); + let needs_body = setup_lldecl(d, &impl_item.attrs); if needs_body { trans_fn(ccx, - mth.pe_fn_decl(), - mth.pe_body(), + &sig.decl, + body, d, psubsts, - mth.id, + impl_item.id, &[]); } d @@ -235,22 +235,25 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ast::TypeImplItem(_) => { ccx.sess().bug("can't monomorphize an associated type") } + ast::MacImplItem(_) => { + ccx.sess().bug("can't monomorphize an unexpanded macro") + } } } - ast_map::NodeTraitItem(method) => { - match *method { - ast::ProvidedMethod(ref mth) => { + ast_map::NodeTraitItem(trait_item) => { + match trait_item.node { + ast::MethodTraitItem(ref sig, Some(ref body)) => { let d = mk_lldecl(abi::Rust); - let needs_body = setup_lldecl(d, &mth.attrs[]); + let needs_body = setup_lldecl(d, &trait_item.attrs); if needs_body { - trans_fn(ccx, mth.pe_fn_decl(), mth.pe_body(), d, - psubsts, mth.id, &[]); + trans_fn(ccx, &sig.decl, body, d, + psubsts, trait_item.id, &[]); } d } _ => { ccx.sess().bug(&format!("can't monomorphize a {:?}", - map_node)[]) + map_node)) } } } @@ -258,7 +261,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let d = mk_lldecl(abi::Rust); set_inline_hint(d); base::trans_tuple_struct(ccx, - &struct_def.fields[], + &struct_def.fields, struct_def.ctor_id.expect("ast-mapped tuple struct \ didn't have a ctor id"), psubsts, @@ -276,7 +279,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ast_map::NodePat(..) | ast_map::NodeLocal(..) => { ccx.sess().bug(&format!("can't monomorphize a {:?}", - map_node)[]) + map_node)) } }; @@ -336,7 +339,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T for obligation in obligations { fulfill_cx.register_predicate_obligation(&infcx, obligation); } - let result = drain_fulfillment_cx(DUMMY_SP, &infcx, &mut fulfill_cx, &result); + let result = drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result); result } diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 7b59e0258e..791b58d88a 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -12,7 +12,7 @@ use back::abi; use llvm; -use llvm::{ValueRef}; +use llvm::ValueRef; use trans::base::*; use trans::base; use trans::build::*; @@ -24,8 +24,6 @@ use trans::datum::*; use trans::debuginfo::DebugLoc; use trans::expr::{Dest, Ignore, SaveIn}; use trans::expr; -use trans::glue; -use trans::machine; use trans::machine::llsize_of_alloc; use trans::type_::Type; use trans::type_of; @@ -35,80 +33,17 @@ use util::ppaux::ty_to_string; use syntax::ast; use syntax::parse::token::InternedString; -fn get_len(bcx: Block, vptr: ValueRef) -> ValueRef { - let _icx = push_ctxt("tvec::get_lenl"); - Load(bcx, expr::get_len(bcx, vptr)) -} - -fn get_dataptr(bcx: Block, vptr: ValueRef) -> ValueRef { - let _icx = push_ctxt("tvec::get_dataptr"); - Load(bcx, expr::get_dataptr(bcx, vptr)) -} - -pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - vptr: ValueRef, - unit_ty: Ty<'tcx>, - should_deallocate: bool) - -> Block<'blk, 'tcx> { - let not_null = IsNotNull(bcx, vptr); - with_cond(bcx, not_null, |bcx| { - let ccx = bcx.ccx(); - let tcx = bcx.tcx(); - let _icx = push_ctxt("tvec::make_drop_glue_unboxed"); - - let dataptr = get_dataptr(bcx, vptr); - let bcx = if type_needs_drop(tcx, unit_ty) { - let len = get_len(bcx, vptr); - iter_vec_raw(bcx, - dataptr, - unit_ty, - len, - |bb, vv, tt| glue::drop_ty(bb, vv, tt, DebugLoc::None)) - } else { - bcx - }; - - if should_deallocate { - let llty = type_of::type_of(ccx, unit_ty); - let unit_size = llsize_of_alloc(ccx, llty); - if unit_size != 0 { - let len = get_len(bcx, vptr); - let not_empty = ICmp(bcx, - llvm::IntNE, - len, - C_uint(ccx, 0_u32), - DebugLoc::None); - with_cond(bcx, not_empty, |bcx| { - let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty)); - let size = Mul(bcx, C_uint(ccx, unit_size), len, DebugLoc::None); - glue::trans_exchange_free_dyn(bcx, - dataptr, - size, - llalign, - DebugLoc::None) - }) - } else { - bcx - } - } else { - bcx - } - }) -} - -#[derive(Copy)] -pub struct VecTypes<'tcx> { - pub unit_ty: Ty<'tcx>, - pub llunit_ty: Type, - pub llunit_alloc_size: u64 +#[derive(Copy, Clone)] +struct VecTypes<'tcx> { + unit_ty: Ty<'tcx>, + llunit_ty: Type } impl<'tcx> VecTypes<'tcx> { pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String { - format!("VecTypes {{unit_ty={}, llunit_ty={}, llunit_alloc_size={}}}", + format!("VecTypes {{unit_ty={}, llunit_ty={}}}", ty_to_string(ccx.tcx(), self.unit_ty), - ccx.tn().type_to_string(self.llunit_ty), - self.llunit_alloc_size) + ccx.tn().type_to_string(self.llunit_ty)) } } @@ -222,12 +157,12 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - vt: &VecTypes<'tcx>, - vstore_expr: &ast::Expr, - content_expr: &ast::Expr, - dest: Dest) - -> Block<'blk, 'tcx> { +fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + vt: &VecTypes<'tcx>, + vstore_expr: &ast::Expr, + content_expr: &ast::Expr, + dest: Dest) + -> Block<'blk, 'tcx> { let _icx = push_ctxt("tvec::write_content"); let fcx = bcx.fcx; let mut bcx = bcx; @@ -294,7 +229,7 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } SaveIn(lldest) => { match ty::eval_repeat_count(bcx.tcx(), &**count_expr) { - 0 => bcx, + 0 => expr::trans_into(bcx, &**element, Ignore), 1 => expr::trans_into(bcx, &**element, SaveIn(lldest)), count => { let elem = unpack_datum!(bcx, expr::trans(bcx, &**element)); @@ -316,28 +251,21 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -pub fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - vec_expr: &ast::Expr) - -> VecTypes<'tcx> { +fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, vec_expr: &ast::Expr) + -> VecTypes<'tcx> { let vec_ty = node_id_type(bcx, vec_expr.id); vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty)) } -pub fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - unit_ty: Ty<'tcx>) - -> VecTypes<'tcx> { - let ccx = bcx.ccx(); - let llunit_ty = type_of::type_of(ccx, unit_ty); - let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty); - +fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, unit_ty: Ty<'tcx>) + -> VecTypes<'tcx> { VecTypes { unit_ty: unit_ty, - llunit_ty: llunit_ty, - llunit_alloc_size: llunit_alloc_size + llunit_ty: type_of::type_of(bcx.ccx(), unit_ty) } } -pub fn elements_required(bcx: Block, content_expr: &ast::Expr) -> uint { +fn elements_required(bcx: Block, content_expr: &ast::Expr) -> usize { //! Figure out the number of elements we need to store this content match content_expr.node { @@ -363,7 +291,7 @@ pub fn elements_required(bcx: Block, content_expr: &ast::Expr) -> uint { /// which should be by ref. pub fn get_fixed_base_and_len(bcx: Block, llval: ValueRef, - vec_length: uint) + vec_length: usize) -> (ValueRef, ValueRef) { let ccx = bcx.ccx(); @@ -372,54 +300,51 @@ pub fn get_fixed_base_and_len(bcx: Block, (base, len) } -fn get_slice_base_and_len(bcx: Block, - llval: ValueRef) - -> (ValueRef, ValueRef) { - let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR])); - let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA])); - (base, len) -} - /// Converts a vector into the slice pair. The vector should be stored in `llval` which should be /// by-reference. If you have a datum, you would probably prefer to call /// `Datum::get_base_and_len()` which will handle any conversions for you. -pub fn get_base_and_len(bcx: Block, - llval: ValueRef, - vec_ty: Ty) - -> (ValueRef, ValueRef) { +pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + llval: ValueRef, + vec_ty: Ty<'tcx>) + -> (ValueRef, ValueRef) { let ccx = bcx.ccx(); match vec_ty.sty { ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n), - ty::ty_open(ty) => match ty.sty { - ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval), - _ => ccx.sess().bug("unexpected type in get_base_and_len") - }, + ty::ty_vec(_, None) | ty::ty_str => { + let base = Load(bcx, expr::get_dataptr(bcx, llval)); + let len = Load(bcx, expr::get_len(bcx, llval)); + (base, len) + } // Only used for pattern matching. - ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty { - ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval), - ty::ty_vec(_, Some(n)) => { - let base = GEPi(bcx, Load(bcx, llval), &[0, 0]); - (base, C_uint(ccx, n)) - } - _ => ccx.sess().bug("unexpected type in get_base_and_len"), + ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => { + let inner = if type_is_sized(bcx.tcx(), ty) { + Load(bcx, llval) + } else { + llval + }; + get_base_and_len(bcx, inner, ty) }, _ => ccx.sess().bug("unexpected type in get_base_and_len"), } } -pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, - data_ptr: ValueRef, - vt: &VecTypes<'tcx>, - count: ValueRef, - f: F) - -> Block<'blk, 'tcx> where +fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, + data_ptr: ValueRef, + vt: &VecTypes<'tcx>, + count: 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_loop"); - let fcx = bcx.fcx; + if bcx.unreachable.get() { + return bcx; + } + + let fcx = bcx.fcx; let loop_bcx = fcx.new_temp_block("expr_repeat"); let next_bcx = fcx.new_temp_block("expr_repeat: next"); @@ -430,7 +355,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let bcx = loop_bcx; - let lleltptr = if vt.llunit_alloc_size == 0 { + let lleltptr = if llsize_of_alloc(bcx.ccx(), vt.llunit_ty) == 0 { data_ptr } else { InBoundsGEP(bcx, data_ptr, &[loop_counter]) @@ -458,7 +383,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let vt = vec_types(bcx, unit_ty); - if vt.llunit_alloc_size == 0 { + if llsize_of_alloc(bcx.ccx(), vt.llunit_ty) == 0 { // Special-case vectors with elements of size 0 so they don't go out of bounds (#9890) iter_vec_loop(bcx, data_ptr, &vt, len, f) } else { @@ -475,7 +400,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let body_bcx = fcx.new_temp_block("iter_vec_loop_body"); let next_bcx = fcx.new_temp_block("iter_vec_next"); CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None); - let body_bcx = f(body_bcx, data_ptr, vt.unit_ty); + let body_bcx = f(body_bcx, data_ptr, unit_ty); AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr, &[C_int(bcx.ccx(), 1)]), body_bcx.llbb); diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index ad83135a0d..339b4734ee 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -109,7 +109,7 @@ impl Type { } pub fn int(ccx: &CrateContext) -> Type { - match &ccx.tcx().sess.target.target.target_pointer_width[] { + match &ccx.tcx().sess.target.target.target_pointer_width[..] { "32" => Type::i32(ccx), "64" => Type::i64(ccx), tws => panic!("Unsupported target word size for int: {}", tws), @@ -118,7 +118,7 @@ impl Type { pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type { match t { - ast::TyIs(_) => ccx.int_type(), + ast::TyIs => ccx.int_type(), ast::TyI8 => Type::i8(ccx), ast::TyI16 => Type::i16(ccx), ast::TyI32 => Type::i32(ccx), @@ -128,7 +128,7 @@ impl Type { pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type { match t { - ast::TyUs(_) => ccx.int_type(), + ast::TyUs => ccx.int_type(), ast::TyU8 => Type::i8(ccx), ast::TyU16 => Type::i16(ccx), ast::TyU32 => Type::i32(ccx), @@ -175,41 +175,10 @@ impl Type { Type::array(&Type::i8p(ccx).ptr_to(), 1) } - pub fn generic_glue_fn(cx: &CrateContext) -> Type { - match cx.tn().find_type("glue_fn") { - Some(ty) => return ty, - None => () - } - - let ty = Type::glue_fn(cx, Type::i8p(cx)); - cx.tn().associate_type("glue_fn", &ty); - - ty - } - pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type { Type::func(&[t], &Type::void(ccx)) } - pub fn tydesc(ccx: &CrateContext, str_slice_ty: Type) -> Type { - let mut tydesc = Type::named_struct(ccx, "tydesc"); - let glue_fn_ty = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to(); - - let int_ty = Type::int(ccx); - - // Must mirror: - // - // std::unstable::intrinsics::TyDesc - - let elems = [int_ty, // size - int_ty, // align - glue_fn_ty, // drop - str_slice_ty]; // name - tydesc.set_struct_body(&elems, false); - - tydesc - } - pub fn array(ty: &Type, len: u64) -> Type { ty!(llvm::LLVMRustArrayType(ty.to_ref(), len)) } @@ -232,14 +201,6 @@ impl Type { Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to() } - pub fn opaque_trait(ccx: &CrateContext) -> Type { - Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false) - } - - pub fn opaque_trait_data(ccx: &CrateContext) -> Type { - Type::i8(ccx) - } - pub fn kind(&self) -> TypeKind { unsafe { llvm::LLVMGetTypeKind(self.to_ref()) @@ -278,21 +239,21 @@ impl Type { } /// Return the number of elements in `self` if it is a LLVM vector type. - pub fn vector_length(&self) -> uint { + pub fn vector_length(&self) -> usize { unsafe { - llvm::LLVMGetVectorSize(self.to_ref()) as uint + llvm::LLVMGetVectorSize(self.to_ref()) as usize } } - pub fn array_length(&self) -> uint { + pub fn array_length(&self) -> usize { unsafe { - llvm::LLVMGetArrayLength(self.to_ref()) as uint + llvm::LLVMGetArrayLength(self.to_ref()) as usize } } pub fn field_types(&self) -> Vec { unsafe { - let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as uint; + let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as usize; if n_elts == 0 { return Vec::new(); } @@ -309,7 +270,7 @@ impl Type { pub fn func_params(&self) -> Vec { unsafe { - let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint; + let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize; let mut args: Vec<_> = repeat(Type { rf: ptr::null_mut() }).take(n_args).collect(); llvm::LLVMGetParamTypes(self.to_ref(), args.as_mut_ptr() as *mut TypeRef); @@ -317,7 +278,7 @@ impl Type { } } - pub fn float_width(&self) -> uint { + pub fn float_width(&self) -> usize { match self.kind() { Float => 32, Double => 64, diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 489b56bbe6..2e577a0bd1 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -10,8 +10,6 @@ #![allow(non_camel_case_types)] -pub use self::named_ty::*; - use middle::subst; use trans::adt; use trans::common::*; @@ -23,6 +21,7 @@ use util::ppaux::Repr; use trans::type_::Type; +#[allow(deprecated)] use std::num::Int; use syntax::abi; use syntax::ast; @@ -183,9 +182,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } let llsizingty = match t.sty { - _ if !lltype_is_sized(cx.tcx(), t) => { - cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type", - ppaux::ty_to_string(cx.tcx(), t))[]) + _ if !type_is_sized(cx.tcx(), t) => { + Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) } ty::ty_bool => Type::bool(cx), @@ -232,15 +230,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } } - ty::ty_open(_) => { - Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) - } - ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => { cx.sess().bug(&format!("fictitious type {} in sizing_type_of()", - ppaux::ty_to_string(cx.tcx(), t))[]) + ppaux::ty_to_string(cx.tcx(), t))) } - ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable") + ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!() }; cx.llsizingtypes().borrow_mut().insert(t, llsizingty); @@ -270,25 +264,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { } } -// NB: If you update this, be sure to update `sizing_type_of()` as well. -pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { - fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { - // It is possible to end up here with a sized type. This happens with a - // struct which might be unsized, but is monomorphised to a sized type. - // In this case we'll fake a fat pointer with no unsize info (we use 0). - // However, its still a fat pointer, so we need some type use. - if type_is_sized(cx.tcx(), t) { - return Type::i8p(cx); - } - - match unsized_part_of_type(cx.tcx(), t).sty { - ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)), - ty::ty_trait(_) => Type::vtable_ptr(cx), - _ => panic!("Unexpected type returned from unsized_part_of_type : {}", - t.repr(cx.tcx())) - } - } +/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`. +/// This is the right LLVM type for an alloca containing a value of that type, +/// and the pointee of an Lvalue Datum (which is always a LLVM pointer). +/// For unsized types, the returned type is a fat pointer, thus the resulting +/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double +/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`. +/// This is needed due to the treatment of immediate values, as a fat pointer +/// is too large for it to be placed in SSA value (by our rules). +/// For the raw type without far pointer indirection, see `in_memory_type_of`. +pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type { + let ty = if !type_is_sized(cx.tcx(), ty) { + ty::mk_imm_ptr(cx.tcx(), ty) + } else { + ty + }; + in_memory_type_of(cx, ty) +} +/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`. +/// This is the right LLVM type for a field/array element of that type, +/// and is the same as `type_of` for all Sized types. +/// Unsized types, however, are represented by a "minimal unit", e.g. +/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this +/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`. +/// If the type is an unsized struct, the regular layout is generated, +/// with the inner-most trailing unsized field using the "minimal unit" +/// of that field's type - this is useful for taking the address of +/// that field and ensuring the struct has the right alignment. +/// For the LLVM type of a value as a whole, see `type_of`. +/// NB: If you update this, be sure to update `sizing_type_of()` as well. +pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // Check the cache. match cx.lltypes().borrow().get(&t) { Some(&llty) => return llty, @@ -307,7 +313,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { let t_norm = erase_regions(cx.tcx(), &t); if t != t_norm { - let llty = type_of(cx, t_norm); + let llty = in_memory_type_of(cx, t_norm); debug!("--> normalized {} {:?} to {} {:?} llty={}", t.repr(cx.tcx()), t, @@ -331,10 +337,10 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // of the enum's variants refers to the enum itself. let repr = adt::represent_type(cx, t); let tps = substs.types.get_slice(subst::TypeSpace); - let name = llvm_type_name(cx, an_enum, did, tps); + let name = llvm_type_name(cx, did, tps); adt::incomplete_type_of(cx, &*repr, &name[..]) } - ty::ty_closure(did, _, ref substs) => { + ty::ty_closure(..) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. let repr = adt::represent_type(cx, t); @@ -342,41 +348,47 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // inherited from their environment, so we use entire // contents of the VecPerParamSpace to to construct the llvm // name - let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice()); - adt::incomplete_type_of(cx, &*repr, &name[..]) + adt::incomplete_type_of(cx, &*repr, "closure") } ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => { - match ty.sty { - ty::ty_str => { + if !type_is_sized(cx.tcx(), ty) { + if let ty::ty_str = ty.sty { // This means we get a nicer name in the output (str is always // unsized). cx.tn().find_type("str_slice").unwrap() + } else { + let ptr_ty = in_memory_type_of(cx, ty).ptr_to(); + let unsized_part = unsized_part_of_type(cx.tcx(), ty); + let info_ty = match unsized_part.sty { + ty::ty_str | ty::ty_vec(..) => { + Type::uint_from_ty(cx, ast::TyUs) + } + ty::ty_trait(_) => Type::vtable_ptr(cx), + _ => panic!("Unexpected type returned from \ + unsized_part_of_type: {} for ty={}", + unsized_part.repr(cx.tcx()), ty.repr(cx.tcx())) + }; + Type::struct_(cx, &[ptr_ty, info_ty], false) } - ty::ty_trait(..) => Type::opaque_trait(cx), - _ if !type_is_sized(cx.tcx(), ty) => { - let p_ty = type_of(cx, ty).ptr_to(); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false) - } - _ => type_of(cx, ty).ptr_to(), + } else { + in_memory_type_of(cx, ty).ptr_to() } } ty::ty_vec(ty, Some(size)) => { let size = size as u64; - let llty = type_of(cx, ty); + let llty = in_memory_type_of(cx, ty); ensure_array_fits_in_address_space(cx, llty, size, t); Type::array(&llty, size) } - ty::ty_vec(ty, None) => { - type_of(cx, ty) - } - ty::ty_trait(..) => { - Type::opaque_trait_data(cx) - } - - ty::ty_str => Type::i8(cx), + // Unsized slice types (and str) have the type of their element, and + // traits have the type of u8. This is so that the data pointer inside + // fat pointers is of the right type (e.g. for array accesses), even + // when taking the address of an unsized field in a struct. + ty::ty_vec(ty, None) => in_memory_type_of(cx, ty), + ty::ty_str | ty::ty_trait(..) => Type::i8(cx), ty::ty_bare_fn(..) => { type_of_fn_from_ty(cx, t).ptr_to() @@ -388,7 +400,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { } ty::ty_struct(did, ref substs) => { if ty::type_is_simd(cx.tcx(), t) { - let llet = type_of(cx, ty::simd_type(cx.tcx(), t)); + let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t)); let n = ty::simd_size(cx.tcx(), t) as u64; ensure_array_fits_in_address_space(cx, llet, n, t); Type::vector(&llet, n) @@ -398,29 +410,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // infinite recursion with recursive struct types. let repr = adt::represent_type(cx, t); let tps = substs.types.get_slice(subst::TypeSpace); - let name = llvm_type_name(cx, a_struct, did, tps); + let name = llvm_type_name(cx, did, tps); adt::incomplete_type_of(cx, &*repr, &name[..]) } } - ty::ty_open(t) => match t.sty { - ty::ty_struct(..) => { - let p_ty = type_of(cx, t).ptr_to(); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false) - } - ty::ty_vec(ty, None) => { - let p_ty = type_of(cx, ty).ptr_to(); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false) - } - ty::ty_str => { - let p_ty = Type::i8p(cx); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false) - } - ty::ty_trait(..) => Type::opaque_trait(cx), - _ => cx.sess().bug(&format!("ty_open with sized type: {}", - ppaux::ty_to_string(cx.tcx(), t))[]) - }, - ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"), ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"), ty::ty_param(..) => cx.sess().bug("type_of with ty_param"), @@ -444,7 +438,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { _ => () } - return llty; + llty } pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) @@ -453,37 +447,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) machine::llalign_of_min(cx, llty) } -// Want refinements! (Or case classes, I guess -#[derive(Copy)] -pub enum named_ty { - a_struct, - an_enum, - a_closure, -} - -pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - what: named_ty, - did: ast::DefId, - tps: &[Ty<'tcx>]) - -> String { - let name = match what { - a_struct => "struct", - an_enum => "enum", - a_closure => return "closure".to_string(), - }; - +fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + did: ast::DefId, + tps: &[Ty<'tcx>]) + -> String { let base = ty::item_path_str(cx.tcx(), did); let strings: Vec = tps.iter().map(|t| t.repr(cx.tcx())).collect(); let tstr = if strings.is_empty() { base } else { - format!("{}<{:?}>", base, strings) + format!("{}<{}>", base, strings.connect(", ")) }; if did.krate == 0 { - format!("{}.{}", name, tstr) + tstr } else { - format!("{}.{}[{}{}]", name, tstr, "#", did.krate) + format!("{}.{}", did.krate, tstr) } } diff --git a/src/librustc_trans/trans/value.rs b/src/librustc_trans/trans/value.rs index 464522f167..bc71278c15 100644 --- a/src/librustc_trans/trans/value.rs +++ b/src/librustc_trans/trans/value.rs @@ -14,7 +14,7 @@ use trans::basic_block::BasicBlock; use trans::common::Block; use libc::c_uint; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Value(pub ValueRef); macro_rules! opt_val { ($e:expr) => ( @@ -107,7 +107,7 @@ impl Value { /// Returns the requested operand of this instruction /// Returns None, if there's no operand at the given index - pub fn get_operand(self, i: uint) -> Option { + pub fn get_operand(self, i: usize) -> Option { opt_val!(llvm::LLVMGetOperand(self.get(), i as c_uint)) } @@ -125,7 +125,7 @@ impl Value { } /// Wrapper for LLVM UseRef -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Use(UseRef); impl Use { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e3c1c66f78..939142cff1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -48,22 +48,22 @@ //! case but `&a` in the second. Basically, defaults that appear inside //! an rptr (`&r.T`) use the region `r` that appears in the rptr. -use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS}; +use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS}; use middle::const_eval; use middle::def; use middle::resolve_lifetime as rl; +use middle::privacy::{AllPublic, LastMod}; use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs}; use middle::traits; -use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; +use middle::ty::{self, RegionEscape, Ty}; use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope}; -use TypeAndSubsts; use util::common::{ErrorReported, FN_OUTPUT_NAME}; -use util::nodemap::DefIdMap; use util::ppaux::{self, Repr, UserString}; -use std::rc::Rc; use std::iter::{repeat, AdditiveIterator}; +use std::rc::Rc; +use std::slice; use syntax::{abi, ast, ast_util}; use syntax::codemap::Span; use syntax::parse::token; @@ -72,9 +72,32 @@ use syntax::print::pprust; 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>; + /// Identify the type scheme for an item with a type, like a type + /// alias, fn, or struct. This allows you to figure out the set of + /// type parameters defined on the item. + fn get_item_type_scheme(&self, span: Span, id: ast::DefId) + -> Result, ErrorReported>; + + /// Returns the `TraitDef` for a given trait. This allows you to + /// figure out the set of type parameters defined on the trait. + fn get_trait_def(&self, span: Span, id: ast::DefId) + -> Result>, ErrorReported>; + + /// Ensure that the super-predicates for the trait with the given + /// id are available and also for the transitive set of + /// super-predicates. + fn ensure_super_predicates(&self, span: Span, id: ast::DefId) + -> Result<(), ErrorReported>; + + /// Returns the set of bounds in scope for the type parameter with + /// the given id. + fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId) + -> Result>, ErrorReported>; + + /// Returns true if the trait with id `trait_def_id` defines an + /// associated type with the name `name`. + fn trait_defines_associated_type_named(&self, trait_def_id: ast::DefId, name: ast::Name) + -> bool; /// Return an (optional) substitution to convert bound type parameters that /// are in scope into free ones. This function should only return Some @@ -117,13 +140,7 @@ pub trait AstConv<'tcx> { span: Span, _trait_ref: Rc>, _item_name: ast::Name) - -> Ty<'tcx> - { - span_err!(self.tcx().sess, span, E0213, - "associated types are not accepted in this context"); - - self.tcx().types.err - } + -> Ty<'tcx>; } pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime) @@ -195,29 +212,29 @@ pub fn opt_ast_region_to_region<'tcx>( help_name } else { format!("one of {}'s {} elided lifetimes", help_name, n) - })[]); + })[..]); if len == 2 && i == 0 { m.push_str(" or "); - } else if i == len - 2 { + } else if i + 2 == len { m.push_str(", or "); - } else if i != len - 1 { + } else if i + 1 != len { m.push_str(", "); } } if len == 1 { - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "this function's return type contains a borrowed value, but \ the signature does not say which {} it is borrowed from", m); } else if len == 0 { - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "this function's return type contains a borrowed value, but \ there is no value for it to be borrowed from"); - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "consider giving it a 'static lifetime"); } else { - span_help!(this.tcx().sess, default_span, + fileline_help!(this.tcx().sess, default_span, "this function's return type contains a borrowed value, but \ the signature does not say whether it is borrowed from {}", m); @@ -245,8 +262,10 @@ pub fn opt_ast_region_to_region<'tcx>( pub fn ast_path_substs_for_ty<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, - path: &ast::Path) + item_segment: &ast::PathSegment) -> Substs<'tcx> { let tcx = this.tcx(); @@ -262,27 +281,36 @@ pub fn ast_path_substs_for_ty<'tcx>( assert!(decl_generics.regions.all(|d| d.space == TypeSpace)); assert!(decl_generics.types.all(|d| d.space != FnSpace)); - let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { + let (regions, types, assoc_bindings) = match item_segment.parameters { ast::AngleBracketedParameters(ref data) => { - convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data) + convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data) } ast::ParenthesizedParameters(ref data) => { - span_err!(tcx.sess, path.span, E0214, + span_err!(tcx.sess, span, E0214, "parenthesized parameters may only be used with a trait"); - convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data) + convert_parenthesized_parameters(this, rscope, span, decl_generics, data) } }; prohibit_projections(this.tcx(), &assoc_bindings); create_substs_for_ast_path(this, - path.span, + span, + param_mode, decl_generics, None, types, regions) } +#[derive(PartialEq, Eq)] +pub enum PathParamMode { + // Any path in a type context. + Explicit, + // The `module::Type` in `module::Type::method` in an expression. + Optional +} + fn create_region_substs<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, @@ -305,9 +333,9 @@ fn create_region_substs<'tcx>( rscope.anon_regions(span, expected_num_region_params); if supplied_num_region_params != 0 || anon_regions.is_err() { - span_err!(tcx.sess, span, E0107, - "wrong number of lifetime parameters: expected {}, found {}", - expected_num_region_params, supplied_num_region_params); + report_lifetime_number_error(tcx, span, + supplied_num_region_params, + expected_num_region_params); } match anon_regions { @@ -330,6 +358,7 @@ fn create_region_substs<'tcx>( fn create_substs_for_ast_path<'tcx>( this: &AstConv<'tcx>, span: Span, + param_mode: PathParamMode, decl_generics: &ty::Generics<'tcx>, self_ty: Option>, types_provided: Vec>, @@ -348,38 +377,29 @@ fn create_substs_for_ast_path<'tcx>( // Convert the type parameters supplied by the user. let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - let supplied_ty_param_count = types_provided.len(); let formal_ty_param_count = ty_param_defs.len(); let required_ty_param_count = ty_param_defs.iter() .take_while(|x| x.default.is_none()) .count(); - let mut type_substs = types_provided; + // Fill with `ty_infer` if no params were specified, as long as + // they were optional (e.g. paths inside expressions). + let mut type_substs = if param_mode == PathParamMode::Optional && + types_provided.is_empty() { + (0..formal_ty_param_count).map(|_| this.ty_infer(span)).collect() + } else { + types_provided + }; + + let supplied_ty_param_count = type_substs.len(); + check_type_argument_count(this.tcx(), span, supplied_ty_param_count, + required_ty_param_count, formal_ty_param_count); + if supplied_ty_param_count < required_ty_param_count { - let expected = if required_ty_param_count < formal_ty_param_count { - "expected at least" - } else { - "expected" - }; - span_err!(this.tcx().sess, span, E0243, - "wrong number of type arguments: {} {}, found {}", - expected, - required_ty_param_count, - supplied_ty_param_count); while type_substs.len() < required_ty_param_count { type_substs.push(tcx.types.err); } } else if supplied_ty_param_count > formal_ty_param_count { - let expected = if required_ty_param_count < formal_ty_param_count { - "expected at most" - } else { - "expected" - }; - span_err!(this.tcx().sess, span, E0244, - "wrong number of type arguments: {} {}, found {}", - expected, - formal_ty_param_count, - supplied_ty_param_count); type_substs.truncate(formal_ty_param_count); } assert!(type_substs.len() >= required_ty_param_count && @@ -431,7 +451,7 @@ fn create_substs_for_ast_path<'tcx>( } } - return substs; + substs } struct ConvertedBinding<'tcx> { @@ -478,9 +498,9 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>, /// (if one exists) and a vector of the (pattern, number of lifetimes) /// corresponding to each input type/pattern. fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec) - -> (Option, Vec<(String, uint)>) + -> (Option, Vec<(String, usize)>) { - let mut lifetimes_for_params: Vec<(String, uint)> = Vec::new(); + let mut lifetimes_for_params: Vec<(String, usize)> = Vec::new(); let mut possible_implied_output_region = None; for (input_type, input_pat) in input_tys.iter().zip(input_pats.into_iter()) { @@ -508,7 +528,7 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec) fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>, implied_output_region: Option, - param_lifetimes: Vec<(String, uint)>, + param_lifetimes: Vec<(String, usize)>, ty: &ast::Ty) -> Ty<'tcx> { @@ -582,24 +602,16 @@ pub fn instantiate_poly_trait_ref<'tcx>( poly_projections: &mut Vec>) -> ty::PolyTraitRef<'tcx> { - let mut projections = Vec::new(); - - // The trait reference introduces a binding level here, so - // we need to shift the `rscope`. It'd be nice if we could - // do away with this rscope stuff and work this knowledge - // into resolve_lifetimes, as we do with non-omitted - // lifetimes. Oh well, not there yet. - let shifted_rscope = ShiftedRscope::new(rscope); - - let trait_ref = - instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref, - self_ty, Some(&mut projections)); - - for projection in projections { - poly_projections.push(ty::Binder(projection)); - } - - ty::Binder(trait_ref) + let trait_ref = &ast_trait_ref.trait_ref; + let trait_def_id = trait_def_id(this, trait_ref); + ast_path_to_poly_trait_ref(this, + rscope, + trait_ref.path.span, + PathParamMode::Explicit, + trait_def_id, + self_ty, + trait_ref.path.segments.last().unwrap(), + poly_projections) } /// Instantiates the path for the given trait reference, assuming that it's @@ -608,29 +620,30 @@ pub fn instantiate_poly_trait_ref<'tcx>( /// /// If the `projections` argument is `None`, then assoc type bindings like `Foo` /// are disallowed. Otherwise, they are pushed onto the vector given. -pub fn instantiate_trait_ref<'tcx>( +pub fn instantiate_mono_trait_ref<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, - ast_trait_ref: &ast::TraitRef, - self_ty: Option>, - projections: Option<&mut Vec>>) + trait_ref: &ast::TraitRef, + self_ty: Option>) -> Rc> { - match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { - def::DefTrait(trait_def_id) => { - let trait_ref = ast_path_to_trait_ref(this, - rscope, - trait_def_id, - self_ty, - &ast_trait_ref.path, - projections); - this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone()); - trait_ref - } + let trait_def_id = trait_def_id(this, trait_ref); + ast_path_to_mono_trait_ref(this, + rscope, + trait_ref.path.span, + PathParamMode::Explicit, + trait_def_id, + self_ty, + trait_ref.path.segments.last().unwrap()) +} + +fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::DefId { + let path = &trait_ref.path; + match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) { + def::DefTrait(trait_def_id) => trait_def_id, _ => { - span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245, - "`{}` is not a trait", - ast_trait_ref.path.user_string(this.tcx())); + span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait", + path.user_string(this.tcx())); } } } @@ -638,103 +651,160 @@ pub fn instantiate_trait_ref<'tcx>( fn object_path_to_poly_trait_ref<'a,'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, trait_def_id: ast::DefId, - path: &ast::Path, + trait_segment: &ast::PathSegment, mut projections: &mut Vec>) -> ty::PolyTraitRef<'tcx> { - // we are introducing a binder here, so shift the - // anonymous regions depth to account for that - let shifted_rscope = ShiftedRscope::new(rscope); - - let mut tmp = Vec::new(); - let trait_ref = ty::Binder(ast_path_to_trait_ref(this, - &shifted_rscope, - trait_def_id, - None, - path, - Some(&mut tmp))); - projections.extend(tmp.into_iter().map(ty::Binder)); - trait_ref + ast_path_to_poly_trait_ref(this, + rscope, + span, + param_mode, + trait_def_id, + None, + trait_segment, + projections) } -fn ast_path_to_trait_ref<'a,'tcx>( +fn ast_path_to_poly_trait_ref<'a,'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, trait_def_id: ast::DefId, self_ty: Option>, - path: &ast::Path, - mut projections: Option<&mut Vec>>) - -> Rc> + trait_segment: &ast::PathSegment, + poly_projections: &mut Vec>) + -> ty::PolyTraitRef<'tcx> +{ + // The trait reference introduces a binding level here, so + // we need to shift the `rscope`. It'd be nice if we could + // do away with this rscope stuff and work this knowledge + // into resolve_lifetimes, as we do with non-omitted + // lifetimes. Oh well, not there yet. + let shifted_rscope = &ShiftedRscope::new(rscope); + + let (substs, assoc_bindings) = + create_substs_for_ast_trait_ref(this, + shifted_rscope, + span, + param_mode, + trait_def_id, + self_ty, + trait_segment); + let poly_trait_ref = ty::Binder(Rc::new(ty::TraitRef::new(trait_def_id, substs))); + + { + let converted_bindings = + assoc_bindings + .iter() + .filter_map(|binding| { + // specify type to assert that error was already reported in Err case: + let predicate: Result<_, ErrorReported> = + ast_type_binding_to_poly_projection_predicate(this, + poly_trait_ref.clone(), + self_ty, + binding); + predicate.ok() // ok to ignore Err() because ErrorReported (see above) + }); + poly_projections.extend(converted_bindings); + } + + poly_trait_ref +} + +fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>, + rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, + trait_def_id: ast::DefId, + self_ty: Option>, + trait_segment: &ast::PathSegment) + -> Rc> +{ + let (substs, assoc_bindings) = + create_substs_for_ast_trait_ref(this, + rscope, + span, + param_mode, + trait_def_id, + self_ty, + trait_segment); + prohibit_projections(this.tcx(), &assoc_bindings); + Rc::new(ty::TraitRef::new(trait_def_id, substs)) +} + +fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>, + rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, + trait_def_id: ast::DefId, + self_ty: Option>, + trait_segment: &ast::PathSegment) + -> (&'tcx Substs<'tcx>, Vec>) { - debug!("ast_path_to_trait_ref {:?}", path); - let trait_def = this.get_trait_def(trait_def_id); + debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", + trait_segment); + + let trait_def = match this.get_trait_def(span, trait_def_id) { + Ok(trait_def) => trait_def, + Err(ErrorReported) => { + // No convenient way to recover from a cycle here. Just bail. Sorry! + this.tcx().sess.abort_if_errors(); + this.tcx().sess.bug("ErrorReported returned, but no errors reports?") + } + }; - let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters { + let (regions, types, assoc_bindings) = match trait_segment.parameters { ast::AngleBracketedParameters(ref data) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar { - span_err!(this.tcx().sess, path.span, E0215, + span_err!(this.tcx().sess, span, E0215, "angle-bracket notation is not stable when \ used with the `Fn` family of traits, use parentheses"); - span_help!(this.tcx().sess, path.span, + fileline_help!(this.tcx().sess, span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } - convert_angle_bracketed_parameters(this, rscope, path.span, &trait_def.generics, data) + convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data) } ast::ParenthesizedParameters(ref data) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar { - span_err!(this.tcx().sess, path.span, E0216, + span_err!(this.tcx().sess, span, E0216, "parenthetical notation is only stable when \ used with the `Fn` family of traits"); - span_help!(this.tcx().sess, path.span, + fileline_help!(this.tcx().sess, span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } - convert_parenthesized_parameters(this, rscope, path.span, &trait_def.generics, data) + convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data) } }; let substs = create_substs_for_ast_path(this, - path.span, + span, + param_mode, &trait_def.generics, self_ty, types, regions); - let substs = this.tcx().mk_substs(substs); - - let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs)); - match projections { - None => { - prohibit_projections(this.tcx(), &assoc_bindings); - } - Some(ref mut v) => { - for binding in &assoc_bindings { - match ast_type_binding_to_projection_predicate(this, trait_ref.clone(), - self_ty, binding) { - Ok(pp) => { v.push(pp); } - Err(ErrorReported) => { } - } - } - } - } - - trait_ref + (this.tcx().mk_substs(substs), assoc_bindings) } -fn ast_type_binding_to_projection_predicate<'tcx>( +fn ast_type_binding_to_poly_projection_predicate<'tcx>( this: &AstConv<'tcx>, - mut trait_ref: Rc>, + mut trait_ref: ty::PolyTraitRef<'tcx>, self_ty: Option>, binding: &ConvertedBinding<'tcx>) - -> Result, ErrorReported> + -> Result, ErrorReported> { let tcx = this.tcx(); @@ -755,14 +825,14 @@ fn ast_type_binding_to_projection_predicate<'tcx>( // We want to produce `>::T == foo`. // 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, + if this.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { + return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+ + projection_ty: ty::ProjectionTy { // | + trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+ item_name: binding.item_name, }, ty: binding.ty, - }); + })); } // Otherwise, we have to walk through the supertraits to find @@ -775,16 +845,18 @@ fn ast_type_binding_to_projection_predicate<'tcx>( 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 dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+ + assert!(dummy_substs.self_ty().is_none()); // | + dummy_substs.types.push(SelfSpace, dummy_self_ty); // | + trait_ref = ty::Binder(Rc::new(ty::TraitRef::new(trait_ref.def_id(), // <------------+ + tcx.mk_substs(dummy_substs)))); } + try!(this.ensure_super_predicates(binding.span, trait_ref.def_id())); + let mut candidates: Vec = - traits::supertraits(tcx, trait_ref.to_poly_trait_ref()) - .filter(|r| trait_defines_associated_type_named(this, r.def_id(), binding.item_name)) + traits::supertraits(tcx, trait_ref.clone()) + .filter(|r| this.trait_defines_associated_type_named(r.def_id(), binding.item_name)) .collect(); // If converting for an object type, then remove the dummy-ty from `Self` now. @@ -818,95 +890,48 @@ fn ast_type_binding_to_projection_predicate<'tcx>( } }; - if ty::binds_late_bound_regions(tcx, &candidate) { - span_err!(tcx.sess, binding.span, E0219, - "associated type `{}` defined in higher-ranked supertrait `{}`", - token::get_name(binding.item_name), - candidate.user_string(tcx)); - return Err(ErrorReported); - } - - Ok(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - trait_ref: candidate.0, + Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+ + projection_ty: ty::ProjectionTy { // | + trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+ item_name: binding.item_name, }, ty: binding.ty, - }) + })) } -pub fn ast_path_to_ty<'tcx>( +fn ast_path_to_ty<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, did: ast::DefId, - path: &ast::Path) - -> TypeAndSubsts<'tcx> + item_segment: &ast::PathSegment) + -> Ty<'tcx> { let tcx = this.tcx(); - let ty::TypeScheme { - generics, - ty: decl_ty - } = this.get_item_type_scheme(did); + let (generics, decl_ty) = match this.get_item_type_scheme(span, did) { + Ok(ty::TypeScheme { generics, ty: decl_ty }) => { + (generics, decl_ty) + } + Err(ErrorReported) => { + return tcx.types.err; + } + }; let substs = ast_path_substs_for_ty(this, rscope, + span, + param_mode, &generics, - path); - let ty = decl_ty.subst(tcx, &substs); - TypeAndSubsts { substs: substs, ty: ty } -} + item_segment); -/// 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>( - this: &AstConv<'tcx>, - rscope: &RegionScope, - ast_ty: &ast::Ty) - -> Option> { - match ast_ty_to_prim_ty(this.tcx(), ast_ty) { - Some(typ) => return Some(typ), - None => {} + // FIXME(#12938): This is a hack until we have full support for DST. + if Some(did) == this.tcx().lang_items.owned_box() { + assert_eq!(substs.types.len(TypeSpace), 1); + return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0)); } - match ast_ty.node { - ast::TyPath(ref path, id) => { - let a_def = match this.tcx().def_map.borrow().get(&id) { - None => { - this.tcx() - .sess - .span_bug(ast_ty.span, - &format!("unbound path {}", - path.repr(this.tcx()))[]) - } - Some(&d) => d - }; - - // FIXME(#12938): This is a hack until we have full support for - // DST. - match a_def { - def::DefTy(did, _) | - def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => { - let ty = ast_path_to_ty(this, rscope, did, path).ty; - match ty.sty { - ty::ty_struct(struct_def_id, ref substs) => { - assert_eq!(struct_def_id, did); - assert_eq!(substs.types.len(TypeSpace), 1); - let referent_ty = *substs.types.get(TypeSpace, 0); - Some(ty::mk_uniq(this.tcx(), referent_ty)) - } - _ => { - this.tcx().sess.span_bug( - path.span, - &format!("converting `Box` to `{}`", - ty.repr(this.tcx()))[]); - } - } - } - _ => None - } - } - _ => None - } + decl_ty.subst(this.tcx(), &substs) } type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); @@ -929,14 +954,20 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, */ match ty.node { - ast::TyPath(ref path, id) => { - match this.tcx().def_map.borrow().get(&id) { - Some(&def::DefTrait(trait_def_id)) => { + ast::TyPath(None, ref path) => { + let def = match this.tcx().def_map.borrow().get(&ty.id) { + Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def), + _ => None + }; + match def { + Some(def::DefTrait(trait_def_id)) => { let mut projection_bounds = Vec::new(); let trait_ref = object_path_to_poly_trait_ref(this, rscope, + path.span, + PathParamMode::Explicit, trait_def_id, - path, + path.segments.last().unwrap(), &mut projection_bounds); Ok((trait_ref, projection_bounds)) } @@ -952,14 +983,14 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, pprust::ty_to_string(ty)); match ty.node { ast::TyRptr(None, ref mut_ty) => { - span_help!(this.tcx().sess, ty.span, + fileline_help!(this.tcx().sess, ty.span, "perhaps you meant `&{}({} +{})`? (per RFC 438)", ppaux::mutability_to_string(mut_ty.mutbl), pprust::ty_to_string(&*mut_ty.ty), pprust::bounds_to_string(bounds)); } ast::TyRptr(Some(ref lt), ref mut_ty) => { - span_help!(this.tcx().sess, ty.span, + fileline_help!(this.tcx().sess, ty.span, "perhaps you meant `&{} {}({} +{})`? (per RFC 438)", pprust::lifetime_to_string(lt), ppaux::mutability_to_string(mut_ty.mutbl), @@ -968,7 +999,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>, } _ => { - span_help!(this.tcx().sess, ty.span, + fileline_help!(this.tcx().sess, ty.span, "perhaps you forgot parentheses? (per RFC 438)"); } } @@ -999,45 +1030,89 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>, result } +fn report_ambiguous_associated_type(tcx: &ty::ctxt, + span: Span, + type_str: &str, + trait_str: &str, + name: &str) { + span_err!(tcx.sess, span, E0223, + "ambiguous associated type; specify the type using the syntax \ + `<{} as {}>::{}`", + type_str, trait_str, name); +} + +// Create a type from a a path to an associated type. +// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C +// and item_segment is the path segment for D. We return a type and a def for +// the whole path. +// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type +// parameter or Self. fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, - ast_ty: &ast::Ty, - provenance: def::TyParamProvenance, - assoc_name: ast::Name) - -> Ty<'tcx> + span: Span, + ty: Ty<'tcx>, + ty_path_def: def::Def, + item_segment: &ast::PathSegment) + -> (Ty<'tcx>, def::Def) { 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: - let ty_param_defs = tcx.ty_param_defs.borrow(); - let ty_param_def = &ty_param_defs[ty_param_def_id.node]; - ty_param_name = ty_param_def.name; - - // FIXME(#20300) -- search where clauses, not bounds - suitable_bounds = - traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds) - .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name)) - .collect(); + let assoc_name = item_segment.identifier.name; + + debug!("associated_path_def_to_ty: {}::{}", ty.repr(tcx), token::get_name(assoc_name)); + + check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); + + // Check that the path prefix given by ty/ty_path_def is a type parameter/Self. + match (&ty.sty, ty_path_def) { + (&ty::ty_param(_), def::DefTyParam(..)) | + (&ty::ty_param(_), def::DefSelfTy(_)) => {} + _ => { + report_ambiguous_associated_type(tcx, + span, + &ty.user_string(tcx), + "Trait", + &token::get_name(assoc_name)); + return (tcx.types.err, ty_path_def); + } } + let ty_param_node_id = ty_path_def.local_node_id(); + let ty_param_name = tcx.ty_param_defs.borrow().get(&ty_param_node_id).unwrap().name; + + let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) { + Ok(v) => v, + Err(ErrorReported) => { + return (tcx.types.err, ty_path_def); + } + }; + + // Ensure the super predicates and stop if we encountered an error. + if bounds.iter().any(|b| this.ensure_super_predicates(span, b.def_id()).is_err()) { + return (this.tcx().types.err, ty_path_def); + } + + // Check that there is exactly one way to find an associated type with the + // correct name. + let mut suitable_bounds: Vec<_> = + traits::transitive_bounds(tcx, &bounds) + .filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name)) + .collect(); + if suitable_bounds.len() == 0 { - span_err!(tcx.sess, ast_ty.span, E0220, + span_err!(tcx.sess, span, E0220, "associated type `{}` not found for type parameter `{}`", token::get_name(assoc_name), token::get_name(ty_param_name)); - return this.tcx().types.err; + return (this.tcx().types.err, ty_path_def); } if suitable_bounds.len() > 1 { - span_err!(tcx.sess, ast_ty.span, E0221, + span_err!(tcx.sess, span, E0221, "ambiguous associated type `{}` in bounds of `{}`", token::get_name(assoc_name), token::get_name(ty_param_name)); for suitable_bound in &suitable_bounds { - span_note!(this.tcx().sess, ast_ty.span, + span_note!(this.tcx().sess, span, "associated type `{}` could derive from `{}`", token::get_name(ty_param_name), suitable_bound.user_string(this.tcx())); @@ -1045,46 +1120,71 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, } let suitable_bound = suitable_bounds.pop().unwrap().clone(); - return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name); -} + let trait_did = suitable_bound.0.def_id; + + let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name); + + let item_did = if trait_did.krate == ast::LOCAL_CRATE { + // `ty::trait_items` used below requires information generated + // by type collection, which may be in progress at this point. + match this.tcx().map.expect_item(trait_did.node).node { + ast::ItemTrait(_, _, _, ref trait_items) => { + let item = trait_items.iter() + .find(|i| i.ident.name == assoc_name) + .expect("missing associated type"); + ast_util::local_def(item.id) + } + _ => unreachable!() + } + } else { + let trait_items = ty::trait_items(this.tcx(), trait_did); + let item = trait_items.iter().find(|i| i.name() == assoc_name); + item.expect("missing associated type").def_id() + }; -fn trait_defines_associated_type_named(this: &AstConv, - trait_def_id: ast::DefId, - assoc_name: ast::Name) - -> bool -{ - let tcx = this.tcx(); - let trait_def = ty::lookup_trait_def(tcx, trait_def_id); - trait_def.associated_type_names.contains(&assoc_name) + (ty, def::DefAssociatedTy(trait_did, item_did)) } fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, rscope: &RegionScope, - ast_ty: &ast::Ty, // the TyQPath - qpath: &ast::QPath) + span: Span, + param_mode: PathParamMode, + opt_self_ty: Option>, + trait_def_id: ast::DefId, + trait_segment: &ast::PathSegment, + item_segment: &ast::PathSegment) -> Ty<'tcx> { - debug!("qpath_to_ty(ast_ty={})", - ast_ty.repr(this.tcx())); + let tcx = this.tcx(); - let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type); + check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS); - debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx())); + let self_ty = if let Some(ty) = opt_self_ty { + ty + } else { + let path_str = ty::item_path_str(tcx, trait_def_id); + report_ambiguous_associated_type(tcx, + span, + "Type", + &path_str, + &token::get_ident(item_segment.identifier)); + return tcx.types.err; + }; - let trait_ref = instantiate_trait_ref(this, - rscope, - &*qpath.trait_ref, - Some(self_type), - None); + debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx)); - debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx())); + let trait_ref = + ast_path_to_mono_trait_ref(this, + rscope, + span, + param_mode, + trait_def_id, + Some(self_ty), + trait_segment); - // `::U` shouldn't parse right now. - assert!(qpath.item_path.parameters.is_empty()); + debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx)); - return this.projected_ty(ast_ty.span, - trait_ref, - qpath.item_path.identifier.name); + this.projected_ty(span, trait_ref, item_segment.identifier.name) } /// Convert a type supplied as value for a type argument from AST into our @@ -1120,6 +1220,115 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>, } } +// Note that both base_segments and assoc_segments may be empty, although not at +// the same time. +pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>, + rscope: &RegionScope, + span: Span, + param_mode: PathParamMode, + def: &def::Def, + opt_self_ty: Option>, + base_segments: &[ast::PathSegment], + assoc_segments: &[ast::PathSegment]) + -> Ty<'tcx> { + let tcx = this.tcx(); + + let base_ty = match *def { + def::DefTrait(trait_def_id) => { + // N.B. this case overlaps somewhat with + // TyObjectSum, see that fn for details + let mut projection_bounds = Vec::new(); + + let trait_ref = object_path_to_poly_trait_ref(this, + rscope, + span, + param_mode, + trait_def_id, + base_segments.last().unwrap(), + &mut projection_bounds); + + check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + trait_ref_to_object_type(this, + rscope, + span, + trait_ref, + projection_bounds, + &[]) + } + def::DefTy(did, _) | def::DefStruct(did) => { + check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS); + ast_path_to_ty(this, rscope, span, + param_mode, did, + base_segments.last().unwrap()) + } + def::DefTyParam(space, index, _, name) => { + check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS); + ty::mk_param(tcx, space, index, name) + } + def::DefSelfTy(_) => { + // N.b.: resolve guarantees that the this type only appears in a + // trait, which we rely upon in various places when creating + // substs. + check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS); + ty::mk_self_type(tcx) + } + def::DefAssociatedTy(trait_did, _) => { + check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS); + qpath_to_ty(this, + rscope, + span, + param_mode, + opt_self_ty, + trait_did, + &base_segments[base_segments.len()-2], + base_segments.last().unwrap()) + } + def::DefMod(id) => { + // Used as sentinel by callers to indicate the `::A::B::C` form. + // FIXME(#22519) This part of the resolution logic should be + // avoided entirely for that form, once we stop needed a Def + // for `associated_path_def_to_ty`. + + if !base_segments.is_empty() { + span_err!(tcx.sess, + span, + E0247, + "found module name used as a type: {}", + tcx.map.node_to_string(id.node)); + return this.tcx().types.err; + } + + opt_self_ty.expect("missing T in ::a::b::c") + } + def::DefPrimTy(prim_ty) => { + prim_ty_to_ty(tcx, base_segments, prim_ty) + } + _ => { + span_err!(tcx.sess, span, E0248, + "found value name used as a type: {:?}", *def); + return this.tcx().types.err; + } + }; + + // If any associated type segments remain, attempt to resolve them. + let mut ty = base_ty; + let mut def = *def; + for segment in assoc_segments { + if ty.sty == ty::ty_err { + break; + } + // This is pretty bad (it will fail except for T::A and Self::A). + let (a_ty, a_def) = associated_path_def_to_ty(this, + span, + ty, + def, + segment); + ty = a_ty; + def = a_def; + } + ty +} + /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, @@ -1132,189 +1341,145 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, let tcx = this.tcx(); - let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut(); - match ast_ty_to_ty_cache.get(&ast_ty.id) { - Some(&ty::atttce_resolved(ty)) => return ty, - Some(&ty::atttce_unresolved) => { - span_fatal!(tcx.sess, ast_ty.span, E0246, - "illegal recursive type; insert an enum \ - or struct in the cycle, if this is \ - desired"); - } - None => { /* go on */ } + if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) { + return ty; } - ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved); - drop(ast_ty_to_ty_cache); - let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| { - match ast_ty.node { - ast::TyVec(ref ty) => { - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) - } - ast::TyObjectSum(ref ty, ref bounds) => { - match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) { - Ok((trait_ref, projection_bounds)) => { - trait_ref_to_object_type(this, - rscope, - ast_ty.span, - trait_ref, - projection_bounds, - &bounds[..]) - } - Err(ErrorReported) => { - this.tcx().types.err - } + let typ = match ast_ty.node { + ast::TyVec(ref ty) => { + ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) + } + ast::TyObjectSum(ref ty, ref bounds) => { + match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) { + Ok((trait_ref, projection_bounds)) => { + trait_ref_to_object_type(this, + rscope, + ast_ty.span, + trait_ref, + projection_bounds, + bounds) } - } - ast::TyPtr(ref mt) => { - ty::mk_ptr(tcx, ty::mt { - ty: ast_ty_to_ty(this, rscope, &*mt.ty), - mutbl: mt.mutbl - }) - } - ast::TyRptr(ref region, ref mt) => { - let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region); - debug!("ty_rptr r={}", r.repr(this.tcx())); - let rscope1 = - &ObjectLifetimeDefaultRscope::new( - rscope, - Some(ty::ObjectLifetimeDefault::Specific(r))); - let t = ast_ty_to_ty(this, rscope1, &*mt.ty); - ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl}) - } - ast::TyTup(ref fields) => { - let flds = fields.iter() - .map(|t| ast_ty_to_ty(this, rscope, &**t)) - .collect(); - ty::mk_tup(tcx, flds) - } - ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ), - ast::TyBareFn(ref bf) => { - if bf.decl.variadic && bf.abi != abi::C { - span_err!(tcx.sess, ast_ty.span, E0222, - "variadic function must have C calling convention"); + Err(ErrorReported) => { + this.tcx().types.err } - 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::TyPolyTraitRef(ref bounds) => { - conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..]) + } + ast::TyPtr(ref mt) => { + ty::mk_ptr(tcx, ty::mt { + ty: ast_ty_to_ty(this, rscope, &*mt.ty), + mutbl: mt.mutbl + }) + } + ast::TyRptr(ref region, ref mt) => { + let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region); + debug!("ty_rptr r={}", r.repr(this.tcx())); + let rscope1 = + &ObjectLifetimeDefaultRscope::new( + rscope, + Some(ty::ObjectLifetimeDefault::Specific(r))); + let t = ast_ty_to_ty(this, rscope1, &*mt.ty); + ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl}) + } + ast::TyTup(ref fields) => { + let flds = fields.iter() + .map(|t| ast_ty_to_ty(this, rscope, &**t)) + .collect(); + ty::mk_tup(tcx, flds) + } + ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ), + ast::TyBareFn(ref bf) => { + if bf.decl.variadic && bf.abi != abi::C { + span_err!(tcx.sess, ast_ty.span, E0222, + "variadic function must have C calling convention"); } - ast::TyPath(ref path, id) => { - let a_def = match tcx.def_map.borrow().get(&id) { - None => { - tcx.sess - .span_bug(ast_ty.span, - &format!("unbound path {}", - path.repr(tcx))[]) - } - Some(&d) => d - }; - match a_def { - def::DefTrait(trait_def_id) => { - // N.B. this case overlaps somewhat with - // TyObjectSum, see that fn for details - let mut projection_bounds = Vec::new(); - - let trait_ref = object_path_to_poly_trait_ref(this, - rscope, - trait_def_id, - path, - &mut projection_bounds); - - trait_ref_to_object_type(this, rscope, path.span, - trait_ref, projection_bounds, &[]) - } - def::DefTy(did, _) | def::DefStruct(did) => { - ast_path_to_ty(this, rscope, did, path).ty - } - def::DefTyParam(space, index, _, name) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_param(tcx, space, index, name) - } - def::DefSelfTy(_) => { - // n.b.: resolve guarantees that the this type only appears in a - // trait, which we rely upon in various places when creating - // substs - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - ty::mk_self_type(tcx) - } - def::DefMod(id) => { - span_fatal!(tcx.sess, ast_ty.span, E0247, - "found module name used as a type: {}", - tcx.map.node_to_string(id.node)); - } - def::DefPrimTy(_) => { - panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call"); - } - def::DefAssociatedTy(trait_type_id) => { - let path_str = tcx.map.path_to_string( - tcx.map.get_parent(trait_type_id.node)); - span_err!(tcx.sess, ast_ty.span, E0223, - "ambiguous associated \ - type; specify the type \ - using the syntax `::{}`", - path_str, - &token::get_ident( - path.segments - .last() - .unwrap() - .identifier)); - this.tcx().types.err - } - def::DefAssociatedPath(provenance, assoc_ident) => { - associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name) - } - _ => { - span_fatal!(tcx.sess, ast_ty.span, E0248, - "found value name used \ - as a type: {:?}", - a_def); - } + 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::TyPolyTraitRef(ref bounds) => { + conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) + } + ast::TyPath(ref maybe_qself, ref path) => { + let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { + d + } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { + // Create some fake resolution that can't possibly be a type. + def::PathResolution { + base_def: def::DefMod(ast_util::local_def(ast::CRATE_NODE_ID)), + last_private: LastMod(AllPublic), + depth: path.segments.len() } + } else { + tcx.sess.span_bug(ast_ty.span, + &format!("unbound path {}", ast_ty.repr(tcx))) + }; + let def = path_res.base_def; + let base_ty_end = path.segments.len() - path_res.depth; + let opt_self_ty = maybe_qself.as_ref().map(|qself| { + ast_ty_to_ty(this, rscope, &qself.ty) + }); + let ty = finish_resolving_def_to_ty(this, + rscope, + ast_ty.span, + PathParamMode::Explicit, + &def, + opt_self_ty, + &path.segments[..base_ty_end], + &path.segments[base_ty_end..]); + + if path_res.depth != 0 && ty.sty != ty::ty_err { + // Write back the new resolution. + tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution { + base_def: def, + last_private: path_res.last_private, + depth: 0 + }); } - ast::TyQPath(ref qpath) => { - qpath_to_ty(this, rscope, ast_ty, &**qpath) - } - ast::TyFixedLengthVec(ref ty, ref e) => { - match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) { - Ok(ref r) => { - match *r { - const_eval::const_int(i) => - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), - Some(i as uint)), - const_eval::const_uint(i) => - ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), - Some(i as uint)), - _ => { - span_fatal!(tcx.sess, ast_ty.span, E0249, - "expected constant expr for array length"); - } + + ty + } + ast::TyFixedLengthVec(ref ty, ref e) => { + match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.usize)) { + Ok(r) => { + match r { + const_eval::const_int(i) => + ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), + Some(i as usize)), + const_eval::const_uint(i) => + ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), + Some(i as usize)), + _ => { + span_err!(tcx.sess, ast_ty.span, E0249, + "expected constant expr for array length"); + this.tcx().types.err } } - Err(ref r) => { - span_fatal!(tcx.sess, ast_ty.span, E0250, - "expected constant expr for array \ - length: {}", - *r); + } + Err(ref r) => { + let subspan = + ast_ty.span.lo <= r.span.lo && r.span.hi <= ast_ty.span.hi; + span_err!(tcx.sess, r.span, E0250, + "array length constant evaluation error: {}", + r.description()); + if !subspan { + span_note!(tcx.sess, ast_ty.span, "for array length here") } + this.tcx().types.err } } - ast::TyTypeof(ref _e) => { - tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented"); - } - ast::TyInfer => { - // TyInfer also appears as the type of arguments or return - // values in a ExprClosure, or as - // the type of local variables. Both of these cases are - // handled specially and will not descend into this routine. - this.ty_infer(ast_ty.span) - } } - }); + ast::TyTypeof(ref _e) => { + tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented"); + } + ast::TyInfer => { + // TyInfer also appears as the type of arguments or return + // values in a ExprClosure, or as + // the type of local variables. Both of these cases are + // handled specially and will not descend into this routine. + this.ty_infer(ast_ty.span) + } + }; - tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ)); + tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, typ); return typ; } @@ -1337,22 +1502,19 @@ struct SelfInfo<'a, 'tcx> { } 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) + sig: &ast::MethodSig, + untransformed_self_ty: Ty<'tcx>) -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) { let self_info = Some(SelfInfo { untransformed_self_ty: untransformed_self_ty, - explicit_self: explicit_self, + explicit_self: &sig.explicit_self, }); let (bare_fn_ty, optional_explicit_self_category) = ty_of_method_or_bare_fn(this, - unsafety, - abi, + sig.unsafety, + sig.abi, self_info, - decl); + &sig.decl); (bare_fn_ty, optional_explicit_self_category.unwrap()) } @@ -1419,7 +1581,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, let input_params = if self_ty.is_some() { &decl.inputs[1..] } else { - &decl.inputs[] + &decl.inputs[..] }; let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None)); let input_pats: Vec = input_params.iter() @@ -1541,7 +1703,7 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>, } }; - fn count_modifiers(ty: Ty) -> uint { + fn count_modifiers(ty: Ty) -> usize { match ty.sty { ty::ty_rptr(_, mt) => count_modifiers(mt.ty) + 1, ty::ty_uniq(t) => count_modifiers(t) + 1, @@ -1731,6 +1893,10 @@ fn compute_object_lifetime_bound<'tcx>( return ast_region_to_region(tcx, r); } + if let Err(ErrorReported) = this.ensure_super_predicates(span,principal_trait_ref.def_id()) { + return ty::ReStatic; + } + // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = @@ -1816,38 +1982,24 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt, let mut builtin_bounds = ty::empty_builtin_bounds(); let mut region_bounds = Vec::new(); let mut trait_bounds = Vec::new(); - let mut trait_def_ids = DefIdMap(); for ast_bound in ast_bounds { match *ast_bound { ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => { - match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { + match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { def::DefTrait(trait_did) => { - match trait_def_ids.get(&trait_did) { - // Already seen this trait. We forbid - // duplicates in the list (for some - // reason). - Some(span) => { - span_err!( - tcx.sess, b.trait_ref.path.span, E0127, - "trait `{}` already appears in the \ - list of bounds", - b.trait_ref.path.user_string(tcx)); - tcx.sess.span_note( - *span, - "previous appearance is here"); - - continue; - } - - None => { } - } - - trait_def_ids.insert(trait_did, b.trait_ref.path.span); - if ty::try_add_builtin_trait(tcx, trait_did, &mut builtin_bounds) { - // FIXME(#20302) -- we should check for things like Copy + let segments = &b.trait_ref.path.segments; + let parameters = &segments[segments.len() - 1].parameters; + if parameters.types().len() > 0 { + check_type_argument_count(tcx, b.trait_ref.path.span, + parameters.types().len(), 0, 0); + } + if parameters.lifetimes().len() > 0{ + report_lifetime_number_error(tcx, b.trait_ref.path.span, + parameters.lifetimes().len(), 0); + } continue; // success } } @@ -1880,3 +2032,34 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>, "associated type bindings are not allowed here"); } } + +fn check_type_argument_count(tcx: &ty::ctxt, span: Span, supplied: usize, + required: usize, accepted: usize) { + if supplied < required { + let expected = if required < accepted { + "expected at least" + } else { + "expected" + }; + span_err!(tcx.sess, span, E0243, + "wrong number of type arguments: {} {}, found {}", + expected, required, supplied); + } else if supplied > accepted { + let expected = if required < accepted { + "expected at most" + } else { + "expected" + }; + span_err!(tcx.sess, span, E0244, + "wrong number of type arguments: {} {}, found {}", + expected, + accepted, + supplied); + } +} + +fn report_lifetime_number_error(tcx: &ty::ctxt, span: Span, number: usize, expected: usize) { + span_err!(tcx.sess, span, E0107, + "wrong number of lifetime parameters: expected {}, found {}", + expected, number); +} diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 34c52981b7..8f1a67723c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -12,7 +12,7 @@ use middle::const_eval; use middle::def; use middle::infer; use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const}; -use middle::subst::{Substs}; +use middle::subst::Substs; use middle::ty::{self, Ty}; use check::{check_expr, check_expr_has_type, check_expr_with_expectation}; use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation}; @@ -48,7 +48,23 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, ast::PatLit(ref lt) => { check_expr(fcx, &**lt); let expr_ty = fcx.expr_ty(&**lt); - fcx.write_ty(pat.id, expr_ty); + + // Byte string patterns behave the same way as array patterns + // They can denote both statically and dynamically sized byte arrays + let mut pat_ty = expr_ty; + if let ast::ExprLit(ref lt) = lt.node { + if let ast::LitBinary(_) = lt.node { + let expected_ty = structurally_resolved_type(fcx, pat.span, expected); + if let ty::ty_rptr(_, mt) = expected_ty.sty { + if let ty::ty_vec(_, None) = mt.ty.sty { + pat_ty = ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic), + ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable }) + } + } + } + } + + fcx.write_ty(pat.id, pat_ty); // somewhat surprising: in this case, the subtyping // relation goes the opposite way as the other @@ -62,7 +78,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // &'static str <: expected // // that's equivalent to there existing a LUB. - demand::suptype(fcx, pat.span, expected, expr_ty); + demand::suptype(fcx, pat.span, expected, pat_ty); } ast::PatRange(ref begin, ref end) => { check_expr(fcx, &**begin); @@ -103,7 +119,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, 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_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id(); let const_scheme = ty::lookup_item_type(tcx, const_did); assert!(const_scheme.generics.is_empty()); let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, @@ -147,7 +163,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // if there are multiple arms, make sure they all agree on // what the type of the binding `x` ought to be - let canon_id = pcx.map[path.node]; + let canon_id = *pcx.map.get(&path.node).unwrap(); if canon_id != pat.id { let ct = fcx.local_ty(pat.span, canon_id); demand::eqtype(fcx, pat.span, ct, typ); @@ -271,10 +287,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // (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: + // 1. There is no loss of expressiveness here, though it does + // cause some inconvenience. What we are saying is that the type + // of `x` becomes *exactly* what is expected. This can cause unnecessary + // errors in some cases, such as this one: + // it will cause errors in a case like this: // // ``` // fn foo<'x>(x: &'x int) { @@ -345,8 +362,21 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match_src: ast::MatchSource) { let tcx = fcx.ccx.tcx; - let discrim_ty = fcx.infcx().next_ty_var(); - check_expr_has_type(fcx, discrim, discrim_ty); + // Not entirely obvious: if matches may create ref bindings, we + // want to use the *precise* type of the discriminant, *not* some + // supertype, as the "discriminant type" (issue #23116). + let contains_ref_bindings = arms.iter().any(|a| tcx.arm_contains_ref_binding(a)); + let discrim_ty; + if contains_ref_bindings { + check_expr(fcx, discrim); + discrim_ty = fcx.expr_ty(discrim); + } else { + // ...but otherwise we want to use any supertype of the + // discriminant. This is sort of a workaround, see note (*) in + // `check_pat` for some details. + discrim_ty = fcx.infcx().next_ty_var(); + check_expr_has_type(fcx, discrim, discrim_ty); + }; // Typecheck the patterns first, so that we get types for all the // bindings. @@ -433,7 +463,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - let def = tcx.def_map.borrow()[pat.id].clone(); + let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); let (enum_def_id, variant_def_id) = match def { def::DefTrait(_) => { let name = pprust::path_to_string(path); @@ -470,7 +500,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat, }; instantiate_path(pcx.fcx, - path, + &path.segments, ty::lookup_item_type(tcx, enum_def_id), &ty::lookup_predicates(tcx, enum_def_id), None, @@ -502,7 +532,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - let def = tcx.def_map.borrow()[pat.id].clone(); + let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); let enum_def = def.variant_def_ids() .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def); @@ -517,7 +547,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, } else { ctor_scheme }; - instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id); + instantiate_path(pcx.fcx, &path.segments, + path_scheme, &ctor_predicates, + None, def, pat.span, pat.id); let pat_ty = fcx.node_ty(pat.id); demand::eqtype(fcx, pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 0ad15456df..3f9c14e0af 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -9,7 +9,6 @@ // 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; @@ -63,7 +62,7 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id: span_err!(tcx.sess, span, E0174, "explicit use of unboxed closure method `{}` is experimental", method); - span_help!(tcx.sess, span, + fileline_help!(tcx.sess, span, "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); } } @@ -84,9 +83,7 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, UnresolvedTypeAction::Error, 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) + try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx) }); match result { @@ -120,13 +117,15 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr: &'tcx ast::Expr, callee_expr: &'tcx ast::Expr, adjusted_ty: Ty<'tcx>, - autoderefref: ty::AutoDerefRef<'tcx>) + autoderefs: usize) -> Option> { - debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefref={})", + debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefs={})", call_expr.repr(fcx.tcx()), adjusted_ty.repr(fcx.tcx()), - autoderefref.repr(fcx.tcx())); + autoderefs); + + let autoderefref = ty::AutoDerefRef { autoderefs: autoderefs, autoref: None }; // 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 { @@ -137,7 +136,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, return Some(CallStep::Builtin); } - ty::ty_closure(def_id, _, substs) => { + ty::ty_closure(def_id, substs) => { assert_eq!(def_id.krate, ast::LOCAL_CRATE); // Check whether this is a call to a closure where we @@ -152,16 +151,28 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, &closure_ty.sig).0; fcx.record_deferred_call_resolution( def_id, - box CallResolution {call_expr: call_expr, - callee_expr: callee_expr, - adjusted_ty: adjusted_ty, - autoderefref: autoderefref, - fn_sig: fn_sig.clone(), - closure_def_id: def_id}); + Box::new(CallResolution {call_expr: call_expr, + callee_expr: callee_expr, + adjusted_ty: adjusted_ty, + autoderefref: autoderefref, + fn_sig: fn_sig.clone(), + closure_def_id: def_id})); return Some(CallStep::DeferredClosure(fn_sig)); } } + // Hack: we know that there are traits implementing Fn for &F + // where F:Fn and so forth. In the particular case of types + // like `x: &mut FnMut()`, if there is a call `x()`, we would + // normally translate to `FnMut::call_mut(&mut x, ())`, but + // that winds up requiring `mut x: &mut FnMut()`. A little + // over the top. The simplest fix by far is to just ignore + // this case and deref again, so we wind up with + // `FnMut::call_mut(&mut *x, ())`. + ty::ty_rptr(..) if autoderefs == 0 => { + return None; + } + _ => {} } @@ -258,7 +269,6 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, &fn_sig.inputs, &expected_arg_tys[..], arg_exprs, - AutorefArgs::No, fn_sig.variadic, TupleArgumentsFlag::DontTupleArguments); @@ -288,7 +298,6 @@ fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, &*fn_sig.inputs, &*expected_arg_tys, arg_exprs, - AutorefArgs::No, fn_sig.variadic, TupleArgumentsFlag::TupleArguments); @@ -308,7 +317,6 @@ fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_callee.ty, callee_expr, arg_exprs, - AutorefArgs::No, TupleArgumentsFlag::TupleArguments, expected); write_call(fcx, call_expr, output_type); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 0b7c5b04aa..d2a06fcf99 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -16,7 +16,7 @@ use astconv; use middle::region; use middle::subst; use middle::ty::{self, ToPolyTraitRef, Ty}; -use rscope::RegionScope; +use std::cmp; use syntax::abi; use syntax::ast; use syntax::ast_util; @@ -61,17 +61,8 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, abi::RustCall, expected_sig); - let region = match fcx.anon_regions(expr.span, 1) { - Err(_) => { - fcx.ccx.tcx.sess.span_bug(expr.span, - "can't make anon regions here?!") - } - Ok(regions) => regions[0], - }; - let closure_type = ty::mk_closure(fcx.ccx.tcx, expr_def_id, - fcx.ccx.tcx.mk_region(region), fcx.ccx.tcx.mk_substs( fcx.inh.param_env.free_substs.clone())); @@ -119,15 +110,11 @@ fn deduce_expectations_from_expected_type<'a,'tcx>( ty::ty_trait(ref object_type) => { let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(), fcx.tcx().types.err); - let expectations = - proj_bounds.iter() - .filter_map(|pb| deduce_expectations_from_projection(fcx, pb)) - .next(); - - match expectations { - Some((sig, kind)) => (Some(sig), Some(kind)), - None => (None, None) - } + let sig = proj_bounds.iter() + .filter_map(|pb| deduce_sig_from_projection(fcx, pb)) + .next(); + let kind = fcx.tcx().lang_items.fn_trait_kind(object_type.principal_def_id()); + (sig, kind) } ty::ty_infer(ty::TyVar(vid)) => { deduce_expectations_from_obligations(fcx, vid) @@ -146,7 +133,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>( let fulfillment_cx = fcx.inh.fulfillment_cx.borrow(); // Here `expected_ty` is known to be a type inference variable. - let expected_sig_and_kind = + let expected_sig = fulfillment_cx .pending_obligations() .iter() @@ -160,7 +147,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>( ty::Predicate::Projection(ref proj_predicate) => { let trait_ref = proj_predicate.to_poly_trait_ref(); self_type_matches_expected_vid(fcx, trait_ref, expected_vid) - .and_then(|_| deduce_expectations_from_projection(fcx, proj_predicate)) + .and_then(|_| deduce_sig_from_projection(fcx, proj_predicate)) } _ => { None @@ -169,14 +156,10 @@ fn deduce_expectations_from_obligations<'a,'tcx>( }) .next(); - match expected_sig_and_kind { - Some((sig, kind)) => { return (Some(sig), Some(kind)); } - None => { } - } - // Even if we can't infer the full signature, we may be able to // infer the kind. This can occur if there is a trait-reference - // like `F : Fn`. + // like `F : Fn`. Note that due to subtyping we could encounter + // many viable options, so pick the most restrictive. let expected_kind = fulfillment_cx .pending_obligations() @@ -193,54 +176,61 @@ fn deduce_expectations_from_obligations<'a,'tcx>( .and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid)) .and_then(|trait_ref| fcx.tcx().lang_items.fn_trait_kind(trait_ref.def_id())) }) - .next(); + .fold(None, pick_most_restrictive_closure_kind); - (None, expected_kind) + (expected_sig, expected_kind) +} + +fn pick_most_restrictive_closure_kind(best: Option, + cur: ty::ClosureKind) + -> Option +{ + match best { + None => Some(cur), + Some(best) => Some(cmp::min(best, cur)) + } } /// Given a projection like "::Result == Y", we can deduce /// everything we need to know about a closure. -fn deduce_expectations_from_projection<'a,'tcx>( +fn deduce_sig_from_projection<'a,'tcx>( fcx: &FnCtxt<'a,'tcx>, projection: &ty::PolyProjectionPredicate<'tcx>) - -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)> + -> Option> { let tcx = fcx.tcx(); - debug!("deduce_expectations_from_projection({})", + debug!("deduce_sig_from_projection({})", projection.repr(tcx)); let trait_ref = projection.to_poly_trait_ref(); - let kind = match tcx.lang_items.fn_trait_kind(trait_ref.def_id()) { - Some(k) => k, - None => { return None; } - }; - - debug!("found object type {:?}", kind); + if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() { + return None; + } let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0); let arg_param_ty = fcx.infcx().resolve_type_vars_if_possible(&arg_param_ty); - debug!("arg_param_ty {}", arg_param_ty.repr(tcx)); + debug!("deduce_sig_from_projection: arg_param_ty {}", arg_param_ty.repr(tcx)); let input_tys = match arg_param_ty.sty { ty::ty_tup(ref tys) => { (*tys).clone() } _ => { return None; } }; - debug!("input_tys {}", input_tys.repr(tcx)); + debug!("deduce_sig_from_projection: input_tys {}", input_tys.repr(tcx)); let ret_param_ty = projection.0.ty; let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty); - debug!("ret_param_ty {}", ret_param_ty.repr(tcx)); + debug!("deduce_sig_from_projection: ret_param_ty {}", ret_param_ty.repr(tcx)); let fn_sig = ty::FnSig { inputs: input_tys, output: ty::FnConverging(ret_param_ty), variadic: false }; - debug!("fn_sig {}", fn_sig.repr(tcx)); + debug!("deduce_sig_from_projection: fn_sig {}", fn_sig.repr(tcx)); - return Some((fn_sig, kind)); + Some(fn_sig) } fn self_type_matches_expected_vid<'a,'tcx>( @@ -258,5 +248,3 @@ fn self_type_matches_expected_vid<'a,'tcx>( _ => None, } } - - diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 04a3f423dc..ced6cec3ef 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -62,12 +62,11 @@ use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction}; -use middle::infer::{self, cres, Coercion, TypeTrace}; -use middle::infer::combine::Combine; -use middle::infer::sub::Sub; +use middle::infer::{self, Coercion}; use middle::subst; use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe}; use middle::ty::{self, mt, Ty}; +use middle::ty_relate::RelateResult; use util::common::indent; use util::ppaux; use util::ppaux::Repr; @@ -76,10 +75,10 @@ use syntax::ast; struct Coerce<'a, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'tcx>, - trace: TypeTrace<'tcx> + origin: infer::TypeOrigin, } -type CoerceResult<'tcx> = cres<'tcx, Option>>; +type CoerceResult<'tcx> = RelateResult<'tcx, Option>>; impl<'f, 'tcx> Coerce<'f, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { @@ -87,11 +86,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { - let sub = Sub(self.fcx.infcx().combine_fields(false, self.trace.clone())); - try!(sub.tys(a, b)); + try!(self.fcx.infcx().sub_types(false, self.origin.clone(), a, b)); Ok(None) // No coercion required. } + fn outlives(&self, + origin: infer::SubregionOrigin<'tcx>, + a: ty::Region, + b: ty::Region) + -> RelateResult<'tcx, ()> { + infer::mk_subr(self.fcx.infcx(), origin, b, a); + Ok(()) + } + fn unpack_actual_value(&self, a: Ty<'tcx>, f: F) -> T where F: FnOnce(Ty<'tcx>) -> T, { @@ -143,6 +150,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // require double indirection). self.coerce_from_fn_item(a, a_def_id, a_f, b) } + ty::ty_bare_fn(None, a_f) => { + // We permit coercion of fn pointers to drop the + // unsafe qualifier. + self.coerce_from_fn_pointer(a, a_f, b) + } _ => { // Otherwise, just use subtyping rules. self.subtype(a, b) @@ -179,7 +191,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { _ => return self.subtype(a, b) } - let coercion = Coercion(self.trace.clone()); + let coercion = Coercion(self.origin.span()); let r_borrow = self.fcx.infcx().next_region_var(coercion); let autoref = Some(AutoPtr(r_borrow, mutbl_b, None)); @@ -203,7 +215,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } let ty = ty::mk_rptr(self.tcx(), r_borrow, mt {ty: inner_ty, mutbl: mutbl_b}); - if let Err(err) = self.fcx.infcx().try(|_| self.subtype(ty, b)) { + if let Err(err) = self.subtype(ty, b) { if first_error.is_none() { first_error = Some(err); } @@ -247,70 +259,64 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { match (&a.sty, &b.sty) { (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => { - self.unpack_actual_value(t_a, |a| { - match self.unsize_ty(t_a, a, mt_b.ty) { - Some((ty, kind)) => { - if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) { - return Err(ty::terr_mutability); - } - - let coercion = Coercion(self.trace.clone()); - let r_borrow = self.fcx.infcx().next_region_var(coercion); - let ty = ty::mk_rptr(self.tcx(), - self.tcx().mk_region(r_borrow), - ty::mt{ty: ty, mutbl: mt_b.mutbl}); - try!(self.fcx.infcx().try(|_| self.subtype(ty, b))); - debug!("Success, coerced with AutoDerefRef(1, \ - AutoPtr(AutoUnsize({:?})))", kind); - Ok(Some(AdjustDerefRef(AutoDerefRef { - autoderefs: 1, - autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl, - Some(box AutoUnsize(kind)))) - }))) + match self.unsize_ty(t_a, mt_b.ty) { + Some((ty, kind)) => { + if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) { + return Err(ty::terr_mutability); } - _ => Err(ty::terr_mismatch) + + let coercion = Coercion(self.origin.span()); + let r_borrow = self.fcx.infcx().next_region_var(coercion); + let ty = ty::mk_rptr(self.tcx(), + self.tcx().mk_region(r_borrow), + ty::mt{ty: ty, mutbl: mt_b.mutbl}); + try!(self.subtype(ty, b)); + debug!("Success, coerced with AutoDerefRef(1, \ + AutoPtr(AutoUnsize({:?})))", kind); + Ok(Some(AdjustDerefRef(AutoDerefRef { + autoderefs: 1, + autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl, + Some(box AutoUnsize(kind)))) + }))) } - }) + _ => Err(ty::terr_mismatch) + } } (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => { - self.unpack_actual_value(t_a, |a| { - match self.unsize_ty(t_a, a, mt_b.ty) { - Some((ty, kind)) => { - if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) { - return Err(ty::terr_mutability); - } - - let ty = ty::mk_ptr(self.tcx(), - ty::mt{ty: ty, mutbl: mt_b.mutbl}); - try!(self.fcx.infcx().try(|_| self.subtype(ty, b))); - debug!("Success, coerced with AutoDerefRef(1, \ - AutoPtr(AutoUnsize({:?})))", kind); - Ok(Some(AdjustDerefRef(AutoDerefRef { - autoderefs: 1, - autoref: Some(ty::AutoUnsafe(mt_b.mutbl, - Some(box AutoUnsize(kind)))) - }))) + match self.unsize_ty(t_a, mt_b.ty) { + Some((ty, kind)) => { + if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) { + return Err(ty::terr_mutability); } - _ => Err(ty::terr_mismatch) + + let ty = ty::mk_ptr(self.tcx(), + ty::mt{ty: ty, mutbl: mt_b.mutbl}); + try!(self.subtype(ty, b)); + debug!("Success, coerced with AutoDerefRef(1, \ + AutoPtr(AutoUnsize({:?})))", kind); + Ok(Some(AdjustDerefRef(AutoDerefRef { + autoderefs: 1, + autoref: Some(ty::AutoUnsafe(mt_b.mutbl, + Some(box AutoUnsize(kind)))) + }))) } - }) + _ => Err(ty::terr_mismatch) + } } (&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => { - self.unpack_actual_value(t_a, |a| { - match self.unsize_ty(t_a, a, t_b) { - Some((ty, kind)) => { - let ty = ty::mk_uniq(self.tcx(), ty); - try!(self.fcx.infcx().try(|_| self.subtype(ty, b))); - debug!("Success, coerced with AutoDerefRef(1, \ - AutoUnsizeUniq({:?}))", kind); - Ok(Some(AdjustDerefRef(AutoDerefRef { - autoderefs: 1, - autoref: Some(ty::AutoUnsizeUniq(kind)) - }))) - } - _ => Err(ty::terr_mismatch) + match self.unsize_ty(t_a, t_b) { + Some((ty, kind)) => { + let ty = ty::mk_uniq(self.tcx(), ty); + try!(self.subtype(ty, b)); + debug!("Success, coerced with AutoDerefRef(1, \ + AutoUnsizeUniq({:?}))", kind); + Ok(Some(AdjustDerefRef(AutoDerefRef { + autoderefs: 1, + autoref: Some(ty::AutoUnsizeUniq(kind)) + }))) } - }) + _ => Err(ty::terr_mismatch) + } } _ => Err(ty::terr_mismatch) } @@ -321,76 +327,148 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // E.g., `[T, ..n]` -> `([T], UnsizeLength(n))` fn unsize_ty(&self, ty_a: Ty<'tcx>, - a: Ty<'tcx>, ty_b: Ty<'tcx>) - -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> { - debug!("unsize_ty(a={:?}, ty_b={})", a, ty_b.repr(self.tcx())); - + -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> + { let tcx = self.tcx(); - self.unpack_actual_value(ty_b, |b| - match (&a.sty, &b.sty) { - (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => { - let ty = ty::mk_vec(tcx, t_a, None); - Some((ty, ty::UnsizeLength(len))) - } - (&ty::ty_trait(..), &ty::ty_trait(..)) => { - None - } - (_, &ty::ty_trait(box ty::TyTrait { ref principal, ref bounds })) => { - // FIXME what is the purpose of `ty`? - let ty = ty::mk_trait(tcx, principal.clone(), bounds.clone()); - Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: principal.clone(), - bounds: bounds.clone() }, - ty_a))) - } - (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b)) - if did_a == did_b => { - debug!("unsizing a struct"); - // Try unsizing each type param in turn to see if we end up with ty_b. - let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace); - let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace); - assert!(ty_substs_a.len() == ty_substs_b.len()); - - let mut result = None; - let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate(); - for (i, (tp_a, tp_b)) in tps { - if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() { - continue; + self.unpack_actual_value(ty_a, |a| { + self.unpack_actual_value(ty_b, |b| { + debug!("unsize_ty(a={}, b={})", a.repr(self.tcx()), b.repr(self.tcx())); + match (&a.sty, &b.sty) { + (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => { + let ty = ty::mk_vec(tcx, t_a, None); + Some((ty, ty::UnsizeLength(len))) + } + (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => { + // Upcasts permit two things: + // + // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo` + // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b` + // + // Note that neither of these changes requires any + // change at runtime. Eventually this will be + // generalized. + // + // We always upcast when we can because of reason + // #2 (region bounds). + if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) { + // construct a type `a1` which is a version of + // `a` using the upcast bounds from `b` + let bounds_a1 = ty::ExistentialBounds { + // From type b + region_bound: data_b.bounds.region_bound, + builtin_bounds: data_b.bounds.builtin_bounds, + + // From type a + projection_bounds: data_a.bounds.projection_bounds.clone(), + }; + let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1); + + // relate `a1` to `b` + let result = self.fcx.infcx().commit_if_ok(|_| { + // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b + try!(self.outlives(infer::RelateObjectBound(self.origin.span()), + data_a.bounds.region_bound, + data_b.bounds.region_bound)); + self.subtype(ty_a1, ty_b) + }); + + // if that was successful, we have a coercion + match result { + Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))), + Err(_) => None, + } + } else { + None } - match - self.unpack_actual_value( - *tp_a, - |tp| self.unsize_ty(*tp_a, tp, *tp_b)) - { - Some((new_tp, k)) => { - // Check that the whole types match. - let mut new_substs = substs_a.clone(); - new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp; - let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs)); - if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() { - debug!("Unsized type parameter '{}', but still \ - could not match types {} and {}", - ppaux::ty_to_string(tcx, *tp_a), - ppaux::ty_to_string(tcx, ty), - ppaux::ty_to_string(tcx, ty_b)); - // We can only unsize a single type parameter, so - // if we unsize one and it doesn't give us the - // type we want, then we won't succeed later. + } + (_, &ty::ty_trait(ref data)) => { + Some((ty_b, ty::UnsizeVtable(ty::TyTrait { + principal: data.principal.clone(), + bounds: data.bounds.clone() + }, + ty_a))) + } + (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b)) + if did_a == did_b => { + debug!("unsizing a struct"); + // Try unsizing each type param in turn to see if we end up with ty_b. + let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace); + let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace); + assert!(ty_substs_a.len() == ty_substs_b.len()); + + let mut result = None; + let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate(); + for (i, (tp_a, tp_b)) in tps { + if self.subtype(*tp_a, *tp_b).is_ok() { + continue; + } + match self.unsize_ty(*tp_a, *tp_b) { + Some((new_tp, k)) => { + // Check that the whole types match. + let mut new_substs = substs_a.clone(); + new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp; + let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs)); + if self.subtype(ty, ty_b).is_err() { + debug!("Unsized type parameter '{}', but still \ + could not match types {} and {}", + ppaux::ty_to_string(tcx, *tp_a), + ppaux::ty_to_string(tcx, ty), + ppaux::ty_to_string(tcx, ty_b)); + // We can only unsize a single type parameter, so + // if we unsize one and it doesn't give us the + // type we want, then we won't succeed later. + break; + } + + result = Some((ty, ty::UnsizeStruct(box k, i))); break; } - - result = Some((ty, ty::UnsizeStruct(box k, i))); - break; + None => {} } - None => {} } + result } - result + _ => None + } + }) + }) + } + + fn coerce_from_fn_pointer(&self, + a: Ty<'tcx>, + fn_ty_a: &'tcx ty::BareFnTy<'tcx>, + b: Ty<'tcx>) + -> CoerceResult<'tcx> + { + /*! + * Attempts to coerce from the type of a Rust function item + * into a closure or a `proc`. + */ + + self.unpack_actual_value(b, |b| { + debug!("coerce_from_fn_pointer(a={}, b={})", + a.repr(self.tcx()), b.repr(self.tcx())); + + match b.sty { + ty::ty_bare_fn(None, fn_ty_b) => { + match (fn_ty_a.unsafety, fn_ty_b.unsafety) { + (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => { + let unsafe_a = self.tcx().safe_to_unsafe_fn_ty(fn_ty_a); + try!(self.subtype(unsafe_a, b)); + Ok(Some(ty::AdjustUnsafeFnPointer)) + } + _ => { + self.subtype(a, b) + } + } + } + _ => { + return self.subtype(a, b) } - _ => None } - ) + }) } fn coerce_from_fn_item(&self, @@ -458,14 +536,13 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr, a: Ty<'tcx>, b: Ty<'tcx>) - -> cres<'tcx, ()> { + -> RelateResult<'tcx, ()> { debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx())); let adjustment = try!(indent(|| { - fcx.infcx().commit_if_ok(|| { - let origin = infer::ExprAssignable(expr.span); + fcx.infcx().commit_if_ok(|_| { Coerce { fcx: fcx, - trace: infer::TypeTrace::types(origin, false, a, b) + origin: infer::ExprAssignable(expr.span), }.coerce(expr, a, b) }) })); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 1e1d7e0926..532277d75b 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -15,7 +15,7 @@ use middle::subst::{self, Subst, Substs, VecPerParamSpace}; use util::ppaux::{self, Repr}; use syntax::ast; -use syntax::codemap::{Span}; +use syntax::codemap::Span; use syntax::parse::token; use super::assoc; @@ -282,7 +282,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone())); let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); - let err = infcx.try(|snapshot| { + let err = infcx.commit_if_ok(|snapshot| { let origin = infer::MethodCompatCheck(impl_m_span); let (impl_sig, _) = diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 6f2d0cb366..cd6a1226e0 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -53,9 +53,11 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, } } -// Checks that the type `actual` can be coerced to `expected`. -pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, - expected: Ty<'tcx>, expr: &ast::Expr) { +// Checks that the type of `expr` can be coerced to `expected`. +pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + sp: Span, + expected: Ty<'tcx>, + expr: &ast::Expr) { let expr_ty = fcx.expr_ty(expr); debug!("demand::coerce(expected = {}, expr_ty = {})", expected.repr(fcx.ccx.tcx), diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index ce67369ca9..2f7e0073e1 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -12,12 +12,249 @@ use check::regionck::{self, Rcx}; use middle::infer; use middle::region; -use middle::subst; +use middle::subst::{self, Subst}; use middle::ty::{self, Ty}; -use util::ppaux::{Repr}; +use util::ppaux::{Repr, UserString}; + +use syntax::ast; +use syntax::codemap::{self, Span}; + +/// check_drop_impl confirms that the Drop implementation identfied by +/// `drop_impl_did` is not any more specialized than the type it is +/// attached to (Issue #8142). +/// +/// This means: +/// +/// 1. The self type must be nominal (this is already checked during +/// coherence), +/// +/// 2. The generic region/type parameters of the impl's self-type must +/// all be parameters of the Drop impl itself (i.e. no +/// specialization like `impl Drop for Foo`), and, +/// +/// 3. Any bounds on the generic parameters must be reflected in the +/// struct/enum definition for the nominal type itself (i.e. +/// cannot do `struct S; impl Drop for S { ... }`). +/// +pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(), ()> { + let ty::TypeScheme { generics: ref dtor_generics, + ty: ref dtor_self_type } = ty::lookup_item_type(tcx, drop_impl_did); + let dtor_predicates = ty::lookup_predicates(tcx, drop_impl_did); + match dtor_self_type.sty { + ty::ty_enum(self_type_did, self_to_impl_substs) | + ty::ty_struct(self_type_did, self_to_impl_substs) | + ty::ty_closure(self_type_did, self_to_impl_substs) => { + try!(ensure_drop_params_and_item_params_correspond(tcx, + drop_impl_did, + dtor_generics, + dtor_self_type, + self_type_did)); + + ensure_drop_predicates_are_implied_by_item_defn(tcx, + drop_impl_did, + &dtor_predicates, + self_type_did, + self_to_impl_substs) + } + _ => { + // Destructors only work on nominal types. This was + // already checked by coherence, so we can panic here. + let span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP); + tcx.sess.span_bug( + span, &format!("should have been rejected by coherence check: {}", + dtor_self_type.repr(tcx))); + } + } +} + +fn ensure_drop_params_and_item_params_correspond<'tcx>( + tcx: &ty::ctxt<'tcx>, + drop_impl_did: ast::DefId, + drop_impl_generics: &ty::Generics<'tcx>, + drop_impl_ty: &ty::Ty<'tcx>, + self_type_did: ast::DefId) -> Result<(), ()> +{ + // New strategy based on review suggestion from nikomatsakis. + // + // (In the text and code below, "named" denotes "struct/enum", and + // "generic params" denotes "type and region params") + // + // 1. Create fresh skolemized type/region "constants" for each of + // the named type's generic params. Instantiate the named type + // with the fresh constants, yielding `named_skolem`. + // + // 2. Create unification variables for each of the Drop impl's + // generic params. Instantiate the impl's Self's type with the + // unification-vars, yielding `drop_unifier`. + // + // 3. Attempt to unify Self_unif with Type_skolem. If unification + // succeeds, continue (i.e. with the predicate checks). + + let ty::TypeScheme { generics: ref named_type_generics, + ty: named_type } = + ty::lookup_item_type(tcx, self_type_did); + + let infcx = infer::new_infer_ctxt(tcx); + infcx.commit_if_ok(|snapshot| { + let (named_type_to_skolem, skol_map) = + infcx.construct_skolemized_subst(named_type_generics, snapshot); + let named_type_skolem = named_type.subst(tcx, &named_type_to_skolem); + + let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP); + let drop_to_unifier = + infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics); + let drop_unifier = drop_impl_ty.subst(tcx, &drop_to_unifier); + + if let Ok(()) = infer::mk_eqty(&infcx, true, infer::TypeOrigin::Misc(drop_impl_span), + named_type_skolem, drop_unifier) { + // Even if we did manage to equate the types, the process + // may have just gathered unsolvable region constraints + // like `R == 'static` (represented as a pair of subregion + // constraints) for some skolemization constant R. + // + // However, the leak_check method allows us to confirm + // that no skolemized regions escaped (i.e. were related + // to other regions in the constraint graph). + if let Ok(()) = infcx.leak_check(&skol_map, snapshot) { + return Ok(()) + } + } + + span_err!(tcx.sess, drop_impl_span, E0366, + "Implementations of Drop cannot be specialized"); + let item_span = tcx.map.span(self_type_did.node); + tcx.sess.span_note(item_span, + "Use same sequence of generic type and region \ + parameters that is on the struct/enum definition"); + return Err(()); + }) +} + +/// Confirms that every predicate imposed by dtor_predicates is +/// implied by assuming the predicates attached to self_type_did. +fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( + tcx: &ty::ctxt<'tcx>, + drop_impl_did: ast::DefId, + dtor_predicates: &ty::GenericPredicates<'tcx>, + self_type_did: ast::DefId, + self_to_impl_substs: &subst::Substs<'tcx>) -> Result<(), ()> { + + // Here is an example, analogous to that from + // `compare_impl_method`. + // + // Consider a struct type: + // + // struct Type<'c, 'b:'c, 'a> { + // x: &'a Contents // (contents are irrelevant; + // y: &'c Cell<&'b Contents>, // only the bounds matter for our purposes.) + // } + // + // and a Drop impl: + // + // impl<'z, 'y:'z, 'x:'y> Drop for P<'z, 'y, 'x> { + // fn drop(&mut self) { self.y.set(self.x); } // (only legal if 'x: 'y) + // } + // + // We start out with self_to_impl_substs, that maps the generic + // parameters of Type to that of the Drop impl. + // + // self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x} + // + // Applying this to the predicates (i.e. assumptions) provided by the item + // definition yields the instantiated assumptions: + // + // ['y : 'z] + // + // We then check all of the predicates of the Drop impl: + // + // ['y:'z, 'x:'y] + // + // and ensure each is in the list of instantiated + // assumptions. Here, `'y:'z` is present, but `'x:'y` is + // absent. So we report an error that the Drop impl injected a + // predicate that is not present on the struct definition. + + assert_eq!(self_type_did.krate, ast::LOCAL_CRATE); + + let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP); + + // We can assume the predicates attached to struct/enum definition + // hold. + let generic_assumptions = ty::lookup_predicates(tcx, self_type_did); + + let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs); + assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace)); + assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::FnSpace)); + let assumptions_in_impl_context = + assumptions_in_impl_context.predicates.get_slice(subst::TypeSpace); + + // An earlier version of this code attempted to do this checking + // via the traits::fulfill machinery. However, it ran into trouble + // since the fulfill machinery merely turns outlives-predicates + // 'a:'b and T:'b into region inference constraints. It is simpler + // just to look for all the predicates directly. + + assert!(dtor_predicates.predicates.is_empty_in(subst::SelfSpace)); + assert!(dtor_predicates.predicates.is_empty_in(subst::FnSpace)); + let predicates = dtor_predicates.predicates.get_slice(subst::TypeSpace); + for predicate in predicates { + // (We do not need to worry about deep analysis of type + // expressions etc because the Drop impls are already forced + // to take on a structure that is roughly a alpha-renaming of + // the generic parameters of the item definition.) + + // This path now just checks *all* predicates via the direct + // lookup, rather than using fulfill machinery. + // + // However, it may be more efficient in the future to batch + // the analysis together via the fulfill , rather than the + // repeated `contains` calls. + + if !assumptions_in_impl_context.contains(&predicate) { + let item_span = tcx.map.span(self_type_did.node); + let req = predicate.user_string(tcx); + span_err!(tcx.sess, drop_impl_span, E0367, + "The requirement `{}` is added only by the Drop impl.", req); + tcx.sess.span_note(item_span, + "The same requirement must be part of \ + the struct/enum definition"); + } + } -use syntax::codemap::Span; + if tcx.sess.has_errors() { + return Err(()); + } + Ok(()) +} +/// check_safety_of_destructor_if_necessary confirms that the type +/// expression `typ` conforms to the "Drop Check Rule" from the Sound +/// Generic Drop (RFC 769). +/// +/// ---- +/// +/// The Drop Check Rule is the following: +/// +/// Let `v` be some value (either temporary or named) and 'a be some +/// lifetime (scope). If the type of `v` owns data of type `D`, where +/// +/// (1.) `D` has a lifetime- or type-parametric Drop implementation, and +/// (2.) the structure of `D` can reach a reference of type `&'a _`, and +/// (3.) either: +/// +/// (A.) the Drop impl for `D` instantiates `D` at 'a directly, +/// i.e. `D<'a>`, or, +/// +/// (B.) the Drop impl for `D` has some type parameter with a +/// trait bound `T` where `T` is a trait that has at least +/// one method, +/// +/// then 'a must strictly outlive the scope of v. +/// +/// ---- +/// +/// This function is meant to by applied to the type for every +/// expression in the program. pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, typ: ty::Ty<'tcx>, span: Span, @@ -28,29 +265,98 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx> // types that have been traversed so far by `traverse_type_if_unseen` let mut breadcrumbs: Vec> = Vec::new(); - iterate_over_potentially_unsafe_regions_in_type( + let result = iterate_over_potentially_unsafe_regions_in_type( rcx, &mut breadcrumbs, + TypeContext::Root, typ, span, scope, + 0, 0); + match result { + Ok(()) => {} + Err(Error::Overflow(ref ctxt, ref detected_on_typ)) => { + let tcx = rcx.tcx(); + span_err!(tcx.sess, span, E0320, + "overflow while adding drop-check rules for {}", + typ.user_string(rcx.tcx())); + match *ctxt { + TypeContext::Root => { + // no need for an additional note if the overflow + // was somehow on the root. + } + TypeContext::EnumVariant { def_id, variant, arg_index } => { + // FIXME (pnkfelix): eventually lookup arg_name + // for the given index on struct variants. + span_note!( + rcx.tcx().sess, + span, + "overflowed on enum {} variant {} argument {} type: {}", + ty::item_path_str(tcx, def_id), + variant, + arg_index, + detected_on_typ.user_string(rcx.tcx())); + } + TypeContext::Struct { def_id, field } => { + span_note!( + rcx.tcx().sess, + span, + "overflowed on struct {} field {} type: {}", + ty::item_path_str(tcx, def_id), + field, + detected_on_typ.user_string(rcx.tcx())); + } + } + } + } +} + +enum Error<'tcx> { + Overflow(TypeContext, ty::Ty<'tcx>), } +enum TypeContext { + Root, + EnumVariant { + def_id: ast::DefId, + variant: ast::Name, + arg_index: usize, + }, + Struct { + def_id: ast::DefId, + field: ast::Name, + } +} + +// The `depth` counts the number of calls to this function; +// the `xref_depth` counts the subset of such calls that go +// across a `Box` or `PhantomData`. fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( rcx: &mut Rcx<'a, 'tcx>, breadcrumbs: &mut Vec>, + context: TypeContext, ty_root: ty::Ty<'tcx>, span: Span, scope: region::CodeExtent, - depth: uint) + depth: usize, + xref_depth: usize) -> Result<(), Error<'tcx>> { - let origin = |&:| infer::SubregionOrigin::SafeDestructor(span); + // Issue #22443: Watch out for overflow. While we are careful to + // handle regular types properly, non-regular ones cause problems. + let recursion_limit = rcx.tcx().sess.recursion_limit.get(); + if xref_depth >= recursion_limit { + return Err(Error::Overflow(context, ty_root)) + } + + let origin = || infer::SubregionOrigin::SafeDestructor(span); let mut walker = ty_root.walk(); let opt_phantom_data_def_id = rcx.tcx().lang_items.phantom_data(); let destructor_for_type = rcx.tcx().destructor_for_type.borrow(); + let xref_depth_orig = xref_depth; + while let Some(typ) = walker.next() { // Avoid recursing forever. if breadcrumbs.contains(&typ) { @@ -61,20 +367,33 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( // If we encounter `PhantomData`, then we should replace it // with `T`, the type it represents as owned by the // surrounding context, before doing further analysis. - let typ = if let ty::ty_struct(struct_did, substs) = typ.sty { - if opt_phantom_data_def_id == Some(struct_did) { - let item_type = ty::lookup_item_type(rcx.tcx(), struct_did); - let tp_def = item_type.generics.types - .opt_get(subst::TypeSpace, 0).unwrap(); - let new_typ = substs.type_for_def(tp_def); - debug!("replacing phantom {} with {}", + let (typ, xref_depth) = match typ.sty { + ty::ty_struct(struct_did, substs) => { + if opt_phantom_data_def_id == Some(struct_did) { + let item_type = ty::lookup_item_type(rcx.tcx(), struct_did); + let tp_def = item_type.generics.types + .opt_get(subst::TypeSpace, 0).unwrap(); + let new_typ = substs.type_for_def(tp_def); + debug!("replacing phantom {} with {}", + typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx())); + (new_typ, xref_depth_orig + 1) + } else { + (typ, xref_depth_orig) + } + } + + // Note: When ty_uniq is removed from compiler, the + // definition of `Box` must carry a PhantomData that + // puts us into the previous case. + ty::ty_uniq(new_typ) => { + debug!("replacing ty_uniq {} with {}", typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx())); - new_typ - } else { - typ + (new_typ, xref_depth_orig + 1) + } + + _ => { + (typ, xref_depth_orig) } - } else { - typ }; let opt_type_did = match typ.sty { @@ -87,9 +406,9 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( opt_type_did.and_then(|did| destructor_for_type.get(&did)); debug!("iterate_over_potentially_unsafe_regions_in_type \ - {}typ: {} scope: {:?} opt_dtor: {:?}", + {}typ: {} scope: {:?} opt_dtor: {:?} xref: {}", (0..depth).map(|_| ' ').collect::(), - typ.repr(rcx.tcx()), scope, opt_dtor); + typ.repr(rcx.tcx()), scope, opt_dtor, xref_depth); // If `typ` has a destructor, then we must ensure that all // borrowed data reachable via `typ` must outlive the parent @@ -215,8 +534,8 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( match rcx.tcx().region_maps.opt_encl_scope(scope) { Some(parent_scope) => ty::ReScope(parent_scope), None => rcx.tcx().sess.span_bug( - span, format!("no enclosing scope found for scope: {:?}", - scope).as_slice()), + span, &format!("no enclosing scope found for scope: {:?}", + scope)), }; regionck::type_must_outlive(rcx, origin(), typ, parent_region); @@ -228,6 +547,8 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( match typ.sty { ty::ty_struct(struct_did, substs) => { + debug!("typ: {} is struct; traverse structure and not type-expression", + typ.repr(rcx.tcx())); // Don't recurse; we extract type's substructure, // so do not process subparts of type expression. walker.skip_current_subtree(); @@ -240,17 +561,24 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( struct_did, field.id, substs); - iterate_over_potentially_unsafe_regions_in_type( + try!(iterate_over_potentially_unsafe_regions_in_type( rcx, breadcrumbs, + TypeContext::Struct { + def_id: struct_did, + field: field.name, + }, field_type, span, scope, - depth+1) + depth+1, + xref_depth)) } } ty::ty_enum(enum_did, substs) => { + debug!("typ: {} is enum; traverse structure and not type-expression", + typ.repr(rcx.tcx())); // Don't recurse; we extract type's substructure, // so do not process subparts of type expression. walker.skip_current_subtree(); @@ -260,14 +588,20 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( enum_did, substs); for variant_info in all_variant_info.iter() { - for argument_type in variant_info.args.iter() { - iterate_over_potentially_unsafe_regions_in_type( + for (i, arg_type) in variant_info.args.iter().enumerate() { + try!(iterate_over_potentially_unsafe_regions_in_type( rcx, breadcrumbs, - *argument_type, + TypeContext::EnumVariant { + def_id: enum_did, + variant: variant_info.name, + arg_index: i, + }, + *arg_type, span, scope, - depth+1) + depth+1, + xref_depth)); } } } @@ -290,4 +624,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( // is done. } } + + return Ok(()); } diff --git a/src/librustc_typeck/check/implicator.rs b/src/librustc_typeck/check/implicator.rs index 4aaaf4ffe5..a4a18c7cfd 100644 --- a/src/librustc_typeck/check/implicator.rs +++ b/src/librustc_typeck/check/implicator.rs @@ -12,7 +12,7 @@ use astconv::object_region_bounds; use middle::infer::{InferCtxt, GenericKind}; -use middle::subst::{Substs}; +use middle::subst::Substs; use middle::traits; use middle::ty::{self, ToPolyTraitRef, Ty}; use middle::ty_fold::{TypeFoldable, TypeFolder}; @@ -22,6 +22,7 @@ use syntax::ast; use syntax::codemap::Span; use util::common::ErrorReported; +use util::nodemap::FnvHashSet; use util::ppaux::Repr; // Helper functions related to manipulating region types. @@ -29,6 +30,7 @@ use util::ppaux::Repr; pub enum Implication<'tcx> { RegionSubRegion(Option>, ty::Region, ty::Region), RegionSubGeneric(Option>, ty::Region, GenericKind<'tcx>), + RegionSubClosure(Option>, ty::Region, ast::DefId, &'tcx Substs<'tcx>), Predicate(ast::DefId, ty::Predicate<'tcx>), } @@ -39,6 +41,7 @@ struct Implicator<'a, 'tcx: 'a> { stack: Vec<(ty::Region, Option>)>, span: Span, out: Vec>, + visited: FnvHashSet>, } /// This routine computes the well-formedness constraints that must hold for the type `ty` to @@ -64,7 +67,8 @@ pub fn implications<'a,'tcx>( body_id: body_id, span: span, stack: stack, - out: Vec::new() }; + out: Vec::new(), + visited: FnvHashSet() }; wf.accumulate_from_ty(ty); debug!("implications: out={}", wf.out.repr(closure_typer.tcx())); wf.out @@ -79,6 +83,12 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> { debug!("accumulate_from_ty(ty={})", ty.repr(self.tcx())); + // When expanding out associated types, we can visit a cyclic + // set of types. Issue #23003. + if !self.visited.insert(ty) { + return; + } + match ty.sty { ty::ty_bool | ty::ty_char | @@ -91,29 +101,9 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> { // No borrowed content reachable here. } - ty::ty_closure(_, region, _) => { - // An "closure type" is basically - // modeled here as equivalent to a struct like - // - // struct TheClosure<'b> { - // ... - // } - // - // where the `'b` is the lifetime bound of the - // contents (i.e., all contents must outlive 'b). - // - // Even though closures are glorified structs - // of upvars, we do not need to consider them as they - // can't generate any new constraints. The - // substitutions on the closure are equal to the free - // substitutions of the enclosing parameter - // environment. An upvar captured by value has the - // same type as the original local variable which is - // already checked for consistency. If the upvar is - // captured by reference it must also outlive the - // region bound on the closure, but this is explicitly - // handled by logic in regionck. - self.push_region_constraint_from_top(*region); + ty::ty_closure(def_id, substs) => { + let &(r_a, opt_ty) = self.stack.last().unwrap(); + self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs)); } ty::ty_trait(ref t) => { @@ -161,12 +151,6 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> { // entering the fn check. We should do this after // the fn check, then we can call this case a bug(). } - - ty::ty_open(_) => { - self.tcx().sess.bug( - &format!("Unexpected type encountered while doing wf check: {}", - ty.repr(self.tcx()))[]); - } } } @@ -454,6 +438,13 @@ impl<'tcx> Repr<'tcx> for Implication<'tcx> { p.repr(tcx)) } + Implication::RegionSubClosure(_, ref a, ref b, ref c) => { + format!("RegionSubClosure({}, {}, {})", + a.repr(tcx), + b.repr(tcx), + c.repr(tcx)) + } + Implication::Predicate(ref def_id, ref p) => { format!("Predicate({}, {})", def_id.repr(tcx), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index dfbfc86c65..6aefcf5a47 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -176,13 +176,13 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { probe::AutoDeref(num) => { ty::AutoDerefRef { autoderefs: num, - autoref: None + autoref: None, } } probe::AutoUnsizeLength(autoderefs, len) => { ty::AutoDerefRef { autoderefs: autoderefs, - autoref: Some(ty::AutoUnsize(ty::UnsizeLength(len))) + autoref: Some(ty::AutoUnsize(ty::UnsizeLength(len))), } } probe::AutoRef(mutability, ref sub_adjustment) => { @@ -331,7 +331,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.tcx().sess.span_bug( self.span, &format!("self-type `{}` for ObjectPick never dereferenced to an object", - self_ty.repr(self.tcx()))[]) + self_ty.repr(self.tcx()))) } } } @@ -386,7 +386,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { &format!( "{} was a subtype of {} but now is not?", self_ty.repr(self.tcx()), - method_self_ty.repr(self.tcx()))[]); + method_self_ty.repr(self.tcx()))); } } } @@ -404,26 +404,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { all_substs.repr(self.tcx())); // Instantiate the bounds on the method with the - // type/early-bound-regions substitutions performed. The only - // late-bound-regions that can appear in bounds are from the - // impl, and those were already instantiated above. - // - // FIXME(DST). Super hack. For a method on a trait object - // `Trait`, the generic signature requires that - // `Self:Trait`. Since, for an object, we bind `Self` to the - // type `Trait`, this leads to an obligation - // `Trait:Trait`. Until such time we DST is fully implemented, - // that obligation is not necessarily satisfied. (In the - // future, it would be.) But we know that the true `Self` DOES implement - // the trait. So we just delete this requirement. Hack hack hack. - let mut method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs); - match pick.kind { - probe::ObjectPick(..) => { - assert_eq!(method_predicates.predicates.get_slice(subst::SelfSpace).len(), 1); - method_predicates.predicates.pop(subst::SelfSpace); - } - _ => { } - } + // type/early-bound-regions substitutions performed. There can + // be no late-bound regions appearing here. + let method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs); let method_predicates = self.fcx.normalize_associated_types_in(self.span, &method_predicates); @@ -651,16 +634,21 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { target_trait_def_id: ast::DefId) -> ty::PolyTraitRef<'tcx> { - match traits::upcast(self.tcx(), source_trait_ref.clone(), target_trait_def_id) { - Some(super_trait_ref) => super_trait_ref, - None => { - self.tcx().sess.span_bug( - self.span, - &format!("cannot upcast `{}` to `{}`", - source_trait_ref.repr(self.tcx()), - target_trait_def_id.repr(self.tcx()))); - } + let upcast_trait_refs = traits::upcast(self.tcx(), + source_trait_ref.clone(), + target_trait_def_id); + + // must be exactly one trait ref or we'd get an ambig error etc + if upcast_trait_refs.len() != 1 { + self.tcx().sess.span_bug( + self.span, + &format!("cannot uniquely upcast `{}` to `{}`: `{}`", + source_trait_ref.repr(self.tcx()), + target_trait_def_id.repr(self.tcx()), + upcast_trait_refs.repr(self.tcx()))); } + + upcast_trait_refs.into_iter().next().unwrap() } fn replace_late_bound_regions_with_fresh_var(&self, value: &ty::Binder) -> T diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index ffbc8ad020..677ab56852 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Method lookup: the secret sauce of Rust. See `doc.rs`. +//! Method lookup: the secret sauce of Rust. See `README.md`. use astconv::AstConv; -use check::{FnCtxt}; +use check::FnCtxt; use check::vtable; use check::vtable::select_new_fcx_obligations; +use middle::def; +use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod}; use middle::subst; use middle::traits; use middle::ty::*; @@ -22,7 +24,7 @@ use middle::infer; use util::ppaux::Repr; use std::rc::Rc; -use syntax::ast::{DefId}; +use syntax::ast::DefId; use syntax::ast; use syntax::codemap::Span; @@ -50,13 +52,13 @@ pub enum MethodError { // A pared down enum describing just the places from which a method // candidate can arise. Used for error reporting only. -#[derive(Copy, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)] pub enum CandidateSource { ImplSource(ast::DefId), TraitSource(/* trait id */ ast::DefId), } -type MethodIndex = uint; // just for doc purposes +type MethodIndex = usize; // just for doc purposes /// Determines whether the type `self_ty` supports a method name `method_name` or not. pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, @@ -66,7 +68,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr_id: ast::NodeId) -> bool { - match probe::probe(fcx, span, method_name, self_ty, call_expr_id) { + let mode = probe::Mode::MethodCall; + match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) { Ok(..) => true, Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, @@ -103,8 +106,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, call_expr.repr(fcx.tcx()), self_expr.repr(fcx.tcx())); + let mode = probe::Mode::MethodCall; let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty); - let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id)); + let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id)); Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types)) } @@ -272,7 +276,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span, &format!( "trait method is &self but first arg is: {}", - transformed_self_ty.repr(fcx.tcx()))[]); + transformed_self_ty.repr(fcx.tcx()))); } } } @@ -282,7 +286,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span, &format!( "unexpected explicit self type in operator method: {:?}", - method_ty.explicit_self)[]); + method_ty.explicit_self)); } } } @@ -301,13 +305,36 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Some(callee) } +pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + span: Span, + method_name: ast::Name, + self_ty: Ty<'tcx>, + expr_id: ast::NodeId) + -> Result<(def::Def, LastPrivate), MethodError> +{ + let mode = probe::Mode::Path; + let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id)); + let def_id = pick.method_ty.def_id; + let mut lp = LastMod(AllPublic); + let provenance = match pick.kind { + probe::InherentImplPick(impl_def_id) => { + if pick.method_ty.vis != ast::Public { + lp = LastMod(DependsOn(def_id)); + } + def::FromImpl(impl_def_id) + } + _ => def::FromTrait(pick.method_ty.container.id()) + }; + Ok((def::DefMethod(def_id, provenance), lp)) +} + /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its /// index (or `None`, if no such method). fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId, method_name: ast::Name) - -> Option<(uint, Rc>)> + -> Option<(usize, Rc>)> { let trait_items = ty::trait_items(tcx, trait_def_id); trait_items diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 978fbbbcff..41eae88158 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{MethodError}; +use super::MethodError; use super::MethodIndex; use super::{CandidateSource,ImplSource,TraitSource}; use super::suggest; @@ -37,6 +37,7 @@ pub use self::PickKind::*; struct ProbeContext<'a, 'tcx:'a> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, + mode: Mode, method_name: ast::Name, steps: Rc>>, opt_simplified_steps: Option>, @@ -59,7 +60,7 @@ struct Candidate<'tcx> { enum CandidateKind<'tcx> { InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>), - ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* vtable index */ uint), + ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ usize, /* vtable index */ usize), ExtensionImplCandidate(/* Impl */ ast::DefId, Rc>, subst::Substs<'tcx>, MethodIndex), ClosureCandidate(/* Trait */ ast::DefId, MethodIndex), @@ -76,7 +77,7 @@ pub struct Pick<'tcx> { #[derive(Clone,Debug)] pub enum PickKind<'tcx> { InherentImplPick(/* Impl */ ast::DefId), - ObjectPick(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint), + ObjectPick(/* Trait */ ast::DefId, /* method_num */ usize, /* real_index */ usize), ExtensionImplPick(/* Impl */ ast::DefId, MethodIndex), TraitPick(/* Trait */ ast::DefId, MethodIndex), WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, MethodIndex), @@ -93,14 +94,14 @@ pub enum PickAdjustment { // Indicates that the source expression should be autoderef'd N times // // A = expr | *expr | **expr - AutoDeref(uint), + AutoDeref(usize), // Indicates that the source expression should be autoderef'd N // times and then "unsized". This should probably eventually go // away in favor of just coercing method receivers. // // A = unsize(expr | *expr | **expr) - AutoUnsizeLength(/* number of autoderefs */ uint, /* length*/ uint), + AutoUnsizeLength(/* number of autoderefs */ usize, /* length*/ usize), // Indicates that an autoref is applied after some number of other adjustments // @@ -108,17 +109,30 @@ pub enum PickAdjustment { AutoRef(ast::Mutability, Box), } +#[derive(PartialEq, Eq, Copy, Clone)] +pub enum Mode { + // An expression of the form `receiver.method_name(...)`. + // Autoderefs are performed on `receiver`, lookup is done based on the + // `self` argument of the method, and static methods aren't considered. + MethodCall, + // An expression of the form `Type::method` or `::method`. + // No autoderefs are performed, lookup is done based on the type each + // implementation is for, and static methods are included. + Path +} + pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, + mode: Mode, method_name: ast::Name, self_ty: Ty<'tcx>, - call_expr_id: ast::NodeId) + scope_expr_id: ast::NodeId) -> PickResult<'tcx> { - debug!("probe(self_ty={}, method_name={}, call_expr_id={})", + debug!("probe(self_ty={}, method_name={}, scope_expr_id={})", self_ty.repr(fcx.tcx()), method_name, - call_expr_id); + scope_expr_id); // FIXME(#18741) -- right now, creating the steps involves evaluating the // `*` operator, which registers obligations that then escape into @@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // it ride, although it's really not great, and in fact could I // think cause spurious errors. Really though this part should // take place in the `fcx.infcx().probe` below. - let steps = match create_steps(fcx, span, self_ty) { - Some(steps) => steps, - None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())), + let steps = if mode == Mode::MethodCall { + match create_steps(fcx, span, self_ty) { + Some(steps) => steps, + None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())), + } + } else { + vec![CandidateStep { + self_ty: self_ty, + adjustment: AutoDeref(0) + }] }; // Create a list of simplified self types, if we can. @@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // this creates one big transaction so that all type variables etc // that we create during the probe process are removed later - let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures fcx.infcx().probe(|_| { - let (steps, opt_simplified_steps) = dummy.take().unwrap(); - let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps); + let mut probe_cx = ProbeContext::new(fcx, + span, + mode, + method_name, + steps, + opt_simplified_steps); probe_cx.assemble_inherent_candidates(); - try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id)); + try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)); probe_cx.pick() }) } @@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, impl<'a,'tcx> ProbeContext<'a,'tcx> { fn new(fcx: &'a FnCtxt<'a,'tcx>, span: Span, + mode: Mode, method_name: ast::Name, steps: Vec>, opt_simplified_steps: Option>) @@ -206,6 +231,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { ProbeContext { fcx: fcx, span: span, + mode: mode, method_name: method_name, inherent_candidates: Vec::new(), extension_candidates: Vec::new(), @@ -252,17 +278,98 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } ty::ty_enum(did, _) | ty::ty_struct(did, _) | - ty::ty_closure(did, _, _) => { + ty::ty_closure(did, _) => { self.assemble_inherent_impl_candidates_for_type(did); } + ty::ty_uniq(_) => { + if let Some(box_did) = self.tcx().lang_items.owned_box() { + self.assemble_inherent_impl_candidates_for_type(box_did); + } + } ty::ty_param(p) => { self.assemble_inherent_candidates_from_param(self_ty, p); } + ty::ty_char => { + let lang_def_id = self.tcx().lang_items.char_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_str => { + let lang_def_id = self.tcx().lang_items.str_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_vec(_, None) => { + let lang_def_id = self.tcx().lang_items.slice_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { + let lang_def_id = self.tcx().lang_items.const_ptr_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { + let lang_def_id = self.tcx().lang_items.mut_ptr_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI8) => { + let lang_def_id = self.tcx().lang_items.i8_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI16) => { + let lang_def_id = self.tcx().lang_items.i16_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI32) => { + let lang_def_id = self.tcx().lang_items.i32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyI64) => { + let lang_def_id = self.tcx().lang_items.i64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_int(ast::TyIs) => { + let lang_def_id = self.tcx().lang_items.isize_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU8) => { + let lang_def_id = self.tcx().lang_items.u8_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU16) => { + let lang_def_id = self.tcx().lang_items.u16_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU32) => { + let lang_def_id = self.tcx().lang_items.u32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyU64) => { + let lang_def_id = self.tcx().lang_items.u64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_uint(ast::TyUs) => { + let lang_def_id = self.tcx().lang_items.usize_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_float(ast::TyF32) => { + let lang_def_id = self.tcx().lang_items.f32_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + ty::ty_float(ast::TyF64) => { + let lang_def_id = self.tcx().lang_items.f64_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } _ => { } } } + fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option) { + if let Some(impl_def_id) = lang_def_id { + ty::populate_implementations_for_primitive_if_necessary(self.tcx(), impl_def_id); + + self.assemble_inherent_impl_probe(impl_def_id); + } + } + fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) { // Read the inherent implementation candidates for this type from the // metadata if necessary. @@ -292,11 +399,12 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { return self.record_static_candidate(ImplSource(impl_def_id)); } - let impl_substs = self.impl_substs(impl_def_id); + let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); + let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty); // Determine the receiver type that the method itself expects. let xform_self_ty = - self.xform_self_ty(&method, &impl_substs); + self.xform_self_ty(&method, impl_ty, &impl_substs); self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, @@ -330,7 +438,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { new_trait_ref.def_id, method_num); - let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs); + let xform_self_ty = this.xform_self_ty(&m, + new_trait_ref.self_ty(), + new_trait_ref.substs); this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, @@ -373,7 +483,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { this.erase_late_bound_regions(&poly_trait_ref); let xform_self_ty = - this.xform_self_ty(&m, trait_ref.substs); + this.xform_self_ty(&m, + trait_ref.self_ty(), + trait_ref.substs); debug!("found match: trait_ref={} substs={} m={}", trait_ref.repr(this.tcx()), @@ -414,19 +526,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { &mut ProbeContext<'b, 'tcx>, ty::PolyTraitRef<'tcx>, Rc>, - uint, + usize, ), { debug!("elaborate_bounds(bounds={})", bounds.repr(self.tcx())); let tcx = self.tcx(); - let mut cache = HashSet::new(); for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { - // Already visited this trait, skip it. - if !cache.insert(bound_trait_ref.def_id()) { - continue; - } - let (pos, method) = match trait_method(tcx, bound_trait_ref.def_id(), self.method_name) { @@ -519,7 +625,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn assemble_extension_candidates_for_trait_impls(&mut self, trait_def_id: ast::DefId, method: Rc>, - method_index: uint) + method_index: usize) { ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_def_id); @@ -540,7 +646,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { continue; } - let impl_substs = self.impl_substs(impl_def_id); + let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id); debug!("impl_substs={}", impl_substs.repr(self.tcx())); @@ -553,7 +659,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // Determine the receiver type that the method itself expects. let xform_self_ty = - self.xform_self_ty(&method, impl_trait_ref.substs); + self.xform_self_ty(&method, + impl_trait_ref.self_ty(), + impl_trait_ref.substs); debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx())); @@ -584,7 +692,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn assemble_closure_candidates(&mut self, trait_def_id: ast::DefId, method_ty: Rc>, - method_index: uint) + method_index: usize) -> Result<(),MethodError> { // Check if this is one of the Fn,FnMut,FnOnce traits. @@ -603,8 +711,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // If so, add "synthetic impls". let steps = self.steps.clone(); for step in &*steps { - let (closure_def_id, _, _) = match step.self_ty.sty { - ty::ty_closure(a, b, ref c) => (a, b, c), + let closure_def_id = match step.self_ty.sty { + ty::ty_closure(a, _) => a, _ => continue, }; @@ -617,7 +725,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { }; // this closure doesn't implement the right kind of `Fn` trait - if closure_kind != kind { + if !closure_kind.extends(kind) { continue; } @@ -630,7 +738,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { &trait_def.generics, step.self_ty); - let xform_self_ty = self.xform_self_ty(&method_ty, &substs); + let xform_self_ty = self.xform_self_ty(&method_ty, + step.self_ty, + &substs); self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, method_ty: method_ty.clone(), @@ -644,7 +754,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn assemble_projection_candidates(&mut self, trait_def_id: ast::DefId, method: Rc>, - method_index: uint) + method_index: usize) { debug!("assemble_projection_candidates(\ trait_def_id={}, \ @@ -684,7 +794,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { bound.repr(self.tcx())); if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() { - let xform_self_ty = self.xform_self_ty(&method, bound.substs); + let xform_self_ty = self.xform_self_ty(&method, + bound.self_ty(), + bound.substs); debug!("assemble_projection_candidates: bound={} xform_self_ty={}", bound.repr(self.tcx()), @@ -703,7 +815,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn assemble_where_clause_candidates(&mut self, trait_def_id: ast::DefId, method_ty: Rc>, - method_index: uint) + method_index: usize) { debug!("assemble_where_clause_candidates(trait_def_id={})", trait_def_id.repr(self.tcx())); @@ -714,7 +826,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { .filter(|b| b.def_id() == trait_def_id) { let bound = self.erase_late_bound_regions(&poly_bound); - let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs); + let xform_self_ty = self.xform_self_ty(&method_ty, + bound.self_ty(), + bound.substs); debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}", bound.repr(self.tcx()), @@ -819,7 +933,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { return self.pick_method(step.self_ty).map(|r| self.adjust(r, adjustment.clone())); - fn consider_reborrow(ty: Ty, d: uint) -> PickAdjustment { + fn consider_reborrow<'tcx>(ty: Ty<'tcx>, d: usize) -> PickAdjustment { // Insert a `&*` or `&mut *` if this is a reference type: match ty.sty { ty::ty_rptr(_, ref mt) => AutoRef(mt.mutbl, box AutoDeref(d+1)), @@ -864,7 +978,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn adjust(&mut self, result: PickResult<'tcx>, adjustment: PickAdjustment) - -> PickResult<'tcx> { + -> PickResult<'tcx> + { match result { Err(e) => Err(e), Ok(mut pick) => { @@ -878,7 +993,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { debug!("pick_method(self_ty={})", self.infcx().ty_to_string(self_ty)); debug!("searching inherent candidates"); - match self.consider_candidates(self_ty, &self.inherent_candidates[]) { + match self.consider_candidates(self_ty, &self.inherent_candidates) { None => {} Some(pick) => { return Some(pick); @@ -886,7 +1001,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } debug!("searching extension candidates"); - self.consider_candidates(self_ty, &self.extension_candidates[]) + self.consider_candidates(self_ty, &self.extension_candidates) } fn consider_candidates(&self, @@ -985,7 +1100,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { /// ``` /// trait Foo { ... } /// impl Foo for Vec { ... } - /// impl Foo for Vec { ... } + /// impl Foo for Vec { ... } /// ``` /// /// Now imagine the receiver is `Vec<_>`. It doesn't really matter at this time which impl we @@ -1015,7 +1130,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { /////////////////////////////////////////////////////////////////////////// // MISCELLANY - fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::ures<'tcx> { + fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::UnitResult<'tcx> { self.infcx().sub_types(false, infer::Misc(DUMMY_SP), sub, sup) } @@ -1023,7 +1138,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // "fast track" -- check for usage of sugar match method.explicit_self { ty::StaticExplicitSelfCategory => { - // fallthrough + if self.mode == Mode::Path { + return true; + } } ty::ByValueExplicitSelfCategory | ty::ByReferenceExplicitSelfCategory(..) | @@ -1047,11 +1164,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn xform_self_ty(&self, method: &Rc>, + impl_ty: Ty<'tcx>, substs: &subst::Substs<'tcx>) -> Ty<'tcx> { - debug!("xform_self_ty(self_ty={}, substs={})", - method.fty.sig.0.inputs[0].repr(self.tcx()), + debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})", + impl_ty.repr(self.tcx()), + method.fty.sig.0.inputs.get(0).repr(self.tcx()), substs.repr(self.tcx())); assert!(!substs.has_escaping_regions()); @@ -1063,6 +1182,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // if there are any. assert_eq!(substs.types.len(subst::FnSpace), 0); assert_eq!(substs.regions().len(subst::FnSpace), 0); + + if self.mode == Mode::Path { + return impl_ty; + } + let placeholder; let mut substs = substs; if @@ -1094,9 +1218,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { xform_self_ty } - fn impl_substs(&self, - impl_def_id: ast::DefId) - -> subst::Substs<'tcx> + /// Get the type of an impl and generate substitutions with placeholders. + fn impl_ty_and_substs(&self, + impl_def_id: ast::DefId) + -> (Ty<'tcx>, subst::Substs<'tcx>) { let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id); @@ -1108,7 +1233,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { impl_pty.generics.regions.map( |_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static - subst::Substs::new(type_vars, region_placeholders) + let substs = subst::Substs::new(type_vars, region_placeholders); + (impl_pty.ty, substs) } /// Replace late-bound-regions bound by `value` with `'static` using @@ -1155,7 +1281,7 @@ fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, trait_def_id: ast::DefId, method_name: ast::Name) - -> Option<(uint, Rc>)> + -> Option<(usize, Rc>)> { let trait_items = ty::trait_items(tcx, trait_def_id); debug!("trait_method; items: {:?}", trait_items); @@ -1214,10 +1340,12 @@ impl<'tcx> Candidate<'tcx> { fn to_trait_data(&self) -> Option<(ast::DefId,MethodIndex)> { match self.kind { - InherentImplCandidate(..) | - ObjectCandidate(..) => { + InherentImplCandidate(..) => { None } + ObjectCandidate(trait_def_id, method_num, _) => { + Some((trait_def_id, method_num)) + } ClosureCandidate(trait_def_id, method_num) => { Some((trait_def_id, method_num)) } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 1639772103..c5ff8a14bc 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, method_name: ast::Name, - callee_expr: &ast::Expr, + rcvr_expr: Option<&ast::Expr>, error: MethodError) { // avoid suggestions when we don't know what's going on. @@ -46,16 +46,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let cx = fcx.tcx(); let method_ustring = method_name.user_string(cx); - // True if the type is a struct and contains a field with - // the same name as the not-found method - let is_field = match rcvr_ty.sty { - ty::ty_struct(did, _) => - ty::lookup_struct_fields(cx, did) - .iter() - .any(|f| f.name.user_string(cx) == method_ustring), - _ => false - }; - fcx.type_error_message( span, |actual| { @@ -68,10 +58,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, None); // If the method has the name of a field, give a help note - if is_field { - cx.sess.span_note(span, - &format!("use `(s.{0})(...)` if you meant to call the \ - function stored in the `{0}` field", method_ustring)[]); + if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) { + let fields = ty::lookup_struct_fields(cx, did); + if fields.iter().any(|f| f.name == method_name) { + cx.sess.span_note(span, + &format!("use `(s.{0})(...)` if you meant to call the \ + function stored in the `{0}` field", method_ustring)); + } } if static_sources.len() > 0 { @@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, report_candidates(fcx, span, method_name, static_sources); } - suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits) + suggest_traits_to_import(fcx, span, rcvr_ty, method_name, + rcvr_expr, out_of_scope_traits) } MethodError::Ambiguity(sources) => { @@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } MethodError::ClosureAmbiguity(trait_def_id) => { - fcx.sess().span_err( - span, - &*format!("the `{}` method from the `{}` trait cannot be explicitly \ - invoked on this closure as we have not yet inferred what \ - kind of closure it is; use overloaded call notation instead \ - (e.g., `{}()`)", - method_name.user_string(fcx.tcx()), - ty::item_path_str(fcx.tcx(), trait_def_id), - pprust::expr_to_string(callee_expr))); + let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \ + invoked on this closure as we have not yet inferred what \ + kind of closure it is", + method_name.user_string(fcx.tcx()), + ty::item_path_str(fcx.tcx(), trait_def_id)); + let msg = if let Some(callee) = rcvr_expr { + format!("{}; use overloaded call notation instead (e.g., `{}()`)", + msg, pprust::expr_to_string(callee)) + } else { + msg + }; + fcx.sess().span_err(span, &msg); } } @@ -156,6 +153,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, method_name: ast::Name, + rcvr_expr: Option<&ast::Expr>, valid_out_of_scope_traits: Vec) { let tcx = fcx.tcx(); @@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, return } - let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty); + let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr); // there's no implemented traits, so lets suggest some traits to // implement, by finding ones that have the method name, and are @@ -233,36 +231,42 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /// autoderefs of `rcvr_ty`. fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, - rcvr_ty: Ty<'tcx>) -> bool { - check::autoderef(fcx, span, rcvr_ty, None, - check::UnresolvedTypeAction::Ignore, check::NoPreference, - |&: ty, _| { - let is_local = match ty.sty { + rcvr_ty: Ty<'tcx>, + rcvr_expr: Option<&ast::Expr>) -> bool { + fn is_local(ty: Ty) -> bool { + match ty.sty { ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did), ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()), ty::ty_param(_) => true, - // the user cannot implement traits for unboxed closures, so - // there's no point suggesting anything at all, local or not. - ty::ty_closure(..) => return Some(false), - // everything else (primitive types etc.) is effectively // non-local (there are "edge" cases, e.g. (LocalType,), but // the noise from these sort of types is usually just really // annoying, rather than any sort of help). _ => false - }; - if is_local { - Some(true) + } + } + + // This occurs for UFCS desugaring of `T::method`, where there is no + // receiver expression for the method call, and thus no autoderef. + if rcvr_expr.is_none() { + return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty)); + } + + check::autoderef(fcx, span, rcvr_ty, None, + check::UnresolvedTypeAction::Ignore, check::NoPreference, + |ty, _| { + if is_local(ty) { + Some(()) } else { None } - }).2.unwrap_or(false) + }).2.is_some() } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct TraitInfo { pub def_id: ast::DefId, } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e443b4d0e6..156fbfede9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -79,47 +79,48 @@ type parameter). pub use self::LvaluePreference::*; pub use self::Expectation::*; pub use self::compare_method::compare_impl_method; -use self::IsBinopAssignment::*; use self::TupleArgumentsFlag::*; -use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv}; +use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode}; use check::_match::pat_ctxt; use fmt_macros::{Parser, Piece, Position}; -use middle::{const_eval, def}; +use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS}; +use middle::def; use middle::infer; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::pat_util::{self, pat_id_map}; +use middle::privacy::{AllPublic, LastMod}; use middle::region::{self, CodeExtent}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::traits; -use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme}; +use middle::ty::{FnSig, GenericPredicates, TypeScheme}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; -use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty}; +use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty}; use middle::ty::liberate_late_bound_regions; use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap}; use middle::ty_fold::{TypeFolder, TypeFoldable}; use rscope::RegionScope; use session::Session; -use {CrateCtxt, lookup_def_ccx, require_same_types}; +use {CrateCtxt, lookup_full_def, require_same_types}; use TypeAndSubsts; use lint; -use util::common::{block_query, indenter, loop_query}; +use util::common::{block_query, ErrorReported, indenter, loop_query}; use util::ppaux::{self, Repr}; use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use util::lev_distance::lev_distance; use std::cell::{Cell, Ref, RefCell}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem::replace; use std::rc::Rc; use std::iter::repeat; use std::slice; use syntax::{self, abi, attr}; use syntax::attr::AttrMetaMethods; -use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId}; -use syntax::ast_util::{self, local_def, PostExpansionMethod}; +use syntax::ast::{self, DefId, Visibility}; +use syntax::ast_util::{self, local_def}; use syntax::codemap::{self, Span}; +use syntax::feature_gate; use syntax::owned_slice::OwnedSlice; use syntax::parse::token; use syntax::print::pprust; @@ -141,6 +142,7 @@ pub mod wf; mod closure; mod callee; mod compare_method; +mod op; /// closures defined within the function. For example: /// @@ -182,6 +184,8 @@ pub struct Inherited<'a, 'tcx: 'a> { // def-id of the closure, so that once we decide, we can easily go // back and process them. deferred_call_resolutions: RefCell>>>, + + deferred_cast_checks: RefCell>>, } trait DeferredCallResolution<'tcx> { @@ -190,10 +194,19 @@ trait DeferredCallResolution<'tcx> { type DeferredCallResolutionHandler<'tcx> = Box+'tcx>; +/// Reifies a cast check to be checked once we have full type information for +/// a function context. +struct CastCheck<'tcx> { + expr: ast::Expr, + expr_ty: Ty<'tcx>, + cast_ty: Ty<'tcx>, + span: Span, +} + /// When type-checking an expression, we propagate downward /// whatever type hint we are able in the form of an `Expectation`. -#[derive(Copy)] -enum Expectation<'tcx> { +#[derive(Copy, Clone)] +pub enum Expectation<'tcx> { /// We know nothing about what type this expression should have. NoExpectation, @@ -276,15 +289,6 @@ impl UnsafetyState { } } -/// Whether `check_binop` is part of an assignment or not. -/// Used to know whether we allow user overloads and to print -/// better messages on error. -#[derive(PartialEq)] -enum IsBinopAssignment{ - SimpleBinop, - BinopAssignment, -} - #[derive(Clone)] pub struct FnCtxt<'a, 'tcx: 'a> { body_id: ast::NodeId, @@ -297,7 +301,7 @@ pub struct FnCtxt<'a, 'tcx: 'a> { // checking this function. On exit, if we find that *more* errors // have been reported, we will skip regionck and other work that // expects the types within the function to be consistent. - err_count_on_creation: uint, + err_count_on_creation: usize, ret_ty: ty::FnOutput<'tcx>, @@ -366,7 +370,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> { substs: &subst::Substs<'tcx>) -> ty::ClosureTy<'tcx> { - self.inh.closure_tys.borrow()[def_id].subst(self.tcx(), substs) + self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs) } fn closure_upvars(&self, @@ -397,6 +401,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> { fn_sig_map: RefCell::new(NodeMap()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), deferred_call_resolutions: RefCell::new(DefIdMap()), + deferred_cast_checks: RefCell::new(Vec::new()), } } @@ -454,7 +459,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &'tcx ast::Ty) { match t.node { ast::TyFixedLengthVec(_, ref expr) => { - check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint); + check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize); } _ => {} } @@ -476,6 +481,20 @@ pub fn check_item_types(ccx: &CrateCtxt) { visit::walk_crate(&mut visit, krate); ccx.tcx.sess.abort_if_errors(); + + for drop_method_did in ccx.tcx.destructors.borrow().iter() { + if drop_method_did.krate == ast::LOCAL_CRATE { + let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node); + match dropck::check_drop_impl(ccx.tcx, drop_impl_did) { + Ok(()) => {} + Err(()) => { + assert!(ccx.tcx.sess.has_errors()); + } + } + } + } + + ccx.tcx.sess.abort_if_errors(); } fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -506,6 +525,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, vtable::select_all_fcx_obligations_and_apply_defaults(&fcx); upvar::closure_analyze_fn(&fcx, fn_id, decl, body); vtable::select_all_fcx_obligations_or_error(&fcx); + fcx.check_casts(); regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body); writeback::resolve_type_vars_in_fn(&fcx, decl, body); } @@ -547,7 +567,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { debug!("Local variable {} is assigned type {}", self.fcx.pat_to_string(&*local.pat), self.fcx.infcx().ty_to_string( - self.fcx.inh.locals.borrow()[local.id].clone())); + self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone())); visit::walk_local(self, local); } @@ -563,7 +583,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { debug!("Pattern binding {} is assigned to {} with type {}", token::get_ident(path1.node), self.fcx.infcx().ty_to_string( - self.fcx.inh.locals.borrow()[p.id].clone()), + self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()), var_ty.repr(self.fcx.tcx())); } } @@ -583,7 +603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { match t.node { ast::TyFixedLengthVec(ref ty, ref count_expr) => { self.visit_ty(&**ty); - check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint); + check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize); } _ => visit::walk_ty(self, t) } @@ -615,7 +635,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, let tcx = ccx.tcx; let err_count_on_creation = tcx.sess.err_count(); - let arg_tys = &fn_sig.inputs[]; + let arg_tys = &fn_sig.inputs; let ret_ty = fn_sig.output; debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})", @@ -713,7 +733,7 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { ast::ItemEnum(ref enum_definition, _) => { check_enum_variants(ccx, it.span, - &enum_definition.variants[], + &enum_definition.variants, it.id); } ast::ItemFn(ref decl, _, _, _, ref body) => { @@ -737,30 +757,33 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) { } for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref m) => { - check_method_body(ccx, &impl_pty.generics, &**m); + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + check_method_body(ccx, &impl_pty.generics, sig, body, + impl_item.id, impl_item.span); } - ast::TypeImplItem(_) => { + ast::TypeImplItem(_) | + ast::MacImplItem(_) => { // Nothing to do here. } } } } - ast::ItemTrait(_, ref generics, _, ref trait_methods) => { + ast::ItemTrait(_, ref generics, _, ref trait_items) => { check_trait_on_unimplemented(ccx, generics, it); let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); - for trait_method in trait_methods { - match *trait_method { - RequiredMethod(..) => { + for trait_item in trait_items { + match trait_item.node { + ast::MethodTraitItem(_, None) => { // Nothing to do, since required methods don't have // bodies to check. } - ProvidedMethod(ref m) => { - check_method_body(ccx, &trait_def.generics, &**m); + ast::MethodTraitItem(ref sig, Some(ref body)) => { + check_method_body(ccx, &trait_def.generics, sig, body, + trait_item.id, trait_item.span); } - TypeTraitItem(_) => { + ast::TypeTraitItem(..) => { // Nothing to do. } } @@ -853,28 +876,23 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /// * `method`: the method definition fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, item_generics: &ty::Generics<'tcx>, - method: &'tcx ast::Method) { - debug!("check_method_body(item_generics={}, method.id={})", - item_generics.repr(ccx.tcx), - method.id); - let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id); - - let fty = ty::node_id_to_type(ccx.tcx, method.id); + sig: &'tcx ast::MethodSig, + body: &'tcx ast::Block, + id: ast::NodeId, span: Span) { + debug!("check_method_body(item_generics={}, id={})", + item_generics.repr(ccx.tcx), id); + let param_env = ParameterEnvironment::for_item(ccx.tcx, id); + + let fty = ty::node_id_to_type(ccx.tcx, id); debug!("check_method_body: fty={}", fty.repr(ccx.tcx)); - check_bare_fn(ccx, - &*method.pe_fn_decl(), - &*method.pe_body(), - method.id, - method.span, - fty, - param_env); + check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env); } fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_span: Span, impl_trait_ref: &ty::TraitRef<'tcx>, - impl_items: &[ast::ImplItem]) { + impl_items: &[P]) { // Locate trait methods let tcx = ccx.tcx; let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id); @@ -882,9 +900,9 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Check existing impl methods to see if they are both present in trait // and compatible with trait signature for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref impl_method) => { - let impl_method_def_id = local_def(impl_method.id); + match impl_item.node { + ast::MethodImplItem(_, ref body) => { + let impl_method_def_id = local_def(impl_item.id); let impl_item_ty = ty::impl_or_trait_item(ccx.tcx, impl_method_def_id); @@ -900,8 +918,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, &ty::MethodTraitItem(ref impl_method_ty)) => { compare_impl_method(ccx.tcx, &**impl_method_ty, - impl_method.span, - impl_method.pe_body().id, + impl_item.span, + body.id, &**trait_method_ty, &*impl_trait_ref); } @@ -909,7 +927,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // This is span_bug as it should have already been // caught in resolve. tcx.sess.span_bug( - impl_method.span, + impl_item.span, &format!("item `{}` is of a different kind from its trait `{}`", token::get_name(impl_item_ty.name()), impl_trait_ref.repr(tcx))); @@ -920,15 +938,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // This is span_bug as it should have already been // caught in resolve. tcx.sess.span_bug( - impl_method.span, + impl_item.span, &format!("method `{}` is not a member of trait `{}`", token::get_name(impl_item_ty.name()), impl_trait_ref.repr(tcx))); } } } - ast::TypeImplItem(ref typedef) => { - let typedef_def_id = local_def(typedef.id); + ast::TypeImplItem(_) => { + let typedef_def_id = local_def(impl_item.id); let typedef_ty = ty::impl_or_trait_item(ccx.tcx, typedef_def_id); @@ -945,7 +963,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // This is `span_bug` as it should have // already been caught in resolve. tcx.sess.span_bug( - typedef.span, + impl_item.span, &format!("item `{}` is of a different kind from its trait `{}`", token::get_name(typedef_ty.name()), impl_trait_ref.repr(tcx))); @@ -956,7 +974,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // This is `span_bug` as it should have already been // caught in resolve. tcx.sess.span_bug( - typedef.span, + impl_item.span, &format!( "associated type `{}` is not a member of \ trait `{}`", @@ -965,6 +983,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } } + ast::MacImplItem(_) => tcx.sess.span_bug(impl_item.span, + "unexpanded macro") } } @@ -976,11 +996,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty::MethodTraitItem(ref trait_method) => { let is_implemented = impl_items.iter().any(|ii| { - match *ii { - ast::MethodImplItem(ref m) => { - m.pe_ident().name == trait_method.name + match ii.node { + ast::MethodImplItem(..) => { + ii.ident.name == trait_method.name } - ast::TypeImplItem(_) => false, + ast::TypeImplItem(_) | + ast::MacImplItem(_) => false, } }); let is_provided = @@ -991,11 +1012,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } ty::TypeTraitItem(ref associated_type) => { let is_implemented = impl_items.iter().any(|ii| { - match *ii { - ast::TypeImplItem(ref typedef) => { - typedef.ident.name == associated_type.name + match ii.node { + ast::TypeImplItem(_) => { + ii.ident.name == associated_type.name } - ast::MethodImplItem(_) => false, + ast::MethodImplItem(..) | + ast::MacImplItem(_) => false, } }); if !is_implemented { @@ -1049,11 +1071,7 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } -fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - span: Span, - t_1: Ty<'tcx>, - t_e: Ty<'tcx>, - e: &ast::Expr) { +fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) { fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, t_1: Ty<'tcx>, @@ -1066,6 +1084,37 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }, t_e, None); } + let span = cast.span; + let e = &cast.expr; + let t_e = structurally_resolved_type(fcx, span, cast.expr_ty); + let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty); + + // Check for trivial casts. + if !ty::type_has_ty_infer(t_1) { + if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) { + if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) { + fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS, + e.id, + span, + format!("trivial numeric cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.infcx().ty_to_string(t_e), + fcx.infcx().ty_to_string(t_1))); + } else { + fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS, + e.id, + span, + format!("trivial cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.infcx().ty_to_string(t_e), + fcx.infcx().ty_to_string(t_1))); + } + return; + } + } + let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e); let t_e_is_scalar = ty::type_is_scalar(t_e); let t_e_is_integral = ty::type_is_integral(t_e); @@ -1081,18 +1130,17 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn; if t_e_is_bare_fn_item && t_1_is_bare_fn { - demand::coerce(fcx, e.span, t_1, &*e); + demand::coerce(fcx, e.span, t_1, &e); } else if t_1_is_char { let t_e = fcx.infcx().shallow_resolve(t_e); if t_e.sty != ty::ty_uint(ast::TyU8) { fcx.type_error_message(span, |actual| { - format!("only `u8` can be cast as \ - `char`, not `{}`", actual) + format!("only `u8` can be cast as `char`, not `{}`", actual) }, t_e, None); } } else if t_1.sty == ty::ty_bool { span_err!(fcx.tcx().sess, span, E0054, - "cannot cast as `bool`, compare with zero instead"); + "cannot cast as `bool`, compare with zero instead"); } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !( t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) { // Casts to float must go through an integer or boolean @@ -1141,7 +1189,7 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, /* this case is allowed */ } _ => { - demand::coerce(fcx, e.span, t_1, &*e); + demand::coerce(fcx, e.span, t_1, &e); } } } else if !(t_e_is_scalar && t_1_is_trivial) { @@ -1158,64 +1206,65 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } -fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, - cast_expr: &ast::Expr, - e: &'tcx ast::Expr, - t: &ast::Ty) { - let id = cast_expr.id; - let span = cast_expr.span; - - // Find the type of `e`. Supply hints based on the type we are casting to, - // if appropriate. - let t_1 = fcx.to_ty(t); - let t_1 = structurally_resolved_type(fcx, span, t_1); - - check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1)); - - let t_e = fcx.expr_ty(e); - - debug!("t_1={}", fcx.infcx().ty_to_string(t_1)); - debug!("t_e={}", fcx.infcx().ty_to_string(t_e)); - - if ty::type_is_error(t_e) { - fcx.write_error(id); - return - } - - if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) { - report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id); - return - } - - if ty::type_is_trait(t_1) { - // This will be looked up later on. - vtable::check_object_cast(fcx, cast_expr, e, t_1); - fcx.write_ty(id, t_1); - return - } - - let t_1 = structurally_resolved_type(fcx, span, t_1); - let t_e = structurally_resolved_type(fcx, span, t_e); - - check_cast_inner(fcx, span, t_1, t_e, e); - fcx.write_ty(id, t_1); -} - impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } - fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> { - ty::lookup_item_type(self.tcx(), id) + fn get_item_type_scheme(&self, _: Span, id: ast::DefId) + -> Result, ErrorReported> + { + Ok(ty::lookup_item_type(self.tcx(), id)) } - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - ty::lookup_trait_def(self.tcx(), id) + fn get_trait_def(&self, _: Span, id: ast::DefId) + -> Result>, ErrorReported> + { + Ok(ty::lookup_trait_def(self.tcx(), id)) + } + + fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> { + // all super predicates are ensured during collect pass + Ok(()) } fn get_free_substs(&self) -> Option<&Substs<'tcx>> { Some(&self.inh.param_env.free_substs) } + fn get_type_parameter_bounds(&self, + _: Span, + node_id: ast::NodeId) + -> Result>, ErrorReported> + { + let def = self.tcx().type_parameter_def(node_id); + let r = self.inh.param_env.caller_bounds + .iter() + .filter_map(|predicate| { + match *predicate { + ty::Predicate::Trait(ref data) => { + if data.0.self_ty().is_param(def.space, def.index) { + Some(data.to_poly_trait_ref()) + } else { + None + } + } + _ => { + None + } + } + }) + .collect(); + Ok(r) + } + + fn trait_defines_associated_type_named(&self, + trait_def_id: ast::DefId, + assoc_name: ast::Name) + -> bool + { + let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id); + trait_def.associated_type_names.contains(&assoc_name) + } + fn ty_infer(&self, _span: Span) -> Ty<'tcx> { self.infcx().next_ty_var() } @@ -1260,7 +1309,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self.tcx().sess } - pub fn err_count_since_creation(&self) -> uint { + pub fn err_count_since_creation(&self) -> usize { self.ccx.tcx.sess.err_count() - self.err_count_on_creation } @@ -1268,14 +1317,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// version, this version will also select obligations if it seems /// useful, in an effort to get more type information. fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { + debug!("resolve_type_vars_if_possible(ty={})", ty.repr(self.tcx())); + // No ty::infer()? Nothing needs doing. if !ty::type_has_ty_infer(ty) { + debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx())); return ty; } // If `ty` is a type variable, see whether we already know what it is. ty = self.infcx().resolve_type_vars_if_possible(&ty); if !ty::type_has_ty_infer(ty) { + debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx())); return ty; } @@ -1283,6 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { vtable::select_new_fcx_obligations(self); ty = self.infcx().resolve_type_vars_if_possible(&ty); if !ty::type_has_ty_infer(ty) { + debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx())); return ty; } @@ -1291,7 +1345,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // indirect dependencies that don't seem worth tracking // precisely. vtable::select_fcx_obligations_where_possible(self); - self.infcx().resolve_type_vars_if_possible(&ty) + ty = self.infcx().resolve_type_vars_if_possible(&ty); + + debug!("resolve_type_vars_if_possible: ty={}", ty.repr(self.tcx())); + ty } /// Resolves all type variables in `t` and then, if any were left @@ -1308,11 +1365,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_def_id: ast::DefId, r: DeferredCallResolutionHandler<'tcx>) { let mut deferred_call_resolutions = self.inh.deferred_call_resolutions.borrow_mut(); - let mut vec = match deferred_call_resolutions.entry(closure_def_id) { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(Vec::new()), - }; - vec.push(r); + deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r); } fn remove_deferred_call_resolutions(&self, @@ -1324,17 +1377,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn tag(&self) -> String { - format!("{:?}", self as *const FnCtxt) + let self_ptr: *const FnCtxt = self; + format!("{:?}", self_ptr) } pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> { match self.inh.locals.borrow().get(&nid) { Some(&t) => t, None => { - self.tcx().sess.span_bug( + self.tcx().sess.span_err( span, - &format!("no type for local variable {}", - nid)[]); + &format!("no type for local variable {}", nid)); + self.tcx().types.err } } } @@ -1368,14 +1422,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.inh.node_types.borrow_mut().insert(node_id, ty); } - pub fn write_object_cast(&self, - key: ast::NodeId, - trait_ref: ty::PolyTraitRef<'tcx>) { - debug!("write_object_cast key={} trait_ref={}", - key, trait_ref.repr(self.tcx())); - self.inh.object_cast_map.borrow_mut().insert(key, trait_ref); - } - pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) { if !substs.substs.is_noop() { debug!("write_substs({}, {}) in fcx {}", @@ -1390,7 +1436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn write_autoderef_adjustment(&self, node_id: ast::NodeId, span: Span, - derefs: uint) { + derefs: usize) { if derefs == 0 { return; } self.write_adjustment( node_id, @@ -1484,8 +1530,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, adj: &ty::AutoAdjustment<'tcx>) { match *adj { - ty::AdjustReifyFnPointer(..) => { - } + ty::AdjustReifyFnPointer(..) => { } + ty::AdjustUnsafeFnPointer => { } ty::AdjustDerefRef(ref d_r) => { match d_r.autoref { Some(ref a_r) => { @@ -1544,6 +1590,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObjectCastObligation(self_ty) }; self.register_region_obligation(self_ty, ty_trait.bounds.region_bound, cause); } + ty::UnsizeUpcast(_) => { } } } @@ -1598,23 +1645,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did); - let wants_params = - generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace); - - let needs_defaults = - wants_params && - path.segments.iter().all(|s| s.parameters.is_empty()); - - let substs = if needs_defaults { - let tps = - self.infcx().next_ty_vars(generics.types.len(TypeSpace)); - let rps = - self.infcx().region_vars_for_defs(path.span, - generics.regions.get_slice(TypeSpace)); - Substs::new_type(tps, rps) - } else { - astconv::ast_path_substs_for_ty(self, self, &generics, path) - }; + let substs = astconv::ast_path_substs_for_ty(self, self, + path.span, + PathParamMode::Optional, + &generics, + path.segments.last().unwrap()); let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty); @@ -1707,7 +1742,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(&t) => t, None => { self.tcx().sess.bug(&format!("no type for expr in fcx {}", - self.tag())[]); + self.tag())); } } } @@ -1739,7 +1774,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx().sess.bug( &format!("no type for node {}: {} in fcx {}", id, self.tcx().map.node_to_string(id), - self.tag())[]); + self.tag())); } } } @@ -1878,7 +1913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, class_id: ast::DefId, items: &[ty::field_ty], - idx: uint, + idx: usize, substs: &subst::Substs<'tcx>) -> Option> { @@ -1886,6 +1921,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs)) .map(|t| self.normalize_associated_types_in(span, &t)) } + + fn check_casts(&self) { + let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut(); + for check in deferred_cast_checks.iter() { + check_cast(self, check); + } + + deferred_cast_checks.clear(); + } } impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { @@ -1900,22 +1944,22 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { Some(self.infcx().next_region_var(infer::MiscVariable(span))) } - fn anon_regions(&self, span: Span, count: uint) - -> Result, Option>> { + fn anon_regions(&self, span: Span, count: usize) + -> Result, Option>> { Ok((0..count).map(|_| { self.infcx().next_region_var(infer::MiscVariable(span)) }).collect()) } } -#[derive(Copy, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum LvaluePreference { PreferMutLvalue, NoPreference } /// Whether `autoderef` requires types to resolve. -#[derive(Copy, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum UnresolvedTypeAction { /// Produce an error and return `ty_err` whenever a type cannot /// be resolved (i.e. it is `ty_infer`). @@ -1937,8 +1981,8 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, unresolved_type_action: UnresolvedTypeAction, mut lvalue_pref: LvaluePreference, mut should_stop: F) - -> (Ty<'tcx>, uint, Option) - where F: FnMut(Ty<'tcx>, uint) -> Option, + -> (Ty<'tcx>, usize, Option) + where F: FnMut(Ty<'tcx>, usize) -> Option, { debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={:?})", base_ty.repr(fcx.tcx()), @@ -2048,24 +2092,17 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, { match method { Some(method) => { - let ref_ty = // invoked methods have all LB regions instantiated - ty::no_late_bound_regions( - fcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap(); - match method_call { - Some(method_call) => { - fcx.inh.method_map.borrow_mut().insert(method_call, - method); - } - None => {} - } - match ref_ty { - ty::FnConverging(ref_ty) => { - ty::deref(ref_ty, true) - } - ty::FnDiverging => { - fcx.tcx().sess.bug("index/deref traits do not define a `!` return") - } + // extract method method return type, which will be &T; + // all LB regions should have been instantiated during method lookup + let ret_ty = ty::ty_fn_ret(method.ty); + let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap(); + + if let Some(method_call) = method_call { + fcx.inh.method_map.borrow_mut().insert(method_call, method); } + + // method returns &T, but the type as visible to user is T, so deref + ty::deref(ret_ty, true) } None => None, } @@ -2141,10 +2178,10 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // First, try built-in indexing. match (ty::index(adjusted_ty), &index_ty.sty) { - (Some(ty), &ty::ty_uint(ast::TyUs(_))) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => { + (Some(ty), &ty::ty_uint(ast::TyUs)) | (Some(ty), &ty::ty_infer(ty::IntVar(_))) => { debug!("try_index_step: success, using built-in indexing"); fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment)); - return Some((tcx.types.uint, ty)); + return Some((tcx.types.usize, ty)); } _ => {} } @@ -2194,7 +2231,6 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_fn_ty: Ty<'tcx>, callee_expr: &'tcx ast::Expr, args_no_rcvr: &'tcx [P], - autoref_args: AutorefArgs, tuple_arguments: TupleArgumentsFlag, expected: Expectation<'tcx>) -> ty::FnOutput<'tcx> { @@ -2211,7 +2247,6 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, &err_inputs[..], &[], args_no_rcvr, - autoref_args, false, tuple_arguments); ty::FnConverging(fcx.tcx().types.err) @@ -2229,7 +2264,6 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, &fty.sig.0.inputs[1..], &expected_arg_tys[..], args_no_rcvr, - autoref_args, fty.sig.0.variadic, tuple_arguments); fty.sig.0.output @@ -2249,7 +2283,6 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fn_inputs: &[Ty<'tcx>], expected_arg_tys: &[Ty<'tcx>], args: &'tcx [P], - autoref_args: AutorefArgs, variadic: bool, tuple_arguments: TupleArgumentsFlag) { let tcx = fcx.ccx.tcx; @@ -2275,7 +2308,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if arg_types.len() == 1 {""} else {"s"}, args.len(), if args.len() == 1 {" was"} else {"s were"}); - expected_arg_tys = &[][]; + expected_arg_tys = &[]; err_args(fcx.tcx(), args.len()) } else { expected_arg_tys = match expected_arg_tys.get(0) { @@ -2292,7 +2325,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span_err!(tcx.sess, sp, E0059, "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit"); - expected_arg_tys = &[][]; + expected_arg_tys = &[]; err_args(fcx.tcx(), args.len()) } } @@ -2309,7 +2342,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if expected_arg_count == 1 {""} else {"s"}, supplied_arg_count, if supplied_arg_count == 1 {" was"} else {"s were"}); - expected_arg_tys = &[][]; + expected_arg_tys = &[]; err_args(fcx.tcx(), supplied_arg_count) } } else { @@ -2319,7 +2352,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if expected_arg_count == 1 {""} else {"s"}, supplied_arg_count, if supplied_arg_count == 1 {" was"} else {"s were"}); - expected_arg_tys = &[][]; + expected_arg_tys = &[]; err_args(fcx.tcx(), supplied_arg_count) }; @@ -2362,26 +2395,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if is_block == check_blocks { debug!("checking the argument"); - let mut formal_ty = formal_tys[i]; - - match autoref_args { - AutorefArgs::Yes => { - match formal_ty.sty { - ty::ty_rptr(_, mt) => formal_ty = mt.ty, - ty::ty_err => (), - _ => { - // So we hit this case when one implements the - // operator traits but leaves an argument as - // just T instead of &T. We'll catch it in the - // mismatch impl/trait method phase no need to - // ICE here. - // See: #11450 - formal_ty = tcx.types.err; - } - } - } - AutorefArgs::No => {} - } + let formal_ty = formal_tys[i]; // The special-cased logic below has three functions: // 1. Provide as good of an expected type as possible. @@ -2445,7 +2459,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx. -fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec> { +fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: usize) -> Vec> { (0..len).map(|_| tcx.types.err).collect() } @@ -2468,10 +2482,11 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match lit.node { ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable), - ast::LitBinary(..) => { - ty::mk_slice(tcx, - tcx.mk_region(ty::ReStatic), - ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable }) + ast::LitBinary(ref v) => { + ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt { + ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())), + mutbl: ast::MutImmutable, + }) } ast::LitByte(_) => tcx.types.u8, ast::LitChar(_) => tcx.types.char, @@ -2482,8 +2497,8 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match ty.sty { ty::ty_int(_) | ty::ty_uint(_) => Some(ty), ty::ty_char => Some(tcx.types.u8), - ty::ty_ptr(..) => Some(tcx.types.uint), - ty::ty_bare_fn(..) => Some(tcx.types.uint), + ty::ty_ptr(..) => Some(tcx.types.usize), + ty::ty_bare_fn(..) => Some(tcx.types.usize), _ => None } }); @@ -2577,14 +2592,6 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, TypeAndSubsts { substs: substs, ty: substd_ty } } -// Controls whether the arguments are automatically referenced. This is useful -// for overloaded binary and unary operators. -#[derive(Copy, PartialEq)] -pub enum AutorefArgs { - Yes, - No, -} - /// Controls whether the arguments are tupled. This is used for the call /// operator. /// @@ -2592,7 +2599,7 @@ pub enum AutorefArgs { /// passed as a single parameter. For example, if tupling is enabled, this /// function: /// -/// fn f(x: (int, int)) +/// fn f(x: (isize, isize)) /// /// Can be called as: /// @@ -2698,7 +2705,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } Err(error) => { method::report_error(fcx, method_name.span, expr_t, - method_name.node.name, rcvr, error); + method_name.node.name, Some(rcvr), error); fcx.write_error(expr.id); fcx.tcx().types.err } @@ -2710,7 +2717,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fn_ty, expr, &args[1..], - AutorefArgs::No, DontTupleArguments, expected); @@ -2761,277 +2767,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, if_ty); } - fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>, - op_ex: &'tcx ast::Expr, - lhs_ty: Ty<'tcx>, - opname: ast::Name, - trait_did: Option, - lhs: &'a ast::Expr, - rhs: Option<&'tcx P>, - unbound_method: F, - autoref_args: AutorefArgs) -> Ty<'tcx> where - F: FnOnce(), - { - let method = match trait_did { - Some(trait_did) => { - // We do eager coercions to make using operators - // more ergonomic: - // - // - If the input is of type &'a T (resp. &'a mut T), - // then reborrow it to &'b T (resp. &'b mut T) where - // 'b <= 'a. This makes things like `x == y`, where - // `x` and `y` are both region pointers, work. We - // could also solve this with variance or different - // traits that don't force left and right to have same - // type. - let (adj_ty, adjustment) = match lhs_ty.sty { - ty::ty_rptr(r_in, mt) => { - let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span)); - fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, *r_in); - let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt); - let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None); - let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) }; - (adjusted_ty, adjustment) - } - _ => { - (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None }) - } - }; - - debug!("adjusted_ty={} adjustment={:?}", - adj_ty.repr(fcx.tcx()), - adjustment); - - method::lookup_in_trait_adjusted(fcx, op_ex.span, Some(lhs), opname, - trait_did, adjustment, adj_ty, None) - } - None => None - }; - let args = match rhs { - Some(rhs) => slice::ref_slice(rhs), - None => &[][] - }; - match method { - Some(method) => { - let method_ty = method.ty; - // HACK(eddyb) Fully qualified path to work around a resolve bug. - let method_call = ::middle::ty::MethodCall::expr(op_ex.id); - fcx.inh.method_map.borrow_mut().insert(method_call, method); - match check_method_argument_types(fcx, - op_ex.span, - method_ty, - op_ex, - args, - autoref_args, - DontTupleArguments, - NoExpectation) { - ty::FnConverging(result_type) => result_type, - ty::FnDiverging => fcx.tcx().types.err - } - } - None => { - unbound_method(); - // Check the args anyway - // so we get all the error messages - let expected_ty = fcx.tcx().types.err; - check_method_argument_types(fcx, - op_ex.span, - expected_ty, - op_ex, - args, - autoref_args, - DontTupleArguments, - NoExpectation); - fcx.tcx().types.err - } - } - } - - // could be either an expr_binop or an expr_assign_binop - fn check_binop<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, - expr: &'tcx ast::Expr, - op: ast::BinOp, - lhs: &'tcx ast::Expr, - rhs: &'tcx P, - is_binop_assignment: IsBinopAssignment) { - let tcx = fcx.ccx.tcx; - - let lvalue_pref = match is_binop_assignment { - BinopAssignment => PreferMutLvalue, - SimpleBinop => NoPreference - }; - check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref); - - // Callee does bot / err checking - let lhs_t = - structurally_resolve_type_or_else(fcx, lhs.span, fcx.expr_ty(lhs), || { - if ast_util::is_symmetric_binop(op.node) { - // Try RHS first - check_expr(fcx, &**rhs); - fcx.expr_ty(&**rhs) - } else { - fcx.tcx().types.err - } - }); - - if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op.node) { - // Shift is a special case: rhs must be uint, no matter what lhs is - check_expr(fcx, &**rhs); - let rhs_ty = fcx.expr_ty(&**rhs); - let rhs_ty = structurally_resolved_type(fcx, rhs.span, rhs_ty); - if ty::type_is_integral(rhs_ty) { - fcx.write_ty(expr.id, lhs_t); - } else { - fcx.type_error_message( - expr.span, - |actual| { - format!( - "right-hand-side of a shift operation must have integral type, \ - not `{}`", - actual) - }, - rhs_ty, - None); - fcx.write_ty(expr.id, fcx.tcx().types.err); - } - return; - } - - if ty::is_binopable(tcx, lhs_t, op) { - let tvar = fcx.infcx().next_ty_var(); - demand::suptype(fcx, expr.span, tvar, lhs_t); - check_expr_has_type(fcx, &**rhs, tvar); - - let result_t = match op.node { - ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe | - ast::BiGt => { - if ty::type_is_simd(tcx, lhs_t) { - if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) { - fcx.type_error_message(expr.span, - |actual| { - format!("binary comparison \ - operation `{}` not \ - supported for floating \ - point SIMD vector `{}`", - ast_util::binop_to_string(op.node), - actual) - }, - lhs_t, - None - ); - fcx.tcx().types.err - } else { - lhs_t - } - } else { - fcx.tcx().types.bool - } - }, - _ => lhs_t, - }; - - fcx.write_ty(expr.id, result_t); - return; - } - - if op.node == ast::BiOr || op.node == ast::BiAnd { - // This is an error; one of the operands must have the wrong - // type - fcx.write_error(expr.id); - fcx.write_error(rhs.id); - fcx.type_error_message(expr.span, - |actual| { - format!("binary operation `{}` cannot be applied \ - to type `{}`", - ast_util::binop_to_string(op.node), - actual) - }, - lhs_t, - None) - } - - // Check for overloaded operators if not an assignment. - let result_t = if is_binop_assignment == SimpleBinop { - check_user_binop(fcx, expr, lhs, lhs_t, op, rhs) - } else { - fcx.type_error_message(expr.span, - |actual| { - format!("binary assignment \ - operation `{}=` \ - cannot be applied to \ - type `{}`", - ast_util::binop_to_string(op.node), - actual) - }, - lhs_t, - None); - check_expr(fcx, &**rhs); - fcx.tcx().types.err - }; - - fcx.write_ty(expr.id, result_t); - if ty::type_is_error(result_t) { - fcx.write_ty(rhs.id, result_t); - } - } - - fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - ex: &'tcx ast::Expr, - lhs_expr: &'tcx ast::Expr, - lhs_resolved_t: Ty<'tcx>, - op: ast::BinOp, - rhs: &'tcx P) -> Ty<'tcx> { - let tcx = fcx.ccx.tcx; - let lang = &tcx.lang_items; - let (name, trait_did) = match op.node { - ast::BiAdd => ("add", lang.add_trait()), - ast::BiSub => ("sub", lang.sub_trait()), - ast::BiMul => ("mul", lang.mul_trait()), - ast::BiDiv => ("div", lang.div_trait()), - ast::BiRem => ("rem", lang.rem_trait()), - ast::BiBitXor => ("bitxor", lang.bitxor_trait()), - ast::BiBitAnd => ("bitand", lang.bitand_trait()), - ast::BiBitOr => ("bitor", lang.bitor_trait()), - ast::BiShl => ("shl", lang.shl_trait()), - ast::BiShr => ("shr", lang.shr_trait()), - ast::BiLt => ("lt", lang.ord_trait()), - ast::BiLe => ("le", lang.ord_trait()), - ast::BiGe => ("ge", lang.ord_trait()), - ast::BiGt => ("gt", lang.ord_trait()), - ast::BiEq => ("eq", lang.eq_trait()), - ast::BiNe => ("ne", lang.eq_trait()), - ast::BiAnd | ast::BiOr => { - check_expr(fcx, &**rhs); - return tcx.types.err; - } - }; - lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name), - trait_did, lhs_expr, Some(rhs), || { - fcx.type_error_message(ex.span, |actual| { - format!("binary operation `{}` cannot be applied to type `{}`", - ast_util::binop_to_string(op.node), - actual) - }, lhs_resolved_t, None) - }, if ast_util::is_by_value_binop(op.node) { AutorefArgs::No } else { AutorefArgs::Yes }) - } - - fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - op_str: &str, - mname: &str, - trait_did: Option, - ex: &'tcx ast::Expr, - rhs_expr: &'tcx ast::Expr, - rhs_t: Ty<'tcx>, - op: ast::UnOp) -> Ty<'tcx> { - lookup_op_method(fcx, ex, rhs_t, token::intern(mname), - trait_did, rhs_expr, None, || { - fcx.type_error_message(ex.span, |actual| { - format!("cannot apply unary operator `{}` to type `{}`", - op_str, actual) - }, rhs_t, None); - }, if ast_util::is_by_value_unop(op) { AutorefArgs::No } else { AutorefArgs::Yes }) - } - // Check field access expressions fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &'tcx ast::Expr, @@ -3078,7 +2813,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }, expr_t, None); - tcx.sess.span_help(field.span, + tcx.sess.fileline_help(field.span, "maybe a `()` to call it is missing? \ If not, try an anonymous function"); } else { @@ -3117,6 +2852,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, if skip.iter().any(|&x| x == n) { continue; } + // ignore private fields from non-local crates + if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public { + continue; + } let dist = lev_distance(n, name); if dist < best_dist { best = Some(n); @@ -3134,7 +2873,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, expr: &'tcx ast::Expr, lvalue_pref: LvaluePreference, base: &'tcx ast::Expr, - idx: codemap::Spanned) { + idx: codemap::Spanned) { let tcx = fcx.ccx.tcx; check_expr_with_lvalue_pref(fcx, base, lvalue_pref); let expr_t = structurally_resolved_type(fcx, expr.span, @@ -3285,7 +3024,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let mut missing_fields = Vec::new(); for class_field in field_types { let name = class_field.name; - let (_, seen) = class_field_map[name]; + let (_, seen) = *class_field_map.get(&name).unwrap(); if !seen { missing_fields.push( format!("`{}`", &token::get_name(name))) @@ -3404,10 +3143,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let mut checked = false; opt_place.as_ref().map(|place| match place.node { - ast::ExprPath(ref path) => { + ast::ExprPath(None, ref path) => { // FIXME(pcwalton): For now we hardcode the two permissible // places: the exchange heap and the managed heap. - let definition = lookup_def(fcx, path.span, place.id); + let definition = lookup_full_def(tcx, path.span, place.id); let def_id = definition.def_id(); let referent_ty = fcx.expr_ty(&**subexpr); if tcx.lang_items.exchange_heap() == Some(def_id) { @@ -3430,35 +3169,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, typ); } ast::ExprBinary(op, ref lhs, ref rhs) => { - check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop); - - let lhs_ty = fcx.expr_ty(&**lhs); - let rhs_ty = fcx.expr_ty(&**rhs); - if ty::type_is_error(lhs_ty) || - ty::type_is_error(rhs_ty) { - fcx.write_error(id); - } + op::check_binop(fcx, expr, op, lhs, rhs); } ast::ExprAssignOp(op, ref lhs, ref rhs) => { - check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment); - - let lhs_t = fcx.expr_ty(&**lhs); - let result_t = fcx.expr_ty(expr); - demand::suptype(fcx, expr.span, result_t, lhs_t); - - let tcx = fcx.tcx(); - if !ty::expr_is_lval(tcx, &**lhs) { - span_err!(tcx.sess, lhs.span, E0067, "illegal left-hand side expression"); - } - - fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized); - - // Overwrite result of check_binop...this preserves existing behavior - // but seems quite dubious with regard to user-defined methods - // and so forth. - Niko - if !ty::type_is_error(result_t) { - fcx.write_nil(expr.id); - } + op::check_binop_assign(fcx, expr, op, lhs, rhs); } ast::ExprUnary(unop, ref oprnd) => { let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| { @@ -3531,9 +3245,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, oprnd_t); if !(ty::type_is_integral(oprnd_t) || oprnd_t.sty == ty::ty_bool) { - oprnd_t = check_user_unop(fcx, "!", "not", - tcx.lang_items.not_trait(), - expr, &**oprnd, oprnd_t, unop); + oprnd_t = op::check_user_unop(fcx, "!", "not", + tcx.lang_items.not_trait(), + expr, &**oprnd, oprnd_t, unop); } } ast::UnNeg => { @@ -3541,9 +3255,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::type_is_fp(oprnd_t)) { - oprnd_t = check_user_unop(fcx, "-", "neg", - tcx.lang_items.neg_trait(), - expr, &**oprnd, oprnd_t, unop); + oprnd_t = op::check_user_unop(fcx, "-", "neg", + tcx.lang_items.neg_trait(), + expr, &**oprnd, oprnd_t, unop); + } + if let ty::ty_uint(_) = oprnd_t.sty { + if !tcx.sess.features.borrow().negate_unsigned { + feature_gate::emit_feature_err( + &tcx.sess.parse_sess.span_diagnostic, + "negate_unsigned", + expr.span, + "unary negation of unsigned integers may be removed in the future"); + } } } } @@ -3597,26 +3320,67 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }; fcx.write_ty(id, oprnd_t); } - ast::ExprPath(ref path) => { - let defn = lookup_def(fcx, path.span, id); - let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id); + ast::ExprPath(ref maybe_qself, ref path) => { + let opt_self_ty = maybe_qself.as_ref().map(|qself| { + fcx.to_ty(&qself.ty) + }); - // We always require that the type provided as the value for - // a type parameter outlives the moment of instantiation. - constrain_path_type_parameters(fcx, expr); - } - ast::ExprQPath(ref qpath) => { - // Require explicit type params for the trait. - let self_ty = fcx.to_ty(&*qpath.self_type); - astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None); - - let defn = lookup_def(fcx, expr.span, id); - let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - let mut path = qpath.trait_ref.path.clone(); - path.segments.push(qpath.item_path.clone()); - instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty), - defn, expr.span, expr.id); + let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { + d + } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself { + // Create some fake resolution that can't possibly be a type. + def::PathResolution { + base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)), + last_private: LastMod(AllPublic), + depth: path.segments.len() + } + } else { + tcx.sess.span_bug(expr.span, + &format!("unbound path {}", expr.repr(tcx))) + }; + + let def = path_res.base_def; + if path_res.depth == 0 { + let (scheme, predicates) = + type_scheme_and_predicates_for_def(fcx, expr.span, def); + instantiate_path(fcx, &path.segments, + scheme, &predicates, + opt_self_ty, def, expr.span, id); + } else { + let ty_segments = path.segments.init(); + let base_ty_end = path.segments.len() - path_res.depth; + let ty = astconv::finish_resolving_def_to_ty(fcx, + fcx, + expr.span, + PathParamMode::Optional, + &def, + opt_self_ty, + &ty_segments[..base_ty_end], + &ty_segments[base_ty_end..]); + let method_segment = path.segments.last().unwrap(); + let method_name = method_segment.identifier.name; + match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) { + Ok((def, lp)) => { + // Write back the new resolution. + tcx.def_map.borrow_mut().insert(id, def::PathResolution { + base_def: def, + last_private: path_res.last_private.or(lp), + depth: 0 + }); + + let (scheme, predicates) = + type_scheme_and_predicates_for_def(fcx, expr.span, def); + instantiate_path(fcx, slice::ref_slice(method_segment), + scheme, &predicates, + Some(ty), def, expr.span, id); + } + Err(error) => { + method::report_error(fcx, expr.span, ty, + method_name, None, error); + fcx.write_error(id); + } + } + } // We always require that the type provided as the value for // a type parameter outlives the moment of instantiation. @@ -3745,9 +3509,35 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprCast(ref e, ref t) => { if let ast::TyFixedLengthVec(_, ref count_expr) = t.node { - check_expr_with_hint(fcx, &**count_expr, tcx.types.uint); + check_expr_with_hint(fcx, &**count_expr, tcx.types.usize); + } + + // Find the type of `e`. Supply hints based on the type we are casting to, + // if appropriate. + let t_1 = fcx.to_ty(t); + let t_1 = structurally_resolved_type(fcx, expr.span, t_1); + check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1)); + let t_e = fcx.expr_ty(e); + + // Eagerly check for some obvious errors. + if ty::type_is_error(t_e) { + fcx.write_error(id); + } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) { + report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id); + } else { + // Write a type for the whole expression, assuming everything is going + // to work out Ok. + fcx.write_ty(id, t_1); + + // Defer other checks until we're done type checking. + let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut(); + deferred_cast_checks.push(CastCheck { + expr: (**e).clone(), + expr_ty: t_e, + cast_ty: t_1, + span: expr.span, + }); } - check_cast(fcx, expr, &**e, &**t); } ast::ExprVec(ref args) => { let uty = expected.to_option(fcx).and_then(|uty| { @@ -3776,7 +3566,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, fcx.write_ty(id, typ); } ast::ExprRepeat(ref element, ref count_expr) => { - check_expr_has_type(fcx, &**count_expr, tcx.types.uint); + check_expr_has_type(fcx, &**count_expr, tcx.types.usize); let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr); let uty = match expected { @@ -3851,14 +3641,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } ast::ExprStruct(ref path, ref fields, ref base_expr) => { // Resolve the path. - let def = tcx.def_map.borrow().get(&id).cloned(); + let def = lookup_full_def(tcx, path.span, id); let struct_id = match def { - Some(def::DefVariant(enum_id, variant_id, true)) => { + def::DefVariant(enum_id, variant_id, true) => { check_struct_enum_variant(fcx, id, expr.span, enum_id, variant_id, &fields[..]); enum_id } - Some(def::DefTrait(def_id)) => { + def::DefTrait(def_id) => { span_err!(tcx.sess, path.span, E0159, "use of trait `{}` as a struct constructor", pprust::path_to_string(path)); @@ -3868,7 +3658,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, base_expr); def_id }, - Some(def) => { + def => { // Verify that this was actually a struct. let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id()); match typ.ty.sty { @@ -3893,10 +3683,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, def.def_id() } - _ => { - tcx.sess.span_bug(path.span, - "structure constructor wasn't resolved") - } }; // Turn the path into a type and verify that that type unifies with @@ -3963,9 +3749,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, match result { Some((index_ty, element_ty)) => { - // FIXME: we've already checked idx above, we should - // probably just demand subtype or something here. - check_expr_has_type(fcx, &**idx, index_ty); + let idx_expr_ty = fcx.expr_ty(idx); + demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty); fcx.write_ty(id, element_ty); } _ => { @@ -4088,16 +3873,16 @@ impl<'tcx> Expectation<'tcx> { /// is useful in determining the concrete type. /// /// The primary use case is where the expected type is a fat pointer, - /// like `&[int]`. For example, consider the following statement: + /// like `&[isize]`. For example, consider the following statement: /// - /// let x: &[int] = &[1, 2, 3]; + /// let x: &[isize] = &[1, 2, 3]; /// /// In this case, the expected type for the `&[1, 2, 3]` expression is - /// `&[int]`. If however we were to say that `[1, 2, 3]` has the - /// expectation `ExpectHasType([int])`, that would be too strong -- - /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`. + /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the + /// expectation `ExpectHasType([isize])`, that would be too strong -- + /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`. /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced - /// to the type `&[int]`. Therefore, we propagate this more limited hint, + /// to the type `&[isize]`. Therefore, we propagate this more limited hint, /// which still is useful, because it informs integer literals and the like. /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169 /// for examples of where this comes up,. @@ -4165,11 +3950,27 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> { } pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, - nid: ast::NodeId, + local: &'tcx ast::Local, init: &'tcx ast::Expr) { - let local_ty = fcx.local_ty(init.span, nid); - check_expr_coercable_to_type(fcx, init, local_ty) + let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat); + + let local_ty = fcx.local_ty(init.span, local.id); + if !ref_bindings { + check_expr_coercable_to_type(fcx, init, local_ty) + } else { + // Somewhat subtle: if we have a `ref` binding in the pattern, + // we want to avoid introducing coercions for the RHS. This is + // both because it helps preserve sanity and, in the case of + // ref mut, for soundness (issue #23116). In particular, in + // the latter case, we need to be clear that the type of the + // referent for the reference that results is *equal to* the + // type of the lvalue it is referencing, and not some + // supertype thereof. + check_expr(fcx, init); + let init_ty = fcx.expr_ty(init); + demand::eqtype(fcx, init.span, init_ty, local_ty); + }; } pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) { @@ -4179,7 +3980,7 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) fcx.write_ty(local.id, t); if let Some(ref init) = local.init { - check_decl_initializer(fcx, local.id, &**init); + check_decl_initializer(fcx, local, &**init); let init_ty = fcx.expr_ty(&**init); if ty::type_is_error(init_ty) { fcx.write_ty(local.id, init_ty); @@ -4351,7 +4152,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let inh = static_inherited_fields(ccx); let rty = ty::node_id_to_type(ccx.tcx, id); let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); - let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty; + let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty; check_const_with_ty(&fcx, sp, e, declty); } @@ -4368,6 +4169,7 @@ fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, check_expr_with_hint(fcx, e, declty); demand::coerce(fcx, e.span, declty, e); vtable::select_all_fcx_obligations_or_error(fcx); + fcx.check_casts(); regionck::regionck_expr(fcx, e); writeback::resolve_type_vars_in_expr(fcx, e); } @@ -4421,7 +4223,7 @@ pub fn check_instantiable(tcx: &ty::ctxt, span_err!(tcx.sess, sp, E0073, "this type cannot be instantiated without an \ instance of itself"); - span_help!(tcx.sess, sp, "consider using `Option<{}>`", + fileline_help!(tcx.sess, sp, "consider using `Option<{}>`", ppaux::ty_to_string(tcx, item_ty)); false } else { @@ -4472,7 +4274,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ast::TyU16 => disr as u16 as Disr == disr, ast::TyU32 => disr as u32 as Disr == disr, ast::TyU64 => disr as u64 as Disr == disr, - ast::TyUs(_) => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr) + ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr) } } fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool { @@ -4481,7 +4283,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ast::TyI16 => disr as i16 as Disr == disr, ast::TyI32 => disr as i32 as Disr == disr, ast::TyI64 => disr as i64 as Disr == disr, - ast::TyIs(_) => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr) + ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr) } } match ty { @@ -4493,58 +4295,30 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, vs: &'tcx [P], id: ast::NodeId, - hint: attr::ReprAttr) - -> Vec>> { + hint: attr::ReprAttr) { + #![allow(trivial_numeric_casts)] let rty = ty::node_id_to_type(ccx.tcx, id); - let mut variants: Vec> = Vec::new(); let mut disr_vals: Vec = Vec::new(); - let mut prev_disr_val: Option = None; + let inh = static_inherited_fields(ccx); + let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id); + + let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint)); for v in vs { + if let Some(ref e) = v.node.disr_expr { + check_const_with_ty(&fcx, e.span, e, repr_type_ty); + } + } - // If the discriminant value is specified explicitly in the enum check whether the - // initialization expression is valid, otherwise use the last value plus one. - let mut current_disr_val = match prev_disr_val { - Some(prev_disr_val) => prev_disr_val + 1, - None => ty::INITIAL_DISCRIMINANT_VALUE - }; + let def_id = local_def(id); - match v.node.disr_expr { - Some(ref e) => { - debug!("disr expr, checking {}", pprust::expr_to_string(&**e)); + // ty::enum_variants guards against discriminant overflows, so + // we need not check for that. + let variants = ty::enum_variants(ccx.tcx, def_id); - let inh = static_inherited_fields(ccx); - let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id); - let declty = match hint { - attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int, - attr::ReprInt(_, attr::SignedInt(ity)) => { - ty::mk_mach_int(fcx.tcx(), ity) - } - attr::ReprInt(_, attr::UnsignedInt(ity)) => { - ty::mk_mach_uint(fcx.tcx(), ity) - }, - }; - check_const_with_ty(&fcx, e.span, &**e, declty); - // check_expr (from check_const pass) doesn't guarantee - // that the expression is in a form that eval_const_expr can - // handle, so we may still get an internal compiler error - - match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) { - Ok(const_eval::const_int(val)) => current_disr_val = val as Disr, - Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr, - Ok(_) => { - span_err!(ccx.tcx.sess, e.span, E0079, - "expected signed integer constant"); - } - Err(ref err) => { - span_err!(ccx.tcx.sess, e.span, E0080, - "expected constant: {}", *err); - } - } - }, - None => () - }; + for (v, variant) in vs.iter().zip(variants.iter()) { + let current_disr_val = variant.disr_val; // Check for duplicate discriminant values match disr_vals.iter().position(|&x| x == current_disr_val) { @@ -4572,19 +4346,11 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } disr_vals.push(current_disr_val); - - let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v, - current_disr_val)); - prev_disr_val = Some(current_disr_val); - - variants.push(variant_info); } - - return variants; } let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id }) - [].get(0).unwrap_or(&attr::ReprAny); + .get(0).unwrap_or(&attr::ReprAny); if hint != attr::ReprAny && vs.len() <= 1 { if vs.len() == 1 { @@ -4596,10 +4362,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, }; } - let variants = do_check(ccx, vs, id, hint); - - // cache so that ty::enum_variants won't repeat this work - ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants)); + do_check(ccx, vs, id, hint); check_representable(ccx.tcx, sp, id, "enum"); @@ -4610,10 +4373,6 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, check_instantiable(ccx.tcx, sp, id); } -pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def { - lookup_def_ccx(fcx.ccx, sp, id) -} - // Returns the type parameter count and the type for the given definition. fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, @@ -4625,7 +4384,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ }, ty::GenericPredicates::empty()) } - def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) | + def::DefFn(id, _) | def::DefMethod(id, _) | def::DefStatic(id, _) | def::DefVariant(_, id, _) | def::DefStruct(id) | def::DefConst(id) => { (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id)) @@ -4633,14 +4392,12 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefTrait(_) | def::DefTy(..) | def::DefAssociatedTy(..) | - def::DefAssociatedPath(..) | def::DefPrimTy(_) | def::DefTyParam(..) | def::DefMod(..) | def::DefForeignMod(..) | def::DefUse(..) | def::DefRegion(..) | - def::DefTyParamBinder(..) | def::DefLabel(..) | def::DefSelfTy(..) => { fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn)); @@ -4651,15 +4408,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - path: &ast::Path, + segments: &[ast::PathSegment], type_scheme: TypeScheme<'tcx>, type_predicates: &ty::GenericPredicates<'tcx>, opt_self_ty: Option>, def: def::Def, span: Span, node_id: ast::NodeId) { - debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})", - path.repr(fcx.tcx()), + debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})", + segments, def.repr(fcx.tcx()), node_id, type_scheme.repr(fcx.tcx())); @@ -4723,23 +4480,23 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // // The first step then is to categorize the segments appropriately. - assert!(path.segments.len() >= 1); + assert!(segments.len() >= 1); + + let mut ufcs_method = None; let mut segment_spaces: Vec<_>; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. def::DefSelfTy(..) | def::DefStruct(..) | def::DefVariant(..) | - def::DefTyParamBinder(..) | def::DefTy(..) | def::DefAssociatedTy(..) | - def::DefAssociatedPath(..) | def::DefTrait(..) | def::DefPrimTy(..) | def::DefTyParam(..) => { // Everything but the final segment should have no // parameters at all. - segment_spaces = repeat(None).take(path.segments.len() - 1).collect(); + segment_spaces = repeat(None).take(segments.len() - 1).collect(); segment_spaces.push(Some(subst::TypeSpace)); } @@ -4747,25 +4504,29 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefFn(..) | def::DefConst(..) | def::DefStatic(..) => { - segment_spaces = repeat(None).take(path.segments.len() - 1).collect(); + segment_spaces = repeat(None).take(segments.len() - 1).collect(); segment_spaces.push(Some(subst::FnSpace)); } // Case 3. Reference to a method. - def::DefStaticMethod(_, providence) | - def::DefMethod(_, _, providence) => { - assert!(path.segments.len() >= 2); - - match providence { + def::DefMethod(_, provenance) => { + match provenance { def::FromTrait(trait_did) => { callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did) } def::FromImpl(_) => {} } - segment_spaces = repeat(None).take(path.segments.len() - 2).collect(); - segment_spaces.push(Some(subst::TypeSpace)); - segment_spaces.push(Some(subst::FnSpace)); + if segments.len() >= 2 { + segment_spaces = repeat(None).take(segments.len() - 2).collect(); + segment_spaces.push(Some(subst::TypeSpace)); + segment_spaces.push(Some(subst::FnSpace)); + } else { + // `::method` will end up here, and so can `T::method`. + let self_ty = opt_self_ty.expect("UFCS sugared method missing Self"); + segment_spaces = vec![Some(subst::FnSpace)]; + ufcs_method = Some((provenance, self_ty)); + } } // Other cases. Various nonsense that really shouldn't show up @@ -4778,10 +4539,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, def::DefRegion(..) | def::DefLabel(..) | def::DefUpvar(..) => { - segment_spaces = repeat(None).take(path.segments.len()).collect(); + segment_spaces = repeat(None).take(segments.len()).collect(); } } - assert_eq!(segment_spaces.len(), path.segments.len()); + assert_eq!(segment_spaces.len(), segments.len()); + + // In `>::method`, `A` and `B` are mandatory, but + // `opt_self_ty` can also be Some for `Foo::method`, where Foo's + // type parameters are not mandatory. + let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none(); debug!("segment_spaces={:?}", segment_spaces); @@ -4795,16 +4561,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. let mut substs = Substs::empty(); - for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) { + for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) { match *opt_space { None => { - report_error_if_segment_contains_type_parameters(fcx, segment); + check_path_args(fcx.tcx(), slice::ref_slice(segment), + NO_TPS | NO_REGIONS); } Some(space) => { push_explicit_parameters_from_segment_to_substs(fcx, space, - path.span, + span, type_defs, region_defs, segment, @@ -4813,9 +4580,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } if let Some(self_ty) = opt_self_ty { - // `::foo` shouldn't have resolved to a `Self`-less item. - assert_eq!(type_defs.len(subst::SelfSpace), 1); - substs.types.push(subst::SelfSpace, self_ty); + if type_defs.len(subst::SelfSpace) == 1 { + substs.types.push(subst::SelfSpace, self_ty); + } } // Now we have to compare the types that the user *actually* @@ -4825,7 +4592,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // to add defaults. If the user provided *too many* types, that's // a problem. for &space in &ParamSpace::all() { - adjust_type_parameters(fcx, span, space, type_defs, &mut substs); + adjust_type_parameters(fcx, span, space, type_defs, + require_type_space, &mut substs); assert_eq!(substs.types.len(space), type_defs.len(space)); adjust_region_parameters(fcx, span, space, region_defs, &mut substs); @@ -4848,27 +4616,32 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // the referenced item. let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty); - fcx.write_ty(node_id, ty_substituted); - fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); - return; - fn report_error_if_segment_contains_type_parameters( - fcx: &FnCtxt, - segment: &ast::PathSegment) - { - for typ in &segment.parameters.types() { - span_err!(fcx.tcx().sess, typ.span, E0085, - "type parameters may not appear here"); - break; - } + if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method { + // In the case of `Foo::method` and `>::method`, if `method` + // is inherent, there is no `Self` parameter, instead, the impl needs + // type parameters, which we can infer by unifying the provided `Self` + // with the substituted impl type. + let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id); + assert_eq!(substs.types.len(subst::TypeSpace), + impl_scheme.generics.types.len(subst::TypeSpace)); + assert_eq!(substs.regions().len(subst::TypeSpace), + impl_scheme.generics.regions.len(subst::TypeSpace)); - for lifetime in &segment.parameters.lifetimes() { - span_err!(fcx.tcx().sess, lifetime.span, E0086, - "lifetime parameters may not appear here"); - break; + let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty); + if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() { + fcx.tcx().sess.span_bug(span, + &format!( + "instantiate_path: (UFCS) {} was a subtype of {} but now is not?", + self_ty.repr(fcx.tcx()), + impl_ty.repr(fcx.tcx()))); } } + fcx.write_ty(node_id, ty_substituted); + fcx.write_substs(node_id, ty::ItemSubsts { substs: substs }); + return; + /// Finds the parameters that the user provided and adds them to `substs`. If too many /// parameters are provided, then reports an error and clears the output vector. /// @@ -5003,6 +4776,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, space: ParamSpace, defs: &VecPerParamSpace>, + require_type_space: bool, substs: &mut Substs<'tcx>) { let provided_len = substs.types.len(space); @@ -5025,9 +4799,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Nothing specified at all: supply inference variables for // everything. - if provided_len == 0 { - substs.types.replace(space, - fcx.infcx().next_ty_vars(desired.len())); + if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) { + substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len())); return; } @@ -5145,22 +4918,19 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool { // inside the loop? (loop_query(&*b, |e| { match *e { - ast::ExprBreak(_) => true, + ast::ExprBreak(None) => true, _ => false } })) || - // Second: is there a labeled break with label - // nested anywhere inside the loop? + // Second: is there a labeled break with label + // nested anywhere inside the loop? (block_query(b, |e| { - match e.node { - ast::ExprBreak(Some(_)) => { - match cx.def_map.borrow().get(&e.id) { - Some(&def::DefLabel(loop_id)) if id == loop_id => true, - _ => false, - } - } - _ => false - }})) + if let ast::ExprBreak(Some(_)) = e.node { + lookup_full_def(cx, e.span, e.id) == def::DefLabel(id) + } else { + false + } + })) } pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -5178,7 +4948,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, match t.sty { ty::ty_param(ParamTy {idx, ..}) => { debug!("Found use of ty param num {}", idx); - tps_used[idx as uint] = true; + tps_used[idx as usize] = true; } _ => () } @@ -5237,8 +5007,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { let (n_tps, inputs, output) = match &name[..] { "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)), "size_of" | - "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.uint), - "init" => (1, Vec::new(), param(ccx, 0)), + "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize), + "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)), "uninit" => (1, Vec::new(), param(ccx, 0)), "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)), "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)), @@ -5256,17 +5026,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool), "owns_managed" => (1, Vec::new(), ccx.tcx.types.bool), - "get_tydesc" => { - let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) { - Ok(t) => t, - Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[..]); } - }; - let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { - ty: tydesc_ty, - mutbl: ast::MutImmutable - }); - (1, Vec::new(), td_ptr) - } + "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), + ast::MutImmutable)), "type_id" => (1, Vec::new(), ccx.tcx.types.u64), "offset" => { (1, @@ -5275,14 +5036,28 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty: param(ccx, 0), mutbl: ast::MutImmutable }), - ccx.tcx.types.int + ccx.tcx.types.isize ), ty::mk_ptr(tcx, ty::mt { ty: param(ccx, 0), mutbl: ast::MutImmutable })) } - "copy_memory" | "copy_nonoverlapping_memory" | + "copy" | "copy_nonoverlapping" => { + (1, + vec!( + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::MutImmutable + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::MutMutable + }), + tcx.types.usize, + ), + ty::mk_nil(tcx)) + } "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => { (1, vec!( @@ -5294,11 +5069,11 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { ty: param(ccx, 0), mutbl: ast::MutImmutable }), - tcx.types.uint, + tcx.types.usize, ), ty::mk_nil(tcx)) } - "set_memory" | "volatile_set_memory" => { + "write_bytes" | "volatile_set_memory" => { (1, vec!( ty::mk_ptr(tcx, ty::mt { @@ -5306,7 +5081,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { mutbl: ast::MutMutable }), tcx.types.u8, - tcx.types.uint, + tcx.types.usize, ), ty::mk_nil(tcx)) } @@ -5425,6 +5200,9 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { (0, vec!(tcx.types.u64, tcx.types.u64), ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))), + "overflowing_add" | "overflowing_sub" | "overflowing_mul" => + (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)), + "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)), "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)), diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs new file mode 100644 index 0000000000..49e88dc148 --- /dev/null +++ b/src/librustc_typeck/check/op.rs @@ -0,0 +1,481 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Code related to processing overloaded binary and unary operators. + +use super::{ + check_expr, + check_expr_coercable_to_type, + check_expr_with_lvalue_pref, + demand, + method, + FnCtxt, + PreferMutLvalue, + structurally_resolved_type, +}; +use middle::infer; +use middle::traits; +use middle::ty::{self, Ty}; +use syntax::ast; +use syntax::ast_util; +use syntax::parse::token; +use util::ppaux::{Repr, UserString}; + +/// Check a `a = b` +pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, + expr: &'tcx ast::Expr, + op: ast::BinOp, + lhs_expr: &'tcx ast::Expr, + rhs_expr: &'tcx ast::Expr) +{ + let tcx = fcx.ccx.tcx; + + check_expr_with_lvalue_pref(fcx, lhs_expr, PreferMutLvalue); + check_expr(fcx, rhs_expr); + + let lhs_ty = structurally_resolved_type(fcx, lhs_expr.span, fcx.expr_ty(lhs_expr)); + let rhs_ty = structurally_resolved_type(fcx, rhs_expr.span, fcx.expr_ty(rhs_expr)); + + if is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op) { + enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); + fcx.write_nil(expr.id); + } else { + // error types are considered "builtin" + assert!(!ty::type_is_error(lhs_ty) || !ty::type_is_error(rhs_ty)); + span_err!(tcx.sess, lhs_expr.span, E0368, + "binary assignment operation `{}=` cannot be applied to types `{}` and `{}`", + ast_util::binop_to_string(op.node), + lhs_ty.user_string(fcx.tcx()), + rhs_ty.user_string(fcx.tcx())); + fcx.write_error(expr.id); + } + + let tcx = fcx.tcx(); + if !ty::expr_is_lval(tcx, lhs_expr) { + span_err!(tcx.sess, lhs_expr.span, E0067, "illegal left-hand side expression"); + } + + fcx.require_expr_have_sized_type(lhs_expr, traits::AssignmentLhsSized); +} + +/// Check a potentially overloaded binary operator. +pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + expr: &'tcx ast::Expr, + op: ast::BinOp, + lhs_expr: &'tcx ast::Expr, + rhs_expr: &'tcx ast::Expr) +{ + let tcx = fcx.ccx.tcx; + + debug!("check_binop(expr.id={}, expr={}, op={:?}, lhs_expr={}, rhs_expr={})", + expr.id, + expr.repr(tcx), + op, + lhs_expr.repr(tcx), + rhs_expr.repr(tcx)); + + check_expr(fcx, lhs_expr); + let lhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr)); + + // Annoyingly, SIMD ops don't fit into the PartialEq/PartialOrd + // traits, because their return type is not bool. Perhaps this + // should change, but for now if LHS is SIMD we go down a + // different path that bypassess all traits. + if ty::type_is_simd(fcx.tcx(), lhs_ty) { + check_expr_coercable_to_type(fcx, rhs_expr, lhs_ty); + let rhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr)); + let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); + fcx.write_ty(expr.id, return_ty); + return; + } + + match BinOpCategory::from(op) { + BinOpCategory::Shortcircuit => { + // && and || are a simple case. + demand::suptype(fcx, lhs_expr.span, ty::mk_bool(tcx), lhs_ty); + check_expr_coercable_to_type(fcx, rhs_expr, ty::mk_bool(tcx)); + fcx.write_ty(expr.id, ty::mk_bool(tcx)); + } + _ => { + // Otherwise, we always treat operators as if they are + // overloaded. This is the way to be most flexible w/r/t + // types that get inferred. + let (rhs_ty, return_ty) = + check_overloaded_binop(fcx, expr, lhs_expr, lhs_ty, rhs_expr, op); + + // Supply type inference hints if relevant. Probably these + // hints should be enforced during select as part of the + // `consider_unification_despite_ambiguity` routine, but this + // more convenient for now. + // + // The basic idea is to help type inference by taking + // advantage of things we know about how the impls for + // scalar types are arranged. This is important in a + // scenario like `1_u32 << 2`, because it lets us quickly + // deduce that the result type should be `u32`, even + // though we don't know yet what type 2 has and hence + // can't pin this down to a specific impl. + let rhs_ty = fcx.resolve_type_vars_if_possible(rhs_ty); + if + !ty::type_is_ty_var(lhs_ty) && + !ty::type_is_ty_var(rhs_ty) && + is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op) + { + let builtin_return_ty = + enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); + demand::suptype(fcx, expr.span, builtin_return_ty, return_ty); + } + + fcx.write_ty(expr.id, return_ty); + } + } +} + +fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + lhs_expr: &'tcx ast::Expr, + lhs_ty: Ty<'tcx>, + rhs_expr: &'tcx ast::Expr, + rhs_ty: Ty<'tcx>, + op: ast::BinOp) + -> Ty<'tcx> +{ + debug_assert!(is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op)); + + let tcx = fcx.tcx(); + match BinOpCategory::from(op) { + BinOpCategory::Shortcircuit => { + demand::suptype(fcx, lhs_expr.span, ty::mk_bool(tcx), lhs_ty); + demand::suptype(fcx, rhs_expr.span, ty::mk_bool(tcx), rhs_ty); + ty::mk_bool(tcx) + } + + BinOpCategory::Shift => { + // For integers, the shift amount can be of any integral + // type. For simd, the type must match exactly. + if ty::type_is_simd(tcx, lhs_ty) { + demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty); + } + + // result type is same as LHS always + lhs_ty + } + + BinOpCategory::Math | + BinOpCategory::Bitwise => { + // both LHS and RHS and result will have the same type + demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty); + lhs_ty + } + + BinOpCategory::Comparison => { + // both LHS and RHS and result will have the same type + demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty); + + // if this is simd, result is same as lhs, else bool + if ty::type_is_simd(tcx, lhs_ty) { + let unit_ty = ty::simd_type(tcx, lhs_ty); + debug!("enforce_builtin_binop_types: lhs_ty={} unit_ty={}", + lhs_ty.repr(tcx), + unit_ty.repr(tcx)); + if !ty::type_is_integral(unit_ty) { + tcx.sess.span_err( + lhs_expr.span, + &format!("binary comparison operation `{}` not supported \ + for floating point SIMD vector `{}`", + ast_util::binop_to_string(op.node), + lhs_ty.user_string(tcx))); + tcx.types.err + } else { + lhs_ty + } + } else { + ty::mk_bool(tcx) + } + } + } +} + +fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + expr: &'tcx ast::Expr, + lhs_expr: &'tcx ast::Expr, + lhs_ty: Ty<'tcx>, + rhs_expr: &'tcx ast::Expr, + op: ast::BinOp) + -> (Ty<'tcx>, Ty<'tcx>) +{ + debug!("check_overloaded_binop(expr.id={}, lhs_ty={})", + expr.id, + lhs_ty.repr(fcx.tcx())); + + let (name, trait_def_id) = name_and_trait_def_id(fcx, op); + + // NB: As we have not yet type-checked the RHS, we don't have the + // type at hand. Make a variable to represent it. The whole reason + // for this indirection is so that, below, we can check the expr + // using this variable as the expected type, which sometimes lets + // us do better coercions than we would be able to do otherwise, + // particularly for things like `String + &String`. + let rhs_ty_var = fcx.infcx().next_ty_var(); + + let return_ty = match lookup_op_method(fcx, expr, lhs_ty, vec![rhs_ty_var], + token::intern(name), trait_def_id, + lhs_expr) { + Ok(return_ty) => return_ty, + Err(()) => { + // error types are considered "builtin" + if !ty::type_is_error(lhs_ty) { + span_err!(fcx.tcx().sess, lhs_expr.span, E0369, + "binary operation `{}` cannot be applied to type `{}`", + ast_util::binop_to_string(op.node), + lhs_ty.user_string(fcx.tcx())); + } + fcx.tcx().types.err + } + }; + + // see `NB` above + check_expr_coercable_to_type(fcx, rhs_expr, rhs_ty_var); + + (rhs_ty_var, return_ty) +} + +pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, + op_str: &str, + mname: &str, + trait_did: Option, + ex: &'tcx ast::Expr, + operand_expr: &'tcx ast::Expr, + operand_ty: Ty<'tcx>, + op: ast::UnOp) + -> Ty<'tcx> +{ + assert!(ast_util::is_by_value_unop(op)); + match lookup_op_method(fcx, ex, operand_ty, vec![], + token::intern(mname), trait_did, + operand_expr) { + Ok(t) => t, + Err(()) => { + fcx.type_error_message(ex.span, |actual| { + format!("cannot apply unary operator `{}` to type `{}`", + op_str, actual) + }, operand_ty, None); + fcx.tcx().types.err + } + } +} + +fn name_and_trait_def_id(fcx: &FnCtxt, op: ast::BinOp) -> (&'static str, Option) { + let lang = &fcx.tcx().lang_items; + match op.node { + ast::BiAdd => ("add", lang.add_trait()), + ast::BiSub => ("sub", lang.sub_trait()), + ast::BiMul => ("mul", lang.mul_trait()), + ast::BiDiv => ("div", lang.div_trait()), + ast::BiRem => ("rem", lang.rem_trait()), + ast::BiBitXor => ("bitxor", lang.bitxor_trait()), + ast::BiBitAnd => ("bitand", lang.bitand_trait()), + ast::BiBitOr => ("bitor", lang.bitor_trait()), + ast::BiShl => ("shl", lang.shl_trait()), + ast::BiShr => ("shr", lang.shr_trait()), + ast::BiLt => ("lt", lang.ord_trait()), + ast::BiLe => ("le", lang.ord_trait()), + ast::BiGe => ("ge", lang.ord_trait()), + ast::BiGt => ("gt", lang.ord_trait()), + ast::BiEq => ("eq", lang.eq_trait()), + ast::BiNe => ("ne", lang.eq_trait()), + ast::BiAnd | ast::BiOr => { + fcx.tcx().sess.span_bug(op.span, "&& and || are not overloadable") + } + } +} + +fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, + expr: &'tcx ast::Expr, + lhs_ty: Ty<'tcx>, + other_tys: Vec>, + opname: ast::Name, + trait_did: Option, + lhs_expr: &'a ast::Expr) + -> Result,()> +{ + debug!("lookup_op_method(expr={}, lhs_ty={}, opname={:?}, trait_did={}, lhs_expr={})", + expr.repr(fcx.tcx()), + lhs_ty.repr(fcx.tcx()), + opname, + trait_did.repr(fcx.tcx()), + lhs_expr.repr(fcx.tcx())); + + let method = match trait_did { + Some(trait_did) => { + // We do eager coercions to make using operators + // more ergonomic: + // + // - If the input is of type &'a T (resp. &'a mut T), + // then reborrow it to &'b T (resp. &'b mut T) where + // 'b <= 'a. This makes things like `x == y`, where + // `x` and `y` are both region pointers, work. We + // could also solve this with variance or different + // traits that don't force left and right to have same + // type. + let (adj_ty, adjustment) = match lhs_ty.sty { + ty::ty_rptr(r_in, mt) => { + let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs_expr.span)); + fcx.mk_subr(infer::Reborrow(lhs_expr.span), r_adj, *r_in); + let adjusted_ty = ty::mk_rptr(fcx.tcx(), fcx.tcx().mk_region(r_adj), mt); + let autoptr = ty::AutoPtr(r_adj, mt.mutbl, None); + let adjustment = ty::AutoDerefRef { autoderefs: 1, autoref: Some(autoptr) }; + (adjusted_ty, adjustment) + } + _ => { + (lhs_ty, ty::AutoDerefRef { autoderefs: 0, autoref: None }) + } + }; + + debug!("adjusted_ty={} adjustment={:?}", + adj_ty.repr(fcx.tcx()), + adjustment); + + method::lookup_in_trait_adjusted(fcx, expr.span, Some(lhs_expr), opname, + trait_did, adjustment, adj_ty, Some(other_tys)) + } + None => None + }; + + match method { + Some(method) => { + let method_ty = method.ty; + + // HACK(eddyb) Fully qualified path to work around a resolve bug. + let method_call = ::middle::ty::MethodCall::expr(expr.id); + fcx.inh.method_map.borrow_mut().insert(method_call, method); + + // extract return type for method; all late bound regions + // should have been instantiated by now + let ret_ty = ty::ty_fn_ret(method_ty); + Ok(ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap()) + } + None => { + Err(()) + } + } +} + +// Binary operator categories. These categories summarize the behavior +// with respect to the builtin operationrs supported. +enum BinOpCategory { + /// &&, || -- cannot be overridden + Shortcircuit, + + /// <<, >> -- when shifting a single integer, rhs can be any + /// integer type. For simd, types must match. + Shift, + + /// +, -, etc -- takes equal types, produces same type as input, + /// applicable to ints/floats/simd + Math, + + /// &, |, ^ -- takes equal types, produces same type as input, + /// applicable to ints/floats/simd/bool + Bitwise, + + /// ==, !=, etc -- takes equal types, produces bools, except for simd, + /// which produce the input type + Comparison, +} + +impl BinOpCategory { + fn from(op: ast::BinOp) -> BinOpCategory { + match op.node { + ast::BiShl | ast::BiShr => + BinOpCategory::Shift, + + ast::BiAdd | + ast::BiSub | + ast::BiMul | + ast::BiDiv | + ast::BiRem => + BinOpCategory::Math, + + ast::BiBitXor | + ast::BiBitAnd | + ast::BiBitOr => + BinOpCategory::Bitwise, + + ast::BiEq | + ast::BiNe | + ast::BiLt | + ast::BiLe | + ast::BiGe | + ast::BiGt => + BinOpCategory::Comparison, + + ast::BiAnd | + ast::BiOr => + BinOpCategory::Shortcircuit, + } + } +} + +/// Returns true if this is a built-in arithmetic operation (e.g. u32 +/// + u32, i16x4 == i16x4) and false if these types would have to be +/// overloaded to be legal. There are two reasons that we distinguish +/// builtin operations from overloaded ones (vs trying to drive +/// everything uniformly through the trait system and intrinsics or +/// something like that): +/// +/// 1. Builtin operations can trivially be evaluated in constants. +/// 2. For comparison operators applied to SIMD types the result is +/// not of type `bool`. For example, `i16x4==i16x4` yields a +/// type like `i16x4`. This means that the overloaded trait +/// `PartialEq` is not applicable. +/// +/// Reason #2 is the killer. I tried for a while to always use +/// overloaded logic and just check the types in constants/trans after +/// the fact, and it worked fine, except for SIMD types. -nmatsakis +fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>, + lhs: Ty<'tcx>, + rhs: Ty<'tcx>, + op: ast::BinOp) + -> bool +{ + match BinOpCategory::from(op) { + BinOpCategory::Shortcircuit => { + true + } + + BinOpCategory::Shift => { + ty::type_is_error(lhs) || ty::type_is_error(rhs) || + ty::type_is_integral(lhs) && ty::type_is_integral(rhs) || + ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs) + } + + BinOpCategory::Math => { + ty::type_is_error(lhs) || ty::type_is_error(rhs) || + ty::type_is_integral(lhs) && ty::type_is_integral(rhs) || + ty::type_is_floating_point(lhs) && ty::type_is_floating_point(rhs) || + ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs) + } + + BinOpCategory::Bitwise => { + ty::type_is_error(lhs) || ty::type_is_error(rhs) || + ty::type_is_integral(lhs) && ty::type_is_integral(rhs) || + ty::type_is_floating_point(lhs) && ty::type_is_floating_point(rhs) || + ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs) || + ty::type_is_bool(lhs) && ty::type_is_bool(rhs) + } + + BinOpCategory::Comparison => { + ty::type_is_error(lhs) || ty::type_is_error(rhs) || + ty::type_is_scalar(lhs) && ty::type_is_scalar(rhs) || + ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs) + } + } +} + diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 82abff8c42..9171367468 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -87,12 +87,11 @@ use check::dropck; use check::FnCtxt; use check::implicator; use check::vtable; -use middle::def; use middle::mem_categorization as mc; use middle::region::CodeExtent; +use middle::subst::Substs; use middle::traits; -use middle::ty::{ReScope}; -use middle::ty::{self, Ty, MethodCall}; +use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall}; use middle::infer::{self, GenericKind}; use middle::pat_util; use util::ppaux::{ty_to_string, Repr}; @@ -179,21 +178,7 @@ pub struct Rcx<'a, 'tcx: 'a> { } -/// Returns the validity region of `def` -- that is, how long is `def` valid? -fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region { - let tcx = fcx.tcx(); - match def { - def::DefLocal(node_id) | def::DefUpvar(node_id, _) => { - tcx.region_maps.var_region(node_id) - } - _ => { - tcx.sess.bug(&format!("unexpected def in region_of_def: {:?}", - def)[]) - } - } -} - -struct RepeatingScope(ast::NodeId); +pub struct RepeatingScope(ast::NodeId); pub enum SubjectNode { Subject(ast::NodeId), None } impl<'a, 'tcx> Rcx<'a, 'tcx> { @@ -240,7 +225,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { /// } /// ``` /// - /// Here, the region of `b` will be ``. `` is constrainted to be some subregion of the + /// Here, the region of `b` will be ``. `` is constrained to be some subregion of the /// block B and some superregion of the call. If we forced it now, we'd choose the smaller /// region (the call). But that would make the *b illegal. Since we don't resolve, the type /// of b will be `&.int` and then `*b` will require that `` be bigger than the let and @@ -288,7 +273,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { Some(f) => f, None => { self.tcx().sess.bug( - &format!("No fn-sig entry for id={}", id)[]); + &format!("No fn-sig entry for id={}", id)); } }; @@ -334,7 +319,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { /// This method populates the region map's `free_region_map`. It walks over the transformed /// argument and return types for each function just before we check the body of that function, /// looking for types where you have a borrowed pointer to other borrowed data (e.g., `&'a &'b - /// [uint]`. We do not allow references to outlive the things they point at, so we can assume + /// [usize]`. We do not allow references to outlive the things they point at, so we can assume /// that `'a <= 'b`. This holds for both the argument and return types, basically because, on /// the caller side, the caller is responsible for checking that the type of every expression /// (including the actual values for the arguments, as well as the return type of the fn call) @@ -368,7 +353,15 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { ty::ReInfer(ty::ReVar(vid_b))) => { self.fcx.inh.infcx.add_given(free_a, vid_b); } - implicator::Implication::RegionSubRegion(..) => { + implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => { + debug!("RegionSubGeneric: {} <= {}", + r_a.repr(tcx), generic_b.repr(tcx)); + + self.region_bound_pairs.push((r_a, generic_b.clone())); + } + implicator::Implication::RegionSubRegion(..) | + implicator::Implication::RegionSubClosure(..) | + implicator::Implication::Predicate(..) => { // In principle, we could record (and take // advantage of) every relationship here, but // we are also free not to -- it simply means @@ -379,13 +372,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { // relationship that arises here, but // presently we do not.) } - implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => { - debug!("RegionSubGeneric: {} <= {}", - r_a.repr(tcx), generic_b.repr(tcx)); - - self.region_bound_pairs.push((r_a, generic_b.clone())); - } - implicator::Implication::Predicate(..) => { } } } } @@ -554,8 +540,12 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { expr.span); } Err(..) => { - rcx.fcx.tcx().sess.span_note(expr.span, - "cat_expr_unadjusted Errd during dtor check"); + let tcx = rcx.fcx.tcx(); + if tcx.sess.has_errors() { + // cannot run dropck; okay b/c in error state anyway. + } else { + tcx.sess.span_bug(expr.span, "cat_expr_unadjusted Errd"); + } } } } @@ -571,8 +561,12 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { check_safety_of_rvalue_destructor_if_necessary(rcx, head_cmt, expr.span); } Err(..) => { - rcx.fcx.tcx().sess.span_note(expr.span, - "cat_expr Errd during dtor check"); + let tcx = rcx.fcx.tcx(); + if tcx.sess.has_errors() { + // cannot run dropck; okay b/c in error state anyway. + } else { + tcx.sess.span_bug(expr.span, "cat_expr Errd"); + } } } @@ -784,124 +778,9 @@ fn constrain_cast(rcx: &mut Rcx, fn check_expr_fn_block(rcx: &mut Rcx, expr: &ast::Expr, body: &ast::Block) { - let tcx = rcx.fcx.tcx(); - let function_type = rcx.resolve_node_type(expr.id); - - match function_type.sty { - ty::ty_closure(_, region, _) => { - ty::with_freevars(tcx, expr.id, |freevars| { - constrain_captured_variables(rcx, *region, expr, freevars); - }) - } - _ => { } - } - let repeating_scope = rcx.set_repeating_scope(body.id); visit::walk_expr(rcx, expr); rcx.set_repeating_scope(repeating_scope); - - match function_type.sty { - ty::ty_closure(_, region, _) => { - ty::with_freevars(tcx, expr.id, |freevars| { - let bounds = ty::region_existential_bound(*region); - ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars); - }) - } - _ => {} - } - - /// Make sure that the type of all free variables referenced inside a closure/proc outlive the - /// closure/proc's lifetime bound. This is just a special case of the usual rules about closed - /// over values outliving the object's lifetime bound. - fn ensure_free_variable_types_outlive_closure_bound( - rcx: &mut Rcx, - bounds: &ty::ExistentialBounds, - expr: &ast::Expr, - freevars: &[ty::Freevar]) - { - let tcx = rcx.fcx.ccx.tcx; - - debug!("ensure_free_variable_types_outlive_closure_bound({}, {})", - bounds.region_bound.repr(tcx), expr.repr(tcx)); - - for freevar in freevars { - let var_node_id = { - let def_id = freevar.def.def_id(); - assert!(def_id.krate == ast::LOCAL_CRATE); - def_id.node - }; - - // Compute the type of the field in the environment that - // represents `var_node_id`. For a by-value closure, this - // will be the same as the type of the variable. For a - // by-reference closure, this will be `&T` where `T` is - // the type of the variable. - let raw_var_ty = rcx.resolve_node_type(var_node_id); - let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; - let var_ty = match rcx.fcx.inh.upvar_capture_map.borrow()[upvar_id] { - ty::UpvarCapture::ByRef(ref upvar_borrow) => { - ty::mk_rptr(rcx.tcx(), - rcx.tcx().mk_region(upvar_borrow.region), - ty::mt { mutbl: upvar_borrow.kind.to_mutbl_lossy(), - ty: raw_var_ty }) - } - ty::UpvarCapture::ByValue => raw_var_ty, - }; - - // Check that the type meets the criteria of the existential bounds: - for builtin_bound in &bounds.builtin_bounds { - let code = traits::ClosureCapture(var_node_id, expr.span, builtin_bound); - let cause = traits::ObligationCause::new(freevar.span, rcx.fcx.body_id, code); - rcx.fcx.register_builtin_bound(var_ty, builtin_bound, cause); - } - - type_must_outlive( - rcx, infer::FreeVariable(expr.span, var_node_id), - var_ty, bounds.region_bound); - } - } - - /// Make sure that all free variables referenced inside the closure outlive the closure's - /// lifetime bound. Also, create an entry in the upvar_borrows map with a region. - fn constrain_captured_variables( - rcx: &mut Rcx, - region_bound: ty::Region, - expr: &ast::Expr, - freevars: &[ty::Freevar]) - { - let tcx = rcx.fcx.ccx.tcx; - debug!("constrain_captured_variables({}, {})", - region_bound.repr(tcx), expr.repr(tcx)); - for freevar in freevars { - debug!("constrain_captured_variables: freevar.def={:?}", freevar.def); - - // Identify the variable being closed over and its node-id. - let def = freevar.def; - let var_node_id = { - let def_id = def.def_id(); - assert!(def_id.krate == ast::LOCAL_CRATE); - def_id.node - }; - let upvar_id = ty::UpvarId { var_id: var_node_id, - closure_expr_id: expr.id }; - - match rcx.fcx.inh.upvar_capture_map.borrow()[upvar_id] { - ty::UpvarCapture::ByValue => { } - ty::UpvarCapture::ByRef(upvar_borrow) => { - rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id), - region_bound, upvar_borrow.region); - - // Guarantee that the closure does not outlive the variable itself. - let enclosing_region = region_of_def(rcx.fcx, def); - debug!("constrain_captured_variables: enclosing_region = {}", - enclosing_region.repr(tcx)); - rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id), - region_bound, enclosing_region); - } - } - } - } } fn constrain_callee(rcx: &mut Rcx, @@ -983,7 +862,7 @@ fn constrain_call<'a, I: Iterator>(rcx: &mut Rcx, /// dereferenced, the lifetime of the pointer includes the deref expr. fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, deref_expr: &ast::Expr, - derefs: uint, + derefs: usize, mut derefd_ty: Ty<'tcx>) { debug!("constrain_autoderefs(deref_expr={}, derefs={}, derefd_ty={})", @@ -1013,7 +892,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, rcx.tcx().sess.span_bug( deref_expr.span, &format!("bad overloaded deref type {}", - method.ty.repr(rcx.tcx()))[]) + method.ty.repr(rcx.tcx()))) } }; @@ -1084,9 +963,9 @@ fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 't rcx.tcx() .sess .span_bug(span, - format!("unexpected rvalue region in rvalue \ - destructor safety checking: `{}`", - region.repr(rcx.tcx())).as_slice()); + &format!("unexpected rvalue region in rvalue \ + destructor safety checking: `{}`", + region.repr(rcx.tcx()))); } } } @@ -1239,7 +1118,7 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, /// autoref'd. fn link_autoref(rcx: &Rcx, expr: &ast::Expr, - autoderefs: uint, + autoderefs: usize, autoref: &ty::AutoRef) { debug!("link_autoref(autoref={:?})", autoref); @@ -1417,7 +1296,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, rcx.tcx().sess.span_bug( span, &format!("Illegal upvar id: {}", - upvar_id.repr(rcx.tcx()))[]); + upvar_id.repr(rcx.tcx()))); } } } @@ -1530,6 +1409,9 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, let o1 = infer::ReferenceOutlivesReferent(ty, origin.span()); generic_must_outlive(rcx, o1, r_a, generic_b); } + implicator::Implication::RegionSubClosure(_, r_a, def_id, substs) => { + closure_must_outlive(rcx, origin.clone(), r_a, def_id, substs); + } implicator::Implication::Predicate(def_id, predicate) => { let cause = traits::ObligationCause::new(origin.span(), rcx.body_id, @@ -1541,6 +1423,23 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, } } +fn closure_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region, + def_id: ast::DefId, + substs: &'tcx Substs<'tcx>) { + debug!("closure_must_outlive(region={}, def_id={}, substs={})", + region.repr(rcx.tcx()), def_id.repr(rcx.tcx()), substs.repr(rcx.tcx())); + + let upvars = rcx.fcx.closure_upvars(def_id, substs).unwrap(); + for upvar in upvars { + let var_id = upvar.def.def_id().local_id(); + type_must_outlive( + rcx, infer::FreeVariable(origin.span(), var_id), + upvar.ty, region); + } +} + fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, origin: infer::SubregionOrigin<'tcx>, region: ty::Region, @@ -1562,7 +1461,7 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, GenericKind::Param(..) => { } GenericKind::Projection(ref projection_ty) => { param_bounds.push_all( - &projection_bounds(rcx, origin.span(), projection_ty)[]); + &projection_bounds(rcx, origin.span(), projection_ty)); } } @@ -1643,7 +1542,7 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>, debug!("projection_bounds: outlives={} (2)", outlives.repr(tcx)); - let region_result = infcx.try(|_| { + let region_result = infcx.commit_if_ok(|_| { let (outlives, _) = infcx.replace_late_bound_regions_with_fresh_var( span, diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index f452c8488c..340cca7d47 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -294,7 +294,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { /// Indicates that `cmt` is being directly mutated (e.g., assigned /// to). If cmt contains any by-ref upvars, this implies that - /// those upvars must be borrowed using an `&mut` borow. + /// those upvars must be borrowed using an `&mut` borrow. fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) { debug!("adjust_upvar_borrow_kind_for_mut(cmt={})", cmt.repr(self.tcx())); @@ -380,7 +380,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { // borrow_kind of the upvar to make sure it // is inferred to mutable if necessary let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut(); - let ub = &mut upvar_capture_map[upvar_id]; + let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); // also need to be in an FnMut closure since this is not an ImmBorrow @@ -448,7 +448,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { let closure_def_id = ast_util::local_def(closure_id); let mut closure_kinds = self.fcx.inh.closure_kinds.borrow_mut(); - let existing_kind = closure_kinds[closure_def_id]; + let existing_kind = *closure_kinds.get(&closure_def_id).unwrap(); debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", closure_id, existing_kind, new_kind); @@ -556,5 +556,3 @@ impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> { self.adjust_upvar_borrow_kind_for_mut(assignee_cmt); } } - - diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 3666b69d1c..63c34b65d7 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use check::{FnCtxt}; -use check::demand; +use check::FnCtxt; use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode}; use middle::traits::{Obligation, ObligationCause}; use middle::traits::report_fulfillment_errors; @@ -19,83 +18,6 @@ use syntax::codemap::Span; use util::nodemap::FnvHashSet; use util::ppaux::{Repr, UserString}; -pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - cast_expr: &ast::Expr, - source_expr: &ast::Expr, - target_object_ty: Ty<'tcx>) -{ - let tcx = fcx.tcx(); - debug!("check_object_cast(cast_expr={}, target_object_ty={})", - cast_expr.repr(tcx), - target_object_ty.repr(tcx)); - - // Look up vtables for the type we're casting to, - // passing in the source and target type. The source - // must be a pointer type suitable to the object sigil, - // e.g.: `&x as &Trait` or `box x as Box` - - // First, construct a fresh type that we can feed into `` - // within ` as ` to inform type inference (e.g. to - // tell it that we are expecting a `Box<_>` or an `&_`). - let fresh_ty = fcx.infcx().next_ty_var(); - let (object_trait_ty, source_expected_ty) = match target_object_ty.sty { - ty::ty_uniq(object_trait_ty) => { - (object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty)) - } - ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty, - mutbl: target_mutbl }) => { - (object_trait_ty, - ty::mk_rptr(fcx.tcx(), - target_region, ty::mt { ty: fresh_ty, - mutbl: target_mutbl })) - } - _ => { - fcx.tcx().sess.span_bug(source_expr.span, "expected object type"); - } - }; - - let source_ty = fcx.expr_ty(source_expr); - debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx)); - - // This ensures that the source_ty <: source_expected_ty, which - // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait` - // - // FIXME (pnkfelix): do we need to use suptype_with_fn in order to - // override the error message emitted when the types do not work - // out in the manner desired? - demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty); - - debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx)); - - let object_trait = object_trait(&object_trait_ty); - - // Ensure that if Ptr is cast to Ptr, then T : Trait. - push_cast_obligation(fcx, cast_expr, object_trait, fresh_ty); - check_object_safety(tcx, object_trait, source_expr.span); - - fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> { - match t.sty { - ty::ty_trait(ref ty_trait) => &**ty_trait, - _ => panic!("expected ty_trait") - } - } - - fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - cast_expr: &ast::Expr, - object_trait: &ty::TyTrait<'tcx>, - referent_ty: Ty<'tcx>) { - let object_trait_ref = - register_object_cast_obligations(fcx, - cast_expr.span, - object_trait, - referent_ty); - - // Finally record the object_trait_ref for use during trans - // (it would prob be better not to do this, but it's just kind - // of a pain to have to reconstruct it). - fcx.write_object_cast(cast_expr.id, object_trait_ref); - } -} // Check that a trait is 'object-safe'. This should be checked whenever a trait object // is created (by casting or coercion, etc.). A trait is object-safe if all its @@ -106,18 +28,17 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, object_trait: &ty::TyTrait<'tcx>, span: Span) { - let object_trait_ref = - object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err); + let trait_def_id = object_trait.principal_def_id(); - if traits::is_object_safe(tcx, object_trait_ref.clone()) { + if traits::is_object_safe(tcx, trait_def_id) { return; } span_err!(tcx.sess, span, E0038, "cannot convert to a trait object because trait `{}` is not object-safe", - ty::item_path_str(tcx, object_trait_ref.def_id())); + ty::item_path_str(tcx, trait_def_id)); - let violations = traits::object_safety_violations(tcx, object_trait_ref.clone()); + let violations = traits::object_safety_violations(tcx, trait_def_id); for violation in violations { match violation { ObjectSafetyViolation::SizedSelf => { @@ -133,14 +54,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, in the supertrait listing"); } - ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => { - tcx.sess.span_note( - span, - &format!("method `{}` has a receiver type of `Self`, \ - which cannot be used with a trait object", - method.name.user_string(tcx))); - } - ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => { tcx.sess.span_note( span, @@ -310,4 +223,3 @@ pub fn select_new_fcx_obligations(fcx: &FnCtxt) { Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); } } } - diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 2601c4d275..a86e2b17c9 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -22,8 +22,7 @@ use util::ppaux::{Repr, UserString}; use std::collections::HashSet; use syntax::ast; -use syntax::ast_util::{local_def}; -use syntax::attr; +use syntax::ast_util::local_def; use syntax::codemap::Span; use syntax::parse::token::{self, special_idents}; use syntax::visit; @@ -81,14 +80,17 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => { self.check_impl(item); } - ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id); + ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => { + let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id); + ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id); match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { Some(ty::BoundSend) | Some(ty::BoundSync) => {} Some(_) | None => { - span_err!(ccx.tcx.sess, item.span, E0192, - "negative impls are currently \ - allowed just for `Send` and `Sync`") + if !ty::trait_has_default_impl(ccx.tcx, trait_ref.def_id) { + span_err!(ccx.tcx.sess, item.span, E0192, + "negative impls are only allowed for traits with \ + default impls (e.g., `Send` and `Sync`)") + } } } } @@ -115,7 +117,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.check_variances_for_type_defn(item, ast_generics); } - ast::ItemTrait(_, ref ast_generics, _, _) => { + ast::ItemTrait(_, ref ast_generics, _, ref items) => { let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(item.id)); reject_non_type_param_bounds( @@ -124,6 +126,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &trait_predicates); self.check_variances(item, ast_generics, &trait_predicates, self.tcx().lang_items.phantom_fn()); + if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) { + if !items.is_empty() { + ccx.tcx.sess.span_err( + item.span, + "traits with default impls (`e.g. unsafe impl Trait for ..`) must \ + have no methods or associated items") + } + } } _ => {} } @@ -239,27 +249,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &fcx.inh.param_env.free_substs, &trait_ref); - // There are special rules that apply to drop. - if - fcx.tcx().lang_items.drop_trait() == Some(trait_ref.def_id) && - !attr::contains_name(&item.attrs, "unsafe_destructor") - { - match self_ty.sty { - ty::ty_struct(def_id, _) | - ty::ty_enum(def_id, _) => { - check_struct_safe_for_destructor(fcx, item.span, def_id); - } - _ => { - // Coherence already reports an error in this case. - } - } - } - - if fcx.tcx().lang_items.copy_trait() == Some(trait_ref.def_id) { - // This is checked in coherence. - return - } - // We are stricter on the trait-ref in an impl than the // self-type. In particular, we enforce region // relationships. The reason for this is that (at least @@ -278,12 +267,13 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { // Find the supertrait bounds. This will add `int:Bar`. let poly_trait_ref = ty::Binder(trait_ref); - let predicates = ty::predicates_for_trait_ref(fcx.tcx(), &poly_trait_ref); + let predicates = ty::lookup_super_predicates(fcx.tcx(), poly_trait_ref.def_id()); + let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref); let predicates = { let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx); traits::normalize(selcx, cause.clone(), &predicates) }; - for predicate in predicates.value { + for predicate in predicates.value.predicates { fcx.register_predicate(traits::Obligation::new(cause.clone(), predicate)); } for obligation in predicates.obligations { @@ -393,15 +383,15 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { self.tcx().sess.span_err( span, &format!("parameter `{}` is never used", - param_name.user_string(self.tcx()))[]); + param_name.user_string(self.tcx()))); match suggested_marker_id { Some(def_id) => { - self.tcx().sess.span_help( + self.tcx().sess.fileline_help( span, - format!("consider removing `{}` or using a marker such as `{}`", - param_name.user_string(self.tcx()), - ty::item_path_str(self.tcx(), def_id)).as_slice()); + &format!("consider removing `{}` or using a marker such as `{}`", + param_name.user_string(self.tcx()), + ty::item_path_str(self.tcx(), def_id))); } None => { // no lang items, no help! @@ -486,28 +476,24 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> { visit::walk_fn(self, fk, fd, b, span) } - fn visit_trait_item(&mut self, t: &'v ast::TraitItem) { - match t { - &ast::TraitItem::ProvidedMethod(_) | - &ast::TraitItem::TypeTraitItem(_) => {}, - &ast::TraitItem::RequiredMethod(ref method) => { - match ty::impl_or_trait_item(self.tcx(), local_def(method.id)) { - ty::ImplOrTraitItem::MethodTraitItem(ty_method) => { - reject_non_type_param_bounds( - self.tcx(), - method.span, - &ty_method.predicates); - reject_shadowing_type_parameters( - self.tcx(), - method.span, - &ty_method.generics); - } - _ => {} + fn visit_trait_item(&mut self, trait_item: &'v ast::TraitItem) { + if let ast::MethodTraitItem(_, None) = trait_item.node { + match ty::impl_or_trait_item(self.tcx(), local_def(trait_item.id)) { + ty::ImplOrTraitItem::MethodTraitItem(ty_method) => { + reject_non_type_param_bounds( + self.tcx(), + trait_item.span, + &ty_method.predicates); + reject_shadowing_type_parameters( + self.tcx(), + trait_item.span, + &ty_method.generics); } + _ => {} } } - visit::walk_trait_item(self, t) + visit::walk_trait_item(self, trait_item) } } @@ -520,7 +506,7 @@ pub struct BoundsChecker<'cx,'tcx:'cx> { // has left it as a NodeId rather than porting to CodeExtent. scope: ast::NodeId, - binding_count: uint, + binding_count: usize, cache: Option<&'cx mut HashSet>>, } @@ -753,22 +739,3 @@ fn filter_to_trait_obligations<'tcx>(bounds: ty::InstantiatedPredicates<'tcx>) } result } - -/////////////////////////////////////////////////////////////////////////// -// Special drop trait checking - -fn check_struct_safe_for_destructor<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - span: Span, - struct_did: ast::DefId) { - let struct_tpt = ty::lookup_item_type(fcx.tcx(), struct_did); - if struct_tpt.generics.has_type_params(subst::TypeSpace) - || struct_tpt.generics.has_region_params(subst::TypeSpace) - { - span_err!(fcx.tcx().sess, span, E0141, - "cannot implement a destructor on a structure \ - with type parameters"); - span_note!(fcx.tcx().sess, span, - "use \"#[unsafe_destructor]\" on the implementation \ - to force the compiler to allow this"); - } -} diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index fca40df7aa..37f4325248 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -26,6 +26,7 @@ use util::ppaux::Repr; use std::cell::Cell; use syntax::ast; +use syntax::ast_util; use syntax::codemap::{DUMMY_SP, Span}; use syntax::print::pprust::pat_to_string; use syntax::visit; @@ -113,6 +114,31 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { return; } + // Hacky hack: During type-checking, we treat *all* operators + // as potentially overloaded. But then, during writeback, if + // we observe that something like `a+b` is (known to be) + // operating on scalars, we clear the overload. + match e.node { + ast::ExprBinary(ref op, ref lhs, ref rhs) => { + let lhs_ty = self.fcx.expr_ty(lhs); + let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty); + let rhs_ty = self.fcx.expr_ty(rhs); + let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty); + if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) { + self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id)); + + // weird but true: the by-ref binops put an + // adjustment on the lhs but not the rhs; the + // adjustment for rhs is kind of baked into the + // system. + if !ast_util::is_by_value_binop(op.node) { + self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id); + } + } + } + _ => { } + } + self.visit_node_id(ResolvingExpr(e.span), e.id); self.visit_method_map_entry(ResolvingExpr(e.span), MethodCall::expr(e.id)); @@ -169,7 +195,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { match t.node { ast::TyFixedLengthVec(ref ty, ref count_expr) => { self.visit_ty(&**ty); - write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.uint); + write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.usize); } _ => visit::walk_ty(self, t) } @@ -265,6 +291,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ty::AdjustReifyFnPointer(def_id) } + ty::AdjustUnsafeFnPointer => { + ty::AdjustUnsafeFnPointer + } + ty::AdjustDerefRef(adj) => { for autoderef in 0..adj.autoderefs { let method_call = MethodCall::autoderef(id, autoderef); @@ -320,7 +350,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { /////////////////////////////////////////////////////////////////////////// // Resolution reason. -#[derive(Copy)] +#[derive(Copy, Clone)] enum ResolveReason { ResolvingExpr(Span), ResolvingLocal(Span), diff --git a/src/librustc_typeck/coherence/impls.rs b/src/librustc_typeck/coherence/impls.rs deleted file mode 100644 index e535b86a7b..0000000000 --- a/src/librustc_typeck/coherence/impls.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementations checker: builtin traits and default impls are allowed just -//! for structs and enums. - -use middle::ty; -use syntax::ast::{Item, ItemImpl}; -use syntax::ast; -use syntax::visit; - -pub fn check(tcx: &ty::ctxt) { - let mut impls = ImplsChecker { tcx: tcx }; - visit::walk_crate(&mut impls, tcx.map.krate()); -} - -struct ImplsChecker<'cx, 'tcx:'cx> { - tcx: &'cx ty::ctxt<'tcx> -} - -impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> { - fn visit_item(&mut self, item: &'v ast::Item) { - match item.node { - ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id); - if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { - match trait_ref.self_ty().sty { - ty::ty_struct(..) | ty::ty_enum(..) => {} - _ => { - span_err!(self.tcx.sess, item.span, E0209, - "builtin traits can only be \ - implemented on structs or enums"); - } - } - } - } - _ => {} - } - } -} diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 1542e74ff8..51d0c18872 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -25,15 +25,14 @@ use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type}; 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}; +use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int}; use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn}; -use middle::ty::{ty_projection}; +use middle::ty::ty_projection; use middle::ty; use CrateCtxt; -use middle::infer::combine::Combine; use middle::infer::InferCtxt; -use middle::infer::{new_infer_ctxt}; -use std::collections::{HashSet}; +use middle::infer::new_infer_ctxt; +use std::collections::HashSet; use std::cell::RefCell; use std::rc::Rc; use syntax::ast::{Crate, DefId}; @@ -42,14 +41,13 @@ use syntax::ast::{LOCAL_CRATE, TraitRef}; use syntax::ast; use syntax::ast_map::NodeItem; use syntax::ast_map; -use syntax::ast_util::{local_def}; -use syntax::codemap::{Span}; +use syntax::ast_util::local_def; +use syntax::codemap::Span; use syntax::parse::token; use syntax::visit; use util::nodemap::{DefIdMap, FnvHashMap}; use util::ppaux::Repr; -mod impls; mod orphan; mod overlap; mod unsafety; @@ -75,7 +73,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_tup(..) | - ty_param(..) | ty_err | ty_open(..) | + ty_param(..) | ty_err | ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => { None } @@ -86,7 +84,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>, inference_context.tcx.sess.span_bug( span, &format!("coherence encountered unexpected type searching for base type: {}", - ty.repr(inference_context.tcx))[]); + ty.repr(inference_context.tcx))); } } } @@ -106,19 +104,9 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> { //debug!("(checking coherence) item '{}'", token::get_ident(item.ident)); - match item.node { - ItemImpl(_, _, _, ref opt_trait, _, _) => { - match opt_trait.clone() { - Some(opt_trait) => { - self.cc.check_implementation(item, &[opt_trait]); - } - None => self.cc.check_implementation(item, &[]) - } - } - _ => { - // Nothing to do. - } - }; + if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node { + self.cc.check_implementation(item, opt_trait.as_ref()) + } visit::walk_item(self, item); } @@ -155,9 +143,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { self.check_implementations_of_copy(); } - fn check_implementation(&self, - item: &Item, - associated_traits: &[TraitRef]) { + fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) { let tcx = self.crate_context.tcx; let impl_did = local_def(item.id); let self_type = ty::lookup_item_type(tcx, impl_did); @@ -167,9 +153,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { let impl_items = self.create_impl_from_item(item); - for associated_trait in associated_traits { - let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx, - associated_trait.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id); debug!("(checking implementation) adding impl for trait '{}', item '{}'", trait_ref.repr(self.crate_context.tcx), token::get_ident(item.ident)); @@ -191,7 +176,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { } Some(base_type_def_id) => { // FIXME: Gather up default methods? - if associated_traits.len() == 0 { + if opt_trait.is_none() { self.add_inherent_impl(base_type_def_id, impl_did); } } @@ -283,34 +268,35 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { fn get_self_type_for_implementation(&self, impl_did: DefId) -> TypeScheme<'tcx> { - self.crate_context.tcx.tcache.borrow()[impl_did].clone() + self.crate_context.tcx.tcache.borrow().get(&impl_did).unwrap().clone() } // Converts an implementation in the AST to a vector of items. fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { - ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => { + ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => { let mut items: Vec = - ast_items.iter() - .map(|ast_item| { - match *ast_item { - ast::MethodImplItem(ref ast_method) => { - MethodTraitItemId( - local_def(ast_method.id)) - } - ast::TypeImplItem(ref typedef) => { - TypeTraitItemId(local_def(typedef.id)) - } - } - }).collect(); + impl_items.iter().map(|impl_item| { + match impl_item.node { + ast::MethodImplItem(..) => { + MethodTraitItemId(local_def(impl_item.id)) + } + ast::TypeImplItem(_) => { + TypeTraitItemId(local_def(impl_item.id)) + } + ast::MacImplItem(_) => { + self.crate_context.tcx.sess.span_bug(impl_item.span, + "unexpanded macro"); + } + } + }).collect(); - if let Some(ref trait_ref) = *trait_refs { - let ty_trait_ref = ty::node_id_to_trait_ref( - self.crate_context.tcx, - trait_ref.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, + item.id); self.instantiate_default_methods(local_def(item.id), - &*ty_trait_ref, + &*trait_ref, &mut items); } @@ -400,7 +386,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { }; for &impl_did in &*trait_impls.borrow() { - let items = &(*impl_items)[impl_did]; + let items = impl_items.get(&impl_did).unwrap(); if items.len() < 1 { // We'll error out later. For now, just don't ICE. continue; @@ -411,7 +397,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { match self_type.ty.sty { ty::ty_enum(type_def_id, _) | ty::ty_struct(type_def_id, _) | - ty::ty_closure(type_def_id, _, _) => { + ty::ty_closure(type_def_id, _) => { tcx.destructor_for_type .borrow_mut() .insert(type_def_id, method_def_id.def_id()); @@ -538,7 +524,7 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id: return // everything OK }; span_err!(tcx.sess, sp, E0183, "manual implementations of `{}` are experimental", trait_name); - span_help!(tcx.sess, sp, + fileline_help!(tcx.sess, sp, "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); } @@ -597,7 +583,6 @@ pub fn check_coherence(crate_context: &CrateCtxt) { inference_context: new_infer_ctxt(crate_context.tcx), inherent_impls: RefCell::new(FnvHashMap()), }.check(crate_context.tcx.map.krate()); - impls::check(crate_context.tcx); unsafety::check(crate_context.tcx); orphan::check(crate_context.tcx); overlap::check(crate_context.tcx); diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index f43469363c..b450e6b398 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -30,18 +30,38 @@ struct OrphanChecker<'cx, 'tcx:'cx> { } impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { - fn check_def_id(&self, span: Span, def_id: ast::DefId) { + fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) { if def_id.krate != ast::LOCAL_CRATE { - span_err!(self.tcx.sess, span, E0116, + span_err!(self.tcx.sess, item.span, E0116, "cannot associate methods with a type outside the \ crate the type is defined in; define and implement \ a trait or new type instead"); } } -} -impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { - fn visit_item(&mut self, item: &'v ast::Item) { + fn check_primitive_impl(&self, + impl_def_id: ast::DefId, + lang_def_id: Option, + lang: &str, + ty: &str, + span: Span) { + match lang_def_id { + Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ }, + _ => { + self.tcx.sess.span_err( + span, + &format!("only a single inherent implementation marked with `#[lang = \"{}\"]` \ + is allowed for the `{}` primitive", lang, ty)); + } + } + } + + /// Checks exactly one impl for orphan rules and other such + /// restrictions. In this fn, it can happen that multiple errors + /// apply to a specific impl, so just return after reporting one + /// to prevent inundating the user with a bunch of similar error + /// reports. + fn check_item(&self, item: &ast::Item) { let def_id = ast_util::local_def(item.id); match item.node { ast::ItemImpl(_, _, _, None, _, _) => { @@ -52,55 +72,278 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { match self_ty.sty { ty::ty_enum(def_id, _) | ty::ty_struct(def_id, _) => { - self.check_def_id(item.span, def_id); + self.check_def_id(item, def_id); } ty::ty_trait(ref data) => { - self.check_def_id(item.span, data.principal_def_id()); + self.check_def_id(item, data.principal_def_id()); } ty::ty_uniq(..) => { - self.check_def_id(item.span, - self.tcx.lang_items.owned_box() - .unwrap()); + self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap()); + } + ty::ty_char => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.char_impl(), + "char", + "char", + item.span); + } + ty::ty_str => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.str_impl(), + "str", + "str", + item.span); + } + ty::ty_vec(_, None) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.slice_impl(), + "slice", + "[T]", + item.span); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutImmutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.const_ptr_impl(), + "const_ptr", + "*const T", + item.span); + } + ty::ty_ptr(ty::mt { ty: _, mutbl: ast::MutMutable }) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.mut_ptr_impl(), + "mut_ptr", + "*mut T", + item.span); + } + ty::ty_int(ast::TyI8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i8_impl(), + "i8", + "i8", + item.span); + } + ty::ty_int(ast::TyI16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i16_impl(), + "i16", + "i16", + item.span); + } + ty::ty_int(ast::TyI32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i32_impl(), + "i32", + "i32", + item.span); + } + ty::ty_int(ast::TyI64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.i64_impl(), + "i64", + "i64", + item.span); + } + ty::ty_int(ast::TyIs) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.isize_impl(), + "isize", + "isize", + item.span); + } + ty::ty_uint(ast::TyU8) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u8_impl(), + "u8", + "u8", + item.span); + } + ty::ty_uint(ast::TyU16) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u16_impl(), + "u16", + "u16", + item.span); + } + ty::ty_uint(ast::TyU32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u32_impl(), + "u32", + "u32", + item.span); + } + ty::ty_uint(ast::TyU64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.u64_impl(), + "u64", + "u64", + item.span); + } + ty::ty_uint(ast::TyUs) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.usize_impl(), + "usize", + "usize", + item.span); + } + ty::ty_float(ast::TyF32) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f32_impl(), + "f32", + "f32", + item.span); + } + ty::ty_float(ast::TyF64) => { + self.check_primitive_impl(def_id, + self.tcx.lang_items.f64_impl(), + "f64", + "f64", + item.span); } _ => { span_err!(self.tcx.sess, item.span, E0118, "no base type found for inherent implementation; \ implement a trait or new type instead"); + return; } } } ast::ItemImpl(_, _, _, Some(_), _, _) => { // "Trait" impl debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx)); - let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id; + let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap(); + let trait_def_id = trait_ref.def_id; match traits::orphan_check(self.tcx, def_id) { Ok(()) => { } Err(traits::OrphanCheckErr::NoLocalInputType) => { - if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { - span_err!( - self.tcx.sess, item.span, E0117, - "the impl does not reference any \ - types defined in this crate; \ - only traits defined in the current crate can be \ - implemented for arbitrary types"); - } + span_err!( + self.tcx.sess, item.span, E0117, + "the impl does not reference any \ + types defined in this crate; \ + only traits defined in the current crate can be \ + implemented for arbitrary types"); + return; } Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { - if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") { - span_err!(self.tcx.sess, item.span, E0210, - "type parameter `{}` must be used as the type parameter for \ - some local type (e.g. `MyStruct`); only traits defined in \ - the current crate can be implemented for a type parameter", - param_ty.user_string(self.tcx)); + span_err!(self.tcx.sess, item.span, E0210, + "type parameter `{}` must be used as the type parameter for \ + some local type (e.g. `MyStruct`); only traits defined in \ + the current crate can be implemented for a type parameter", + param_ty.user_string(self.tcx)); + return; + } + } + + // In addition to the above rules, we restrict impls of defaulted traits + // so that they can only be implemented on structs/enums. To see why this + // restriction exists, consider the following example (#22978). Imagine + // that crate A defines a defaulted trait `Foo` and a fn that operates + // on pairs of types: + // + // ``` + // // Crate A + // trait Foo { } + // impl Foo for .. { } + // fn two_foos(..) { + // one_foo::<(A,B)>(..) + // } + // fn one_foo(..) { .. } + // ``` + // + // This type-checks fine; in particular the fn + // `two_foos` is able to conclude that `(A,B):Foo` + // because `A:Foo` and `B:Foo`. + // + // Now imagine that crate B comes along and does the following: + // + // ``` + // struct A { } + // struct B { } + // impl Foo for A { } + // impl Foo for B { } + // impl !Send for (A, B) { } + // ``` + // + // This final impl is legal according to the orpan + // rules, but it invalidates the reasoning from + // `two_foos` above. + debug!("trait_ref={} trait_def_id={} trait_has_default_impl={}", + trait_ref.repr(self.tcx), + trait_def_id.repr(self.tcx), + ty::trait_has_default_impl(self.tcx, trait_def_id)); + if + ty::trait_has_default_impl(self.tcx, trait_def_id) && + trait_def_id.krate != ast::LOCAL_CRATE + { + let self_ty = trait_ref.self_ty(); + let opt_self_def_id = match self_ty.sty { + ty::ty_struct(self_def_id, _) | ty::ty_enum(self_def_id, _) => + Some(self_def_id), + ty::ty_uniq(..) => + self.tcx.lang_items.owned_box(), + _ => + None + }; + + let msg = match opt_self_def_id { + // We only want to permit structs/enums, but not *all* structs/enums. + // They must be local to the current crate, so that people + // can't do `unsafe impl Send for Rc` or + // `impl !Send for Box`. + Some(self_def_id) => { + if self_def_id.krate == ast::LOCAL_CRATE { + None + } else { + Some(format!( + "cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type \ + defined in the current crate", + ty::item_path_str(self.tcx, trait_def_id))) + } + } + _ => { + Some(format!( + "cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type, \ + not `{}`", + ty::item_path_str(self.tcx, trait_def_id), + self_ty.user_string(self.tcx))) } + }; + + if let Some(msg) = msg { + span_err!(self.tcx.sess, item.span, E0321, "{}", msg); + return; } } + + // Disallow *all* explicit impls of `Sized` for now. + if Some(trait_def_id) == self.tcx.lang_items.sized_trait() { + span_err!(self.tcx.sess, item.span, E0322, + "explicit impls for the `Sized` trait are not permitted"); + return; + } + } + ast::ItemDefaultImpl(..) => { + // "Trait" impl + debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx)); + let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap(); + if trait_ref.def_id.krate != ast::LOCAL_CRATE { + span_err!(self.tcx.sess, item.span, E0318, + "cannot create default implementations for traits outside the \ + crate they're defined in; define a new trait instead"); + return; + } } _ => { // Not an impl } } + } +} +impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { + fn visit_item(&mut self, item: &ast::Item) { + self.check_item(item); visit::walk_item(self, item); } } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 403dcf1e25..f8ca51b9e4 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -14,19 +14,29 @@ use middle::traits; use middle::ty; use middle::infer::{self, new_infer_ctxt}; -use syntax::ast::{DefId}; -use syntax::ast::{LOCAL_CRATE}; +use syntax::ast::DefId; +use syntax::ast::LOCAL_CRATE; use syntax::ast; -use syntax::codemap::{Span}; +use syntax::ast_util; +use syntax::visit; +use syntax::codemap::Span; +use util::nodemap::DefIdMap; use util::ppaux::Repr; pub fn check(tcx: &ty::ctxt) { - let overlap = OverlapChecker { tcx: tcx }; + let mut overlap = OverlapChecker { tcx: tcx, default_impls: DefIdMap() }; overlap.check_for_overlapping_impls(); + + // this secondary walk specifically checks for impls of defaulted + // traits, for which additional overlap rules exist + visit::walk_crate(&mut overlap, tcx.map.krate()); } struct OverlapChecker<'cx, 'tcx:'cx> { - tcx: &'cx ty::ctxt<'tcx> + tcx: &'cx ty::ctxt<'tcx>, + + // maps from a trait def-id to an impl id + default_impls: DefIdMap, } impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { @@ -90,17 +100,28 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { return; } - span_err!(self.tcx.sess, self.span_of_impl(impl1_def_id), E0119, + self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id); + } + + fn report_overlap_error(&self, trait_def_id: ast::DefId, + impl1: ast::DefId, impl2: ast::DefId) { + + span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119, "conflicting implementations for trait `{}`", ty::item_path_str(self.tcx, trait_def_id)); - if impl2_def_id.krate == ast::LOCAL_CRATE { - span_note!(self.tcx.sess, self.span_of_impl(impl2_def_id), + self.report_overlap_note(impl1, impl2); + } + + fn report_overlap_note(&self, impl1: ast::DefId, impl2: ast::DefId) { + + if impl2.krate == ast::LOCAL_CRATE { + span_note!(self.tcx.sess, self.span_of_impl(impl2), "note conflicting implementation here"); } else { let crate_store = &self.tcx.sess.cstore; - let cdata = crate_store.get_crate_data(impl2_def_id.krate); - span_note!(self.tcx.sess, self.span_of_impl(impl1_def_id), + let cdata = crate_store.get_crate_data(impl2.krate); + span_note!(self.tcx.sess, self.span_of_impl(impl1), "conflicting implementation in crate `{}`", cdata.name); } @@ -111,3 +132,28 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { self.tcx.map.span(impl_did.node) } } + + +impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { + fn visit_item(&mut self, item: &'v ast::Item) { + match item.node { + ast::ItemDefaultImpl(_, _) => { + // look for another default impl; note that due to the + // general orphan/coherence rules, it must always be + // in this crate. + let impl_def_id = ast_util::local_def(item.id); + let trait_ref = ty::impl_trait_ref(self.tcx, impl_def_id).unwrap(); + let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id); + match prev_default_impl { + Some(prev_id) => { + self.report_overlap_error(trait_ref.def_id, + impl_def_id, + ast_util::local_def(prev_id)); + } + None => { } + } + } + _ => {} + } + } +} diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 867dea9588..e4926b119d 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -27,55 +27,66 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> { tcx: &'cx ty::ctxt<'tcx> } -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, polarity, _, _, _, _) => { - match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) { - None => { - // Inherent impl. - match unsafety { - ast::Unsafety::Normal => { /* OK */ } - ast::Unsafety::Unsafe => { - span_err!(self.tcx.sess, item.span, E0197, - "inherent impls cannot be declared as unsafe"); - } - } +impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { + fn check_unsafety_coherence(&mut self, item: &'v ast::Item, + unsafety: ast::Unsafety, + polarity: ast::ImplPolarity) { + match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) { + None => { + // Inherent impl. + match unsafety { + ast::Unsafety::Normal => { /* OK */ } + ast::Unsafety::Unsafe => { + span_err!(self.tcx.sess, item.span, E0197, + "inherent impls cannot be declared as unsafe"); } + } + } - Some(trait_ref) => { - let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id); - match (trait_def.unsafety, unsafety, polarity) { - (ast::Unsafety::Unsafe, - ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => { - span_err!(self.tcx.sess, item.span, E0198, - "negative implementations are not unsafe"); - } + Some(trait_ref) => { + let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id); + match (trait_def.unsafety, unsafety, polarity) { + (ast::Unsafety::Unsafe, + ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => { + span_err!(self.tcx.sess, item.span, E0198, + "negative implementations are not unsafe"); + } - (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => { - span_err!(self.tcx.sess, item.span, E0199, - "implementing the trait `{}` is not unsafe", - trait_ref.user_string(self.tcx)); - } + (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => { + span_err!(self.tcx.sess, item.span, E0199, + "implementing the trait `{}` is not unsafe", + trait_ref.user_string(self.tcx)); + } - (ast::Unsafety::Unsafe, - ast::Unsafety::Normal, ast::ImplPolarity::Positive) => { - span_err!(self.tcx.sess, item.span, E0200, - "the trait `{}` requires an `unsafe impl` declaration", - trait_ref.user_string(self.tcx)); - } + (ast::Unsafety::Unsafe, + ast::Unsafety::Normal, ast::ImplPolarity::Positive) => { + span_err!(self.tcx.sess, item.span, E0200, + "the trait `{}` requires an `unsafe impl` declaration", + trait_ref.user_string(self.tcx)); + } - (ast::Unsafety::Unsafe, - ast::Unsafety::Normal, ast::ImplPolarity::Negative) | - (ast::Unsafety::Unsafe, - ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) | - (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => { - /* OK */ - } - } + (ast::Unsafety::Unsafe, + ast::Unsafety::Normal, ast::ImplPolarity::Negative) | + (ast::Unsafety::Unsafe, + ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) | + (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => { + /* OK */ } } } + } + } +} + +impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { + fn visit_item(&mut self, item: &'v ast::Item) { + match item.node { + ast::ItemDefaultImpl(unsafety, _) => { + self.check_unsafety_coherence(item, unsafety, ast::ImplPolarity::Positive); + } + ast::ItemImpl(unsafety, polarity, _, _, _, _) => { + self.check_unsafety_coherence(item, unsafety, polarity); + } _ => { } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0b78af18e2..8f1b8bf109 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -26,35 +26,17 @@ represented by an instance of `ty::TypeScheme`. This combines the core type along with a list of the bounds for each parameter. Type parameters themselves are represented as `ty_param()` instances. -The phasing of type conversion is somewhat complicated. There are a -number of possible cycles that can arise. - -Converting types can require: - -1. `Foo` where `Foo` is a type alias, or trait requires knowing: - - number of region / type parameters - - for type parameters, `T:'a` annotations to control defaults for object lifetimes - - defaults for type parameters (which are themselves types!) -2. `Foo` where `Foo` is a type alias requires knowing what `Foo` expands to -3. Translating `SomeTrait` with no explicit lifetime bound requires knowing - - supertraits of `SomeTrait` -4. Translating `T::X` (vs `::X`) requires knowing - - bounds on `T` - - supertraits of those bounds - -So as you can see, in general translating types requires knowing the -trait hierarchy. But this gets a bit tricky because translating the -trait hierarchy requires converting the types that appear in trait -references. One potential saving grace is that in general knowing the -trait hierarchy is only necessary for shorthands like `T::X` or -handling omitted lifetime bounds on object types. Therefore, if we are -lazy about expanding out the trait hierachy, users can sever cycles if -necessary. Lazy expansion is also needed for type aliases. - -This system is not perfect yet. Currently, we "convert" types and -traits in three phases (note that conversion only affects the types of -items / enum variants / methods; it does not e.g. compute the types of -individual expressions): +The phasing of type conversion is somewhat complicated. There is no +clear set of phases we can enforce (e.g., converting traits first, +then types, or something like that) because the user can introduce +arbitrary interdependencies. So instead we generally convert things +lazilly and on demand, and include logic that checks for cycles. +Demand is driven by calls to `AstConv::get_item_type_scheme` or +`AstConv::lookup_trait_def`. + +Currently, we "convert" types and traits in three phases (note that +conversion only affects the types of items / enum variants / methods; +it does not e.g. compute the types of individual expressions): 0. Intrinsics 1. Trait definitions @@ -64,16 +46,13 @@ Conversion itself is done by simply walking each of the items in turn and invoking an appropriate function (e.g., `trait_def_of_item` or `convert_item`). However, it is possible that while converting an item, we may need to compute the *type scheme* or *trait definition* -for other items. This is a kind of shallow conversion that is -triggered on demand by calls to `AstConv::get_item_type_scheme` or -`AstConv::lookup_trait_def`. It is possible for cycles to result from -this (e.g., `type A = B; type B = A;`), in which case astconv -(currently) reports the error. +for other items. There are some shortcomings in this design: -- Cycles through trait definitions (e.g. supertraits) are not currently - detected by astconv. (#12511) +- Before walking the set of supertraits for a given trait, you must + call `ensure_super_predicates` on that trait def-id. Otherwise, + `lookup_super_predicates` will result in ICEs. - Because the type scheme includes defaults, cycles through type parameter defaults are illegal even if those defaults are never employed. This is not necessarily a bug. @@ -91,28 +70,28 @@ use constrained_type_params::identify_constrained_type_params; use middle::lang_items::SizedTraitLangItem; use middle::region; use middle::resolve_lifetime; -use middle::subst; -use middle::subst::{Substs, SelfSpace, TypeSpace, VecPerParamSpace}; +use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; -use middle::ty::{self, RegionEscape, Ty, TypeScheme}; +use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme}; use middle::ty_fold::{self, TypeFolder, TypeFoldable}; use middle::infer; use rscope::*; -use util::common::memoized; +use util::common::{ErrorReported, memoized}; use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux; use util::ppaux::{Repr,UserString}; use write_ty_to_tcx; +use std::cell::RefCell; use std::collections::HashSet; use std::rc::Rc; use syntax::abi; use syntax::ast; use syntax::ast_map; -use syntax::ast_util::{local_def, PostExpansionMethod}; +use syntax::ast_util::local_def; use syntax::codemap::Span; -use syntax::parse::token::{special_idents}; +use syntax::parse::token::special_idents; use syntax::parse::token; use syntax::ptr::P; use syntax::visit; @@ -121,16 +100,7 @@ use syntax::visit; // Main entry point 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); } - None => {} - } - match ccx.tcx.lang_items.opaque() { - Some(id) => { collect_intrinsic_type(ccx, id); } - None => {} - } + let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) }; let mut visitor = CollectTraitDefVisitor{ ccx: ccx }; visit::walk_crate(&mut visitor, ccx.tcx.map.krate()); @@ -141,18 +111,36 @@ pub fn collect_item_types(tcx: &ty::ctxt) { /////////////////////////////////////////////////////////////////////////// -struct CollectCtxt<'a,'tcx:'a> { +struct CrateCtxt<'a,'tcx:'a> { tcx: &'a ty::ctxt<'tcx>, + + // This stack is used to identify cycles in the user's source. + // Note that these cycles can cross multiple items. + stack: RefCell>, } -/////////////////////////////////////////////////////////////////////////// -// Zeroth phase: collect types of intrinsics +/// Context specific to some particular item. This is what implements +/// AstConv. It has information about the predicates that are defined +/// on the trait. Unfortunately, this predicate information is +/// available in various different forms at various points in the +/// process. So we can't just store a pointer to e.g. the AST or the +/// parsed ty form, we have to be more flexible. To this end, the +/// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object +/// that it uses to satisfy `get_type_parameter_bounds` requests. +/// This object might draw the information from the AST +/// (`ast::Generics`) or it might draw from a `ty::GenericPredicates` +/// or both (a tuple). +struct ItemCtxt<'a,'tcx:'a> { + ccx: &'a CrateCtxt<'a,'tcx>, + param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a), +} -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); +#[derive(Copy, Clone, PartialEq, Eq)] +enum AstConvRequest { + GetItemTypeScheme(ast::DefId), + GetTraitDef(ast::DefId), + EnsureSuperPredicates(ast::DefId), + GetTypeParameterBounds(ast::NodeId), } /////////////////////////////////////////////////////////////////////////// @@ -161,7 +149,7 @@ fn collect_intrinsic_type(ccx: &CollectCtxt, // know later when parsing field defs. struct CollectTraitDefVisitor<'a, 'tcx: 'a> { - ccx: &'a CollectCtxt<'a, 'tcx> + ccx: &'a CrateCtxt<'a, 'tcx> } impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> { @@ -182,7 +170,7 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> { // Second phase: collection proper. struct CollectItemTypesVisitor<'a, 'tcx: 'a> { - ccx: &'a CollectCtxt<'a, 'tcx> + ccx: &'a CrateCtxt<'a, 'tcx> } impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> { @@ -199,42 +187,223 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // Utility types and common code for the above passes. -pub trait ToTy<'tcx> { - fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>; -} +impl<'a,'tcx> CrateCtxt<'a,'tcx> { + fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> { + ItemCtxt { ccx: self, param_bounds: param_bounds } + } -impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> { - fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> { - ast_ty_to_ty(self, rs, ast_ty) + fn method_ty(&self, method_id: ast::NodeId) -> Rc> { + let def_id = local_def(method_id); + match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() { + ty::MethodTraitItem(ref mty) => mty.clone(), + ty::TypeTraitItem(..) => { + self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id)); + } + } } -} -impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> { - fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx } + fn cycle_check(&self, + span: Span, + request: AstConvRequest, + code: F) + -> Result + where F: FnOnce() -> Result + { + { + let mut stack = self.stack.borrow_mut(); + match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) { + None => { } + Some((i, _)) => { + let cycle = &stack[i..]; + self.report_cycle(span, cycle); + return Err(ErrorReported); + } + } + stack.push(request); + } - fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> { - if id.krate != ast::LOCAL_CRATE { - return ty::lookup_item_type(self.tcx, id); + let result = code(); + + self.stack.borrow_mut().pop(); + result + } + + fn report_cycle(&self, + span: Span, + cycle: &[AstConvRequest]) + { + assert!(!cycle.is_empty()); + let tcx = self.tcx; + + tcx.sess.span_err( + span, + &format!("unsupported cyclic reference between types/traits detected")); + + match cycle[0] { + AstConvRequest::GetItemTypeScheme(def_id) | + AstConvRequest::GetTraitDef(def_id) => { + tcx.sess.note( + &format!("the cycle begins when processing `{}`...", + ty::item_path_str(tcx, def_id))); + } + AstConvRequest::EnsureSuperPredicates(def_id) => { + tcx.sess.note( + &format!("the cycle begins when computing the supertraits of `{}`...", + ty::item_path_str(tcx, def_id))); + } + AstConvRequest::GetTypeParameterBounds(id) => { + let def = tcx.type_parameter_def(id); + tcx.sess.note( + &format!("the cycle begins when computing the bounds \ + for type parameter `{}`...", + def.name.user_string(tcx))); + } + } + + for request in cycle[1..].iter() { + match *request { + AstConvRequest::GetItemTypeScheme(def_id) | + AstConvRequest::GetTraitDef(def_id) => { + tcx.sess.note( + &format!("...which then requires processing `{}`...", + ty::item_path_str(tcx, def_id))); + } + AstConvRequest::EnsureSuperPredicates(def_id) => { + tcx.sess.note( + &format!("...which then requires computing the supertraits of `{}`...", + ty::item_path_str(tcx, def_id))); + } + AstConvRequest::GetTypeParameterBounds(id) => { + let def = tcx.type_parameter_def(id); + tcx.sess.note( + &format!("...which then requires computing the bounds \ + for type parameter `{}`...", + def.name.user_string(tcx))); + } + } } - match self.tcx.map.find(id.node) { - Some(ast_map::NodeItem(item)) => { - type_scheme_of_item(self, &*item) + match cycle[0] { + AstConvRequest::GetItemTypeScheme(def_id) | + AstConvRequest::GetTraitDef(def_id) => { + tcx.sess.note( + &format!("...which then again requires processing `{}`, completing the cycle.", + ty::item_path_str(tcx, def_id))); } - Some(ast_map::NodeForeignItem(foreign_item)) => { - let abi = self.tcx.map.get_foreign_abi(id.node); - type_scheme_of_foreign_item(self, &*foreign_item, abi) + AstConvRequest::EnsureSuperPredicates(def_id) => { + tcx.sess.note( + &format!("...which then again requires computing the supertraits of `{}`, \ + completing the cycle.", + ty::item_path_str(tcx, def_id))); } - x => { - self.tcx.sess.bug(&format!("unexpected sort of node \ - in get_item_type_scheme(): {:?}", - x)); + AstConvRequest::GetTypeParameterBounds(id) => { + let def = tcx.type_parameter_def(id); + tcx.sess.note( + &format!("...which then again requires computing the bounds \ + for type parameter `{}`, completing the cycle.", + def.name.user_string(tcx))); } } } - fn get_trait_def(&self, id: ast::DefId) -> Rc> { - get_trait_def(self, id) + /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises. + fn get_trait_def(&self, trait_id: ast::DefId) + -> Rc> + { + let tcx = self.tcx; + + if trait_id.krate != ast::LOCAL_CRATE { + return ty::lookup_trait_def(tcx, trait_id) + } + + let item = match tcx.map.get(trait_id.node) { + ast_map::NodeItem(item) => item, + _ => tcx.sess.bug(&format!("get_trait_def({}): not an item", trait_id.repr(tcx))) + }; + + trait_def_of_item(self, &*item) + } + + /// Ensure that the (transitive) super predicates for + /// `trait_def_id` are available. This will report a cycle error + /// if a trait `X` (transitively) extends itself in some form. + fn ensure_super_predicates(&self, span: Span, trait_def_id: ast::DefId) + -> Result<(), ErrorReported> + { + self.cycle_check(span, AstConvRequest::EnsureSuperPredicates(trait_def_id), || { + let def_ids = ensure_super_predicates_step(self, trait_def_id); + + for def_id in def_ids { + try!(self.ensure_super_predicates(span, def_id)); + } + + Ok(()) + }) + } +} + +impl<'a,'tcx> ItemCtxt<'a,'tcx> { + fn to_ty(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> { + ast_ty_to_ty(self, rs, ast_ty) + } +} + +impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> { + fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } + + fn get_item_type_scheme(&self, span: Span, id: ast::DefId) + -> Result, ErrorReported> + { + self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || { + Ok(type_scheme_of_def_id(self.ccx, id)) + }) + } + + fn get_trait_def(&self, span: Span, id: ast::DefId) + -> Result>, ErrorReported> + { + self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || { + Ok(self.ccx.get_trait_def(id)) + }) + } + + fn ensure_super_predicates(&self, + span: Span, + trait_def_id: ast::DefId) + -> Result<(), ErrorReported> + { + debug!("ensure_super_predicates(trait_def_id={})", + trait_def_id.repr(self.tcx())); + + self.ccx.ensure_super_predicates(span, trait_def_id) + } + + + fn get_type_parameter_bounds(&self, + span: Span, + node_id: ast::NodeId) + -> Result>, ErrorReported> + { + self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || { + let v = self.param_bounds.get_type_parameter_bounds(self, span, node_id) + .into_iter() + .filter_map(|p| p.to_opt_poly_trait_ref()) + .collect(); + Ok(v) + }) + } + + fn trait_defines_associated_type_named(&self, + trait_def_id: ast::DefId, + assoc_name: ast::Name) + -> bool + { + if trait_def_id.krate == ast::LOCAL_CRATE { + trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name) + } else { + let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id); + trait_def.associated_type_names.contains(&assoc_name) + } } fn ty_infer(&self, span: Span) -> Ty<'tcx> { @@ -253,11 +422,151 @@ impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> { } } -fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +/// Interface used to find the bounds on a type parameter from within +/// an `ItemCtxt`. This allows us to use multiple kinds of sources. +trait GetTypeParameterBounds<'tcx> { + fn get_type_parameter_bounds(&self, + astconv: &AstConv<'tcx>, + span: Span, + node_id: ast::NodeId) + -> Vec>; +} + +/// Find bounds from both elements of the tuple. +impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B) + where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx> +{ + fn get_type_parameter_bounds(&self, + astconv: &AstConv<'tcx>, + span: Span, + node_id: ast::NodeId) + -> Vec> + { + let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id); + v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id).into_iter()); + v + } +} + +/// Empty set of bounds. +impl<'tcx> GetTypeParameterBounds<'tcx> for () { + fn get_type_parameter_bounds(&self, + _astconv: &AstConv<'tcx>, + _span: Span, + _node_id: ast::NodeId) + -> Vec> + { + Vec::new() + } +} + +/// Find bounds from the parsed and converted predicates. This is +/// used when converting methods, because by that time the predicates +/// from the trait/impl have been fully converted. +impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, + astconv: &AstConv<'tcx>, + _span: Span, + node_id: ast::NodeId) + -> Vec> + { + let def = astconv.tcx().type_parameter_def(node_id); + + self.predicates + .iter() + .filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref data) => { + data.skip_binder().self_ty().is_param(def.space, def.index) + } + ty::Predicate::TypeOutlives(ref data) => { + data.skip_binder().0.is_param(def.space, def.index) + } + ty::Predicate::Equate(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::Projection(..) => { + false + } + } + }) + .cloned() + .collect() + } +} + +/// Find bounds from ast::Generics. This requires scanning through the +/// AST. We do this to avoid having to convert *all* the bounds, which +/// would create artificial cycles. Instead we can only convert the +/// bounds for those a type parameter `X` if `X::Foo` is used. +impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics { + fn get_type_parameter_bounds(&self, + astconv: &AstConv<'tcx>, + _: Span, + node_id: ast::NodeId) + -> Vec> + { + // In the AST, bounds can derive from two places. Either + // written inline like `` or in a where clause like + // `where T:Foo`. + + let def = astconv.tcx().type_parameter_def(node_id); + let ty = ty::mk_param_from_def(astconv.tcx(), &def); + + let from_ty_params = + self.ty_params + .iter() + .filter(|p| p.id == node_id) + .flat_map(|p| p.bounds.iter()) + .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter()); + + let from_where_clauses = + self.where_clause + .predicates + .iter() + .filter_map(|wp| match *wp { + ast::WherePredicate::BoundPredicate(ref bp) => Some(bp), + _ => None + }) + .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id)) + .flat_map(|bp| bp.bounds.iter()) + .flat_map(|b| predicates_from_bound(astconv, ty, b).into_iter()); + + from_ty_params.chain(from_where_clauses).collect() + } +} + +/// Tests whether this is the AST for a reference to the type +/// parameter with id `param_id`. We use this so as to avoid running +/// `ast_ty_to_ty`, because we want to avoid triggering an all-out +/// conversion of the type to avoid inducing unnecessary cycles. +fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>, + ast_ty: &ast::Ty, + param_id: ast::NodeId) + -> bool +{ + if let ast::TyPath(None, _) = ast_ty.node { + let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap(); + match path_res.base_def { + def::DefSelfTy(node_id) => + path_res.depth == 0 && node_id == param_id, + + def::DefTyParam(_, _, def_id, _) => + path_res.depth == 0 && def_id == local_def(param_id), + + _ => + false, + } + } else { + false + } +} + +fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, enum_scheme: ty::TypeScheme<'tcx>, enum_predicates: ty::GenericPredicates<'tcx>, variants: &[P]) { let tcx = ccx.tcx; + let icx = ccx.icx(&enum_predicates); // Create a set of parameter types shared among all the variants. for variant in variants { @@ -268,8 +577,8 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, let result_ty = match variant.node.kind { ast::TupleVariantKind(ref args) if args.len() > 0 => { let rs = ExplicitRscope; - let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect(); - ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[..], enum_scheme.ty) + let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect(); + ty::mk_ctor_fn(tcx, variant_def_id, &input_tys, enum_scheme.ty) } ast::TupleVariantKind(_) => { @@ -294,172 +603,62 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, } } -fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, - trait_id: ast::NodeId, - trait_def: &ty::TraitDef<'tcx>, - trait_predicates: &ty::GenericPredicates<'tcx>) { - let tcx = ccx.tcx; - if let ast_map::NodeItem(item) = tcx.map.get(trait_id) { - if let ast::ItemTrait(_, _, _, ref trait_items) = item.node { - // For each method, construct a suitable ty::Method and - // store it into the `tcx.impl_or_trait_items` table: - for trait_item in trait_items { - match *trait_item { - ast::RequiredMethod(_) | - ast::ProvidedMethod(_) => { - let ty_method = Rc::new(match *trait_item { - ast::RequiredMethod(ref m) => { - ty_method_of_trait_method( - ccx, - trait_id, - &trait_def.generics, - &trait_predicates, - &trait_items[..], - &m.id, - &m.ident.name, - &m.explicit_self, - m.abi, - &m.generics, - &m.unsafety, - &*m.decl) - } - ast::ProvidedMethod(ref m) => { - ty_method_of_trait_method( - ccx, - trait_id, - &trait_def.generics, - &trait_predicates, - &trait_items[..], - &m.id, - &m.pe_ident().name, - m.pe_explicit_self(), - m.pe_abi(), - m.pe_generics(), - &m.pe_unsafety(), - &*m.pe_fn_decl()) - } - ast::TypeTraitItem(ref at) => { - tcx.sess.span_bug(at.ty_param.span, - "there shouldn't be a type trait item here") - } - }); - - debug!("ty_method_of_trait_method yielded {} for method {} of trait {}", - ty_method.repr(ccx.tcx), - trait_item.repr(ccx.tcx), - local_def(trait_id).repr(ccx.tcx)); - - make_method_ty(ccx, &*ty_method); - - tcx.impl_or_trait_items - .borrow_mut() - .insert(ty_method.def_id, ty::MethodTraitItem(ty_method)); - } - ast::TypeTraitItem(ref ast_associated_type) => { - let trait_did = local_def(trait_id); - let associated_type = ty::AssociatedType { - name: ast_associated_type.ty_param.ident.name, - vis: ast::Public, - def_id: local_def(ast_associated_type.ty_param.id), - container: TraitContainer(trait_did), - }; - - let trait_item = ty::TypeTraitItem(Rc::new(associated_type)); - tcx.impl_or_trait_items - .borrow_mut() - .insert(associated_type.def_id, trait_item); - } - } - } - - // Add an entry mapping - let trait_item_def_ids = - Rc::new(trait_items.iter().map(|ti| { - match *ti { - ast::RequiredMethod(ref ty_method) => { - ty::MethodTraitItemId(local_def(ty_method.id)) - } - ast::ProvidedMethod(ref method) => { - ty::MethodTraitItemId(local_def(method.id)) - } - ast::TypeTraitItem(ref typedef) => { - ty::TypeTraitItemId(local_def(typedef.ty_param.id)) - } - } - }).collect()); - - let trait_def_id = local_def(trait_id); - tcx.trait_item_def_ids.borrow_mut().insert(trait_def_id, trait_item_def_ids); - } - } +fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + container: ImplOrTraitItemContainer, + sig: &ast::MethodSig, + id: ast::NodeId, + ident: ast::Ident, + vis: ast::Visibility, + untransformed_rcvr_ty: Ty<'tcx>, + rcvr_ty_generics: &ty::Generics<'tcx>, + rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { + let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics); + + let ty_generic_predicates = + ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates); + + let (fty, explicit_self_category) = + astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), + sig, untransformed_rcvr_ty); + + let def_id = local_def(id); + let ty_method = ty::Method::new(ident.name, + ty_generics, + ty_generic_predicates, + fty, + explicit_self_category, + vis, + def_id, + container, + None); + + let fty = ty::mk_bare_fn(ccx.tcx, Some(def_id), + ccx.tcx.mk_bare_fn(ty_method.fty.clone())); + debug!("method {} (id {}) has type {}", + ident.repr(ccx.tcx), id, fty.repr(ccx.tcx)); + ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme { + generics: ty_method.generics.clone(), + ty: fty + }); + ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone()); - fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) { - ccx.tcx.tcache.borrow_mut().insert( - m.def_id, - TypeScheme { - generics: m.generics.clone(), - ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) - }); - ccx.tcx.predicates.borrow_mut().insert( - m.def_id, - m.predicates.clone()); - } + write_ty_to_tcx(ccx.tcx, id, fty); - fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, - trait_id: ast::NodeId, - trait_generics: &ty::Generics<'tcx>, - trait_bounds: &ty::GenericPredicates<'tcx>, - _trait_items: &[ast::TraitItem], - m_id: &ast::NodeId, - m_name: &ast::Name, - m_explicit_self: &ast::ExplicitSelf, - m_abi: abi::Abi, - m_generics: &ast::Generics, - m_unsafety: &ast::Unsafety, - m_decl: &ast::FnDecl) - -> ty::Method<'tcx> { - let ty_generics = - ty_generics_for_fn_or_method(ccx, - m_generics, - trait_generics.clone()); - - let ty_bounds = - ty_generic_bounds_for_fn_or_method(ccx, - m_generics, - &ty_generics, - trait_bounds.clone()); - - let (fty, explicit_self_category) = { - let trait_self_ty = ty::mk_self_type(ccx.tcx); - astconv::ty_of_method(ccx, - *m_unsafety, - trait_self_ty, - m_explicit_self, - m_decl, - m_abi) - }; + debug!("writing method type: def_id={:?} mty={}", + def_id, ty_method.repr(ccx.tcx)); - ty::Method::new( - *m_name, - ty_generics, - ty_bounds, - fty, - explicit_self_category, - // assume public, because this is only invoked on trait methods - ast::Public, - local_def(*m_id), - TraitContainer(local_def(trait_id)), - None - ) - } + ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id, + ty::MethodTraitItem(Rc::new(ty_method))); } -fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, - struct_generics: &ty::Generics<'tcx>, - struct_predicates: &ty::GenericPredicates<'tcx>, - v: &ast::StructField, - origin: ast::DefId) -> ty::field_ty { - let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty); +fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + struct_generics: &ty::Generics<'tcx>, + struct_predicates: &ty::GenericPredicates<'tcx>, + v: &ast::StructField, + origin: ast::DefId) + -> ty::field_ty +{ + let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty); write_ty_to_tcx(ccx.tcx, v.node.id, tt); /* add the field to the tcache */ @@ -491,119 +690,55 @@ fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, } } -fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, - trait_def: &ty::TraitDef<'tcx>, - associated_type: &ast::AssociatedType) +fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + container: ImplOrTraitItemContainer, + ident: ast::Ident, + id: ast::NodeId, + vis: ast::Visibility) { let associated_type = Rc::new(ty::AssociatedType { - name: associated_type.ty_param.ident.name, - vis: ast::Public, - def_id: local_def(associated_type.ty_param.id), - container: TraitContainer(trait_def.trait_ref.def_id), + name: ident.name, + vis: vis, + def_id: local_def(id), + container: container }); - ccx.tcx - .impl_or_trait_items - .borrow_mut() - .insert(associated_type.def_id, - ty::TypeTraitItem(associated_type)); + ccx.tcx.impl_or_trait_items.borrow_mut() + .insert(local_def(id), ty::TypeTraitItem(associated_type)); } -fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>, +fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, - ms: I, + methods: I, untransformed_rcvr_ty: Ty<'tcx>, rcvr_ty_generics: &ty::Generics<'tcx>, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>, - rcvr_visibility: ast::Visibility) - where I: Iterator { - debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})", + rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) + where I: Iterator +{ + debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={}, rcvr_ty_predicates={})", untransformed_rcvr_ty.repr(ccx.tcx), - rcvr_ty_generics.repr(ccx.tcx)); + rcvr_ty_generics.repr(ccx.tcx), + rcvr_ty_predicates.repr(ccx.tcx)); let tcx = ccx.tcx; let mut seen_methods = FnvHashSet(); - for m in ms { - if !seen_methods.insert(m.pe_ident().repr(tcx)) { - span_err!(tcx.sess, m.span, E0201, "duplicate method in trait impl"); + for (sig, id, ident, vis, span) in methods { + if !seen_methods.insert(ident.name) { + span_err!(tcx.sess, span, E0201, "duplicate method"); } - let m_def_id = local_def(m.id); - - let mty = Rc::new(ty_of_method(ccx, - container, - m, - untransformed_rcvr_ty, - rcvr_ty_generics, - rcvr_ty_predicates, - rcvr_visibility)); - let fty = ty::mk_bare_fn(tcx, Some(m_def_id), tcx.mk_bare_fn(mty.fty.clone())); - debug!("method {} (id {}) has type {}", - m.pe_ident().repr(tcx), - m.id, - fty.repr(tcx)); - tcx.tcache.borrow_mut().insert( - m_def_id, - TypeScheme { - generics: mty.generics.clone(), - ty: fty - }); - tcx.predicates.borrow_mut().insert(m_def_id, mty.predicates.clone()); - - write_ty_to_tcx(tcx, m.id, fty); - - debug!("writing method type: def_id={:?} mty={}", - mty.def_id, mty.repr(ccx.tcx)); - - tcx.impl_or_trait_items - .borrow_mut() - .insert(mty.def_id, ty::MethodTraitItem(mty)); - } - - fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, - container: ImplOrTraitItemContainer, - m: &ast::Method, - untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_generics: &ty::Generics<'tcx>, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>, - rcvr_visibility: ast::Visibility) - -> ty::Method<'tcx> { - let m_ty_generics = - ty_generics_for_fn_or_method(ccx, - m.pe_generics(), - rcvr_ty_generics.clone()); - - let m_ty_bounds = - ty_generic_bounds_for_fn_or_method(ccx, - m.pe_generics(), - &m_ty_generics, - rcvr_ty_predicates.clone()); - - let (fty, explicit_self_category) = astconv::ty_of_method(ccx, - m.pe_unsafety(), - untransformed_rcvr_ty, - m.pe_explicit_self(), - &*m.pe_fn_decl(), - m.pe_abi()); - - // if the method specifies a visibility, use that, otherwise - // inherit the visibility from the impl (so `foo` in `pub impl - // { fn foo(); }` is public, but private in `priv impl { fn - // foo(); }`). - let method_vis = m.pe_vis().inherit_from(rcvr_visibility); - - ty::Method::new(m.pe_ident().name, - m_ty_generics, - m_ty_bounds, - fty, - explicit_self_category, - method_vis, - local_def(m.id), - container, - None) + convert_method(ccx, + container, + sig, + id, + ident, + vis, + untransformed_rcvr_ty, + rcvr_ty_generics, + rcvr_ty_predicates); } } -fn ensure_no_ty_param_bounds(ccx: &CollectCtxt, +fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, span: Span, generics: &ast::Generics, thing: &'static str) { @@ -632,7 +767,7 @@ fn ensure_no_ty_param_bounds(ccx: &CollectCtxt, } } -fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { +fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { let tcx = ccx.tcx; debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id); match it.node { @@ -648,6 +783,17 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { predicates, &enum_definition.variants); }, + ast::ItemDefaultImpl(_, ref ast_trait_ref) => { + let trait_ref = + astconv::instantiate_mono_trait_ref(&ccx.icx(&()), + &ExplicitRscope, + ast_trait_ref, + None); + + ty::record_trait_has_default_impl(tcx, trait_ref.def_id); + + tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref); + } ast::ItemImpl(_, _, ref generics, ref opt_trait_ref, @@ -657,11 +803,11 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { debug!("convert: ast_generics={:?}", generics); let ty_generics = ty_generics_for_type_or_impl(ccx, generics); - let ty_predicates = ty_generic_bounds_for_type_or_impl(ccx, &ty_generics, generics); + let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); debug!("convert: impl_bounds={:?}", ty_predicates); - let selfty = ccx.to_ty(&ExplicitRscope, &**selfty); + let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty); write_ty_to_tcx(tcx, it.id, selfty); tcx.tcache.borrow_mut().insert(local_def(it.id), @@ -681,119 +827,148 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { it.vis }; - let mut methods = Vec::new(); + // Convert all the associated types. for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref method) => { - let body_id = method.pe_body().id; - check_method_self_type(ccx, - &BindingRscope::new(), - selfty, - method.pe_explicit_self(), - body_id); - methods.push(&**method); - } - ast::TypeImplItem(ref typedef) => { + match impl_item.node { + ast::TypeImplItem(ref ty) => { if opt_trait_ref.is_none() { - span_err!(tcx.sess, typedef.span, E0202, + span_err!(tcx.sess, impl_item.span, E0202, "associated items are not allowed in inherent impls"); } - let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ); - tcx.tcache.borrow_mut().insert(local_def(typedef.id), + as_refsociated_type(ccx, ImplContainer(local_def(it.id)), + impl_item.ident, impl_item.id, impl_item.vis); + + let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty); + tcx.tcache.borrow_mut().insert(local_def(impl_item.id), TypeScheme { generics: ty::Generics::empty(), ty: typ, }); - tcx.predicates.borrow_mut().insert(local_def(typedef.id), + tcx.predicates.borrow_mut().insert(local_def(impl_item.id), ty::GenericPredicates::empty()); - write_ty_to_tcx(tcx, typedef.id, typ); - - let associated_type = Rc::new(ty::AssociatedType { - name: typedef.ident.name, - vis: typedef.vis, - def_id: local_def(typedef.id), - container: ty::ImplContainer(local_def(it.id)), - }); - tcx.impl_or_trait_items - .borrow_mut() - .insert(local_def(typedef.id), - ty::TypeTraitItem(associated_type)); + write_ty_to_tcx(tcx, impl_item.id, typ); } + ast::MethodImplItem(..) | + ast::MacImplItem(_) => {} } } + let methods = impl_items.iter().filter_map(|ii| { + match ii.node { + ast::MethodImplItem(ref sig, _) => { + // if the method specifies a visibility, use that, otherwise + // inherit the visibility from the impl (so `foo` in `pub impl + // { fn foo(); }` is public, but private in `priv impl { fn + // foo(); }`). + let method_vis = ii.vis.inherit_from(parent_visibility); + Some((sig, ii.id, ii.ident, method_vis, ii.span)) + } + ast::TypeImplItem(_) | + ast::MacImplItem(_) => None + } + }); convert_methods(ccx, ImplContainer(local_def(it.id)), - methods.into_iter(), + methods, selfty, &ty_generics, - &ty_predicates, - parent_visibility); - - if let Some(ref trait_ref) = *opt_trait_ref { - astconv::instantiate_trait_ref(ccx, - &ExplicitRscope, - trait_ref, - Some(selfty), - None); + &ty_predicates); + + for impl_item in impl_items { + match impl_item.node { + ast::MethodImplItem(ref sig, ref body) => { + let body_id = body.id; + check_method_self_type(ccx, + &BindingRscope::new(), + ccx.method_ty(impl_item.id), + selfty, + &sig.explicit_self, + body_id); + } + ast::TypeImplItem(_) | + ast::MacImplItem(_) => {} + } + } + + if let Some(ref ast_trait_ref) = *opt_trait_ref { + let trait_ref = + astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), + &ExplicitRscope, + ast_trait_ref, + Some(selfty)); + + tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref); } enforce_impl_ty_params_are_constrained(tcx, generics, local_def(it.id)); }, - ast::ItemTrait(_, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, ref trait_items) => { let trait_def = trait_def_of_item(ccx, it); + let _: Result<(), ErrorReported> = // any error is already reported, can ignore + ccx.ensure_super_predicates(it.span, local_def(it.id)); convert_trait_predicates(ccx, it); - let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(it.id)); + let trait_predicates = ty::lookup_predicates(tcx, local_def(it.id)); debug!("convert: trait_bounds={:?}", trait_predicates); - for trait_method in trait_methods { - let self_type = ty::mk_self_type(tcx); - match *trait_method { - ast::RequiredMethod(ref type_method) => { - let rscope = BindingRscope::new(); - check_method_self_type(ccx, - &rscope, - self_type, - &type_method.explicit_self, - it.id) - } - ast::ProvidedMethod(ref method) => { - check_method_self_type(ccx, - &BindingRscope::new(), - self_type, - method.pe_explicit_self(), - it.id) - } - ast::TypeTraitItem(ref associated_type) => { - convert_associated_type(ccx, - &*trait_def, - &**associated_type); + // Convert all the associated types. + for trait_item in trait_items { + match trait_item.node { + ast::MethodTraitItem(..) => {} + ast::TypeTraitItem(..) => { + as_refsociated_type(ccx, TraitContainer(local_def(it.id)), + trait_item.ident, trait_item.id, ast::Public); } } - } + }; + + let methods = trait_items.iter().filter_map(|ti| { + let sig = match ti.node { + ast::MethodTraitItem(ref sig, _) => sig, + ast::TypeTraitItem(..) => return None, + }; + Some((sig, ti.id, ti.ident, ast::Inherited, ti.span)) + }); - // Run convert_methods on the provided methods. - let untransformed_rcvr_ty = ty::mk_self_type(tcx); + // Run convert_methods on the trait methods. convert_methods(ccx, TraitContainer(local_def(it.id)), - trait_methods.iter().filter_map(|m| match *m { - ast::RequiredMethod(_) => None, - ast::ProvidedMethod(ref m) => Some(&**m), - ast::TypeTraitItem(_) => None, - }), - untransformed_rcvr_ty, + methods, + ty::mk_self_type(tcx), &trait_def.generics, - &trait_predicates, - it.vis); + &trait_predicates); - // We need to do this *after* converting methods, since - // convert_methods produces a tcache entry that is wrong for - // static trait methods. This is somewhat unfortunate. - collect_trait_methods(ccx, it.id, &*trait_def, &trait_predicates); + // Add an entry mapping + let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| { + let def_id = local_def(trait_item.id); + match trait_item.node { + ast::MethodTraitItem(..) => { + ty::MethodTraitItemId(def_id) + } + ast::TypeTraitItem(..) => { + ty::TypeTraitItemId(def_id) + } + } + }).collect()); + tcx.trait_item_def_ids.borrow_mut().insert(local_def(it.id), trait_item_def_ids); + + // This must be done after `collect_trait_methods` so that + // we have a method type stored for every method. + for trait_item in trait_items { + let sig = match trait_item.node { + ast::MethodTraitItem(ref sig, _) => sig, + ast::TypeTraitItem(..) => continue + }; + check_method_self_type(ccx, + &BindingRscope::new(), + ccx.method_ty(trait_item.id), + ty::mk_self_type(tcx), + &sig.explicit_self, + it.id) + } }, ast::ItemStruct(ref struct_def, _) => { // Write the class type. @@ -816,7 +991,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { } } -fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, struct_def: &ast::StructDef, scheme: ty::TypeScheme<'tcx>, predicates: ty::GenericPredicates<'tcx>, @@ -867,9 +1042,13 @@ fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates); } else if struct_def.fields[0].node.kind.is_unnamed() { // Tuple-like. - let inputs: Vec<_> = struct_def.fields.iter().map( - |field| (*tcx.tcache.borrow())[ - local_def(field.node.id)].ty).collect(); + let inputs: Vec<_> = + struct_def.fields + .iter() + .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id)) + .unwrap() + .ty) + .collect(); let ctor_fn_ty = ty::mk_ctor_fn(tcx, local_def(ctor_id), &inputs[..], @@ -886,25 +1065,92 @@ fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, } } -fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, - trait_id: ast::DefId) - -> Rc> { +/// Ensures that the super-predicates of the trait with def-id +/// trait_def_id are converted and stored. This does NOT ensure that +/// the transitive super-predicates are converted; that is the job of +/// the `ensure_super_predicates()` method in the `AstConv` impl +/// above. Returns a list of trait def-ids that must be ensured as +/// well to guarantee that the transitive superpredicates are +/// converted. +fn ensure_super_predicates_step(ccx: &CrateCtxt, + trait_def_id: ast::DefId) + -> Vec +{ let tcx = ccx.tcx; - if trait_id.krate != ast::LOCAL_CRATE { - return ty::lookup_trait_def(tcx, trait_id) - } + debug!("ensure_super_predicates_step(trait_def_id={})", trait_def_id.repr(tcx)); - match tcx.map.get(trait_id.node) { - ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item), - _ => { - tcx.sess.bug(&format!("get_trait_def({}): not an item", - trait_id.node)[]) - } + if trait_def_id.krate != ast::LOCAL_CRATE { + // If this trait comes from an external crate, then all of the + // supertraits it may depend on also must come from external + // crates, and hence all of them already have their + // super-predicates "converted" (and available from crate + // meta-data), so there is no need to transitively test them. + return Vec::new(); } + + let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned(); + let superpredicates = superpredicates.unwrap_or_else(|| { + let trait_node_id = trait_def_id.node; + + let item = match ccx.tcx.map.get(trait_node_id) { + ast_map::NodeItem(item) => item, + _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id)) + }; + + let (generics, bounds) = match item.node { + ast::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits), + _ => tcx.sess.span_bug(item.span, + "ensure_super_predicates_step invoked on non-trait"), + }; + + // In-scope when converting the superbounds for `Trait` are + // that `Self:Trait` as well as any bounds that appear on the + // generic types: + let trait_def = trait_def_of_item(ccx, item); + let self_predicate = ty::GenericPredicates { + predicates: VecPerParamSpace::new(vec![], + vec![trait_def.trait_ref.as_predicate()], + vec![]) + }; + let scope = &(generics, &self_predicate); + + // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`. + let self_param_ty = ty::mk_self_type(tcx); + let superbounds1 = compute_bounds(&ccx.icx(scope), self_param_ty, bounds, + SizedByDefault::No, item.span); + let superbounds1 = ty::predicates(tcx, self_param_ty, &superbounds1); + + // Convert any explicit superbounds in the where clause, + // e.g. `trait Foo where Self : Bar`: + let superbounds2 = generics.get_type_parameter_bounds(&ccx.icx(scope), item.span, item.id); + + // Combine the two lists to form the complete set of superbounds: + let superbounds = superbounds1.into_iter().chain(superbounds2.into_iter()).collect(); + let superpredicates = ty::GenericPredicates { + predicates: VecPerParamSpace::new(superbounds, vec![], vec![]) + }; + debug!("superpredicates for trait {} = {}", + local_def(item.id).repr(ccx.tcx), + superpredicates.repr(ccx.tcx)); + + tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone()); + + superpredicates + }); + + let def_ids: Vec<_> = superpredicates.predicates + .iter() + .filter_map(|p| p.to_opt_poly_trait_ref()) + .map(|tr| tr.def_id()) + .collect(); + + debug!("ensure_super_predicates_step: def_ids={}", def_ids.repr(tcx)); + + def_ids } -fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) -> Rc> { @@ -915,18 +1161,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, return def.clone(); } - let (unsafety, generics, bounds, items) = match it.node { - ast::ItemTrait(unsafety, - ref generics, - ref supertraits, - ref items) => { - (unsafety, generics, supertraits, items) - } - ref s => { - tcx.sess.span_bug( - it.span, - &format!("trait_def_of_item invoked on {:?}", s)[]); - } + let (unsafety, generics, items) = match it.node { + ast::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items), + _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"), }; let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar"); @@ -935,7 +1172,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ which traits can use parenthetical notation"); - span_help!(ccx.tcx.sess, it.span, + fileline_help!(ccx.tcx.sess, it.span, "add `#![feature(unboxed_closures)]` to \ the crate attributes to use it"); } @@ -944,24 +1181,12 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics); - let self_param_ty = ty::ParamTy::for_self().to_ty(ccx.tcx); - - // supertraits: - let bounds = compute_bounds(ccx, - self_param_ty, - bounds, - SizedByDefault::No, - it.span); - - let associated_type_names: Vec<_> = - items.iter() - .filter_map(|item| { - match *item { - ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None, - ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name), - } - }) - .collect(); + let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| { + match trait_item.node { + ast::MethodTraitItem(..) => None, + ast::TypeTraitItem(..) => Some(trait_item.ident.name), + } + }).collect(); let trait_ref = Rc::new(ty::TraitRef { def_id: def_id, @@ -972,7 +1197,6 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, paren_sugar: paren_sugar, unsafety: unsafety, generics: ty_generics, - bounds: bounds, trait_ref: trait_ref, associated_type_names: associated_type_names, }); @@ -981,9 +1205,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, return trait_def; - fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, + fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &ast::Generics) - -> subst::Substs<'tcx> + -> Substs<'tcx> { let tcx = ccx.tcx; @@ -993,7 +1217,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, .iter() .enumerate() .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id, - subst::TypeSpace, + TypeSpace, i as u32, def.lifetime.name)) .collect(); @@ -1003,18 +1227,41 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, generics.ty_params .iter() .enumerate() - .map(|(i, def)| ty::mk_param(tcx, subst::TypeSpace, + .map(|(i, def)| ty::mk_param(tcx, TypeSpace, i as u32, def.ident.name)) .collect(); // ...and also create the `Self` parameter. let self_ty = ty::mk_self_type(tcx); - subst::Substs::new_trait(types, regions, self_ty) + Substs::new_trait(types, regions, self_ty) } } -fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item) { +fn trait_defines_associated_type_named(ccx: &CrateCtxt, + trait_node_id: ast::NodeId, + assoc_name: ast::Name) + -> bool +{ + let item = match ccx.tcx.map.get(trait_node_id) { + ast_map::NodeItem(item) => item, + _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id)) + }; + + let trait_items = match item.node { + ast::ItemTrait(_, _, _, ref trait_items) => trait_items, + _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id)) + }; + + trait_items.iter().any(|trait_item| { + match trait_item.node { + ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name, + ast::MethodTraitItem(..) => false, + } + }) +} + +fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) { let tcx = ccx.tcx; let trait_def = trait_def_of_item(ccx, it); @@ -1025,77 +1272,95 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Ite ref s => { tcx.sess.span_bug( it.span, - &format!("trait_def_of_item invoked on {:?}", s)[]); + &format!("trait_def_of_item invoked on {:?}", s)); } }; - let self_param_ty = ty::ParamTy::for_self().to_ty(ccx.tcx); + let super_predicates = ty::lookup_super_predicates(ccx.tcx, def_id); - let super_predicates = ty::predicates(ccx.tcx, self_param_ty, &trait_def.bounds); - - let assoc_predicates = predicates_for_associated_types(ccx, &trait_def.trait_ref, items); - - // `ty_generic_bounds` below will consider the bounds on the type + // `ty_generic_predicates` below will consider the bounds on the type // parameters (including `Self`) and the explicit where-clauses, // but to get the full set of predicates on a trait we need to add // in the supertrait bounds and anything declared on the // associated types. - let mut base_predicates = - ty::GenericPredicates { - predicates: VecPerParamSpace::new(super_predicates, vec![], vec![]) - }; - base_predicates.predicates.extend(subst::TypeSpace, assoc_predicates.into_iter()); + let mut base_predicates = super_predicates; - let self_bounds = &trait_def.generics.types.get_self().unwrap().bounds; - base_predicates.predicates.extend( - subst::SelfSpace, - ty::predicates(ccx.tcx, self_param_ty, self_bounds).into_iter()); + // Add in a predicate that `Self:Trait` (where `Trait` is the + // current trait). This is needed for builtin bounds. + let self_predicate = trait_def.trait_ref.to_poly_trait_ref().as_predicate(); + base_predicates.predicates.push(SelfSpace, self_predicate); // add in the explicit where-clauses - let trait_predicates = - ty_generic_bounds(ccx, - subst::TypeSpace, - &trait_def.generics, - base_predicates, - &generics.where_clause); + let mut trait_predicates = + ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates); + + let assoc_predicates = predicates_for_associated_types(ccx, + generics, + &trait_predicates, + &trait_def.trait_ref, + items); + trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter()); let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates); assert!(prev_predicates.is_none()); return; - fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, + fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + ast_generics: &ast::Generics, + trait_predicates: &ty::GenericPredicates<'tcx>, self_trait_ref: &Rc>, - trait_items: &[ast::TraitItem]) + trait_items: &[P]) -> Vec> { - trait_items - .iter() - .flat_map(|trait_item| { - let assoc_type_def = match *trait_item { - ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param, - ast::RequiredMethod(..) | ast::ProvidedMethod(..) => { - return vec!().into_iter(); - } - }; + trait_items.iter().flat_map(|trait_item| { + let bounds = match trait_item.node { + ast::TypeTraitItem(ref bounds, _) => bounds, + ast::MethodTraitItem(..) => { + return vec!().into_iter(); + } + }; - let assoc_ty = ty::mk_projection(ccx.tcx, - self_trait_ref.clone(), - assoc_type_def.ident.name); + let assoc_ty = ty::mk_projection(ccx.tcx, + self_trait_ref.clone(), + trait_item.ident.name); - let bounds = compute_bounds(ccx, - assoc_ty, - &*assoc_type_def.bounds, - SizedByDefault::Yes, - assoc_type_def.span); + let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)), + assoc_ty, + bounds, + SizedByDefault::Yes, + trait_item.span); - ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter() - }) - .collect() + ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter() + }).collect() } } -fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, +fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + def_id: ast::DefId) + -> ty::TypeScheme<'tcx> +{ + if def_id.krate != ast::LOCAL_CRATE { + return ty::lookup_item_type(ccx.tcx, def_id); + } + + match ccx.tcx.map.find(def_id.node) { + Some(ast_map::NodeItem(item)) => { + type_scheme_of_item(ccx, &*item) + } + Some(ast_map::NodeForeignItem(foreign_item)) => { + let abi = ccx.tcx.map.get_foreign_abi(def_id.node); + type_scheme_of_foreign_item(ccx, &*foreign_item, abi) + } + x => { + ccx.tcx.sess.bug(&format!("unexpected sort of node \ + in get_item_type_scheme(): {:?}", + x)); + } + } +} + +fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &ast::Item) -> ty::TypeScheme<'tcx> { @@ -1104,28 +1369,25 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, |_| compute_type_scheme_of_item(ccx, it)) } - -fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - it: &ast::Item) - -> ty::TypeScheme<'tcx> +fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + it: &ast::Item) + -> ty::TypeScheme<'tcx> { let tcx = ccx.tcx; match it.node { ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => { - let ty = ccx.to_ty(&ExplicitRscope, &**t); + let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t); ty::TypeScheme { ty: ty, generics: ty::Generics::empty() } } ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { - let ty_generics = ty_generics_for_fn_or_method(ccx, - generics, - ty::Generics::empty()); - let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl); + let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty()); + let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl); let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd)); ty::TypeScheme { ty: ty, generics: ty_generics } } ast::ItemTy(ref t, ref generics) => { - let ty = ccx.to_ty(&ExplicitRscope, &**t); let ty_generics = ty_generics_for_type_or_impl(ccx, generics); + let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t); ty::TypeScheme { ty: ty, generics: ty_generics } } ast::ItemEnum(_, ref generics) => { @@ -1141,6 +1403,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs)); ty::TypeScheme { ty: t, generics: ty_generics } } + ast::ItemDefaultImpl(..) | ast::ItemTrait(..) | ast::ItemImpl(..) | ast::ItemMod(..) | @@ -1150,13 +1413,13 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, ast::ItemMac(..) => { tcx.sess.span_bug( it.span, - format!("compute_type_scheme_of_item: unexpected item type: {:?}", - it.node).as_slice()); + &format!("compute_type_scheme_of_item: unexpected item type: {:?}", + it.node)); } } } -fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>) { @@ -1169,20 +1432,18 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, ty::GenericPredicates::empty() } ast::ItemFn(_, _, _, ref ast_generics, _) => { - ty_generic_bounds_for_fn_or_method(ccx, - ast_generics, - &scheme.generics, - ty::GenericPredicates::empty()) + ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty()) } ast::ItemTy(_, ref generics) => { - ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics) + ty_generic_predicates_for_type_or_impl(ccx, generics) } ast::ItemEnum(_, ref generics) => { - ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics) + ty_generic_predicates_for_type_or_impl(ccx, generics) } ast::ItemStruct(_, ref generics) => { - ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics) + ty_generic_predicates_for_type_or_impl(ccx, generics) } + ast::ItemDefaultImpl(..) | ast::ItemTrait(..) | ast::ItemExternCrate(..) | ast::ItemUse(..) | @@ -1192,8 +1453,8 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, ast::ItemMac(..) => { tcx.sess.span_bug( it.span, - format!("compute_type_scheme_of_item: unexpected item type: {:?}", - it.node).as_slice()); + &format!("compute_type_scheme_of_item: unexpected item type: {:?}", + it.node)); } }; @@ -1209,7 +1470,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, Some(ty::ObjectLifetimeDefault::Specific(r)) => r.user_string(tcx), d => - d.repr(ccx.tcx()), + d.repr(ccx.tcx), }) .collect::>() .connect(","); @@ -1221,18 +1482,18 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, } fn type_scheme_of_foreign_item<'a, 'tcx>( - ccx: &CollectCtxt<'a, 'tcx>, + ccx: &CrateCtxt<'a, 'tcx>, it: &ast::ForeignItem, abi: abi::Abi) -> ty::TypeScheme<'tcx> { - memoized(&ccx.tcx().tcache, + memoized(&ccx.tcx.tcache, local_def(it.id), |_| compute_type_scheme_of_foreign_item(ccx, it, abi)) } fn compute_type_scheme_of_foreign_item<'a, 'tcx>( - ccx: &CollectCtxt<'a, 'tcx>, + ccx: &CrateCtxt<'a, 'tcx>, it: &ast::ForeignItem, abi: abi::Abi) -> ty::TypeScheme<'tcx> @@ -1244,13 +1505,13 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>( ast::ForeignItemStatic(ref t, _) => { ty::TypeScheme { generics: ty::Generics::empty(), - ty: ast_ty_to_ty(ccx, &ExplicitRscope, t) + ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t) } } } } -fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::ForeignItem) { // For reasons I cannot fully articulate, I do so hate the AST @@ -1265,10 +1526,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, let predicates = match it.node { ast::ForeignItemFn(_, ref generics) => { - ty_generic_bounds_for_fn_or_method(ccx, - generics, - &scheme.generics, - ty::GenericPredicates::empty()) + ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty()) } ast::ForeignItemStatic(..) => { ty::GenericPredicates::empty() @@ -1279,45 +1537,29 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, assert!(prev_predicates.is_none()); } -fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &ast::Generics) -> ty::Generics<'tcx> { - ty_generics(ccx, - subst::TypeSpace, - &generics.lifetimes[], - &generics.ty_params[], - &generics.where_clause, - ty::Generics::empty()) + ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty()) } -fn ty_generic_bounds_for_type_or_impl<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - ty_generics: &ty::Generics<'tcx>, - generics: &ast::Generics) - -> ty::GenericPredicates<'tcx> +fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + generics: &ast::Generics) + -> ty::GenericPredicates<'tcx> { - ty_generic_bounds(ccx, - subst::TypeSpace, - ty_generics, - ty::GenericPredicates::empty(), - &generics.where_clause) + ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty()) } -fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_id: ast::NodeId, - substs: &'tcx subst::Substs<'tcx>, + substs: &'tcx Substs<'tcx>, ast_generics: &ast::Generics) -> ty::Generics<'tcx> { debug!("ty_generics_for_trait(trait_id={}, substs={})", local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx)); - let mut generics = - ty_generics(ccx, - subst::TypeSpace, - &ast_generics.lifetimes[], - &ast_generics.ty_params[], - &ast_generics.where_clause, - ty::Generics::empty()); + let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics); // Add in the self type parameter. // @@ -1325,65 +1567,46 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, // the node id for the Self type parameter. let param_id = trait_id; - let self_trait_ref = - Rc::new(ty::TraitRef { def_id: local_def(trait_id), - substs: substs }); - let def = ty::TypeParameterDef { - space: subst::SelfSpace, + space: SelfSpace, index: 0, name: special_idents::type_self.name, def_id: local_def(param_id), - bounds: ty::ParamBounds { - region_bounds: vec!(), - builtin_bounds: ty::empty_builtin_bounds(), - trait_bounds: vec!(ty::Binder(self_trait_ref.clone())), - projection_bounds: vec!(), - }, default: None, object_lifetime_default: None, }; ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); - generics.types.push(subst::SelfSpace, def); + generics.types.push(SelfSpace, def); return generics; } -fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - generics: &ast::Generics, - base_generics: ty::Generics<'tcx>) - -> ty::Generics<'tcx> +fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + generics: &ast::Generics, + base_generics: &ty::Generics<'tcx>) + -> ty::Generics<'tcx> { - let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics); - ty_generics(ccx, - subst::FnSpace, - &early_lifetimes[..], - &generics.ty_params[], - &generics.where_clause, - base_generics) + ty_generics(ccx, FnSpace, generics, base_generics) } -fn ty_generic_bounds_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - generics: &ast::Generics, - ty_generics: &ty::Generics<'tcx>, - base: ty::GenericPredicates<'tcx>) - -> ty::GenericPredicates<'tcx> +fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + generics: &ast::Generics, + base_predicates: &ty::GenericPredicates<'tcx>) + -> ty::GenericPredicates<'tcx> { - ty_generic_bounds(ccx, - subst::FnSpace, - ty_generics, - base, - &generics.where_clause) + ty_generic_predicates(ccx, FnSpace, generics, base_predicates) } // Add the Sized bound, unless the type parameter is marked as `?Sized`. -fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - bounds: &mut ty::BuiltinBounds, - ast_bounds: &[ast::TyParamBound], - span: Span) +fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>, + bounds: &mut ty::BuiltinBounds, + ast_bounds: &[ast::TyParamBound], + span: Span) { + let tcx = astconv.tcx(); + // Try to find an unbound in bounds. let mut unbound = None; for ab in ast_bounds { @@ -1392,80 +1615,108 @@ fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, assert!(ptr.bound_lifetimes.is_empty()); unbound = Some(ptr.trait_ref.clone()); } else { - span_err!(ccx.tcx.sess, span, E0203, + span_err!(tcx.sess, span, E0203, "type parameter has more than one relaxed default \ bound, only one is supported"); } } } - let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem); + let kind_id = 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(ccx.tcx, tpb); + let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb); match kind_id { Ok(kind_id) if trait_def_id != kind_id => { - 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(ccx.tcx, - kind_id, - bounds); + 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(tcx, kind_id, bounds); } _ => {} } } _ if kind_id.is_ok() => { - ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds); + ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds); } // No lang item for Sized, so we can't add it as a bound. None => {} } } -fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - space: subst::ParamSpace, - generics: &ty::Generics<'tcx>, - base: ty::GenericPredicates<'tcx>, - where_clause: &ast::WhereClause) - -> ty::GenericPredicates<'tcx> +/// Returns the early-bound lifetimes declared in this generics +/// listing. For anything other than fns/methods, this is just all +/// the lifetimes that are declared. For fns or methods, we have to +/// screen out those that do not appear in any where-clauses etc using +/// `resolve_lifetime::early_bound_lifetimes`. +fn early_bound_lifetimes_from_generics(space: ParamSpace, + ast_generics: &ast::Generics) + -> Vec +{ + match space { + SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(), + FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics), + } +} + +fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + space: ParamSpace, + ast_generics: &ast::Generics, + base_predicates: &ty::GenericPredicates<'tcx>) + -> ty::GenericPredicates<'tcx> { let tcx = ccx.tcx; - let mut result = base; - - // For now, scrape the bounds out of parameters from Generics. This is not great. - for def in generics.regions.get_slice(space) { - let r_a = def.to_early_bound_region(); - for &r_b in &def.bounds { - let outlives = ty::Binder(ty::OutlivesPredicate(r_a, r_b)); - result.predicates.push(def.space, ty::Predicate::RegionOutlives(outlives)); - } + let mut result = base_predicates.clone(); + + // Collect the predicates that were written inline by the user on each + // type parameter (e.g., ``). + for (index, param) in ast_generics.ty_params.iter().enumerate() { + let index = index as u32; + let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx); + let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), + param_ty, + ¶m.bounds, + SizedByDefault::Yes, + param.span); + let predicates = ty::predicates(ccx.tcx, param_ty, &bounds); + result.predicates.extend(space, predicates.into_iter()); } - for def in generics.types.get_slice(space) { - let t = ty::mk_param_from_def(ccx.tcx, def); - result.predicates.extend(def.space, ty::predicates(ccx.tcx, t, &def.bounds).into_iter()); + + // Collect the region predicates that were declared inline as + // well. In the case of parameters declared on a fn or method, we + // have to be careful to only iterate over early-bound regions. + let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics); + for (index, param) in early_lifetimes.iter().enumerate() { + let index = index as u32; + let region = ty::ReEarlyBound(param.lifetime.id, space, index, param.lifetime.name); + for bound in ¶m.bounds { + let bound_region = ast_region_to_region(ccx.tcx, bound); + let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); + result.predicates.push(space, outlives.as_predicate()); + } } - // Add the bounds not associated with a type parameter + // Add in the bounds that appear in the where-clause + let where_clause = &ast_generics.where_clause; for predicate in &where_clause.predicates { match predicate { &ast::WherePredicate::BoundPredicate(ref bound_pred) => { - let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty); + let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)), + &ExplicitRscope, + &*bound_pred.bounded_ty); for bound in &*bound_pred.bounds { match bound { &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => { let mut projections = Vec::new(); - let trait_ref = astconv::instantiate_poly_trait_ref( - ccx, - &ExplicitRscope, - poly_trait_ref, - Some(ty), - &mut projections, - ); + let trait_ref = + conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)), + ty, + poly_trait_ref, + &mut projections); result.predicates.push(space, trait_ref.as_predicate()); @@ -1504,18 +1755,17 @@ fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, return result; } -fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - space: subst::ParamSpace, - lifetime_defs: &[ast::LifetimeDef], - types: &[ast::TyParam], - where_clause: &ast::WhereClause, - base_generics: ty::Generics<'tcx>) +fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + space: ParamSpace, + ast_generics: &ast::Generics, + base_generics: &ty::Generics<'tcx>) -> ty::Generics<'tcx> { let tcx = ccx.tcx; - let mut result = base_generics; + let mut result = base_generics.clone(); - for (i, l) in lifetime_defs.iter().enumerate() { + let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics); + for (i, l) in early_lifetimes.iter().enumerate() { let bounds = l.bounds.iter() .map(|l| ast_region_to_region(tcx, l)) .collect(); @@ -1524,16 +1774,14 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, index: i as u32, def_id: local_def(l.lifetime.id), bounds: bounds }; - // debug!("ty_generics: def for region param: {:?}", - // def.repr(tcx)); result.regions.push(space, def); } assert!(result.types.is_empty_in(space)); // Now create the real type parameters. - for (i, param) in types.iter().enumerate() { - let def = get_or_create_type_parameter_def(ccx, space, param, i as u32, where_clause); + for i in 0..ast_generics.ty_params.len() { + let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32); debug!("ty_generics: def for type param: {:?}, {:?}", def, space); result.types.push(space, def); } @@ -1541,29 +1789,24 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, result } -fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - space: subst::ParamSpace, - param: &ast::TyParam, - index: u32, - where_clause: &ast::WhereClause) +fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + ast_generics: &ast::Generics, + space: ParamSpace, + index: u32) -> ty::TypeParameterDef<'tcx> { + let param = &ast_generics.ty_params[index as usize]; + let tcx = ccx.tcx; match tcx.ty_param_defs.borrow().get(¶m.id) { Some(d) => { return d.clone(); } None => { } } - let param_ty = ty::ParamTy::new(space, index, param.ident.name); - let bounds = compute_bounds(ccx, - param_ty.to_ty(ccx.tcx), - ¶m.bounds[], - SizedByDefault::Yes, - param.span); let default = match param.default { None => None, Some(ref path) => { - let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path); + let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path); let cur_idx = index; ty::walk_ty(ty, |t| { @@ -1582,14 +1825,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, }; let object_lifetime_default = - compute_object_lifetime_default(ccx, space, index, ¶m.bounds, where_clause); + compute_object_lifetime_default(ccx, param.id, + ¶m.bounds, &ast_generics.where_clause); let def = ty::TypeParameterDef { space: space, index: index, name: param.ident.name, def_id: local_def(param.id), - bounds: bounds, default: default, object_lifetime_default: object_lifetime_default, }; @@ -1605,15 +1848,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, /// intentionally avoid just asking astconv to convert all the where /// clauses into a `ty::Predicate`. This is because that could induce /// artificial cycles. -fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - space: subst::ParamSpace, - index: u32, +fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + param_id: ast::NodeId, param_bounds: &[ast::TyParamBound], where_clause: &ast::WhereClause) -> Option { let inline_bounds = from_bounds(ccx, param_bounds); - let where_bounds = from_predicates(ccx, space, index, &where_clause.predicates); + let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates); let all_bounds: HashSet<_> = inline_bounds.into_iter() .chain(where_bounds.into_iter()) .collect(); @@ -1625,7 +1867,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, .map(ty::ObjectLifetimeDefault::Specific) }; - fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, + fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, bounds: &[ast::TyParamBound]) -> Vec { @@ -1635,15 +1877,14 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, ast::TraitTyParamBound(..) => None, ast::RegionTyParamBound(ref lifetime) => - Some(astconv::ast_region_to_region(ccx.tcx(), lifetime)), + Some(astconv::ast_region_to_region(ccx.tcx, lifetime)), } }) .collect() } - fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - space: subst::ParamSpace, - index: u32, + fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, + param_id: ast::NodeId, predicates: &[ast::WherePredicate]) -> Vec { @@ -1652,7 +1893,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, match *predicate { ast::WherePredicate::BoundPredicate(ref data) => { if data.bound_lifetimes.len() == 0 && - is_param(ccx, &data.bounded_ty, space, index) + is_param(ccx.tcx, &data.bounded_ty, param_id) { from_bounds(ccx, &data.bounds).into_iter() } else { @@ -1667,58 +1908,30 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, }) .collect() } - - fn is_param(ccx: &CollectCtxt, - ast_ty: &ast::Ty, - space: subst::ParamSpace, - index: u32) - -> bool - { - match ast_ty.node { - ast::TyPath(_, id) => { - match ccx.tcx.def_map.borrow()[id] { - def::DefTyParam(s, i, _, _) => { - space == s && index == i - } - _ => { - false - } - } - } - _ => { - false - } - } - } } -enum SizedByDefault { Yes, No } +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<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - param_ty: ty::Ty<'tcx>, - ast_bounds: &[ast::TyParamBound], - sized_by_default: SizedByDefault, - span: Span) - -> ty::ParamBounds<'tcx> +fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>, + param_ty: ty::Ty<'tcx>, + ast_bounds: &[ast::TyParamBound], + sized_by_default: SizedByDefault, + span: Span) + -> ty::ParamBounds<'tcx> { - let mut param_bounds = conv_param_bounds(ccx, + let mut param_bounds = conv_param_bounds(astconv, span, param_ty, ast_bounds); if let SizedByDefault::Yes = sized_by_default { - add_unsized_bound(ccx, + add_unsized_bound(astconv, &mut param_bounds.builtin_bounds, ast_bounds, span); - - check_bounds_compatible(ccx, - param_ty, - ¶m_bounds, - span); } param_bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id())); @@ -1726,57 +1939,75 @@ fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, param_bounds } -fn check_bounds_compatible<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, - param_ty: Ty<'tcx>, - param_bounds: &ty::ParamBounds<'tcx>, - span: Span) { - if !param_bounds.builtin_bounds.contains(&ty::BoundSized) { - ty::each_bound_trait_and_supertraits( - ccx.tcx, - ¶m_bounds.trait_bounds[], - |trait_ref| { - let trait_def = ccx.get_trait_def(trait_ref.def_id()); - if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) { - span_err!(ccx.tcx.sess, span, E0129, - "incompatible bounds on `{}`, \ - bound `{}` does not allow unsized type", - param_ty.user_string(ccx.tcx), - trait_ref.user_string(ccx.tcx)); - } - true - }); +/// Converts a specific TyParamBound from the AST into a set of +/// predicates that apply to the self-type. A vector is returned +/// because this can be anywhere from 0 predicates (`T:?Sized` adds no +/// predicates) to 1 (`T:Foo`) to many (`T:Bar` adds `T:Bar` +/// and `::X == i32`). +fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>, + param_ty: Ty<'tcx>, + bound: &ast::TyParamBound) + -> Vec> +{ + match *bound { + ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => { + let mut projections = Vec::new(); + let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections); + projections.into_iter() + .map(|p| p.as_predicate()) + .chain(Some(pred.as_predicate()).into_iter()) + .collect() + } + ast::RegionTyParamBound(ref lifetime) => { + let region = ast_region_to_region(astconv.tcx(), lifetime); + let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region)); + vec![ty::Predicate::TypeOutlives(pred)] + } + ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => { + Vec::new() + } } } -fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, +fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>, + param_ty: Ty<'tcx>, + trait_ref: &ast::PolyTraitRef, + projections: &mut Vec>) + -> ty::PolyTraitRef<'tcx> +{ + astconv::instantiate_poly_trait_ref(astconv, + &ExplicitRscope, + trait_ref, + Some(param_ty), + projections) +} + +fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>, span: Span, param_ty: ty::Ty<'tcx>, ast_bounds: &[ast::TyParamBound]) -> ty::ParamBounds<'tcx> { - let tcx = ccx.tcx; + let tcx = astconv.tcx(); let astconv::PartitionedBounds { builtin_bounds, trait_bounds, region_bounds - } = astconv::partition_bounds(tcx, span, ast_bounds.as_slice()); + } = astconv::partition_bounds(tcx, span, &ast_bounds); let mut projection_bounds = Vec::new(); let trait_bounds: Vec = - trait_bounds.into_iter() - .map(|bound| { - astconv::instantiate_poly_trait_ref(ccx, - &ExplicitRscope, - bound, - Some(param_ty), - &mut projection_bounds) - }) - .collect(); + trait_bounds.iter() + .map(|bound| conv_poly_trait_ref(astconv, + param_ty, + *bound, + &mut projection_bounds)) + .collect(); let region_bounds: Vec = region_bounds.into_iter() - .map(|r| ast_region_to_region(ccx.tcx, r)) + .map(|r| ast_region_to_region(tcx, r)) .collect(); ty::ParamBounds { @@ -1788,7 +2019,7 @@ fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, } fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( - ccx: &CollectCtxt<'a, 'tcx>, + ccx: &CrateCtxt<'a, 'tcx>, decl: &ast::FnDecl, ast_generics: &ast::Generics, abi: abi::Abi) @@ -1805,17 +2036,17 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( } } - let ty_generics = ty_generics_for_fn_or_method(ccx, ast_generics, ty::Generics::empty()); + let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty()); let rb = BindingRscope::new(); let input_tys = decl.inputs .iter() - .map(|a| ty_of_arg(ccx, &rb, a, None)) + .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None)) .collect(); let output = match decl.output { ast::Return(ref ty) => - ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)), + ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)), ast::DefaultReturn(..) => ty::FnConverging(ty::mk_nil(ccx.tcx)), ast::NoReturn(..) => @@ -1839,9 +2070,9 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( } } -fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, +fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty_generics: &ty::Generics<'tcx>) - -> subst::Substs<'tcx> + -> Substs<'tcx> { let types = ty_generics.types.map( @@ -1851,7 +2082,7 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, ty_generics.regions.map( |def| def.to_early_bound_region()); - subst::Substs::new(types, regions) + Substs::new(types, regions) } /// Verifies that the explicit self type of a method matches the impl @@ -1861,15 +2092,16 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'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>( - ccx: &CollectCtxt<'a, 'tcx>, + ccx: &CrateCtxt<'a, 'tcx>, rs: &RS, + method_type: Rc>, required_type: Ty<'tcx>, explicit_self: &ast::ExplicitSelf, body_id: ast::NodeId) { let tcx = ccx.tcx; if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node { - let typ = ccx.to_ty(rs, &**ast_type); + let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type); let base_type = match typ.sty { ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty, ty::ty_uniq(typ) => typ, @@ -1976,18 +2208,10 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, idx: index as u32, name: ty_param.ident.name }; if !input_parameters.contains(¶m_ty) { - if ty::has_attr(tcx, impl_def_id, "old_impl_check") { - tcx.sess.span_warn( - ty_param.span, - &format!("the type parameter `{}` is not constrained by the \ - impl trait, self type, or predicates", - param_ty.user_string(tcx))); - } else { - span_err!(tcx.sess, ty_param.span, E0207, - "the type parameter `{}` is not constrained by the \ - impl trait, self type, or predicates", - param_ty.user_string(tcx)); - } + span_err!(tcx.sess, ty_param.span, E0207, + "the type parameter `{}` is not constrained by the \ + impl trait, self type, or predicates", + param_ty.user_string(tcx)); } } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 17cf92d39d..a8d93c8bd1 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -51,8 +51,6 @@ register_diagnostics! { E0075, E0076, E0077, - E0079, - E0080, E0081, E0082, E0083, @@ -80,6 +78,7 @@ register_diagnostics! { E0120, E0121, E0122, + E0123, E0124, E0127, E0128, @@ -171,8 +170,16 @@ register_diagnostics! { E0247, // found module name used as a type E0248, // found value name used as a type E0249, // expected constant expr for array length - E0250 // expected constant expr for array length + E0250, // expected constant expr for array length + E0318, // can't create default impls for traits outside their crates + E0319, // trait impls for defaulted traits allowed just for structs/enums + E0320, // recursive overflow during dropck + E0321, // extended coherence rules for defaulted traits violated + E0322, // cannot implement Sized explicitly + E0366, // dropck forbid specialization to concrete type or region + E0367, // dropck forbid specialization to predicate not in struct/enum + E0368, // binary operation `=` cannot be applied to types + E0369 // binary operation `` cannot be applied to types } __build_diagnostic_array! { DIAGNOSTICS } - diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index b5dca0bd4f..9d6c04b1ad 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -62,7 +62,8 @@ independently: This API is completely unstable and subject to change. */ - +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustc_typeck"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -78,8 +79,6 @@ This API is completely unstable and subject to change. #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(int_uint)] -#![feature(std_misc)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] @@ -127,12 +126,12 @@ mod constrained_type_params; mod coherence; mod variance; -struct TypeAndSubsts<'tcx> { +pub struct TypeAndSubsts<'tcx> { pub substs: subst::Substs<'tcx>, pub ty: Ty<'tcx>, } -struct CrateCtxt<'a, 'tcx: 'a> { +pub struct CrateCtxt<'a, 'tcx: 'a> { // A mapping from method call sites to traits that have that method. trait_map: ty::TraitMap, /// A vector of every trait accessible in the whole crate @@ -147,7 +146,7 @@ struct CrateCtxt<'a, 'tcx: 'a> { fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) { debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty)); assert!(!ty::type_needs_infer(ty)); - tcx.node_types.borrow_mut().insert(node_id, ty); + tcx.node_type_insert(node_id, ty); } fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, @@ -163,20 +162,16 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, tcx.item_substs.borrow_mut().insert(node_id, item_substs); } } -fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { + +fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { match tcx.def_map.borrow().get(&id) { - Some(x) => x.clone(), - _ => { + Some(x) => x.full_def(), + None => { span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition") } } } -fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId) - -> def::Def { - lookup_def_tcx(ccx.tcx, sp, id) -} - fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>, maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>, t1_is_expected: bool, @@ -253,7 +248,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, &format!("main has a non-function type: found \ `{}`", ppaux::ty_to_string(tcx, - main_t))[]); + main_t))); } } } @@ -285,10 +280,10 @@ fn check_start_fn_ty(ccx: &CrateCtxt, abi: abi::Rust, sig: ty::Binder(ty::FnSig { inputs: vec!( - tcx.types.int, + tcx.types.isize, ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, tcx.types.u8)) ), - output: ty::FnConverging(tcx.types.int), + output: ty::FnConverging(tcx.types.isize), variadic: false, }), })); @@ -304,7 +299,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, tcx.sess.span_bug(start_span, &format!("start has a non-function type: found \ `{}`", - ppaux::ty_to_string(tcx, start_t))[]); + ppaux::ty_to_string(tcx, start_t))); } } } diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index b591209a63..c908e21626 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -29,8 +29,8 @@ use syntax::codemap::Span; pub trait RegionScope { fn anon_regions(&self, span: Span, - count: uint) - -> Result, Option>>; + count: usize) + -> Result, Option>>; /// If an object omits any explicit lifetime bound, and none can /// be derived from the object traits, what should we use? If @@ -40,7 +40,7 @@ pub trait RegionScope { // A scope in which all regions must be explicitly named. This is used // for types that appear in structs and so on. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct ExplicitRscope; impl RegionScope for ExplicitRscope { @@ -50,17 +50,17 @@ impl RegionScope for ExplicitRscope { fn anon_regions(&self, _span: Span, - _count: uint) - -> Result, Option>> { + _count: usize) + -> Result, Option>> { Err(None) } } // Same as `ExplicitRscope`, but provides some extra information for diagnostics -pub struct UnelidableRscope(Vec<(String, uint)>); +pub struct UnelidableRscope(Vec<(String, usize)>); impl UnelidableRscope { - pub fn new(v: Vec<(String, uint)>) -> UnelidableRscope { + pub fn new(v: Vec<(String, usize)>) -> UnelidableRscope { UnelidableRscope(v) } } @@ -72,8 +72,8 @@ impl RegionScope for UnelidableRscope { fn anon_regions(&self, _span: Span, - _count: uint) - -> Result, Option>> { + _count: usize) + -> Result, Option>> { let UnelidableRscope(ref v) = *self; Err(Some(v.clone())) } @@ -103,8 +103,8 @@ impl RegionScope for ElidableRscope { fn anon_regions(&self, _span: Span, - count: uint) - -> Result, Option>> + count: usize) + -> Result, Option>> { Ok(repeat(self.default).take(count).collect()) } @@ -140,8 +140,8 @@ impl RegionScope for BindingRscope { fn anon_regions(&self, _: Span, - count: uint) - -> Result, Option>> + count: usize) + -> Result, Option>> { Ok((0..count).map(|_| self.next_region()).collect()) } @@ -176,8 +176,8 @@ impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> { fn anon_regions(&self, span: Span, - count: uint) - -> Result, Option>> + count: usize) + -> Result, Option>> { self.base_scope.anon_regions(span, count) } @@ -203,8 +203,8 @@ impl<'r> RegionScope for ShiftedRscope<'r> { fn anon_regions(&self, span: Span, - count: uint) - -> Result, Option>> + count: usize) + -> Result, Option>> { match self.base_scope.anon_regions(span, count) { Ok(mut v) => { diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 1adcf133bf..b83d8fc6af 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -203,6 +203,56 @@ //! failure, but rather because the target type `Foo` is itself just //! not well-formed. Basically we get to assume well-formedness of all //! types involved before considering variance. +//! +//! ### Associated types +//! +//! Any trait with an associated type is invariant with respect to all +//! of its inputs. To see why this makes sense, consider what +//! subtyping for a trait reference means: +//! +//! <: +//! +//! means that if I know that `T as Trait`, +//! I also know that `U as +//! Trait`. Moreover, if you think of it as +//! dictionary passing style, it means that +//! a dictionary for `` is safe +//! to use where a dictionary for `` is expected. +//! +//! The problem is that when you can +//! project types out from ``, +//! the relationship to types projected out +//! of `` is completely unknown +//! unless `T==U` (see #21726 for more +//! details). Making `Trait` invariant +//! ensures that this is true. +//! +//! *Historical note: we used to preserve this invariant another way, +//! by tweaking the subtyping rules and requiring that when a type `T` +//! appeared as part of a projection, that was considered an invariant +//! location, but this version does away with the need for those +//! somewhat "special-case-feeling" rules.* +//! +//! Another related reason is that if we didn't make traits with +//! associated types invariant, then projection is no longer a +//! function with a single result. Consider: +//! +//! ``` +//! trait Identity { type Out; fn foo(&self); } +//! impl Identity for T { type Out = T; ... } +//! ``` +//! +//! Now if I have `<&'static () as Identity>::Out`, this can be +//! validly derived as `&'a ()` for any `'a`: +//! +//! <&'a () as Identity> <: <&'static () as Identity> +//! if &'static () < : &'a () -- Identity is contravariant in Self +//! if 'static : 'a -- Subtyping rules for relations +//! +//! This change otoh means that `<'static () as Identity>::Out` is +//! always `&'static ()` (which might then be upcast to `'a ()`, +//! separately). This was helpful in solving #21750. use self::VarianceTerm::*; use self::ParamKind::*; @@ -245,10 +295,10 @@ pub fn infer_variance(tcx: &ty::ctxt) { type VarianceTermPtr<'a> = &'a VarianceTerm<'a>; -#[derive(Copy, Debug)] -struct InferredIndex(uint); +#[derive(Copy, Clone, Debug)] +struct InferredIndex(usize); -#[derive(Copy)] +#[derive(Copy, Clone)] enum VarianceTerm<'a> { ConstantTerm(ty::Variance), TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>), @@ -286,7 +336,7 @@ struct TermsContext<'a, 'tcx: 'a> { inferred_infos: Vec> , } -#[derive(Copy, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] enum ParamKind { TypeParam, RegionParam, @@ -296,7 +346,7 @@ struct InferredInfo<'a> { item_id: ast::NodeId, kind: ParamKind, space: ParamSpace, - index: uint, + index: usize, param_id: ast::NodeId, term: VarianceTermPtr<'a>, @@ -407,7 +457,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { item_id: ast::NodeId, kind: ParamKind, space: ParamSpace, - index: uint, + index: usize, param_id: ast::NodeId) { let inf_index = InferredIndex(self.inferred_infos.len()); let term = self.arena.alloc(InferredTerm(inf_index)); @@ -438,7 +488,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { fn pick_initial_variance(&self, item_id: ast::NodeId, space: ParamSpace, - index: uint) + index: usize) -> ty::Variance { match space { @@ -455,7 +505,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { } } - fn num_inferred(&self) -> uint { + fn num_inferred(&self) -> usize { self.inferred_infos.len() } } @@ -476,6 +526,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { ast::ItemExternCrate(_) | ast::ItemUse(_) | + ast::ItemDefaultImpl(..) | ast::ItemImpl(..) | ast::ItemStatic(..) | ast::ItemConst(..) | @@ -509,7 +560,7 @@ struct ConstraintContext<'a, 'tcx: 'a> { /// Declares that the variable `decl_id` appears in a location with /// variance `variance`. -#[derive(Copy)] +#[derive(Copy, Clone)] struct Constraint<'a> { inferred: InferredIndex, variance: &'a VarianceTerm<'a>, @@ -593,9 +644,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { ast::ItemTrait(..) => { let trait_def = ty::lookup_trait_def(tcx, did); - let predicates = ty::predicates(tcx, ty::mk_self_type(tcx), &trait_def.bounds); + let predicates = ty::lookup_super_predicates(tcx, did); self.add_constraints_from_predicates(&trait_def.generics, - &predicates[], + predicates.predicates.as_slice(), self.covariant); let trait_items = ty::trait_items(tcx, did); @@ -612,7 +663,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { &method.fty.sig, self.covariant); } - ty::TypeTraitItem(_) => {} + ty::TypeTraitItem(ref data) => { + // Any trait with an associated type is + // invariant with respect to all of its + // inputs. See length discussion in the comment + // on this module. + let projection_ty = ty::mk_projection(tcx, + trait_def.trait_ref.clone(), + data.name); + self.add_constraints_from_ty(&trait_def.generics, + projection_ty, + self.invariant); + } } } } @@ -626,6 +688,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> { ast::ItemForeignMod(..) | ast::ItemTy(..) | ast::ItemImpl(..) | + ast::ItemDefaultImpl(..) | ast::ItemMac(..) => { } } @@ -652,7 +715,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { None => { self.tcx().sess.bug(&format!( "no inferred index entry for {}", - self.tcx().map.node_to_string(param_id))[]); + self.tcx().map.node_to_string(param_id))); } } } @@ -728,7 +791,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { item_def_id: ast::DefId, kind: ParamKind, space: ParamSpace, - index: uint) + index: usize) -> VarianceTermPtr<'a> { assert_eq!(param_def_id.krate, item_def_id.krate); @@ -847,7 +910,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_mt(generics, mt, variance); } - ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => { + ty::ty_uniq(typ) | ty::ty_vec(typ, _) => { self.add_constraints_from_ty(generics, typ, variance); } @@ -891,7 +954,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { trait_def.generics.types.as_slice(), trait_def.generics.regions.as_slice(), trait_ref.substs, - self.invariant); + variance); } ty::ty_trait(ref data) => { @@ -914,7 +977,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::ty_param(ref data) => { - let def_id = generics.types.get(data.space, data.idx as uint).def_id; + let def_id = generics.types.get(data.space, data.idx as usize).def_id; assert_eq!(def_id.krate, ast::LOCAL_CRATE); match self.terms_cx.inferred_map.get(&def_id.node) { Some(&index) => { @@ -941,7 +1004,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.tcx().sess.bug( &format!("unexpected type encountered in \ variance inference: {}", - ty.repr(self.tcx()))[]); + ty.repr(self.tcx()))); } } } @@ -964,9 +1027,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { for p in type_param_defs { let variance_decl = self.declared_variance(p.def_id, def_id, TypeParam, - p.space, p.index as uint); + p.space, p.index as usize); let variance_i = self.xform(variance, variance_decl); - let substs_ty = *substs.types.get(p.space, p.index as uint); + let substs_ty = *substs.types.get(p.space, p.index as usize); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", variance_decl, variance_i); self.add_constraints_from_ty(generics, substs_ty, variance_i); @@ -975,9 +1038,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { for p in region_param_defs { let variance_decl = self.declared_variance(p.def_id, def_id, - RegionParam, p.space, p.index as uint); + RegionParam, p.space, p.index as usize); let variance_i = self.xform(variance, variance_decl); - let substs_r = *substs.regions().get(p.space, p.index as uint); + let substs_r = *substs.regions().get(p.space, p.index as usize); self.add_constraints_from_region(generics, substs_r, variance_i); } } @@ -996,14 +1059,29 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::Predicate::Equate(ty::Binder(ref data)) => { - self.add_constraints_from_ty(generics, data.0, variance); - self.add_constraints_from_ty(generics, data.1, variance); + // A == B is only true if A and B are the same + // types, not subtypes of one another, so this is + // an invariant position: + self.add_constraints_from_ty(generics, data.0, self.invariant); + self.add_constraints_from_ty(generics, data.1, self.invariant); } ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { - self.add_constraints_from_ty(generics, data.0, variance); + // Why contravariant on both? Let's consider: + // + // Under what conditions is `(T:'t) <: (U:'u)`, + // meaning that `(T:'t) => (U:'u)`. The answer is + // if `U <: T` or `'u <= 't`. Let's see some examples: + // + // (T: 'big) => (T: 'small) + // where 'small <= 'big + // + // (&'small Foo: 't) => (&'big Foo: 't) + // where 'small <= 'big + // note that &'big Foo <: &'small Foo let variance_r = self.xform(variance, self.contravariant); + self.add_constraints_from_ty(generics, data.0, variance_r); self.add_constraints_from_region(generics, data.1, variance_r); } @@ -1021,6 +1099,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { &*data.projection_ty.trait_ref, variance); + // as the equality predicate above, a binder is a + // type equality relation, not a subtyping + // relation self.add_constraints_from_ty(generics, data.ty, self.invariant); } } @@ -1071,7 +1152,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { .sess .bug(&format!("unexpected region encountered in variance \ inference: {}", - region.repr(self.tcx()))[]); + region.repr(self.tcx()))); } } } @@ -1287,4 +1368,3 @@ fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { (x, ty::Bivariant) | (ty::Bivariant, x) => x, } } - diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d1283d6f46..aa17bf20d7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -46,7 +46,7 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option) None => return None, }; let def = match tcx.def_map.borrow().get(&id) { - Some(def) => *def, + Some(d) => d.full_def(), None => return None, }; let did = def.def_id(); @@ -147,32 +147,14 @@ pub fn record_extern_fqn(cx: &DocContext, did: ast::DefId, kind: clean::TypeKind pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait { - use clean::TraitMethod; - let def = ty::lookup_trait_def(tcx, did); let trait_items = ty::trait_items(tcx, did).clean(cx); - let provided = ty::provided_trait_methods(tcx, did); - let items = trait_items.into_iter().map(|trait_item| { - match trait_item.inner { - clean::TyMethodItem(_) => { - if provided.iter().any(|a| a.def_id == trait_item.def_id) { - TraitMethod::ProvidedMethod(trait_item) - } else { - TraitMethod::RequiredMethod(trait_item) - } - }, - clean::AssociatedTypeItem(_) => TraitMethod::TypeTraitItem(trait_item), - _ => unreachable!() - } - }); - let trait_def = ty::lookup_trait_def(tcx, did); let predicates = ty::lookup_predicates(tcx, did); - let bounds = trait_def.bounds.clean(cx); clean::Trait { unsafety: def.unsafety, generics: (&def.generics, &predicates, subst::TypeSpace).clean(cx), - items: items.collect(), - bounds: bounds, + items: trait_items, + bounds: vec![], // supertraits can be found in the list of predicates } } @@ -277,26 +259,43 @@ fn build_impls(cx: &DocContext, tcx: &ty::ctxt, impls.into_iter().filter_map(|a| a).collect() } -fn build_impl(cx: &DocContext, tcx: &ty::ctxt, +fn build_impl(cx: &DocContext, + tcx: &ty::ctxt, did: ast::DefId) -> Option { if !cx.inlined.borrow_mut().as_mut().unwrap().insert(did) { return None } + let attrs = load_attrs(cx, tcx, did); let associated_trait = csearch::get_impl_trait(tcx, did); - // If this is an impl for a #[doc(hidden)] trait, be sure to not inline it. - match associated_trait { - Some(ref t) => { - let trait_attrs = load_attrs(cx, tcx, t.def_id); - if trait_attrs.iter().any(|a| is_doc_hidden(a)) { - return None - } + if let Some(ref t) = associated_trait { + // If this is an impl for a #[doc(hidden)] trait, be sure to not inline + let trait_attrs = load_attrs(cx, tcx, t.def_id); + if trait_attrs.iter().any(|a| is_doc_hidden(a)) { + return None } - None => {} } - let attrs = load_attrs(cx, tcx, did); - let ty = ty::lookup_item_type(tcx, did); + // If this is a defaulted impl, then bail out early here + if csearch::is_default_impl(&tcx.sess.cstore, did) { + return Some(clean::Item { + inner: clean::DefaultImplItem(clean::DefaultImpl { + // FIXME: this should be decoded + unsafety: ast::Unsafety::Normal, + trait_: match associated_trait.as_ref().unwrap().clean(cx) { + clean::TraitBound(polyt, _) => polyt.trait_, + clean::RegionBound(..) => unreachable!(), + }, + }), + source: clean::Span::empty(), + name: None, + attrs: attrs, + visibility: Some(ast::Inherited), + stability: stability::lookup(tcx, did).clean(cx), + def_id: did, + }); + } + let predicates = ty::lookup_predicates(tcx, did); let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did) .iter() @@ -308,6 +307,9 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, if method.vis != ast::Public && associated_trait.is_none() { return None } + if method.provided_source.is_some() { + return None + } let mut item = method.clean(cx); item.inner = match item.inner.clone() { clean::TyMethodItem(clean::TyMethod { @@ -345,8 +347,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, } }).collect(); let polarity = csearch::get_impl_polarity(tcx, did); + let ty = ty::lookup_item_type(tcx, did); return Some(clean::Item { inner: clean::ImplItem(clean::Impl { + unsafety: ast::Unsafety::Normal, // FIXME: this should be decoded derived: clean::detect_derived(&attrs), trait_: associated_trait.clean(cx).map(|bound| { match bound { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7ef48378af..e0ed83f401 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -11,7 +11,6 @@ //! This module contains the "cleaned" pieces of the AST, and the functions //! that clean them. -pub use self::ImplMethod::*; pub use self::Type::*; pub use self::PrimitiveType::*; pub use self::TypeKind::*; @@ -24,13 +23,11 @@ pub use self::Attribute::*; pub use self::TyParamBound::*; pub use self::SelfTy::*; pub use self::FunctionRetTy::*; -pub use self::TraitMethod::*; use syntax; use syntax::abi; use syntax::ast; use syntax::ast_util; -use syntax::ast_util::PostExpansionMethod; use syntax::attr; use syntax::attr::{AttributeMethods, AttrMetaMethods}; use syntax::codemap; @@ -49,7 +46,7 @@ use rustc::middle::stability; use std::rc::Rc; use std::u32; -use std::old_path::Path as FsPath; // Conflicts with Path struct +use std::path::PathBuf; use core::DocContext; use doctree; @@ -70,7 +67,7 @@ pub trait Clean { fn clean(&self, cx: &DocContext) -> T; } -impl, U> Clean> for Vec { +impl, U> Clean> for [T] { fn clean(&self, cx: &DocContext) -> Vec { self.iter().map(|x| x.clean(cx)).collect() } @@ -118,7 +115,7 @@ impl, U> Clean> for syntax::owned_slice::OwnedSlice { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Crate { pub name: String, - pub src: FsPath, + pub src: PathBuf, pub module: Option, pub externs: Vec<(ast::CrateNum, ExternalCrate)>, pub primitives: Vec, @@ -191,7 +188,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { let src = match cx.input { Input::File(ref path) => path.clone(), - Input::Str(_) => FsPath::new("") // FIXME: this is wrong + Input::Str(_) => PathBuf::new() // FIXME: this is wrong }; Crate { @@ -339,7 +336,8 @@ pub enum ItemEnum { ForeignStaticItem(Static), MacroItem(Macro), PrimitiveItem(PrimitiveType), - AssociatedTypeItem(TyParam), + AssociatedTypeItem(Vec, Option), + DefaultImplItem(DefaultImpl), } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -370,6 +368,7 @@ impl Clean for doctree::Module { items.extend(self.traits.iter().map(|x| x.clean(cx))); items.extend(self.impls.iter().map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); + items.extend(self.def_traits.iter().map(|x| x.clean(cx))); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -479,11 +478,10 @@ impl<'tcx> Clean for ty::TypeParameterDef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParam { cx.external_typarams.borrow_mut().as_mut().unwrap() .insert(self.def_id, self.name.clean(cx)); - let bounds = self.bounds.clean(cx); TyParam { name: self.name.clean(cx), did: self.def_id, - bounds: bounds, + bounds: vec![], // these are filled in from the where-clauses default: self.default.clean(cx), } } @@ -892,9 +890,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, // Bounds in the type_params and lifetimes fields are repeated in the predicates // field (see rustc_typeck::collect::ty_generics), so remove them. let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| { - let mut stp = tp.clone(); - stp.bounds = ty::ParamBounds::empty(); - stp.clean(cx) + tp.clean(cx) }).collect::>(); let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { let mut srp = rp.clone(); @@ -954,34 +950,26 @@ pub struct Method { pub abi: abi::Abi } -impl Clean for ast::Method { - fn clean(&self, cx: &DocContext) -> Item { - let all_inputs = &self.pe_fn_decl().inputs; - let inputs = match self.pe_explicit_self().node { +impl Clean for ast::MethodSig { + fn clean(&self, cx: &DocContext) -> Method { + let all_inputs = &self.decl.inputs; + let inputs = match self.explicit_self.node { ast::SelfStatic => &**all_inputs, _ => &all_inputs[1..] }; let decl = FnDecl { inputs: Arguments { - values: inputs.iter().map(|x| x.clean(cx)).collect(), + values: inputs.clean(cx), }, - output: self.pe_fn_decl().output.clean(cx), + output: self.decl.output.clean(cx), attrs: Vec::new() }; - Item { - name: Some(self.pe_ident().clean(cx)), - attrs: self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: ast_util::local_def(self.id), - visibility: self.pe_vis().clean(cx), - stability: get_stability(cx, ast_util::local_def(self.id)), - inner: MethodItem(Method { - generics: self.pe_generics().clean(cx), - self_: self.pe_explicit_self().node.clean(cx), - unsafety: self.pe_unsafety().clone(), - decl: decl, - abi: self.pe_abi() - }), + Method { + generics: self.generics.clean(cx), + self_: self.explicit_self.node.clean(cx), + unsafety: self.unsafety.clone(), + decl: decl, + abi: self.abi } } } @@ -995,33 +983,25 @@ pub struct TyMethod { pub abi: abi::Abi } -impl Clean for ast::TypeMethod { - fn clean(&self, cx: &DocContext) -> Item { +impl Clean for ast::MethodSig { + fn clean(&self, cx: &DocContext) -> TyMethod { let inputs = match self.explicit_self.node { ast::SelfStatic => &*self.decl.inputs, _ => &self.decl.inputs[1..] }; let decl = FnDecl { inputs: Arguments { - values: inputs.iter().map(|x| x.clean(cx)).collect(), + values: inputs.clean(cx), }, output: self.decl.output.clean(cx), attrs: Vec::new() }; - Item { - name: Some(self.ident.clean(cx)), - attrs: self.attrs.clean(cx), - source: self.span.clean(cx), - def_id: ast_util::local_def(self.id), - visibility: None, - stability: get_stability(cx, ast_util::local_def(self.id)), - inner: TyMethodItem(TyMethod { - unsafety: self.unsafety.clone(), - decl: decl, - self_: self.explicit_self.node.clean(cx), - generics: self.generics.clean(cx), - abi: self.abi - }), + TyMethod { + unsafety: self.unsafety.clone(), + decl: decl, + self_: self.explicit_self.node.clean(cx), + generics: self.generics.clean(cx), + abi: self.abi } } } @@ -1169,7 +1149,7 @@ impl Clean for ast::FunctionRetTy { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Trait { pub unsafety: ast::Unsafety, - pub items: Vec, + pub items: Vec, pub generics: Generics, pub bounds: Vec, } @@ -1208,64 +1188,59 @@ impl Clean for ast::PolyTraitRef { } } -/// An item belonging to a trait, whether a method or associated. Could be named -/// TraitItem except that's already taken by an exported enum variant. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum TraitMethod { - RequiredMethod(Item), - ProvidedMethod(Item), - TypeTraitItem(Item), // an associated type -} - -impl TraitMethod { - pub fn is_req(&self) -> bool { - match self { - &RequiredMethod(..) => true, - _ => false, - } - } - pub fn is_def(&self) -> bool { - match self { - &ProvidedMethod(..) => true, - _ => false, - } - } - pub fn is_type(&self) -> bool { - match self { - &TypeTraitItem(..) => true, - _ => false, - } - } - pub fn item<'a>(&'a self) -> &'a Item { - match *self { - RequiredMethod(ref item) => item, - ProvidedMethod(ref item) => item, - TypeTraitItem(ref item) => item, - } - } -} - -impl Clean for ast::TraitItem { - fn clean(&self, cx: &DocContext) -> TraitMethod { - match self { - &ast::RequiredMethod(ref t) => RequiredMethod(t.clean(cx)), - &ast::ProvidedMethod(ref t) => ProvidedMethod(t.clean(cx)), - &ast::TypeTraitItem(ref t) => TypeTraitItem(t.clean(cx)), +impl Clean for ast::TraitItem { + fn clean(&self, cx: &DocContext) -> Item { + let inner = match self.node { + ast::MethodTraitItem(ref sig, Some(_)) => { + MethodItem(sig.clean(cx)) + } + ast::MethodTraitItem(ref sig, None) => { + TyMethodItem(sig.clean(cx)) + } + ast::TypeTraitItem(ref bounds, ref default) => { + AssociatedTypeItem(bounds.clean(cx), default.clean(cx)) + } + }; + Item { + name: Some(self.ident.clean(cx)), + attrs: self.attrs.clean(cx), + source: self.span.clean(cx), + def_id: ast_util::local_def(self.id), + visibility: None, + stability: get_stability(cx, ast_util::local_def(self.id)), + inner: inner } } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ImplMethod { - MethodImplItem(Item), - TypeImplItem(Item), -} - -impl Clean for ast::ImplItem { - fn clean(&self, cx: &DocContext) -> ImplMethod { - match self { - &ast::MethodImplItem(ref t) => MethodImplItem(t.clean(cx)), - &ast::TypeImplItem(ref t) => TypeImplItem(t.clean(cx)), +impl Clean for ast::ImplItem { + fn clean(&self, cx: &DocContext) -> Item { + let inner = match self.node { + ast::MethodImplItem(ref sig, _) => { + MethodItem(sig.clean(cx)) + } + ast::TypeImplItem(ref ty) => TypedefItem(Typedef { + type_: ty.clean(cx), + generics: Generics { + lifetimes: Vec::new(), + type_params: Vec::new(), + where_predicates: Vec::new() + }, + }), + ast::MacImplItem(_) => { + MacroItem(Macro { + source: self.span.to_src(cx), + }) + } + }; + Item { + name: Some(self.ident.clean(cx)), + source: self.span.clean(cx), + attrs: self.attrs.clean(cx), + def_id: ast_util::local_def(self.id), + visibility: self.vis.clean(cx), + stability: get_stability(cx, ast_util::local_def(self.id)), + inner: inner } } } @@ -1344,12 +1319,11 @@ pub enum Type { typarams: Option>, did: ast::DefId, }, - // I have no idea how to usefully use this. - TyParamBinder(ast::NodeId), /// For parameterized types, so the consumer of the JSON don't go /// looking for types which don't exist anywhere. Generic(String), - /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char. + /// Primitives are the fixed-size numeric types (plus int/usize/float), char, + /// arrays, slices, and tuples. Primitive(PrimitiveType), /// extern "ABI" fn BareFunction(Box), @@ -1389,6 +1363,7 @@ pub enum PrimitiveType { Bool, Str, Slice, + Array, PrimitiveTuple, } @@ -1408,12 +1383,12 @@ pub enum TypeKind { impl PrimitiveType { fn from_str(s: &str) -> Option { match s { - "isize" | "int" => Some(Isize), + "isize" => Some(Isize), "i8" => Some(I8), "i16" => Some(I16), "i32" => Some(I32), "i64" => Some(I64), - "usize" | "uint" => Some(Usize), + "usize" => Some(Usize), "u8" => Some(U8), "u16" => Some(U16), "u32" => Some(U32), @@ -1423,6 +1398,7 @@ impl PrimitiveType { "str" => Some(Str), "f32" => Some(F32), "f64" => Some(F64), + "array" => Some(Array), "slice" => Some(Slice), "tuple" => Some(PrimitiveTuple), _ => None, @@ -1467,6 +1443,7 @@ impl PrimitiveType { Str => "str", Bool => "bool", Char => "char", + Array => "array", Slice => "slice", PrimitiveTuple => "tuple", } @@ -1496,8 +1473,17 @@ impl Clean for ast::Ty { TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), e.span.to_src(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)), - TyPath(ref p, id) => { - resolve_type(cx, p.clean(cx), id) + TyPath(None, ref p) => { + resolve_type(cx, p.clean(cx), self.id) + } + TyPath(Some(ref qself), ref p) => { + let mut trait_path = p.clone(); + trait_path.segments.pop(); + Type::QPath { + name: p.segments.last().unwrap().identifier.clean(cx), + self_type: box qself.ty.clean(cx), + trait_: box resolve_type(cx, trait_path.clean(cx), self.id) + } } TyObjectSum(ref lhs, ref bounds) => { let lhs_ty = lhs.clean(cx); @@ -1512,7 +1498,6 @@ impl Clean for ast::Ty { } TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyParen(ref ty) => ty.clean(cx), - TyQPath(ref qp) => qp.clean(cx), TyPolyTraitRef(ref bounds) => { PolyTraitRef(bounds.clean(cx)) }, @@ -1531,12 +1516,12 @@ impl<'tcx> Clean for ty::Ty<'tcx> { match self.sty { ty::ty_bool => Primitive(Bool), ty::ty_char => Primitive(Char), - ty::ty_int(ast::TyIs(_)) => Primitive(Isize), + ty::ty_int(ast::TyIs) => Primitive(Isize), ty::ty_int(ast::TyI8) => Primitive(I8), ty::ty_int(ast::TyI16) => Primitive(I16), ty::ty_int(ast::TyI32) => Primitive(I32), ty::ty_int(ast::TyI64) => Primitive(I64), - ty::ty_uint(ast::TyUs(_)) => Primitive(Usize), + ty::ty_uint(ast::TyUs) => Primitive(Usize), ty::ty_uint(ast::TyU8) => Primitive(U8), ty::ty_uint(ast::TyU16) => Primitive(U16), ty::ty_uint(ast::TyU32) => Primitive(U32), @@ -1619,22 +1604,11 @@ impl<'tcx> Clean for ty::Ty<'tcx> { ty::ty_closure(..) => Tuple(vec![]), // FIXME(pcwalton) ty::ty_infer(..) => panic!("ty_infer"), - ty::ty_open(..) => panic!("ty_open"), ty::ty_err => panic!("ty_err"), } } } -impl Clean for ast::QPath { - fn clean(&self, cx: &DocContext) -> Type { - Type::QPath { - name: self.item_path.identifier.clean(cx), - self_type: box self.self_type.clean(cx), - trait_: box self.trait_ref.clean(cx) - } - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum StructField { HiddenStructField, // inserted later by strip passes @@ -1859,10 +1833,10 @@ impl Clean for ast::VariantKind { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Span { pub filename: String, - pub loline: uint, - pub locol: uint, - pub hiline: uint, - pub hicol: uint, + pub loline: usize, + pub locol: usize, + pub hiline: usize, + pub hicol: usize, } impl Span { @@ -2111,6 +2085,7 @@ impl Clean for ast::ImplPolarity { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Impl { + pub unsafety: ast::Unsafety, pub generics: Generics, pub trait_: Option, pub for_: Type, @@ -2133,15 +2108,11 @@ impl Clean for doctree::Impl { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), inner: ImplItem(Impl { + unsafety: self.unsafety, generics: self.generics.clean(cx), trait_: self.trait_.clean(cx), for_: self.for_.clean(cx), - items: self.items.clean(cx).into_iter().map(|ti| { - match ti { - MethodImplItem(i) => i, - TypeImplItem(i) => i, - } - }).collect(), + items: self.items.clean(cx), derived: detect_derived(&self.attrs), polarity: Some(self.polarity.clean(cx)), }), @@ -2149,6 +2120,29 @@ impl Clean for doctree::Impl { } } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct DefaultImpl { + pub unsafety: ast::Unsafety, + pub trait_: Type, +} + +impl Clean for doctree::DefaultImpl { + fn clean(&self, cx: &DocContext) -> Item { + Item { + name: None, + attrs: self.attrs.clean(cx), + source: self.whence.clean(cx), + def_id: ast_util::local_def(self.id), + visibility: Some(ast::Public), + stability: None, + inner: DefaultImplItem(DefaultImpl { + unsafety: self.unsafety, + trait_: self.trait_.clean(cx), + }), + } + } +} + impl Clean for doctree::ExternCrate { fn clean(&self, cx: &DocContext) -> Item { Item { @@ -2169,7 +2163,7 @@ impl Clean> for doctree::Import { // forcefully don't inline if this is not public or if the // #[doc(no_inline)] attribute is present. let denied = self.vis != ast::Public || self.attrs.iter().any(|a| { - &a.name()[] == "doc" && match a.meta_item_list() { + &a.name()[..] == "doc" && match a.meta_item_list() { Some(l) => attr::contains_name(l, "no_inline"), None => false, } @@ -2393,24 +2387,24 @@ fn resolve_type(cx: &DocContext, }; debug!("searching for {} in defmap", id); let def = match tcx.def_map.borrow().get(&id) { - Some(&k) => k, + Some(k) => k.full_def(), None => panic!("unresolved id not in defmap") }; match def { - def::DefSelfTy(..) => { + def::DefSelfTy(..) if path.segments.len() == 1 => { return Generic(token::get_name(special_idents::type_self.name).to_string()); } def::DefPrimTy(p) => match p { ast::TyStr => return Primitive(Str), ast::TyBool => return Primitive(Bool), ast::TyChar => return Primitive(Char), - ast::TyInt(ast::TyIs(_)) => return Primitive(Isize), + ast::TyInt(ast::TyIs) => return Primitive(Isize), ast::TyInt(ast::TyI8) => return Primitive(I8), ast::TyInt(ast::TyI16) => return Primitive(I16), ast::TyInt(ast::TyI32) => return Primitive(I32), ast::TyInt(ast::TyI64) => return Primitive(I64), - ast::TyUint(ast::TyUs(_)) => return Primitive(Usize), + ast::TyUint(ast::TyUs) => return Primitive(Usize), ast::TyUint(ast::TyU8) => return Primitive(U8), ast::TyUint(ast::TyU16) => return Primitive(U16), ast::TyUint(ast::TyU32) => return Primitive(U32), @@ -2418,8 +2412,9 @@ fn resolve_type(cx: &DocContext, ast::TyFloat(ast::TyF32) => return Primitive(F32), ast::TyFloat(ast::TyF64) => return Primitive(F64), }, - def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()), - def::DefTyParamBinder(i) => return TyParamBinder(i), + def::DefTyParam(_, _, _, n) => { + return Generic(token::get_name(n).to_string()) + } _ => {} }; let did = register_def(&*cx, def); @@ -2460,7 +2455,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option { cx.tcx_opt().and_then(|tcx| { - tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def)) + tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def())) }) } @@ -2509,37 +2504,15 @@ impl Clean for attr::Stability { } } -impl Clean for ast::AssociatedType { - fn clean(&self, cx: &DocContext) -> Item { - Item { - source: self.ty_param.span.clean(cx), - name: Some(self.ty_param.ident.clean(cx)), - attrs: self.attrs.clean(cx), - inner: AssociatedTypeItem(self.ty_param.clean(cx)), - visibility: None, - def_id: ast_util::local_def(self.ty_param.id), - stability: None, - } - } -} - impl Clean for ty::AssociatedType { fn clean(&self, cx: &DocContext) -> Item { Item { source: DUMMY_SP.clean(cx), name: Some(self.name.clean(cx)), attrs: Vec::new(), - inner: AssociatedTypeItem(TyParam { - name: self.name.clean(cx), - did: ast::DefId { - krate: 0, - node: ast::DUMMY_NODE_ID - }, - // FIXME(#20727): bounds are missing and need to be filled in from the - // predicates on the trait itself - bounds: vec![], - default: None, - }), + // FIXME(#20727): bounds are missing and need to be filled in from the + // predicates on the trait itself + inner: AssociatedTypeItem(vec![], None), visibility: None, def_id: self.def_id, stability: None, @@ -2547,27 +2520,6 @@ impl Clean for ty::AssociatedType { } } -impl Clean for ast::Typedef { - fn clean(&self, cx: &DocContext) -> Item { - Item { - source: self.span.clean(cx), - name: Some(self.ident.clean(cx)), - attrs: self.attrs.clean(cx), - inner: TypedefItem(Typedef { - type_: self.typ.clean(cx), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, - }), - visibility: None, - def_id: ast_util::local_def(self.id), - stability: None, - } - } -} - impl<'a> Clean for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>, ParamSpace) { fn clean(&self, cx: &DocContext) -> Typedef { let (ref ty_scheme, ref predicates, ps) = *self; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index f862970446..113a622b07 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -9,6 +9,7 @@ // except according to those terms. pub use self::MaybeTyped::*; +use rustc_lint; use rustc_driver::driver; use rustc::session::{self, config}; use rustc::session::config::UnstableFeatures; @@ -114,6 +115,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, let sess = session::build_session_(sessopts, cpath, span_diagnostic_handler); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let cfg = config::build_configuration(&sess); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index ba5df56f4f..c6d8b9428c 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -39,6 +39,7 @@ pub struct Module { pub vis: ast::Visibility, pub stab: Option, pub impls: Vec, + pub def_traits: Vec, pub foreigns: Vec, pub macros: Vec, pub is_crate: bool, @@ -65,6 +66,7 @@ impl Module { constants : Vec::new(), traits : Vec::new(), impls : Vec::new(), + def_traits : Vec::new(), foreigns : Vec::new(), macros : Vec::new(), is_crate : false, @@ -172,7 +174,7 @@ pub struct Constant { pub struct Trait { pub unsafety: ast::Unsafety, pub name: Ident, - pub items: Vec, //should be TraitItem + pub items: Vec>, //should be TraitItem pub generics: ast::Generics, pub bounds: Vec, pub attrs: Vec, @@ -188,7 +190,7 @@ pub struct Impl { pub generics: ast::Generics, pub trait_: Option, pub for_: P, - pub items: Vec, + pub items: Vec>, pub attrs: Vec, pub whence: Span, pub vis: ast::Visibility, @@ -196,6 +198,14 @@ pub struct Impl { pub id: ast::NodeId, } +pub struct DefaultImpl { + pub unsafety: ast::Unsafety, + pub trait_: ast::TraitRef, + pub id: ast::NodeId, + pub attrs: Vec, + pub whence: Span, +} + pub struct Macro { pub name: Ident, pub id: ast::NodeId, diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 942aec7d22..57cb87e1b2 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{old_io, str}; +use std::fs::File; +use std::io::prelude::*; +use std::io; +use std::path::{PathBuf, Path}; +use std::str; #[derive(Clone)] pub struct ExternalHtml{ @@ -33,24 +37,25 @@ impl ExternalHtml { } } -pub fn load_string(input: &Path) -> old_io::IoResult> { - let mut f = try!(old_io::File::open(input)); - let d = try!(f.read_to_end()); +pub fn load_string(input: &Path) -> io::Result> { + let mut f = try!(File::open(input)); + let mut d = Vec::new(); + try!(f.read_to_end(&mut d)); Ok(str::from_utf8(&d).map(|s| s.to_string()).ok()) } macro_rules! load_or_return { ($input: expr, $cant_read: expr, $not_utf8: expr) => { { - let input = Path::new($input); + let input = PathBuf::from(&$input[..]); match ::externalfiles::load_string(&input) { Err(e) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error reading `{}`: {}", input.display(), e); return $cant_read; } Ok(None) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error reading `{}`: not UTF-8", input.display()); return $not_utf8; } diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index ad91c3cb2c..760fa329fd 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -20,9 +20,11 @@ pub use self::imp::Lock; #[cfg(unix)] mod imp { - use std::ffi::CString; + use std::ffi::{CString, OsStr}; + use std::os::unix::prelude::*; + use std::path::Path; + use std::io; use libc; - use std::os as stdos; #[cfg(target_os = "linux")] mod os { @@ -64,7 +66,9 @@ mod imp { pub const F_SETLKW: libc::c_int = 13; } - #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] + #[cfg(any(target_os = "dragonfly", + target_os = "bitrig", + target_os = "openbsd"))] mod os { use libc; @@ -112,13 +116,14 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let buf = CString::new(p.as_vec()).unwrap(); + let os: &OsStr = p.as_ref(); + let buf = CString::new(os.as_bytes()).unwrap(); let fd = unsafe { libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU) }; - assert!(fd > 0, "failed to open lockfile: [{}] {}", - stdos::errno(), stdos::last_os_error()); + assert!(fd > 0, "failed to open lockfile: {}", + io::Error::last_os_error()); let flock = os::flock { l_start: 0, l_len: 0, @@ -131,10 +136,9 @@ mod imp { libc::fcntl(fd, os::F_SETLKW, &flock) }; if ret == -1 { - let errno = stdos::errno(); + let err = io::Error::last_os_error(); unsafe { libc::close(fd); } - panic!("could not lock `{}`: [{}] {}", p.display(), - errno, stdos::error_string(errno)) + panic!("could not lock `{}`: {}", p.display(), err); } Lock { fd: fd } } @@ -161,11 +165,14 @@ mod imp { #[cfg(windows)] mod imp { use libc; + use std::io; use std::mem; - use std::os; + use std::ffi::OsStr; + use std::os::windows::prelude::*; + use std::path::Path; use std::ptr; - static LOCKFILE_EXCLUSIVE_LOCK: libc::DWORD = 0x00000002; + const LOCKFILE_EXCLUSIVE_LOCK: libc::DWORD = 0x00000002; #[allow(non_snake_case)] extern "system" { @@ -188,7 +195,8 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let mut p_16: Vec = p.as_str().unwrap().utf16_units().collect(); + let os: &OsStr = p.as_ref(); + let mut p_16: Vec<_> = os.encode_wide().collect(); p_16.push(0); let handle = unsafe { libc::CreateFileW(p_16.as_ptr(), @@ -203,8 +211,7 @@ mod imp { ptr::null_mut()) }; if handle == libc::INVALID_HANDLE_VALUE { - panic!("create file error: [{}] {}", - os::errno(), os::last_os_error()); + panic!("create file error: {}", io::Error::last_os_error()); } let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() }; let ret = unsafe { @@ -212,10 +219,9 @@ mod imp { &mut overlapped) }; if ret == 0 { - let errno = os::errno(); + let err = io::Error::last_os_error(); unsafe { libc::CloseHandle(handle); } - panic!("could not lock `{}`: [{}] {}", p.display(), - errno, os::error_string(errno)); + panic!("could not lock `{}`: {}", p.display(), err); } Lock { handle: handle } } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 4f277cc868..cdeeacfb78 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -40,37 +40,13 @@ pub trait DocFolder : Sized { EnumItem(i) }, TraitItem(mut i) => { - fn vtrm(this: &mut T, trm: TraitMethod) - -> Option { - match trm { - RequiredMethod(it) => { - match this.fold_item(it) { - Some(x) => return Some(RequiredMethod(x)), - None => return None, - } - }, - ProvidedMethod(it) => { - match this.fold_item(it) { - Some(x) => return Some(ProvidedMethod(x)), - None => return None, - } - }, - TypeTraitItem(it) => { - match this.fold_item(it) { - Some(x) => return Some(TypeTraitItem(x)), - None => return None, - } - } - } - } let mut foo = Vec::new(); swap(&mut foo, &mut i.items); - i.items.extend(foo.into_iter().filter_map(|x| vtrm(self, x))); + i.items.extend(foo.into_iter().filter_map(|x| self.fold_item(x))); TraitItem(i) }, ImplItem(mut i) => { let mut foo = Vec::new(); swap(&mut foo, &mut i.items); - i.items.extend(foo.into_iter() - .filter_map(|x| self.fold_item(x))); + i.items.extend(foo.into_iter().filter_map(|x| self.fold_item(x))); ImplItem(i) }, VariantItem(i) => { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index ed7f051408..ed37b973f7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -25,23 +25,24 @@ use clean; use stability_summary::ModuleSummary; use html::item_type::ItemType; use html::render; +use html::escape::Escape; use html::render::{cache, CURRENT_LOCATION_KEY}; /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct VisSpace(pub Option); /// Similarly to VisSpace, this structure is used to render a function style with a /// space after it. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct UnsafetySpace(pub ast::Unsafety); /// Wrapper struct for properly emitting a method declaration. pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); /// Similar to VisSpace, but used for mutability -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); /// Similar to VisSpace, but used for mutability -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct RawMutableSpace(pub clean::Mutability); /// Wrapper struct for properly emitting the stability level. pub struct Stability<'a>(pub &'a Option); @@ -289,7 +290,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: ast::DefId, p: &clean::Path, if ast_util::is_local(did) || cache.inlined.contains(&did) { Some(repeat("../").take(loc.len()).collect::()) } else { - match cache.extern_locations[did.krate] { + match cache.extern_locations[&did.krate] { render::Remote(ref s) => Some(s.to_string()), render::Local => { Some(repeat("../").take(loc.len()).collect::()) @@ -403,11 +404,11 @@ fn primitive_link(f: &mut fmt::Formatter, needs_termination = true; } Some(&cnum) => { - let path = &m.paths[ast::DefId { + let path = &m.paths[&ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID, }]; - let loc = match m.extern_locations[cnum] { + let loc = match m.extern_locations[&cnum] { render::Remote(ref s) => Some(s.to_string()), render::Local => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); @@ -453,9 +454,6 @@ fn tybounds(w: &mut fmt::Formatter, impl fmt::Display for clean::Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - clean::TyParamBinder(id) => { - f.write_str(&cache().typarams[ast_util::local_def(id)]) - } clean::Generic(ref name) => { f.write_str(name) } @@ -488,7 +486,7 @@ impl fmt::Display for clean::Type { primitive_link(f, clean::Slice, &format!("[{}]", **t)) } clean::FixedVector(ref t, ref s) => { - primitive_link(f, clean::Slice, + primitive_link(f, clean::PrimitiveType::Array, &format!("[{}; {}]", **t, *s)) } clean::Bottom => f.write_str("!"), @@ -710,13 +708,14 @@ impl<'a> fmt::Display for Stability<'a> { let Stability(stab) = *self; match *stab { Some(ref stability) => { + let lvl = if stability.deprecated_since.is_empty() { + format!("{}", stability.level) + } else { + "Deprecated".to_string() + }; write!(f, "{lvl}", - lvl = if stability.deprecated_since.is_empty() { - format!("{}", stability.level) - } else { - "Deprecated".to_string() - }, - reason = stability.reason) + lvl = Escape(&*lvl), + reason = Escape(&*stability.reason)) } None => Ok(()) } @@ -728,14 +727,15 @@ impl<'a> fmt::Display for ConciseStability<'a> { let ConciseStability(stab) = *self; match *stab { Some(ref stability) => { + let lvl = if stability.deprecated_since.is_empty() { + format!("{}", stability.level) + } else { + "Deprecated".to_string() + }; write!(f, "", - lvl = if stability.deprecated_since.is_empty() { - format!("{}", stability.level) - } else { - "Deprecated".to_string() - }, + lvl = Escape(&*lvl), colon = if stability.reason.len() > 0 { ": " } else { "" }, - reason = stability.reason) + reason = Escape(&*stability.reason)) } None => { write!(f, "") diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 44c0acda66..d19ccabed4 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -15,7 +15,8 @@ use html::escape::Escape; -use std::old_io; +use std::io; +use std::io::prelude::*; use syntax::parse::lexer; use syntax::parse::token; use syntax::parse; @@ -46,7 +47,7 @@ pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { /// source. fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader, class: Option<&str>, id: Option<&str>, - out: &mut Writer) -> old_io::IoResult<()> { + out: &mut Write) -> io::Result<()> { use syntax::parse::lexer::Reader; try!(write!(out, "

 {
-                match &token::get_ident(ident)[] {
+                match &token::get_ident(ident)[..] {
                     "ref" | "mut" => "kw-2",
 
                     "self" => "self",
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index 356be2ffeb..d2385702a7 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -64,6 +64,7 @@ impl ItemType {
             clean::MacroItem(..)           => ItemType::Macro,
             clean::PrimitiveItem(..)       => ItemType::Primitive,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
+            clean::DefaultImplItem(..)     => ItemType::Impl,
         }
     }
 
@@ -110,4 +111,3 @@ impl fmt::Display for ItemType {
         self.to_static_str().fmt(f)
     }
 }
-
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index c537e37072..3acd17dedd 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 use std::fmt;
-use std::old_io;
+use std::io::prelude::*;
+use std::io;
 
 use externalfiles::ExternalHtml;
 
@@ -31,8 +32,8 @@ pub struct Page<'a> {
 }
 
 pub fn render(
-    dst: &mut old_io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
-    -> old_io::IoResult<()>
+    dst: &mut io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T)
+    -> io::Result<()>
 {
     write!(dst,
 r##"
@@ -159,7 +160,7 @@ r##"
     )
 }
 
-pub fn redirect(dst: &mut old_io::Writer, url: &str) -> old_io::IoResult<()> {
+pub fn redirect(dst: &mut io::Write, url: &str) -> io::Result<()> {
     // ",
+                    name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""),
+                    ty = shortty(it).to_static_str(),
+                    path = relpath));
+        if parentlen == 0 {
+            // there is no sidebar-items.js beyond the crate root path
+            // FIXME maybe dynamic crate loading can be merged here
+        } else {
+            try!(write!(fmt, "",
+                        path = relpath));
         }
 
-        try!(block(fmt, "mod", "Modules", it, cx));
-        try!(block(fmt, "struct", "Structs", it, cx));
-        try!(block(fmt, "enum", "Enums", it, cx));
-        try!(block(fmt, "trait", "Traits", it, cx));
-        try!(block(fmt, "fn", "Functions", it, cx));
-        try!(block(fmt, "macro", "Macros", it, cx));
         Ok(())
     }
 }
@@ -2304,6 +2379,52 @@ fn make_item_keywords(it: &clean::Item) -> String {
     format!("{}, {}", get_basic_keywords(), it.name.as_ref().unwrap())
 }
 
+fn get_index_search_type(item: &clean::Item,
+                         parent: Option) -> Option {
+    let decl = match item.inner {
+        clean::FunctionItem(ref f) => &f.decl,
+        clean::MethodItem(ref m) => &m.decl,
+        clean::TyMethodItem(ref m) => &m.decl,
+        _ => return None
+    };
+
+    let mut inputs = Vec::new();
+
+    // Consider `self` an argument as well.
+    if let Some(name) = parent {
+        inputs.push(Type { name: Some(name.into_ascii_lowercase()) });
+    }
+
+    inputs.extend(&mut decl.inputs.values.iter().map(|arg| {
+        get_index_type(&arg.type_)
+    }));
+
+    let output = match decl.output {
+        clean::FunctionRetTy::Return(ref return_type) => Some(get_index_type(return_type)),
+        _ => None
+    };
+
+    Some(IndexItemFunctionType { inputs: inputs, output: output })
+}
+
+fn get_index_type(clean_type: &clean::Type) -> Type {
+    Type { name: get_index_type_name(clean_type).map(|s| s.into_ascii_lowercase()) }
+}
+
+fn get_index_type_name(clean_type: &clean::Type) -> Option {
+    match *clean_type {
+        clean::ResolvedPath { ref path, .. } => {
+            let segments = &path.segments;
+            Some(segments[segments.len() - 1].name.clone())
+        },
+        clean::Generic(ref s) => Some(s.clone()),
+        clean::Primitive(ref p) => Some(format!("{:?}", p)),
+        clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_),
+        // FIXME: add all from clean::Type.
+        _ => None
+    }
+}
+
 pub fn cache() -> Arc {
     CACHE_KEY.with(|c| c.borrow().clone())
 }
diff --git a/src/librustdoc/html/static/Heuristica-LICENSE.txt b/src/librustdoc/html/static/Heuristica-LICENSE.txt
index 9693dc1db2..dd85e40e64 100644
--- a/src/librustdoc/html/static/Heuristica-LICENSE.txt
+++ b/src/librustdoc/html/static/Heuristica-LICENSE.txt
@@ -1,7 +1,7 @@
 Copyright 1989, 1991 Adobe Systems Incorporated. All rights reserved.
 Utopia is either a registered trademark or trademark of Adobe Systems
 Incorporated in the United States and/or other countries. Used under
-license. 
+license.
 
 Copyright 2006 Han The Thanh, Vntopia font family, http://vntex.sf.net
 
@@ -26,7 +26,7 @@ with others.
 
 The OFL allows the licensed fonts to be used, studied, modified and
 redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
+fonts, including any derivative works, can be bundled, embedded,
 redistributed and/or sold with any software provided that any reserved
 names are not used by derivative works. The fonts and derivatives,
 however, cannot be released under any other type of license. The
diff --git a/src/librustdoc/html/static/SourceCodePro-LICENSE.txt b/src/librustdoc/html/static/SourceCodePro-LICENSE.txt
index 1177330426..07542572e3 100644
--- a/src/librustdoc/html/static/SourceCodePro-LICENSE.txt
+++ b/src/librustdoc/html/static/SourceCodePro-LICENSE.txt
@@ -18,7 +18,7 @@ with others.
 
 The OFL allows the licensed fonts to be used, studied, modified and
 redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
+fonts, including any derivative works, can be bundled, embedded,
 redistributed and/or sold with any software provided that any reserved
 names are not used by derivative works. The fonts and derivatives,
 however, cannot be released under any other type of license. The
diff --git a/src/librustdoc/html/static/SourceSerifPro-LICENSE.txt b/src/librustdoc/html/static/SourceSerifPro-LICENSE.txt
index 14b5481375..b77d653ad4 100644
--- a/src/librustdoc/html/static/SourceSerifPro-LICENSE.txt
+++ b/src/librustdoc/html/static/SourceSerifPro-LICENSE.txt
@@ -18,7 +18,7 @@ with others.
 
 The OFL allows the licensed fonts to be used, studied, modified and
 redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
+fonts, including any derivative works, can be bundled, embedded,
 redistributed and/or sold with any software provided that any reserved
 names are not used by derivative works. The fonts and derivatives,
 however, cannot be released under any other type of license. The
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 2f0755ecb8..2af20ce59d 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -83,7 +83,7 @@ h2 {
 h3 {
     font-size: 1.3em;
 }
-h1, h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
+h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
     color: black;
     font-weight: 500;
     margin: 20px 0 15px 0;
@@ -93,7 +93,7 @@ h1.fqn {
     border-bottom: 1px dashed #D5D5D5;
     margin-top: 0;
 }
-h2, h3:not(.impl):not(.method):not(.type), h4:not(.method):not(.type) {
+h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
     border-bottom: 1px solid #DDDDDD;
 }
 h3.impl, h3.method, h4.method, h3.type, h4.type {
@@ -374,8 +374,14 @@ a {
     color: #000;
     background: transparent;
 }
-.docblock a { color: #4e8bca; }
-.docblock a:hover { text-decoration: underline; }
+
+.docblock a {
+    color: #4e8bca;
+}
+
+.docblock a:hover {
+    text-decoration: underline;
+}
 
 .content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; }
 .content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
@@ -487,6 +493,10 @@ h1 .stability {
 .stability.Locked { border-color: #0084B6; color: #00668c; }
 .stability.Unmarked { border-color: #BBBBBB; }
 
+td.summary-column {
+    width: 100%;
+}
+
 .summary {
     padding-right: 0px;
 }
@@ -529,10 +539,19 @@ pre.rust { position: relative; }
     margin: 0 0 -5px;
     padding: 0;
 }
+
 .section-header:hover a:after {
     content: '\2002\00a7\2002';
 }
 
+.section-header:hover a {
+    text-decoration: none;
+}
+
+.section-header a {
+    color: inherit;
+}
+
 .collapse-toggle {
     font-weight: 300;
     position: absolute;
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index aac3985f0c..ca6d944195 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -15,6 +15,27 @@
     "use strict";
     var resizeTimeout, interval;
 
+    // This mapping table should match the discriminants of
+    // `rustdoc::html::item_type::ItemType` type in Rust.
+    var itemTypes = ["mod",
+                     "externcrate",
+                     "import",
+                     "struct",
+                     "enum",
+                     "fn",
+                     "type",
+                     "static",
+                     "trait",
+                     "impl",
+                     "tymethod",
+                     "method",
+                     "structfield",
+                     "variant",
+                     "macro",
+                     "primitive",
+                     "associatedtype",
+                     "constant"];
+
     $('.js-only').removeClass('js-only');
 
     function getQueryStringParams() {
@@ -33,23 +54,6 @@
         return window.history && typeof window.history.pushState === "function";
     }
 
-    function resizeShortBlocks() {
-        if (resizeTimeout) {
-            clearTimeout(resizeTimeout);
-        }
-        resizeTimeout = setTimeout(function() {
-            var contentWidth = $('.content').width();
-            $('.docblock.short').width(function() {
-                return contentWidth - 40 - $(this).prev().width();
-            }).addClass('nowrap');
-            $('.summary-column').width(function() {
-                return contentWidth - 40 - $(this).prev().width();
-            })
-        }, 150);
-    }
-    resizeShortBlocks();
-    $(window).on('resize', resizeShortBlocks);
-
     function highlightSourceLines(ev) {
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
@@ -205,6 +209,33 @@
                         break;
                     }
                 }
+            // searching by type
+            } else if (val.search("->") > -1) {
+                var trimmer = function (s) { return s.trim(); };
+                var parts = val.split("->").map(trimmer);
+                var input = parts[0];
+                // sort inputs so that order does not matter
+                var inputs = input.split(",").map(trimmer).sort();
+                var output = parts[1];
+
+                for (var i = 0; i < nSearchWords; ++i) {
+                    var type = searchIndex[i].type;
+                    if (!type) {
+                        continue;
+                    }
+
+                    // sort index inputs so that order does not matter
+                    var typeInputs = type.inputs.map(function (input) {
+                        return input.name;
+                    }).sort();
+
+                    // allow searching for void (no output) functions as well
+                    var typeOutput = type.output ? type.output.name : "";
+                    if (inputs.toString() === typeInputs.toString() &&
+                        output == typeOutput) {
+                        results.push({id: i, index: -1, dontValidate: true});
+                    }
+                }
             } else {
                 // gather matching search results up to a certain maximum
                 val = val.replace(/\_/g, "");
@@ -325,6 +356,11 @@
                     path = result.item.path.toLowerCase(),
                     parent = result.item.parent;
 
+                // this validation does not make sense when searching by types
+                if (result.dontValidate) {
+                    continue;
+                }
+
                 var valid = validateResult(name, path, split, parent);
                 if (!valid) {
                     result.id = -1;
@@ -552,27 +588,6 @@
             showResults(results);
         }
 
-        // This mapping table should match the discriminants of
-        // `rustdoc::html::item_type::ItemType` type in Rust.
-        var itemTypes = ["mod",
-                         "externcrate",
-                         "import",
-                         "struct",
-                         "enum",
-                         "fn",
-                         "type",
-                         "static",
-                         "trait",
-                         "impl",
-                         "tymethod",
-                         "method",
-                         "structfield",
-                         "variant",
-                         "macro",
-                         "primitive",
-                         "associatedtype",
-                         "constant"];
-
         function itemTypeFromName(typename) {
             for (var i = 0; i < itemTypes.length; ++i) {
                 if (itemTypes[i] === typename) return i;
@@ -590,7 +605,8 @@
                 //              (String) name,
                 //              (String) full path or empty string for previous path,
                 //              (String) description,
-                //              (optional Number) the parent path index to `paths`]
+                //              (Number | null) the parent path index to `paths`]
+                //              (Object | null) the type of the function (if any)
                 var items = rawSearchIndex[crate].items;
                 // an array of [(Number) item type,
                 //              (String) name]
@@ -615,7 +631,7 @@
                     var rawRow = items[i];
                     var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
                                path: rawRow[2] || lastPath, desc: rawRow[3],
-                               parent: paths[rawRow[4]]};
+                               parent: paths[rawRow[4]], type: rawRow[5]};
                     searchIndex.push(row);
                     if (typeof row.name === "string") {
                         var word = row.name.toLowerCase();
@@ -708,6 +724,50 @@
 
     window.initSearch = initSearch;
 
+    // delayed sidebar rendering.
+    function initSidebarItems(items) {
+        var sidebar = $('.sidebar');
+        var current = window.sidebarCurrent;
+
+        function block(shortty, longty) {
+            var filtered = items[shortty];
+            if (!filtered) return;
+
+            var div = $('
').attr('class', 'block ' + shortty); + div.append($('

').text(longty)); + + for (var i = 0; i < filtered.length; ++i) { + var item = filtered[i]; + var name = item[0]; + var desc = item[1]; // can be null + + var klass = shortty; + if (name === current.name && shortty == current.ty) { + klass += ' current'; + } + var path; + if (shortty === 'mod') { + path = name + '/index.html'; + } else { + path = shortty + '.' + name + '.html'; + } + div.append($('', {'href': current.relpath + path, + 'title': desc, + 'class': klass}).text(name)); + } + sidebar.append(div); + } + + block("mod", "Modules"); + block("struct", "Structs"); + block("enum", "Enums"); + block("trait", "Traits"); + block("fn", "Functions"); + block("macro", "Macros"); + } + + window.initSidebarItems = initSidebarItems; + window.register_implementors = function(imp) { var list = $('#implementors-list'); var libs = Object.getOwnPropertyNames(imp); diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js index 687f764f02..06b3c4e42d 100644 --- a/src/librustdoc/html/static/playpen.js +++ b/src/librustdoc/html/static/playpen.js @@ -15,7 +15,7 @@ if (window.playgroundUrl) { $('pre.rust').hover(function() { var a = $('').text('⇱').attr('class', 'test-arrow'); - var code = $(this).siblings(".rusttest").text(); + var code = $(this).prev(".rusttest").text(); a.attr('href', window.playgroundUrl + '?code=' + encodeURIComponent(code)); a.attr('target', '_blank'); @@ -25,4 +25,3 @@ }); } }()); - diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index ecef4c9bf7..78feb6c77c 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -33,7 +33,7 @@ pub struct Toc { } impl Toc { - fn count_entries_with_level(&self, level: u32) -> uint { + fn count_entries_with_level(&self, level: u32) -> usize { self.entries.iter().filter(|e| e.level == level).count() } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f9e0948d7b..d1dcfc2600 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,32 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "rustdoc"] #![unstable(feature = "rustdoc")] #![staged_api] #![crate_type = "dylib"] #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "http://www.rust-lang.org/favicon.ico", - html_root_url = "http://doc.rust-lang.org/nightly/", - html_playground_url = "http://play.rust-lang.org/")] + html_favicon_url = "http://www.rust-lang.org/favicon.ico", + html_root_url = "http://doc.rust-lang.org/nightly/", + html_playground_url = "http://play.rust-lang.org/")] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(collections)] -#![feature(core)] -#![feature(env)] -#![feature(int_uint)] -#![feature(old_io)] +#![feature(exit_status)] +#![feature(set_stdio)] #![feature(libc)] -#![feature(os)] -#![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] #![feature(test)] #![feature(unicode)] #![feature(str_words)] +#![feature(file_path)] +#![feature(path_ext)] +#![feature(path_relative_from)] +#![feature(slice_patterns)] extern crate arena; extern crate getopts; @@ -42,20 +44,25 @@ extern crate rustc; extern crate rustc_trans; extern crate rustc_driver; extern crate rustc_resolve; +extern crate rustc_lint; +extern crate rustc_back; extern crate serialize; extern crate syntax; -extern crate "test" as testing; +extern crate test as testing; +extern crate unicode; #[macro_use] extern crate log; -extern crate "serialize" as rustc_serialize; // used by deriving +extern crate serialize as rustc_serialize; // used by deriving use std::cell::RefCell; use std::collections::HashMap; use std::env; -use std::old_io::File; -use std::old_io; +use std::fs::File; +use std::io::{self, Read, Write}; +use std::path::PathBuf; use std::rc::Rc; use std::sync::mpsc::channel; + use externalfiles::ExternalHtml; use serialize::Decodable; use serialize::json::{self, Json}; @@ -93,7 +100,7 @@ type Pass = (&'static str, // name fn(clean::Crate) -> plugins::PluginResult, // fn &'static str); // description -static PASSES: &'static [Pass] = &[ +const PASSES: &'static [Pass] = &[ ("strip-hidden", passes::strip_hidden, "strips all doc(hidden) items from the output"), ("unindent-comments", passes::unindent_comments, @@ -104,7 +111,7 @@ static PASSES: &'static [Pass] = &[ "strips all private items from a crate which cannot be seen externally"), ]; -static DEFAULT_PASSES: &'static [&'static str] = &[ +const DEFAULT_PASSES: &'static [&'static str] = &[ "strip-hidden", "strip-private", "collapse-docs", @@ -183,7 +190,7 @@ pub fn usage(argv0: &str) { &opts())); } -pub fn main_args(args: &[String]) -> int { +pub fn main_args(args: &[String]) -> isize { let matches = match getopts::getopts(args.tail(), &opts()) { Ok(m) => m, Err(err) => { @@ -241,7 +248,7 @@ pub fn main_args(args: &[String]) -> int { let should_test = matches.opt_present("test"); let markdown_input = input.ends_with(".md") || input.ends_with(".markdown"); - let output = matches.opt_str("o").map(|s| Path::new(s)); + let output = matches.opt_str("o").map(|s| PathBuf::from(&s)); let cfgs = matches.opt_strs("cfg"); let external_html = match ExternalHtml::load( @@ -260,7 +267,8 @@ pub fn main_args(args: &[String]) -> int { (true, false) => { return test::run(input, cfgs, libs, externs, test_args, crate_name) } - (false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")), + (false, true) => return markdown::render(input, + output.unwrap_or(PathBuf::from("doc")), &matches, &external_html, !matches.opt_present("markdown-no-toc")), (false, false) => {} @@ -277,7 +285,8 @@ pub fn main_args(args: &[String]) -> int { info!("going to format"); match matches.opt_str("w").as_ref().map(|s| &**s) { Some("html") | None => { - match html::render::run(krate, &external_html, output.unwrap_or(Path::new("doc")), + match html::render::run(krate, &external_html, + output.unwrap_or(PathBuf::from("doc")), passes.into_iter().collect()) { Ok(()) => {} Err(e) => panic!("failed to generate documentation: {}", e), @@ -285,7 +294,7 @@ pub fn main_args(args: &[String]) -> int { } Some("json") => { match json_output(krate, json_plugins, - output.unwrap_or(Path::new("doc.json"))) { + output.unwrap_or(PathBuf::from("doc.json"))) { Ok(()) => {} Err(e) => panic!("failed to write json: {}", e), } @@ -324,7 +333,7 @@ fn acquire_input(input: &str, fn parse_externs(matches: &getopts::Matches) -> Result { let mut externs = HashMap::new(); for arg in &matches.opt_strs("extern") { - let mut parts = arg.splitn(1, '='); + let mut parts = arg.splitn(2, '='); let name = match parts.next() { Some(s) => s, None => { @@ -338,9 +347,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result { } }; 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()); + externs.entry(name).or_insert(vec![]).push(location.to_string()); } Ok(externs) } @@ -350,6 +357,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result { /// generated from the cleaned AST of the crate. /// /// This form of input will run all of the plug/cleaning passes +#[allow(deprecated)] // for old Path in plugin manager fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matches) -> Output { let mut default_passes = !matches.opt_present("no-defaults"); let mut passes = matches.opt_strs("passes"); @@ -363,15 +371,15 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche let cfgs = matches.opt_strs("cfg"); let triple = matches.opt_str("target"); - let cr = Path::new(cratefile); + let cr = PathBuf::from(cratefile); info!("starting to run rustc"); let (tx, rx) = channel(); std::thread::spawn(move || { use rustc::session::config::Input; - let cr = cr; - tx.send(core::run_core(paths, cfgs, externs, Input::File(cr), triple)).unwrap(); + tx.send(core::run_core(paths, cfgs, externs, Input::File(cr), + triple)).unwrap(); }).join().map_err(|_| "rustc failed").unwrap(); let (mut krate, analysis) = rx.recv().unwrap(); info!("finished with rustc"); @@ -422,7 +430,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche // Load all plugins/passes into a PluginManager let path = matches.opt_str("plugin-path") .unwrap_or("/tmp/rustdoc/plugins".to_string()); - let mut pm = plugins::PluginManager::new(Path::new(path)); + let mut pm = plugins::PluginManager::new(PathBuf::from(path)); for pass in &passes { let plugin = match PASSES.iter() .position(|&(p, _, _)| { @@ -450,13 +458,12 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche /// This input format purely deserializes the json output file. No passes are /// run over the deserialized output. fn json_input(input: &str) -> Result { - let mut input = match File::open(&Path::new(input)) { - Ok(f) => f, - Err(e) => { - return Err(format!("couldn't open {}: {}", input, e)) - } + let mut bytes = Vec::new(); + match File::open(input).and_then(|mut f| f.read_to_end(&mut bytes)) { + Ok(_) => {} + Err(e) => return Err(format!("couldn't open {}: {}", input, e)), }; - match json::from_reader(&mut input) { + match json::from_reader(&mut &bytes[..]) { Err(s) => Err(format!("{:?}", s)), Ok(Json::Object(obj)) => { let mut obj = obj; @@ -494,7 +501,7 @@ fn json_input(input: &str) -> Result { /// Outputs the crate/plugin json as a giant json blob at the specified /// destination. fn json_output(krate: clean::Crate, res: Vec , - dst: Path) -> old_io::IoResult<()> { + dst: PathBuf) -> io::Result<()> { // { // "schema": version, // "crate": { parsed crate ... }, diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index d64d9becc0..a84da60b01 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io; +use std::fs::File; +use std::io; +use std::io::prelude::*; +use std::path::{PathBuf, Path}; use core; use getopts; @@ -40,10 +43,10 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { /// Render `input` (e.g. "foo.md") into an HTML file in `output` /// (e.g. output = "bar" => "bar/foo.html"). -pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, - external_html: &ExternalHtml, include_toc: bool) -> int { +pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, + external_html: &ExternalHtml, include_toc: bool) -> isize { let input_p = Path::new(input); - output.push(input_p.filestem().unwrap()); + output.push(input_p.file_stem().unwrap()); output.set_extension("html"); let mut css = String::new(); @@ -59,9 +62,9 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, } let playground = playground.unwrap_or("".to_string()); - let mut out = match old_io::File::create(&output) { + let mut out = match File::create(&output) { Err(e) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error opening `{}` for writing: {}", output.display(), e); return 4; @@ -71,7 +74,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, let (metadata, text) = extract_leading_metadata(&input_str); if metadata.len() == 0 { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "invalid markdown file: expecting initial line with `% ...TITLE...`"); return 5; } @@ -126,7 +129,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, match err { Err(e) => { - let _ = writeln!(&mut old_io::stderr(), + let _ = writeln!(&mut io::stderr(), "error writing to `{}`: {}", output.display(), e); 6 @@ -137,10 +140,10 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, /// Run any tests/code examples in the markdown file `input`. pub fn test(input: &str, libs: SearchPaths, externs: core::Externs, - mut test_args: Vec) -> int { + mut test_args: Vec) -> isize { let input_str = load_or_return!(input, 1, 2); - let mut collector = Collector::new(input.to_string(), libs, externs, true); + let mut collector = Collector::new(input.to_string(), libs, externs, true, false); find_testable_code(&input_str, &mut collector); test_args.insert(0, "rustdoctest".to_string()); testing::test_main(&test_args, collector.tests); diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 722f14fa6d..953b442bb3 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -176,7 +176,7 @@ impl<'a> fold::DocFolder for Stripper<'a> { return None; } } - clean::ImplItem(..) => {} + clean::DefaultImplItem(..) | clean::ImplItem(..) => {} // tymethods/macros have no control over privacy clean::MacroItem(..) | clean::TyMethodItem(..) => {} diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs index b65b2841aa..d4d214f449 100644 --- a/src/librustdoc/plugins.rs +++ b/src/librustdoc/plugins.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] // old path, used for compatibility with dynamic lib + use clean; use std::dynamic_lib as dl; use serialize::json; use std::mem; use std::string::String; +use std::path::PathBuf; pub type PluginJson = Option<(String, json::Json)>; pub type PluginResult = (clean::Crate, PluginJson); @@ -24,12 +27,12 @@ pub struct PluginManager { dylibs: Vec , callbacks: Vec , /// The directory plugins will be loaded from - pub prefix: Path, + pub prefix: PathBuf, } impl PluginManager { /// Create a new plugin manager - pub fn new(prefix: Path) -> PluginManager { + pub fn new(prefix: PathBuf) -> PluginManager { PluginManager { dylibs: Vec::new(), callbacks: Vec::new(), diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs index 47918ba78a..3e4f6896ee 100644 --- a/src/librustdoc/stability_summary.rs +++ b/src/librustdoc/stability_summary.rs @@ -20,14 +20,14 @@ use syntax::attr::{Unstable, Stable}; use syntax::ast::Public; use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum}; -use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod}; -use clean::{TypeTraitItem, ExternCrateItem, ImportItem, PrimitiveItem, Stability}; +use clean::{ImplItem, Impl, Trait, TraitItem}; +use clean::{ExternCrateItem, ImportItem, PrimitiveItem, Stability}; use html::render::cache; #[derive(RustcEncodable, RustcDecodable, PartialEq, Eq)] /// The counts for each stability level. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Counts { pub deprecated: u64, pub unstable: u64, @@ -86,7 +86,7 @@ impl Ord for ModuleSummary { } } -// is the item considered publically visible? +// is the item considered publicly visible? fn visible(item: &Item) -> bool { match item.inner { ImplItem(_) => true, @@ -140,11 +140,11 @@ fn summarize_item(item: &Item) -> (Counts, Option) { // considered to have no children. match item.inner { // Require explicit `pub` to be visible - ImplItem(Impl { items: ref subitems, trait_: None, .. }) => { - let subcounts = subitems.iter().filter(|i| visible(*i)) - .map(summarize_item) - .map(|s| s.0) - .fold(Counts::zero(), |acc, x| acc + x); + ImplItem(Impl { ref items, trait_: None, .. }) => { + let subcounts = items.iter().filter(|i| visible(*i)) + .map(summarize_item) + .map(|s| s.0) + .fold(Counts::zero(), |acc, x| acc + x); (subcounts, None) } // `pub` automatically @@ -154,22 +154,10 @@ fn summarize_item(item: &Item) -> (Counts, Option) { .fold(Counts::zero(), |acc, x| acc + x); (item_counts + subcounts, None) } - TraitItem(Trait { - items: ref trait_items, - .. - }) => { - fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item { - match *trait_item { - ProvidedMethod(ref item) | - RequiredMethod(ref item) | - TypeTraitItem(ref item) => item - } - } - let subcounts = trait_items.iter() - .map(extract_item) - .map(summarize_item) - .map(|s| s.0) - .fold(Counts::zero(), |acc, x| acc + x); + TraitItem(Trait { ref items, .. }) => { + let subcounts = items.iter().map(summarize_item) + .map(|s| s.0) + .fold(Counts::zero(), |acc, x| acc + x); (item_counts + subcounts, None) } ModuleItem(Module { ref items, .. }) => { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index bf14b86ebd..f5bee6240d 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -9,20 +9,23 @@ // except according to those terms. use std::cell::RefCell; -use std::sync::mpsc::channel; +use std::collections::{HashSet, HashMap}; use std::dynamic_lib::DynamicLibrary; -use std::old_io::{Command, TempDir}; -use std::old_io; use std::env; +use std::ffi::OsString; +use std::io::prelude::*; +use std::io; +use std::path::PathBuf; +use std::process::Command; use std::str; -use std::thread; -use std::thunk::Thunk; +use std::sync::{Arc, Mutex}; -use std::collections::{HashSet, HashMap}; use testing; +use rustc_lint; use rustc::session::{self, config}; use rustc::session::config::get_unstable_features_setting; use rustc::session::search_paths::{SearchPaths, PathKind}; +use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; use syntax::codemap::CodeMap; use syntax::diagnostic; @@ -41,12 +44,13 @@ pub fn run(input: &str, externs: core::Externs, mut test_args: Vec, crate_name: Option) - -> int { - let input_path = Path::new(input); + -> isize { + let input_path = PathBuf::from(input); let input = config::Input::File(input_path.clone()); let sessopts = config::Options { - maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()), + maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap() + .parent().unwrap().to_path_buf()), search_paths: libs.clone(), crate_types: vec!(config::CrateTypeDylib), externs: externs.clone(), @@ -62,6 +66,7 @@ pub fn run(input: &str, let sess = session::build_session_(sessopts, Some(input_path.clone()), span_diagnostic_handler); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess); cfg.extend(config::parse_cfgspecs(cfgs).into_iter()); @@ -70,6 +75,8 @@ pub fn run(input: &str, "rustdoc-test", None) .expect("phase_2_configure_and_expand aborted in rustdoc!"); + let inject_crate = should_inject_crate(&krate); + let ctx = core::DocContext { krate: &krate, maybe_typed: core::NotTyped(sess), @@ -94,7 +101,8 @@ pub fn run(input: &str, let mut collector = Collector::new(krate.name.to_string(), libs, externs, - false); + false, + inject_crate); collector.fold_crate(krate); test_args.insert(0, "rustdoctest".to_string()); @@ -104,16 +112,47 @@ pub fn run(input: &str, 0 } +// Look for #![doc(test(no_crate_inject))], used by crates in the std facade +fn should_inject_crate(krate: &::syntax::ast::Crate) -> bool { + use syntax::attr::AttrMetaMethods; + + let mut inject_crate = true; + + for attr in &krate.attrs { + if attr.check_name("doc") { + for list in attr.meta_item_list().into_iter() { + for attr in list { + if attr.check_name("test") { + for list in attr.meta_item_list().into_iter() { + for attr in list { + if attr.check_name("no_crate_inject") { + inject_crate = false; + } + } + } + } + } + } + } + } + + return inject_crate; +} + +#[allow(deprecated)] fn runtest(test: &str, cratename: &str, libs: SearchPaths, externs: core::Externs, - should_fail: bool, no_run: bool, as_test_harness: bool) { + should_panic: bool, no_run: bool, as_test_harness: bool, + inject_crate: bool) { // the test harness wants its own `main` & top level functions, so // never wrap the test in `fn main() { ... }` - let test = maketest(test, Some(cratename), true, as_test_harness); + let test = maketest(test, Some(cratename), true, as_test_harness, + inject_crate); let input = config::Input::Str(test.to_string()); let sessopts = config::Options { - maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()), + maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap() + .parent().unwrap().to_path_buf()), search_paths: libs, crate_types: vec!(config::CrateTypeExecutable), output_types: vec!(config::OutputTypeExe), @@ -131,30 +170,29 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, // an explicit handle into rustc to collect output messages, but we also // want to catch the error message that rustc prints when it fails. // - // We take our task-local stderr (likely set by the test runner), and move - // it into another task. This helper task then acts as a sink for both the - // stderr of this task and stderr of rustc itself, copying all the info onto - // the stderr channel we originally started with. + // We take our task-local stderr (likely set by the test runner) and replace + // it with a sink that is also passed to rustc itself. When this function + // returns the output of the sink is copied onto the output of our own task. // // The basic idea is to not use a default_handler() for rustc, and then also // not print things by default to the actual stderr. - let (tx, rx) = channel(); - let w1 = old_io::ChanWriter::new(tx); - let w2 = w1.clone(); - let old = old_io::stdio::set_stderr(box w1); - thread::spawn(move || { - let mut p = old_io::ChanReader::new(rx); - let mut err = match old { - Some(old) => { - // Chop off the `Send` bound. - let old: Box = old; - old - } - None => box old_io::stderr() as Box, - }; - old_io::util::copy(&mut p, &mut err).unwrap(); - }); - let emitter = diagnostic::EmitterWriter::new(box w2, None); + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + struct Bomb(Arc>>, Box); + impl Drop for Bomb { + fn drop(&mut self) { + let _ = self.1.write_all(&self.0.lock().unwrap()); + } + } + let data = Arc::new(Mutex::new(Vec::new())); + let emitter = diagnostic::EmitterWriter::new(box Sink(data.clone()), None); + let old = io::set_panic(box Sink(data.clone())); + let _bomb = Bomb(data, old.unwrap_or(box io::stdout())); // Compile the code let codemap = CodeMap::new(); @@ -165,9 +203,10 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, let sess = session::build_session_(sessopts, None, span_diagnostic_handler); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"); - let out = Some(outdir.path().clone()); + let out = Some(outdir.path().to_path_buf()); let cfg = config::build_configuration(&sess); let libdir = sess.target_filesearch(PathKind::All).get_lib_path(); let mut control = driver::CompileController::basic(); @@ -184,32 +223,43 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths, // environment to ensure that the target loads the right libraries at // runtime. It would be a sad day if the *host* libraries were loaded as a // mistake. - let mut cmd = Command::new(outdir.path().join("rust-out")); + let mut cmd = Command::new(&outdir.path().join("rust_out")); + let var = DynamicLibrary::envvar(); let newpath = { - let mut path = DynamicLibrary::search_path(); + let path = env::var_os(var).unwrap_or(OsString::new()); + let mut path = env::split_paths(&path).collect::>(); path.insert(0, libdir.clone()); - DynamicLibrary::create_path(&path) + env::join_paths(path.iter()).unwrap() }; - cmd.env(DynamicLibrary::envvar(), newpath); + cmd.env(var, &newpath); match cmd.output() { Err(e) => panic!("couldn't run the test: {}{}", e, - if e.kind == old_io::PermissionDenied { + if e.kind() == io::ErrorKind::PermissionDenied { " - maybe your tempdir is mounted with noexec?" } else { "" }), Ok(out) => { - if should_fail && out.status.success() { + if should_panic && out.status.success() { panic!("test executable succeeded when it should have failed"); - } else if !should_fail && !out.status.success() { - panic!("test executable failed:\n{:?}", - str::from_utf8(&out.error)); + } else if !should_panic && !out.status.success() { + panic!("test executable failed:\n{}\n{}", + str::from_utf8(&out.stdout).unwrap_or(""), + str::from_utf8(&out.stderr).unwrap_or("")); } } } } -pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: bool) -> String { +pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, + dont_insert_main: bool, inject_crate: bool) -> String { + let (crate_attrs, everything_else) = partition_source(s); + let mut prog = String::new(); + + // First push any outer attributes from the example, assuming they + // are intended to be crate attributes. + prog.push_str(&crate_attrs); + if lints { prog.push_str(r" #![allow(unused_variables, unused_assignments, unused_mut, unused_attributes, dead_code)] @@ -218,7 +268,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: // Don't inject `extern crate std` because it's already injected by the // compiler. - if !s.contains("extern crate") && cratename != Some("std") { + if !s.contains("extern crate") && inject_crate { match cratename { Some(cratename) => { if s.contains(cratename) { @@ -230,30 +280,57 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main: } } if dont_insert_main || s.contains("fn main") { - prog.push_str(s); + prog.push_str(&everything_else); } else { prog.push_str("fn main() {\n "); - prog.push_str(&s.replace("\n", "\n ")); + prog.push_str(&everything_else.replace("\n", "\n ")); prog.push_str("\n}"); } + info!("final test program: {}", prog); + return prog } +fn partition_source(s: &str) -> (String, String) { + use unicode::str::UnicodeStr; + + let mut after_header = false; + let mut before = String::new(); + let mut after = String::new(); + + for line in s.lines() { + let trimline = line.trim(); + let header = trimline.is_whitespace() || + trimline.starts_with("#![feature"); + if !header || after_header { + after_header = true; + after.push_str(line); + after.push_str("\n"); + } else { + before.push_str(line); + before.push_str("\n"); + } + } + + return (before, after); +} + pub struct Collector { pub tests: Vec, names: Vec, libs: SearchPaths, externs: core::Externs, - cnt: uint, + cnt: usize, use_headers: bool, current_header: Option, cratename: String, + inject_crate: bool } impl Collector { pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs, - use_headers: bool) -> Collector { + use_headers: bool, inject_crate: bool) -> Collector { Collector { tests: Vec::new(), names: Vec::new(), @@ -263,11 +340,13 @@ impl Collector { use_headers: use_headers, current_header: None, cratename: cratename, + inject_crate: inject_crate } } pub fn add_test(&mut self, test: String, - should_fail: bool, no_run: bool, should_ignore: bool, as_test_harness: bool) { + should_panic: bool, no_run: bool, should_ignore: bool, + as_test_harness: bool) { let name = if self.use_headers { let s = self.current_header.as_ref().map(|s| &**s).unwrap_or(""); format!("{}_{}", s, self.cnt) @@ -278,21 +357,23 @@ impl Collector { let libs = self.libs.clone(); let externs = self.externs.clone(); let cratename = self.cratename.to_string(); + let inject_crate = self.inject_crate; debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { name: testing::DynTestName(name), ignore: should_ignore, - should_fail: testing::ShouldFail::No, // compiler failures are test failures + should_panic: testing::ShouldPanic::No, // compiler failures are test failures }, - testfn: testing::DynTestFn(Thunk::new(move|| { + testfn: testing::DynTestFn(Box::new(move|| { runtest(&test, &cratename, libs, externs, - should_fail, + should_panic, no_run, - as_test_harness); + as_test_harness, + inject_crate); })) }); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c52b0bab1f..3f813b30ec 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Some(tcx) => tcx, None => return false }; - let def = (*tcx.def_map.borrow())[id].def_id(); + let def = tcx.def_map.borrow()[&id].def_id(); if !ast_util::is_local(def) { return false } let analysis = match self.analysis { Some(analysis) => analysis, None => return false @@ -237,7 +237,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ast::ItemExternCrate(ref p) => { let path = match *p { None => None, - Some((ref x, _)) => Some(x.to_string()), + Some(x) => Some(x.to_string()), }; om.extern_crates.push(ExternCrate { name: name, @@ -253,7 +253,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let please_inline = item.attrs.iter().any(|item| { match item.meta_item_list() { Some(list) => { - list.iter().any(|i| &i.name()[] == "inline") + list.iter().any(|i| &i.name()[..] == "inline") } None => false, } @@ -358,6 +358,16 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.impls.push(i); }, + ast::ItemDefaultImpl(unsafety, ref trait_ref) => { + let i = DefaultImpl { + unsafety: unsafety, + trait_: trait_ref.clone(), + id: item.id, + attrs: item.attrs.clone(), + whence: item.span, + }; + om.def_traits.push(i); + } ast::ItemForeignMod(ref fm) => { om.foreigns.push(fm.clone()); } diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 10cf02f85e..e7430f698e 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -13,7 +13,6 @@ use std::usize; use std::default::Default; use std::hash::Hash; -#[cfg(stage0)] use std::hash::Hasher; use std::collections::hash_state::HashState; use {Decodable, Encodable, Decoder, Encoder}; @@ -158,26 +157,6 @@ impl< } } -#[cfg(stage0)] -impl Encodable for HashMap - where K: Encodable + Hash< ::Hasher> + Eq, - V: Encodable, - S: HashState, - ::Hasher: Hasher -{ - fn encode(&self, e: &mut E) -> Result<(), E::Error> { - e.emit_map(self.len(), |e| { - let mut i = 0; - for (key, val) in self { - 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(()) - }) - } -} -#[cfg(not(stage0))] impl Encodable for HashMap where K: Encodable + Hash + Eq, V: Encodable, @@ -196,27 +175,6 @@ impl Encodable for HashMap } } -#[cfg(stage0)] -impl Decodable for HashMap - where K: Decodable + Hash< ::Hasher> + Eq, - V: Decodable, - S: HashState + Default, - ::Hasher: Hasher -{ - fn decode(d: &mut D) -> Result, D::Error> { - d.read_map(|d, len| { - let state = Default::default(); - let mut map = HashMap::with_capacity_and_hash_state(len, state); - for i in 0..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) - }) - } -} -#[cfg(not(stage0))] impl Decodable for HashMap where K: Decodable + Hash + Eq, V: Decodable, @@ -236,24 +194,6 @@ impl Decodable for HashMap } } -#[cfg(stage0)] -impl Encodable for HashSet - where T: Encodable + Hash< ::Hasher> + Eq, - S: HashState, - ::Hasher: Hasher -{ - fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_seq(self.len(), |s| { - let mut i = 0; - for e in self { - try!(s.emit_seq_elt(i, |s| e.encode(s))); - i += 1; - } - Ok(()) - }) - } -} -#[cfg(not(stage0))] impl Encodable for HashSet where T: Encodable + Hash + Eq, S: HashState, @@ -270,24 +210,6 @@ impl Encodable for HashSet } } -#[cfg(stage0)] -impl Decodable for HashSet - where T: Decodable + Hash< ::Hasher> + Eq, - S: HashState + Default, - ::Hasher: Hasher -{ - fn decode(d: &mut D) -> Result, D::Error> { - d.read_seq(|d, len| { - let state = Default::default(); - let mut set = HashSet::with_capacity_and_hash_state(len, state); - for i in 0..len { - set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); - } - Ok(set) - }) - } -} -#[cfg(not(stage0))] impl Decodable for HashSet where T: Decodable + Hash + Eq, S: HashState + Default, diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index a3cc2d6b93..0676edf816 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -24,14 +24,15 @@ pub trait ToHex { fn to_hex(&self) -> String; } -static CHARS: &'static[u8] = b"0123456789abcdef"; +const CHARS: &'static [u8] = b"0123456789abcdef"; impl ToHex for [u8] { /// Turn a vector of `u8` bytes into a hexadecimal string. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(rustc_private)] /// extern crate serialize; /// use serialize::hex::ToHex; /// @@ -43,8 +44,8 @@ impl ToHex for [u8] { fn to_hex(&self) -> String { let mut v = Vec::with_capacity(self.len() * 2); for &byte in self { - v.push(CHARS[(byte >> 4) as uint]); - v.push(CHARS[(byte & 0xf) as uint]); + v.push(CHARS[(byte >> 4) as usize]); + v.push(CHARS[(byte & 0xf) as usize]); } unsafe { @@ -61,10 +62,10 @@ pub trait FromHex { } /// Errors that can occur when decoding a hex encoded string -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum FromHexError { /// The input contained a character not part of the hex format - InvalidHexCharacter(char, uint), + InvalidHexCharacter(char, usize), /// The input had an invalid length InvalidHexLength, } @@ -96,11 +97,12 @@ impl FromHex for str { /// You can use the `String::from_utf8` function to turn a /// `Vec` into a string with characters corresponding to those values. /// - /// # Example + /// # Examples /// /// This converts a string literal to hexadecimal and back. /// - /// ```rust + /// ``` + /// # #![feature(rustc_private)] /// extern crate serialize; /// use serialize::hex::{FromHex, ToHex}; /// @@ -117,7 +119,7 @@ impl FromHex for str { // This may be an overestimate if there is any whitespace let mut b = Vec::with_capacity(self.len() / 2); let mut modulus = 0; - let mut buf = 0u8; + let mut buf = 0; for (idx, byte) in self.bytes().enumerate() { buf <<= 4; @@ -186,7 +188,7 @@ mod tests { #[test] pub fn test_to_hex_all_bytes() { for i in 0..256 { - assert_eq!([i as u8].to_hex(), format!("{:02x}", i as uint)); + assert_eq!([i as u8].to_hex(), format!("{:02x}", i as usize)); } } @@ -194,10 +196,10 @@ mod tests { pub fn test_from_hex_all_bytes() { for i in 0..256 { let ii: &[u8] = &[i as u8]; - assert_eq!(format!("{:02x}", i as uint).from_hex() + assert_eq!(format!("{:02x}", i as usize).from_hex() .unwrap(), ii); - assert_eq!(format!("{:02X}", i as uint).from_hex() + assert_eq!(format!("{:02X}", i as usize).from_hex() .unwrap(), ii); } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index a0f42815b4..5890bdec8c 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -100,7 +100,7 @@ //! let encoded = json::encode(&object).unwrap(); //! //! // Deserialize using `json::decode` -//! let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap(); +//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap(); //! } //! ``` //! @@ -188,7 +188,7 @@ //! let json_str: String = json_obj.to_string(); //! //! // Deserialize like before -//! let decoded: TestStruct = json::decode(json_str.as_slice()).unwrap(); +//! let decoded: TestStruct = json::decode(json_str)).unwrap(); //! } //! ``` @@ -199,15 +199,18 @@ use self::DecoderError::*; use self::ParserState::*; use self::InternalStackElement::*; -use std; use std::collections::{HashMap, BTreeMap}; -use std::{char, f64, fmt, old_io, num, str}; -use std::mem::{swap}; -use std::num::{Float, Int}; +use std::io::prelude::*; +use std::io; +use std::mem::swap; use std::num::FpCategory as Fp; +#[allow(deprecated)] +use std::num::wrapping::WrappingOps; +use std::ops::Index; use std::str::FromStr; use std::string; -use std::ops::Index; +use std::{char, f64, fmt, num, str}; +use std; use unicode::str as unicode_str; use unicode::str::Utf16Item; @@ -232,7 +235,7 @@ pub type Object = BTreeMap; 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 } +pub struct AsPrettyJson<'a, T: 'a> { inner: &'a T, indent: Option } /// The errors that can arise while parsing a JSON stream. #[derive(Clone, Copy, PartialEq, Debug)] @@ -256,11 +259,11 @@ pub enum ErrorCode { NotUtf8, } -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug)] pub enum ParserError { /// msg, line, col - SyntaxError(ErrorCode, uint, uint), - IoError(old_io::IoErrorKind, &'static str), + SyntaxError(ErrorCode, usize, usize), + IoError(io::ErrorKind, String), } // Builder and Parser have the same errors. @@ -275,7 +278,7 @@ pub enum DecoderError { ApplicationError(string::String) } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum EncoderError { FmtError(fmt::Error), BadHashmapKey, @@ -331,8 +334,8 @@ impl fmt::Display for ErrorCode { } } -fn io_error_to_error(io: old_io::IoError) -> ParserError { - IoError(io.kind, io.desc) +fn io_error_to_error(io: io::Error) -> ParserError { + IoError(io.kind(), io.to_string()) } impl fmt::Display for ParserError { @@ -364,8 +367,8 @@ impl std::error::Error for EncoderError { fn description(&self) -> &str { "encoder error" } } -impl std::error::FromError for EncoderError { - fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } +impl From for EncoderError { + fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) } } pub type EncodeResult = Result<(), EncoderError>; @@ -440,7 +443,7 @@ fn escape_char(writer: &mut fmt::Write, v: char) -> EncodeResult { escape_str(writer, buf) } -fn spaces(wr: &mut fmt::Write, mut n: uint) -> EncodeResult { +fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult { const BUF: &'static str = " "; while n >= BUF.len() { @@ -497,13 +500,13 @@ impl<'a> ::Encoder for Encoder<'a> { Ok(()) } - fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_uint(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } - fn emit_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_int(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } @@ -541,8 +544,8 @@ impl<'a> ::Encoder for Encoder<'a> { fn emit_enum_variant(&mut self, name: &str, - _id: uint, - cnt: uint, + _id: usize, + cnt: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { @@ -562,7 +565,7 @@ impl<'a> ::Encoder for Encoder<'a> { } } - fn emit_enum_variant_arg(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_enum_variant_arg(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -574,8 +577,8 @@ impl<'a> ::Encoder for Encoder<'a> { fn emit_enum_struct_variant(&mut self, name: &str, - id: uint, - cnt: uint, + id: usize, + cnt: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { @@ -585,7 +588,7 @@ impl<'a> ::Encoder for Encoder<'a> { fn emit_enum_struct_variant_field(&mut self, _: &str, - idx: uint, + idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { @@ -593,7 +596,7 @@ impl<'a> ::Encoder for Encoder<'a> { self.emit_enum_variant_arg(idx, f) } - fn emit_struct(&mut self, _: &str, _: uint, f: F) -> EncodeResult where + fn emit_struct(&mut self, _: &str, _: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -603,7 +606,7 @@ impl<'a> ::Encoder for Encoder<'a> { Ok(()) } - fn emit_struct_field(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where + fn emit_struct_field(&mut self, name: &str, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -613,26 +616,26 @@ impl<'a> ::Encoder for Encoder<'a> { f(self) } - fn emit_tuple(&mut self, len: uint, f: F) -> EncodeResult where + fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } self.emit_seq(len, f) } - fn emit_tuple_arg(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } self.emit_seq_elt(idx, f) } - fn emit_tuple_struct(&mut self, _name: &str, len: uint, f: F) -> EncodeResult where + fn emit_tuple_struct(&mut self, _name: &str, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } self.emit_seq(len, f) } - fn emit_tuple_struct_arg(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -656,7 +659,7 @@ impl<'a> ::Encoder for Encoder<'a> { f(self) } - fn emit_seq(&mut self, _len: uint, f: F) -> EncodeResult where + fn emit_seq(&mut self, _len: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -666,7 +669,7 @@ impl<'a> ::Encoder for Encoder<'a> { Ok(()) } - fn emit_seq_elt(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_seq_elt(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -676,7 +679,7 @@ impl<'a> ::Encoder for Encoder<'a> { f(self) } - fn emit_map(&mut self, _len: uint, f: F) -> EncodeResult where + fn emit_map(&mut self, _len: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -686,7 +689,7 @@ impl<'a> ::Encoder for Encoder<'a> { Ok(()) } - fn emit_map_elt_key(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_map_elt_key(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -697,7 +700,7 @@ impl<'a> ::Encoder for Encoder<'a> { Ok(()) } - fn emit_map_elt_val(&mut self, _idx: uint, f: F) -> EncodeResult where + fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -710,8 +713,8 @@ impl<'a> ::Encoder for Encoder<'a> { /// compact data pub struct PrettyEncoder<'a> { writer: &'a mut (fmt::Write+'a), - curr_indent: uint, - indent: uint, + curr_indent: usize, + indent: usize, is_emitting_map_key: bool, } @@ -728,7 +731,7 @@ impl<'a> PrettyEncoder<'a> { /// 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) { + pub fn set_indent(&mut self, indent: usize) { // 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; @@ -745,13 +748,13 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { Ok(()) } - fn emit_uint(&mut self, v: uint) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_uint(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } - fn emit_int(&mut self, v: int) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_int(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } @@ -789,8 +792,8 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { fn emit_enum_variant(&mut self, name: &str, - _id: uint, - cnt: uint, + _id: usize, + cnt: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, @@ -820,7 +823,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } } - fn emit_enum_variant_arg(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_enum_variant_arg(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -833,8 +836,8 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { fn emit_enum_struct_variant(&mut self, name: &str, - id: uint, - cnt: uint, + id: usize, + cnt: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { @@ -844,7 +847,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { fn emit_enum_struct_variant_field(&mut self, _: &str, - idx: uint, + idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { @@ -853,7 +856,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { } - fn emit_struct(&mut self, _: &str, len: uint, f: F) -> EncodeResult where + fn emit_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -871,7 +874,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { Ok(()) } - fn emit_struct_field(&mut self, name: &str, idx: uint, f: F) -> EncodeResult where + fn emit_struct_field(&mut self, name: &str, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -886,26 +889,26 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { f(self) } - fn emit_tuple(&mut self, len: uint, f: F) -> EncodeResult where + fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } self.emit_seq(len, f) } - fn emit_tuple_arg(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } self.emit_seq_elt(idx, f) } - fn emit_tuple_struct(&mut self, _: &str, len: uint, f: F) -> EncodeResult where + fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } self.emit_seq(len, f) } - fn emit_tuple_struct_arg(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -929,7 +932,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { f(self) } - fn emit_seq(&mut self, len: uint, f: F) -> EncodeResult where + fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -947,7 +950,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { Ok(()) } - fn emit_seq_elt(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_seq_elt(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -960,7 +963,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { f(self) } - fn emit_map(&mut self, len: uint, f: F) -> EncodeResult where + fn emit_map(&mut self, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -978,7 +981,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { Ok(()) } - fn emit_map_elt_key(&mut self, idx: uint, f: F) -> EncodeResult where + fn emit_map_elt_key(&mut self, idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -994,7 +997,7 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { Ok(()) } - fn emit_map_elt_val(&mut self, _idx: uint, f: F) -> EncodeResult where + fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult where F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult, { if self.is_emitting_map_key { return Err(EncoderError::BadHashmapKey); } @@ -1220,18 +1223,18 @@ impl Json { impl<'a> Index<&'a str> for Json { type Output = Json; - fn index(&self, idx: & &str) -> &Json { - self.find(*idx).unwrap() + fn index(&self, idx: &'a str) -> &Json { + self.find(idx).unwrap() } } -impl Index for Json { +impl Index for Json { type Output = Json; - fn index<'a>(&'a self, idx: &uint) -> &'a Json { + fn index<'a>(&'a self, idx: usize) -> &'a Json { match self { - &Json::Array(ref v) => &v[*idx], - _ => panic!("can only index Json with uint if it is an array") + &Json::Array(ref v) => &v[idx], + _ => panic!("can only index Json with usize if it is an array") } } } @@ -1302,7 +1305,7 @@ impl Stack { } /// Returns The number of elements in the Stack. - pub fn len(&self) -> uint { self.stack.len() } + pub fn len(&self) -> usize { self.stack.len() } /// Returns true if the stack is empty. pub fn is_empty(&self) -> bool { self.stack.is_empty() } @@ -1310,12 +1313,12 @@ impl Stack { /// 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> { + pub fn get<'l>(&'l self, idx: usize) -> StackElement<'l> { match self.stack[idx] { InternalIndex(i) => StackElement::Index(i), InternalKey(start, size) => { StackElement::Key(str::from_utf8( - &self.str_buffer[start as uint .. start as uint + size as uint]) + &self.str_buffer[start as usize .. start as usize + size as usize]) .unwrap()) } } @@ -1358,7 +1361,7 @@ impl Stack { Some(&InternalIndex(i)) => Some(StackElement::Index(i)), Some(&InternalKey(start, size)) => { Some(StackElement::Key(str::from_utf8( - &self.str_buffer[start as uint .. (start+size) as uint] + &self.str_buffer[start as usize .. (start+size) as usize] ).unwrap())) } } @@ -1382,7 +1385,7 @@ impl Stack { assert!(!self.is_empty()); match *self.stack.last().unwrap() { InternalKey(_, sz) => { - let new_size = self.str_buffer.len() - sz as uint; + let new_size = self.str_buffer.len() - sz as usize; self.str_buffer.truncate(new_size); } InternalIndex(_) => {} @@ -1415,8 +1418,8 @@ impl Stack { pub struct Parser { rdr: T, ch: Option, - line: uint, - col: uint, + line: usize, + col: usize, // We maintain a stack representing where we are in the logical structure // of the JSON stream. stack: Stack, @@ -1551,6 +1554,7 @@ impl> Parser { } } + #[allow(deprecated)] // possible resolve bug is mapping these to traits fn parse_u64(&mut self) -> Result { let mut accum = 0; let last_accum = 0; // necessary to detect overflow. @@ -1569,8 +1573,8 @@ impl> Parser { while !self.eof() { match self.ch_or_null() { c @ '0' ... '9' => { - accum *= 10; - accum += (c as u64) - ('0' as u64); + accum = accum.wrapping_mul(10); + accum = accum.wrapping_add((c as u64) - ('0' as u64)); // Detect overflow by comparing to the last value. if accum <= last_accum { return self.error(InvalidNumber); } @@ -1601,7 +1605,7 @@ impl> Parser { match self.ch_or_null() { c @ '0' ... '9' => { dec /= 10.0; - res += (((c as int) - ('0' as int)) as f64) * dec; + res += (((c as isize) - ('0' as isize)) as f64) * dec; self.bump(); } _ => break, @@ -1633,7 +1637,7 @@ impl> Parser { match self.ch_or_null() { c @ '0' ... '9' => { exp *= 10; - exp += (c as uint) - ('0' as uint); + exp += (c as usize) - ('0' as usize); self.bump(); } @@ -1653,7 +1657,7 @@ impl> Parser { fn decode_hex_escape(&mut self) -> Result { let mut i = 0; - let mut n = 0u16; + let mut n = 0; while i < 4 && !self.eof() { self.bump(); n = match self.ch_or_null() { @@ -1745,7 +1749,7 @@ impl> Parser { // 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 + // stream isize the form of a stack that can be queried by the user using the // stack() method. fn parse(&mut self) -> JsonEvent { loop { @@ -1982,7 +1986,7 @@ impl> Builder { self.bump(); match self.token { None => {} - Some(Error(e)) => { return Err(e); } + Some(Error(ref e)) => { return Err(e.clone()); } ref tok => { panic!("unexpected token {:?}", tok.clone()); } } result @@ -2004,7 +2008,7 @@ impl> Builder { swap(s, &mut temp); Ok(Json::String(temp)) } - Some(Error(e)) => Err(e), + Some(Error(ref e)) => Err(e.clone()), Some(ArrayStart) => self.build_array(), Some(ObjectStart) => self.build_object(), Some(ObjectEnd) => self.parser.error(InvalidSyntax), @@ -2037,7 +2041,7 @@ impl> Builder { loop { match self.token { Some(ObjectEnd) => { return Ok(Json::Object(values)); } - Some(Error(e)) => { return Err(e); } + Some(Error(ref e)) => { return Err(e.clone()); } None => { break; } _ => {} } @@ -2056,8 +2060,9 @@ impl> Builder { } /// Decodes a json value from an `&mut old_io::Reader` -pub fn from_reader(rdr: &mut old_io::Reader) -> Result { - let contents = match rdr.read_to_end() { +pub fn from_reader(rdr: &mut Read) -> Result { + let mut contents = Vec::new(); + match rdr.read_to_end(&mut contents) { Ok(c) => c, Err(e) => return Err(io_error_to_error(e)) }; @@ -2125,7 +2130,7 @@ macro_rules! read_primitive { 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 etc) + // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. Json::String(s) => match s.parse().ok() { Some(f) => Ok(f), @@ -2144,12 +2149,12 @@ impl ::Decoder for Decoder { expect!(self.pop(), Null) } - read_primitive! { read_uint, uint } + read_primitive! { read_uint, usize } 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_int, isize } read_primitive! { read_i8, i8 } read_primitive! { read_i16, i16 } read_primitive! { read_i32, i32 } @@ -2163,7 +2168,7 @@ impl ::Decoder for Decoder { Json::U64(f) => Ok(f as f64), Json::F64(f) => Ok(f), Json::String(s) => { - // re: #12967.. a type w/ numeric keys (ie HashMap etc) + // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. match s.parse().ok() { Some(f) => Ok(f), @@ -2204,7 +2209,7 @@ impl ::Decoder for Decoder { fn read_enum_variant(&mut self, names: &[&str], mut f: F) -> DecodeResult - where F: FnMut(&mut Decoder, uint) -> DecodeResult, + where F: FnMut(&mut Decoder, usize) -> DecodeResult, { let name = match self.pop() { Json::String(s) => s, @@ -2244,14 +2249,14 @@ impl ::Decoder for Decoder { f(self, idx) } - fn read_enum_variant_arg(&mut self, _idx: uint, f: F) -> DecodeResult where + fn read_enum_variant_arg(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn read_enum_struct_variant(&mut self, names: &[&str], f: F) -> DecodeResult where - F: FnMut(&mut Decoder, uint) -> DecodeResult, + F: FnMut(&mut Decoder, usize) -> DecodeResult, { self.read_enum_variant(names, f) } @@ -2259,7 +2264,7 @@ impl ::Decoder for Decoder { fn read_enum_struct_variant_field(&mut self, _name: &str, - idx: uint, + idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, @@ -2267,7 +2272,7 @@ impl ::Decoder for Decoder { self.read_enum_variant_arg(idx, f) } - fn read_struct(&mut self, _name: &str, _len: uint, f: F) -> DecodeResult where + fn read_struct(&mut self, _name: &str, _len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { let value = try!(f(self)); @@ -2277,7 +2282,7 @@ impl ::Decoder for Decoder { fn read_struct_field(&mut self, name: &str, - _idx: uint, + _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, @@ -2303,7 +2308,7 @@ impl ::Decoder for Decoder { Ok(value) } - fn read_tuple(&mut self, tuple_len: uint, f: F) -> DecodeResult where + fn read_tuple(&mut self, tuple_len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_seq(move |d, len| { @@ -2315,7 +2320,7 @@ impl ::Decoder for Decoder { }) } - fn read_tuple_arg(&mut self, idx: uint, f: F) -> DecodeResult where + fn read_tuple_arg(&mut self, idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { self.read_seq_elt(idx, f) @@ -2323,7 +2328,7 @@ impl ::Decoder for Decoder { fn read_tuple_struct(&mut self, _name: &str, - len: uint, + len: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, @@ -2332,7 +2337,7 @@ impl ::Decoder for Decoder { } fn read_tuple_struct_arg(&mut self, - idx: uint, + idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, @@ -2350,7 +2355,7 @@ impl ::Decoder for Decoder { } fn read_seq(&mut self, f: F) -> DecodeResult where - F: FnOnce(&mut Decoder, uint) -> DecodeResult, + F: FnOnce(&mut Decoder, usize) -> DecodeResult, { let array = try!(expect!(self.pop(), Array)); let len = array.len(); @@ -2360,14 +2365,14 @@ impl ::Decoder for Decoder { f(self, len) } - fn read_seq_elt(&mut self, _idx: uint, f: F) -> DecodeResult where + fn read_seq_elt(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } fn read_map(&mut self, f: F) -> DecodeResult where - F: FnOnce(&mut Decoder, uint) -> DecodeResult, + F: FnOnce(&mut Decoder, usize) -> DecodeResult, { let obj = try!(expect!(self.pop(), Object)); let len = obj.len(); @@ -2378,13 +2383,13 @@ impl ::Decoder for Decoder { f(self, len) } - fn read_map_elt_key(&mut self, _idx: uint, f: F) -> DecodeResult where + fn read_map_elt_key(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) } - fn read_map_elt_val(&mut self, _idx: uint, f: F) -> DecodeResult where + fn read_map_elt_val(&mut self, _idx: usize, f: F) -> DecodeResult where F: FnOnce(&mut Decoder) -> DecodeResult, { f(self) @@ -2404,22 +2409,26 @@ pub trait ToJson { macro_rules! to_json_impl_i64 { ($($t:ty), +) => ( $(impl ToJson for $t { - fn to_json(&self) -> Json { Json::I64(*self as i64) } + fn to_json(&self) -> Json { + Json::I64(*self as i64) + } })+ ) } -to_json_impl_i64! { int, i8, i16, i32, i64 } +to_json_impl_i64! { isize, 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) } + fn to_json(&self) -> Json { + Json::U64(*self as u64) + } })+ ) } -to_json_impl_u64! { uint, u8, u16, u32, u64 } +to_json_impl_u64! { usize, u8, u16, u32, u64 } impl ToJson for Json { fn to_json(&self) -> Json { self.clone() } @@ -2574,7 +2583,7 @@ impl<'a, T: Encodable> fmt::Display for AsJson<'a, T> { impl<'a, T> AsPrettyJson<'a, T> { /// Set the indentation level for the emitted JSON - pub fn indent(mut self, indent: uint) -> AsPrettyJson<'a, T> { + pub fn indent(mut self, indent: usize) -> AsPrettyJson<'a, T> { self.indent = Some(indent); self } @@ -2619,12 +2628,12 @@ mod tests { StackElement, Stack, Decoder, Encoder, EncoderError}; use std::{i64, u64, f32, f64}; use std::collections::BTreeMap; - use std::num::Float; use std::string; + use std::old_io::Writer; #[derive(RustcDecodable, Eq, PartialEq, Debug)] struct OptionData { - opt: Option, + opt: Option, } #[test] @@ -2652,13 +2661,13 @@ mod tests { #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] enum Animal { Dog, - Frog(string::String, int) + Frog(string::String, isize) } #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] struct Inner { a: (), - b: uint, + b: usize, c: Vec, } @@ -3074,38 +3083,38 @@ mod tests { #[test] fn test_decode_array() { let v: Vec<()> = super::decode("[]").unwrap(); - assert_eq!(v, vec![]); + assert_eq!(v, []); let v: Vec<()> = super::decode("[null]").unwrap(); - assert_eq!(v, vec![()]); + assert_eq!(v, [()]); let v: Vec = super::decode("[true]").unwrap(); - assert_eq!(v, vec![true]); + assert_eq!(v, [true]); - let v: Vec = super::decode("[3, 1]").unwrap(); - assert_eq!(v, vec![3, 1]); + let v: Vec = super::decode("[3, 1]").unwrap(); + assert_eq!(v, [3, 1]); - let v: Vec> = super::decode("[[3], [1, 2]]").unwrap(); - assert_eq!(v, vec![vec![3], vec![1, 2]]); + let v: Vec> = super::decode("[[3], [1, 2]]").unwrap(); + assert_eq!(v, [vec![3], vec![1, 2]]); } #[test] fn test_decode_tuple() { - let t: (uint, uint, uint) = super::decode("[1, 2, 3]").unwrap(); + let t: (usize, usize, usize) = super::decode("[1, 2, 3]").unwrap(); assert_eq!(t, (1, 2, 3)); - let t: (uint, string::String) = super::decode("[1, \"two\"]").unwrap(); + let t: (usize, string::String) = super::decode("[1, \"two\"]").unwrap(); assert_eq!(t, (1, "two".to_string())); } #[test] fn test_decode_tuple_malformed_types() { - assert!(super::decode::<(uint, string::String)>("[1, 2]").is_err()); + assert!(super::decode::<(usize, string::String)>("[1, 2]").is_err()); } #[test] fn test_decode_tuple_malformed_length() { - assert!(super::decode::<(uint, uint)>("[1, 2, 3]").is_err()); + assert!(super::decode::<(usize, usize)>("[1, 2, 3]").is_err()); } #[test] @@ -3457,7 +3466,7 @@ mod tests { use std::str::from_utf8; use std::old_io::Writer; use std::collections::HashMap; - let mut hm: HashMap = HashMap::new(); + let mut hm: HashMap = HashMap::new(); hm.insert(1, true); let mut mem_buf = Vec::new(); write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap(); @@ -3473,7 +3482,7 @@ mod tests { use std::str::from_utf8; use std::old_io::Writer; use std::collections::HashMap; - let mut hm: HashMap = HashMap::new(); + let mut hm: HashMap = HashMap::new(); hm.insert(1, true); let mut mem_buf = Vec::new(); write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap(); @@ -3506,7 +3515,7 @@ mod tests { ); // Helper function for counting indents - fn indents(source: &str) -> uint { + fn indents(source: &str) -> usize { let trimmed = source.trim_left_matches(' '); source.len() - trimmed.len() } @@ -3564,7 +3573,7 @@ mod tests { Ok(o) => o }; let mut decoder = Decoder::new(json_obj); - let _hm: HashMap = Decodable::decode(&mut decoder).unwrap(); + let _hm: HashMap = Decodable::decode(&mut decoder).unwrap(); } #[test] @@ -3577,7 +3586,7 @@ mod tests { Ok(o) => o }; let mut decoder = Decoder::new(json_obj); - let result: Result, DecoderError> = Decodable::decode(&mut decoder); + let result: Result, DecoderError> = Decodable::decode(&mut decoder); assert_eq!(result, Err(ExpectedError("Number".to_string(), "a".to_string()))); } @@ -3940,16 +3949,14 @@ mod tests { assert_eq!(hash_map.to_json(), object); assert_eq!(Some(15).to_json(), I64(15)); assert_eq!(Some(15 as usize).to_json(), U64(15)); - assert_eq!(None::.to_json(), Null); + assert_eq!(None::.to_json(), Null); } #[test] fn test_encode_hashmap_with_arbitrary_key() { - use std::old_io::Writer; use std::collections::HashMap; - use std::fmt; #[derive(PartialEq, Eq, Hash, RustcEncodable)] - struct ArbitraryType(uint); + struct ArbitraryType(usize); let mut hm: HashMap = HashMap::new(); hm.insert(ArbitraryType(1), true); let mut mem_buf = string::String::new(); diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index d476fd72ab..2e86712c9b 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -14,6 +14,8 @@ Core encoding and decoding interfaces. */ +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "serialize"] #![unstable(feature = "rustc_private", reason = "deprecated in favor of rustc-serialize on crates.io")] @@ -28,14 +30,13 @@ Core encoding and decoding interfaces. #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(int_uint)] -#![feature(old_io)] #![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] #![feature(unicode)] -#![cfg_attr(test, feature(test))] +#![feature(str_char)] +#![cfg_attr(test, feature(test, old_io))] // test harness access #[cfg(test)] extern crate test; diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 70f0ba4bb2..81b5d4c581 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -14,7 +14,9 @@ Core encoding and decoding interfaces. */ -use std::old_path; +#[allow(deprecated)] +use std::old_path::{self, GenericPath}; +use std::path; use std::rc::Rc; use std::cell::{Cell, RefCell}; use std::sync::Arc; @@ -24,12 +26,12 @@ pub trait Encoder { // Primitive types: fn emit_nil(&mut self) -> Result<(), Self::Error>; - fn emit_uint(&mut self, v: uint) -> Result<(), Self::Error>; + fn emit_uint(&mut self, v: usize) -> 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_int(&mut self, v: isize) -> 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>; @@ -45,41 +47,41 @@ pub trait Encoder { where F: FnOnce(&mut Self) -> Result<(), Self::Error>; fn emit_enum_variant(&mut self, v_name: &str, - v_id: uint, - len: uint, + v_id: usize, + len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_enum_variant_arg(&mut self, a_idx: uint, f: F) + fn emit_enum_variant_arg(&mut self, a_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; fn emit_enum_struct_variant(&mut self, v_name: &str, - v_id: uint, - len: uint, + v_id: usize, + len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; fn emit_enum_struct_variant_field(&mut self, f_name: &str, - f_idx: uint, + f_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_struct(&mut self, name: &str, len: uint, f: F) + fn emit_struct(&mut self, name: &str, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_struct_field(&mut self, f_name: &str, f_idx: uint, f: F) + fn emit_struct_field(&mut self, f_name: &str, f_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_tuple(&mut self, len: uint, f: F) -> Result<(), Self::Error> + fn emit_tuple(&mut self, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_tuple_arg(&mut self, idx: uint, f: F) -> Result<(), Self::Error> + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_tuple_struct(&mut self, name: &str, len: uint, f: F) + fn emit_tuple_struct(&mut self, name: &str, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: F) + fn emit_tuple_struct_arg(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; @@ -90,16 +92,16 @@ pub trait Encoder { fn emit_option_some(&mut self, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_seq(&mut self, len: uint, f: F) -> Result<(), Self::Error> + fn emit_seq(&mut self, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_seq_elt(&mut self, idx: uint, f: F) -> Result<(), Self::Error> + fn emit_seq_elt(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_map(&mut self, len: uint, f: F) -> Result<(), Self::Error> + fn emit_map(&mut self, len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_map_elt_key(&mut self, idx: uint, f: F) -> Result<(), Self::Error> + fn emit_map_elt_key(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; - fn emit_map_elt_val(&mut self, idx: uint, f: F) -> Result<(), Self::Error> + fn emit_map_elt_val(&mut self, idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; } @@ -108,12 +110,12 @@ pub trait Decoder { // Primitive types: fn read_nil(&mut self) -> Result<(), Self::Error>; - fn read_uint(&mut self) -> Result; + fn read_uint(&mut self) -> Result; fn read_u64(&mut self) -> Result; fn read_u32(&mut self) -> Result; fn read_u16(&mut self) -> Result; fn read_u8(&mut self) -> Result; - fn read_int(&mut self) -> Result; + fn read_int(&mut self) -> Result; fn read_i64(&mut self) -> Result; fn read_i32(&mut self) -> Result; fn read_i16(&mut self) -> Result; @@ -130,41 +132,41 @@ pub trait Decoder { fn read_enum_variant(&mut self, names: &[&str], f: F) -> Result - where F: FnMut(&mut Self, uint) -> Result; - fn read_enum_variant_arg(&mut self, a_idx: uint, f: F) + where F: FnMut(&mut Self, usize) -> Result; + fn read_enum_variant_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; fn read_enum_struct_variant(&mut self, names: &[&str], f: F) -> Result - where F: FnMut(&mut Self, uint) -> Result; + where F: FnMut(&mut Self, usize) -> Result; fn read_enum_struct_variant_field(&mut self, &f_name: &str, - f_idx: uint, + f_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; - fn read_struct(&mut self, s_name: &str, len: uint, f: F) + fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; fn read_struct_field(&mut self, f_name: &str, - f_idx: uint, + f_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; - fn read_tuple(&mut self, len: uint, f: F) -> Result + fn read_tuple(&mut self, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; - fn read_tuple_arg(&mut self, a_idx: uint, f: F) + fn read_tuple_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; - fn read_tuple_struct(&mut self, s_name: &str, len: uint, f: F) + fn read_tuple_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; - fn read_tuple_struct_arg(&mut self, a_idx: uint, f: F) + fn read_tuple_struct_arg(&mut self, a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; @@ -173,16 +175,16 @@ pub trait Decoder { where F: FnMut(&mut Self, bool) -> Result; fn read_seq(&mut self, f: F) -> Result - where F: FnOnce(&mut Self, uint) -> Result; - fn read_seq_elt(&mut self, idx: uint, f: F) -> Result + where F: FnOnce(&mut Self, usize) -> Result; + fn read_seq_elt(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; fn read_map(&mut self, f: F) -> Result - where F: FnOnce(&mut Self, uint) -> Result; - fn read_map_elt_key(&mut self, idx: uint, f: F) + where F: FnOnce(&mut Self, usize) -> Result; + fn read_map_elt_key(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; - fn read_map_elt_val(&mut self, idx: uint, f: F) + fn read_map_elt_val(&mut self, idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; @@ -198,14 +200,14 @@ pub trait Decodable { fn decode(d: &mut D) -> Result; } -impl Encodable for uint { +impl Encodable for usize { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_uint(*self) } } -impl Decodable for uint { - fn decode(d: &mut D) -> Result { +impl Decodable for usize { + fn decode(d: &mut D) -> Result { d.read_uint() } } @@ -258,14 +260,14 @@ impl Decodable for u64 { } } -impl Encodable for int { +impl Encodable for isize { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_int(*self) } } -impl Decodable for int { - fn decode(d: &mut D) -> Result { +impl Decodable for isize { + fn decode(d: &mut D) -> Result { d.read_int() } } @@ -508,7 +510,7 @@ macro_rules! tuple { impl<$($name:Decodable),*> Decodable for ($($name,)*) { #[allow(non_snake_case)] fn decode(d: &mut D) -> Result<($($name,)*), D::Error> { - let len: uint = count_idents!($($name,)*); + let len: usize = count_idents!($($name,)*); d.read_tuple(len, |d| { let mut i = 0; let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, @@ -538,12 +540,14 @@ macro_rules! tuple { tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } +#[allow(deprecated)] impl Encodable for old_path::posix::Path { fn encode(&self, e: &mut S) -> Result<(), S::Error> { self.as_vec().encode(e) } } +#[allow(deprecated)] impl Decodable for old_path::posix::Path { fn decode(d: &mut D) -> Result { let bytes: Vec = try!(Decodable::decode(d)); @@ -551,12 +555,14 @@ impl Decodable for old_path::posix::Path { } } +#[allow(deprecated)] impl Encodable for old_path::windows::Path { fn encode(&self, e: &mut S) -> Result<(), S::Error> { self.as_vec().encode(e) } } +#[allow(deprecated)] impl Decodable for old_path::windows::Path { fn decode(d: &mut D) -> Result { let bytes: Vec = try!(Decodable::decode(d)); @@ -564,6 +570,19 @@ impl Decodable for old_path::windows::Path { } } +impl Encodable for path::PathBuf { + fn encode(&self, e: &mut S) -> Result<(), S::Error> { + self.to_str().unwrap().encode(e) + } +} + +impl Decodable for path::PathBuf { + fn decode(d: &mut D) -> Result { + let bytes: String = try!(Decodable::decode(d)); + Ok(path::PathBuf::from(bytes)) + } +} + impl Encodable for Cell { fn encode(&self, s: &mut S) -> Result<(), S::Error> { self.get().encode(s) diff --git a/src/libstd/array.rs b/src/libstd/array.rs new file mode 100644 index 0000000000..a6b8cd71a3 --- /dev/null +++ b/src/libstd/array.rs @@ -0,0 +1,13 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The fixed-size array type (`[T; n]`). + +#![doc(primitive = "array")] diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 4d38d17576..20ad71a4bf 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -16,8 +16,8 @@ use prelude::v1::*; +use ops::Range; use mem; -use iter::Range; /// Extension methods for ASCII-subset only operations on owned strings #[unstable(feature = "std_misc", @@ -34,43 +34,124 @@ pub trait OwnedAsciiExt { fn into_ascii_lowercase(self) -> Self; } -/// Extension methods for ASCII-subset only operations on string slices +/// Extension methods for ASCII-subset only operations on string slices. #[stable(feature = "rust1", since = "1.0.0")] pub trait AsciiExt { + /// Container type for copied ASCII characters. #[stable(feature = "rust1", since = "1.0.0")] type Owned; /// Check if within the ASCII range. + /// + /// # Examples + /// + /// ``` + /// use std::ascii::AsciiExt; + /// + /// let ascii = 'a'; + /// let utf8 = '❤'; + /// + /// assert_eq!(true, ascii.is_ascii()); + /// assert_eq!(false, utf8.is_ascii()) + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn is_ascii(&self) -> bool; - /// Makes a copy of the string in ASCII upper case: + /// Makes a copy of the string in ASCII upper case. + /// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. + /// + /// # Examples + /// + /// ``` + /// use std::ascii::AsciiExt; + /// + /// let ascii = 'a'; + /// let utf8 = '❤'; + /// + /// assert_eq!('A', ascii.to_ascii_uppercase()); + /// assert_eq!('❤', utf8.to_ascii_uppercase()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn to_ascii_uppercase(&self) -> Self::Owned; - /// Makes a copy of the string in ASCII lower case: + /// Makes a copy of the string in ASCII lower case. + /// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. + /// + /// # Examples + /// + /// ``` + /// use std::ascii::AsciiExt; + /// + /// let ascii = 'A'; + /// let utf8 = '❤'; + /// + /// assert_eq!('a', ascii.to_ascii_lowercase()); + /// assert_eq!('❤', utf8.to_ascii_lowercase()); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn to_ascii_lowercase(&self) -> Self::Owned; /// Check that two strings are an ASCII case-insensitive match. + /// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, /// but without allocating and copying temporary strings. + /// + /// # Examples + /// + /// ``` + /// use std::ascii::AsciiExt; + /// + /// let ascii1 = 'A'; + /// let ascii2 = 'a'; + /// let ascii3 = 'A'; + /// let ascii4 = 'z'; + /// + /// assert_eq!(true, ascii1.eq_ignore_ascii_case(&ascii2)); + /// assert_eq!(true, ascii1.eq_ignore_ascii_case(&ascii3)); + /// assert_eq!(false, ascii1.eq_ignore_ascii_case(&ascii4)); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn eq_ignore_ascii_case(&self, other: &Self) -> bool; /// Convert this type to its ASCII upper case equivalent in-place. /// /// See `to_ascii_uppercase` for more information. + /// + /// # Examples + /// + /// ``` + /// # #![feature(ascii)] + /// use std::ascii::AsciiExt; + /// + /// let mut ascii = 'a'; + /// + /// ascii.make_ascii_uppercase(); + /// + /// assert_eq!('A', ascii); + /// ``` #[unstable(feature = "ascii")] fn make_ascii_uppercase(&mut self); /// Convert this type to its ASCII lower case equivalent in-place. /// /// See `to_ascii_lowercase` for more information. + /// + /// # Examples + /// + /// ``` + /// # #![feature(ascii)] + /// use std::ascii::AsciiExt; + /// + /// let mut ascii = 'A'; + /// + /// ascii.make_ascii_lowercase(); + /// + /// assert_eq!('a', ascii); + /// ``` #[unstable(feature = "ascii")] fn make_ascii_lowercase(&mut self); } @@ -185,7 +266,7 @@ impl OwnedAsciiExt for Vec { impl AsciiExt for u8 { type Owned = u8; #[inline] - fn is_ascii(&self) -> bool { *self & 128 == 0u8 } + fn is_ascii(&self) -> bool { *self & 128 == 0 } #[inline] fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] } #[inline] @@ -245,7 +326,7 @@ pub struct EscapeDefault { data: [u8; 4], } -/// Returns a 'default' ASCII and C++11-like literal escape of a `u8` +/// Returns an iterator that produces an escaped version of a `u8`. /// /// 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 @@ -256,6 +337,20 @@ pub struct EscapeDefault { /// - Any other chars in the range [0x20,0x7e] are not escaped. /// - Any other chars are given hex escapes of the form '\xNN'. /// - Unicode escapes are never generated by this function. +/// +/// # Examples +/// +/// ``` +/// use std::ascii; +/// +/// let escaped = ascii::escape_default(b'0').next().unwrap(); +/// assert_eq!(b'0', escaped); +/// +/// let mut escaped = ascii::escape_default(b'\t'); +/// +/// assert_eq!(b'\\', escaped.next().unwrap()); +/// assert_eq!(b't', escaped.next().unwrap()); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn escape_default(c: u8) -> EscapeDefault { let (data, len) = match c { @@ -269,7 +364,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), }; - return EscapeDefault { range: range(0, len), data: data }; + return EscapeDefault { range: (0.. len), data: data }; fn hexify(b: u8) -> u8 { match b { @@ -397,7 +492,7 @@ mod tests { assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL"); assert_eq!("hıKß".to_ascii_uppercase(), "HıKß"); - for i in 0u32..501 { + for i in 0..501 { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_uppercase(), @@ -411,7 +506,7 @@ mod tests { // Dotted capital I, Kelvin sign, Sharp S. assert_eq!("HİKß".to_ascii_lowercase(), "hİKß"); - for i in 0u32..501 { + for i in 0..501 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().to_ascii_lowercase(), @@ -425,7 +520,7 @@ mod tests { "URL()URL()URL()üRL".to_string()); assert_eq!(("hıKß".to_string()).into_ascii_uppercase(), "HıKß"); - for i in 0u32..501 { + for i in 0..501 { let upper = if 'a' as u32 <= i && i <= 'z' as u32 { i + 'A' as u32 - 'a' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_uppercase(), @@ -440,7 +535,7 @@ mod tests { // Dotted capital I, Kelvin sign, Sharp S. assert_eq!(("HİKß".to_string()).into_ascii_lowercase(), "hİKß"); - for i in 0u32..501 { + for i in 0..501 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert_eq!((from_u32(i).unwrap()).to_string().into_ascii_lowercase(), @@ -458,7 +553,7 @@ mod tests { assert!(!"K".eq_ignore_ascii_case("k")); assert!(!"ß".eq_ignore_ascii_case("s")); - for i in 0u32..501 { + for i in 0..501 { let lower = if 'A' as u32 <= i && i <= 'Z' as u32 { i + 'a' as u32 - 'A' as u32 } else { i }; assert!((from_u32(i).unwrap()).to_string().eq_ignore_ascii_case( diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index 0d8b233a16..df703b3e43 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -12,4 +12,3 @@ #![doc(primitive = "bool")] #![stable(feature = "rust1", since = "1.0.0")] - diff --git a/src/libstd/collections/hash/bench.rs b/src/libstd/collections/hash/bench.rs index ca506e8c36..ac21ae0f0a 100644 --- a/src/libstd/collections/hash/bench.rs +++ b/src/libstd/collections/hash/bench.rs @@ -14,7 +14,7 @@ extern crate test; use prelude::v1::*; use self::test::Bencher; -use iter::{range_inclusive}; +use iter::range_inclusive; #[bench] fn new_drop(b : &mut Bencher) { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ade4f1f053..a636c1a812 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -20,11 +20,10 @@ use cmp::{max, Eq, PartialEq}; use default::Default; use fmt::{self, Debug}; use hash::{Hash, SipHasher}; -use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; +use iter::{self, Iterator, ExactSizeIterator, IntoIterator, FromIterator, Extend, Map}; use marker::Sized; use mem::{self, replace}; -use num::{Int, UnsignedInt}; -use ops::{Deref, FnMut, Index, IndexMut}; +use ops::{Deref, FnMut, FnOnce, Index}; use option::Option::{self, Some, None}; use rand::{self, Rng}; use result::Result::{self, Ok, Err}; @@ -88,7 +87,6 @@ impl DefaultResizePolicy { #[test] fn test_resize_policy() { - use prelude::v1::*; let rp = DefaultResizePolicy; for n in 0..1000 { assert!(rp.min_capacity(rp.usable_capacity(n)) <= n); @@ -204,7 +202,7 @@ fn test_resize_policy() { // produces identical results to a linear naive reinsertion from the same // element. // -// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs +// FIXME(Gankro, pczarn): review the proof and put it all in a separate README.md /// A hash map implementation which uses linear probing with Robin /// Hood bucket stealing. @@ -216,7 +214,19 @@ fn test_resize_policy() { /// overridden with one of the constructors. /// /// It is required that the keys implement the `Eq` and `Hash` traits, although -/// this can frequently be achieved by using `#[derive(Eq, Hash)]`. +/// this can frequently be achieved by using `#[derive(Eq, Hash)]`. If you +/// implement these yourself, it is important that the following property holds: +/// +/// ```text +/// k1 == k2 -> hash(k1) == hash(k2) +/// ``` +/// +/// In other words, if two keys are equal, their hashes must be equal. +/// +/// It is a logic error for a key to be modified in such a way that the key's +/// hash, as determined by the `Hash` trait, or its equality, as determined by +/// the `Eq` trait, changes while it is in the map. This is normally only +/// possible through `Cell`, `RefCell`, global state, I/O, or unsafe code. /// /// Relevant papers/articles: /// @@ -226,7 +236,7 @@ fn test_resize_policy() { /// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift /// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/) /// -/// # Example +/// # Examples /// /// ``` /// use std::collections::HashMap; @@ -315,6 +325,13 @@ fn search_hashed(table: M, M: Deref>, F: FnMut(&K) -> bool, { + // This is the only function where capacity can be zero. To avoid + // undefined behaviour when Bucket::new gets the raw bucket in this + // case, immediately return the appropriate search result. + if table.capacity() == 0 { + return TableRef(table); + } + let size = table.size(); let mut probe = Bucket::new(table, hash); let ib = probe.index(); @@ -491,11 +508,11 @@ impl HashMap impl HashMap { /// Create an empty HashMap. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::new(); + /// let mut map: HashMap<&str, isize> = HashMap::new(); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -505,11 +522,11 @@ impl HashMap { /// Creates an empty hash map with the given initial capacity. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); + /// let mut map: HashMap<&str, isize> = HashMap::with_capacity(10); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -525,9 +542,10 @@ impl HashMap /// /// The creates map has the default initial capacity. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(std_misc)] /// use std::collections::HashMap; /// use std::collections::hash_map::RandomState; /// @@ -553,9 +571,10 @@ impl HashMap /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(std_misc)] /// use std::collections::HashMap; /// use std::collections::hash_map::RandomState; /// @@ -580,11 +599,11 @@ impl HashMap /// Returns the number of elements the map can hold without reallocating. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; - /// let map: HashMap = HashMap::with_capacity(100); + /// let map: HashMap = HashMap::with_capacity(100); /// assert!(map.capacity() >= 100); /// ``` #[inline] @@ -601,11 +620,11 @@ impl HashMap /// /// Panics if the new allocation size overflows `usize`. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::new(); + /// let mut map: HashMap<&str, isize> = HashMap::new(); /// map.reserve(10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -708,12 +727,12 @@ impl HashMap /// down as much as possible while maintaining the internal rules /// and possibly leaving some space in accordance with the resize policy. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; /// - /// let mut map: HashMap = HashMap::with_capacity(100); + /// let mut map: HashMap = HashMap::with_capacity(100); /// map.insert(1, 2); /// map.insert(3, 4); /// assert!(map.capacity() >= 100); @@ -785,9 +804,9 @@ impl HashMap } } - let robin_ib = bucket.index() as int - bucket.distance() as int; + let robin_ib = bucket.index() as isize - bucket.distance() as isize; - if (ib as int) < robin_ib { + if (ib as isize) < robin_ib { // Found a luckier bucket than me. Better steal his spot. return robin_hood(bucket, robin_ib as usize, hash, k, v); } @@ -800,7 +819,7 @@ impl HashMap /// An iterator visiting all keys in arbitrary order. /// Iterator element type is `&'a K`. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -825,7 +844,7 @@ impl HashMap /// An iterator visiting all values in arbitrary order. /// Iterator element type is `&'a V`. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -850,7 +869,7 @@ impl HashMap /// An iterator visiting all key-value pairs in arbitrary order. /// Iterator element type is `(&'a K, &'a V)`. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -873,7 +892,7 @@ impl HashMap /// with mutable references to the values. /// Iterator element type is `(&'a K, &'a mut V)`. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -901,7 +920,7 @@ impl HashMap /// pair out of the map in arbitrary order. The map cannot be used after /// calling this. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -912,7 +931,7 @@ impl HashMap /// map.insert("c", 3); /// /// // Not possible with .iter() - /// let vec: Vec<(&str, int)> = map.into_iter().collect(); + /// let vec: Vec<(&str, isize)> = map.into_iter().collect(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { @@ -936,7 +955,7 @@ impl HashMap /// Returns the number of elements in the map. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -951,7 +970,7 @@ impl HashMap /// Returns true if the map contains no elements. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -968,9 +987,10 @@ impl HashMap /// Clears the map, returning all key-value pairs as an iterator. Keeps the /// allocated memory for reuse. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(std_misc)] /// use std::collections::HashMap; /// /// let mut a = HashMap::new(); @@ -999,7 +1019,7 @@ impl HashMap /// Clears the map, removing all key-value pairs. Keeps the allocated memory /// for reuse. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -1021,7 +1041,7 @@ impl HashMap /// `Hash` and `Eq` on the borrowed form *must* match those for /// the key type. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -1044,7 +1064,7 @@ impl HashMap /// `Hash` and `Eq` on the borrowed form *must* match those for /// the key type. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -1067,7 +1087,7 @@ impl HashMap /// `Hash` and `Eq` on the borrowed form *must* match those for /// the key type. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -1078,7 +1098,7 @@ impl HashMap /// Some(x) => *x = "b", /// None => (), /// } - /// assert_eq!(map[1], "b"); + /// assert_eq!(map[&1], "b"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> @@ -1090,7 +1110,7 @@ impl HashMap /// Inserts a key-value pair from the map. If the key already had a value /// present in the map, that value is returned. Otherwise, `None` is returned. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -1101,7 +1121,7 @@ impl HashMap /// /// map.insert(37, "b"); /// assert_eq!(map.insert(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); + /// assert_eq!(map[&37], "c"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, k: K, v: V) -> Option { @@ -1122,7 +1142,7 @@ impl HashMap /// `Hash` and `Eq` on the borrowed form *must* match those for /// the key type. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashMap; @@ -1175,9 +1195,9 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHas } } - let robin_ib = bucket.index() as int - bucket.distance() as int; + let robin_ib = bucket.index() as isize - bucket.distance() as isize; - if (ib as int) < robin_ib { + if (ib as isize) < robin_ib { // Found a luckier bucket than me. Better steal his spot. return Vacant(VacantEntry { hash: hash, @@ -1213,14 +1233,7 @@ impl Debug for HashMap where K: Eq + Hash + Debug, V: Debug, S: HashState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "HashMap {{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}: {:?}", *k, *v)); - } - - write!(f, "}}") + self.iter().fold(f.debug_map(), |b, (k, v)| b.entry(k, v)).finish() } } @@ -1235,7 +1248,7 @@ impl Default for HashMap } #[stable(feature = "rust1", since = "1.0.0")] -impl Index for HashMap +impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap where K: Eq + Hash + Borrow, Q: Eq + Hash, S: HashState, @@ -1243,23 +1256,11 @@ impl Index for HashMap type Output = V; #[inline] - fn index<'a>(&'a self, index: &Q) -> &'a V { + fn index(&self, index: &Q) -> &V { self.get(index).expect("no entry found for key") } } -#[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for HashMap - where K: Eq + Hash + Borrow, - Q: Eq + Hash, - S: HashState, -{ - #[inline] - fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V { - self.get_mut(index).expect("no entry found for key") - } -} - /// HashMap iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { @@ -1325,15 +1326,13 @@ pub struct Drain<'a, K: 'a, V: 'a> { } /// A view into a single occupied location in a HashMap. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry<'a, K: 'a, V: 'a> { elem: FullBucket>, } /// A view into a single empty location in a HashMap. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry<'a, K: 'a, V: 'a> { hash: SafeHash, key: K, @@ -1341,12 +1340,14 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> { } /// A view into a single location in a map, which may be vacant or occupied. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied Entry. + #[stable(feature = "rust1", since = "1.0.0")] Occupied(OccupiedEntry<'a, K, V>), + /// A vacant Entry. + #[stable(feature = "rust1", since = "1.0.0")] Vacant(VacantEntry<'a, K, V>), } @@ -1467,16 +1468,39 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } -#[unstable(feature = "std_misc", - reason = "matches collection reform v2 specification, waiting for dust to settle")] impl<'a, K, V> Entry<'a, K, V> { /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant. + #[unstable(feature = "std_misc", + reason = "will soon be replaced by or_insert")] + #[deprecated(since = "1.0", + reason = "replaced with more ergonomic `or_insert` and `or_insert_with`")] + /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => Err(entry), } } + + #[stable(feature = "rust1", since = "1.0.0")] + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default), + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(default()), + } + } } impl<'a, K, V> OccupiedEntry<'a, K, V> { @@ -1631,7 +1655,7 @@ mod test_map { assert_eq!(*m.get(&2).unwrap(), 4); } - thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } + thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } #[derive(Hash, PartialEq, Eq)] struct Dropable { @@ -1788,7 +1812,7 @@ mod test_map { #[test] fn test_empty_pop() { - let mut m: HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); assert_eq!(m.remove(&0), None); } @@ -2000,9 +2024,9 @@ mod test_map { let map_str = format!("{:?}", map); - assert!(map_str == "HashMap {1: 2, 3: 4}" || - map_str == "HashMap {3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "HashMap {}"); + assert!(map_str == "{1: 2, 3: 4}" || + map_str == "{3: 4, 1: 2}"); + assert_eq!(format!("{:?}", empty), "{}"); } #[test] @@ -2187,11 +2211,11 @@ mod test_map { map.insert(2, 1); map.insert(3, 4); - assert_eq!(map[2], 1); + assert_eq!(map[&2], 1); } #[test] - #[should_fail] + #[should_panic] fn test_index_nonexistent() { let mut map = HashMap::new(); @@ -2199,7 +2223,7 @@ mod test_map { map.insert(2, 1); map.insert(3, 4); - map[4]; + map[&4]; } #[test] @@ -2256,6 +2280,7 @@ mod test_map { #[test] fn test_entry_take_doesnt_corrupt() { + #![allow(deprecated)] //rand // Test for #19292 fn check(m: &HashMap) { for k in m.keys() { diff --git a/src/libstd/collections/hash/map_stage0.rs b/src/libstd/collections/hash/map_stage0.rs deleted file mode 100644 index f9e5044c59..0000000000 --- a/src/libstd/collections/hash/map_stage0.rs +++ /dev/null @@ -1,2330 +0,0 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15883 - -use self::Entry::*; -use self::SearchResult::*; -use self::VacantEntryState::*; - -use borrow::Borrow; -use clone::Clone; -use cmp::{max, Eq, PartialEq}; -use default::Default; -use fmt::{self, Debug}; -use hash::{self, Hash, SipHasher}; -use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map}; -use marker::Sized; -use mem::{self, replace}; -use num::{Int, UnsignedInt}; -use ops::{Deref, FnMut, Index, IndexMut}; -use option::Option::{self, Some, None}; -use rand::{self, Rng}; -use result::Result::{self, Ok, Err}; - -use super::table::{ - self, - Bucket, - EmptyBucket, - FullBucket, - FullBucketImm, - FullBucketMut, - RawTable, - SafeHash -}; -use super::table::BucketState::{ - Empty, - Full, -}; -use super::state::HashState; - -const INITIAL_LOG2_CAP: usize = 5; -#[unstable(feature = "std_misc")] -pub const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5 - -/// The default behavior of HashMap implements a load factor of 90.9%. -/// This behavior is characterized by the following condition: -/// -/// - if size > 0.909 * capacity: grow the map -#[derive(Clone)] -struct DefaultResizePolicy; - -impl DefaultResizePolicy { - fn new() -> DefaultResizePolicy { - DefaultResizePolicy - } - - #[inline] - fn min_capacity(&self, usable_size: usize) -> usize { - // Here, we are rephrasing the logic by specifying the lower limit - // on capacity: - // - // - if `cap < size * 1.1`: grow the map - usable_size * 11 / 10 - } - - /// An inverse of `min_capacity`, approximately. - #[inline] - fn usable_capacity(&self, cap: usize) -> usize { - // As the number of entries approaches usable capacity, - // min_capacity(size) must be smaller than the internal capacity, - // so that the map is not resized: - // `min_capacity(usable_capacity(x)) <= x`. - // The left-hand side can only be smaller due to flooring by integer - // division. - // - // This doesn't have to be checked for overflow since allocation size - // in bytes will overflow earlier than multiplication by 10. - cap * 10 / 11 - } -} - -#[test] -fn test_resize_policy() { - use prelude::v1::*; - let rp = DefaultResizePolicy; - for n in 0..1000 { - assert!(rp.min_capacity(rp.usable_capacity(n)) <= n); - assert!(rp.usable_capacity(rp.min_capacity(n)) <= n); - } -} - -// The main performance trick in this hashmap is called Robin Hood Hashing. -// It gains its excellent performance from one essential operation: -// -// If an insertion collides with an existing element, and that element's -// "probe distance" (how far away the element is from its ideal location) -// is higher than how far we've already probed, swap the elements. -// -// This massively lowers variance in probe distance, and allows us to get very -// high load factors with good performance. The 90% load factor I use is rather -// conservative. -// -// > Why a load factor of approximately 90%? -// -// In general, all the distances to initial buckets will converge on the mean. -// At a load factor of α, the odds of finding the target bucket after k -// probes is approximately 1-α^k. If we set this equal to 50% (since we converge -// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round -// this down to make the math easier on the CPU and avoid its FPU. -// Since on average we start the probing in the middle of a cache line, this -// strategy pulls in two cache lines of hashes on every lookup. I think that's -// pretty good, but if you want to trade off some space, it could go down to one -// cache line on average with an α of 0.84. -// -// > Wait, what? Where did you get 1-α^k from? -// -// On the first probe, your odds of a collision with an existing element is α. -// The odds of doing this twice in a row is approximately α^2. For three times, -// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT -// colliding after k tries is 1-α^k. -// -// The paper from 1986 cited below mentions an implementation which keeps track -// of the distance-to-initial-bucket histogram. This approach is not suitable -// for modern architectures because it requires maintaining an internal data -// structure. This allows very good first guesses, but we are most concerned -// with guessing entire cache lines, not individual indexes. Furthermore, array -// accesses are no longer linear and in one direction, as we have now. There -// is also memory and cache pressure that this would entail that would be very -// difficult to properly see in a microbenchmark. -// -// ## Future Improvements (FIXME!) -// -// Allow the load factor to be changed dynamically and/or at initialization. -// -// Also, would it be possible for us to reuse storage when growing the -// underlying table? This is exactly the use case for 'realloc', and may -// be worth exploring. -// -// ## Future Optimizations (FIXME!) -// -// Another possible design choice that I made without any real reason is -// parameterizing the raw table over keys and values. Technically, all we need -// is the size and alignment of keys and values, and the code should be just as -// efficient (well, we might need one for power-of-two size and one for not...). -// This has the potential to reduce code bloat in rust executables, without -// really losing anything except 4 words (key size, key alignment, val size, -// val alignment) which can be passed in to every call of a `RawTable` function. -// This would definitely be an avenue worth exploring if people start complaining -// about the size of rust executables. -// -// Annotate exceedingly likely branches in `table::make_hash` -// and `search_hashed` to reduce instruction cache pressure -// and mispredictions once it becomes possible (blocked on issue #11092). -// -// Shrinking the table could simply reallocate in place after moving buckets -// to the first half. -// -// The growth algorithm (fragment of the Proof of Correctness) -// -------------------- -// -// The growth algorithm is basically a fast path of the naive reinsertion- -// during-resize algorithm. Other paths should never be taken. -// -// Consider growing a robin hood hashtable of capacity n. Normally, we do this -// by allocating a new table of capacity `2n`, and then individually reinsert -// each element in the old table into the new one. This guarantees that the -// new table is a valid robin hood hashtable with all the desired statistical -// properties. Remark that the order we reinsert the elements in should not -// matter. For simplicity and efficiency, we will consider only linear -// reinsertions, which consist of reinserting all elements in the old table -// into the new one by increasing order of index. However we will not be -// starting our reinsertions from index 0 in general. If we start from index -// i, for the purpose of reinsertion we will consider all elements with real -// index j < i to have virtual index n + j. -// -// Our hash generation scheme consists of generating a 64-bit hash and -// truncating the most significant bits. When moving to the new table, we -// simply introduce a new bit to the front of the hash. Therefore, if an -// elements has ideal index i in the old table, it can have one of two ideal -// locations in the new table. If the new bit is 0, then the new ideal index -// is i. If the new bit is 1, then the new ideal index is n + i. Intuitively, -// we are producing two independent tables of size n, and for each element we -// independently choose which table to insert it into with equal probability. -// However the rather than wrapping around themselves on overflowing their -// indexes, the first table overflows into the first, and the first into the -// second. Visually, our new table will look something like: -// -// [yy_xxx_xxxx_xxx|xx_yyy_yyyy_yyy] -// -// Where x's are elements inserted into the first table, y's are elements -// inserted into the second, and _'s are empty sections. We now define a few -// key concepts that we will use later. Note that this is a very abstract -// perspective of the table. A real resized table would be at least half -// empty. -// -// Theorem: A linear robin hood reinsertion from the first ideal element -// produces identical results to a linear naive reinsertion from the same -// element. -// -// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs - -/// A hash map implementation which uses linear probing with Robin -/// Hood bucket stealing. -/// -/// The hashes are all keyed by the task-local random number generator -/// on creation by default. This means that the ordering of the keys is -/// randomized, but makes the tables more resistant to -/// denial-of-service attacks (Hash DoS). This behaviour can be -/// overridden with one of the constructors. -/// -/// It is required that the keys implement the `Eq` and `Hash` traits, although -/// this can frequently be achieved by using `#[derive(Eq, Hash)]`. -/// -/// Relevant papers/articles: -/// -/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf) -/// 2. Emmanuel Goossaert. ["Robin Hood -/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/) -/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift -/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/) -/// -/// # Example -/// -/// ``` -/// use std::collections::HashMap; -/// -/// // type inference lets us omit an explicit type signature (which -/// // would be `HashMap<&str, &str>` in this example). -/// let mut book_reviews = HashMap::new(); -/// -/// // review some books. -/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book."); -/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece."); -/// book_reviews.insert("Pride and Prejudice", "Very enjoyable."); -/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot."); -/// -/// // check for a specific one. -/// if !book_reviews.contains_key(&("Les Misérables")) { -/// println!("We've got {} reviews, but Les Misérables ain't one.", -/// book_reviews.len()); -/// } -/// -/// // oops, this review has a lot of spelling mistakes, let's delete it. -/// book_reviews.remove(&("The Adventures of Sherlock Holmes")); -/// -/// // look up the values associated with some keys. -/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"]; -/// for book in to_find.iter() { -/// match book_reviews.get(book) { -/// Some(review) => println!("{}: {}", *book, *review), -/// None => println!("{} is unreviewed.", *book) -/// } -/// } -/// -/// // iterate over everything. -/// for (book, review) in book_reviews.iter() { -/// println!("{}: \"{}\"", *book, *review); -/// } -/// ``` -/// -/// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`. -/// We must also derive `PartialEq`. -/// -/// ``` -/// use std::collections::HashMap; -/// -/// #[derive(Hash, Eq, PartialEq, Debug)] -/// struct Viking { -/// name: String, -/// country: String, -/// } -/// -/// impl Viking { -/// /// Create a new Viking. -/// fn new(name: &str, country: &str) -> Viking { -/// Viking { name: name.to_string(), country: country.to_string() } -/// } -/// } -/// -/// // Use a HashMap to store the vikings' health points. -/// let mut vikings = HashMap::new(); -/// -/// vikings.insert(Viking::new("Einar", "Norway"), 25); -/// vikings.insert(Viking::new("Olaf", "Denmark"), 24); -/// vikings.insert(Viking::new("Harald", "Iceland"), 12); -/// -/// // Use derived implementation to print the status of the vikings. -/// for (viking, health) in vikings.iter() { -/// println!("{:?} has {} hp", viking, health); -/// } -/// ``` -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct HashMap { - // All hashes are keyed on these values, to prevent hash collision attacks. - hash_state: S, - - table: RawTable, - - resize_policy: DefaultResizePolicy, -} - -/// Search for a pre-hashed key. -fn search_hashed(table: M, - hash: SafeHash, - mut is_match: F) - -> SearchResult where - M: Deref>, - F: FnMut(&K) -> bool, -{ - let size = table.size(); - let mut probe = Bucket::new(table, hash); - let ib = probe.index(); - - while probe.index() != ib + size { - let full = match probe.peek() { - Empty(b) => return TableRef(b.into_table()), // hit an empty bucket - Full(b) => b - }; - - if full.distance() + ib < full.index() { - // We can finish the search early if we hit any bucket - // with a lower distance to initial bucket than we've probed. - return TableRef(full.into_table()); - } - - // If the hash doesn't match, it can't be this one.. - if hash == full.hash() { - // If the key doesn't match, it can't be this one.. - if is_match(full.read().0) { - return FoundExisting(full); - } - } - - probe = full.next(); - } - - TableRef(probe.into_table()) -} - -fn pop_internal(starting_bucket: FullBucketMut) -> (K, V) { - let (empty, retkey, retval) = starting_bucket.take(); - let mut gap = match empty.gap_peek() { - Some(b) => b, - None => return (retkey, retval) - }; - - while gap.full().distance() != 0 { - gap = match gap.shift() { - Some(b) => b, - None => break - }; - } - - // Now we've done all our shifting. Return the value we grabbed earlier. - (retkey, retval) -} - -/// Perform robin hood bucket stealing at the given `bucket`. You must -/// also pass the position of that bucket's initial bucket so we don't have -/// to recalculate it. -/// -/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable. -fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>, - mut ib: usize, - mut hash: SafeHash, - mut k: K, - mut v: V) - -> &'a mut V { - let starting_index = bucket.index(); - let size = { - let table = bucket.table(); // FIXME "lifetime too short". - table.size() - }; - // There can be at most `size - dib` buckets to displace, because - // in the worst case, there are `size` elements and we already are - // `distance` buckets away from the initial one. - let idx_end = starting_index + size - bucket.distance(); - - loop { - let (old_hash, old_key, old_val) = bucket.replace(hash, k, v); - loop { - let probe = bucket.next(); - assert!(probe.index() != idx_end); - - let full_bucket = match probe.peek() { - Empty(bucket) => { - // Found a hole! - let b = bucket.put(old_hash, old_key, old_val); - // Now that it's stolen, just read the value's pointer - // right out of the table! - return Bucket::at_index(b.into_table(), starting_index) - .peek() - .expect_full() - .into_mut_refs() - .1; - }, - Full(bucket) => bucket - }; - - let probe_ib = full_bucket.index() - full_bucket.distance(); - - bucket = full_bucket; - - // Robin hood! Steal the spot. - if ib < probe_ib { - ib = probe_ib; - hash = old_hash; - k = old_key; - v = old_val; - break; - } - } - } -} - -/// A result that works like Option> but preserves -/// the reference that grants us access to the table in any case. -enum SearchResult { - // This is an entry that holds the given key: - FoundExisting(FullBucket), - - // There was no such entry. The reference is given back: - TableRef(M) -} - -impl SearchResult { - fn into_option(self) -> Option> { - match self { - FoundExisting(bucket) => Some(bucket), - TableRef(_) => None - } - } -} - -impl HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - fn make_hash(&self, x: &X) -> SafeHash where X: Hash { - table::make_hash(&self.hash_state, x) - } - - /// Search for a key, yielding the index if it's found in the hashtable. - /// If you already have the hash for the key lying around, use - /// search_hashed. - fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option> - where K: Borrow, Q: Eq + Hash - { - let hash = self.make_hash(q); - search_hashed(&self.table, hash, |k| q.eq(k.borrow())) - .into_option() - } - - fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option> - where K: Borrow, Q: Eq + Hash - { - let hash = self.make_hash(q); - search_hashed(&mut self.table, hash, |k| q.eq(k.borrow())) - .into_option() - } - - // The caller should ensure that invariants by Robin Hood Hashing hold. - fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) { - let cap = self.table.capacity(); - let mut buckets = Bucket::new(&mut self.table, hash); - let ib = buckets.index(); - - while buckets.index() != ib + cap { - // We don't need to compare hashes for value swap. - // Not even DIBs for Robin Hood. - buckets = match buckets.peek() { - Empty(empty) => { - empty.put(hash, k, v); - return; - } - Full(b) => b.into_bucket() - }; - buckets.next(); - } - panic!("Internal HashMap error: Out of space."); - } -} - -impl + Eq, V> HashMap { - /// Create an empty HashMap. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::new(); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> HashMap { - Default::default() - } - - /// Creates an empty hash map with the given initial capacity. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> HashMap { - HashMap::with_capacity_and_hash_state(capacity, Default::default()) - } -} - -impl HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - /// Creates an empty hashmap which will use the given hasher to hash keys. - /// - /// The creates map has the default initial capacity. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// let mut map = HashMap::with_hash_state(s); - /// map.insert(1, 2); - /// ``` - #[inline] - #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] - pub fn with_hash_state(hash_state: S) -> HashMap { - HashMap { - hash_state: hash_state, - resize_policy: DefaultResizePolicy::new(), - table: RawTable::new(0), - } - } - - /// Create an empty HashMap with space for at least `capacity` - /// elements, using `hasher` to hash the keys. - /// - /// Warning: `hasher` is normally randomly generated, and - /// is designed to allow HashMaps to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// let mut map = HashMap::with_capacity_and_hash_state(10, s); - /// map.insert(1, 2); - /// ``` - #[inline] - #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] - pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S) - -> HashMap { - let resize_policy = DefaultResizePolicy::new(); - let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity)); - let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow"); - assert!(internal_cap >= capacity, "capacity overflow"); - HashMap { - hash_state: hash_state, - resize_policy: resize_policy, - table: RawTable::new(internal_cap), - } - } - - /// Returns the number of elements the map can hold without reallocating. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let map: HashMap = HashMap::with_capacity(100); - /// assert!(map.capacity() >= 100); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { - self.resize_policy.usable_capacity(self.table.capacity()) - } - - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashMap`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new allocation size overflows `usize`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::new(); - /// map.reserve(10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn reserve(&mut self, additional: usize) { - let new_size = self.len().checked_add(additional).expect("capacity overflow"); - let min_cap = self.resize_policy.min_capacity(new_size); - - // An invalid value shouldn't make us run out of space. This includes - // an overflow check. - assert!(new_size <= min_cap); - - if self.table.capacity() < min_cap { - let new_capacity = max(min_cap.next_power_of_two(), INITIAL_CAPACITY); - self.resize(new_capacity); - } - } - - /// Resizes the internal vectors to a new capacity. It's your responsibility to: - /// 1) Make sure the new capacity is enough for all the elements, accounting - /// for the load factor. - /// 2) Ensure new_capacity is a power of two or zero. - fn resize(&mut self, new_capacity: usize) { - assert!(self.table.size() <= new_capacity); - assert!(new_capacity.is_power_of_two() || new_capacity == 0); - - let mut old_table = replace(&mut self.table, RawTable::new(new_capacity)); - let old_size = old_table.size(); - - if old_table.capacity() == 0 || old_table.size() == 0 { - return; - } - - // Grow the table. - // Specialization of the other branch. - let mut bucket = Bucket::first(&mut old_table); - - // "So a few of the first shall be last: for many be called, - // but few chosen." - // - // We'll most likely encounter a few buckets at the beginning that - // have their initial buckets near the end of the table. They were - // placed at the beginning as the probe wrapped around the table - // during insertion. We must skip forward to a bucket that won't - // get reinserted too early and won't unfairly steal others spot. - // This eliminates the need for robin hood. - loop { - bucket = match bucket.peek() { - Full(full) => { - if full.distance() == 0 { - // This bucket occupies its ideal spot. - // It indicates the start of another "cluster". - bucket = full.into_bucket(); - break; - } - // Leaving this bucket in the last cluster for later. - full.into_bucket() - } - Empty(b) => { - // Encountered a hole between clusters. - b.into_bucket() - } - }; - bucket.next(); - } - - // This is how the buckets might be laid out in memory: - // ($ marks an initialized bucket) - // ________________ - // |$$$_$$$$$$_$$$$$| - // - // But we've skipped the entire initial cluster of buckets - // and will continue iteration in this order: - // ________________ - // |$$$$$$_$$$$$ - // ^ wrap around once end is reached - // ________________ - // $$$_____________| - // ^ exit once table.size == 0 - loop { - bucket = match bucket.peek() { - Full(bucket) => { - let h = bucket.hash(); - let (b, k, v) = bucket.take(); - self.insert_hashed_ordered(h, k, v); - { - let t = b.table(); // FIXME "lifetime too short". - if t.size() == 0 { break } - }; - b.into_bucket() - } - Empty(b) => b.into_bucket() - }; - bucket.next(); - } - - assert_eq!(self.table.size(), old_size); - } - - /// Shrinks the capacity of the map as much as possible. It will drop - /// down as much as possible while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map: HashMap = HashMap::with_capacity(100); - /// map.insert(1, 2); - /// map.insert(3, 4); - /// assert!(map.capacity() >= 100); - /// map.shrink_to_fit(); - /// assert!(map.capacity() >= 2); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn shrink_to_fit(&mut self) { - let min_capacity = self.resize_policy.min_capacity(self.len()); - let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY); - - // An invalid value shouldn't make us run out of space. - debug_assert!(self.len() <= min_capacity); - - if self.table.capacity() != min_capacity { - let old_table = replace(&mut self.table, RawTable::new(min_capacity)); - let old_size = old_table.size(); - - // Shrink the table. Naive algorithm for resizing: - for (h, k, v) in old_table.into_iter() { - self.insert_hashed_nocheck(h, k, v); - } - - debug_assert_eq!(self.table.size(), old_size); - } - } - - /// Insert a pre-hashed key-value pair, without first checking - /// that there's enough room in the buckets. Returns a reference to the - /// newly insert value. - /// - /// If the key already exists, the hashtable will be returned untouched - /// and a reference to the existing element will be returned. - fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> &mut V { - self.insert_or_replace_with(hash, k, v, |_, _, _| ()) - } - - fn insert_or_replace_with<'a, F>(&'a mut self, - hash: SafeHash, - k: K, - v: V, - mut found_existing: F) - -> &'a mut V where - F: FnMut(&mut K, &mut V, V), - { - // Worst case, we'll find one empty bucket among `size + 1` buckets. - let size = self.table.size(); - let mut probe = Bucket::new(&mut self.table, hash); - let ib = probe.index(); - - loop { - let mut bucket = match probe.peek() { - Empty(bucket) => { - // Found a hole! - return bucket.put(hash, k, v).into_mut_refs().1; - } - Full(bucket) => bucket - }; - - // hash matches? - if bucket.hash() == hash { - // key matches? - if k == *bucket.read_mut().0 { - let (bucket_k, bucket_v) = bucket.into_mut_refs(); - debug_assert!(k == *bucket_k); - // Key already exists. Get its reference. - found_existing(bucket_k, bucket_v, v); - return bucket_v; - } - } - - let robin_ib = bucket.index() as int - bucket.distance() as int; - - if (ib as int) < robin_ib { - // Found a luckier bucket than me. Better steal his spot. - return robin_hood(bucket, robin_ib as usize, hash, k, v); - } - - probe = bucket.next(); - assert!(probe.index() != ib + size + 1); - } - } - - /// An iterator visiting all keys in arbitrary order. - /// Iterator element type is `&'a K`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for key in map.keys() { - /// println!("{}", key); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { - fn first((a, _): (A, B)) -> A { a } - let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr - - Keys { inner: self.iter().map(first) } - } - - /// An iterator visiting all values in arbitrary order. - /// Iterator element type is `&'a V`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for val in map.values() { - /// println!("{}", val); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn values<'a>(&'a self) -> Values<'a, K, V> { - fn second((_, b): (A, B)) -> B { b } - let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr - - Values { inner: self.iter().map(second) } - } - - /// An iterator visiting all key-value pairs in arbitrary order. - /// Iterator element type is `(&'a K, &'a V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter { - Iter { inner: self.table.iter() } - } - - /// An iterator visiting all key-value pairs in arbitrary order, - /// with mutable references to the values. - /// Iterator element type is `(&'a K, &'a mut V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Update all values - /// for (_, val) in map.iter_mut() { - /// *val *= 2; - /// } - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter_mut(&mut self) -> IterMut { - IterMut { inner: self.table.iter_mut() } - } - - /// Creates a consuming iterator, that is, one that moves each key-value - /// pair out of the map in arbitrary order. The map cannot be used after - /// calling this. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Not possible with .iter() - /// let vec: Vec<(&str, int)> = map.into_iter().collect(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } - let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; - - IntoIter { - inner: self.table.into_iter().map(last_two) - } - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry { - // Gotta resize now. - self.reserve(1); - - let hash = self.make_hash(&key); - search_entry_hashed(&mut self.table, hash, key) - } - - /// Returns the number of elements in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn len(&self) -> usize { self.table.size() } - - /// Returns true if the map contains no elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the map, returning all key-value pairs as an iterator. Keeps the - /// allocated memory for reuse. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.insert(2, "b"); - /// - /// for (k, v) in a.drain().take(1) { - /// assert!(k == 1 || k == 2); - /// assert!(v == "a" || v == "b"); - /// } - /// - /// assert!(a.is_empty()); - /// ``` - #[inline] - #[unstable(feature = "std_misc", - reason = "matches collection reform specification, waiting for dust to settle")] - pub fn drain(&mut self) -> Drain { - fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } - let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer - - Drain { - inner: self.table.drain().map(last_two), - } - } - - /// Clears the map, removing all key-value pairs. Keeps the allocated memory - /// for reuse. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn clear(&mut self) { - self.drain(); - } - - /// Returns a reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// `Hash` and `Eq` on the borrowed form *must* match those for - /// the key type. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.get(&1), Some(&"a")); - /// assert_eq!(map.get(&2), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self, k: &Q) -> Option<&V> - where K: Borrow, Q: Hash + Eq - { - self.search(k).map(|bucket| bucket.into_refs().1) - } - - /// Returns true if the map contains a value for the specified key. - /// - /// The key may be any borrowed form of the map's key type, but - /// `Hash` and `Eq` on the borrowed form *must* match those for - /// the key type. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains_key(&self, k: &Q) -> bool - where K: Borrow, Q: Hash + Eq - { - self.search(k).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// `Hash` and `Eq` on the borrowed form *must* match those for - /// the key type. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// match map.get_mut(&1) { - /// Some(x) => *x = "b", - /// None => (), - /// } - /// assert_eq!(map[1], "b"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> - where K: Borrow, Q: Hash + Eq - { - self.search_mut(k).map(|bucket| bucket.into_mut_refs().1) - } - - /// Inserts a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise, `None` is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.insert(37, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.insert(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, k: K, v: V) -> Option { - let hash = self.make_hash(&k); - self.reserve(1); - - let mut retval = None; - self.insert_or_replace_with(hash, k, v, |_, val_ref, val| { - retval = Some(replace(val_ref, val)); - }); - retval - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - /// - /// The key may be any borrowed form of the map's key type, but - /// `Hash` and `Eq` on the borrowed form *must* match those for - /// the key type. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.remove(&1), Some("a")); - /// assert_eq!(map.remove(&1), None); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, k: &Q) -> Option - where K: Borrow, Q: Hash + Eq - { - if self.table.size() == 0 { - return None - } - - self.search_mut(k).map(|bucket| pop_internal(bucket).1) - } -} - -fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHash, k: K) - -> Entry<'a, K, V> -{ - // Worst case, we'll find one empty bucket among `size + 1` buckets. - let size = table.size(); - let mut probe = Bucket::new(table, hash); - let ib = probe.index(); - - loop { - let bucket = match probe.peek() { - Empty(bucket) => { - // Found a hole! - return Vacant(VacantEntry { - hash: hash, - key: k, - elem: NoElem(bucket), - }); - }, - Full(bucket) => bucket - }; - - // hash matches? - if bucket.hash() == hash { - // key matches? - if k == *bucket.read().0 { - return Occupied(OccupiedEntry{ - elem: bucket, - }); - } - } - - let robin_ib = bucket.index() as int - bucket.distance() as int; - - if (ib as int) < robin_ib { - // Found a luckier bucket than me. Better steal his spot. - return Vacant(VacantEntry { - hash: hash, - key: k, - elem: NeqElem(bucket, robin_ib as usize), - }); - } - - probe = bucket.next(); - assert!(probe.index() != ib + size + 1); - } -} - -impl PartialEq for HashMap - where K: Eq + Hash, V: PartialEq, - S: HashState, - H: hash::Hasher -{ - fn eq(&self, other: &HashMap) -> bool { - if self.len() != other.len() { return false; } - - self.iter().all(|(key, value)| - other.get(key).map_or(false, |v| *value == *v) - ) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for HashMap - where K: Eq + Hash, V: Eq, - S: HashState, - H: hash::Hasher -{} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Debug for HashMap - where K: Eq + Hash + Debug, V: Debug, - S: HashState, - H: hash::Hasher -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "HashMap {{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}: {:?}", *k, *v)); - } - - write!(f, "}}") - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for HashMap - where K: Eq + Hash, - S: HashState + Default, - H: hash::Hasher -{ - fn default() -> HashMap { - HashMap::with_hash_state(Default::default()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Index for HashMap - where K: Eq + Hash + Borrow, - Q: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Output = V; - - #[inline] - fn index<'a>(&'a self, index: &Q) -> &'a V { - self.get(index).expect("no entry found for key") - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for HashMap - where K: Eq + Hash + Borrow, - Q: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - #[inline] - fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V { - self.get_mut(index).expect("no entry found for key") - } -} - -/// HashMap iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Iter<'a, K: 'a, V: 'a> { - inner: table::Iter<'a, K, V> -} - -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -impl<'a, K, V> Clone for Iter<'a, K, V> { - fn clone(&self) -> Iter<'a, K, V> { - Iter { - inner: self.inner.clone() - } - } -} - -/// HashMap mutable values iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IterMut<'a, K: 'a, V: 'a> { - inner: table::IterMut<'a, K, V> -} - -/// HashMap move iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { - inner: iter::Map, fn((SafeHash, K, V)) -> (K, V)> -} - -/// HashMap keys iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Keys<'a, K: 'a, V: 'a> { - inner: Map, fn((&'a K, &'a V)) -> &'a K> -} - -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -impl<'a, K, V> Clone for Keys<'a, K, V> { - fn clone(&self) -> Keys<'a, K, V> { - Keys { - inner: self.inner.clone() - } - } -} - -/// HashMap values iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Values<'a, K: 'a, V: 'a> { - inner: Map, fn((&'a K, &'a V)) -> &'a V> -} - -// FIXME(#19839) Remove in favor of `#[derive(Clone)]` -impl<'a, K, V> Clone for Values<'a, K, V> { - fn clone(&self) -> Values<'a, K, V> { - Values { - inner: self.inner.clone() - } - } -} - -/// HashMap drain iterator. -#[unstable(feature = "std_misc", - reason = "matches collection reform specification, waiting for dust to settle")] -pub struct Drain<'a, K: 'a, V: 'a> { - inner: iter::Map, fn((SafeHash, K, V)) -> (K, V)> -} - -/// A view into a single occupied location in a HashMap. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] -pub struct OccupiedEntry<'a, K: 'a, V: 'a> { - elem: FullBucket>, -} - -/// A view into a single empty location in a HashMap. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] -pub struct VacantEntry<'a, K: 'a, V: 'a> { - hash: SafeHash, - key: K, - elem: VacantEntryState>, -} - -/// A view into a single location in a map, which may be vacant or occupied. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] -pub enum Entry<'a, K: 'a, V: 'a> { - /// An occupied Entry. - Occupied(OccupiedEntry<'a, K, V>), - /// A vacant Entry. - Vacant(VacantEntry<'a, K, V>), -} - -/// Possible states of a VacantEntry. -enum VacantEntryState { - /// The index is occupied, but the key to insert has precedence, - /// and will kick the current one out on insertion. - NeqElem(FullBucket, usize), - /// The index is genuinely vacant. - NoElem(EmptyBucket), -} - -impl<'a, K, V, S, H> IntoIterator for &'a HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - - fn into_iter(self) -> Iter<'a, K, V> { - self.iter() - } -} - -impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = (&'a K, &'a mut V); - type IntoIter = IterMut<'a, K, V>; - - fn into_iter(mut self) -> IterMut<'a, K, V> { - self.iter_mut() - } -} - -impl IntoIterator for HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = (K, V); - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - self.into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Iterator for Iter<'a, K, V> { - type Item = (&'a K, &'a V); - - #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { - #[inline] fn len(&self) -> usize { self.inner.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Iterator for IterMut<'a, K, V> { - type Item = (&'a K, &'a mut V); - - #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { - #[inline] fn len(&self) -> usize { self.inner.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = (K, V); - - #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { - #[inline] fn len(&self) -> usize { self.inner.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Iterator for Keys<'a, K, V> { - type Item = &'a K; - - #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { - #[inline] fn len(&self) -> usize { self.inner.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Iterator for Values<'a, K, V> { - type Item = &'a V; - - #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { - #[inline] fn len(&self) -> usize { self.inner.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> Iterator for Drain<'a, K, V> { - type Item = (K, V); - - #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() } - #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { - #[inline] fn len(&self) -> usize { self.inner.len() } -} - -#[unstable(feature = "std_misc", - reason = "matches collection reform v2 specification, waiting for dust to settle")] -impl<'a, K, V> Entry<'a, K, V> { - /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant. - pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { - match self { - Occupied(entry) => Ok(entry.into_mut()), - Vacant(entry) => Err(entry), - } - } -} - -impl<'a, K, V> OccupiedEntry<'a, K, V> { - /// Gets a reference to the value in the entry. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self) -> &V { - self.elem.read().1 - } - - /// Gets a mutable reference to the value in the entry. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_mut(&mut self) -> &mut V { - self.elem.read_mut().1 - } - - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_mut(self) -> &'a mut V { - self.elem.into_mut_refs().1 - } - - /// Sets the value of the entry, and returns the entry's old value - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, mut value: V) -> V { - let old_value = self.get_mut(); - mem::swap(&mut value, old_value); - value - } - - /// Takes the value out of the entry, and returns it - #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(self) -> V { - pop_internal(self.elem).1 - } -} - -impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(self, value: V) -> &'a mut V { - match self.elem { - NeqElem(bucket, ib) => { - robin_hood(bucket, ib, self.hash, self.key, value) - } - NoElem(bucket) => { - bucket.put(self.hash, self.key, value).into_mut_refs().1 - } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator<(K, V)> for HashMap - where K: Eq + Hash, - S: HashState + Default, - H: hash::Hasher -{ - fn from_iter>(iter: T) -> HashMap { - let iter = iter.into_iter(); - let lower = iter.size_hint().0; - let mut map = HashMap::with_capacity_and_hash_state(lower, - Default::default()); - map.extend(iter); - map - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Extend<(K, V)> for HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - fn extend>(&mut self, iter: T) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - - -/// `RandomState` is the default state for `HashMap` types. -/// -/// A particular instance `RandomState` will create the same instances of -/// `Hasher`, but the hashers created by two different `RandomState` -/// instances are unlikely to produce the same result for the same values. -#[derive(Clone)] -#[unstable(feature = "std_misc", - reason = "hashing an hash maps may be altered")] -pub struct RandomState { - k0: u64, - k1: u64, -} - -#[unstable(feature = "std_misc", - reason = "hashing an hash maps may be altered")] -impl RandomState { - /// Construct a new `RandomState` that is initialized with random keys. - #[inline] - #[allow(deprecated)] - pub fn new() -> RandomState { - let mut r = rand::thread_rng(); - RandomState { k0: r.gen(), k1: r.gen() } - } -} - -#[unstable(feature = "std_misc", - reason = "hashing an hash maps may be altered")] -impl HashState for RandomState { - type Hasher = Hasher; - fn hasher(&self) -> Hasher { - Hasher { inner: SipHasher::new_with_keys(self.k0, self.k1) } - } -} - -#[unstable(feature = "std_misc", - reason = "hashing an hash maps may be altered")] -impl Default for RandomState { - #[inline] - fn default() -> RandomState { - RandomState::new() - } -} - -/// A hasher implementation which is generated from `RandomState` instances. -/// -/// This is the default hasher used in a `HashMap` to hash keys. Types do not -/// typically declare an ability to explicitly hash into this particular type, -/// but rather in a `H: hash::Writer` type parameter. -#[unstable(feature = "std_misc", - reason = "hashing an hash maps may be altered")] -pub struct Hasher { inner: SipHasher } - -impl hash::Writer for Hasher { - fn write(&mut self, data: &[u8]) { - hash::Writer::write(&mut self.inner, data) - } -} - -impl hash::Hasher for Hasher { - type Output = u64; - fn reset(&mut self) { hash::Hasher::reset(&mut self.inner) } - fn finish(&self) -> u64 { self.inner.finish() } -} - -#[cfg(test)] -mod test_map { - use prelude::v1::*; - - use super::HashMap; - use super::Entry::{Occupied, Vacant}; - use iter::{range_inclusive, range_step_inclusive, repeat}; - use cell::RefCell; - use rand::{weak_rng, Rng}; - - #[test] - fn test_create_capacity_zero() { - let mut m = HashMap::with_capacity(0); - - assert!(m.insert(1, 1).is_none()); - - assert!(m.contains_key(&1)); - assert!(!m.contains_key(&0)); - } - - #[test] - fn test_insert() { - let mut m = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1, 2).is_none()); - assert_eq!(m.len(), 1); - assert!(m.insert(2, 4).is_none()); - assert_eq!(m.len(), 2); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&2).unwrap(), 4); - } - - thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } - - #[derive(Hash, PartialEq, Eq)] - struct Dropable { - k: usize - } - - impl Dropable { - fn new(k: usize) -> Dropable { - DROP_VECTOR.with(|slot| { - slot.borrow_mut()[k] += 1; - }); - - Dropable { k: k } - } - } - - impl Drop for Dropable { - fn drop(&mut self) { - DROP_VECTOR.with(|slot| { - slot.borrow_mut()[self.k] -= 1; - }); - } - } - - impl Clone for Dropable { - fn clone(&self) -> Dropable { - Dropable::new(self.k) - } - } - - #[test] - fn test_drops() { - DROP_VECTOR.with(|slot| { - *slot.borrow_mut() = repeat(0).take(200).collect(); - }); - - { - let mut m = HashMap::new(); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - - for i in 0..100 { - let d1 = Dropable::new(i); - let d2 = Dropable::new(i+100); - m.insert(d1, d2); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - for i in 0..50 { - let k = Dropable::new(i); - let v = m.remove(&k); - - assert!(v.is_some()); - - DROP_VECTOR.with(|v| { - assert_eq!(v.borrow()[i], 1); - assert_eq!(v.borrow()[i+100], 1); - }); - } - - DROP_VECTOR.with(|v| { - for i in 0..50 { - assert_eq!(v.borrow()[i], 0); - assert_eq!(v.borrow()[i+100], 0); - } - - for i in 50..100 { - assert_eq!(v.borrow()[i], 1); - assert_eq!(v.borrow()[i+100], 1); - } - }); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - } - - #[test] - fn test_move_iter_drops() { - DROP_VECTOR.with(|v| { - *v.borrow_mut() = repeat(0).take(200).collect(); - }); - - let hm = { - let mut hm = HashMap::new(); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - - for i in 0..100 { - let d1 = Dropable::new(i); - let d2 = Dropable::new(i+100); - hm.insert(d1, d2); - } - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - { - let mut half = hm.into_iter().take(50); - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 1); - } - }); - - for _ in half.by_ref() {} - - DROP_VECTOR.with(|v| { - let nk = (0..100).filter(|&i| { - v.borrow()[i] == 1 - }).count(); - - let nv = (0..100).filter(|&i| { - v.borrow()[i+100] == 1 - }).count(); - - assert_eq!(nk, 50); - assert_eq!(nv, 50); - }); - }; - - DROP_VECTOR.with(|v| { - for i in 0..200 { - assert_eq!(v.borrow()[i], 0); - } - }); - } - - #[test] - fn test_empty_pop() { - let mut m: HashMap = HashMap::new(); - assert_eq!(m.remove(&0), None); - } - - #[test] - fn test_lots_of_insertions() { - let mut m = HashMap::new(); - - // Try this a few times to make sure we never screw up the hashmap's - // internal state. - for _ in 0..10 { - assert!(m.is_empty()); - - for i in range_inclusive(1, 1000) { - assert!(m.insert(i, i).is_none()); - - for j in range_inclusive(1, i) { - let r = m.get(&j); - assert_eq!(r, Some(&j)); - } - - for j in range_inclusive(i+1, 1000) { - let r = m.get(&j); - assert_eq!(r, None); - } - } - - for i in range_inclusive(1001, 2000) { - assert!(!m.contains_key(&i)); - } - - // remove forwards - for i in range_inclusive(1, 1000) { - assert!(m.remove(&i).is_some()); - - for j in range_inclusive(1, i) { - assert!(!m.contains_key(&j)); - } - - for j in range_inclusive(i+1, 1000) { - assert!(m.contains_key(&j)); - } - } - - for i in range_inclusive(1, 1000) { - assert!(!m.contains_key(&i)); - } - - for i in range_inclusive(1, 1000) { - assert!(m.insert(i, i).is_none()); - } - - // remove backwards - for i in range_step_inclusive(1000, 1, -1) { - assert!(m.remove(&i).is_some()); - - for j in range_inclusive(i, 1000) { - assert!(!m.contains_key(&j)); - } - - for j in range_inclusive(1, i-1) { - assert!(m.contains_key(&j)); - } - } - } - } - - #[test] - fn test_find_mut() { - let mut m = HashMap::new(); - assert!(m.insert(1, 12).is_none()); - assert!(m.insert(2, 8).is_none()); - assert!(m.insert(5, 14).is_none()); - let new = 100; - match m.get_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.get(&5), Some(&new)); - } - - #[test] - fn test_insert_overwrite() { - let mut m = HashMap::new(); - assert!(m.insert(1, 2).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert!(!m.insert(1, 3).is_none()); - assert_eq!(*m.get(&1).unwrap(), 3); - } - - #[test] - fn test_insert_conflicts() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert!(m.insert(5, 3).is_none()); - assert!(m.insert(9, 4).is_none()); - assert_eq!(*m.get(&9).unwrap(), 4); - assert_eq!(*m.get(&5).unwrap(), 3); - assert_eq!(*m.get(&1).unwrap(), 2); - } - - #[test] - fn test_conflict_remove() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert!(m.insert(5, 3).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&5).unwrap(), 3); - assert!(m.insert(9, 4).is_none()); - assert_eq!(*m.get(&1).unwrap(), 2); - assert_eq!(*m.get(&5).unwrap(), 3); - assert_eq!(*m.get(&9).unwrap(), 4); - assert!(m.remove(&1).is_some()); - assert_eq!(*m.get(&9).unwrap(), 4); - assert_eq!(*m.get(&5).unwrap(), 3); - } - - #[test] - fn test_is_empty() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1, 2).is_none()); - assert!(!m.is_empty()); - assert!(m.remove(&1).is_some()); - assert!(m.is_empty()); - } - - #[test] - fn test_pop() { - let mut m = HashMap::new(); - m.insert(1, 2); - assert_eq!(m.remove(&1), Some(2)); - assert_eq!(m.remove(&1), None); - } - - #[test] - fn test_iterate() { - let mut m = HashMap::with_capacity(4); - for i in 0..32 { - assert!(m.insert(i, i*2).is_none()); - } - assert_eq!(m.len(), 32); - - let mut observed: u32 = 0; - - for (k, v) in &m { - assert_eq!(*v, *k * 2); - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let keys: Vec<_> = map.keys().cloned().collect(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map: HashMap<_, _> = vec.into_iter().collect(); - let values: Vec<_> = map.values().cloned().collect(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_find() { - let mut m = HashMap::new(); - assert!(m.get(&1).is_none()); - m.insert(1, 2); - match m.get(&1) { - None => panic!(), - Some(v) => assert_eq!(*v, 2) - } - } - - #[test] - fn test_eq() { - let mut m1 = HashMap::new(); - m1.insert(1, 2); - m1.insert(2, 3); - m1.insert(3, 4); - - let mut m2 = HashMap::new(); - m2.insert(1, 2); - m2.insert(2, 3); - - assert!(m1 != m2); - - m2.insert(3, 4); - - assert_eq!(m1, m2); - } - - #[test] - fn test_show() { - let mut map = HashMap::new(); - let empty: HashMap = HashMap::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{:?}", map); - - assert!(map_str == "HashMap {1: 2, 3: 4}" || - map_str == "HashMap {3: 4, 1: 2}"); - assert_eq!(format!("{:?}", empty), "HashMap {}"); - } - - #[test] - fn test_expand() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - - let mut i = 0; - let old_cap = m.table.capacity(); - while old_cap == m.table.capacity() { - m.insert(i, i); - i += 1; - } - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - } - - #[test] - fn test_behavior_resize_policy() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert_eq!(m.table.capacity(), 0); - assert!(m.is_empty()); - - m.insert(0, 0); - m.remove(&0); - assert!(m.is_empty()); - let initial_cap = m.table.capacity(); - m.reserve(initial_cap); - let cap = m.table.capacity(); - - assert_eq!(cap, initial_cap * 2); - - let mut i = 0; - for _ in 0..cap * 3 / 4 { - m.insert(i, i); - i += 1; - } - // three quarters full - - assert_eq!(m.len(), i); - assert_eq!(m.table.capacity(), cap); - - for _ in 0..cap / 4 { - m.insert(i, i); - i += 1; - } - // half full - - let new_cap = m.table.capacity(); - assert_eq!(new_cap, cap * 2); - - for _ in 0..cap / 2 - 1 { - i -= 1; - m.remove(&i); - assert_eq!(m.table.capacity(), new_cap); - } - // A little more than one quarter full. - m.shrink_to_fit(); - assert_eq!(m.table.capacity(), cap); - // again, a little more than half full - for _ in 0..cap / 2 - 1 { - i -= 1; - m.remove(&i); - } - m.shrink_to_fit(); - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - assert_eq!(m.table.capacity(), initial_cap); - } - - #[test] - fn test_reserve_shrink_to_fit() { - let mut m = HashMap::new(); - m.insert(0, 0); - m.remove(&0); - assert!(m.capacity() >= m.len()); - for i in 0..128 { - m.insert(i, i); - } - m.reserve(256); - - let usable_cap = m.capacity(); - for i in 128..(128 + 256) { - m.insert(i, i); - assert_eq!(m.capacity(), usable_cap); - } - - for i in 100..(128 + 256) { - assert_eq!(m.remove(&i), Some(i)); - } - m.shrink_to_fit(); - - assert_eq!(m.len(), 100); - assert!(!m.is_empty()); - assert!(m.capacity() >= m.len()); - - for i in 0..100 { - assert_eq!(m.remove(&i), Some(i)); - } - m.shrink_to_fit(); - m.insert(0, 0); - - assert_eq!(m.len(), 1); - assert!(m.capacity() >= m.len()); - assert_eq!(m.remove(&0), Some(0)); - } - - #[test] - fn test_from_iter() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().cloned().collect(); - - for &(k, v) in &xs { - assert_eq!(map.get(&k), Some(&v)); - } - } - - #[test] - fn test_size_hint() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_iter_len() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.len(), 3); - } - - #[test] - fn test_mut_size_hint() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_iter_mut_len() { - let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.len(), 3); - } - - #[test] - fn test_index() { - let mut map = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[2], 1); - } - - #[test] - #[should_fail] - fn test_index_nonexistent() { - let mut map = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } - - #[test] - fn test_entry(){ - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } - - #[test] - fn test_entry_take_doesnt_corrupt() { - // Test for #19292 - fn check(m: &HashMap) { - for k in m.keys() { - assert!(m.contains_key(k), - "{} is in keys() but not in the map?", k); - } - } - - let mut m = HashMap::new(); - let mut rng = weak_rng(); - - // Populate the map with some items. - for _ in 0..50 { - let x = rng.gen_range(-10, 10); - m.insert(x, ()); - } - - for i in 0..1000 { - let x = rng.gen_range(-10, 10); - match m.entry(x) { - Vacant(_) => {}, - Occupied(e) => { - println!("{}: remove {}", i, x); - e.remove(); - }, - } - - check(&m); - } - } -} diff --git a/src/libstd/collections/hash/mod.rs b/src/libstd/collections/hash/mod.rs index 39c1458b72..47e300af26 100644 --- a/src/libstd/collections/hash/mod.rs +++ b/src/libstd/collections/hash/mod.rs @@ -12,14 +12,6 @@ mod bench; mod table; -#[cfg(stage0)] -#[path = "map_stage0.rs"] pub mod map; -#[cfg(not(stage0))] -pub mod map; -#[cfg(stage0)] -#[path = "set_stage0.rs"] -pub mod set; -#[cfg(not(stage0))] pub mod set; pub mod state; diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index e0631a64d4..5fbc21797a 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -18,9 +18,7 @@ use default::Default; use fmt::Debug; use fmt; use hash::Hash; -use iter::{ - Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend, -}; +use iter::{Iterator, IntoIterator, ExactSizeIterator, FromIterator, Map, Chain, Extend}; use ops::{BitOr, BitAnd, BitXor, Sub}; use option::Option::{Some, None, self}; @@ -36,9 +34,24 @@ use super::state::HashState; /// An implementation of a hash set using the underlying representation of a /// HashMap where the value is (). As with the `HashMap` type, a `HashSet` -/// requires that the elements implement the `Eq` and `Hash` traits. +/// requires that the elements implement the `Eq` and `Hash` traits. This can +/// frequently be achieved by using `#[derive(Eq, Hash)]`. If you implement +/// these yourself, it is important that the following property holds: +/// +/// ```text +/// k1 == k2 -> hash(k1) == hash(k2) +/// ``` +/// +/// In other words, if two keys are equal, their hashes must be equal. /// -/// # Example +/// +/// It is a logic error for an item to be modified in such a way that the +/// item's hash, as determined by the `Hash` trait, or its equality, as +/// determined by the `Eq` trait, changes while it is in the set. This is +/// normally only possible through `Cell`, `RefCell`, global state, I/O, or +/// unsafe code. +/// +/// # Examples /// /// ``` /// use std::collections::HashSet; @@ -100,7 +113,7 @@ pub struct HashSet { impl HashSet { /// Create an empty HashSet. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -115,7 +128,7 @@ impl HashSet { /// Create an empty HashSet with space for at least `n` elements in /// the hash table. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -136,9 +149,10 @@ impl HashSet /// /// The hash set is also created with the default initial capacity. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(std_misc)] /// use std::collections::HashSet; /// use std::collections::hash_map::RandomState; /// @@ -160,9 +174,10 @@ impl HashSet /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(std_misc)] /// use std::collections::HashSet; /// use std::collections::hash_map::RandomState; /// @@ -181,7 +196,7 @@ impl HashSet /// Returns the number of elements the set can hold without reallocating. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -202,7 +217,7 @@ impl HashSet /// /// Panics if the new allocation size overflows `usize`. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -218,7 +233,7 @@ impl HashSet /// down as much as possible while maintaining the internal rules /// and possibly leaving some space in accordance with the resize policy. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -238,7 +253,7 @@ impl HashSet /// An iterator visiting all elements in arbitrary order. /// Iterator element type is &'a T. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -260,7 +275,7 @@ impl HashSet /// of the set in arbitrary order. The set cannot be used after calling /// this. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -286,9 +301,10 @@ impl HashSet /// Visit the values representing the difference. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); @@ -316,9 +332,10 @@ impl HashSet /// Visit the values representing the symmetric difference. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); @@ -342,9 +359,10 @@ impl HashSet /// Visit the values representing the intersection. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); @@ -367,9 +385,10 @@ impl HashSet /// Visit the values representing the union. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); @@ -389,7 +408,7 @@ impl HashSet /// Return the number of elements in the set /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -404,7 +423,7 @@ impl HashSet /// Returns true if the set contains no elements /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -430,7 +449,7 @@ impl HashSet /// Clears the set, removing all values. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -449,9 +468,10 @@ impl HashSet /// `Hash` and `Eq` on the borrowed form *must* match those for /// the value type. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); @@ -468,9 +488,10 @@ impl HashSet /// Returns `true` if the set has no elements in common with `other`. /// This is equivalent to checking for an empty intersection. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); @@ -489,9 +510,10 @@ impl HashSet /// Returns `true` if the set is a subset of another. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect(); @@ -510,9 +532,10 @@ impl HashSet /// Returns `true` if the set is a superset of another. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(core)] /// use std::collections::HashSet; /// /// let sub: HashSet<_> = [1, 2].iter().cloned().collect(); @@ -536,7 +559,7 @@ impl HashSet /// Adds a value to the set. Returns `true` if the value was not already /// present in the set. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -557,7 +580,7 @@ impl HashSet /// `Hash` and `Eq` on the borrowed form *must* match those for /// the value type. /// - /// # Example + /// # Examples /// /// ``` /// use std::collections::HashSet; @@ -598,14 +621,7 @@ impl fmt::Debug for HashSet S: HashState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "HashSet {{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *x)); - } - - write!(f, "}}") + self.iter().fold(f.debug_set(), |b, e| b.entry(e)).finish() } } @@ -847,6 +863,9 @@ impl IntoIterator for HashSet } } +impl<'a, K> Clone for Iter<'a, K> { + fn clone(&self) -> Iter<'a, K> { Iter { iter: self.iter.clone() } } +} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K> Iterator for Iter<'a, K> { type Item = &'a K; @@ -883,6 +902,12 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { fn len(&self) -> usize { self.iter.len() } } +impl<'a, T, S> Clone for Intersection<'a, T, S> { + fn clone(&self) -> Intersection<'a, T, S> { + Intersection { iter: self.iter.clone(), ..*self } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for Intersection<'a, T, S> where T: Eq + Hash, S: HashState @@ -906,6 +931,12 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } +impl<'a, T, S> Clone for Difference<'a, T, S> { + fn clone(&self) -> Difference<'a, T, S> { + Difference { iter: self.iter.clone(), ..*self } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for Difference<'a, T, S> where T: Eq + Hash, S: HashState @@ -929,6 +960,12 @@ impl<'a, T, S> Iterator for Difference<'a, T, S> } } +impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { + fn clone(&self) -> SymmetricDifference<'a, T, S> { + SymmetricDifference { iter: self.iter.clone() } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> where T: Eq + Hash, S: HashState @@ -939,6 +976,10 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } +impl<'a, T, S> Clone for Union<'a, T, S> { + fn clone(&self) -> Union<'a, T, S> { Union { iter: self.iter.clone() } } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for Union<'a, T, S> where T: Eq + Hash, S: HashState @@ -1151,7 +1192,7 @@ mod test_set { }; let v = hs.into_iter().collect::>(); - assert!(['a', 'b'] == v || ['b', 'a'] == v); + assert!(v == ['a', 'b'] || v == ['b', 'a']); } #[test] @@ -1186,8 +1227,8 @@ mod test_set { let set_str = format!("{:?}", set); - assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}"); - assert_eq!(format!("{:?}", empty), "HashSet {}"); + assert!(set_str == "{1, 2}" || set_str == "{2, 1}"); + assert_eq!(format!("{:?}", empty), "{}"); } #[test] diff --git a/src/libstd/collections/hash/set_stage0.rs b/src/libstd/collections/hash/set_stage0.rs deleted file mode 100644 index 68c9e02d8a..0000000000 --- a/src/libstd/collections/hash/set_stage0.rs +++ /dev/null @@ -1,1252 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15883 - -use borrow::Borrow; -use clone::Clone; -use cmp::{Eq, PartialEq}; -use core::marker::Sized; -use default::Default; -use fmt::Debug; -use fmt; -use hash::{self, Hash}; -use iter::{ - Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend, -}; -use ops::{BitOr, BitAnd, BitXor, Sub}; -use option::Option::{Some, None, self}; - -use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState, Hasher}; -use super::state::HashState; - -// Future Optimization (FIXME!) -// ============================= -// -// Iteration over zero sized values is a noop. There is no need -// for `bucket.val` in the case of HashSet. I suppose we would need HKT -// to get rid of it properly. - -/// An implementation of a hash set using the underlying representation of a -/// HashMap where the value is (). As with the `HashMap` type, a `HashSet` -/// requires that the elements implement the `Eq` and `Hash` traits. -/// -/// # Example -/// -/// ``` -/// use std::collections::HashSet; -/// // Type inference lets us omit an explicit type signature (which -/// // would be `HashSet<&str>` in this example). -/// let mut books = HashSet::new(); -/// -/// // Add some books. -/// books.insert("A Dance With Dragons"); -/// books.insert("To Kill a Mockingbird"); -/// books.insert("The Odyssey"); -/// books.insert("The Great Gatsby"); -/// -/// // Check for a specific one. -/// if !books.contains(&("The Winds of Winter")) { -/// println!("We have {} books, but The Winds of Winter ain't one.", -/// books.len()); -/// } -/// -/// // Remove a book. -/// books.remove(&"The Odyssey"); -/// -/// // Iterate over everything. -/// for book in books.iter() { -/// println!("{}", *book); -/// } -/// ``` -/// -/// The easiest way to use `HashSet` with a custom type is to derive -/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the -/// future be implied by `Eq`. -/// -/// ``` -/// use std::collections::HashSet; -/// #[derive(Hash, Eq, PartialEq, Debug)] -/// struct Viking<'a> { -/// name: &'a str, -/// power: usize, -/// } -/// -/// let mut vikings = HashSet::new(); -/// -/// vikings.insert(Viking { name: "Einar", power: 9 }); -/// vikings.insert(Viking { name: "Einar", power: 9 }); -/// vikings.insert(Viking { name: "Olaf", power: 4 }); -/// vikings.insert(Viking { name: "Harald", power: 8 }); -/// -/// // Use derived implementation to print the vikings. -/// for x in vikings.iter() { -/// println!("{:?}", x); -/// } -/// ``` -#[derive(Clone)] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct HashSet { - map: HashMap -} - -impl + Eq> HashSet { - /// Create an empty HashSet. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set: HashSet = HashSet::new(); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> HashSet { - HashSet::with_capacity(INITIAL_CAPACITY) - } - - /// Create an empty HashSet with space for at least `n` elements in - /// the hash table. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set: HashSet = HashSet::with_capacity(10); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> HashSet { - HashSet { map: HashMap::with_capacity(capacity) } - } -} - -impl HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - /// Creates a new empty hash set which will use the given hasher to hash - /// keys. - /// - /// The hash set is also created with the default initial capacity. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// let mut set = HashSet::with_hash_state(s); - /// set.insert(2); - /// ``` - #[inline] - #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] - pub fn with_hash_state(hash_state: S) -> HashSet { - HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state) - } - - /// Create an empty HashSet with space for at least `capacity` - /// elements in the hash table, using `hasher` to hash the keys. - /// - /// Warning: `hasher` is normally randomly generated, and - /// is designed to allow `HashSet`s to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// let mut set = HashSet::with_capacity_and_hash_state(10, s); - /// set.insert(1); - /// ``` - #[inline] - #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] - pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S) - -> HashSet { - HashSet { - map: HashMap::with_capacity_and_hash_state(capacity, hash_state), - } - } - - /// Returns the number of elements the set can hold without reallocating. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let set: HashSet = HashSet::with_capacity(100); - /// assert!(set.capacity() >= 100); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { - self.map.capacity() - } - - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashSet`. The collection may reserve more space to avoid - /// frequent reallocations. - /// - /// # Panics - /// - /// Panics if the new allocation size overflows `usize`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set: HashSet = HashSet::new(); - /// set.reserve(10); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn reserve(&mut self, additional: usize) { - self.map.reserve(additional) - } - - /// Shrinks the capacity of the set as much as possible. It will drop - /// down as much as possible while maintaining the internal rules - /// and possibly leaving some space in accordance with the resize policy. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut set: HashSet = HashSet::with_capacity(100); - /// set.insert(1); - /// set.insert(2); - /// assert!(set.capacity() >= 100); - /// set.shrink_to_fit(); - /// assert!(set.capacity() >= 2); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn shrink_to_fit(&mut self) { - self.map.shrink_to_fit() - } - - /// An iterator visiting all elements in arbitrary order. - /// Iterator element type is &'a T. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a"); - /// set.insert("b"); - /// - /// // Will print in an arbitrary order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter { - Iter { iter: self.map.keys() } - } - - /// Creates a consuming iterator, that is, one that moves each value out - /// of the set in arbitrary order. The set cannot be used after calling - /// this. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a".to_string()); - /// set.insert("b".to_string()); - /// - /// // Not possible to collect to a Vec with a regular `.iter()`. - /// let v: Vec = set.into_iter().collect(); - /// - /// // Will print in an arbitrary order. - /// for x in v.iter() { - /// println!("{}", x); - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_iter(self) -> IntoIter { - fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; - - IntoIter { iter: self.map.into_iter().map(first) } - } - - /// Visit the values representing the difference. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Can be seen as `a - b`. - /// for x in a.difference(&b) { - /// println!("{}", x); // Print 1 - /// } - /// - /// let diff: HashSet = a.difference(&b).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 = b.difference(&a).map(|&x| x).collect(); - /// assert_eq!(diff, [4].iter().map(|&x| x).collect()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn difference<'a>(&'a self, other: &'a HashSet) -> Difference<'a, T, S> { - Difference { - iter: self.iter(), - other: other, - } - } - - /// Visit the values representing the symmetric difference. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 1, 4 in arbitrary order. - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// - /// let diff1: HashSet = a.symmetric_difference(&b).map(|&x| x).collect(); - /// let diff2: HashSet = b.symmetric_difference(&a).map(|&x| x).collect(); - /// - /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1, 4].iter().map(|&x| x).collect()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet) - -> SymmetricDifference<'a, T, S> { - SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) } - } - - /// Visit the values representing the intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 2, 3 in arbitrary order. - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: HashSet = a.intersection(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn intersection<'a>(&'a self, other: &'a HashSet) -> Intersection<'a, T, S> { - Intersection { - iter: self.iter(), - other: other, - } - } - - /// Visit the values representing the union. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 1, 2, 3, 4 in arbitrary order. - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: HashSet = a.union(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1, 2, 3, 4].iter().map(|&x| x).collect()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn union<'a>(&'a self, other: &'a HashSet) -> Union<'a, T, S> { - Union { iter: self.iter().chain(other.difference(self)) } - } - - /// Return the number of elements in the set - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1); - /// assert_eq!(v.len(), 1); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn len(&self) -> usize { self.map.len() } - - /// Returns true if the set contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1); - /// assert!(!v.is_empty()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { self.map.len() == 0 } - - /// Clears the set, returning all elements in an iterator. - #[inline] - #[unstable(feature = "std_misc", - reason = "matches collection reform specification, waiting for dust to settle")] - pub fn drain(&mut self) -> Drain { - fn first((a, _): (A, B)) -> A { a } - let first: fn((T, ())) -> T = first; // coerce to fn pointer - - Drain { iter: self.map.drain().map(first) } - } - - /// Clears the set, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut v = HashSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { self.map.clear() } - - /// Returns `true` if the set contains a value. - /// - /// The value may be any borrowed form of the set's value type, but - /// `Hash` and `Eq` on the borrowed form *must* match those for - /// the value type. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains(&self, value: &Q) -> bool - where T: Borrow, Q: Hash + Eq - { - self.map.contains_key(value) - } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let mut b = HashSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_disjoint(&self, other: &HashSet) -> bool { - self.iter().all(|v| !other.contains(v)) - } - - /// Returns `true` if the set is a subset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_subset(&self, other: &HashSet) -> bool { - self.iter().all(|v| other.contains(v)) - } - - /// Returns `true` if the set is a superset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let sub: HashSet<_> = [1, 2].iter().cloned().collect(); - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_superset(&self, other: &HashSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.insert(2), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - /// - /// The value may be any borrowed form of the set's value type, but - /// `Hash` and `Eq` on the borrowed form *must* match those for - /// the value type. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// set.insert(2); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, value: &Q) -> bool - where T: Borrow, Q: Hash + Eq - { - self.map.remove(value).is_some() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - fn eq(&self, other: &HashSet) -> bool { - if self.len() != other.len() { return false; } - - self.iter().all(|key| other.contains(key)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for HashSet - where T: Eq + Hash + fmt::Debug, - S: HashState, - H: hash::Hasher -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "HashSet {{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *x)); - } - - write!(f, "}}") - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for HashSet - where T: Eq + Hash, - S: HashState + Default, - H: hash::Hasher -{ - fn from_iter>(iter: I) -> HashSet { - let iter = iter.into_iter(); - let lower = iter.size_hint().0; - let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default()); - set.extend(iter); - set - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Extend for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - fn extend>(&mut self, iter: I) { - for k in iter { - self.insert(k); - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for HashSet - where T: Eq + Hash, - S: HashState + Default, - H: hash::Hasher -{ - #[stable(feature = "rust1", since = "1.0.0")] - fn default() -> HashSet { - HashSet::with_hash_state(Default::default()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> BitOr<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher -{ - type Output = HashSet; - - /// Returns the union of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a | &b; - /// - /// let mut i = 0; - /// let expected = [1, 2, 3, 4, 5]; - /// for x in set.iter() { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitor(self, rhs: &HashSet) -> HashSet { - self.union(rhs).cloned().collect() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> BitAnd<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher -{ - type Output = HashSet; - - /// Returns the intersection of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect(); - /// - /// let set = &a & &b; - /// - /// let mut i = 0; - /// let expected = [2, 3]; - /// for x in set.iter() { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitand(self, rhs: &HashSet) -> HashSet { - self.intersection(rhs).cloned().collect() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> BitXor<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher -{ - type Output = HashSet; - - /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a ^ &b; - /// - /// let mut i = 0; - /// let expected = [1, 2, 4, 5]; - /// for x in set.iter() { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn bitxor(self, rhs: &HashSet) -> HashSet { - self.symmetric_difference(rhs).cloned().collect() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> Sub<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher -{ - type Output = HashSet; - - /// Returns the difference of `self` and `rhs` as a new `HashSet`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); - /// - /// let set = &a - &b; - /// - /// let mut i = 0; - /// let expected = [1, 2]; - /// for x in set.iter() { - /// assert!(expected.contains(x)); - /// i += 1; - /// } - /// assert_eq!(i, expected.len()); - /// ``` - fn sub(self, rhs: &HashSet) -> HashSet { - self.difference(rhs).cloned().collect() - } -} - -/// HashSet iterator -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Iter<'a, K: 'a> { - iter: Keys<'a, K, ()> -} - -/// HashSet move iterator -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { - iter: Map, fn((K, ())) -> K> -} - -/// HashSet drain iterator -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Drain<'a, K: 'a> { - iter: Map, fn((K, ())) -> K>, -} - -/// Intersection iterator -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Intersection<'a, T: 'a, S: 'a> { - // iterator of the first set - iter: Iter<'a, T>, - // the second set - other: &'a HashSet, -} - -/// Difference iterator -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Difference<'a, T: 'a, S: 'a> { - // iterator of the first set - iter: Iter<'a, T>, - // the second set - other: &'a HashSet, -} - -/// Symmetric difference iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct SymmetricDifference<'a, T: 'a, S: 'a> { - iter: Chain, Difference<'a, T, S>> -} - -/// Set union iterator. -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Union<'a, T: 'a, S: 'a> { - iter: Chain, Difference<'a, T, S>> -} - -impl<'a, T, S, H> IntoIterator for &'a HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = &'a T; - type IntoIter = Iter<'a, T>; - - fn into_iter(self) -> Iter<'a, T> { - self.iter() - } -} - -impl IntoIterator for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - self.into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> Iterator for Iter<'a, K> { - type Item = &'a K; - - fn next(&mut self) -> Option<&'a K> { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> ExactSizeIterator for Iter<'a, K> { - fn len(&self) -> usize { self.iter.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = K; - - fn next(&mut self) -> Option { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { - fn len(&self) -> usize { self.iter.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> Iterator for Drain<'a, K> { - type Item = K; - - fn next(&mut self) -> Option { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K> ExactSizeIterator for Drain<'a, K> { - fn len(&self) -> usize { self.iter.len() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> Iterator for Intersection<'a, T, S> - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = &'a T; - - fn next(&mut self) -> Option<&'a T> { - loop { - match self.iter.next() { - None => return None, - Some(elt) => if self.other.contains(elt) { - return Some(elt) - }, - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> Iterator for Difference<'a, T, S> - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = &'a T; - - fn next(&mut self) -> Option<&'a T> { - loop { - match self.iter.next() { - None => return None, - Some(elt) => if !self.other.contains(elt) { - return Some(elt) - }, - } - } - } - - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S> - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = &'a T; - - fn next(&mut self) -> Option<&'a T> { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> Iterator for Union<'a, T, S> - where T: Eq + Hash, - S: HashState, - H: hash::Hasher -{ - type Item = &'a T; - - fn next(&mut self) -> Option<&'a T> { self.iter.next() } - fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } -} - -#[cfg(test)] -mod test_set { - use prelude::v1::*; - - use super::HashSet; - - #[test] - fn test_disjoint() { - let mut xs = HashSet::new(); - let mut ys = HashSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5)); - assert!(ys.insert(11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = HashSet::new(); - assert!(a.insert(0)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = HashSet::new(); - assert!(b.insert(0)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } - - #[test] - fn test_iterate() { - let mut a = HashSet::new(); - for i in 0..32 { - assert!(a.insert(i)); - } - let mut observed: u32 = 0; - for k in &a { - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_intersection() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let mut i = 0; - let expected = [3, 5, 11, 77]; - for x in a.intersection(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - - let mut i = 0; - let expected = [1, 5, 11]; - for x in a.difference(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_symmetric_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let mut i = 0; - let expected = [-2, 1, 5, 11, 14, 22]; - for x in a.symmetric_difference(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_union() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let mut i = 0; - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - for x in a.union(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: HashSet<_> = xs.iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } - } - - #[test] - fn test_move_iter() { - let hs = { - let mut hs = HashSet::new(); - - hs.insert('a'); - hs.insert('b'); - - hs - }; - - let v = hs.into_iter().collect::>(); - assert!(['a', 'b'] == v || ['b', 'a'] == v); - } - - #[test] - fn test_eq() { - // These constants once happened to expose a bug in insert(). - // I'm keeping them around to prevent a regression. - let mut s1 = HashSet::new(); - - s1.insert(1); - s1.insert(2); - s1.insert(3); - - let mut s2 = HashSet::new(); - - s2.insert(1); - s2.insert(2); - - assert!(s1 != s2); - - s2.insert(3); - - assert_eq!(s1, s2); - } - - #[test] - fn test_show() { - let mut set = HashSet::new(); - let empty = HashSet::::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}"); - assert_eq!(format!("{:?}", empty), "HashSet {}"); - } - - #[test] - fn test_trivial_drain() { - let mut s = HashSet::::new(); - for _ in s.drain() {} - assert!(s.is_empty()); - drop(s); - - let mut s = HashSet::::new(); - drop(s.drain()); - assert!(s.is_empty()); - } - - #[test] - fn test_drain() { - let mut s: HashSet<_> = (1..100).collect(); - - // try this a bunch of times to make sure we don't screw up internal state. - for _ in 0..20 { - assert_eq!(s.len(), 99); - - { - let mut last_i = 0; - let mut d = s.drain(); - for (i, x) in d.by_ref().take(50).enumerate() { - last_i = i; - assert!(x != 0); - } - assert_eq!(last_i, 49); - } - - for _ in &s { panic!("s should be empty!"); } - - // reset to try again. - s.extend(1..100); - } - } -} diff --git a/src/libstd/collections/hash/state.rs b/src/libstd/collections/hash/state.rs index 7e6dd45b51..3a06d2d03b 100644 --- a/src/libstd/collections/hash/state.rs +++ b/src/libstd/collections/hash/state.rs @@ -27,6 +27,7 @@ use marker; /// to `Default` when asked to create a hasher. #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] pub trait HashState { + /// Type of the hasher that will be created. type Hasher: hash::Hasher; /// Creates a new hasher based on the given state of this object. diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index f301f6db92..dec6d1e220 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -15,19 +15,19 @@ use self::BucketState::*; use clone::Clone; use cmp; use hash::{Hash, Hasher}; -use iter::{Iterator, IteratorExt, ExactSizeIterator, count}; +use iter::{Iterator, ExactSizeIterator}; use marker::{Copy, Send, Sync, Sized, self}; use mem::{min_align_of, size_of}; use mem; -use num::{Int, UnsignedInt}; +use num::wrapping::{OverflowingOps, WrappingOps}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; -use ptr::{self, PtrExt, copy_nonoverlapping_memory, Unique, zero_memory}; +use ptr::{self, Unique}; use rt::heap::{allocate, deallocate, EMPTY}; use collections::hash_state::HashState; -const EMPTY_BUCKET: u64 = 0u64; +const EMPTY_BUCKET: u64 = 0; /// The raw hashtable, providing safe-ish access to the unzipped and highly /// optimized arrays of hashes, keys, and values. @@ -87,6 +87,9 @@ struct RawBucket { } impl Copy for RawBucket {} +impl Clone for RawBucket { + fn clone(&self) -> RawBucket { *self } +} pub struct Bucket { raw: RawBucket, @@ -95,6 +98,9 @@ pub struct Bucket { } impl Copy for Bucket {} +impl Clone for Bucket { + fn clone(&self) -> Bucket { *self } +} pub struct EmptyBucket { raw: RawBucket, @@ -129,7 +135,7 @@ struct GapThenFull { /// A hash that is not zero, since we use a hash of zero to represent empty /// buckets. -#[derive(PartialEq, Copy)] +#[derive(PartialEq, Copy, Clone)] pub struct SafeHash { hash: u64, } @@ -143,31 +149,12 @@ impl SafeHash { /// We need to remove hashes of 0. That's reserved for empty buckets. /// This function wraps up `hash_keyed` to be the only way outside this /// module to generate a SafeHash. -#[cfg(stage0)] -pub fn make_hash(hash_state: &S, t: &T) -> SafeHash - where T: Hash, - S: HashState, - H: Hasher -{ - let mut state = hash_state.hasher(); - t.hash(&mut state); - // 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 | state.finish() } -} - -/// We need to remove hashes of 0. That's reserved for empty buckets. -/// This function wraps up `hash_keyed` to be the only way outside this -/// module to generate a SafeHash. -#[cfg(not(stage0))] pub fn make_hash(hash_state: &S, t: &T) -> SafeHash where T: Hash, S: HashState { let mut state = hash_state.hasher(); t.hash(&mut state); - // We need to avoid 0u64 in order to prevent collisions with + // We need to avoid 0 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. @@ -243,6 +230,9 @@ impl>> Bucket { } pub fn at_index(table: M, ib_index: usize) -> Bucket { + // if capacity is 0, then the RawBucket will be populated with bogus pointers. + // This is an uncommon case though, so avoid it in release builds. + debug_assert!(table.capacity() > 0, "Table should have capacity at this point"); let ib_index = ib_index & (table.capacity() - 1); Bucket { raw: unsafe { @@ -390,7 +380,7 @@ impl>> FullBucket { // Calculates the distance one has to travel when going from // `hash mod capacity` onwards to `idx mod capacity`, wrapping around // if the destination is not reached before the end of the table. - (self.idx - self.hash().inspect() as usize) & (self.table.capacity() - 1) + (self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1) } #[inline] @@ -496,8 +486,8 @@ impl>> GapThenFull { pub fn shift(mut self) -> Option> { unsafe { *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET); - copy_nonoverlapping_memory(self.gap.raw.key, self.full.raw.key, 1); - copy_nonoverlapping_memory(self.gap.raw.val, self.full.raw.val, 1); + ptr::copy_nonoverlapping(self.full.raw.key, self.gap.raw.key, 1); + ptr::copy_nonoverlapping(self.full.raw.val, self.gap.raw.val, 1); } let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full; @@ -543,13 +533,13 @@ fn test_rounding() { fn calculate_offsets(hashes_size: usize, keys_size: usize, keys_align: usize, vals_align: usize) - -> (usize, usize) { + -> (usize, usize, bool) { let keys_offset = round_up_to_next(hashes_size, keys_align); - let end_of_keys = keys_offset + keys_size; + let (end_of_keys, oflo) = keys_offset.overflowing_add(keys_size); let vals_offset = round_up_to_next(end_of_keys, vals_align); - (keys_offset, vals_offset) + (keys_offset, vals_offset, oflo) } // Returns a tuple of (minimum required malloc alignment, hash_offset, @@ -557,26 +547,26 @@ fn calculate_offsets(hashes_size: usize, fn calculate_allocation(hash_size: usize, hash_align: usize, keys_size: usize, keys_align: usize, vals_size: usize, vals_align: usize) - -> (usize, usize, usize) { + -> (usize, usize, usize, bool) { let hash_offset = 0; - let (_, vals_offset) = calculate_offsets(hash_size, - keys_size, keys_align, - vals_align); - let end_of_vals = vals_offset + vals_size; + let (_, vals_offset, oflo) = calculate_offsets(hash_size, + keys_size, keys_align, + vals_align); + let (end_of_vals, oflo2) = vals_offset.overflowing_add(vals_size); let min_align = cmp::max(hash_align, cmp::max(keys_align, vals_align)); - (min_align, hash_offset, end_of_vals) + (min_align, hash_offset, end_of_vals, oflo || oflo2) } #[test] fn test_offset_calculation() { - assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4), (8, 0, 148)); - assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6)); - assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48)); - assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144)); - assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5)); - assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24)); + assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4), (8, 0, 148, false)); + assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6, false)); + assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48, false)); + assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144, false)); + assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5, false)); + assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24, false)); } impl RawTable { @@ -606,12 +596,14 @@ impl RawTable { // This is great in theory, but in practice getting the alignment // right is a little subtle. Therefore, calculating offsets has been // factored out into a different function. - let (malloc_alignment, hash_offset, size) = + let (malloc_alignment, hash_offset, size, oflo) = calculate_allocation( hashes_size, min_align_of::(), keys_size, min_align_of::< K >(), vals_size, min_align_of::< V >()); + assert!(!oflo, "capacity overflow"); + // One check for overflow that covers calculation and rounding of size. let size_of_bucket = size_of::().checked_add(size_of::()).unwrap() .checked_add(size_of::()).unwrap(); @@ -637,10 +629,11 @@ impl RawTable { let keys_size = self.capacity * size_of::(); let buffer = *self.hashes as *mut u8; - let (keys_offset, vals_offset) = calculate_offsets(hashes_size, - keys_size, min_align_of::(), - min_align_of::()); - + let (keys_offset, vals_offset, oflo) = + calculate_offsets(hashes_size, + keys_size, min_align_of::(), + min_align_of::()); + debug_assert!(!oflo, "capacity overflow"); unsafe { RawBucket { hash: *self.hashes, @@ -656,7 +649,7 @@ impl RawTable { pub fn new(capacity: usize) -> RawTable { unsafe { let ret = RawTable::new_uninitialized(capacity); - zero_memory(*ret.hashes, capacity); + ptr::write_bytes(*ret.hashes, 0, capacity); ret } } @@ -998,7 +991,7 @@ impl Clone for RawTable { #[unsafe_destructor] impl Drop for RawTable { fn drop(&mut self) { - if self.capacity == 0 { + if self.capacity == 0 || self.capacity == mem::POST_DROP_USIZE { return; } @@ -1014,9 +1007,12 @@ impl Drop for RawTable { let hashes_size = self.capacity * size_of::(); let keys_size = self.capacity * size_of::(); let vals_size = self.capacity * size_of::(); - let (align, _, size) = calculate_allocation(hashes_size, min_align_of::(), - keys_size, min_align_of::(), - vals_size, min_align_of::()); + let (align, _, size, oflo) = + calculate_allocation(hashes_size, min_align_of::(), + keys_size, min_align_of::(), + vals_size, min_align_of::()); + + debug_assert!(!oflo, "should be impossible"); unsafe { deallocate(*self.hashes as *mut u8, size, align); diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 0e64370df6..0ac97b7129 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -23,9 +23,9 @@ //! //! Rust's collections can be grouped into four major categories: //! -//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitV` +//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitVec` //! * Maps: `HashMap`, `BTreeMap`, `VecMap` -//! * Sets: `HashSet`, `BTreeSet`, `BitVSet` +//! * Sets: `HashSet`, `BTreeSet`, `BitSet` //! * Misc: `BinaryHeap` //! //! # When Should You Use Which Collection? @@ -73,12 +73,12 @@ //! * There is no meaningful value to associate with your keys. //! * You just want a set. //! -//! ### Use a `BitV` when: +//! ### Use a `BitVec` when: //! * You want to store an unbounded number of booleans in a small space. //! * You want a bit vector. //! -//! ### Use a `BitVSet` when: -//! * You want a `VecSet`. +//! ### Use a `BitSet` when: +//! * You want a `BitVec`, but want `Set` properties //! //! ### Use a `BinaryHeap` when: //! * You want to store a bunch of elements, but only ever want to process the "biggest" @@ -89,7 +89,8 @@ //! //! Choosing the right collection for the job requires an understanding of what each collection //! is good at. Here we briefly summarize the performance of different collections for certain -//! important operations. For further details, see each type's documentation. +//! important operations. For further details, see each type's documentation, and note that the +//! names of actual methods may differ from the tables below on certain collections. //! //! Throughout the documentation, we will follow a few conventions. For all operations, //! the collection's size is denoted by n. If another collection is involved in the operation, it @@ -280,16 +281,16 @@ //! a variant of the `Entry` enum. //! //! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case the -//! only valid operation is to `set` the value of the entry. When this is done, +//! only valid operation is to `insert` a value into the entry. When this is done, //! the vacant entry is consumed and converted into a mutable reference to the //! the value that was inserted. This allows for further manipulation of the value //! beyond the lifetime of the search itself. This is useful if complex logic needs to //! be performed on the value regardless of whether the value was just inserted. //! //! If an `Occupied(entry)` is yielded, then the key *was* found. In this case, the user -//! has several options: they can `get`, `set`, or `take` the value of the occupied +//! has several options: they can `get`, `insert`, or `remove` the value of the occupied //! entry. Additionally, they can convert the occupied entry into a mutable reference -//! to its value, providing symmetry to the vacant `set` case. +//! to its value, providing symmetry to the vacant `insert` case. //! //! ### Examples //! @@ -299,16 +300,14 @@ //! #### Counting the number of times each character in a string occurs //! //! ``` +//! # #![feature(collections)] //! use std::collections::btree_map::{BTreeMap, Entry}; //! //! let mut count = BTreeMap::new(); //! let message = "she sells sea shells by the sea shore"; //! //! for c in message.chars() { -//! match count.entry(c) { -//! Entry::Vacant(entry) => { entry.insert(1); }, -//! Entry::Occupied(mut entry) => *entry.get_mut() += 1, -//! } +//! *count.entry(c).or_insert(0) += 1; //! } //! //! assert_eq!(count.get(&'s'), Some(&8)); @@ -326,10 +325,11 @@ //! #### Tracking the inebriation of customers at a bar //! //! ``` +//! # #![feature(collections)] //! use std::collections::btree_map::{BTreeMap, Entry}; //! //! // A client of the bar. They have an id and a blood alcohol level. -//! struct Person { id: u32, blood_alcohol: f32 }; +//! struct Person { id: u32, blood_alcohol: f32 } //! //! // All the orders made to the bar, by client id. //! let orders = vec![1,2,1,2,3,4,1,2,2,3,4,1,1,1]; @@ -340,10 +340,7 @@ //! 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) { -//! Entry::Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}), -//! Entry::Occupied(entry) => entry.into_mut(), -//! }; +//! let person = blood_alcohol.entry(id).or_insert(Person{id: id, blood_alcohol: 0.0}); //! //! // Reduce their blood alcohol level. It takes time to order and drink a beer! //! person.blood_alcohol *= 0.9; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index b0fb9c2940..e76d5460eb 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -17,10 +17,10 @@ use prelude::v1::*; -use ffi::CString; -use mem; use env; -use str; +use ffi::{CString, OsString}; +use mem; +use path::{Path, PathBuf}; pub struct DynamicLibrary { handle: *mut u8 @@ -51,7 +51,7 @@ impl DynamicLibrary { /// Lazily open a dynamic library. When passed None it gives a /// handle to the calling process pub fn open(filename: Option<&Path>) -> Result { - let maybe_library = dl::open(filename.map(|path| path.as_vec())); + let maybe_library = dl::open(filename.map(|path| path.as_os_str())); // The dynamic library must not be constructed if there is // an error opening the library so the destructor does not @@ -65,19 +65,17 @@ impl DynamicLibrary { /// Prepends a path to this process's search path for dynamic libraries pub fn prepend_search_path(path: &Path) { let mut search_path = DynamicLibrary::search_path(); - search_path.insert(0, path.clone()); - let newval = DynamicLibrary::create_path(&search_path); - env::set_var(DynamicLibrary::envvar(), - str::from_utf8(&newval).unwrap()); + search_path.insert(0, path.to_path_buf()); + env::set_var(DynamicLibrary::envvar(), &DynamicLibrary::create_path(&search_path)); } /// From a slice of paths, create a new vector which is suitable to be an /// environment variable for this platforms dylib search path. - pub fn create_path(path: &[Path]) -> Vec { - let mut newvar = Vec::new(); + pub fn create_path(path: &[PathBuf]) -> OsString { + let mut newvar = OsString::new(); for (i, path) in path.iter().enumerate() { if i > 0 { newvar.push(DynamicLibrary::separator()); } - newvar.push_all(path.as_vec()); + newvar.push(path); } return newvar; } @@ -94,13 +92,13 @@ impl DynamicLibrary { } } - fn separator() -> u8 { - if cfg!(windows) {b';'} else {b':'} + fn separator() -> &'static str { + if cfg!(windows) { ";" } else { ":" } } /// Returns the current search path for dynamic libraries being used by this /// process - pub fn search_path() -> Vec { + pub fn search_path() -> Vec { match env::var_os(DynamicLibrary::envvar()) { Some(var) => env::split_paths(&var).collect(), None => Vec::new(), @@ -132,14 +130,14 @@ mod test { use prelude::v1::*; use libc; use mem; + use path::Path; #[test] #[cfg_attr(any(windows, target_os = "android"), ignore)] // FIXME #8818, #10379 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 libm = match DynamicLibrary::open(none) { + let libm = match DynamicLibrary::open(None) { Err(error) => panic!("Could not load self as module: {}", error), Ok(libm) => libm }; @@ -165,6 +163,7 @@ mod test { target_os = "macos", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] fn test_errors_do_not_crash() { // Open /dev/null as a library to get an error, and make sure @@ -183,16 +182,17 @@ mod test { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] mod dl { use prelude::v1::*; - use ffi::{CString, CStr}; + use ffi::{CStr, OsStr}; use str; use libc; use ptr; - pub fn open(filename: Option<&[u8]>) -> Result<*mut u8, String> { + pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { check_for_errors_in(|| { unsafe { match filename { @@ -205,8 +205,8 @@ mod dl { const LAZY: libc::c_int = 1; - unsafe fn open_external(filename: &[u8]) -> *mut u8 { - let s = CString::new(filename).unwrap(); + unsafe fn open_external(filename: &OsStr) -> *mut u8 { + let s = filename.to_cstring().unwrap(); dlopen(s.as_ptr(), LAZY) as *mut u8 } @@ -259,23 +259,22 @@ mod dl { #[cfg(target_os = "windows")] mod dl { - use iter::IteratorExt; + use ffi::OsStr; + use iter::Iterator; use libc; use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED; use ops::FnOnce; - use os; + use sys::os; + use os::windows::prelude::*; use option::Option::{self, Some, None}; use ptr; use result::Result; use result::Result::{Ok, Err}; - use slice::SliceExt; - use str::StrExt; - use str; use string::String; use vec::Vec; use sys::c::compat::kernel32::SetThreadErrorMode; - pub fn open(filename: Option<&[u8]>) -> Result<*mut u8, String> { + pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { // disable "dll load failed" error dialog. let mut use_thread_mode = true; let prev_error_mode = unsafe { @@ -288,10 +287,11 @@ mod dl { let err = os::errno(); if err as libc::c_int == ERROR_CALL_NOT_IMPLEMENTED { use_thread_mode = false; - // SetThreadErrorMode not found. use fallback solution: SetErrorMode() - // Note that SetErrorMode is process-wide so this can cause race condition! - // However, since even Windows APIs do not care of such problem (#20650), - // we just assume SetErrorMode race is not a great deal. + // SetThreadErrorMode not found. use fallback solution: + // SetErrorMode() Note that SetErrorMode is process-wide so + // this can cause race condition! However, since even + // Windows APIs do not care of such problem (#20650), we + // just assume SetErrorMode race is not a great deal. prev_error_mode = SetErrorMode(new_error_mode); } } @@ -304,9 +304,8 @@ mod dl { let result = match filename { Some(filename) => { - let filename_str = str::from_utf8(filename).unwrap(); - let mut filename_str: Vec = filename_str.utf16_units().collect(); - filename_str.push(0); + let filename_str: Vec<_> = + filename.encode_wide().chain(Some(0).into_iter()).collect(); let result = unsafe { LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) }; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 8676586e7d..931cf46a58 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -14,14 +14,16 @@ //! environment varibles, process arguments, the current directory, and various //! other important directories. -#![unstable(feature = "env", reason = "recently added via RFC 578")] +#![stable(feature = "env", since = "1.0.0")] use prelude::v1::*; +use iter::IntoIterator; use error::Error; -use ffi::{OsString, AsOsStr}; +use ffi::{OsStr, OsString}; use fmt; -use old_io::IoResult; +use io; +use path::{Path, PathBuf}; use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; use sync::{StaticMutex, MUTEX_INIT}; use sys::os as os_imp; @@ -37,34 +39,36 @@ use sys::os as os_imp; /// * There are insufficient permissions to access the current directory. /// * The internal buffer is not large enough to hold the path. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// // We assume that we are in a valid directory. /// let p = env::current_dir().unwrap(); /// println!("The current directory is {}", p.display()); /// ``` -pub fn current_dir() -> IoResult { +#[stable(feature = "env", since = "1.0.0")] +pub fn current_dir() -> io::Result { os_imp::getcwd() } /// Changes the current working directory to the specified path, returning /// whether the change was completed successfully or not. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; -/// use std::old_path::Path; +/// use std::path::Path; /// /// let root = Path::new("/"); /// assert!(env::set_current_dir(&root).is_ok()); /// println!("Successfully changed working directory to {}!", root.display()); /// ``` -pub fn set_current_dir(p: &Path) -> IoResult<()> { - os_imp::chdir(p) +#[stable(feature = "env", since = "1.0.0")] +pub fn set_current_dir + ?Sized>(p: &P) -> io::Result<()> { + os_imp::chdir(p.as_ref()) } static ENV_LOCK: StaticMutex = MUTEX_INIT; @@ -73,12 +77,14 @@ static ENV_LOCK: StaticMutex = MUTEX_INIT; /// /// This iterator is created through `std::env::vars()` and yields `(String, /// String)` pairs. +#[stable(feature = "env", since = "1.0.0")] pub struct Vars { inner: VarsOs } /// An iterator over a snapshot of the environment variables of this process. /// /// This iterator is created through `std::env::vars_os()` and yields /// `(OsString, OsString)` pairs. +#[stable(feature = "env", since = "1.0.0")] pub struct VarsOs { inner: os_imp::Env } /// Returns an iterator of (variable, value) pairs of strings, for all the @@ -94,9 +100,9 @@ pub struct VarsOs { inner: os_imp::Env } /// environment is not valid unicode. If this is not desired, consider using the /// `env::vars_os` function. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// // We will iterate through the references to the element returned by @@ -105,6 +111,7 @@ pub struct VarsOs { inner: os_imp::Env } /// println!("{}: {}", key, value); /// } /// ``` +#[stable(feature = "env", since = "1.0.0")] pub fn vars() -> Vars { Vars { inner: vars_os() } } @@ -116,9 +123,9 @@ pub fn vars() -> Vars { /// variables at the time of this invocation, modifications to environment /// variables afterwards will not be reflected in the returned iterator. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// // We will iterate through the references to the element returned by @@ -127,11 +134,13 @@ pub fn vars() -> Vars { /// println!("{:?}: {:?}", key, value); /// } /// ``` +#[stable(feature = "env", since = "1.0.0")] pub fn vars_os() -> VarsOs { let _g = ENV_LOCK.lock(); VarsOs { inner: os_imp::env() } } +#[stable(feature = "env", since = "1.0.0")] impl Iterator for Vars { type Item = (String, String); fn next(&mut self) -> Option<(String, String)> { @@ -142,6 +151,7 @@ impl Iterator for Vars { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "env", since = "1.0.0")] impl Iterator for VarsOs { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() } @@ -154,9 +164,9 @@ impl Iterator for VarsOs { /// valid unicode. If the environment variable is not present, or it is not /// valid unicode, then `Err` will be returned. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// let key = "HOME"; @@ -165,7 +175,8 @@ impl Iterator for VarsOs { /// Err(e) => println!("couldn't interpret {}: {}", key, e), /// } /// ``` -pub fn var(key: &K) -> Result where K: AsOsStr { +#[stable(feature = "env", since = "1.0.0")] +pub fn var(key: &K) -> Result where K: AsRef { match var_os(key) { Some(s) => s.into_string().map_err(VarError::NotUnicode), None => Err(VarError::NotPresent) @@ -175,9 +186,9 @@ pub fn var(key: &K) -> Result where K: AsOsStr { /// Fetches the environment variable `key` from the current process, returning /// None if the variable isn't set. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// let key = "HOME"; @@ -186,24 +197,29 @@ pub fn var(key: &K) -> Result where K: AsOsStr { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` -pub fn var_os(key: &K) -> Option where K: AsOsStr { +#[stable(feature = "env", since = "1.0.0")] +pub fn var_os(key: &K) -> Option where K: AsRef { let _g = ENV_LOCK.lock(); - os_imp::getenv(key.as_os_str()) + os_imp::getenv(key.as_ref()) } /// Possible errors from the `env::var` method. #[derive(Debug, PartialEq, Eq, Clone)] +#[stable(feature = "env", since = "1.0.0")] pub enum VarError { /// The specified environment variable was not present in the current /// process's environment. + #[stable(feature = "env", since = "1.0.0")] NotPresent, /// The specified environment variable was found, but it did not contain /// valid unicode data. The found data is returned as a payload of this /// variant. + #[stable(feature = "env", since = "1.0.0")] NotUnicode(OsString), } +#[stable(feature = "env", since = "1.0.0")] impl fmt::Display for VarError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -215,6 +231,7 @@ impl fmt::Display for VarError { } } +#[stable(feature = "env", since = "1.0.0")] impl Error for VarError { fn description(&self) -> &str { match *self { @@ -227,32 +244,48 @@ impl Error for VarError { /// Sets the environment variable `k` to the value `v` for the currently running /// process. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// let key = "KEY"; /// env::set_var(key, "VALUE"); /// assert_eq!(env::var(key), Ok("VALUE".to_string())); /// ``` +#[stable(feature = "env", since = "1.0.0")] pub fn set_var(k: &K, v: &V) - where K: AsOsStr, V: AsOsStr + where K: AsRef, V: AsRef { let _g = ENV_LOCK.lock(); - os_imp::setenv(k.as_os_str(), v.as_os_str()) + os_imp::setenv(k.as_ref(), v.as_ref()) } -/// Remove a variable from the environment entirely. -pub fn remove_var(k: &K) where K: AsOsStr { +/// Remove an environment variable from the environment of the currently running process. +/// +/// # Examples +/// +/// ``` +/// use std::env; +/// +/// let key = "KEY"; +/// env::set_var(key, "VALUE"); +/// assert_eq!(env::var(key), Ok("VALUE".to_string())); +/// +/// env::remove_var(key); +/// assert!(env::var(key).is_err()); +/// ``` +#[stable(feature = "env", since = "1.0.0")] +pub fn remove_var(k: &K) where K: AsRef { let _g = ENV_LOCK.lock(); - os_imp::unsetenv(k.as_os_str()) + os_imp::unsetenv(k.as_ref()) } /// An iterator over `Path` instances for parsing an environment variable /// according to platform-specific conventions. /// /// This structure is returned from `std::env::split_paths`. +#[stable(feature = "env", since = "1.0.0")] pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } /// Parses input according to platform conventions for the `PATH` @@ -260,9 +293,9 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } /// /// Returns an iterator over the paths contained in `unparsed`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// let key = "PATH"; @@ -275,19 +308,22 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } /// None => println!("{} is not defined in the environment.", key) /// } /// ``` -pub fn split_paths(unparsed: &T) -> SplitPaths { - SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) } +#[stable(feature = "env", since = "1.0.0")] +pub fn split_paths + ?Sized>(unparsed: &T) -> SplitPaths { + SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) } } +#[stable(feature = "env", since = "1.0.0")] impl<'a> Iterator for SplitPaths<'a> { - type Item = Path; - fn next(&mut self) -> Option { self.inner.next() } + type Item = PathBuf; + fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } /// Error type returned from `std::env::join_paths` when paths fail to be /// joined. #[derive(Debug)] +#[stable(feature = "env", since = "1.0.0")] pub struct JoinPathsError { inner: os_imp::JoinPathsError } @@ -301,32 +337,36 @@ pub struct JoinPathsError { /// `Path`s contains an invalid character for constructing the `PATH` /// variable (a double quote on Windows or a colon on Unix). /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; +/// use std::path::PathBuf; /// /// if let Some(path) = env::var_os("PATH") { /// let mut paths = env::split_paths(&path).collect::>(); -/// paths.push(Path::new("/home/xyz/bin")); +/// paths.push(PathBuf::from("/home/xyz/bin")); /// let new_path = env::join_paths(paths.iter()).unwrap(); /// env::set_var("PATH", &new_path); /// } /// ``` +#[stable(feature = "env", since = "1.0.0")] pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: IntoIterator, T: AsRef { - os_imp::join_paths(paths).map_err(|e| { + os_imp::join_paths(paths.into_iter()).map_err(|e| { JoinPathsError { inner: e } }) } +#[stable(feature = "env", since = "1.0.0")] impl fmt::Display for JoinPathsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.inner.fmt(f) } } +#[stable(feature = "env", since = "1.0.0")] impl Error for JoinPathsError { fn description(&self) -> &str { self.inner.description() } } @@ -345,9 +385,9 @@ impl Error for JoinPathsError { /// 'USERPROFILE' environment variable if it is set and not equal to the empty /// string. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// match env::home_dir() { @@ -355,7 +395,8 @@ impl Error for JoinPathsError { /// None => println!("Impossible to get your home dir!") /// } /// ``` -pub fn home_dir() -> Option { +#[stable(feature = "env", since = "1.0.0")] +pub fn home_dir() -> Option { os_imp::home_dir() } @@ -369,7 +410,21 @@ pub fn home_dir() -> Option { /// On Windows, returns the value of, in order, the 'TMP', 'TEMP', /// 'USERPROFILE' environment variable if any are set and not the empty /// string. Otherwise, tmpdir returns the path to the Windows directory. -pub fn temp_dir() -> Path { +/// +/// ``` +/// use std::env; +/// use std::fs::File; +/// +/// # fn foo() -> std::io::Result<()> { +/// let mut dir = env::temp_dir(); +/// dir.push("foo.txt"); +/// +/// let f = try!(File::create(dir)); +/// # Ok(()) +/// # } +/// ``` +#[stable(feature = "env", since = "1.0.0")] +pub fn temp_dir() -> PathBuf { os_imp::temp_dir() } @@ -387,7 +442,7 @@ pub fn temp_dir() -> Path { /// /// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// match env::current_exe() { @@ -396,7 +451,8 @@ pub fn temp_dir() -> Path { /// Err(e) => println!("failed to get current exe path: {}", e), /// }; /// ``` -pub fn current_exe() -> IoResult { +#[stable(feature = "env", since = "1.0.0")] +pub fn current_exe() -> io::Result { os_imp::current_exe() } @@ -410,26 +466,30 @@ static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT; /// ignored and the process exits with the default panic status. /// /// Note that this is not synchronized against modifications of other threads. +#[unstable(feature = "exit_status", reason = "managing the exit status may change")] pub fn set_exit_status(code: i32) { EXIT_STATUS.store(code as isize, Ordering::SeqCst) } /// Fetches the process's current exit code. This defaults to 0 and can change /// by calling `set_exit_status`. +#[unstable(feature = "exit_status", reason = "managing the exit status may change")] pub fn get_exit_status() -> i32 { EXIT_STATUS.load(Ordering::SeqCst) as i32 } -/// An iterator over the arguments of a process, yielding an `String` value +/// An iterator over the arguments of a process, yielding a `String` value /// for each argument. /// /// This structure is created through the `std::env::args` method. +#[stable(feature = "env", since = "1.0.0")] pub struct Args { inner: ArgsOs } /// An iterator over the arguments of a process, yielding an `OsString` value /// for each argument. /// /// This structure is created through the `std::env::args_os` method. +#[stable(feature = "env", since = "1.0.0")] pub struct ArgsOs { inner: os_imp::Args } /// Returns the arguments which this program was started with (normally passed @@ -445,9 +505,9 @@ pub struct ArgsOs { inner: os_imp::Args } /// process is not valid unicode. If this is not desired it is recommended to /// use the `args_os` function instead. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// // Prints each argument on a separate line @@ -455,6 +515,7 @@ pub struct ArgsOs { inner: os_imp::Args } /// println!("{}", argument); /// } /// ``` +#[stable(feature = "env", since = "1.0.0")] pub fn args() -> Args { Args { inner: args_os() } } @@ -466,9 +527,9 @@ pub fn args() -> Args { /// set to arbitrary text, and it may not even exist, so this property should /// not be relied upon for security purposes. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::env; /// /// // Prints each argument on a separate line @@ -476,10 +537,12 @@ pub fn args() -> Args { /// println!("{:?}", argument); /// } /// ``` +#[stable(feature = "env", since = "1.0.0")] pub fn args_os() -> ArgsOs { ArgsOs { inner: os_imp::args() } } +#[stable(feature = "env", since = "1.0.0")] impl Iterator for Args { type Item = String; fn next(&mut self) -> Option { @@ -488,301 +551,204 @@ impl Iterator for Args { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "env", since = "1.0.0")] impl ExactSizeIterator for Args { fn len(&self) -> usize { self.inner.len() } } +#[stable(feature = "env", since = "1.0.0")] impl Iterator for ArgsOs { type Item = OsString; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "env", since = "1.0.0")] impl ExactSizeIterator for ArgsOs { fn len(&self) -> usize { self.inner.len() } } /// Returns the page size of the current architecture in bytes. +#[unstable(feature = "page_size", reason = "naming and/or location may change")] pub fn page_size() -> usize { os_imp::page_size() } /// Constants associated with the current target -#[cfg(target_os = "linux")] +#[stable(feature = "env", since = "1.0.0")] pub mod consts { - pub use super::arch_consts::ARCH; + /// A string describing the architecture of the CPU that this is currently + /// in use. + #[stable(feature = "env", since = "1.0.0")] + pub const ARCH: &'static str = super::arch::ARCH; - pub const FAMILY: &'static str = "unix"; + /// The family of the operating system. In this case, `unix`. + #[stable(feature = "env", since = "1.0.0")] + pub const FAMILY: &'static str = super::os::FAMILY; /// A string describing the specific operating system in use: in this /// case, `linux`. - pub const OS: &'static str = "linux"; + #[stable(feature = "env", since = "1.0.0")] + pub const OS: &'static str = super::os::OS; /// Specifies the filename prefix used for shared libraries on this /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; + #[stable(feature = "env", since = "1.0.0")] + pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX; /// Specifies the filename suffix used for shared libraries on this /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; + #[stable(feature = "env", since = "1.0.0")] + pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX; /// Specifies the file extension used for shared libraries on this /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; + #[stable(feature = "env", since = "1.0.0")] + pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION; /// Specifies the filename suffix used for executable binaries on this /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; + #[stable(feature = "env", since = "1.0.0")] + pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX; /// Specifies the file extension, if any, used for executable binaries /// on this platform: in this case, the empty string. + #[stable(feature = "env", since = "1.0.0")] + pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION; + +} + +#[cfg(target_os = "linux")] +mod os { + pub const FAMILY: &'static str = "unix"; + pub const OS: &'static str = "linux"; + pub const DLL_PREFIX: &'static str = "lib"; + pub const DLL_SUFFIX: &'static str = ".so"; + pub const DLL_EXTENSION: &'static str = "so"; + pub const EXE_SUFFIX: &'static str = ""; pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "macos")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `macos`. pub const OS: &'static str = "macos"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dylib`. pub const DLL_SUFFIX: &'static str = ".dylib"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dylib`. pub const DLL_EXTENSION: &'static str = "dylib"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "ios")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `ios`. pub const OS: &'static str = "ios"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. + pub const DLL_PREFIX: &'static str = "lib"; + pub const DLL_SUFFIX: &'static str = ".dylib"; + pub const DLL_EXTENSION: &'static str = "dylib"; pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "freebsd")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `freebsd`. pub const OS: &'static str = "freebsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "dragonfly")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `dragonfly`. pub const OS: &'static str = "dragonfly"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. pub const EXE_SUFFIX: &'static str = ""; + pub const EXE_EXTENSION: &'static str = ""; +} - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. +#[cfg(target_os = "bitrig")] +mod os { + pub const FAMILY: &'static str = "unix"; + pub const OS: &'static str = "bitrig"; + pub const DLL_PREFIX: &'static str = "lib"; + pub const DLL_SUFFIX: &'static str = ".so"; + pub const DLL_EXTENSION: &'static str = "so"; + pub const EXE_SUFFIX: &'static str = ""; pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "openbsd")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `dragonfly`. pub const OS: &'static str = "openbsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "android")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `android`. pub const OS: &'static str = "android"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. pub const EXE_EXTENSION: &'static str = ""; } -/// Constants associated with the current target #[cfg(target_os = "windows")] -pub mod consts { - pub use super::arch_consts::ARCH; - +mod os { pub const FAMILY: &'static str = "windows"; - - /// A string describing the specific operating system in use: in this - /// case, `windows`. pub const OS: &'static str = "windows"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, the empty string. pub const DLL_PREFIX: &'static str = ""; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dll`. pub const DLL_SUFFIX: &'static str = ".dll"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dll`. pub const DLL_EXTENSION: &'static str = "dll"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, `.exe`. pub const EXE_SUFFIX: &'static str = ".exe"; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, `exe`. pub const EXE_EXTENSION: &'static str = "exe"; } #[cfg(target_arch = "x86")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "x86"; } #[cfg(target_arch = "x86_64")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "x86_64"; } #[cfg(target_arch = "arm")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "arm"; } #[cfg(target_arch = "aarch64")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "aarch64"; } #[cfg(target_arch = "mips")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "mips"; } #[cfg(target_arch = "mipsel")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "mipsel"; } #[cfg(target_arch = "powerpc")] -mod arch_consts { +mod arch { pub const ARCH: &'static str = "powerpc"; } @@ -790,15 +756,17 @@ mod arch_consts { mod tests { use prelude::v1::*; use super::*; + use iter::repeat; use rand::{self, Rng}; use ffi::{OsString, OsStr}; + use path::{Path, PathBuf}; fn make_rand_name() -> OsString { let mut rng = rand::thread_rng(); let n = format!("TEST{}", rng.gen_ascii_chars().take(10) .collect::()); - let n = OsString::from_string(n); + let n = OsString::from(n); assert!(var_os(&n).is_none()); n } @@ -841,8 +809,8 @@ mod tests { i += 1; } let n = make_rand_name(); - set_var(&n, s.as_slice()); - eq(var_os(&n), Some(s.as_slice())); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); } #[test] @@ -860,7 +828,7 @@ mod tests { let n = make_rand_name(); let s = repeat("x").take(10000).collect::(); set_var(&n, &s); - eq(var_os(&n), Some(s.as_slice())); + eq(var_os(&n), Some(&s)); remove_var(&n); eq(var_os(&n), None); } @@ -892,7 +860,7 @@ mod tests { fn split_paths_windows() { fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { split_paths(unparsed).collect::>() == - parsed.iter().map(|s| Path::new(*s)).collect::>() + parsed.iter().map(|s| PathBuf::from(*s)).collect::>() } assert!(check_parse("", &mut [""])); @@ -912,7 +880,7 @@ mod tests { fn split_paths_unix() { fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { split_paths(unparsed).collect::>() == - parsed.iter().map(|s| Path::new(*s)).collect::>() + parsed.iter().map(|s| PathBuf::from(*s)).collect::>() } assert!(check_parse("", &mut [""])); diff --git a/src/libstd/error.rs b/src/libstd/error.rs new file mode 100644 index 0000000000..150ffcdd77 --- /dev/null +++ b/src/libstd/error.rs @@ -0,0 +1,152 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits for working with Errors. +//! +//! # The `Error` trait +//! +//! `Error` is a trait representing the basic expectations for error values, +//! i.e. values of type `E` in `Result`. At a minimum, errors must provide +//! a description, but they may optionally provide additional detail (via +//! `Display`) and cause chain information: +//! +//! ``` +//! use std::fmt::Display; +//! +//! trait Error: Display { +//! fn description(&self) -> &str; +//! +//! fn cause(&self) -> Option<&Error> { None } +//! } +//! ``` +//! +//! The `cause` method is generally used when errors cross "abstraction +//! boundaries", i.e. when a one module must report an error that is "caused" +//! by an error from a lower-level module. This setup makes it possible for the +//! high-level module to provide its own errors that do not commit to any +//! particular implementation, but also reveal some of its implementation for +//! debugging via `cause` chains. + +#![stable(feature = "rust1", since = "1.0.0")] + +// A note about crates and the facade: +// +// Originally, the `Error` trait was defined in libcore, and the impls +// were scattered about. However, coherence objected to this +// arrangement, because to create the blanket impls for `Box` required +// knowing that `&str: !Error`, and we have no means to deal with that +// sort of conflict just now. Therefore, for the time being, we have +// moved the `Error` trait into libstd. As we evolve a sol'n to the +// coherence challenge (e.g., specialization, neg impls, etc) we can +// reconsider what crate these items belong in. + +use boxed::Box; +use convert::From; +use fmt::{self, Debug, Display}; +use marker::Send; +use num; +use option::Option; +use option::Option::None; +use str; +use string::{self, String}; + +/// Base functionality for all errors in Rust. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Error: Debug + Display { + /// A short description of the error. + /// + /// The description should not contain newlines or sentence-ending + /// punctuation, to facilitate embedding in larger user-facing + /// strings. + #[stable(feature = "rust1", since = "1.0.0")] + fn description(&self) -> &str; + + /// The lower-level cause of this error, if any. + #[stable(feature = "rust1", since = "1.0.0")] + fn cause(&self) -> Option<&Error> { None } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { + #[derive(Debug)] + struct StringError(String); + + impl Error for StringError { + fn description(&self) -> &str { &self.0 } + } + + impl Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } + } + + Box::new(StringError(String::from_str(err))) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::ParseBoolError { + fn description(&self) -> &str { "failed to parse bool" } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::Utf8Error { + fn description(&self) -> &str { + match *self { + str::Utf8Error::TooShort => "invalid utf-8: not enough bytes", + str::Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseIntError { + fn description(&self) -> &str { + self.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseFloatError { + fn description(&self) -> &str { + self.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for string::FromUtf8Error { + fn description(&self) -> &str { + "invalid utf-8" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for string::FromUtf16Error { + fn description(&self) -> &str { + "invalid utf-16" + } +} + diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 8976813d3f..de91e5f326 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -8,19 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "std_misc")] + +use convert::{Into, From}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use error::{Error, FromError}; +use error::Error; use fmt; use io; -use iter::IteratorExt; +use iter::Iterator; use libc; use mem; +#[allow(deprecated)] use old_io; use ops::Deref; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; -use slice::{self, SliceExt}; -use str::StrExt; +use slice; use string::String; use vec::Vec; @@ -39,9 +42,10 @@ use vec::Vec; /// a `CString` do *not* contain the trailing nul terminator unless otherwise /// specified. /// -/// # Example +/// # Examples /// /// ```no_run +/// # #![feature(libc)] /// # extern crate libc; /// # fn main() { /// use std::ffi::CString; @@ -51,7 +55,7 @@ use vec::Vec; /// fn my_printer(s: *const libc::c_char); /// } /// -/// let to_print = b"Hello, world!"; +/// let to_print = &b"Hello, world!"[..]; /// let c_to_print = CString::new(to_print).unwrap(); /// unsafe { /// my_printer(c_to_print.as_ptr()); @@ -59,6 +63,7 @@ use vec::Vec; /// # } /// ``` #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct CString { inner: Vec, } @@ -79,6 +84,7 @@ pub struct CString { /// Inspecting a foreign C string /// /// ```no_run +/// # #![feature(libc)] /// extern crate libc; /// use std::ffi::CStr; /// @@ -95,6 +101,7 @@ pub struct CString { /// Passing a Rust-originating C string /// /// ```no_run +/// # #![feature(libc)] /// extern crate libc; /// use std::ffi::{CString, CStr}; /// @@ -110,22 +117,21 @@ pub struct CString { /// } /// ``` #[derive(Hash)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct CStr { + // FIXME: this should not be represented with a DST slice but rather with + // just a raw `libc::c_char` along with some form of marker to make + // this an unsized type. Essentially `sizeof(&CStr)` should be the + // same as `sizeof(&c_char)` but `CStr` should be an unsized type. inner: [libc::c_char] } /// An error returned from `CString::new` to indicate that a nul byte was found /// in the vector provided. #[derive(Clone, PartialEq, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct NulError(usize, Vec); -/// A conversion trait used by the constructor of `CString` for types that can -/// be converted to a vector of bytes. -pub trait IntoBytes { - /// Consumes this container, returning a vector of bytes. - fn into_bytes(self) -> Vec; -} - impl CString { /// Create a new C-compatible string from a container of bytes. /// @@ -135,6 +141,7 @@ impl CString { /// # Examples /// /// ```no_run + /// # #![feature(libc)] /// extern crate libc; /// use std::ffi::CString; /// @@ -153,69 +160,21 @@ impl CString { /// This function will return an error if the bytes yielded contain an /// internal 0 byte. The error returned will contain the bytes as well as /// the position of the nul byte. - pub fn new(t: T) -> Result { - let bytes = t.into_bytes(); + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new>>(t: T) -> Result { + let bytes = t.into(); match bytes.iter().position(|x| *x == 0) { Some(i) => Err(NulError(i, bytes)), None => Ok(unsafe { CString::from_vec_unchecked(bytes) }), } } - /// 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. - /// - /// # Examples - /// - /// ```no_run - /// extern crate libc; - /// use std::ffi::CString; - /// - /// extern { fn puts(s: *const libc::c_char); } - /// - /// fn main() { - /// let to_print = CString::new("Hello!").unwrap(); - /// unsafe { - /// puts(to_print.as_ptr()); - /// } - /// } - /// ``` - /// - /// # Panics - /// - /// This function will panic if the provided slice contains any - /// interior nul bytes. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use CString::new instead")] - #[allow(deprecated)] - 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 the provided slice contains any - /// interior nul bytes. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "use CString::new instead")] - pub fn from_vec(v: Vec) -> CString { - match v.iter().position(|x| *x == 0) { - Some(i) => panic!("null byte found in slice at: {}", i), - None => unsafe { CString::from_vec_unchecked(v) }, - } - } - /// Create a C-compatible 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. + #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { v.push(0); CString { inner: v } @@ -224,18 +183,21 @@ impl CString { /// Returns the contents of this `CString` as a slice of bytes. /// /// The returned slice does **not** contain the trailing nul separator and - /// it is guaranteet to not have any interior nul bytes. + /// it is guaranteed to not have any interior nul bytes. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { &self.inner[..self.inner.len() - 1] } /// Equivalent to the `as_bytes` function except that the returned slice /// includes the trailing nul byte. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner } } +#[stable(feature = "rust1", since = "1.0.0")] impl Deref for CString { type Target = CStr; @@ -254,32 +216,39 @@ impl fmt::Debug for CString { impl NulError { /// Returns the position of the nul byte in the slice that was provided to /// `CString::from_vec`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn nul_position(&self) -> usize { self.0 } /// Consumes this error, returning the underlying vector of bytes which /// generated the error in the first place. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_vec(self) -> Vec { self.1 } } +#[stable(feature = "rust1", since = "1.0.0")] impl Error for NulError { fn description(&self) -> &str { "nul byte found in data" } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for NulError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "nul byte found in provided data at position: {}", self.0) } } -impl FromError for io::Error { - fn from_error(_: NulError) -> io::Error { +#[stable(feature = "rust1", since = "1.0.0")] +impl From for io::Error { + fn from(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, - "data provided contains a nul byte", None) + "data provided contains a nul byte") } } -impl FromError for old_io::IoError { - fn from_error(_: NulError) -> old_io::IoError { +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] +impl From for old_io::IoError { + fn from(_: NulError) -> old_io::IoError { old_io::IoError { kind: old_io::IoErrorKind::InvalidInput, desc: "data provided contains a nul byte", @@ -305,9 +274,10 @@ impl CStr { /// > currently implemented with an up-front calculation of the length of /// > the string. This is not guaranteed to always be the case. /// - /// # Example + /// # Examples /// /// ```no_run + /// # #![feature(libc)] /// # extern crate libc; /// # fn main() { /// use std::ffi::CStr; @@ -325,6 +295,7 @@ impl CStr { /// } /// # } /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr { let len = libc::strlen(ptr); mem::transmute(slice::from_raw_parts(ptr, len as usize + 1)) @@ -333,8 +304,9 @@ impl CStr { /// Return the inner pointer to this C string. /// /// The returned pointer will be valid for as long as `self` is and points - /// to a continguous region of memory terminated with a 0 byte to represent + /// to a contiguous region of memory terminated with a 0 byte to represent /// the end of the string. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_ptr(&self) -> *const libc::c_char { self.inner.as_ptr() } @@ -351,6 +323,7 @@ impl CStr { /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); &bytes[..bytes.len() - 1] @@ -364,86 +337,59 @@ impl CStr { /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes_with_nul(&self) -> &[u8] { unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for CStr { fn eq(&self, other: &CStr) -> bool { - self.to_bytes().eq(&other.to_bytes()) + self.to_bytes().eq(other.to_bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for CStr {} +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for CStr { fn partial_cmp(&self, other: &CStr) -> Option { self.to_bytes().partial_cmp(&other.to_bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for CStr { fn cmp(&self, other: &CStr) -> Ordering { self.to_bytes().cmp(&other.to_bytes()) } } -/// Deprecated in favor of `CStr` -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")] -pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { - let len = libc::strlen(*raw); - slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) -} - -/// Deprecated in favor of `CStr` -#[unstable(feature = "std_misc")] -#[deprecated(since = "1.0.0", - reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")] -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_parts(*(raw as *const _ as *const *const u8), len as usize) -} - -impl<'a> IntoBytes for &'a str { - fn into_bytes(self) -> Vec { self.as_bytes().to_vec() } -} -impl<'a> IntoBytes for &'a [u8] { - fn into_bytes(self) -> Vec { self.to_vec() } -} -impl IntoBytes for String { - fn into_bytes(self) -> Vec { self.into_bytes() } -} -impl IntoBytes for Vec { - fn into_bytes(self) -> Vec { self } -} - #[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"); + assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123"); + assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0"); } } #[test] fn simple() { - let s = CString::new(b"1234").unwrap(); + let s = CString::new("1234").unwrap(); assert_eq!(s.as_bytes(), b"1234"); assert_eq!(s.as_bytes_with_nul(), b"1234\0"); } #[test] fn build_with_zero1() { - assert!(CString::new(b"\0").is_err()); + assert!(CString::new(&b"\0"[..]).is_err()); } #[test] fn build_with_zero2() { @@ -460,7 +406,7 @@ mod tests { #[test] fn formatted() { - let s = CString::new(b"12").unwrap(); + let s = CString::new(&b"12"[..]).unwrap(); assert_eq!(format!("{:?}", s), "\"12\""); } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 1bff6afb77..1b7e913d46 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -10,24 +10,20 @@ //! Utilities related to FFI bindings. -#![unstable(feature = "std_misc", - reason = "module just underwent fairly large reorganization and the dust \ - still needs to settle")] +#![stable(feature = "rust1", since = "1.0.0")] -pub use self::c_str::{CString, CStr, NulError, IntoBytes}; -#[allow(deprecated)] -pub use self::c_str::c_str_to_bytes; -#[allow(deprecated)] -pub use self::c_str::c_str_to_bytes_with_nul; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::c_str::{CString, CStr, NulError}; -pub use self::os_str::OsString; -pub use self::os_str::OsStr; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::os_str::{OsString, OsStr}; mod c_str; mod os_str; // FIXME (#21670): these should be defined in the os_str module /// Freely convertible to an `&OsStr` slice. +#[unstable(feature = "std_misc")] pub trait AsOsStr { /// Convert to an `&OsStr` slice. fn as_os_str(&self) -> &OsStr; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 84149a2eb8..ab20efe25e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -29,20 +29,21 @@ //! for conversion to/from various other string types. Eventually these types //! will offer a full-fledged string API. -#![unstable(feature = "os", +#![unstable(feature = "os_str", reason = "recently added as part of path/io reform")] use core::prelude::*; -use borrow::{Borrow, ToOwned}; +use borrow::{Borrow, Cow, ToOwned}; +use ffi::CString; use fmt::{self, Debug}; use mem; -use string::{String, CowString}; +use string::String; use ops; use cmp; use hash::{Hash, Hasher}; -#[cfg(stage0)] use hash::Writer; use old_path::{Path, GenericPath}; +use vec::Vec; use sys::os_str::{Buf, Slice}; use sys_common::{AsInner, IntoInner, FromInner}; @@ -50,55 +51,95 @@ use super::AsOsStr; /// Owned, mutable OS strings. #[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { inner: Buf } /// Slices into OS strings. +#[stable(feature = "rust1", since = "1.0.0")] pub struct OsStr { inner: Slice } impl OsString { - /// Constructs an `OsString` at no cost by consuming a `String`. - pub fn from_string(s: String) -> OsString { - OsString { inner: Buf::from_string(s) } - } - - /// Constructs an `OsString` by copying from a `&str` slice. - /// - /// Equivalent to: `OsString::from_string(String::from_str(s))`. - pub fn from_str(s: &str) -> OsString { - OsString { inner: Buf::from_str(s) } - } - /// Constructs a new empty `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> OsString { OsString { inner: Buf::from_string(String::new()) } } + /// Construct an `OsString` from a byte sequence. + /// + /// # Platform behavior + /// + /// On Unix systems, any byte sequence can be successfully + /// converted into an `OsString`. + /// + /// On Windows system, only UTF-8 byte sequences will successfully + /// convert; non UTF-8 data will produce `None`. + #[unstable(feature = "convert", reason = "recently added")] + pub fn from_bytes(bytes: B) -> Option where B: Into> { + #[cfg(unix)] + fn from_bytes_inner(vec: Vec) -> Option { + use os::unix::ffi::OsStringExt; + Some(OsString::from_vec(vec)) + } + + #[cfg(windows)] + fn from_bytes_inner(vec: Vec) -> Option { + String::from_utf8(vec).ok().map(OsString::from) + } + + from_bytes_inner(bytes.into()) + } + + /// Convert to an `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_os_str(&self) -> &OsStr { + self + } + /// Convert the `OsString` into a `String` if it contains valid Unicode data. /// /// On failure, ownership of the original `OsString` is returned. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_string(self) -> Result { self.inner.into_string().map_err(|buf| OsString { inner: buf} ) } /// Extend the string with the given `&OsStr` slice. - pub fn push_os_str(&mut self, s: &OsStr) { - self.inner.push_slice(&s.inner) + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push>(&mut self, s: T) { + self.inner.push_slice(&s.as_ref().inner) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From for OsString { + fn from(s: String) -> OsString { + OsString { inner: Buf::from_string(s) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized + AsRef> From<&'a T> for OsString { + fn from(s: &'a T) -> OsString { + s.as_ref().to_os_string() } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Index for OsString { type Output = OsStr; #[inline] - fn index(&self, _index: &ops::RangeFull) -> &OsStr { + fn index(&self, _index: ops::RangeFull) -> &OsStr { unsafe { mem::transmute(self.inner.as_slice()) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for OsString { type Target = OsStr; @@ -108,32 +149,38 @@ impl ops::Deref for OsString { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Debug for OsString { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Debug::fmt(&**self, formatter) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsString { fn eq(&self, other: &OsString) -> bool { &**self == &**other } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsString { fn eq(&self, other: &str) -> bool { &**self == other } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for str { fn eq(&self, other: &OsString) -> bool { &**other == self } } +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for OsString {} +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsString { #[inline] fn partial_cmp(&self, other: &OsString) -> Option { @@ -149,6 +196,7 @@ impl PartialOrd for OsString { fn ge(&self, other: &OsString) -> bool { &**self >= &**other } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsString { #[inline] fn partial_cmp(&self, other: &str) -> Option { @@ -156,6 +204,7 @@ impl PartialOrd for OsString { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for OsString { #[inline] fn cmp(&self, other: &OsString) -> cmp::Ordering { @@ -163,14 +212,6 @@ impl Ord for OsString { } } -#[cfg(stage0)] -impl<'a, S: Hasher + Writer> Hash for OsString { - #[inline] - fn hash(&self, state: &mut S) { - (&**self).hash(state) - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for OsString { #[inline] @@ -180,7 +221,16 @@ impl Hash for OsString { } impl OsStr { + /// Coerce into an `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new + ?Sized>(s: &S) -> &OsStr { + s.as_ref() + } + /// Coerce directly from a `&str` slice to a `&OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", + reason = "use `OsStr::new` instead")] pub fn from_str(s: &str) -> &OsStr { unsafe { mem::transmute(Slice::from_str(s)) } } @@ -188,22 +238,55 @@ impl OsStr { /// Yield a `&str` slice if the `OsStr` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_str(&self) -> Option<&str> { self.inner.to_str() } - /// Convert an `OsStr` to a `CowString`. + /// Convert an `OsStr` to a `Cow`. /// /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. - pub fn to_string_lossy(&self) -> CowString { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() } /// Copy the slice into an owned `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_os_string(&self) -> OsString { OsString { inner: self.inner.to_owned() } } + /// Yield this `OsStr` as a byte slice. + /// + /// # Platform behavior + /// + /// On Unix systems, this is a no-op. + /// + /// On Windows systems, this returns `None` unless the `OsStr` is + /// valid unicode, in which case it produces UTF-8-encoded + /// data. This may entail checking validity. + #[unstable(feature = "convert", reason = "recently added")] + pub fn to_bytes(&self) -> Option<&[u8]> { + if cfg!(windows) { + self.to_str().map(|s| s.as_bytes()) + } else { + Some(self.bytes()) + } + } + + /// Create a `CString` containing this `OsStr` data. + /// + /// Fails if the `OsStr` contains interior nulls. + /// + /// This is a convenience for creating a `CString` from + /// `self.to_bytes()`, and inherits the platform behavior of the + /// `to_bytes` method. + #[unstable(feature = "convert", reason = "recently added")] + pub fn to_cstring(&self) -> Option { + self.to_bytes().and_then(|b| CString::new(b).ok()) + } + /// Get the underlying byte representation. /// /// Note: it is *crucial* that this API is private, to avoid @@ -213,26 +296,31 @@ impl OsStr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsStr { fn eq(&self, other: &OsStr) -> bool { self.bytes().eq(other.bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for OsStr { fn eq(&self, other: &str) -> bool { - *self == *OsStr::from_str(other) + *self == *OsStr::new(other) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for str { fn eq(&self, other: &OsStr) -> bool { - *other == *OsStr::from_str(self) + *other == *OsStr::new(self) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for OsStr {} +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &OsStr) -> Option { @@ -248,29 +336,23 @@ impl PartialOrd for OsStr { fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for OsStr { #[inline] fn partial_cmp(&self, other: &str) -> Option { - self.partial_cmp(OsStr::from_str(other)) + self.partial_cmp(OsStr::new(other)) } } // FIXME (#19470): cannot provide PartialOrd for str until we // have more flexible coherence rules. +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for OsStr { #[inline] fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) } } -#[cfg(stage0)] -impl<'a, S: Hasher + Writer> Hash for OsStr { - #[inline] - fn hash(&self, state: &mut S) { - self.bytes().hash(state) - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl Hash for OsStr { #[inline] @@ -279,60 +361,101 @@ impl Hash for OsStr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Debug for OsStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.inner.fmt(formatter) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Borrow for OsString { fn borrow(&self) -> &OsStr { &self[..] } } +#[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for OsStr { type Owned = OsString; fn to_owned(&self) -> OsString { self.to_os_string() } } +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T { fn as_os_str(&self) -> &OsStr { (*self).as_os_str() } } +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for OsStr { fn as_os_str(&self) -> &OsStr { self } } +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for OsString { fn as_os_str(&self) -> &OsStr { &self[..] } } +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for str { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(self) + unsafe { mem::transmute(Slice::from_str(self)) } } } +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for String { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(&self[..]) + unsafe { mem::transmute(Slice::from_str(self)) } } } -#[cfg(unix)] -impl AsOsStr for Path { - fn as_os_str(&self) -> &OsStr { - unsafe { mem::transmute(self.as_vec()) } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for OsStr { + fn as_ref(&self) -> &OsStr { + self } } -#[cfg(windows)] +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for OsString { + fn as_ref(&self) -> &OsStr { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for str { + fn as_ref(&self) -> &OsStr { + unsafe { mem::transmute(Slice::from_str(self)) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for String { + fn as_ref(&self) -> &OsStr { + unsafe { mem::transmute(Slice::from_str(self)) } + } +} + +#[allow(deprecated)] +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for Path { + #[cfg(unix)] + fn as_os_str(&self) -> &OsStr { + unsafe { mem::transmute(self.as_vec()) } + } + #[cfg(windows)] fn as_os_str(&self) -> &OsStr { // currently .as_str() is actually infallible on windows OsStr::from_str(self.as_str().unwrap()) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 69791084e2..eabc51beb1 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -15,12 +15,12 @@ //! operations. Extra platform-specific functionality can be found in the //! extension traits of `std::os::$platform`. -#![unstable(feature = "fs")] +#![stable(feature = "rust1", since = "1.0.0")] use core::prelude::*; use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write}; -use path::{AsPath, Path, PathBuf}; +use path::{Path, PathBuf}; use sys::fs2 as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner}; use vec::Vec; @@ -31,7 +31,7 @@ use vec::Vec; /// it was opened with. Files also implement `Seek` to alter the logical cursor /// that the file contains internally. /// -/// # Example +/// # Examples /// /// ```no_run /// use std::io::prelude::*; @@ -48,9 +48,10 @@ use vec::Vec; /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct File { inner: fs_imp::File, - path: PathBuf, + path: Option, } /// Metadata information about a file. @@ -58,6 +59,7 @@ pub struct File { /// This structure is returned from the `metadata` function or method and /// represents known metadata about a file such as its permissions, size, /// modification times, etc. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Metadata(fs_imp::FileAttr); /// Iterator over the entries in a directory. @@ -66,6 +68,12 @@ pub struct Metadata(fs_imp::FileAttr); /// will yield instances of `io::Result`. Through a `DirEntry` /// information like the entry's path and possibly other metadata can be /// learned. +/// +/// # Failure +/// +/// This `io::Result` will be an `Err` if there's some sort of intermittent +/// IO error during iteration. +#[stable(feature = "rust1", since = "1.0.0")] pub struct ReadDir(fs_imp::ReadDir); /// Entries returned by the `ReadDir` iterator. @@ -73,9 +81,14 @@ pub struct ReadDir(fs_imp::ReadDir); /// An instance of `DirEntry` represents an entry inside of a directory on the /// filesystem. Each entry can be inspected via methods to learn about the full /// path or possibly other metadata through per-platform extension traits. +#[stable(feature = "rust1", since = "1.0.0")] pub struct DirEntry(fs_imp::DirEntry); /// An iterator that recursively walks over the contents of a directory. +#[unstable(feature = "fs_walk", + reason = "the precise semantics and defaults for a recursive walk \ + may change and this may end up accounting for files such \ + as symlinks differently")] pub struct WalkDir { cur: Option, stack: Vec>, @@ -88,6 +101,7 @@ pub struct WalkDir { /// `File::create` methods are aliases for commonly used options using this /// builder. #[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OpenOptions(fs_imp::OpenOptions); /// Representation of the various permissions on a file. @@ -97,6 +111,7 @@ pub struct OpenOptions(fs_imp::OpenOptions); /// functionality, such as mode bits, is available through the /// `os::unix::PermissionsExt` trait. #[derive(Clone, PartialEq, Eq, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Permissions(fs_imp::FilePermissions); impl File { @@ -108,7 +123,19 @@ impl File { /// /// This function will return an error if `path` does not already exist. /// Other errors may also be returned according to `OpenOptions::open`. - pub fn open(path: &P) -> io::Result { + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn open>(path: P) -> io::Result { OpenOptions::new().read(true).open(path) } @@ -118,19 +145,50 @@ impl File { /// and will truncate it if it does. /// /// See the `OpenOptions::open` function for more details. - pub fn create(path: &P) -> io::Result { + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::create("foo.txt")); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn create>(path: P) -> io::Result { OpenOptions::new().write(true).create(true).truncate(true).open(path) } /// Returns the original path that was used to open this file. + #[unstable(feature = "file_path", + reason = "this abstraction is imposed by this library instead \ + of the underlying OS and may be removed")] pub fn path(&self) -> Option<&Path> { - Some(&self.path) + self.path.as_ref().map(|p| &**p) } /// Attempt to sync all OS-internal metadata to disk. /// /// This function will attempt to ensure that all in-core data reaches the /// filesystem before returning. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::io::prelude::*; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::create("foo.txt")); + /// try!(f.write_all(b"Hello, world!")); + /// + /// try!(f.sync_all()); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_all(&self) -> io::Result<()> { self.inner.fsync() } @@ -144,6 +202,22 @@ impl File { /// /// Note that some platforms may simply implement this in terms of /// `sync_all`. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::io::prelude::*; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::create("foo.txt")); + /// try!(f.write_all(b"Hello, world!")); + /// + /// try!(f.sync_data()); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn sync_data(&self) -> io::Result<()> { self.inner.datasync() } @@ -155,11 +229,37 @@ impl File { /// be shrunk. If it is greater than the current file's size, then the file /// will be extended to `size` and have all of the intermediate data filled /// in with 0s. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// try!(f.set_len(0)); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_len(&self, size: u64) -> io::Result<()> { self.inner.truncate(size) } - /// Queries information about the underlying file. + /// Queries metadata about the underlying file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let metadata = try!(f.metadata()); + /// # Ok(()) + /// # } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata(&self) -> io::Result { self.inner.file_attr().map(Metadata) } @@ -168,33 +268,45 @@ impl File { impl AsInner for File { fn as_inner(&self) -> &fs_imp::File { &self.inner } } +impl FromInner for File { + fn from_inner(f: fs_imp::File) -> File { + File { inner: f, path: None } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } +#[stable(feature = "rust1", since = "1.0.0")] impl Seek for File { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.inner.seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a File { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a File { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Seek for &'a File { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.inner.seek(pos) @@ -205,6 +317,7 @@ impl OpenOptions { /// Creates a blank net set of options ready for configuration. /// /// All options are initially set to `false`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> OpenOptions { OpenOptions(fs_imp::OpenOptions::new()) } @@ -213,6 +326,7 @@ impl OpenOptions { /// /// This option, when true, will indicate that the file should be /// `read`-able if opened. + #[stable(feature = "rust1", since = "1.0.0")] pub fn read(&mut self, read: bool) -> &mut OpenOptions { self.0.read(read); self } @@ -221,6 +335,7 @@ impl OpenOptions { /// /// This option, when true, will indicate that the file should be /// `write`-able if opened. + #[stable(feature = "rust1", since = "1.0.0")] pub fn write(&mut self, write: bool) -> &mut OpenOptions { self.0.write(write); self } @@ -229,6 +344,7 @@ impl OpenOptions { /// /// This option, when true, means that writes will append to a file instead /// of overwriting previous contents. + #[stable(feature = "rust1", since = "1.0.0")] pub fn append(&mut self, append: bool) -> &mut OpenOptions { self.0.append(append); self } @@ -237,6 +353,7 @@ impl OpenOptions { /// /// If a file is successfully opened with this option set it will truncate /// the file to 0 length if it already exists. + #[stable(feature = "rust1", since = "1.0.0")] pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions { self.0.truncate(truncate); self } @@ -245,6 +362,7 @@ impl OpenOptions { /// /// This option indicates whether a new file will be created if the file /// does not yet already exist. + #[stable(feature = "rust1", since = "1.0.0")] pub fn create(&mut self, create: bool) -> &mut OpenOptions { self.0.create(create); self } @@ -260,37 +378,33 @@ impl OpenOptions { /// * Attempting to open a file with access that the user lacks /// permissions for /// * Filesystem-level errors (full disk, etc) - pub fn open(&self, path: &P) -> io::Result { - let path = path.as_path(); + #[stable(feature = "rust1", since = "1.0.0")] + pub fn open>(&self, path: P) -> io::Result { + let path = path.as_ref(); let inner = try!(fs_imp::File::open(path, &self.0)); - - // On *BSD systems, we can open a directory as a file and read from - // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old - // tradition before the introduction of opendir(3). We explicitly - // reject it because there are few use cases. - if cfg!(not(any(target_os = "linux", target_os = "android"))) && - try!(inner.file_attr()).is_dir() { - Err(Error::new(ErrorKind::InvalidInput, "is a directory", None)) - } else { - Ok(File { path: path.to_path_buf(), inner: inner }) - } + Ok(File { path: Some(path.to_path_buf()), inner: inner }) } } + impl AsInnerMut for OpenOptions { fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } } impl Metadata { /// Returns whether this metadata is for a directory. + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() } /// Returns whether this metadata is for a regular file. + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.0.is_file() } /// Returns the size of the file, in bytes, this metadata is for. + #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> u64 { self.0.size() } /// Returns the permissions of the file this metadata is for. + #[stable(feature = "rust1", since = "1.0.0")] pub fn permissions(&self) -> Permissions { Permissions(self.0.perm()) } @@ -298,22 +412,32 @@ impl Metadata { /// Returns the most recent access time for a file. /// /// The return value is in milliseconds since the epoch. + #[unstable(feature = "fs_time", + reason = "the return type of u64 is not quite appropriate for \ + this method and may change if the standard library \ + gains a type to represent a moment in time")] pub fn accessed(&self) -> u64 { self.0.accessed() } /// Returns the most recent modification time for a file. /// /// The return value is in milliseconds since the epoch. + #[unstable(feature = "fs_time", + reason = "the return type of u64 is not quite appropriate for \ + this method and may change if the standard library \ + gains a type to represent a moment in time")] pub fn modified(&self) -> u64 { self.0.modified() } } impl Permissions { /// Returns whether these permissions describe a readonly file. + #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() } /// Modify the readonly flag for this set of permissions. /// /// This operation does **not** modify the filesystem. To modify the /// filesystem use the `fs::set_permissions` function. + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_readonly(&mut self, readonly: bool) { self.0.set_readonly(readonly) } @@ -325,6 +449,11 @@ impl FromInner for Permissions { } } +impl AsInner for Permissions { + fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ReadDir { type Item = io::Result; @@ -333,17 +462,19 @@ impl Iterator for ReadDir { } } +#[stable(feature = "rust1", since = "1.0.0")] impl DirEntry { /// Returns the full path to the file that this entry represents. /// /// The full path is created by joining the original path to `read_dir` or /// `walk_dir` with the filename of this entry. + #[stable(feature = "rust1", since = "1.0.0")] pub fn path(&self) -> PathBuf { self.0.path() } } /// Remove a file from the underlying filesystem. /// -/// # Example +/// # Examples /// /// ```rust,no_run /// use std::fs; @@ -360,31 +491,9 @@ impl DirEntry { /// This function will return an error if `path` points to a directory, if the /// user lacks permissions to remove the file, or if some other filesystem-level /// error occurs. -pub fn remove_file(path: &P) -> io::Result<()> { - let path = path.as_path(); - let e = match fs_imp::unlink(path) { - Ok(()) => return Ok(()), - Err(e) => e, - }; - if !cfg!(windows) { return Err(e) } - - // On unix, a readonly file can be successfully removed. On windows, - // however, it cannot. To keep the two platforms in line with - // respect to their behavior, catch this case on windows, attempt to - // change it to read-write, and then remove the file. - if e.kind() != ErrorKind::PermissionDenied { return Err(e) } - - let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) }; - let mut perms = attr.permissions(); - if !perms.readonly() { return Err(e) } - perms.set_readonly(false); - - if set_permissions(path, perms).is_err() { return Err(e) } - if fs_imp::unlink(path).is_ok() { return Ok(()) } - - // Oops, try to put things back the way we found it - let _ = set_permissions(path, attr.permissions()); - Err(e) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn remove_file>(path: P) -> io::Result<()> { + fs_imp::unlink(path.as_ref()) } /// Given a path, query the file system to get information about a file, @@ -393,7 +502,7 @@ pub fn remove_file(path: &P) -> io::Result<()> { /// This function will traverse soft links to query information about the /// destination file. /// -/// # Example +/// # Examples /// /// ```rust,no_run /// # fn foo() -> std::io::Result<()> { @@ -410,13 +519,14 @@ pub fn remove_file(path: &P) -> io::Result<()> { /// This function will return an error if the user lacks the requisite /// permissions to perform a `metadata` call on the given `path` or if there /// is no entry in the filesystem at the provided path. -pub fn metadata(path: &P) -> io::Result { - fs_imp::stat(path.as_path()).map(Metadata) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn metadata>(path: P) -> io::Result { + fs_imp::stat(path.as_ref()).map(Metadata) } /// Rename a file or directory to a new name. /// -/// # Example +/// # Examples /// /// ```rust,no_run /// use std::fs; @@ -430,9 +540,9 @@ pub fn metadata(path: &P) -> io::Result { /// the process lacks permissions to view the contents, if `from` and `to` /// reside on separate filesystems, or if some other intermittent I/O error /// occurs. -pub fn rename(from: &P, to: &Q) - -> io::Result<()> { - fs_imp::rename(from.as_path(), to.as_path()) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { + fs_imp::rename(from.as_ref(), to.as_ref()) } /// Copies the contents of one file to another. This function will also @@ -443,9 +553,9 @@ pub fn rename(from: &P, to: &Q) /// Note that if `from` and `to` both point to the same file, then the file /// will likely get truncated by this operation. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::fs; /// /// fs::copy("foo.txt", "bar.txt"); @@ -460,13 +570,13 @@ pub fn rename(from: &P, to: &Q) /// * The `from` file does not exist /// * The current process does not have the permission rights to access /// `from` or write `to` -pub fn copy(from: &P, to: &Q) - -> io::Result { - let from = from.as_path(); +#[stable(feature = "rust1", since = "1.0.0")] +pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { + let from = from.as_ref(); + let to = to.as_ref(); if !from.is_file() { - return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation, - "the source path is not an existing file", - None)) + return Err(Error::new(ErrorKind::InvalidInput, + "the source path is not an existing file")) } let mut reader = try!(File::open(from)); @@ -482,17 +592,17 @@ pub fn copy(from: &P, to: &Q) /// /// The `dst` path will be a link pointing to the `src` path. Note that systems /// often require these two paths to both be located on the same filesystem. -pub fn hard_link(src: &P, dst: &Q) - -> io::Result<()> { - fs_imp::link(src.as_path(), dst.as_path()) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { + fs_imp::link(src.as_ref(), dst.as_ref()) } /// Creates a new soft link on the filesystem. /// /// The `dst` path will be a soft link pointing to the `src` path. -pub fn soft_link(src: &P, dst: &Q) - -> io::Result<()> { - fs_imp::symlink(src.as_path(), dst.as_path()) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn soft_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { + fs_imp::symlink(src.as_ref(), dst.as_ref()) } /// Reads a soft link, returning the file that the link points to. @@ -502,15 +612,16 @@ pub fn soft_link(src: &P, dst: &Q) /// This function will return an error on failure. Failure conditions include /// reading a file that does not exist or reading a file that is not a soft /// link. -pub fn read_link(path: &P) -> io::Result { - fs_imp::readlink(path.as_path()) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn read_link>(path: P) -> io::Result { + fs_imp::readlink(path.as_ref()) } /// Create a new, empty directory at the provided path /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::fs; /// /// fs::create_dir("/some/dir"); @@ -520,8 +631,9 @@ pub fn read_link(path: &P) -> io::Result { /// /// This function will return an error if the user lacks permissions to make a /// new directory at the provided `path`, or if the directory already exists. -pub fn create_dir(path: &P) -> io::Result<()> { - fs_imp::mkdir(path.as_path()) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn create_dir>(path: P) -> io::Result<()> { + fs_imp::mkdir(path.as_ref()) } /// Recursively create a directory and all of its parent components if they @@ -533,21 +645,19 @@ pub fn create_dir(path: &P) -> io::Result<()> { /// does not already exist and it could not be created otherwise. The specific /// error conditions for when a directory is being created (after it is /// determined to not exist) are outlined by `fs::create_dir`. -pub fn create_dir_all(path: &P) -> io::Result<()> { - let path = path.as_path(); - if path.is_dir() { return Ok(()) } - match path.parent() { - Some(p) if p != path => try!(create_dir_all(p)), - _ => {} - } +#[stable(feature = "rust1", since = "1.0.0")] +pub fn create_dir_all>(path: P) -> io::Result<()> { + let path = path.as_ref(); + if path == Path::new("") || path.is_dir() { return Ok(()) } + if let Some(p) = path.parent() { try!(create_dir_all(p)) } create_dir(path) } /// Remove an existing, empty directory /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::fs; /// /// fs::remove_dir("/some/dir"); @@ -557,8 +667,9 @@ pub fn create_dir_all(path: &P) -> io::Result<()> { /// /// This function will return an error if the user lacks permissions to remove /// the directory at the provided `path`, or if the directory isn't empty. -pub fn remove_dir(path: &P) -> io::Result<()> { - fs_imp::rmdir(path.as_path()) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn remove_dir>(path: P) -> io::Result<()> { + fs_imp::rmdir(path.as_ref()) } /// Removes a directory at this path, after removing all its contents. Use @@ -570,8 +681,9 @@ pub fn remove_dir(path: &P) -> io::Result<()> { /// # Errors /// /// See `file::remove_file` and `fs::remove_dir` -pub fn remove_dir_all(path: &P) -> io::Result<()> { - let path = path.as_path(); +#[stable(feature = "rust1", since = "1.0.0")] +pub fn remove_dir_all>(path: P) -> io::Result<()> { + let path = path.as_ref(); for child in try!(read_dir(path)) { let child = try!(child).path(); let stat = try!(lstat(&*child)); @@ -594,9 +706,10 @@ pub fn remove_dir_all(path: &P) -> io::Result<()> { /// The iterator will yield instances of `io::Result`. New errors may /// be encountered after an iterator is initially constructed. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(path_ext)] /// use std::io; /// use std::fs::{self, PathExt, DirEntry}; /// use std::path::Path; @@ -622,8 +735,9 @@ pub fn remove_dir_all(path: &P) -> io::Result<()> { /// This function will return an error if the provided `path` doesn't exist, if /// the process lacks permissions to view the contents or if the `path` points /// at a non-directory file -pub fn read_dir(path: &P) -> io::Result { - fs_imp::readdir(path.as_path()).map(ReadDir) +#[stable(feature = "rust1", since = "1.0.0")] +pub fn read_dir>(path: P) -> io::Result { + fs_imp::readdir(path.as_ref()).map(ReadDir) } /// Returns an iterator that will recursively walk the directory structure @@ -634,11 +748,16 @@ pub fn read_dir(path: &P) -> io::Result { /// /// The iterator will yield instances of `io::Result`. New errors may /// be encountered after an iterator is initially constructed. -pub fn walk_dir(path: &P) -> io::Result { +#[unstable(feature = "fs_walk", + reason = "the precise semantics and defaults for a recursive walk \ + may change and this may end up accounting for files such \ + as symlinks differently")] +pub fn walk_dir>(path: P) -> io::Result { let start = try!(read_dir(path)); Ok(WalkDir { cur: Some(start), stack: Vec::new() }) } +#[unstable(feature = "fs_walk")] impl Iterator for WalkDir { type Item = io::Result; @@ -668,6 +787,9 @@ impl Iterator for WalkDir { } /// Utility methods for paths. +#[unstable(feature = "path_ext", + reason = "the precise set of methods exposed on this trait may \ + change and some methods may be removed")] pub trait PathExt { /// Get information on the file, directory, etc at this path. /// @@ -712,16 +834,21 @@ impl PathExt for Path { /// The file at the path specified will have its last access time set to /// `atime` and its modification time set to `mtime`. The times specified should /// be in milliseconds. -pub fn set_file_times(path: &P, accessed: u64, - modified: u64) -> io::Result<()> { - fs_imp::utimes(path.as_path(), accessed, modified) +#[unstable(feature = "fs_time", + reason = "the argument type of u64 is not quite appropriate for \ + this function and may change if the standard library \ + gains a type to represent a moment in time")] +pub fn set_file_times>(path: P, accessed: u64, + modified: u64) -> io::Result<()> { + fs_imp::utimes(path.as_ref(), accessed, modified) } /// Changes the permissions found on a file or a directory. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(fs)] /// # fn foo() -> std::io::Result<()> { /// use std::fs; /// @@ -737,16 +864,22 @@ pub fn set_file_times(path: &P, accessed: u64, /// This function will return an error if the provided `path` doesn't exist, if /// the process lacks permissions to change the attributes of the file, or if /// some other I/O error is encountered. -pub fn set_permissions(path: &P, perm: Permissions) - -> io::Result<()> { - fs_imp::set_perm(path.as_path(), perm.0) +#[unstable(feature = "fs", + reason = "a more granual ability to set specific permissions may \ + be exposed on the Permissions structure itself and this \ + method may not always exist")] +pub fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { + fs_imp::set_perm(path.as_ref(), perm.0) } #[cfg(test)] mod tests { + #![allow(deprecated)] //rand + use prelude::v1::*; use io::prelude::*; + use env; use fs::{self, File, OpenOptions}; use io::{ErrorKind, SeekFrom}; use path::PathBuf; @@ -765,7 +898,7 @@ mod tests { macro_rules! error { ($e:expr, $s:expr) => ( match $e { Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), - Err(ref err) => assert!(err.to_string().contains($s.as_slice()), + Err(ref err) => assert!(err.to_string().contains($s), format!("`{}` did not contain `{}`", err, $s)) } ) } @@ -794,8 +927,7 @@ mod tests { } pub fn tmpdir() -> TempDir { - let s = os::tmpdir(); - let p = Path2::new(s.as_str().unwrap()); + let p = env::temp_dir(); let ret = p.join(&format!("rust-{}", rand::random::())); check!(fs::create_dir(&ret)); TempDir(ret) @@ -814,10 +946,10 @@ mod tests { let mut read_stream = check!(File::open(filename)); let mut read_buf = [0; 1028]; let read_str = match check!(read_stream.read(&mut read_buf)) { - -1|0 => panic!("shouldn't happen"), + 0 => panic!("shouldn't happen"), n => str::from_utf8(&read_buf[..n]).unwrap().to_string() }; - assert_eq!(read_str.as_slice(), message); + assert_eq!(read_str, message); } check!(fs::remove_file(filename)); } @@ -1028,15 +1160,15 @@ mod tests { let dir = &tmpdir.join("di_readdir"); check!(fs::create_dir(dir)); let prefix = "foo"; - for n in range(0, 3) { + for n in 0..3 { let f = dir.join(&format!("{}.txt", n)); let mut w = check!(File::create(&f)); let msg_str = format!("{}{}", prefix, n.to_string()); let msg = msg_str.as_bytes(); check!(w.write(msg)); } - let mut files = check!(fs::read_dir(dir)); - let mut mem = [0u8; 4]; + let files = check!(fs::read_dir(dir)); + let mut mem = [0; 4]; for f in files { let f = f.unwrap().path(); { @@ -1044,7 +1176,7 @@ mod tests { check!(check!(File::open(&f)).read(&mut mem)); let read_str = str::from_utf8(&mem).unwrap(); let expected = format!("{}{}", prefix, n.to_str().unwrap()); - assert_eq!(expected.as_slice(), read_str); + assert_eq!(expected, read_str); } check!(fs::remove_file(&f)); } @@ -1065,8 +1197,8 @@ mod tests { check!(fs::create_dir_all(dir2)); check!(File::create(&dir2.join("14"))); - let mut files = check!(fs::walk_dir(dir)); - let mut cur = [0u8; 2]; + let files = check!(fs::walk_dir(dir)); + let mut cur = [0; 2]; for f in files { let f = f.unwrap().path(); let stem = f.file_stem().unwrap().to_str().unwrap(); @@ -1085,7 +1217,7 @@ mod tests { let dir = &tmpdir.join("mkdir_error_twice"); check!(fs::create_dir(dir)); let e = fs::create_dir(dir).err().unwrap(); - assert_eq!(e.kind(), ErrorKind::PathAlreadyExists); + assert_eq!(e.kind(), ErrorKind::AlreadyExists); } #[test] @@ -1195,7 +1327,7 @@ mod tests { check!(fs::copy(&input, &out)); let mut v = Vec::new(); check!(check!(File::open(&out)).read_to_end(&mut v)); - assert_eq!(v.as_slice(), b"hello"); + assert_eq!(v, b"hello"); assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions()); @@ -1250,6 +1382,8 @@ mod tests { check!(fs::set_permissions(&input, p)); check!(fs::copy(&input, &out)); assert!(check!(out.metadata()).permissions().readonly()); + check!(fs::set_permissions(&input, attr.permissions())); + check!(fs::set_permissions(&out, attr.permissions())); } #[cfg(not(windows))] // FIXME(#10264) operation not permitted? @@ -1333,10 +1467,13 @@ mod tests { let attr = check!(fs::metadata(&file)); assert!(attr.permissions().readonly()); - match fs::set_permissions(&tmpdir.join("foo"), p) { - Ok(..) => panic!("wanted a panic"), + match fs::set_permissions(&tmpdir.join("foo"), p.clone()) { + Ok(..) => panic!("wanted an error"), Err(..) => {} } + + p.set_readonly(false); + check!(fs::set_permissions(&file, p)); } #[test] @@ -1374,7 +1511,7 @@ mod tests { assert_eq!(v, b"foobar\0\0\0\0".to_vec()); // Truncate to a smaller length, don't seek, and then write something. - // Ensure that the intermediate zeroes are all filled in (we're seeked + // Ensure that the intermediate zeroes are all filled in (we have `seek`ed // past the end of the file). check!(file.set_len(2)); assert_eq!(check!(file.metadata()).len(), 2); @@ -1478,17 +1615,18 @@ mod tests { #[test] fn binary_file() { let mut bytes = [0; 1024]; - StdRng::new().ok().unwrap().fill_bytes(&mut bytes); + StdRng::new().unwrap().fill_bytes(&mut bytes); let tmpdir = tmpdir(); check!(check!(File::create(&tmpdir.join("test"))).write(&bytes)); let mut v = Vec::new(); check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v)); - assert!(v == bytes.as_slice()); + assert!(v == &bytes[..]); } #[test] + #[cfg(not(windows))] fn unlink_readonly() { let tmpdir = tmpdir(); let path = tmpdir.join("file"); @@ -1498,4 +1636,11 @@ mod tests { check!(fs::set_permissions(&path, perm)); check!(fs::remove_file(&path)); } + + #[test] + fn mkdir_trailing_slash() { + let tmpdir = tmpdir(); + let path = tmpdir.join("file"); + check!(fs::create_dir_all(&path.join("a/"))); + } } diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index e9a8dbb409..6fe35614a8 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -16,11 +16,11 @@ use prelude::v1::*; use io::prelude::*; use cmp; -use error::Error as StdError; -use error::FromError; +use error; use fmt; -use io::{self, Cursor, DEFAULT_BUF_SIZE, Error, ErrorKind}; +use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind}; use ptr; +use iter; /// Wraps a `Read` and buffers input from it /// @@ -28,79 +28,95 @@ use ptr; /// For example, every call to `read` on `TcpStream` results in a system call. /// A `BufReader` performs large, infrequent reads on the underlying `Read` /// and maintains an in-memory buffer of the results. +#[stable(feature = "rust1", since = "1.0.0")] pub struct BufReader { inner: R, - buf: Cursor>, + buf: Vec, + pos: usize, + cap: usize, } impl BufReader { /// Creates a new `BufReader` with a default buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: R) -> BufReader { BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new `BufReader` with the specified buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: R) -> BufReader { + let mut buf = Vec::with_capacity(cap); + buf.extend(iter::repeat(0).take(cap)); BufReader { inner: inner, - buf: Cursor::new(Vec::with_capacity(cap)), + buf: buf, + pos: 0, + cap: 0, } } /// Gets a reference to the underlying reader. - pub fn get_ref<'a>(&self) -> &R { &self.inner } + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_ref(&self) -> &R { &self.inner } /// Gets a mutable reference to the underlying reader. /// /// # Warning /// /// It is inadvisable to directly read from the underlying reader. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut R { &mut self.inner } /// Unwraps this `BufReader`, returning the underlying reader. /// /// Note that any leftover data in the internal buffer is lost. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> R { self.inner } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. - if self.buf.get_ref().len() == self.buf.position() as usize && - buf.len() >= self.buf.get_ref().capacity() { + if self.pos == self.cap && buf.len() >= self.buf.len() { return self.inner.read(buf); } - try!(self.fill_buf()); - self.buf.read(buf) + let nread = { + let mut rem = try!(self.fill_buf()); + try!(rem.read(buf)) + }; + self.consume(nread); + Ok(nread) } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { // If we've reached the end of our internal buffer then we need to fetch // some more data from the underlying reader. - if self.buf.position() as usize == self.buf.get_ref().len() { - self.buf.set_position(0); - let v = self.buf.get_mut(); - v.truncate(0); - let inner = &mut self.inner; - try!(super::with_end_to_cap(v, |b| inner.read(b))); + if self.pos == self.cap { + self.cap = try!(self.inner.read(&mut self.buf)); + self.pos = 0; } - self.buf.fill_buf() + Ok(&self.buf[self.pos..self.cap]) } - fn consume(&mut self, amt: uint) { - self.buf.consume(amt) + fn consume(&mut self, amt: usize) { + self.pos = cmp::min(self.pos + amt, self.cap); } } #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for BufReader where R: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "BufReader {{ reader: {:?}, buffer: {}/{} }}", - self.inner, self.buf.position(), self.buf.get_ref().len()) + fmt.debug_struct("BufReader") + .field("reader", &self.inner) + .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len())) + .finish() } } @@ -111,24 +127,29 @@ impl fmt::Debug for BufReader where R: fmt::Debug { /// `BufWriter` keeps an in memory buffer of data and writes it to the /// underlying `Write` in large, infrequent batches. /// -/// This writer will be flushed when it is dropped. -pub struct BufWriter { +/// The buffer will be written out when the writer is dropped. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct BufWriter { inner: Option, buf: Vec, } -/// An error returned by `into_inner` which indicates whether a flush error -/// happened or not. +/// An error returned by `into_inner` which combines an error that +/// happened while writing out the buffer, and the buffered writer object +/// which may be used to recover from the condition. #[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct IntoInnerError(W, Error); impl BufWriter { /// Creates a new `BufWriter` with a default buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> BufWriter { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } /// Creates a new `BufWriter` with the specified buffer capacity + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(cap: usize, inner: W) -> BufWriter { BufWriter { inner: Some(inner), @@ -144,10 +165,11 @@ impl BufWriter { match self.inner.as_mut().unwrap().write(&self.buf[written..]) { Ok(0) => { ret = Err(Error::new(ErrorKind::WriteZero, - "failed to flush", None)); + "failed to write the buffered data")); break; } Ok(n) => written += n, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => { ret = Err(e); break } } @@ -155,9 +177,9 @@ impl BufWriter { if written > 0 { // NB: would be better expressed as .remove(0..n) if it existed unsafe { - ptr::copy_memory(self.buf.as_mut_ptr(), - self.buf.as_ptr().offset(written as isize), - len - written); + ptr::copy(self.buf.as_ptr().offset(written as isize), + self.buf.as_mut_ptr(), + len - written); } } self.buf.truncate(len - written); @@ -165,6 +187,7 @@ impl BufWriter { } /// Gets a reference to the underlying writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } /// Gets a mutable reference to the underlying write. @@ -172,11 +195,13 @@ impl BufWriter { /// # Warning /// /// It is inadvisable to directly read from the underlying writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } /// Unwraps this `BufWriter`, returning the underlying writer. /// - /// The buffer is flushed before returning the writer. + /// The buffer is written out before returning the writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(mut self) -> Result>> { match self.flush_buf() { Err(e) => Err(IntoInnerError(self, e)), @@ -185,6 +210,7 @@ impl BufWriter { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for BufWriter { fn write(&mut self, buf: &[u8]) -> io::Result { if self.buf.len() + buf.len() > self.buf.capacity() { @@ -203,10 +229,12 @@ impl Write for BufWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for BufWriter where W: fmt::Debug { +impl fmt::Debug for BufWriter where W: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "BufWriter {{ writer: {:?}, buffer: {}/{} }}", - self.inner.as_ref().unwrap(), self.buf.len(), self.buf.capacity()) + fmt.debug_struct("BufWriter") + .field("writer", &self.inner.as_ref().unwrap()) + .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) + .finish() } } @@ -223,24 +251,31 @@ impl Drop for BufWriter { impl IntoInnerError { /// Returns the error which caused the call to `into_inner` to fail. /// - /// This error was returned when attempting to flush the internal buffer. + /// This error was returned when attempting to write the internal buffer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn error(&self) -> &Error { &self.1 } - /// Returns the underlying `BufWriter` instance which generated the error. + /// Returns the buffered writer instance which generated the error. /// - /// The returned object can be used to retry a flush or re-inspect the - /// buffer. + /// The returned object can be used for error recovery, such as + /// re-inspecting the buffer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> W { self.0 } } -impl FromError> for Error { - fn from_error(iie: IntoInnerError) -> Error { iie.1 } +#[stable(feature = "rust1", since = "1.0.0")] +impl From> for Error { + fn from(iie: IntoInnerError) -> Error { iie.1 } } -impl StdError for IntoInnerError { - fn description(&self) -> &str { self.error().description() } +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for IntoInnerError { + fn description(&self) -> &str { + error::Error::description(self.error()) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for IntoInnerError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.error().fmt(f) @@ -250,27 +285,42 @@ impl fmt::Display for IntoInnerError { /// Wraps a Writer and buffers output to it, flushing whenever a newline /// (`0x0a`, `'\n'`) is detected. /// -/// This writer will be flushed when it is dropped. -pub struct LineWriter { +/// The buffer will be written out when the writer is dropped. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct LineWriter { inner: BufWriter, } impl LineWriter { /// Creates a new `LineWriter` + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: W) -> LineWriter { // Lines typically aren't that long, don't use a giant buffer - LineWriter { inner: BufWriter::with_capacity(1024, inner) } + LineWriter::with_capacity(1024, inner) + } + + /// Creates a new `LineWriter` with a specified capacity for the internal + /// buffer. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(cap: usize, inner: W) -> LineWriter { + LineWriter { inner: BufWriter::with_capacity(cap, inner) } } /// Gets a reference to the underlying writer. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_ref(&self) -> &W { self.inner.get_ref() } + + /// Gets a mutable reference to the underlying writer. /// - /// This type does not expose the ability to get a mutable reference to the - /// underlying reader because that could possibly corrupt the buffer. - pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() } + /// Caution must be taken when calling methods on the mutable reference + /// returned as extra writes could corrupt the output stream. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Unwraps this `LineWriter`, returning the underlying writer. /// - /// The internal buffer is flushed before returning the writer. + /// The internal buffer is written out before returning the writer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result>> { self.inner.into_inner().map_err(|IntoInnerError(buf, e)| { IntoInnerError(LineWriter { inner: buf }, e) @@ -278,6 +328,7 @@ impl LineWriter { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for LineWriter { fn write(&mut self, buf: &[u8]) -> io::Result { match buf.rposition_elem(&b'\n') { @@ -295,24 +346,26 @@ impl Write for LineWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for LineWriter where W: fmt::Debug { +impl fmt::Debug for LineWriter where W: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "LineWriter {{ writer: {:?}, buffer: {}/{} }}", - self.inner.inner, self.inner.buf.len(), - self.inner.buf.capacity()) + fmt.debug_struct("LineWriter") + .field("writer", &self.inner.inner) + .field("buffer", + &format_args!("{}/{}", self.inner.buf.len(), self.inner.buf.capacity())) + .finish() } } -struct InternalBufWriter(BufWriter); +struct InternalBufWriter(BufWriter); -impl InternalBufWriter { +impl InternalBufWriter { fn get_mut(&mut self) -> &mut BufWriter { let InternalBufWriter(ref mut w) = *self; return w; } } -impl Read for InternalBufWriter { +impl Read for InternalBufWriter { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().inner.as_mut().unwrap().read(buf) } @@ -320,19 +373,21 @@ impl Read for InternalBufWriter { /// Wraps a Stream and buffers input and output to and from it. /// -/// It can be excessively inefficient to work directly with a `Stream`. For +/// It can be excessively inefficient to work directly with a `Read+Write`. For /// example, every call to `read` or `write` on `TcpStream` results in a system /// call. A `BufStream` keeps in memory buffers of data, making large, -/// infrequent calls to `read` and `write` on the underlying `Stream`. +/// infrequent calls to `read` and `write` on the underlying `Read+Write`. /// -/// The output half will be flushed when this stream is dropped. -pub struct BufStream { +/// The output buffer will be written out when this stream is dropped. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct BufStream { inner: BufReader> } impl BufStream { /// Creates a new buffered stream with explicitly listed capacities for the /// reader/writer buffer. + #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S) -> BufStream { let writer = BufWriter::with_capacity(writer_cap, inner); @@ -343,11 +398,13 @@ impl BufStream { /// Creates a new buffered stream with the default reader/writer buffer /// capacities. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: S) -> BufStream { BufStream::with_capacities(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE, inner) } /// Gets a reference to the underlying stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &S { let InternalBufWriter(ref w) = self.inner.inner; w.get_ref() @@ -359,6 +416,7 @@ impl BufStream { /// /// It is inadvisable to read directly from or write directly to the /// underlying stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut S { let InternalBufWriter(ref mut w) = self.inner.inner; w.get_mut() @@ -366,29 +424,33 @@ impl BufStream { /// Unwraps this `BufStream`, returning the underlying stream. /// - /// The internal buffer is flushed before returning the stream. Any leftover - /// data in the read buffer is lost. + /// The internal write buffer is written out before returning the stream. + /// Any leftover data in the read buffer is lost. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> Result>> { - let BufReader { inner: InternalBufWriter(w), buf } = self.inner; + let BufReader { inner: InternalBufWriter(w), buf, pos, cap } = self.inner; w.into_inner().map_err(|IntoInnerError(w, e)| { IntoInnerError(BufStream { - inner: BufReader { inner: InternalBufWriter(w), buf: buf }, + inner: BufReader { inner: InternalBufWriter(w), buf: buf, pos: pos, cap: cap }, }, e) }) } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for BufStream { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } - fn consume(&mut self, amt: uint) { self.inner.consume(amt) } + fn consume(&mut self, amt: usize) { self.inner.consume(amt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for BufStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for BufStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.inner.get_mut().write(buf) @@ -399,14 +461,16 @@ impl Write for BufStream { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for BufStream where S: fmt::Debug { +impl fmt::Debug for BufStream where S: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let reader = &self.inner; let writer = &self.inner.inner.0; - write!(fmt, "BufStream {{ stream: {:?}, write_buffer: {}/{}, read_buffer: {}/{} }}", - writer.inner, - writer.buf.len(), writer.buf.capacity(), - reader.buf.position(), reader.buf.get_ref().len()) + fmt.debug_struct("BufStream") + .field("stream", &writer.inner) + .field("write_buffer", &format_args!("{}/{}", writer.buf.len(), writer.buf.capacity())) + .field("read_buffer", + &format_args!("{}/{}", reader.cap - reader.pos, reader.buf.len())) + .finish() } } @@ -439,34 +503,34 @@ mod tests { let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(3), nread); + assert_eq!(nread.unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(buf, b); let mut buf = [0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(2), nread); + assert_eq!(nread.unwrap(), 2); let b: &[_] = &[0, 1]; assert_eq!(buf, b); let mut buf = [0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[2]; assert_eq!(buf, b); let mut buf = [0, 0, 0]; let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[3, 0, 0]; assert_eq!(buf, b); let nread = reader.read(&mut buf); - assert_eq!(Ok(1), nread); + assert_eq!(nread.unwrap(), 1); let b: &[_] = &[4, 0, 0]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] @@ -497,7 +561,6 @@ mod tests { assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]); writer.write(&[9, 10, 11]).unwrap(); - let a: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); writer.flush().unwrap(); @@ -529,7 +592,7 @@ mod tests { } let mut stream = BufStream::new(S); - assert_eq!(stream.read(&mut [0; 10]), Ok(0)); + assert_eq!(stream.read(&mut [0; 10]).unwrap(), 0); stream.write(&[0; 10]).unwrap(); stream.flush().unwrap(); } @@ -574,7 +637,7 @@ mod tests { #[test] fn test_read_line() { - let in_buf = b"a\nb\nc"; + let in_buf: &[u8] = b"a\nb\nc"; let mut reader = BufReader::with_capacity(2, in_buf); let mut s = String::new(); reader.read_line(&mut s).unwrap(); @@ -592,13 +655,13 @@ mod tests { #[test] fn test_lines() { - let in_buf = b"a\nb\nc"; - let mut reader = BufReader::with_capacity(2, in_buf); + let in_buf: &[u8] = b"a\nb\nc"; + let reader = BufReader::with_capacity(2, in_buf); let mut it = reader.lines(); - assert_eq!(it.next(), Some(Ok("a".to_string()))); - assert_eq!(it.next(), Some(Ok("b".to_string()))); - assert_eq!(it.next(), Some(Ok("c".to_string()))); - assert_eq!(it.next(), None); + assert_eq!(it.next().unwrap().unwrap(), "a".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "b".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "c".to_string()); + assert!(it.next().is_none()); } #[test] @@ -606,34 +669,34 @@ mod tests { let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]}; let mut reader = BufReader::new(inner); let mut buf = [0, 0]; - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(1)); - assert_eq!(reader.read(&mut buf), Ok(2)); - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(1)); - assert_eq!(reader.read(&mut buf), Ok(0)); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 2); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn read_char_buffered() { - let buf = [195u8, 159u8]; - let mut reader = BufReader::with_capacity(1, &buf[..]); - assert_eq!(reader.chars().next(), Some(Ok('ß'))); + let buf = [195, 159]; + let reader = BufReader::with_capacity(1, &buf[..]); + assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß'); } #[test] fn test_chars() { - let buf = [195u8, 159u8, b'a']; - let mut reader = BufReader::with_capacity(1, &buf[..]); + let buf = [195, 159, b'a']; + let reader = BufReader::with_capacity(1, &buf[..]); let mut it = reader.chars(); - assert_eq!(it.next(), Some(Ok('ß'))); - assert_eq!(it.next(), Some(Ok('a'))); - assert_eq!(it.next(), None); + assert_eq!(it.next().unwrap().unwrap(), 'ß'); + assert_eq!(it.next().unwrap().unwrap(), 'a'); + assert!(it.next().is_none()); } #[test] - #[should_fail] + #[should_panic] fn dont_panic_in_drop_on_panicked_flush() { struct FailFlushWriter; diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index f6cb4a8c9f..6433c29bb9 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -8,30 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(missing_copy_implementations)] - use prelude::v1::*; use io::prelude::*; use cmp; use io::{self, SeekFrom, Error, ErrorKind}; use iter::repeat; -use num::Int; use slice; -/// A `Cursor` is a type which wraps another I/O object to provide a `Seek` +/// A `Cursor` is a type which wraps a non-I/O object to provide a `Seek` /// implementation. /// -/// Cursors are currently typically used with memory buffer objects in order to -/// allow `Seek` plus `Read` and `Write` implementations. For example, common -/// cursor types include: -/// -/// * `Cursor>` -/// * `Cursor<&[u8]>` +/// Cursors are typically used with memory buffer objects in order to allow +/// `Seek`, `Read`, and `Write` implementations. For example, common cursor types +/// include `Cursor>` and `Cursor<&[u8]>`. /// -/// Implementations of the I/O traits for `Cursor` are not currently generic +/// Implementations of the I/O traits for `Cursor` are currently not generic /// over `T` itself. Instead, specific implementations are provided for various /// in-memory buffer types like `Vec` and `&[u8]`. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone, Debug)] pub struct Cursor { inner: T, pos: u64, @@ -39,26 +35,32 @@ pub struct Cursor { impl Cursor { /// Create a new cursor wrapping the provided underlying I/O object. + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: T) -> Cursor { Cursor { pos: 0, inner: inner } } /// Consume this cursor, returning the underlying value. + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> T { self.inner } /// Get a reference to the underlying value in this cursor. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_ref(&self) -> &T { &self.inner } /// Get a mutable reference to the underlying value in this cursor. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying value as it may corrupt this cursor's position. + #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut T { &mut self.inner } /// Returns the current value of this cursor + #[stable(feature = "rust1", since = "1.0.0")] pub fn position(&self) -> u64 { self.pos } /// Sets the value of this cursor + #[stable(feature = "rust1", since = "1.0.0")] pub fn set_position(&mut self, pos: u64) { self.pos = pos; } } @@ -73,8 +75,7 @@ macro_rules! seek { if pos < 0 { Err(Error::new(ErrorKind::InvalidInput, - "invalid seek to a negative position", - None)) + "invalid seek to a negative position")) } else { self.pos = pos as u64; Ok(self.pos) @@ -83,8 +84,11 @@ macro_rules! seek { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> io::Seek for Cursor<&'a [u8]> { seek!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> io::Seek for Cursor<&'a mut [u8]> { seek!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl io::Seek for Cursor> { seek!(); } macro_rules! read { @@ -97,8 +101,11 @@ macro_rules! read { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for Cursor<&'a [u8]> { read!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for Cursor<&'a mut [u8]> { read!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Cursor> { read!(); } macro_rules! buffer { @@ -111,10 +118,14 @@ macro_rules! buffer { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor<&'a [u8]> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor<&'a mut [u8]> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for Cursor> { buffer!(); } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for Cursor<&'a mut [u8]> { fn write(&mut self, data: &[u8]) -> io::Result { let pos = cmp::min(self.pos, self.inner.len() as u64); @@ -125,6 +136,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Cursor> { fn write(&mut self, buf: &[u8]) -> io::Result { // Make sure the internal buffer is as least as big as where we @@ -137,7 +149,7 @@ impl Write for Cursor> { // there (left), and what will be appended on the end (right) let space = self.inner.len() - pos as usize; let (left, right) = buf.split_at(cmp::min(space, buf.len())); - slice::bytes::copy_memory(&mut self.inner[(pos as usize)..], left); + slice::bytes::copy_memory(left, &mut self.inner[(pos as usize)..]); self.inner.push_all(right); // Bump us forward @@ -159,9 +171,9 @@ mod tests { #[test] fn test_vec_writer() { let mut writer = Vec::new(); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; assert_eq!(writer, b); } @@ -169,11 +181,11 @@ mod tests { #[test] fn test_mem_writer() { let mut writer = Cursor::new(Vec::new()); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); } #[test] @@ -182,16 +194,16 @@ mod tests { { let mut writer = Cursor::new(&mut buf[..]); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[0]), Ok(1)); + assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); assert_eq!(writer.position(), 8); - assert_eq!(writer.write(&[]), Ok(0)); + assert_eq!(writer.write(&[]).unwrap(), 0); assert_eq!(writer.position(), 8); - assert_eq!(writer.write(&[8, 9]), Ok(1)); - assert_eq!(writer.write(&[10]), Ok(0)); + assert_eq!(writer.write(&[8, 9]).unwrap(), 1); + assert_eq!(writer.write(&[10]).unwrap(), 0); } let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; assert_eq!(buf, b); @@ -203,22 +215,22 @@ mod tests { { let mut writer = Cursor::new(&mut buf[..]); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[1]), Ok(1)); + assert_eq!(writer.write(&[1]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.seek(SeekFrom::Start(2)), Ok(2)); + assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2); assert_eq!(writer.position(), 2); - assert_eq!(writer.write(&[2]), Ok(1)); + assert_eq!(writer.write(&[2]).unwrap(), 1); assert_eq!(writer.position(), 3); - assert_eq!(writer.seek(SeekFrom::Current(-2)), Ok(1)); + assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[3]), Ok(1)); + assert_eq!(writer.write(&[3]).unwrap(), 1); assert_eq!(writer.position(), 2); - assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); assert_eq!(writer.position(), 7); - assert_eq!(writer.write(&[4]), Ok(1)); + assert_eq!(writer.write(&[4]).unwrap(), 1); assert_eq!(writer.position(), 8); } @@ -230,100 +242,100 @@ mod tests { fn test_buf_writer_error() { let mut buf = [0 as u8; 2]; let mut writer = Cursor::new(&mut buf[..]); - assert_eq!(writer.write(&[0]), Ok(1)); - assert_eq!(writer.write(&[0, 0]), Ok(1)); - assert_eq!(writer.write(&[0, 0]), Ok(0)); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 0); } #[test] fn test_mem_reader() { - let mut reader = Cursor::new(vec!(0u8, 1, 2, 3, 4, 5, 6, 7)); + let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.position(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.position(), 1); let b: &[_] = &[0]; assert_eq!(buf, b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.position(), 5); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn read_to_end() { - let mut reader = Cursor::new(vec!(0u8, 1, 2, 3, 4, 5, 6, 7)); + let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); let mut v = Vec::new(); - reader.read_to_end(&mut v).ok().unwrap(); + reader.read_to_end(&mut v).unwrap(); assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]); } #[test] fn test_slice_reader() { - let in_buf = vec![0u8, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = &mut in_buf.as_slice(); + let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let mut reader = &mut &in_buf[..]; let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.len(), 7); let b: &[_] = &[0]; - assert_eq!(buf.as_slice(), b); + assert_eq!(&buf[..], b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.len(), 3); let b: &[_] = &[1, 2, 3, 4]; - assert_eq!(buf.as_slice(), b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(&buf[..], b); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn test_buf_reader() { - let in_buf = vec![0u8, 1, 2, 3, 4, 5, 6, 7]; - let mut reader = Cursor::new(in_buf.as_slice()); + let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let mut reader = Cursor::new(&in_buf[..]); let mut buf = []; - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); assert_eq!(reader.position(), 0); let mut buf = [0]; - assert_eq!(reader.read(&mut buf), Ok(1)); + assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.position(), 1); let b: &[_] = &[0]; assert_eq!(buf, b); let mut buf = [0; 4]; - assert_eq!(reader.read(&mut buf), Ok(4)); + assert_eq!(reader.read(&mut buf).unwrap(), 4); assert_eq!(reader.position(), 5); let b: &[_] = &[1, 2, 3, 4]; assert_eq!(buf, b); - assert_eq!(reader.read(&mut buf), Ok(3)); + assert_eq!(reader.read(&mut buf).unwrap(), 3); let b: &[_] = &[5, 6, 7]; assert_eq!(&buf[..3], b); - assert_eq!(reader.read(&mut buf), Ok(0)); + assert_eq!(reader.read(&mut buf).unwrap(), 0); } #[test] fn test_read_char() { - let b = b"Vi\xE1\xBB\x87t"; + let b = &b"Vi\xE1\xBB\x87t"[..]; let mut c = Cursor::new(b).chars(); - assert_eq!(c.next(), Some(Ok('V'))); - assert_eq!(c.next(), Some(Ok('i'))); - assert_eq!(c.next(), Some(Ok('ệ'))); - assert_eq!(c.next(), Some(Ok('t'))); - assert_eq!(c.next(), None); + assert_eq!(c.next().unwrap().unwrap(), 'V'); + assert_eq!(c.next().unwrap().unwrap(), 'i'); + assert_eq!(c.next().unwrap().unwrap(), 'ệ'); + assert_eq!(c.next().unwrap().unwrap(), 't'); + assert!(c.next().is_none()); } #[test] fn test_read_bad_char() { - let b = b"\x80"; + let b = &b"\x80"[..]; let mut c = Cursor::new(b).chars(); assert!(c.next().unwrap().is_err()); } @@ -332,26 +344,26 @@ mod tests { fn seek_past_end() { let buf = [0xff]; let mut r = Cursor::new(&buf[..]); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.read(&mut [0]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); - let mut r = Cursor::new(vec!(10u8)); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.read(&mut [0]), Ok(0)); + let mut r = Cursor::new(vec!(10)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); let mut buf = [0]; let mut r = Cursor::new(&mut buf[..]); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.write(&[3]), Ok(0)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 0); } #[test] fn seek_before_0() { - let buf = [0xff_u8]; + let buf = [0xff]; let mut r = Cursor::new(&buf[..]); assert!(r.seek(SeekFrom::End(-2)).is_err()); - let mut r = Cursor::new(vec!(10u8)); + let mut r = Cursor::new(vec!(10)); assert!(r.seek(SeekFrom::End(-2)).is_err()); let mut buf = [0]; @@ -363,41 +375,41 @@ mod tests { fn test_seekable_mem_writer() { let mut writer = Cursor::new(Vec::::new()); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[0]), Ok(1)); + assert_eq!(writer.write(&[0]).unwrap(), 1); assert_eq!(writer.position(), 1); - assert_eq!(writer.write(&[1, 2, 3]), Ok(3)); - assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4)); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); assert_eq!(writer.position(), 8); let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0)); + assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0); assert_eq!(writer.position(), 0); - assert_eq!(writer.write(&[3, 4]), Ok(2)); + assert_eq!(writer.write(&[3, 4]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3)); - assert_eq!(writer.write(&[0, 1]), Ok(2)); + assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3); + assert_eq!(writer.write(&[0, 1]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7)); - assert_eq!(writer.write(&[1, 2]), Ok(2)); + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); + assert_eq!(writer.write(&[1, 2]).unwrap(), 2); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); - assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10)); - assert_eq!(writer.write(&[1]), Ok(1)); + assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10); + assert_eq!(writer.write(&[1]).unwrap(), 1); let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); } #[test] fn vec_seek_past_end() { let mut r = Cursor::new(Vec::new()); - assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10)); - assert_eq!(r.write(&[3]), Ok(1)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 1); } #[test] diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 9f3cd8c8b1..b84dcb8fb6 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -9,12 +9,12 @@ // except according to those terms. use boxed::Box; -use clone::Clone; -use error::Error as StdError; +use convert::Into; +use error; use fmt; +use marker::Send; use option::Option::{self, Some, None}; use result; -use string::String; use sys; /// A type for results generated by I/O related functions where the `Err` type @@ -22,6 +22,7 @@ use sys; /// /// This typedef is generally used to avoid writing out `io::Error` directly and /// is otherwise a direct mapping to `std::result::Result`. +#[stable(feature = "rust1", since = "1.0.0")] pub type Result = result::Result; /// The error type for I/O operations of the `Read`, `Write`, `Seek`, and @@ -30,56 +31,72 @@ pub type Result = result::Result; /// Errors mostly originate from the underlying OS, but custom instances of /// `Error` can be created with crafted error messages and a particular value of /// `ErrorKind`. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Error { repr: Repr, } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] enum Repr { Os(i32), Custom(Box), } -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(Debug)] struct Custom { kind: ErrorKind, - desc: &'static str, - detail: Option + error: Box, } /// A list specifying general categories of I/O error. +/// +/// This list is intended to grow over time and it is not recommended to +/// exhaustively match against it. #[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum ErrorKind { - /// The file was not found. - FileNotFound, - /// The file permissions disallowed access to this file. + /// An entity was not found, often a file. + #[stable(feature = "rust1", since = "1.0.0")] + NotFound, + /// The operation lacked the necessary privileges to complete. + #[stable(feature = "rust1", since = "1.0.0")] PermissionDenied, /// The connection was refused by the remote server. + #[stable(feature = "rust1", since = "1.0.0")] ConnectionRefused, /// The connection was reset by the remote server. + #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, /// The connection was aborted (terminated) by the remote server. + #[stable(feature = "rust1", since = "1.0.0")] ConnectionAborted, /// The network operation failed because it was not connected yet. + #[stable(feature = "rust1", since = "1.0.0")] NotConnected, + /// A socket address could not be bound because the address is already in + /// use elsewhere. + #[stable(feature = "rust1", since = "1.0.0")] + AddrInUse, + /// A nonexistent interface was requested or the requested address was not + /// local. + #[stable(feature = "rust1", since = "1.0.0")] + AddrNotAvailable, /// The operation failed because a pipe was closed. + #[stable(feature = "rust1", since = "1.0.0")] BrokenPipe, - /// A file already existed with that name. - PathAlreadyExists, - /// No file exists at that location. - PathDoesntExist, - /// The path did not specify the type of file that this operation required. - /// For example, attempting to copy a directory with the `fs::copy()` - /// operation will fail with this error. - MismatchedFileTypeForOperation, - /// The operation temporarily failed (for example, because a signal was - /// received), and retrying may succeed. - ResourceUnavailable, - /// A parameter was incorrect in a way that caused an I/O error not part of - /// this list. + /// An entity already exists, often a file. + #[stable(feature = "rust1", since = "1.0.0")] + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was + /// requested to not occur. + #[stable(feature = "rust1", since = "1.0.0")] + WouldBlock, + /// A parameter was incorrect. + #[stable(feature = "rust1", since = "1.0.0")] InvalidInput, /// The I/O operation's timeout expired, causing it to be canceled. + #[stable(feature = "rust1", since = "1.0.0")] TimedOut, /// An error returned when an operation could not be completed because a /// call to `write` returned `Ok(0)`. @@ -87,23 +104,54 @@ pub enum ErrorKind { /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. + #[stable(feature = "rust1", since = "1.0.0")] WriteZero, - /// This operation was interrupted + /// This operation was interrupted. + /// + /// Interrupted operations can typically be retried. + #[stable(feature = "rust1", since = "1.0.0")] Interrupted, /// Any I/O error not part of this list. + #[stable(feature = "rust1", since = "1.0.0")] Other, + + /// Any I/O error not part of this list. + #[unstable(feature = "std_misc", + reason = "better expressed through extensible enums that this \ + enum cannot be exhaustively matched against")] + #[doc(hidden)] + __Nonexhaustive, } impl Error { - /// Creates a new custom error from a specified kind/description/detail. - pub fn new(kind: ErrorKind, - description: &'static str, - detail: Option) -> Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. The `error` argument is an arbitrary + /// payload which will be contained in this `Error`. Accessors as well as + /// downcasting will soon be added to this type as well to access the custom + /// information. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(kind: ErrorKind, error: E) -> Error + where E: Into> + { Error { repr: Repr::Custom(Box::new(Custom { kind: kind, - desc: description, - detail: detail, + error: error.into(), })) } } @@ -113,40 +161,41 @@ impl Error { /// This function reads the value of `errno` for the target platform (e.g. /// `GetLastError` on Windows) and will return a corresponding instance of /// `Error` for the error code. + #[stable(feature = "rust1", since = "1.0.0")] pub fn last_os_error() -> Error { Error::from_os_error(sys::os::errno() as i32) } /// Creates a new instance of an `Error` from a particular OS error code. + #[unstable(feature = "io", + reason = "unclear whether this function is necessary")] pub fn from_os_error(code: i32) -> Error { Error { repr: Repr::Os(code) } } - /// Return the corresponding `ErrorKind` for this error. - pub fn kind(&self) -> ErrorKind { - match self.repr { - Repr::Os(code) => sys::decode_error_kind(code), - Repr::Custom(ref c) => c.kind, - } - } - - /// Returns a short description for this error message - pub fn description(&self) -> &str { + /// Returns the OS error that this error represents (if any). + /// + /// If this `Error` was constructed via `last_os_error` then this function + /// will return `Some`, otherwise it will return `None`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn raw_os_error(&self) -> Option { match self.repr { - Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, + Repr::Os(i) => Some(i), + Repr::Custom(..) => None, } } - /// Returns a detailed error message for this error (if one is available) - pub fn detail(&self) -> Option { + /// Return the corresponding `ErrorKind` for this error. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn kind(&self) -> ErrorKind { match self.repr { - Repr::Os(code) => Some(sys::os::error_string(code)), - Repr::Custom(ref s) => s.detail.clone(), + Repr::Os(code) => sys::decode_error_kind(code), + Repr::Custom(ref c) => c.kind, } } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.repr { @@ -154,30 +203,17 @@ impl fmt::Display for Error { let detail = sys::os::error_string(code); write!(fmt, "{} (os error {})", detail, code) } - Repr::Custom(ref c) => { - match **c { - Custom { - kind: ErrorKind::Other, - desc: "unknown error", - detail: Some(ref detail) - } => { - write!(fmt, "{}", detail) - } - Custom { detail: None, desc, .. } => - write!(fmt, "{}", desc), - Custom { detail: Some(ref detail), desc, .. } => - write!(fmt, "{} ({})", desc, detail) - } - } + Repr::Custom(ref c) => c.error.fmt(fmt), } } } -impl StdError for Error { +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) => "os error", - Repr::Custom(ref c) => c.desc, + Repr::Custom(ref c) => c.error.description(), } } } diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 7f3ce7924c..67bc45d3b6 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -12,77 +12,259 @@ use core::prelude::*; use boxed::Box; use cmp; -use io::{self, SeekFrom, Read, Write, Seek, BufRead}; +use io::{self, SeekFrom, Read, Write, Seek, BufRead, Error, ErrorKind}; +use fmt; use mem; use slice; +use string::String; use vec::Vec; // ============================================================================= // Forwarding implementations +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, R: Read + ?Sized> Read for &'a mut R { - fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (**self).read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (**self).read_to_string(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, W: Write + ?Sized> Write for &'a mut W { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } + + #[inline] fn flush(&mut self) -> io::Result<()> { (**self).flush() } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, S: Seek + ?Sized> Seek for &'a mut S { + #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } + + #[inline] fn consume(&mut self, amt: usize) { (**self).consume(amt) } + + #[inline] + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result { + (**self).read_until(byte, buf) + } + + #[inline] + fn read_line(&mut self, buf: &mut String) -> io::Result { + (**self).read_line(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Box { - fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (**self).read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (**self).read_to_string(buf) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Box { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } + + #[inline] fn flush(&mut self) -> io::Result<()> { (**self).flush() } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } } +#[stable(feature = "rust1", since = "1.0.0")] impl Seek for Box { + #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } } +#[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Box { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } + + #[inline] fn consume(&mut self, amt: usize) { (**self).consume(amt) } + + #[inline] + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result { + (**self).read_until(byte, buf) + } + + #[inline] + fn read_line(&mut self, buf: &mut String) -> io::Result { + (**self).read_line(buf) + } } // ============================================================================= // In-memory buffer implementations +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a [u8] { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { let amt = cmp::min(buf.len(), self.len()); let (a, b) = self.split_at(amt); - slice::bytes::copy_memory(buf, a); + slice::bytes::copy_memory(a, buf); *self = b; Ok(amt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> BufRead for &'a [u8] { + #[inline] fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } + + #[inline] fn consume(&mut self, amt: usize) { *self = &self[amt..]; } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a mut [u8] { + #[inline] fn write(&mut self, data: &[u8]) -> io::Result { let amt = cmp::min(data.len(), self.len()); let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); - slice::bytes::copy_memory(a, &data[..amt]); + slice::bytes::copy_memory(&data[..amt], a); *self = b; Ok(amt) } + + #[inline] + fn write_all(&mut self, data: &[u8]) -> io::Result<()> { + if try!(self.write(data)) == data.len() { + Ok(()) + } else { + Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) + } + } + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Vec { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.push_all(buf); Ok(buf.len()) } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.push_all(buf); + Ok(()) + } + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } + +#[cfg(test)] +mod tests { + use io::prelude::*; + use vec::Vec; + use test; + + #[bench] + fn bench_read_slice(b: &mut test::Bencher) { + let buf = [5; 1024]; + let mut dst = [0; 128]; + + b.iter(|| { + let mut rd = &buf[..]; + for _ in (0 .. 8) { + let _ = rd.read(&mut dst); + test::black_box(&dst); + } + }) + } + + #[bench] + fn bench_write_slice(b: &mut test::Bencher) { + let mut buf = [0; 1024]; + let src = [5; 128]; + + b.iter(|| { + let mut wr = &mut buf[..]; + for _ in (0 .. 8) { + let _ = wr.write_all(&src); + test::black_box(&wr); + } + }) + } + + #[bench] + fn bench_read_vec(b: &mut test::Bencher) { + let buf = vec![5; 1024]; + let mut dst = [0; 128]; + + b.iter(|| { + let mut rd = &buf[..]; + for _ in (0 .. 8) { + let _ = rd.read(&mut dst); + test::black_box(&dst); + } + }) + } + + #[bench] + fn bench_write_vec(b: &mut test::Bencher) { + let mut buf = Vec::with_capacity(1024); + let src = [5; 128]; + + b.iter(|| { + let mut wr = &mut buf[..]; + for _ in (0 .. 8) { + let _ = wr.write_all(&src); + test::black_box(&wr); + } + }) + } +} diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs new file mode 100644 index 0000000000..df280dab37 --- /dev/null +++ b/src/libstd/io/lazy.rs @@ -0,0 +1,67 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use boxed; +use cell::UnsafeCell; +use rt; +use sync::{StaticMutex, Arc}; + +pub struct Lazy { + pub lock: StaticMutex, + pub ptr: UnsafeCell<*mut Arc>, + pub init: fn() -> Arc, +} + +unsafe impl Sync for Lazy {} + +macro_rules! lazy_init { + ($init:expr) => (::io::lazy::Lazy { + lock: ::sync::MUTEX_INIT, + ptr: ::cell::UnsafeCell { value: 0 as *mut _ }, + init: $init, + }) +} + +impl Lazy { + pub fn get(&'static self) -> Option> { + let _g = self.lock.lock(); + unsafe { + let ptr = *self.ptr.get(); + if ptr.is_null() { + Some(self.init()) + } else if ptr as usize == 1 { + None + } else { + Some((*ptr).clone()) + } + } + } + + unsafe fn init(&'static self) -> Arc { + // If we successfully register an at exit handler, then we cache the + // `Arc` allocation in our own internal box (it will get deallocated by + // the at exit handler). Otherwise we just return the freshly allocated + // `Arc`. + let registered = rt::at_exit(move || { + let g = self.lock.lock(); + let ptr = *self.ptr.get(); + *self.ptr.get() = 1 as *mut _; + drop(g); + drop(Box::from_raw(ptr)) + }); + let ret = (self.init)(); + if registered.is_ok() { + *self.ptr.get() = boxed::into_raw(Box::new(ret.clone())); + } + return ret + } +} diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c38d52161c..c6335015d7 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -9,29 +9,21 @@ // except according to those terms. //! Traits, helpers, and type definitions for core I/O functionality. -//! -//! > **NOTE**: This module is very much a work in progress and is under active -//! > development. At this time it is still recommended to use the `old_io` -//! > module while the details of this module shake out. -#![unstable(feature = "io", - reason = "this new I/O module is still under active deveopment and \ - APIs are subject to tweaks fairly regularly")] +#![stable(feature = "rust1", since = "1.0.0")] use cmp; use unicode::str as core_str; -use error::Error as StdError; +use error as std_error; use fmt; -use iter::Iterator; +use iter::{self, Iterator, Extend}; use marker::Sized; use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; -use ptr::PtrExt; use result::Result::{Ok, Err}; use result; -use slice::{self, SliceExt}; use string::String; -use str::{self, StrExt}; +use str; use vec::Vec; pub use self::buffered::{BufReader, BufWriter, BufStream, LineWriter}; @@ -39,6 +31,12 @@ pub use self::buffered::IntoInnerError; pub use self::cursor::Cursor; pub use self::error::{Result, Error, ErrorKind}; pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; +pub use self::stdio::{stdin, stdout, stderr, _print, Stdin, Stdout, Stderr}; +pub use self::stdio::{StdoutLock, StderrLock, StdinLock}; +#[doc(no_inline, hidden)] +pub use self::stdio::{set_panic, set_print}; + +#[macro_use] mod lazy; pub mod prelude; mod buffered; @@ -46,48 +44,10 @@ mod cursor; mod error; mod impls; mod util; +mod stdio; const DEFAULT_BUF_SIZE: usize = 64 * 1024; -// Acquires a slice of the vector `v` from its length to its capacity -// (uninitialized data), reads into it, and then updates the length. -// -// This function is leveraged to efficiently read some bytes into a destination -// vector without extra copying and taking advantage of the space that's already -// in `v`. -// -// The buffer we're passing down, however, is pointing at uninitialized data -// (the end of a `Vec`), and many operations will be *much* faster if we don't -// have to zero it out. In order to prevent LLVM from generating an `undef` -// value when reads happen from this uninitialized memory, we force LLVM to -// think it's initialized by sending it through a black box. This should prevent -// actual undefined behavior after optimizations. -fn with_end_to_cap(v: &mut Vec, f: F) -> Result - where F: FnOnce(&mut [u8]) -> Result -{ - unsafe { - let n = try!(f({ - let base = v.as_mut_ptr().offset(v.len() as isize); - black_box(slice::from_raw_parts_mut(base, - v.capacity() - v.len())) - })); - - // If the closure (typically a `read` implementation) reported that it - // read a larger number of bytes than the vector actually has, we need - // to be sure to clamp the vector to at most its capacity. - let new_len = cmp::min(v.capacity(), v.len() + n); - v.set_len(new_len); - return Ok(n); - } - - // Semi-hack used to prevent LLVM from retaining any assumptions about - // `dummy` over this function call - unsafe fn black_box(mut dummy: T) -> T { - asm!("" :: "r"(&mut dummy) : "memory"); - dummy - } -} - // A few methods below (read_to_string, read_line) will append data into a // `String` buffer, but we need to be pretty careful when doing this. The // implementation will just call `.as_mut_vec()` and then delegate to a @@ -106,8 +66,8 @@ fn with_end_to_cap(v: &mut Vec, f: F) -> Result // 2. We're passing a raw buffer to the function `f`, and it is expected that // the function only *appends* bytes to the buffer. We'll get undefined // behavior if existing bytes are overwritten to have non-UTF-8 data. -fn append_to_string(buf: &mut String, f: F) -> Result<()> - where F: FnOnce(&mut Vec) -> Result<()> +fn append_to_string(buf: &mut String, f: F) -> Result + where F: FnOnce(&mut Vec) -> Result { struct Guard<'a> { s: &'a mut Vec, len: usize } #[unsafe_destructor] @@ -121,9 +81,9 @@ fn append_to_string(buf: &mut String, f: F) -> Result<()> let mut g = Guard { len: buf.len(), s: buf.as_mut_vec() }; let ret = f(g.s); if str::from_utf8(&g.s[g.len..]).is_err() { - ret.and_then(|()| { + ret.and_then(|_| { Err(Error::new(ErrorKind::InvalidInput, - "stream did not contain valid UTF-8", None)) + "stream did not contain valid UTF-8")) }) } else { g.len = g.s.len(); @@ -132,18 +92,41 @@ fn append_to_string(buf: &mut String, f: F) -> Result<()> } } -fn read_to_end(r: &mut R, buf: &mut Vec) -> Result<()> { +// This uses an adaptive system to extend the vector when it fills. We want to +// avoid paying to allocate and zero a huge chunk of memory if the reader only +// has 4 bytes while still making large reads if the reader does have a ton +// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every +// time is 4,500 times (!) slower than this if the reader has a very small +// amount of data to return. +fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { + let start_len = buf.len(); + let mut len = start_len; + let mut new_write_size = 16; + let ret; loop { - if buf.capacity() == buf.len() { - buf.reserve(DEFAULT_BUF_SIZE); + if len == buf.len() { + if new_write_size < DEFAULT_BUF_SIZE { + new_write_size *= 2; + } + buf.extend(iter::repeat(0).take(new_write_size)); } - match with_end_to_cap(buf, |b| r.read(b)) { - Ok(0) => return Ok(()), - Ok(_) => {} + + match r.read(&mut buf[len..]) { + Ok(0) => { + ret = Ok(len - start_len); + break; + } + Ok(n) => len += n, Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - Err(e) => return Err(e), + Err(e) => { + ret = Err(e); + break; + } } } + + buf.truncate(len); + ret } /// A trait for objects which are byte-oriented sources. @@ -154,6 +137,7 @@ fn read_to_end(r: &mut R, buf: &mut Vec) -> Result<()> { /// Readers are intended to be composable with one another. Many objects /// throughout the I/O and related libraries take and provide types which /// implement the `Read` trait. +#[stable(feature = "rust1", since = "1.0.0")] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -182,6 +166,7 @@ pub trait Read { /// If this function encounters any form of I/O or other error, an error /// variant will be returned. If an error is returned then it must be /// guaranteed that no bytes were read. + #[stable(feature = "rust1", since = "1.0.0")] fn read(&mut self, buf: &mut [u8]) -> Result; /// Read all bytes until EOF in this source, placing them into `buf`. @@ -193,7 +178,8 @@ pub trait Read { /// 2. Returns an error which is not of the kind `ErrorKind::Interrupted`. /// /// Until one of these conditions is met the function will continuously - /// invoke `read` to append more data to `buf`. + /// invoke `read` to append more data to `buf`. If successful, this function + /// will return the total number of bytes read. /// /// # Errors /// @@ -204,19 +190,24 @@ pub trait Read { /// If any other read error is encountered then this function immediately /// returns. Any bytes which have already been read will be appended to /// `buf`. - fn read_to_end(&mut self, buf: &mut Vec) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_to_end(&mut self, buf: &mut Vec) -> Result { read_to_end(self, buf) } /// Read all bytes until EOF in this source, placing them into `buf`. /// + /// If successful, this function returns the number of bytes which were read + /// and appended to `buf`. + /// /// # Errors /// /// If the data in this stream is *not* valid UTF-8 then an error is /// returned and `buf` is unchanged. /// /// See `read_to_end` for other error semantics. - fn read_to_string(&mut self, buf: &mut String) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_to_string(&mut self, buf: &mut String) -> Result { // Note that we do *not* call `.read_to_end()` here. We are passing // `&mut Vec` (the raw contents of `buf`) into the `read_to_end` // method to fill it up. An arbitrary implementation could overwrite the @@ -228,16 +219,13 @@ pub trait Read { // know is guaranteed to only read data into the end of the buffer. append_to_string(buf, |b| read_to_end(self, b)) } -} -/// Extension methods for all instances of `Read`, typically imported through -/// `std::io::prelude::*`. -pub trait ReadExt: Read + Sized { /// Create a "by reference" adaptor for this instance of `Read`. /// /// The returned adaptor also implements `Read` and will simply borrow this /// current reader. - fn by_ref(&mut self) -> &mut Self { self } + #[stable(feature = "rust1", since = "1.0.0")] + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } /// Transform this `Read` instance to an `Iterator` over its bytes. /// @@ -245,7 +233,8 @@ pub trait ReadExt: Read + Sized { /// R::Err>`. The yielded item is `Ok` if a byte was successfully read and /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from /// this iterator. - fn bytes(self) -> Bytes { + #[stable(feature = "rust1", since = "1.0.0")] + fn bytes(self) -> Bytes where Self: Sized { Bytes { inner: self } } @@ -259,7 +248,10 @@ pub trait ReadExt: Read + Sized { /// /// Currently this adaptor will discard intermediate data read, and should /// be avoided if this is not desired. - fn chars(self) -> Chars { + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] + fn chars(self) -> Chars where Self: Sized { Chars { inner: self } } @@ -268,7 +260,8 @@ pub trait ReadExt: Read + Sized { /// The returned `Read` instance will first read all bytes from this object /// until EOF is encountered. Afterwards the output is equivalent to the /// output of `next`. - fn chain(self, next: R) -> Chain { + #[stable(feature = "rust1", since = "1.0.0")] + fn chain(self, next: R) -> Chain where Self: Sized { Chain { first: self, second: next, done_first: false } } @@ -278,7 +271,8 @@ pub trait ReadExt: Read + Sized { /// `limit` bytes, after which it will always return EOF (`Ok(0)`). Any /// read errors will not count towards the number of bytes read and future /// calls to `read` may succeed. - fn take(self, limit: u64) -> Take { + #[stable(feature = "rust1", since = "1.0.0")] + fn take(self, limit: u64) -> Take where Self: Sized { Take { inner: self, limit: limit } } @@ -288,13 +282,14 @@ pub trait ReadExt: Read + Sized { /// Whenever the returned `Read` instance is read it will write the read /// data to `out`. The current semantics of this implementation imply that /// a `write` error will not report how much data was initially read. - fn tee(self, out: W) -> Tee { + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] + fn tee(self, out: W) -> Tee where Self: Sized { Tee { reader: self, writer: out } } } -impl ReadExt for T {} - /// A trait for objects which are byte-oriented sinks. /// /// The `write` method will attempt to write some data into the object, @@ -306,6 +301,7 @@ impl ReadExt for T {} /// Writers are intended to be composable with one another. Many objects /// throughout the I/O and related libraries take and provide types which /// implement the `Write` trait. +#[stable(feature = "rust1", since = "1.0.0")] pub trait Write { /// Write a buffer into this object, returning how many bytes were written. /// @@ -331,6 +327,7 @@ pub trait Write { /// /// It is **not** considered an error if the entire buffer could not be /// written to this writer. + #[stable(feature = "rust1", since = "1.0.0")] fn write(&mut self, buf: &[u8]) -> Result; /// Flush this output stream, ensuring that all intermediately buffered @@ -340,6 +337,7 @@ pub trait Write { /// /// It is considered an error if not all bytes could be written due to /// I/O errors or EOF being reached. + #[stable(feature = "rust1", since = "1.0.0")] fn flush(&mut self) -> Result<()>; /// Attempts to write an entire buffer into this write. @@ -352,12 +350,12 @@ pub trait Write { /// # Errors /// /// This function will return the first error that `write` returns. + #[stable(feature = "rust1", since = "1.0.0")] fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { while buf.len() > 0 { match self.write(buf) { Ok(0) => return Err(Error::new(ErrorKind::WriteZero, - "failed to write whole buffer", - None)), + "failed to write whole buffer")), Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), @@ -380,6 +378,7 @@ pub trait Write { /// # Errors /// /// This function will return any I/O error reported while formatting. + #[stable(feature = "rust1", since = "1.0.0")] fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { // Create a shim which translates a Write to a fmt::Write and saves // off I/O errors. instead of discarding them @@ -406,16 +405,13 @@ pub trait Write { Err(..) => output.error } } -} -/// Extension methods for all instances of `Write`, typically imported through -/// `std::io::prelude::*`. -pub trait WriteExt: Write + Sized { /// Create a "by reference" adaptor for this instance of `Write`. /// /// The returned adaptor also implements `Write` and will simply borrow this /// current writer. - fn by_ref(&mut self) -> &mut Self { self } + #[stable(feature = "rust1", since = "1.0.0")] + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } /// Creates a new writer which will write all data to both this writer and /// another writer. @@ -425,18 +421,22 @@ pub trait WriteExt: Write + Sized { /// implementation do not precisely track where errors happen. For example /// an error on the second call to `write` will not report that the first /// call to `write` succeeded. - fn broadcast(self, other: W) -> Broadcast { + #[unstable(feature = "io", reason = "the semantics of a partial read/write \ + of where errors happen is currently \ + unclear and may change")] + fn broadcast(self, other: W) -> Broadcast + where Self: Sized + { Broadcast { first: self, second: other } } } -impl WriteExt for T {} - /// An object implementing `Seek` internally has some form of cursor which can /// be moved within a stream of bytes. /// /// The stream typically has a fixed size, allowing seeking relative to either /// end or the current offset. +#[stable(feature = "rust1", since = "1.0.0")] pub trait Seek { /// Seek to an offset, in bytes, in a stream /// @@ -452,13 +452,16 @@ pub trait Seek { /// # Errors /// /// Seeking to a negative offset is considered an error + #[stable(feature = "rust1", since = "1.0.0")] fn seek(&mut self, pos: SeekFrom) -> Result; } /// Enumeration of possible methods to seek within an I/O object. #[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum SeekFrom { /// Set the offset to the provided number of bytes. + #[stable(feature = "rust1", since = "1.0.0")] Start(u64), /// Set the offset to the size of this object plus the specified number of @@ -466,6 +469,7 @@ pub enum SeekFrom { /// /// It is possible to seek beyond the end of an object, but is an error to /// seek before byte 0. + #[stable(feature = "rust1", since = "1.0.0")] End(i64), /// Set the offset to the current position plus the specified number of @@ -473,11 +477,13 @@ pub enum SeekFrom { /// /// It is possible to seek beyond the end of an object, but is an error to /// seek before byte 0. + #[stable(feature = "rust1", since = "1.0.0")] Current(i64), } fn read_until(r: &mut R, delim: u8, buf: &mut Vec) - -> Result<()> { + -> Result { + let mut read = 0; loop { let (done, used) = { let available = match r.fill_buf() { @@ -497,8 +503,9 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) } }; r.consume(used); + read += used; if done || used == 0 { - return Ok(()); + return Ok(read); } } } @@ -508,6 +515,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// This type extends the `Read` trait with a few methods that are not /// possible to reasonably implement with purely a read interface. +#[stable(feature = "rust1", since = "1.0.0")] pub trait BufRead: Read { /// Fills the internal buffer of this object, returning the buffer contents. /// @@ -524,10 +532,22 @@ pub trait BufRead: Read { /// /// This function will return an I/O error if the underlying reader was /// read, but returned an error. + #[stable(feature = "rust1", since = "1.0.0")] fn fill_buf(&mut self) -> Result<&[u8]>; /// Tells this buffer that `amt` bytes have been consumed from the buffer, /// so they should no longer be returned in calls to `read`. + /// + /// This function does not perform any I/O, it simply informs this object + /// that some amount of its buffer, returned from `fill_buf`, has been + /// consumed and should no longer be returned. + /// + /// This function is used to tell the buffer how many bytes you've consumed + /// from the return value of `fill_buf`, and so may do odd things if + /// `fill_buf` isn't called before calling this. + /// + /// The `amt` must be `<=` the number of bytes in the buffer returned by `fill_buf`. + #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); /// Read all bytes until the delimiter `byte` is reached. @@ -538,7 +558,8 @@ pub trait BufRead: Read { /// `buf`. /// /// If this buffered reader is currently at EOF, then this function will not - /// place any more bytes into `buf` and will return `Ok(())`. + /// place any more bytes into `buf` and will return `Ok(n)` where `n` is the + /// number of bytes which were read. /// /// # Errors /// @@ -547,11 +568,13 @@ pub trait BufRead: Read { /// /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. - fn read_until(&mut self, byte: u8, buf: &mut Vec) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> Result { read_until(self, byte, buf) } - /// Read all bytes until a newline byte (the 0xA byte) is reached. + /// Read all bytes until a newline byte (the 0xA byte) is reached, and + /// append them to the provided buffer. /// /// This function will continue to read (and buffer) bytes from the /// underlying stream until the newline delimiter (the 0xA byte) or EOF is @@ -559,7 +582,8 @@ pub trait BufRead: Read { /// found) will be appended to `buf`. /// /// If this reader is currently at EOF then this function will not modify - /// `buf` and will return `Ok(())`. + /// `buf` and will return `Ok(n)` where `n` is the number of bytes which + /// were read. /// /// # Errors /// @@ -567,17 +591,14 @@ pub trait BufRead: Read { /// return an error if the read bytes are not valid UTF-8. If an I/O error /// is encountered then `buf` may contain some bytes already read in the /// event that all data read so far was valid UTF-8. - fn read_line(&mut self, buf: &mut String) -> Result<()> { + #[stable(feature = "rust1", since = "1.0.0")] + fn read_line(&mut self, buf: &mut String) -> Result { // Note that we are not calling the `.read_until` method here, but // rather our hardcoded implementation. For more details as to why, see // the comments in `read_to_end`. append_to_string(buf, |b| read_until(self, b'\n', b)) } -} -/// Extension methods for all instances of `BufRead`, typically imported through -/// `std::io::prelude::*`. -pub trait BufReadExt: BufRead + Sized { /// Returns an iterator over the contents of this reader split on the byte /// `byte`. /// @@ -587,7 +608,8 @@ pub trait BufReadExt: BufRead + Sized { /// /// This function will yield errors whenever `read_until` would have also /// yielded an error. - fn split(self, byte: u8) -> Split { + #[stable(feature = "rust1", since = "1.0.0")] + fn split(self, byte: u8) -> Split where Self: Sized { Split { buf: self, delim: byte } } @@ -599,21 +621,22 @@ pub trait BufReadExt: BufRead + Sized { /// /// This function will yield errors whenever `read_string` would have also /// yielded an error. - fn lines(self) -> Lines { + #[stable(feature = "rust1", since = "1.0.0")] + fn lines(self) -> Lines where Self: Sized { Lines { buf: self } } } -impl BufReadExt for T {} - /// A `Write` adaptor which will write data to multiple locations. /// -/// For more information, see `WriteExt::broadcast`. +/// For more information, see `Write::broadcast`. +#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")] pub struct Broadcast { first: T, second: U, } +#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")] impl Write for Broadcast { fn write(&mut self, data: &[u8]) -> Result { let n = try!(self.first.write(data)); @@ -629,13 +652,15 @@ impl Write for Broadcast { /// Adaptor to chain together two instances of `Read`. /// -/// For more information, see `ReadExt::chain`. +/// For more information, see `Read::chain`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, second: U, done_first: bool, } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { if !self.done_first { @@ -650,12 +675,14 @@ impl Read for Chain { /// Reader adaptor which limits the bytes read from an underlying reader. /// -/// For more information, see `ReadExt::take`. +/// For more information, see `Read::take`. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Take { inner: T, limit: u64, } +#[stable(feature = "rust1", since = "1.0.0")] impl Take { /// Returns the number of bytes that can be read before this instance will /// return EOF. @@ -664,11 +691,18 @@ impl Take { /// /// This instance may reach EOF after reading fewer bytes than indicated by /// this method if the underlying `Read` instance reaches EOF. + #[stable(feature = "rust1", since = "1.0.0")] pub fn limit(&self) -> u64 { self.limit } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Take { fn read(&mut self, buf: &mut [u8]) -> Result { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(0); + } + let max = cmp::min(buf.len() as u64, self.limit) as usize; let n = try!(self.inner.read(&mut buf[..max])); self.limit -= n as u64; @@ -676,14 +710,32 @@ impl Read for Take { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl BufRead for Take { + fn fill_buf(&mut self) -> Result<&[u8]> { + let buf = try!(self.inner.fill_buf()); + let cap = cmp::min(buf.len() as u64, self.limit) as usize; + Ok(&buf[..cap]) + } + + fn consume(&mut self, amt: usize) { + // Don't let callers reset the limit by passing an overlarge value + let amt = cmp::min(amt as u64, self.limit) as usize; + self.limit -= amt as u64; + self.inner.consume(amt); + } +} + /// An adaptor which will emit all read data to a specified writer as well. /// -/// For more information see `ReadExt::tee` +/// For more information see `Read::tee` +#[unstable(feature = "io", reason = "awaiting stability of Read::tee")] pub struct Tee { reader: R, writer: W, } +#[unstable(feature = "io", reason = "awaiting stability of Read::tee")] impl Read for Tee { fn read(&mut self, buf: &mut [u8]) -> Result { let n = try!(self.reader.read(buf)); @@ -695,11 +747,13 @@ impl Read for Tee { /// A bridge from implementations of `Read` to an `Iterator` of `u8`. /// -/// See `ReadExt::bytes` for more information. +/// See `Read::bytes` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Bytes { inner: R, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Bytes { type Item = Result; @@ -715,14 +769,16 @@ impl Iterator for Bytes { /// A bridge from implementations of `Read` to an `Iterator` of `char`. /// -/// See `ReadExt::chars` for more information. +/// See `Read::chars` for more information. +#[unstable(feature = "io", reason = "awaiting stability of Read::chars")] pub struct Chars { inner: R, } /// An enumeration of possible errors that can be generated from the `Chars` /// adapter. -#[derive(PartialEq, Clone, Debug)] +#[derive(Debug)] +#[unstable(feature = "io", reason = "awaiting stability of Read::chars")] pub enum CharsError { /// Variant representing that the underlying stream was read successfully /// but it did not contain valid utf8 data. @@ -732,6 +788,7 @@ pub enum CharsError { Other(Error), } +#[unstable(feature = "io", reason = "awaiting stability of Read::chars")] impl Iterator for Chars { type Item = result::Result; @@ -763,14 +820,15 @@ impl Iterator for Chars { } } -impl StdError for CharsError { +#[unstable(feature = "io", reason = "awaiting stability of Read::chars")] +impl std_error::Error for CharsError { fn description(&self) -> &str { match *self { CharsError::NotUtf8 => "invalid utf8 encoding", - CharsError::Other(ref e) => e.description(), + CharsError::Other(ref e) => std_error::Error::description(e), } } - fn cause(&self) -> Option<&StdError> { + fn cause(&self) -> Option<&std_error::Error> { match *self { CharsError::NotUtf8 => None, CharsError::Other(ref e) => e.cause(), @@ -778,6 +836,7 @@ impl StdError for CharsError { } } +#[unstable(feature = "io", reason = "awaiting stability of Read::chars")] impl fmt::Display for CharsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -793,19 +852,21 @@ impl fmt::Display for CharsError { /// particular byte. /// /// See `BufReadExt::split` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Split { buf: B, delim: u8, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Split { type Item = Result>; fn next(&mut self) -> Option>> { let mut buf = Vec::new(); match self.buf.read_until(self.delim, &mut buf) { - Ok(()) if buf.len() == 0 => None, - Ok(()) => { + Ok(0) => None, + Ok(_n) => { if buf[buf.len() - 1] == self.delim { buf.pop(); } @@ -820,18 +881,20 @@ impl Iterator for Split { /// byte. /// /// See `BufReadExt::lines` for more information. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Lines { buf: B, } +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Lines { type Item = Result; fn next(&mut self) -> Option> { let mut buf = String::new(); match self.buf.read_line(&mut buf) { - Ok(()) if buf.len() == 0 => None, - Ok(()) => { + Ok(0) => None, + Ok(_n) => { if buf.ends_with("\n") { buf.pop(); } @@ -846,101 +909,116 @@ impl Iterator for Lines { mod tests { use prelude::v1::*; use io::prelude::*; + use io; use super::Cursor; #[test] fn read_until() { - let mut buf = Cursor::new(b"12"); + let mut buf = Cursor::new(&b"12"[..]); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); assert_eq!(v, b"12"); - let mut buf = Cursor::new(b"1233"); + let mut buf = Cursor::new(&b"1233"[..]); let mut v = Vec::new(); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); assert_eq!(v, b"123"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); assert_eq!(v, b"3"); v.truncate(0); - assert_eq!(buf.read_until(b'3', &mut v), Ok(())); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); assert_eq!(v, []); } #[test] fn split() { - let mut buf = Cursor::new(b"12"); + let buf = Cursor::new(&b"12"[..]); let mut s = buf.split(b'3'); - assert_eq!(s.next(), Some(Ok(vec![b'1', b'2']))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert!(s.next().is_none()); - let mut buf = Cursor::new(b"1233"); + let buf = Cursor::new(&b"1233"[..]); let mut s = buf.split(b'3'); - assert_eq!(s.next(), Some(Ok(vec![b'1', b'2']))); - assert_eq!(s.next(), Some(Ok(vec![]))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert_eq!(s.next().unwrap().unwrap(), vec![]); + assert!(s.next().is_none()); } #[test] fn read_line() { - let mut buf = Cursor::new(b"12"); + let mut buf = Cursor::new(&b"12"[..]); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v).unwrap(), 2); assert_eq!(v, "12"); - let mut buf = Cursor::new(b"12\n\n"); + let mut buf = Cursor::new(&b"12\n\n"[..]); let mut v = String::new(); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v).unwrap(), 3); assert_eq!(v, "12\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v).unwrap(), 1); assert_eq!(v, "\n"); v.truncate(0); - assert_eq!(buf.read_line(&mut v), Ok(())); + assert_eq!(buf.read_line(&mut v).unwrap(), 0); assert_eq!(v, ""); } #[test] fn lines() { - let mut buf = Cursor::new(b"12"); + let buf = Cursor::new(&b"12"[..]); let mut s = buf.lines(); - assert_eq!(s.next(), Some(Ok("12".to_string()))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert!(s.next().is_none()); - let mut buf = Cursor::new(b"12\n\n"); + let buf = Cursor::new(&b"12\n\n"[..]); let mut s = buf.lines(); - assert_eq!(s.next(), Some(Ok("12".to_string()))); - assert_eq!(s.next(), Some(Ok(String::new()))); - assert_eq!(s.next(), None); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert_eq!(s.next().unwrap().unwrap(), "".to_string()); + assert!(s.next().is_none()); } #[test] fn read_to_end() { - let mut c = Cursor::new(b""); + let mut c = Cursor::new(&b""[..]); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(())); + assert_eq!(c.read_to_end(&mut v).unwrap(), 0); assert_eq!(v, []); - let mut c = Cursor::new(b"1"); + let mut c = Cursor::new(&b"1"[..]); let mut v = Vec::new(); - assert_eq!(c.read_to_end(&mut v), Ok(())); + assert_eq!(c.read_to_end(&mut v).unwrap(), 1); assert_eq!(v, b"1"); } #[test] fn read_to_string() { - let mut c = Cursor::new(b""); + let mut c = Cursor::new(&b""[..]); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(())); + assert_eq!(c.read_to_string(&mut v).unwrap(), 0); assert_eq!(v, ""); - let mut c = Cursor::new(b"1"); + let mut c = Cursor::new(&b"1"[..]); let mut v = String::new(); - assert_eq!(c.read_to_string(&mut v), Ok(())); + assert_eq!(c.read_to_string(&mut v).unwrap(), 1); assert_eq!(v, "1"); - let mut c = Cursor::new(b"\xff"); + let mut c = Cursor::new(&b"\xff"[..]); let mut v = String::new(); assert!(c.read_to_string(&mut v).is_err()); } + + #[test] + fn take_eof() { + struct R; + + impl Read for R { + fn read(&mut self, _: &mut [u8]) -> io::Result { + Err(io::Error::new(io::ErrorKind::Other, "")) + } + } + + let mut buf = [0; 1]; + assert_eq!(0, R.take(0).read(&mut buf).unwrap()); + } } diff --git a/src/libstd/io/prelude.rs b/src/libstd/io/prelude.rs index 637b195098..333ae8f26a 100644 --- a/src/libstd/io/prelude.rs +++ b/src/libstd/io/prelude.rs @@ -18,11 +18,10 @@ //! ``` //! //! This module contains reexports of many core I/O traits such as `Read`, -//! `Write`, `ReadExt`, and `WriteExt`. Structures and functions are not +//! `Write` and `BufRead`. Structures and functions are not //! contained in this module. -pub use super::{Read, ReadExt, Write, WriteExt, BufRead, BufReadExt}; -pub use fs::PathExt; +#![stable(feature = "rust1", since = "1.0.0")] -// FIXME: pub use as `Seek` when the name isn't in the actual prelude any more -pub use super::Seek as NewSeek; +pub use super::{Read, Write, BufRead, Seek}; +pub use fs::PathExt; diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs new file mode 100644 index 0000000000..d361f17cbe --- /dev/null +++ b/src/libstd/io/stdio.rs @@ -0,0 +1,432 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; +use io::prelude::*; + +use cell::{RefCell, BorrowState}; +use cmp; +use fmt; +use io::lazy::Lazy; +use io::{self, BufReader, LineWriter}; +use sync::{Arc, Mutex, MutexGuard}; +use sys::stdio; + +/// Stdout used by print! and println! macros +thread_local! { + static LOCAL_STDOUT: RefCell>> = { + RefCell::new(None) + } +} + +/// A handle to a raw instance of the standard input stream of this process. +/// +/// This handle is not synchronized or buffered in any fashion. Constructed via +/// the `std::io::stdio::stdin_raw` function. +struct StdinRaw(stdio::Stdin); + +/// A handle to a raw instance of the standard output stream of this process. +/// +/// This handle is not synchronized or buffered in any fashion. Constructed via +/// the `std::io::stdio::stdout_raw` function. +struct StdoutRaw(stdio::Stdout); + +/// A handle to a raw instance of the standard output stream of this process. +/// +/// This handle is not synchronized or buffered in any fashion. Constructed via +/// the `std::io::stdio::stderr_raw` function. +struct StderrRaw(stdio::Stderr); + +/// Construct a new raw handle to the standard input of this process. +/// +/// The returned handle does not interact with any other handles created nor +/// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin` +/// handles is **not** available to raw handles returned from this function. +/// +/// The returned handle has no external synchronization or buffering. +fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) } + +/// Construct a new raw handle to the standard input stream of this process. +/// +/// The returned handle does not interact with any other handles created nor +/// handles returned by `std::io::stdout`. Note that data is buffered by the +/// `std::io::stdin` handles so writes which happen via this raw handle may +/// appear before previous writes. +/// +/// The returned handle has no external synchronization or buffering layered on +/// top. +fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) } + +/// Construct a new raw handle to the standard input stream of this process. +/// +/// The returned handle does not interact with any other handles created nor +/// handles returned by `std::io::stdout`. +/// +/// The returned handle has no external synchronization or buffering layered on +/// top. +fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) } + +impl Read for StdinRaw { + fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } +} +impl Write for StdoutRaw { + fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} +impl Write for StderrRaw { + fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +/// A handle to the standard input stream of a process. +/// +/// Each handle is a shared reference to a global buffer of input data to this +/// process. A handle can be `lock`'d to gain full access to `BufRead` methods +/// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect +/// to other writes. +/// +/// This handle implements the `Read` trait, but beware that concurrent reads +/// of `Stdin` must be executed with care. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stdin { + inner: Arc>>, +} + +/// A locked reference to the a `Stdin` handle. +/// +/// This handle implements both the `Read` and `BufRead` traits and is +/// constructed via the `lock` method on `Stdin`. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StdinLock<'a> { + inner: MutexGuard<'a, BufReader>, +} + +/// Create a new handle to the global standard input stream of this process. +/// +/// The handle returned refers to a globally shared buffer between all threads. +/// Access is synchronized and can be explicitly controlled with the `lock()` +/// method. +/// +/// The `Read` trait is implemented for the returned value but the `BufRead` +/// trait is not due to the global nature of the standard input stream. The +/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stdin() -> Stdin { + static INSTANCE: Lazy>> = lazy_init!(stdin_init); + return Stdin { + inner: INSTANCE.get().expect("cannot access stdin during shutdown"), + }; + + fn stdin_init() -> Arc>> { + // The default buffer capacity is 64k, but apparently windows + // doesn't like 64k reads on stdin. See #13304 for details, but the + // idea is that on windows we use a slightly smaller buffer that's + // been seen to be acceptable. + Arc::new(Mutex::new(if cfg!(windows) { + BufReader::with_capacity(8 * 1024, stdin_raw()) + } else { + BufReader::new(stdin_raw()) + })) + } +} + +impl Stdin { + /// Lock this handle to the standard input stream, returning a readable + /// guard. + /// + /// The lock is released when the returned lock goes out of scope. The + /// returned guard also implements the `Read` and `BufRead` traits for + /// accessing the underlying data. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lock(&self) -> StdinLock { + StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + } + + /// Locks this handle and reads a line of input into the specified buffer. + /// + /// For detailed semantics of this method, see the documentation on + /// `BufRead::read_line`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn read_line(&mut self, buf: &mut String) -> io::Result { + self.lock().read_line(buf) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Read for Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.lock().read(buf) + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.lock().read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + self.lock().read_to_string(buf) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Read for StdinLock<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.inner.read(buf) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> BufRead for StdinLock<'a> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() } + fn consume(&mut self, n: usize) { self.inner.consume(n) } +} + +// As with stdin on windows, stdout often can't handle writes of large +// sizes. For an example, see #14940. For this reason, don't try to +// write the entire output buffer on windows. On unix we can just +// write the whole buffer all at once. +// +// For some other references, it appears that this problem has been +// encountered by others [1] [2]. We choose the number 8KB just because +// libuv does the same. +// +// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232 +// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html +#[cfg(windows)] +const OUT_MAX: usize = 8192; +#[cfg(unix)] +const OUT_MAX: usize = ::usize::MAX; + +/// A handle to the global standard output stream of the current process. +/// +/// Each handle shares a global buffer of data to be written to the standard +/// output stream. Access is also synchronized via a lock and explicit control +/// over locking is available via the `lock` method. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stdout { + // FIXME: this should be LineWriter or BufWriter depending on the state of + // stdout (tty or not). Note that if this is not line buffered it + // should also flush-on-panic or some form of flush-on-abort. + inner: Arc>>, +} + +/// A locked reference to the a `Stdout` handle. +/// +/// This handle implements the `Write` trait and is constructed via the `lock` +/// method on `Stdout`. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StdoutLock<'a> { + inner: MutexGuard<'a, LineWriter>, +} + +/// Constructs a new reference to the standard output of the current process. +/// +/// Each handle returned is a reference to a shared global buffer whose access +/// is synchronized via a mutex. Explicit control over synchronization is +/// provided via the `lock` method. +/// +/// The returned handle implements the `Write` trait. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stdout() -> Stdout { + static INSTANCE: Lazy>> = lazy_init!(stdout_init); + return Stdout { + inner: INSTANCE.get().expect("cannot access stdout during shutdown"), + }; + + fn stdout_init() -> Arc>> { + Arc::new(Mutex::new(LineWriter::new(stdout_raw()))) + } +} + +impl Stdout { + /// Lock this handle to the standard output stream, returning a writable + /// guard. + /// + /// The lock is released when the returned lock goes out of scope. The + /// returned guard also implements the `Write` trait for writing data. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lock(&self) -> StdoutLock { + StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.lock().write(buf) + } + fn flush(&mut self) -> io::Result<()> { + self.lock().flush() + } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.lock().write_all(buf) + } + // Don't override write_fmt as it's possible to run arbitrary code during a + // write_fmt, allowing the possibility of a recursive lock (aka deadlock) +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Write for StdoutLock<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)]) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} + +/// A handle to the standard error stream of a process. +/// +/// For more information, see `stderr` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stderr { + inner: Arc>, +} + +/// A locked reference to the a `Stderr` handle. +/// +/// This handle implements the `Write` trait and is constructed via the `lock` +/// method on `Stderr`. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StderrLock<'a> { + inner: MutexGuard<'a, StderrRaw>, +} + +/// Constructs a new reference to the standard error stream of a process. +/// +/// Each returned handle is synchronized amongst all other handles created from +/// this function. No handles are buffered, however. +/// +/// The returned handle implements the `Write` trait. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stderr() -> Stderr { + static INSTANCE: Lazy> = lazy_init!(stderr_init); + return Stderr { + inner: INSTANCE.get().expect("cannot access stderr during shutdown"), + }; + + fn stderr_init() -> Arc> { + Arc::new(Mutex::new(stderr_raw())) + } +} + +impl Stderr { + /// Lock this handle to the standard error stream, returning a writable + /// guard. + /// + /// The lock is released when the returned lock goes out of scope. The + /// returned guard also implements the `Write` trait for writing data. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn lock(&self) -> StderrLock { + StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.lock().write(buf) + } + fn flush(&mut self) -> io::Result<()> { + self.lock().flush() + } + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.lock().write_all(buf) + } + // Don't override write_fmt for the same reasons as Stdout +} +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> Write for StderrLock<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)]) + } + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} + +/// Resets the task-local stderr handle to the specified writer +/// +/// This will replace the current task's stderr handle, returning the old +/// handle. All future calls to `panic!` and friends will emit their output to +/// this specified handle. +/// +/// Note that this does not need to be called for all new tasks; the default +/// output handle is to the process's stderr stream. +#[unstable(feature = "set_stdio", + reason = "this function may disappear completely or be replaced \ + with a more general mechanism")] +#[doc(hidden)] +pub fn set_panic(sink: Box) -> Option> { + use panicking::LOCAL_STDERR; + use mem; + LOCAL_STDERR.with(move |slot| { + mem::replace(&mut *slot.borrow_mut(), Some(sink)) + }).and_then(|mut s| { + let _ = s.flush(); + Some(s) + }) +} + +/// Resets the task-local stdout handle to the specified writer +/// +/// This will replace the current task's stdout handle, returning the old +/// handle. All future calls to `print!` and friends will emit their output to +/// this specified handle. +/// +/// Note that this does not need to be called for all new tasks; the default +/// output handle is to the process's stdout stream. +#[unstable(feature = "set_stdio", + reason = "this function may disappear completely or be replaced \ + with a more general mechanism")] +#[doc(hidden)] +pub fn set_print(sink: Box) -> Option> { + use mem; + LOCAL_STDOUT.with(move |slot| { + mem::replace(&mut *slot.borrow_mut(), Some(sink)) + }).and_then(|mut s| { + let _ = s.flush(); + Some(s) + }) +} + +#[unstable(feature = "print", + reason = "implementation detail which may disappear or be replaced at any time")] +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + let result = LOCAL_STDOUT.with(|s| { + if s.borrow_state() == BorrowState::Unused { + if let Some(w) = s.borrow_mut().as_mut() { + return w.write_fmt(args); + } + } + stdout().write_fmt(args) + }); + if let Err(e) = result { + panic!("failed printing to stdout: {}", e); + } +} + +#[cfg(test)] +mod test { + use thread; + use super::*; + + #[test] + fn panic_doesnt_poison() { + thread::spawn(|| { + let _a = stdin(); + let _a = _a.lock(); + let _a = stdout(); + let _a = _a.lock(); + let _a = stderr(); + let _a = _a.lock(); + panic!(); + }).join().unwrap_err(); + + let _a = stdin(); + let _a = _a.lock(); + let _a = stdout(); + let _a = _a.lock(); + let _a = stderr(); + let _a = _a.lock(); + } +} diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 3d342137c6..c82f9515e8 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -12,7 +12,7 @@ use prelude::v1::*; -use io::{self, Read, Write, ErrorKind}; +use io::{self, Read, Write, ErrorKind, BufRead}; /// Copies the entire contents of a reader into a writer. /// @@ -27,6 +27,7 @@ use io::{self, Read, Write, ErrorKind}; /// This function will return an error immediately if any call to `read` or /// `write` returns an error. All instances of `ErrorKind::Interrupted` are /// handled by this function and the underlying operation is retried. +#[stable(feature = "rust1", since = "1.0.0")] pub fn copy(r: &mut R, w: &mut W) -> io::Result { let mut buf = [0; super::DEFAULT_BUF_SIZE]; let mut written = 0; @@ -43,26 +44,37 @@ pub fn copy(r: &mut R, w: &mut W) -> io::Result { } /// A reader which is always at EOF. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Empty { _priv: () } /// Creates an instance of an empty reader. /// /// All reads from the returned reader will return `Ok(0)`. +#[stable(feature = "rust1", since = "1.0.0")] pub fn empty() -> Empty { Empty { _priv: () } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Empty { fn read(&mut self, _buf: &mut [u8]) -> io::Result { Ok(0) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl BufRead for Empty { + fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + fn consume(&mut self, _n: usize) {} +} /// A reader which infinitely yields one byte. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Repeat { byte: u8 } /// Creates an instance of a reader that infinitely repeats one byte. /// /// All reads from this reader will succeed by filling the specified buffer with /// the given byte. +#[stable(feature = "rust1", since = "1.0.0")] pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for Repeat { fn read(&mut self, buf: &mut [u8]) -> io::Result { for slot in buf.iter_mut() { @@ -73,14 +85,17 @@ impl Read for Repeat { } /// A writer which will move data into the void. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Sink { _priv: () } /// Creates an instance of a writer which will successfully consume all data. /// /// All calls to `write` on the returned instance will return `Ok(buf.len())` /// and the contents of the buffer will not be inspected. +#[stable(feature = "rust1", since = "1.0.0")] pub fn sink() -> Sink { Sink { _priv: () } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for Sink { fn write(&mut self, buf: &[u8]) -> io::Result { Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -96,33 +111,33 @@ mod test { #[test] fn sink_sinks() { let mut s = sink(); - assert_eq!(s.write(&[]), Ok(0)); - assert_eq!(s.write(&[0]), Ok(1)); - assert_eq!(s.write(&[0; 1024]), Ok(1024)); - assert_eq!(s.by_ref().write(&[0; 1024]), Ok(1024)); + assert_eq!(s.write(&[]).unwrap(), 0); + assert_eq!(s.write(&[0]).unwrap(), 1); + assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); + assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); } #[test] fn empty_reads() { let mut e = empty(); - assert_eq!(e.read(&mut []), Ok(0)); - assert_eq!(e.read(&mut [0]), Ok(0)); - assert_eq!(e.read(&mut [0; 1024]), Ok(0)); - assert_eq!(e.by_ref().read(&mut [0; 1024]), Ok(0)); + assert_eq!(e.read(&mut []).unwrap(), 0); + assert_eq!(e.read(&mut [0]).unwrap(), 0); + assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); + assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); } #[test] fn repeat_repeats() { let mut r = repeat(4); let mut b = [0; 1024]; - assert_eq!(r.read(&mut b), Ok(1024)); + assert_eq!(r.read(&mut b).unwrap(), 1024); assert!(b.iter().all(|b| *b == 4)); } #[test] fn take_some_bytes() { assert_eq!(repeat(4).take(100).bytes().count(), 100); - assert_eq!(repeat(4).take(100).bytes().next(), Some(Ok(4))); + assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); } @@ -131,7 +146,7 @@ mod test { let mut buf = [0; 10]; { let mut ptr: &mut [u8] = &mut buf; - assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]), Ok(5)); + assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5); } assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]); } @@ -145,7 +160,7 @@ mod test { let mut ptr2: &mut [u8] = &mut buf2; assert_eq!((&mut ptr1).broadcast(&mut ptr2) - .write(&[1, 2, 3]), Ok(3)); + .write(&[1, 2, 3]).unwrap(), 3); } assert_eq!(buf1, buf2); assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fbd403ea59..5c9ff544fa 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -40,11 +40,11 @@ //! //! ## Vectors, slices and strings //! -//! The common container type, `Vec`, a growable vector backed by an -//! array, lives in the [`vec`](vec/index.html) module. References to -//! arrays, `&[T]`, more commonly called "slices", are built-in types -//! for which the [`slice`](slice/index.html) module defines many -//! methods. +//! The common container type, `Vec`, a growable vector backed by an array, +//! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions +//! of memory, `[T]`, commonly called "slices", and their borrowed versions, +//! `&[T]`, commonly called "borrowed slices", are built-in types for which the +//! [`slice`](slice/index.html) module defines many methods. //! //! `&str`, a UTF-8 string, is a built-in type, and the standard library //! defines methods for it on a variety of traits in the @@ -67,16 +67,15 @@ //! module encapsulates the platform-specific rules for dealing //! with file paths. //! -//! `std` also includes modules for interoperating with the -//! C language: [`c_str`](c_str/index.html) and -//! [`c_vec`](c_vec/index.html). +//! `std` also includes the [`ffi`](ffi/index.html) module for interoperating +//! with the C language. //! //! ## Concurrency, I/O, and the runtime //! -//! The [`thread`](thread/index.html) module contains Rust's threading abstractions, -//! while [`comm`](comm/index.html) contains the channel types for message -//! passing. [`sync`](sync/index.html) contains further, primitive, shared -//! memory types, including [`atomic`](sync/atomic/index.html). +//! The [`thread`](thread/index.html) module contains Rust's threading abstractions. +//! [`sync`](sync/index.html) contains further, primitive, shared memory types, +//! including [`atomic`](sync/atomic/index.html), and [`mpsc`](sync/mpsc/index.html), +//! which contains the channel types for message passing. //! //! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets, //! timers, and process spawning, are defined in the @@ -94,7 +93,8 @@ //! to all code by default. [`macros`](macros/index.html) contains //! all the standard macros, such as `assert!`, `panic!`, `println!`, //! and `format!`, also available to all Rust code. - +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "std"] #![stable(feature = "rust1", since = "1.0.0")] #![staged_api] @@ -104,31 +104,37 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://doc.rust-lang.org/nightly/", html_playground_url = "http://play.rust-lang.org/")] +#![doc(test(no_crate_inject))] #![feature(alloc)] #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(hash)] -#![feature(int_uint)] #![feature(lang_items)] #![feature(libc)] #![feature(linkage, thread_local, asm)] -#![feature(old_impl_check)] #![feature(optin_builtin_traits)] #![feature(rand)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unsafe_destructor)] -#![feature(unsafe_no_drop_flag)] +#![feature(unsafe_no_drop_flag, filling_drop)] #![feature(macro_reexport)] -#![cfg_attr(test, feature(test))] +#![feature(unique)] +#![feature(allow_internal_unstable)] +#![feature(str_char)] +#![feature(into_cow)] +#![feature(std_misc)] +#![feature(slice_patterns)] +#![feature(debug_builders)] +#![cfg_attr(test, feature(test, rustc_private, std_misc))] // Don't link to std. We are std. #![feature(no_std)] #![no_std] +#![allow(trivial_casts)] #![deny(missing_docs)] #[cfg(test)] extern crate test; @@ -141,9 +147,9 @@ extern crate core; #[macro_use] #[macro_reexport(vec, format)] -extern crate "collections" as core_collections; +extern crate collections as core_collections; -#[allow(deprecated)] extern crate "rand" as core_rand; +#[allow(deprecated)] extern crate rand as core_rand; extern crate alloc; extern crate unicode; extern crate libc; @@ -151,7 +157,7 @@ extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; // Make std testable by not duplicating lang items. See #2912 -#[cfg(test)] extern crate "std" as realstd; +#[cfg(test)] extern crate std as realstd; #[cfg(test)] pub use realstd::marker; #[cfg(test)] pub use realstd::ops; #[cfg(test)] pub use realstd::cmp; @@ -164,9 +170,8 @@ pub use core::any; pub use core::cell; pub use core::clone; #[cfg(not(test))] pub use core::cmp; +pub use core::convert; pub use core::default; -#[allow(deprecated)] -pub use core::finally; pub use core::hash; pub use core::intrinsics; pub use core::iter; @@ -178,7 +183,7 @@ pub use core::raw; pub use core::simd; pub use core::result; pub use core::option; -pub use core::error; +pub mod error; #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc; @@ -207,6 +212,9 @@ pub mod prelude; /* Primitive types */ +// NB: slice and str are primitive types too, but their module docs + primitive doc pages +// are inlined from the public re-exports of core_collections::{slice, str} above. + #[path = "num/float_macros.rs"] #[macro_use] mod float_macros; @@ -219,14 +227,12 @@ mod int_macros; #[macro_use] mod uint_macros; -#[path = "num/int.rs"] pub mod int; #[path = "num/isize.rs"] pub mod isize; #[path = "num/i8.rs"] pub mod i8; #[path = "num/i16.rs"] pub mod i16; #[path = "num/i32.rs"] pub mod i32; #[path = "num/i64.rs"] pub mod i64; -#[path = "num/uint.rs"] pub mod uint; #[path = "num/usize.rs"] pub mod usize; #[path = "num/u8.rs"] pub mod u8; #[path = "num/u16.rs"] pub mod u16; @@ -237,6 +243,7 @@ mod uint_macros; #[path = "num/f64.rs"] pub mod f64; pub mod ascii; + pub mod thunk; /* Common traits */ @@ -246,43 +253,38 @@ pub mod num; /* Runtime and platform support */ #[macro_use] -pub mod thread_local; +pub mod thread; +pub mod collections; pub mod dynamic_lib; +pub mod env; pub mod ffi; -pub mod old_io; -pub mod io; pub mod fs; +pub mod io; pub mod net; +pub mod old_io; +pub mod old_path; pub mod os; -pub mod env; pub mod path; -pub mod old_path; pub mod process; pub mod rand; +pub mod sync; pub mod time; -/* Common data structures */ - -pub mod collections; - -/* Threads and communication */ - -pub mod thread; -pub mod sync; +#[macro_use] +#[path = "sys/common/mod.rs"] mod sys_common; #[cfg(unix)] #[path = "sys/unix/mod.rs"] mod sys; #[cfg(windows)] #[path = "sys/windows/mod.rs"] mod sys; -#[path = "sys/common/mod.rs"] mod sys_common; - pub mod rt; mod panicking; -// Documentation for primitive types +// Modules that exist purely to document + host impl docs for primitive types +mod array; mod bool; mod unit; mod tuple; @@ -295,12 +297,13 @@ mod std { pub use sync; // used for select!() pub use error; // used for try!() pub use fmt; // used for any formatting strings + #[allow(deprecated)] pub use old_io; // used for println!() pub use option; // used for bitflags!{} pub use rt; // used for panic!() pub use vec; // used for vec![] pub use cell; // used for tls! - pub use thread_local; // used for thread_local! + pub use thread; // used for thread_local! pub use marker; // used for tls! pub use ops; // used for bitflags! diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 00bb7f86b1..b3d1adb442 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -26,9 +26,9 @@ /// The multi-argument form of this macro panics with a string and has the /// `format!` syntax for building a string. /// -/// # Example +/// # Examples /// -/// ```should_fail +/// ```should_panic /// # #![allow(unreachable_code)] /// panic!(); /// panic!("this is a terrible mistake!"); @@ -44,7 +44,7 @@ macro_rules! panic { ($msg:expr) => ({ $crate::rt::begin_unwind($msg, { // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, usize) = (file!(), line!()); + static _FILE_LINE: (&'static str, usize) = (file!(), line!() as usize); &_FILE_LINE }) }); @@ -54,27 +54,33 @@ macro_rules! panic { // used inside a dead function. Just `#[allow(dead_code)]` is // insufficient, since the user may have // `#[forbid(dead_code)]` and which cannot be overridden. - static _FILE_LINE: (&'static str, usize) = (file!(), line!()); + static _FILE_LINE: (&'static str, usize) = (file!(), line!() as usize); &_FILE_LINE }) }); } +/// Macro for printing to the standard output. +/// /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. +/// +/// Note that stdout is frequently line-buffered by default so it may be +/// necessary to use `io::stdout().flush()` to ensure the output is emitted +/// immediately. #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! print { - ($($arg:tt)*) => ($crate::old_io::stdio::print_args(format_args!($($arg)*))) + ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); } -/// Macro for printing to a task's stdout handle. +/// Macro for printing to the standard output. /// -/// Each task can override its stdout handle via `std::old_io::stdio::set_stdout`. -/// The syntax of this macro is the same as that used for `format!`. For more -/// information, see `std::fmt` and `std::old_io::stdio`. +/// Use the `format!` syntax to write data to the standard output. +/// See `std::fmt` for more information. /// -/// # Example +/// # Examples /// /// ``` /// println!("hello there!"); @@ -83,19 +89,19 @@ macro_rules! print { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! println { - ($($arg:tt)*) => ($crate::old_io::stdio::println_args(format_args!($($arg)*))) + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } /// Helper macro for unwrapping `Result` values while returning early with an -/// error if the value of the expression is `Err`. For more information, see -/// `std::io`. +/// error if the value of the expression is `Err`. #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! try { ($expr:expr) => (match $expr { $crate::result::Result::Ok(val) => val, $crate::result::Result::Err(err) => { - return $crate::result::Result::Err($crate::error::FromError::from_error(err)) + return $crate::result::Result::Err($crate::convert::From::from(err)) } }) } @@ -109,6 +115,7 @@ macro_rules! try { /// # Examples /// /// ``` +/// # #![feature(std_misc)] /// use std::thread; /// use std::sync::mpsc; /// @@ -177,9 +184,9 @@ pub mod builtin { /// /// For more information, see the documentation in `std::fmt`. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// use std::fmt; /// /// let s = fmt::format(format_args!("hello {}", "world")); @@ -200,9 +207,9 @@ pub mod builtin { /// will be emitted. To not emit a compile error, use the `option_env!` /// macro instead. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let path: &'static str = env!("PATH"); /// println!("the $PATH variable at the time of compiling was: {}", path); /// ``` @@ -219,9 +226,9 @@ pub mod builtin { /// A compile time error is never emitted when using this macro regardless /// of whether the environment variable is present or not. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let key: Option<&'static str> = option_env!("SECRET_KEY"); /// println!("the secret key might be: {:?}", key); /// ``` @@ -263,7 +270,7 @@ pub mod builtin { /// Integer and floating point literals are stringified in order to be /// concatenated. /// - /// # Example + /// # Examples /// /// ``` /// let s = concat!("test", 10, 'b', true); @@ -278,7 +285,7 @@ pub mod builtin { /// the invocation of the `line!()` macro itself, but rather the first macro /// invocation leading up to the invocation of the `line!()` macro. /// - /// # Example + /// # Examples /// /// ``` /// let current_line = line!(); @@ -293,7 +300,7 @@ pub mod builtin { /// the invocation of the `column!()` macro itself, but rather the first macro /// invocation leading up to the invocation of the `column!()` macro. /// - /// # Example + /// # Examples /// /// ``` /// let current_col = column!(); @@ -309,7 +316,7 @@ pub mod builtin { /// first macro invocation leading up to the invocation of the `file!()` /// macro. /// - /// # Example + /// # Examples /// /// ``` /// let this_file = file!(); @@ -324,7 +331,7 @@ pub mod builtin { /// stringification of all the tokens passed to the macro. No restrictions /// are placed on the syntax of the macro invocation itself. /// - /// # Example + /// # Examples /// /// ``` /// let one_plus_one = stringify!(1 + 1); @@ -339,7 +346,7 @@ pub mod builtin { /// contents of the filename specified. The file is located relative to the /// current file (similarly to how modules are found), /// - /// # Example + /// # Examples /// /// ```rust,ignore /// let secret_key = include_str!("secret-key.ascii"); @@ -353,7 +360,7 @@ pub mod builtin { /// the contents of the filename specified. The file is located relative to /// the current file (similarly to how modules are found), /// - /// # Example + /// # Examples /// /// ```rust,ignore /// let secret_key = include_bytes!("secret-key.bin"); @@ -367,9 +374,9 @@ pub mod builtin { /// leading back up to the crate root. The first component of the path /// returned is the name of the crate currently being compiled. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// mod test { /// pub fn foo() { /// assert!(module_path!().ends_with("test")); @@ -390,9 +397,9 @@ pub mod builtin { /// The syntax given to this macro is the same syntax as the `cfg` /// attribute. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` /// let my_directory = if cfg!(windows) { /// "windows-specific-directory" /// } else { @@ -401,4 +408,18 @@ pub mod builtin { /// ``` #[macro_export] macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) } + + /// Parse the current given file as an expression. + /// + /// This is generally a bad idea, because it's going to behave unhygenically. + /// + /// # Examples + /// + /// ```ignore + /// fn foo() { + /// include!("/path/to/a/file") + /// } + /// ``` + #[macro_export] + macro_rules! include { ($cfg:tt) => ({ /* compiler built-in */ }) } } diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 51944adf3b..886f252fb1 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -15,165 +15,238 @@ use hash; use io; use libc::{self, socklen_t, sa_family_t}; use mem; -use net::{IpAddr, lookup_host, ntoh, hton}; +use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}; use option; use sys_common::{FromInner, AsInner, IntoInner}; use vec; -/// Representation of a socket address for networking applications +/// Representation of a socket address for networking applications. /// -/// A socket address consists of at least an (ip, port) pair and may also -/// contain other information depending on the protocol. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct SocketAddr { - repr: Repr, +/// A socket address can either represent the IPv4 or IPv6 protocol and is +/// paired with at least a port number as well. Each protocol may have more +/// specific information about the address available to it as well. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum SocketAddr { + /// An IPv4 socket address which is a (ip, port) combination. + #[stable(feature = "rust1", since = "1.0.0")] + V4(SocketAddrV4), + /// An IPv6 socket address + #[stable(feature = "rust1", since = "1.0.0")] + V6(SocketAddrV6), } +/// An IPv4 socket address which is a (ip, port) combination. #[derive(Copy)] -enum Repr { - V4(libc::sockaddr_in), - V6(libc::sockaddr_in6), -} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV4 { inner: libc::sockaddr_in } + +/// An IPv6 socket address +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV6 { inner: libc::sockaddr_in6 } impl SocketAddr { /// Creates a new socket address from the (ip, port) pair. + #[unstable(feature = "ip_addr", reason = "recent addition")] pub fn new(ip: IpAddr, port: u16) -> SocketAddr { - let repr = match ip { - IpAddr::V4(ref ip) => { - Repr::V4(libc::sockaddr_in { - sin_family: libc::AF_INET as sa_family_t, - sin_port: hton(port), - sin_addr: *ip.as_inner(), - .. unsafe { mem::zeroed() } - }) - } - IpAddr::V6(ref ip) => { - Repr::V6(libc::sockaddr_in6 { - sin6_family: libc::AF_INET6 as sa_family_t, - sin6_port: hton(port), - sin6_addr: *ip.as_inner(), - .. unsafe { mem::zeroed() } - }) - } - }; - SocketAddr { repr: repr } + match ip { + IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), + IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), + } } /// Gets the IP address associated with this socket address. + #[unstable(feature = "ip_addr", reason = "recent addition")] pub fn ip(&self) -> IpAddr { - match self.repr { - Repr::V4(ref sa) => IpAddr::V4(FromInner::from_inner(sa.sin_addr)), - Repr::V6(ref sa) => IpAddr::V6(FromInner::from_inner(sa.sin6_addr)), + match *self { + SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), + SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), } } /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { - match self.repr { - Repr::V4(ref sa) => ntoh(sa.sin_port), - Repr::V6(ref sa) => ntoh(sa.sin6_port), + match *self { + SocketAddr::V4(ref a) => a.port(), + SocketAddr::V6(ref a) => a.port(), } } +} - fn set_port(&mut self, port: u16) { - match self.repr { - Repr::V4(ref mut sa) => sa.sin_port = hton(port), - Repr::V6(ref mut sa) => sa.sin6_port = hton(port), +impl SocketAddrV4 { + /// Creates a new socket address from the (ip, port) pair. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { + SocketAddrV4 { + inner: libc::sockaddr_in { + sin_family: libc::AF_INET as sa_family_t, + sin_port: hton(port), + sin_addr: *ip.as_inner(), + .. unsafe { mem::zeroed() } + }, } } + + /// Gets the IP address associated with this socket address. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ip(&self) -> &Ipv4Addr { + unsafe { + &*(&self.inner.sin_addr as *const libc::in_addr as *const Ipv4Addr) + } + } + + /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for SocketAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.repr { - Repr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()), - Repr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()), +impl SocketAddrV6 { + /// Creates a new socket address from the ip/port/flowinfo/scope_id + /// components. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) + -> SocketAddrV6 { + SocketAddrV6 { + inner: libc::sockaddr_in6 { + sin6_family: libc::AF_INET6 as sa_family_t, + sin6_port: hton(port), + sin6_addr: *ip.as_inner(), + sin6_flowinfo: hton(flowinfo), + sin6_scope_id: hton(scope_id), + .. unsafe { mem::zeroed() } + }, } } + + /// Gets the IP address associated with this socket address. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ip(&self) -> &Ipv6Addr { + unsafe { + &*(&self.inner.sin6_addr as *const libc::in6_addr as *const Ipv6Addr) + } + } + + /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) } + + /// Gets scope ID associated with this address, corresponding to the + /// `sin6_flowinfo` field in C. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn flowinfo(&self) -> u32 { ntoh(self.inner.sin6_flowinfo) } + + /// Gets scope ID associated with this address, corresponding to the + /// `sin6_scope_id` field in C. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) } } -impl FromInner for SocketAddr { - fn from_inner(addr: libc::sockaddr_in) -> SocketAddr { - SocketAddr { repr: Repr::V4(addr) } +impl FromInner for SocketAddrV4 { + fn from_inner(addr: libc::sockaddr_in) -> SocketAddrV4 { + SocketAddrV4 { inner: addr } } } -impl FromInner for SocketAddr { - fn from_inner(addr: libc::sockaddr_in6) -> SocketAddr { - SocketAddr { repr: Repr::V6(addr) } +impl FromInner for SocketAddrV6 { + fn from_inner(addr: libc::sockaddr_in6) -> SocketAddrV6 { + SocketAddrV6 { inner: addr } } } impl<'a> IntoInner<(*const libc::sockaddr, socklen_t)> for &'a SocketAddr { fn into_inner(self) -> (*const libc::sockaddr, socklen_t) { - match self.repr { - Repr::V4(ref a) => { + match *self { + SocketAddr::V4(ref a) => { (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) } - Repr::V6(ref a) => { + SocketAddr::V6(ref a) => { (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) } } } } -impl fmt::Debug for SocketAddr { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SocketAddr::V4(ref a) => a.fmt(f), + SocketAddr::V6(ref a) => a.fmt(f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV4 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}", self.ip(), self.port()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV4 { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } -impl Clone for Repr { - fn clone(&self) -> Repr { *self } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV6 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{}]:{}", self.ip(), self.port()) + } } -impl PartialEq for Repr { - fn eq(&self, other: &Repr) -> bool { - match (*self, *other) { - (Repr::V4(ref a), Repr::V4(ref b)) => { - a.sin_port == b.sin_port && - a.sin_addr.s_addr == b.sin_addr.s_addr - } - (Repr::V6(ref a), Repr::V6(ref b)) => { - a.sin6_port == b.sin6_port && - a.sin6_addr.s6_addr == b.sin6_addr.s6_addr && - a.sin6_flowinfo == b.sin6_flowinfo && - a.sin6_scope_id == b.sin6_scope_id - } - _ => false, - } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV6 { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, fmt) } } -impl Eq for Repr {} -#[cfg(stage0)] -impl hash::Hash for Repr { - fn hash(&self, s: &mut S) { - match *self { - Repr::V4(ref a) => { - (a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s) - } - Repr::V6(ref a) => { - (a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr, - a.sin6_flowinfo, a.sin6_scope_id).hash(s) - } - } +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SocketAddrV4 { + fn clone(&self) -> SocketAddrV4 { *self } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SocketAddrV6 { + fn clone(&self) -> SocketAddrV6 { *self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for SocketAddrV4 { + fn eq(&self, other: &SocketAddrV4) -> bool { + self.inner.sin_port == other.inner.sin_port && + self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for SocketAddrV6 { + fn eq(&self, other: &SocketAddrV6) -> bool { + self.inner.sin6_port == other.inner.sin6_port && + self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr && + self.inner.sin6_flowinfo == other.inner.sin6_flowinfo && + self.inner.sin6_scope_id == other.inner.sin6_scope_id } } -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for Repr { +impl Eq for SocketAddrV4 {} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for SocketAddrV6 {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for SocketAddrV4 { fn hash(&self, s: &mut H) { - match *self { - Repr::V4(ref a) => { - (a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s) - } - Repr::V6(ref a) => { - (a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr, - a.sin6_flowinfo, a.sin6_scope_id).hash(s) - } - } + (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for SocketAddrV6 { + fn hash(&self, s: &mut H) { + (self.inner.sin6_port, &self.inner.sin6_addr.s6_addr, + self.inner.sin6_flowinfo, self.inner.sin6_scope_id).hash(s) } } @@ -183,12 +256,13 @@ impl hash::Hash for Repr { /// This trait is used for generic address resolution when constructing network /// objects. By default it is implemented for the following types: /// -/// * `SocketAddr` - `to_socket_addrs` is identity function. +/// * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is +/// identity function. /// -/// * `(IpAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. +/// * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. /// /// * `(&str, u16)` - the string should be either a string representation of an -/// IP address expected by `FromStr` implementation for `IpAddr` or a host +/// IP address expected by `FromStr` implementation for `IpvNAddr` or a host /// name. /// /// * `&str` - the string should be either a string representation of a @@ -207,18 +281,19 @@ impl hash::Hash for Repr { /// Some examples: /// /// ```no_run -/// use std::net::{IpAddr, SocketAddr, TcpStream, UdpSocket, TcpListener}; +/// # #![feature(net)] +/// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr}; /// /// fn main() { -/// let ip = IpAddr::new_v4(127, 0, 0, 1); +/// let ip = Ipv4Addr::new(127, 0, 0, 1); /// let port = 12345; /// /// // The following lines are equivalent modulo possible "localhost" name /// // resolution differences -/// let tcp_s = TcpStream::connect(&SocketAddr::new(ip, port)); -/// let tcp_s = TcpStream::connect(&(ip, port)); -/// let tcp_s = TcpStream::connect(&("127.0.0.1", port)); -/// let tcp_s = TcpStream::connect(&("localhost", port)); +/// let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port)); +/// let tcp_s = TcpStream::connect((ip, port)); +/// let tcp_s = TcpStream::connect(("127.0.0.1", port)); +/// let tcp_s = TcpStream::connect(("localhost", port)); /// let tcp_s = TcpStream::connect("127.0.0.1:12345"); /// let tcp_s = TcpStream::connect("localhost:12345"); /// @@ -226,13 +301,15 @@ impl hash::Hash for Repr { /// // behave similarly /// let tcp_l = TcpListener::bind("localhost:12345"); /// -/// let mut udp_s = UdpSocket::bind(&("127.0.0.1", port)).unwrap(); -/// udp_s.send_to(&[7], &(ip, 23451)); +/// let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap(); +/// udp_s.send_to(&[7], (ip, 23451)); /// } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub trait ToSocketAddrs { /// Returned iterator over socket addresses which this type may correspond /// to. + #[stable(feature = "rust1", since = "1.0.0")] type Iter: Iterator; /// Converts this object to an iterator of resolved `SocketAddr`s. @@ -246,9 +323,11 @@ pub trait ToSocketAddrs { /// # Errors /// /// Any errors encountered during resolution will be returned as an `Err`. + #[stable(feature = "rust1", since = "1.0.0")] fn to_socket_addrs(&self) -> io::Result; } +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for SocketAddr { type Iter = option::IntoIter; fn to_socket_addrs(&self) -> io::Result> { @@ -256,31 +335,84 @@ impl ToSocketAddrs for SocketAddr { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for SocketAddrV4 { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + SocketAddr::V4(*self).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for SocketAddrV6 { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + SocketAddr::V6(*self).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (IpAddr, u16) { type Iter = option::IntoIter; fn to_socket_addrs(&self) -> io::Result> { let (ip, port) = *self; - Ok(Some(SocketAddr::new(ip, port)).into_iter()) + match ip { + IpAddr::V4(ref a) => (*a, port).to_socket_addrs(), + IpAddr::V6(ref a) => (*a, port).to_socket_addrs(), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (Ipv4Addr, u16) { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + let (ip, port) = *self; + SocketAddrV4::new(ip, port).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (Ipv6Addr, u16) { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + let (ip, port) = *self; + SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs() } } fn resolve_socket_addr(s: &str, p: u16) -> io::Result> { let ips = try!(lookup_host(s)); let v: Vec<_> = try!(ips.map(|a| { - a.map(|mut a| { a.set_port(p); a }) + a.map(|a| { + match a { + SocketAddr::V4(ref a) => { + SocketAddr::V4(SocketAddrV4::new(*a.ip(), p)) + } + SocketAddr::V6(ref a) => { + SocketAddr::V6(SocketAddrV6::new(*a.ip(), p, a.flowinfo(), + a.scope_id())) + } + } + }) }).collect()); Ok(v.into_iter()) } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> ToSocketAddrs for (&'a str, u16) { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { let (host, port) = *self; - // try to parse the host as a regular IpAddr first - match host.parse().ok() { - Some(addr) => return Ok(vec![SocketAddr::new(addr, port)].into_iter()), - None => {} + // try to parse the host as a regular IP address first + if let Ok(addr) = host.parse::() { + let addr = SocketAddrV4::new(addr, port); + return Ok(vec![SocketAddr::V4(addr)].into_iter()) + } + if let Ok(addr) = host.parse::() { + let addr = SocketAddrV6::new(addr, port, 0, 0); + return Ok(vec![SocketAddr::V6(addr)].into_iter()) } resolve_socket_addr(host, port) @@ -288,6 +420,7 @@ impl<'a> ToSocketAddrs for (&'a str, u16) { } // accepts strings like 'localhost:12345' +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for str { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { @@ -302,7 +435,7 @@ impl ToSocketAddrs for str { match $e { Some(r) => r, None => return Err(io::Error::new(io::ErrorKind::InvalidInput, - $msg, None)), + $msg)), } ) } @@ -337,16 +470,16 @@ mod tests { assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); // out of range - let none: Option = "256.0.0.1".parse().ok(); + let none: Option = "256.0.0.1".parse().ok(); assert_eq!(None, none); // too short - let none: Option = "255.0.0".parse().ok(); + let none: Option = "255.0.0".parse().ok(); assert_eq!(None, none); // too long - let none: Option = "255.0.0.1.2".parse().ok(); + let none: Option = "255.0.0.1.2".parse().ok(); assert_eq!(None, none); // no number between dots - let none: Option = "255.0..1".parse().ok(); + let none: Option = "255.0..1".parse().ok(); assert_eq!(None, none); } @@ -362,19 +495,19 @@ mod tests { "2a02:6b8::11:11".parse()); // too long group - let none: Option = "::00000".parse().ok(); + let none: Option = "::00000".parse().ok(); assert_eq!(None, none); // too short - let none: Option = "1:2:3:4:5:6:7".parse().ok(); + let none: Option = "1:2:3:4:5:6:7".parse().ok(); assert_eq!(None, none); // too long - let none: Option = "1:2:3:4:5:6:7:8:9".parse().ok(); + let none: Option = "1:2:3:4:5:6:7:8:9".parse().ok(); assert_eq!(None, none); // triple colon - let none: Option = "1:2:::6:7:8".parse().ok(); + let none: Option = "1:2:::6:7:8".parse().ok(); assert_eq!(None, none); // two double colons - let none: Option = "1:2::6::8".parse().ok(); + let none: Option = "1:2::6::8".parse().ok(); assert_eq!(None, none); } @@ -390,24 +523,24 @@ mod tests { "2001:db8:122:c000:2:2100:192.0.2.33".parse()); // colon after v4 - let none: Option = "::127.0.0.1:".parse().ok(); + let none: Option = "::127.0.0.1:".parse().ok(); assert_eq!(None, none); // not enough groups - let none: Option = "1.2.3.4.5:127.0.0.1".parse().ok(); + let none: Option = "1.2.3.4.5:127.0.0.1".parse().ok(); assert_eq!(None, none); // too many groups - let none: Option = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); + let none: Option = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); assert_eq!(None, none); } #[test] fn test_from_str_socket_addr() { - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 80)), - "77.88.21.11:80".parse()); - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), - "[2a02:6b8:0:1::1]:53".parse()); - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), - "[::127.0.0.1]:22".parse()); + assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), + "77.88.21.11:80".parse()); + assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), + "[2a02:6b8:0:1::1]:53".parse()); + assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), + "[::127.0.0.1]:22".parse()); // without port let none: Option = "127.0.0.1".parse().ok(); @@ -515,7 +648,7 @@ mod tests { unique_local: bool, global: bool, u_link_local: bool, u_site_local: bool, u_global: bool, m_scope: Option) { - let ip: Ipv6Addr = str_addr.parse().ok().unwrap(); + let ip: Ipv6Addr = str_addr.parse().unwrap(); assert_eq!(str_addr, ip.to_string()); assert_eq!(ip.is_unspecified(), unspec); @@ -564,45 +697,62 @@ mod tests { false, false, false, true, false, false, false, Some(Global)); } - fn tsa(a: A) -> io::Result> { - Ok(try!(a.to_socket_addrs()).collect()) + fn tsa(a: A) -> Result, String> { + match a.to_socket_addrs() { + Ok(a) => Ok(a.collect()), + Err(e) => Err(e.to_string()), + } } #[test] fn to_socket_addr_socketaddr() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 12345); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345); assert_eq!(Ok(vec![a]), tsa(a)); } + fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new(a, p)) + } + + fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { + SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) + } + #[test] fn to_socket_addr_ipaddr_u16() { - let a = IpAddr::new_v4(77, 88, 21, 11); - let p = 12345u16; - let e = SocketAddr::new(a, p); + let a = Ipv4Addr::new(77, 88, 21, 11); + let p = 12345; + let e = SocketAddr::V4(SocketAddrV4::new(a, p)); assert_eq!(Ok(vec![e]), tsa((a, p))); } #[test] fn to_socket_addr_str_u16() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 24352); - assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352u16))); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); + assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352))); - let a = SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); + let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53))); - let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); - assert!(tsa(("localhost", 23924u16)).unwrap().contains(&a)); + let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); + assert!(tsa(("localhost", 23924)).unwrap().contains(&a)); } #[test] fn to_socket_addr_str() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 24352); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352")); - let a = SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); + let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53")); - let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); + let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); assert!(tsa("localhost:23924").unwrap().contains(&a)); } + + #[test] + #[cfg(not(windows))] + fn to_socket_addr_str_bad() { + assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err()); + } } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 571a1b03ef..c8b1928747 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "ip", reason = "extra functionality has not been \ + scrutinized to the level that it should \ + be stable")] + use prelude::v1::*; use cmp::Ordering; @@ -17,14 +21,26 @@ use libc; use sys_common::{AsInner, FromInner}; use net::{hton, ntoh}; +/// An IP address, either a IPv4 or IPv6 address. +#[unstable(feature = "ip_addr", reason = "recent addition")] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] +pub enum IpAddr { + /// Representation of an IPv4 address. + V4(Ipv4Addr), + /// Representation of an IPv6 address. + V6(Ipv6Addr), +} + /// Representation of an IPv4 address. #[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { inner: libc::in_addr, } /// Representation of an IPv6 address. #[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { inner: libc::in6_addr, } @@ -41,46 +57,11 @@ pub enum Ipv6MulticastScope { Global } -/// Enumeration of possible IP addresses -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] -pub enum IpAddr { - /// An IPv4 address. - V4(Ipv4Addr), - /// An IPv6 address. - V6(Ipv6Addr) -} - -impl IpAddr { - /// Create a new IpAddr that contains an IPv4 address. - /// - /// The result will represent the IP address a.b.c.d - pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr { - IpAddr::V4(Ipv4Addr::new(a, b, c, d)) - } - - /// Create a new IpAddr that contains an IPv6 address. - /// - /// The result will represent the IP address a:b:c:d:e:f - pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, - h: u16) -> IpAddr { - IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for IpAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - IpAddr::V4(v4) => v4.fmt(f), - IpAddr::V6(v6) => v6.fmt(f) - } - } -} - impl Ipv4Addr { /// Create a new IPv4 address from four eight-bit octets. /// /// The result will represent the IP address a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { Ipv4Addr { inner: libc::in_addr { @@ -93,6 +74,7 @@ impl Ipv4Addr { } /// Returns the four eight-bit integers that make up this address + #[stable(feature = "rust1", since = "1.0.0")] pub fn octets(&self) -> [u8; 4] { let bits = ntoh(self.inner.s_addr); [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] @@ -148,6 +130,7 @@ impl Ipv4Addr { /// Convert this address to an IPv4-compatible IPv6 address /// /// a.b.c.d becomes ::a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_compatible(&self) -> Ipv6Addr { Ipv6Addr::new(0, 0, 0, 0, 0, 0, ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, @@ -157,6 +140,7 @@ impl Ipv4Addr { /// Convert this address to an IPv4-mapped IPv6 address /// /// a.b.c.d becomes ::ffff:a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_mapped(&self) -> Ipv6Addr { Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, @@ -165,6 +149,17 @@ impl Ipv4Addr { } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + IpAddr::V4(ref a) => a.fmt(fmt), + IpAddr::V6(ref a) => a.fmt(fmt), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let octets = self.octets(); @@ -172,30 +167,28 @@ impl fmt::Display for Ipv4Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Ipv4Addr { fn clone(&self) -> Ipv4Addr { *self } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Ipv4Addr { fn eq(&self, other: &Ipv4Addr) -> bool { self.inner.s_addr == other.inner.s_addr } } + +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ipv4Addr {} -#[cfg(stage0)] -impl hash::Hash for Ipv4Addr { - fn hash(&self, s: &mut S) { - self.inner.s_addr.hash(s) - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl hash::Hash for Ipv4Addr { fn hash(&self, s: &mut H) { @@ -203,12 +196,14 @@ impl hash::Hash for Ipv4Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv4Addr { fn partial_cmp(&self, other: &Ipv4Addr) -> Option { Some(self.cmp(other)) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv4Addr { fn cmp(&self, other: &Ipv4Addr) -> Ordering { self.inner.s_addr.cmp(&other.inner.s_addr) @@ -227,7 +222,8 @@ impl FromInner for Ipv4Addr { impl Ipv6Addr { /// Create a new IPv6 address from eight 16-bit segments. /// - /// The result will represent the IP address a:b:c:d:e:f + /// The result will represent the IP address a:b:c:d:e:f:g:h + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { Ipv6Addr { @@ -239,6 +235,7 @@ impl Ipv6Addr { } /// Return the eight 16-bit segments that make up this address + #[stable(feature = "rust1", since = "1.0.0")] pub fn segments(&self) -> [u16; 8] { [ntoh(self.inner.s6_addr[0]), ntoh(self.inner.s6_addr[1]), @@ -331,6 +328,7 @@ impl Ipv6Addr { /// neither IPv4-compatible or IPv4-mapped. /// /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv4(&self) -> Option { match self.segments() { [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => { @@ -342,6 +340,7 @@ impl Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv6Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.segments() { @@ -366,7 +365,7 @@ impl fmt::Display for Ipv6Addr { let mut cur_span_len = 0; let mut cur_span_at = 0; - for i in range(0, 8) { + for i in 0..8 { if segments[i] == 0 { if cur_span_len == 0 { cur_span_at = i; @@ -395,7 +394,6 @@ impl fmt::Display for Ipv6Addr { .iter() .map(|&seg| format!("{:x}", seg)) .collect::>() - .as_slice() .connect(":") } @@ -412,30 +410,28 @@ impl fmt::Display for Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Ipv6Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Ipv6Addr { fn clone(&self) -> Ipv6Addr { *self } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Ipv6Addr { fn eq(&self, other: &Ipv6Addr) -> bool { self.inner.s6_addr == other.inner.s6_addr } } + +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ipv6Addr {} -#[cfg(stage0)] -impl hash::Hash for Ipv6Addr { - fn hash(&self, s: &mut S) { - self.inner.s6_addr.hash(s) - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl hash::Hash for Ipv6Addr { fn hash(&self, s: &mut H) { @@ -443,12 +439,14 @@ impl hash::Hash for Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv6Addr { fn partial_cmp(&self, other: &Ipv6Addr) -> Option { Some(self.cmp(other)) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv6Addr { fn cmp(&self, other: &Ipv6Addr) -> Ordering { self.inner.s6_addr.cmp(&other.inner.s6_addr) diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index d73c06a254..a152b98822 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -11,21 +11,22 @@ //! Networking primitives for TCP/UDP communication //! //! > **NOTE**: This module is very much a work in progress and is under active -//! > development. At this time it is still recommended to use the `old_io` -//! > module while the details of this module shake out. +//! > development. -#![unstable(feature = "net")] +#![stable(feature = "rust1", since = "1.0.0")] use prelude::v1::*; use io::{self, Error, ErrorKind}; +#[allow(deprecated)] // Int use num::Int; use sys_common::net2 as net_imp; pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; -pub use self::addr::{SocketAddr, ToSocketAddrs}; +pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; +pub use self::parser::AddrParseError; mod ip; mod addr; @@ -37,23 +38,29 @@ mod parser; /// Possible values which can be passed to the `shutdown` method of `TcpStream` /// and `UdpSocket`. #[derive(Copy, Clone, PartialEq)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Shutdown { /// Indicates that the reading portion of this stream/socket should be shut /// down. All currently blocked and future reads will return `Ok(0)`. + #[stable(feature = "rust1", since = "1.0.0")] Read, /// Indicates that the writing portion of this stream/socket should be shut /// down. All currently blocked and future writes will return an error. + #[stable(feature = "rust1", since = "1.0.0")] Write, /// Shut down both the reading and writing portions of this stream. /// /// See `Shutdown::Read` and `Shutdown::Write` for more information. - Both + #[stable(feature = "rust1", since = "1.0.0")] + Both, } +#[allow(deprecated)] // Int fn hton(i: I) -> I { i.to_be() } +#[allow(deprecated)] // Int fn ntoh(i: I) -> I { Int::from_be(i) } -fn each_addr(addr: &A, mut f: F) -> io::Result +fn each_addr(addr: A, mut f: F) -> io::Result where F: FnMut(&SocketAddr) -> io::Result { let mut last_err = None; @@ -65,13 +72,19 @@ fn each_addr(addr: &A, mut f: F) -> io::Result< } Err(last_err.unwrap_or_else(|| { Error::new(ErrorKind::InvalidInput, - "could not resolve to any addresses", None) + "could not resolve to any addresses") })) } /// An iterator over `SocketAddr` values returned from a host lookup operation. +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] pub struct LookupHost(net_imp::LookupHost); +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] impl Iterator for LookupHost { type Item = io::Result; fn next(&mut self) -> Option> { self.0.next() } @@ -82,9 +95,10 @@ impl Iterator for LookupHost { /// This method may perform a DNS query to resolve `host` and may also inspect /// system configuration to resolve the specified hostname. /// -/// # Example +/// # Examples /// /// ```no_run +/// # #![feature(lookup_host)] /// use std::net; /// /// # fn foo() -> std::io::Result<()> { @@ -94,6 +108,19 @@ impl Iterator for LookupHost { /// # Ok(()) /// # } /// ``` +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] pub fn lookup_host(host: &str) -> io::Result { net_imp::lookup_host(host).map(LookupHost) } + +/// Resolve the given address to a hostname. +/// +/// This function may perform a DNS query to resolve `addr` and may also inspect +/// system configuration to resolve the specified address. If the address +/// cannot be resolved, it is returned in string format. +#[unstable(feature = "lookup_addr", reason = "recent addition")] +pub fn lookup_addr(addr: &IpAddr) -> io::Result { + net_imp::lookup_addr(addr) +} diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index e82dc88cdd..7c1667a603 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use str::FromStr; -use net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr}; +use net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; struct Parser<'a> { // parsing as ASCII, so can use byte array @@ -136,7 +136,7 @@ impl<'a> Parser<'a> { } fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option { - let mut r = 0u32; + let mut r = 0; let mut digit_count = 0; loop { match self.read_digit(radix) { @@ -164,7 +164,7 @@ impl<'a> Parser<'a> { } fn read_ipv4_addr_impl(&mut self) -> Option { - let mut bs = [0u8; 4]; + let mut bs = [0; 4]; let mut i = 0; while i < 4 { if i != 0 && self.read_given_char('.').is_none() { @@ -189,7 +189,7 @@ impl<'a> Parser<'a> { fn read_ipv6_addr_impl(&mut self) -> Option { fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr { assert!(head.len() + tail.len() <= 8); - let mut gs = [0u16; 8]; + let mut gs = [0; 8]; gs.clone_from_slice(head); gs[(8 - tail.len()) .. 8].clone_from_slice(tail); Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) @@ -231,7 +231,7 @@ impl<'a> Parser<'a> { (i, false) } - let mut head = [0u16; 8]; + let mut head = [0; 8]; let (head_size, head_ipv4) = read_groups(self, &mut head, 8); if head_size == 8 { @@ -250,7 +250,7 @@ impl<'a> Parser<'a> { return None; } - let mut tail = [0u16; 8]; + let mut tail = [0; 8]; let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size); Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size])) } @@ -281,50 +281,61 @@ impl<'a> Parser<'a> { let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16); // host, colon, port - self.read_seq_3::(ip_addr, colon, port) - .map(|t| match t { (ip, _, port) => SocketAddr::new(ip, port) }) + self.read_seq_3(ip_addr, colon, port).map(|t| { + let (ip, _, port): (IpAddr, char, u16) = t; + match ip { + IpAddr::V4(ip) => SocketAddr::V4(SocketAddrV4::new(ip, port)), + IpAddr::V6(ip) => SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)), + } + }) } } +#[unstable(feature = "ip_addr", reason = "recent addition")] impl FromStr for IpAddr { - type Err = ParseError; - fn from_str(s: &str) -> Result { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) { Some(s) => Ok(s), - None => Err(ParseError), + None => Err(AddrParseError(())) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl FromStr for Ipv4Addr { - type Err = ParseError; - fn from_str(s: &str) -> Result { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) { Some(s) => Ok(s), - None => Err(ParseError) + None => Err(AddrParseError(())) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl FromStr for Ipv6Addr { - type Err = ParseError; - fn from_str(s: &str) -> Result { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) { Some(s) => Ok(s), - None => Err(ParseError) + None => Err(AddrParseError(())) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl FromStr for SocketAddr { - type Err = ParseError; - fn from_str(s: &str) -> Result { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { match Parser::new(s).read_till_eof(|p| p.read_socket_addr()) { Some(s) => Ok(s), - None => Err(ParseError), + None => Err(AddrParseError(())), } } } -#[derive(Debug, Clone, PartialEq, Copy)] -pub struct ParseError; +/// An error returned when parsing an IP address or a socket address. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug, Clone, PartialEq)] +pub struct AddrParseError(()); diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index b861b74947..04d1013af1 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -8,22 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "tcp", reason = "remaining functions have not been \ + scrutinized enough to be stabilized")] + use prelude::v1::*; use io::prelude::*; use io; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A structure which represents a TCP stream between a local socket and a /// remote socket. /// /// The socket will be closed when the value is dropped. /// -/// # Example +/// # Examples /// /// ```no_run +/// # #![feature(net)] /// use std::io::prelude::*; /// use std::net::TcpStream; /// @@ -35,6 +39,7 @@ use sys_common::AsInner; /// let _ = stream.read(&mut [0; 128]); // ignore here too /// } // the stream is closed here /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct TcpStream(net_imp::TcpStream); /// A structure representing a socket server. @@ -42,6 +47,7 @@ pub struct TcpStream(net_imp::TcpStream); /// # Examples /// /// ```no_run +/// # #![feature(net)] /// use std::net::{TcpListener, TcpStream}; /// use std::thread; /// @@ -67,12 +73,14 @@ pub struct TcpStream(net_imp::TcpStream); /// // close the socket server /// drop(listener); /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); /// An infinite iterator over the connections from a `TcpListener`. /// /// This iterator will infinitely yield `Some` of the accepted connections. It /// is equivalent to calling `accept` in a loop. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Incoming<'a> { listener: &'a TcpListener } impl TcpStream { @@ -81,17 +89,20 @@ impl TcpStream { /// `addr` is an address of the remote host. Anything which implements /// `ToSocketAddrs` trait can be supplied for the address; see this trait /// documentation for concrete examples. - pub fn connect(addr: &A) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn connect(addr: A) -> io::Result { super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) } /// Returns the socket address of the remote peer of this TCP connection. + #[stable(feature = "rust1", since = "1.0.0")] pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Returns the socket address of the local half of this TCP connection. - pub fn socket_addr(&self) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result { self.0.socket_addr() } @@ -100,6 +111,7 @@ impl TcpStream { /// This function will cause all pending and future I/O on the specified /// portions to return immediately with an appropriate value (see the /// documentation of `Shutdown`). + #[stable(feature = "rust1", since = "1.0.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } @@ -110,6 +122,7 @@ impl TcpStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propagated to the other /// stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(TcpStream) } @@ -129,16 +142,20 @@ impl TcpStream { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -148,6 +165,10 @@ impl AsInner for TcpStream { fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } } +impl FromInner for TcpStream { + fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) } +} + impl TcpListener { /// Creates a new `TcpListener` which will be bound to the specified /// address. @@ -160,12 +181,14 @@ impl TcpListener { /// /// The address type can be any implementer of `ToSocketAddrs` trait. See /// its documentation for concrete examples. - pub fn bind(addr: &A) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bind(addr: A) -> io::Result { super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) } /// Returns the local socket address of this listener. - pub fn socket_addr(&self) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result { self.0.socket_addr() } @@ -174,6 +197,7 @@ impl TcpListener { /// The returned `TcpListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(TcpListener) } @@ -183,6 +207,7 @@ impl TcpListener { /// This function will block the calling thread until a new TCP connection /// is established. When established, the corresponding `TcpStream` and the /// remote peer's address will be returned. + #[stable(feature = "rust1", since = "1.0.0")] pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { self.0.accept().map(|(a, b)| (TcpStream(a), b)) } @@ -192,11 +217,13 @@ impl TcpListener { /// /// The returned iterator will never returned `None` and will also not yield /// the peer's `SocketAddr` structure. + #[stable(feature = "rust1", since = "1.0.0")] pub fn incoming(&self) -> Incoming { Incoming { listener: self } } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result; fn next(&mut self) -> Option> { @@ -208,6 +235,12 @@ impl AsInner for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } } +impl FromInner for TcpListener { + fn from_inner(inner: net_imp::TcpListener) -> TcpListener { + TcpListener(inner) + } +} + #[cfg(test)] mod tests { use prelude::v1::*; @@ -233,13 +266,12 @@ mod tests { } } - // FIXME #11530 this fails on android because tests are run as root - #[cfg_attr(any(windows, target_os = "android"), ignore)] #[test] fn bind_error() { - match TcpListener::bind("0.0.0.0:1") { + match TcpListener::bind("1.1.1.1:9999") { Ok(..) => panic!(), - Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied), + Err(e) => + assert_eq!(e.kind(), ErrorKind::AddrNotAvailable), } } @@ -247,8 +279,11 @@ mod tests { fn connect_error() { match TcpStream::connect("0.0.0.0:1") { Ok(..) => panic!(), - Err(e) => assert!((e.kind() == ErrorKind::ConnectionRefused) - || (e.kind() == ErrorKind::InvalidInput)), + Err(e) => assert!(e.kind() == ErrorKind::ConnectionRefused || + e.kind() == ErrorKind::InvalidInput || + e.kind() == ErrorKind::AddrInUse || + e.kind() == ErrorKind::AddrNotAvailable, + "bad error: {} {:?}", e, e.kind()), } } @@ -310,7 +345,7 @@ mod tests { let _t = thread::spawn(move|| { let mut stream = t!(TcpStream::connect(&addr)); t!(stream.write(&[99])); - tx.send(t!(stream.socket_addr())).unwrap(); + tx.send(t!(stream.local_addr())).unwrap(); }); let (mut stream, addr) = t!(acceptor.accept()); @@ -425,7 +460,7 @@ mod tests { #[test] fn multiple_connect_interleaved_lazy_schedule_ip4() { - static MAX: usize = 10; + const MAX: usize = 10; each_ip(&mut |addr| { let acceptor = t!(TcpListener::bind(&addr)); @@ -456,17 +491,11 @@ mod tests { } } - pub fn socket_name(addr: SocketAddr) { - } - - pub fn peer_name(addr: SocketAddr) { - } - #[test] fn socket_and_peer_name_ip4() { each_ip(&mut |addr| { let listener = t!(TcpListener::bind(&addr)); - let so_name = t!(listener.socket_addr()); + let so_name = t!(listener.local_addr()); assert_eq!(addr, so_name); let _t = thread::spawn(move|| { t!(listener.accept()); @@ -492,7 +521,7 @@ mod tests { let mut c = t!(TcpStream::connect(&addr)); let mut b = [0; 10]; - assert_eq!(c.read(&mut b), Ok(1)); + assert_eq!(c.read(&mut b).unwrap(), 1); t!(c.write(&[1])); rx.recv().unwrap(); }) @@ -506,7 +535,8 @@ mod tests { Ok(..) => panic!(), Err(e) => { assert!(e.kind() == ErrorKind::ConnectionRefused || - e.kind() == ErrorKind::Other, + e.kind() == ErrorKind::Other || + e.kind() == ErrorKind::AddrInUse, "unknown error: {} {:?}", e, e.kind()); } } @@ -536,7 +566,7 @@ mod tests { let _t = thread::spawn(move|| { let mut s = t!(TcpStream::connect(&addr)); let mut buf = [0, 0]; - assert_eq!(s.read(&mut buf), Ok(1)); + assert_eq!(s.read(&mut buf).unwrap(), 1); assert_eq!(buf[0], 1); t!(s.write(&[2])); }); @@ -554,7 +584,7 @@ mod tests { }); tx1.send(()).unwrap(); let mut buf = [0, 0]; - assert_eq!(s1.read(&mut buf), Ok(1)); + assert_eq!(s1.read(&mut buf).unwrap(), 1); rx2.recv().unwrap(); }) } @@ -627,7 +657,7 @@ mod tests { let _t = thread::spawn(move|| { let mut c = t!(a.accept()).0; let mut b = [0]; - assert_eq!(c.read(&mut b), Ok(0)); + assert_eq!(c.read(&mut b).unwrap(), 0); t!(c.write(&[1])); }); @@ -658,16 +688,16 @@ mod tests { t!(s.shutdown(Shutdown::Write)); assert!(s.write(&[0]).is_err()); t!(s.shutdown(Shutdown::Read)); - assert_eq!(s.read(&mut b), Ok(0)); + assert_eq!(s.read(&mut b).unwrap(), 0); // closing should affect previous handles assert!(s2.write(&[0]).is_err()); - assert_eq!(s2.read(&mut b), Ok(0)); + assert_eq!(s2.read(&mut b).unwrap(), 0); // closing should affect new handles let mut s3 = t!(s.try_clone()); assert!(s3.write(&[0]).is_err()); - assert_eq!(s3.read(&mut b), Ok(0)); + assert_eq!(s3.read(&mut b).unwrap(), 0); // make sure these don't die let _ = s2.shutdown(Shutdown::Read); diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs index 971fb4b69c..3d42472f0f 100644 --- a/src/libstd/net/test.rs +++ b/src/libstd/net/test.rs @@ -11,19 +11,20 @@ use prelude::v1::*; use env; -use net::{SocketAddr, IpAddr}; +use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr}; use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; +static PORT: AtomicUsize = ATOMIC_USIZE_INIT; + pub fn next_test_ip4() -> SocketAddr { - static PORT: AtomicUsize = ATOMIC_USIZE_INIT; - SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), - PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port()) + let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)) } pub fn next_test_ip6() -> SocketAddr { - static PORT: AtomicUsize = ATOMIC_USIZE_INIT; - SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0, 1), - PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port()) + let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); + SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), + port, 0, 0)) } // The bots run multiple builds at the same time, and these builds @@ -33,7 +34,7 @@ fn base_port() -> u16 { let cwd = env::current_dir().unwrap(); let dirs = ["32-opt", "32-nopt", "64-opt", "64-nopt", "64-opt-vg", "all-opt", "snap3", "dist"]; - dirs.iter().enumerate().find(|&(i, dir)| { - cwd.as_str().unwrap().contains(dir) + dirs.iter().enumerate().find(|&(_, dir)| { + cwd.to_str().unwrap().contains(dir) }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600 } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 92f0059982..7b14e4dbea 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "udp", reason = "remaining functions have not been \ + scrutinized enough to be stabilized")] + use prelude::v1::*; use io::{self, Error, ErrorKind}; use net::{ToSocketAddrs, SocketAddr, IpAddr}; use sys_common::net2 as net_imp; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; /// A User Datagram Protocol socket. /// @@ -21,9 +24,10 @@ use sys_common::AsInner; /// IPv6 addresses, and there is no corresponding notion of a server because UDP /// is a datagram protocol. /// -/// # Example +/// # Examples /// /// ```no_run +/// # #![feature(net)] /// use std::net::UdpSocket; /// /// # fn foo() -> std::io::Result<()> { @@ -41,6 +45,7 @@ use sys_common::AsInner; /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct UdpSocket(net_imp::UdpSocket); impl UdpSocket { @@ -48,12 +53,14 @@ impl UdpSocket { /// /// Address type can be any implementor of `ToSocketAddr` trait. See its /// documentation for concrete examples. - pub fn bind(addr: &A) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bind(addr: A) -> io::Result { super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) } /// Receives data from the socket. On success, returns the number of bytes /// read and the address from whence the data came. + #[stable(feature = "rust1", since = "1.0.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.0.recv_from(buf) } @@ -63,17 +70,19 @@ impl UdpSocket { /// /// Address type can be any implementor of `ToSocketAddrs` trait. See its /// documentation for concrete examples. - pub fn send_to(&self, buf: &[u8], addr: &A) - -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn send_to(&self, buf: &[u8], addr: A) + -> io::Result { match try!(addr.to_socket_addrs()).next() { Some(addr) => self.0.send_to(buf, &addr), None => Err(Error::new(ErrorKind::InvalidInput, - "no addresses to send data to", None)), + "no addresses to send data to")), } } /// Returns the socket address that this socket was created from. - pub fn socket_addr(&self) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result { self.0.socket_addr() } @@ -82,6 +91,7 @@ impl UdpSocket { /// The returned `UdpSocket` is a reference to the same socket that this /// object references. Both handles will read and write the same port, and /// options set on one socket will be propagated to the other. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UdpSocket) } @@ -123,6 +133,10 @@ impl AsInner for UdpSocket { fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } } +impl FromInner for UdpSocket { + fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) } +} + #[cfg(test)] mod tests { use prelude::v1::*; @@ -151,7 +165,7 @@ mod tests { #[cfg_attr(any(windows, target_os = "android"), ignore)] #[test] fn bind_error() { - let addr = SocketAddr::new(IpAddr::new_v4(0, 0, 0, 0), 1); + let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1); match UdpSocket::bind(&addr) { Ok(..) => panic!(), Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied), @@ -186,7 +200,7 @@ mod tests { fn socket_name_ip4() { each_ip(&mut |addr, _| { let server = t!(UdpSocket::bind(&addr)); - assert_eq!(addr, t!(server.socket_addr())); + assert_eq!(addr, t!(server.local_addr())); }) } @@ -198,7 +212,7 @@ mod tests { let _t = thread::spawn(move|| { let mut buf = [0, 0]; - assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1))); + assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1)); assert_eq!(buf[0], 1); t!(sock2.send_to(&[2], &addr1)); }); @@ -214,7 +228,7 @@ mod tests { }); tx1.send(()).unwrap(); let mut buf = [0, 0]; - assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2))); + assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2)); rx2.recv().unwrap(); }) } diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 7d15a16309..0ae4d3c5bd 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -75,6 +75,7 @@ mod cmath { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl Float for f32 { #[inline] fn nan() -> f32 { num::Float::nan() } @@ -91,27 +92,27 @@ impl Float for f32 { #[allow(deprecated)] #[inline] - fn mantissa_digits(unused_self: Option) -> uint { + fn mantissa_digits(unused_self: Option) -> usize { num::Float::mantissa_digits(unused_self) } #[allow(deprecated)] #[inline] - fn digits(unused_self: Option) -> uint { num::Float::digits(unused_self) } + fn digits(unused_self: Option) -> usize { num::Float::digits(unused_self) } #[allow(deprecated)] #[inline] fn epsilon() -> f32 { num::Float::epsilon() } #[allow(deprecated)] #[inline] - fn min_exp(unused_self: Option) -> int { num::Float::min_exp(unused_self) } + fn min_exp(unused_self: Option) -> isize { num::Float::min_exp(unused_self) } #[allow(deprecated)] #[inline] - fn max_exp(unused_self: Option) -> int { num::Float::max_exp(unused_self) } + fn max_exp(unused_self: Option) -> isize { num::Float::max_exp(unused_self) } #[allow(deprecated)] #[inline] - fn min_10_exp(unused_self: Option) -> int { num::Float::min_10_exp(unused_self) } + fn min_10_exp(unused_self: Option) -> isize { num::Float::min_10_exp(unused_self) } #[allow(deprecated)] #[inline] - fn max_10_exp(unused_self: Option) -> int { num::Float::max_10_exp(unused_self) } + fn max_10_exp(unused_self: Option) -> isize { num::Float::max_10_exp(unused_self) } #[allow(deprecated)] #[inline] fn min_value() -> f32 { num::Float::min_value() } @@ -191,8 +192,8 @@ impl Float for f32 { /// Constructs a floating point number by multiplying `x` by 2 raised to the /// power of `exp` #[inline] - fn ldexp(x: f32, exp: int) -> f32 { - unsafe { cmath::ldexpf(x, exp as c_int) } + fn ldexp(self, exp: isize) -> f32 { + unsafe { cmath::ldexpf(self, exp as c_int) } } /// Breaks the number into a normalized fraction and a base-2 exponent, @@ -201,11 +202,11 @@ impl Float for f32 { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` #[inline] - fn frexp(self) -> (f32, int) { + fn frexp(self) -> (f32, isize) { unsafe { let mut exp = 0; let x = cmath::frexpf(self, &mut exp); - (x, exp as int) + (x, exp as isize) } } @@ -357,209 +358,1516 @@ impl Float for f32 { } } -// -// Section: String Conversions -// - -/// Converts a float to a string -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_string(num: f32) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigAll, ExpNone, false); - r -} +#[cfg(not(test))] +#[lang = "f32"] +#[stable(feature = "rust1", since = "1.0.0")] +impl f32 { + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::f32; + /// + /// let nan = f32::NAN; + /// let f = 7.0_f32; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_nan(self) -> bool { num::Float::is_nan(self) } -/// Converts a float to a string in hexadecimal format -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_hex(num: f32) -> String { - let (r, _) = strconv::float_to_str_common( - num, 16, true, SignNeg, DigAll, ExpNone, false); - r -} + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf = f32::INFINITY; + /// let neg_inf = f32::NEG_INFINITY; + /// let nan = f32::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } -/// Converts a float to a string in a given radix, and a flag indicating -/// whether it's a special value -/// -/// # Arguments -/// -/// * num - The float value -/// * radix - The base to use -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_radix_special(num: f32, rdx: u32) -> (String, bool) { - strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false) -} + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::f32; + /// + /// let f = 7.0f32; + /// let inf = f32::INFINITY; + /// let neg_inf = f32::NEG_INFINITY; + /// let nan = f32::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_finite(self) -> bool { num::Float::is_finite(self) } -/// Converts a float to a string with exactly the number of -/// provided significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exact(num: f32, dig: uint) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpNone, false); - r -} + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0_f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_normal(self) -> bool { num::Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::FpCategory; + /// use std::f32; + /// + /// let num = 12.4_f32; + /// let inf = f32::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { num::Float::classify(self) } -/// Converts a float to a string with a maximum number of -/// significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_digits(num: f32, dig: uint) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpNone, false); - r -} + /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. + /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. + /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let num = 2.0f32; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = num.integer_decode(); + /// let sign_f = sign as f32; + /// let mantissa_f = mantissa as f32; + /// let exponent_f = num.powf(exponent as f32); + /// + /// // 1 * 8388608 * 2^(-22) == 2 + /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + /// [floating-point]: ../../../../../reference.html#machine-types + #[unstable(feature = "std_misc", reason = "signature is undecided")] + #[inline] + pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } -/// Converts a float to a string using the exponential notation with exactly the number of -/// provided digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpDec, upper); - r -} + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// let f = 3.99_f32; + /// let g = 3.0_f32; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn floor(self) -> f32 { num::Float::floor(self) } -/// Converts a float to a string using the exponential notation with the maximum number of -/// digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpDec, upper); - r -} + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// let f = 3.01_f32; + /// let g = 4.0_f32; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ceil(self) -> f32 { num::Float::ceil(self) } -#[cfg(test)] -mod tests { - use f32::*; - use num::*; - use num::FpCategory as Fp; + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// let f = 3.3_f32; + /// let g = -3.3_f32; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn round(self) -> f32 { num::Float::round(self) } - #[test] - fn test_min_nan() { - assert_eq!(NAN.min(2.0), 2.0); - assert_eq!(2.0f32.min(NAN), 2.0); - } + /// Return the integer part of a number. + /// + /// ``` + /// let f = 3.3_f32; + /// let g = -3.7_f32; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trunc(self) -> f32 { num::Float::trunc(self) } - #[test] - fn test_max_nan() { - assert_eq!(NAN.max(2.0), 2.0); - assert_eq!(2.0f32.max(NAN), 2.0); - } + /// Returns the fractional part of a number. + /// + /// ``` + /// use std::f32; + /// + /// let x = 3.5_f32; + /// let y = -3.5_f32; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x <= f32::EPSILON); + /// assert!(abs_difference_y <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn fract(self) -> f32 { num::Float::fract(self) } - #[test] - fn test_num_f32() { - test_num(10f32, 2f32); - } + /// Computes the absolute value of `self`. Returns `NAN` if the + /// number is `NAN`. + /// + /// ``` + /// use std::f32; + /// + /// let x = 3.5_f32; + /// let y = -3.5_f32; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x <= f32::EPSILON); + /// assert!(abs_difference_y <= f32::EPSILON); + /// + /// assert!(f32::NAN.abs().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> f32 { num::Float::abs(self) } - #[test] - fn test_floor() { - assert_approx_eq!(1.0f32.floor(), 1.0f32); - assert_approx_eq!(1.3f32.floor(), 1.0f32); - assert_approx_eq!(1.5f32.floor(), 1.0f32); - assert_approx_eq!(1.7f32.floor(), 1.0f32); - assert_approx_eq!(0.0f32.floor(), 0.0f32); - assert_approx_eq!((-0.0f32).floor(), -0.0f32); - assert_approx_eq!((-1.0f32).floor(), -1.0f32); - assert_approx_eq!((-1.3f32).floor(), -2.0f32); - assert_approx_eq!((-1.5f32).floor(), -2.0f32); - assert_approx_eq!((-1.7f32).floor(), -2.0f32); - } + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - `NAN` if the number is `NAN` + /// + /// ``` + /// use std::f32; + /// + /// let f = 3.5_f32; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f32::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f32::NAN.signum().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> f32 { num::Float::signum(self) } - #[test] - fn test_ceil() { - assert_approx_eq!(1.0f32.ceil(), 1.0f32); - assert_approx_eq!(1.3f32.ceil(), 2.0f32); - assert_approx_eq!(1.5f32.ceil(), 2.0f32); - assert_approx_eq!(1.7f32.ceil(), 2.0f32); - assert_approx_eq!(0.0f32.ceil(), 0.0f32); - assert_approx_eq!((-0.0f32).ceil(), -0.0f32); - assert_approx_eq!((-1.0f32).ceil(), -1.0f32); - assert_approx_eq!((-1.3f32).ceil(), -1.0f32); - assert_approx_eq!((-1.5f32).ceil(), -1.0f32); - assert_approx_eq!((-1.7f32).ceil(), -1.0f32); - } + /// Returns `true` if `self`'s sign bit is positive, including + /// `+0.0` and `INFINITY`. + /// + /// ``` + /// use std::f32; + /// + /// let nan = f32::NAN; + /// let f = 7.0_f32; + /// let g = -7.0_f32; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// // Requires both tests to determine if is `NaN` + /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_positive(self) -> bool { num::Float::is_positive(self) } - #[test] - fn test_round() { - assert_approx_eq!(1.0f32.round(), 1.0f32); - assert_approx_eq!(1.3f32.round(), 1.0f32); - assert_approx_eq!(1.5f32.round(), 2.0f32); - assert_approx_eq!(1.7f32.round(), 2.0f32); - assert_approx_eq!(0.0f32.round(), 0.0f32); - assert_approx_eq!((-0.0f32).round(), -0.0f32); - assert_approx_eq!((-1.0f32).round(), -1.0f32); - assert_approx_eq!((-1.3f32).round(), -1.0f32); - assert_approx_eq!((-1.5f32).round(), -2.0f32); - assert_approx_eq!((-1.7f32).round(), -2.0f32); - } + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")] + #[inline] + pub fn is_positive(self) -> bool { num::Float::is_positive(self) } - #[test] - fn test_trunc() { - assert_approx_eq!(1.0f32.trunc(), 1.0f32); - assert_approx_eq!(1.3f32.trunc(), 1.0f32); - assert_approx_eq!(1.5f32.trunc(), 1.0f32); - assert_approx_eq!(1.7f32.trunc(), 1.0f32); - assert_approx_eq!(0.0f32.trunc(), 0.0f32); - assert_approx_eq!((-0.0f32).trunc(), -0.0f32); - assert_approx_eq!((-1.0f32).trunc(), -1.0f32); - assert_approx_eq!((-1.3f32).trunc(), -1.0f32); - assert_approx_eq!((-1.5f32).trunc(), -1.0f32); - assert_approx_eq!((-1.7f32).trunc(), -1.0f32); - } + /// Returns `true` if `self`'s sign is negative, including `-0.0` + /// and `NEG_INFINITY`. + /// + /// ``` + /// use std::f32; + /// + /// let nan = f32::NAN; + /// let f = 7.0f32; + /// let g = -7.0f32; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// // Requires both tests to determine if is `NaN`. + /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_negative(self) -> bool { num::Float::is_negative(self) } - #[test] - fn test_fract() { - assert_approx_eq!(1.0f32.fract(), 0.0f32); - assert_approx_eq!(1.3f32.fract(), 0.3f32); - assert_approx_eq!(1.5f32.fract(), 0.5f32); - assert_approx_eq!(1.7f32.fract(), 0.7f32); - assert_approx_eq!(0.0f32.fract(), 0.0f32); - assert_approx_eq!((-0.0f32).fract(), -0.0f32); - assert_approx_eq!((-1.0f32).fract(), -0.0f32); - assert_approx_eq!((-1.3f32).fract(), -0.3f32); - assert_approx_eq!((-1.5f32).fract(), -0.5f32); - assert_approx_eq!((-1.7f32).fract(), -0.7f32); - } + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")] + #[inline] + pub fn is_negative(self) -> bool { num::Float::is_negative(self) } - #[test] - fn test_exp() { - assert_eq!(1.0, 0.0f32.exp()); - assert_approx_eq!(2.718282, 1.0f32.exp()); - assert_approx_eq!(148.413162, 5.0f32.exp()); + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error. This produces a more accurate result with better performance than + /// a separate multiplication operation followed by an add. + /// + /// ``` + /// use std::f32; + /// + /// let m = 10.0_f32; + /// let x = 4.0_f32; + /// let b = 60.0_f32; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) } + + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// use std::f32; + /// + /// let x = 2.0_f32; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn recip(self) -> f32 { num::Float::recip(self) } + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// use std::f32; + /// + /// let x = 2.0_f32; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) } + + /// Raise a number to a floating point power. + /// + /// ``` + /// use std::f32; + /// + /// let x = 2.0_f32; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) } + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// use std::f32; + /// + /// let positive = 4.0_f32; + /// let negative = -4.0_f32; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// assert!(negative.sqrt().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sqrt(self) -> f32 { num::Float::sqrt(self) } + + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let f = 4.0f32; + /// + /// let abs_difference = (f.rsqrt() - 0.5).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")] + #[inline] + pub fn rsqrt(self) -> f32 { num::Float::rsqrt(self) } + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// use std::f32; + /// + /// let one = 1.0f32; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp(self) -> f32 { num::Float::exp(self) } + + /// Returns `2^(self)`. + /// + /// ``` + /// use std::f32; + /// + /// let f = 2.0f32; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp2(self) -> f32 { num::Float::exp2(self) } + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// use std::f32; + /// + /// let one = 1.0f32; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln(self) -> f32 { num::Float::ln(self) } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// use std::f32; + /// + /// let ten = 10.0f32; + /// let two = 2.0f32; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 <= f32::EPSILON); + /// assert!(abs_difference_2 <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log(self, base: f32) -> f32 { num::Float::log(self, base) } + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// use std::f32; + /// + /// let two = 2.0f32; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log2(self) -> f32 { num::Float::log2(self) } + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// use std::f32; + /// + /// let ten = 10.0f32; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log10(self) -> f32 { num::Float::log10(self) } + + /// Convert radians to degrees. + /// + /// ``` + /// # #![feature(std_misc, core)] + /// use std::f32::{self, consts}; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) } + + /// Convert degrees to radians. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32::{self, consts}; + /// + /// let angle = 180.0f32; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[unstable(feature = "std_misc", reason = "desirability is unclear")] + #[inline] + pub fn to_radians(self) -> f32 { num::Float::to_radians(self) } + + /// Constructs a floating point number of `x*2^exp`. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// // 3*2^2 - 12 == 0 + /// let abs_difference = (f32::ldexp(3.0, 2) - 12.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn ldexp(x: f32, exp: isize) -> f32 { + unsafe { cmath::ldexpf(x, exp as c_int) } + } + + /// Breaks the number into a normalized fraction and a base-2 exponent, + /// satisfying: + /// + /// * `self = x * 2^exp` + /// * `0.5 <= abs(x) < 1.0` + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let x = 4.0f32; + /// + /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 + /// let f = x.frexp(); + /// let abs_difference_0 = (f.0 - 0.5).abs(); + /// let abs_difference_1 = (f.1 as f32 - 3.0).abs(); + /// + /// assert!(abs_difference_0 <= f32::EPSILON); + /// assert!(abs_difference_1 <= f32::EPSILON); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn frexp(self) -> (f32, isize) { + unsafe { + let mut exp = 0; + let x = cmath::frexpf(self, &mut exp); + (x, exp as isize) + } + } + + /// Returns the next representable floating-point value in the direction of + /// `other`. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let x = 1.0f32; + /// + /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); + /// + /// assert!(abs_diff <= f32::EPSILON); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn next_after(self, other: f32) -> f32 { + unsafe { cmath::nextafterf(self, other) } + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f32) -> f32 { + unsafe { cmath::fmaxf(self, other) } + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// let x = 1.0f32; + /// let y = 2.0f32; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f32) -> f32 { + unsafe { cmath::fminf(self, other) } + } + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let x = 3.0f32; + /// let y = -3.0f32; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x <= f32::EPSILON); + /// assert!(abs_difference_y <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs_sub(self, other: f32) -> f32 { + unsafe { cmath::fdimf(self, other) } + } + + /// Take the cubic root of a number. + /// + /// ``` + /// # #![feature(std_misc)] + /// use std::f32; + /// + /// let x = 8.0f32; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cbrt(self) -> f32 { + unsafe { cmath::cbrtf(self) } + } + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// use std::f32; + /// + /// let x = 2.0f32; + /// let y = 3.0f32; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn hypot(self, other: f32) -> f32 { + unsafe { cmath::hypotf(self, other) } + } + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use std::f32; + /// + /// let x = f32::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin(self) -> f32 { + unsafe { intrinsics::sinf32(self) } + } + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use std::f32; + /// + /// let x = 2.0*f32::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cos(self) -> f32 { + unsafe { intrinsics::cosf32(self) } + } + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tan(self) -> f32 { + unsafe { cmath::tanf(self) } + } + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::f32; + /// + /// let f = f32::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = f.sin().asin().abs_sub(f32::consts::PI / 2.0); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asin(self) -> f32 { + unsafe { cmath::asinf(self) } + } + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::f32; + /// + /// let f = f32::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = f.cos().acos().abs_sub(f32::consts::PI / 4.0); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acos(self) -> f32 { + unsafe { cmath::acosf(self) } + } + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// use std::f32; + /// + /// let f = 1.0f32; + /// + /// // atan(tan(1)) + /// let abs_difference = f.tan().atan().abs_sub(1.0); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan(self) -> f32 { + unsafe { cmath::atanf(self) } + } + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use std::f32; + /// + /// let pi = f32::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0f32; + /// let y1 = -3.0f32; + /// + /// // 135 deg clockwise + /// let x2 = -3.0f32; + /// let y2 = 3.0f32; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 <= f32::EPSILON); + /// assert!(abs_difference_2 <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan2(self, other: f32) -> f32 { + unsafe { cmath::atan2f(self, other) } + } + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use std::f32; + /// + /// let x = f32::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 <= f32::EPSILON); + /// assert!(abs_difference_0 <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin_cos(self) -> (f32, f32) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// use std::f64; + /// + /// let x = 7.0f64; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = x.ln().exp_m1().abs_sub(6.0); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp_m1(self) -> f32 { + unsafe { cmath::expm1f(self) } + } + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use std::f32; + /// + /// let x = f32::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln_1p(self) -> f32 { + unsafe { cmath::log1pf(self) } + } + + /// Hyperbolic sine function. + /// + /// ``` + /// use std::f32; + /// + /// let e = f32::consts::E; + /// let x = 1.0f32; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sinh(self) -> f32 { + unsafe { cmath::sinhf(self) } + } + + /// Hyperbolic cosine function. + /// + /// ``` + /// use std::f32; + /// + /// let e = f32::consts::E; + /// let x = 1.0f32; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = f.abs_sub(g); + /// + /// // Same result + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cosh(self) -> f32 { + unsafe { cmath::coshf(self) } + } + + /// Hyperbolic tangent function. + /// + /// ``` + /// use std::f32; + /// + /// let e = f32::consts::E; + /// let x = 1.0f32; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tanh(self) -> f32 { + unsafe { cmath::tanhf(self) } + } + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// use std::f32; + /// + /// let x = 1.0f32; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asinh(self) -> f32 { + match self { + NEG_INFINITY => NEG_INFINITY, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// use std::f32; + /// + /// let x = 1.0f32; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acosh(self) -> f32 { + match self { + x if x < 1.0 => Float::nan(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use std::f32; + /// + /// let e = f32::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = f.abs_sub(e); + /// + /// assert!(abs_difference <= f32::EPSILON); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atanh(self) -> f32 { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + +// +// Section: String Conversions +// + +/// Converts a float to a string +/// +/// # Arguments +/// +/// * num - The float value +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")] +pub fn to_string(num: f32) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigAll, ExpNone, false); + r +} + +/// Converts a float to a string in hexadecimal format +/// +/// # Arguments +/// +/// * num - The float value +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[deprecated(since = "1.0.0", reason = "use format! instead")] +pub fn to_str_hex(num: f32) -> String { + let (r, _) = strconv::float_to_str_common( + num, 16, true, SignNeg, DigAll, ExpNone, false); + r +} + +/// Converts a float to a string in a given radix, and a flag indicating +/// whether it's a special value +/// +/// # Arguments +/// +/// * num - The float value +/// * radix - The base to use +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[deprecated(since = "1.0.0", reason = "use format! instead")] +pub fn to_str_radix_special(num: f32, rdx: u32) -> (String, bool) { + strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false) +} + +/// Converts a float to a string with exactly the number of +/// provided significant digits +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of significant digits +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_exact(num: f32, dig: usize) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigExact(dig), ExpNone, false); + r +} + +/// Converts a float to a string with a maximum number of +/// significant digits +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of significant digits +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_digits(num: f32, dig: usize) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigMax(dig), ExpNone, false); + r +} + +/// Converts a float to a string using the exponential notation with exactly the number of +/// provided digits after the decimal point in the significand +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of digits after the decimal point +/// * upper - Use `E` instead of `e` for the exponent sign +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_exp_exact(num: f32, dig: usize, upper: bool) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigExact(dig), ExpDec, upper); + r +} + +/// Converts a float to a string using the exponential notation with the maximum number of +/// digits after the decimal point in the significand +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of digits after the decimal point +/// * upper - Use `E` instead of `e` for the exponent sign +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_exp_digits(num: f32, dig: usize, upper: bool) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigMax(dig), ExpDec, upper); + r +} + +#[cfg(test)] +mod tests { + use f32::*; + use num::*; + use num::FpCategory as Fp; + + #[test] + fn test_num_f32() { + test_num(10f32, 2f32); + } + + #[test] + fn test_min_nan() { + assert_eq!(NAN.min(2.0), 2.0); + assert_eq!(2.0f32.min(NAN), 2.0); + } + + #[test] + fn test_max_nan() { + assert_eq!(NAN.max(2.0), 2.0); + assert_eq!(2.0f32.max(NAN), 2.0); + } + + #[test] + fn test_nan() { + let nan: f32 = Float::nan(); + assert!(nan.is_nan()); + assert!(!nan.is_infinite()); + assert!(!nan.is_finite()); + assert!(!nan.is_normal()); + assert!(!nan.is_sign_positive()); + assert!(!nan.is_sign_negative()); + assert_eq!(Fp::Nan, nan.classify()); + } + + #[test] + fn test_infinity() { + let inf: f32 = Float::infinity(); + assert!(inf.is_infinite()); + assert!(!inf.is_finite()); + assert!(inf.is_sign_positive()); + assert!(!inf.is_sign_negative()); + assert!(!inf.is_nan()); + assert!(!inf.is_normal()); + assert_eq!(Fp::Infinite, inf.classify()); + } + + #[test] + fn test_neg_infinity() { + let neg_inf: f32 = Float::neg_infinity(); + assert!(neg_inf.is_infinite()); + assert!(!neg_inf.is_finite()); + assert!(!neg_inf.is_sign_positive()); + assert!(neg_inf.is_sign_negative()); + assert!(!neg_inf.is_nan()); + assert!(!neg_inf.is_normal()); + assert_eq!(Fp::Infinite, neg_inf.classify()); + } + + #[test] + fn test_zero() { + let zero: f32 = Float::zero(); + assert_eq!(0.0, zero); + assert!(!zero.is_infinite()); + assert!(zero.is_finite()); + assert!(zero.is_sign_positive()); + assert!(!zero.is_sign_negative()); + assert!(!zero.is_nan()); + assert!(!zero.is_normal()); + assert_eq!(Fp::Zero, zero.classify()); + } + + #[test] + fn test_neg_zero() { + let neg_zero: f32 = Float::neg_zero(); + assert_eq!(0.0, neg_zero); + assert!(!neg_zero.is_infinite()); + assert!(neg_zero.is_finite()); + assert!(!neg_zero.is_sign_positive()); + assert!(neg_zero.is_sign_negative()); + assert!(!neg_zero.is_nan()); + assert!(!neg_zero.is_normal()); + assert_eq!(Fp::Zero, neg_zero.classify()); + } + + #[test] + fn test_one() { + let one: f32 = Float::one(); + assert_eq!(1.0, one); + assert!(!one.is_infinite()); + assert!(one.is_finite()); + assert!(one.is_sign_positive()); + assert!(!one.is_sign_negative()); + assert!(!one.is_nan()); + assert!(one.is_normal()); + assert_eq!(Fp::Normal, one.classify()); + } + + #[test] + fn test_is_nan() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert!(nan.is_nan()); + assert!(!0.0f32.is_nan()); + assert!(!5.3f32.is_nan()); + assert!(!(-10.732f32).is_nan()); + assert!(!inf.is_nan()); + assert!(!neg_inf.is_nan()); + } + + #[test] + fn test_is_infinite() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert!(!nan.is_infinite()); + assert!(inf.is_infinite()); + assert!(neg_inf.is_infinite()); + assert!(!0.0f32.is_infinite()); + assert!(!42.8f32.is_infinite()); + assert!(!(-109.2f32).is_infinite()); + } + + #[test] + fn test_is_finite() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert!(!nan.is_finite()); + assert!(!inf.is_finite()); + assert!(!neg_inf.is_finite()); + assert!(0.0f32.is_finite()); + assert!(42.8f32.is_finite()); + assert!((-109.2f32).is_finite()); + } + + #[test] + fn test_is_normal() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let zero: f32 = Float::zero(); + let neg_zero: f32 = Float::neg_zero(); + assert!(!nan.is_normal()); + assert!(!inf.is_normal()); + assert!(!neg_inf.is_normal()); + assert!(!zero.is_normal()); + assert!(!neg_zero.is_normal()); + assert!(1f32.is_normal()); + assert!(1e-37f32.is_normal()); + assert!(!1e-38f32.is_normal()); + } + + #[test] + fn test_classify() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let zero: f32 = Float::zero(); + let neg_zero: f32 = Float::neg_zero(); + assert_eq!(nan.classify(), Fp::Nan); + assert_eq!(inf.classify(), Fp::Infinite); + assert_eq!(neg_inf.classify(), Fp::Infinite); + assert_eq!(zero.classify(), Fp::Zero); + assert_eq!(neg_zero.classify(), Fp::Zero); + assert_eq!(1f32.classify(), Fp::Normal); + assert_eq!(1e-37f32.classify(), Fp::Normal); + assert_eq!(1e-38f32.classify(), Fp::Subnormal); + } + + #[test] + fn test_integer_decode() { + assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1)); + assert_eq!((-8573.5918555f32).integer_decode(), (8779358, -10, -1)); + assert_eq!(2f32.powf(100.0).integer_decode(), (8388608, 77, 1)); + assert_eq!(0f32.integer_decode(), (0, -150, 1)); + assert_eq!((-0f32).integer_decode(), (0, -150, -1)); + assert_eq!(INFINITY.integer_decode(), (8388608, 105, 1)); + assert_eq!(NEG_INFINITY.integer_decode(), (8388608, 105, -1)); + assert_eq!(NAN.integer_decode(), (12582912, 105, 1)); + } + + #[test] + fn test_floor() { + assert_approx_eq!(1.0f32.floor(), 1.0f32); + assert_approx_eq!(1.3f32.floor(), 1.0f32); + assert_approx_eq!(1.5f32.floor(), 1.0f32); + assert_approx_eq!(1.7f32.floor(), 1.0f32); + assert_approx_eq!(0.0f32.floor(), 0.0f32); + assert_approx_eq!((-0.0f32).floor(), -0.0f32); + assert_approx_eq!((-1.0f32).floor(), -1.0f32); + assert_approx_eq!((-1.3f32).floor(), -2.0f32); + assert_approx_eq!((-1.5f32).floor(), -2.0f32); + assert_approx_eq!((-1.7f32).floor(), -2.0f32); + } + + #[test] + fn test_ceil() { + assert_approx_eq!(1.0f32.ceil(), 1.0f32); + assert_approx_eq!(1.3f32.ceil(), 2.0f32); + assert_approx_eq!(1.5f32.ceil(), 2.0f32); + assert_approx_eq!(1.7f32.ceil(), 2.0f32); + assert_approx_eq!(0.0f32.ceil(), 0.0f32); + assert_approx_eq!((-0.0f32).ceil(), -0.0f32); + assert_approx_eq!((-1.0f32).ceil(), -1.0f32); + assert_approx_eq!((-1.3f32).ceil(), -1.0f32); + assert_approx_eq!((-1.5f32).ceil(), -1.0f32); + assert_approx_eq!((-1.7f32).ceil(), -1.0f32); + } + + #[test] + fn test_round() { + assert_approx_eq!(1.0f32.round(), 1.0f32); + assert_approx_eq!(1.3f32.round(), 1.0f32); + assert_approx_eq!(1.5f32.round(), 2.0f32); + assert_approx_eq!(1.7f32.round(), 2.0f32); + assert_approx_eq!(0.0f32.round(), 0.0f32); + assert_approx_eq!((-0.0f32).round(), -0.0f32); + assert_approx_eq!((-1.0f32).round(), -1.0f32); + assert_approx_eq!((-1.3f32).round(), -1.0f32); + assert_approx_eq!((-1.5f32).round(), -2.0f32); + assert_approx_eq!((-1.7f32).round(), -2.0f32); + } + + #[test] + fn test_trunc() { + assert_approx_eq!(1.0f32.trunc(), 1.0f32); + assert_approx_eq!(1.3f32.trunc(), 1.0f32); + assert_approx_eq!(1.5f32.trunc(), 1.0f32); + assert_approx_eq!(1.7f32.trunc(), 1.0f32); + assert_approx_eq!(0.0f32.trunc(), 0.0f32); + assert_approx_eq!((-0.0f32).trunc(), -0.0f32); + assert_approx_eq!((-1.0f32).trunc(), -1.0f32); + assert_approx_eq!((-1.3f32).trunc(), -1.0f32); + assert_approx_eq!((-1.5f32).trunc(), -1.0f32); + assert_approx_eq!((-1.7f32).trunc(), -1.0f32); + } + + #[test] + fn test_fract() { + assert_approx_eq!(1.0f32.fract(), 0.0f32); + assert_approx_eq!(1.3f32.fract(), 0.3f32); + assert_approx_eq!(1.5f32.fract(), 0.5f32); + assert_approx_eq!(1.7f32.fract(), 0.7f32); + assert_approx_eq!(0.0f32.fract(), 0.0f32); + assert_approx_eq!((-0.0f32).fract(), -0.0f32); + assert_approx_eq!((-1.0f32).fract(), -0.0f32); + assert_approx_eq!((-1.3f32).fract(), -0.3f32); + assert_approx_eq!((-1.5f32).fract(), -0.5f32); + assert_approx_eq!((-1.7f32).fract(), -0.7f32); + } + + #[test] + fn test_abs() { + assert_eq!(INFINITY.abs(), INFINITY); + assert_eq!(1f32.abs(), 1f32); + assert_eq!(0f32.abs(), 0f32); + assert_eq!((-0f32).abs(), 0f32); + assert_eq!((-1f32).abs(), 1f32); + assert_eq!(NEG_INFINITY.abs(), INFINITY); + assert_eq!((1f32/NEG_INFINITY).abs(), 0f32); + assert!(NAN.abs().is_nan()); + } + + #[test] + fn test_signum() { + assert_eq!(INFINITY.signum(), 1f32); + assert_eq!(1f32.signum(), 1f32); + assert_eq!(0f32.signum(), 1f32); + assert_eq!((-0f32).signum(), -1f32); + assert_eq!((-1f32).signum(), -1f32); + assert_eq!(NEG_INFINITY.signum(), -1f32); + assert_eq!((1f32/NEG_INFINITY).signum(), -1f32); + assert!(NAN.signum().is_nan()); + } + + #[test] + fn test_is_sign_positive() { + assert!(INFINITY.is_sign_positive()); + assert!(1f32.is_sign_positive()); + assert!(0f32.is_sign_positive()); + assert!(!(-0f32).is_sign_positive()); + assert!(!(-1f32).is_sign_positive()); + assert!(!NEG_INFINITY.is_sign_positive()); + assert!(!(1f32/NEG_INFINITY).is_sign_positive()); + assert!(!NAN.is_sign_positive()); + } + + #[test] + fn test_is_sign_negative() { + assert!(!INFINITY.is_sign_negative()); + assert!(!1f32.is_sign_negative()); + assert!(!0f32.is_sign_negative()); + assert!((-0f32).is_sign_negative()); + assert!((-1f32).is_sign_negative()); + assert!(NEG_INFINITY.is_sign_negative()); + assert!((1f32/NEG_INFINITY).is_sign_negative()); + assert!(!NAN.is_sign_negative()); + } + + #[test] + fn test_mul_add() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_approx_eq!(12.3f32.mul_add(4.5, 6.7), 62.05); + assert_approx_eq!((-12.3f32).mul_add(-4.5, -6.7), 48.65); + assert_approx_eq!(0.0f32.mul_add(8.9, 1.2), 1.2); + assert_approx_eq!(3.4f32.mul_add(-0.0, 5.6), 5.6); + assert!(nan.mul_add(7.8, 9.0).is_nan()); + assert_eq!(inf.mul_add(7.8, 9.0), inf); + assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf); + assert_eq!(8.9f32.mul_add(inf, 3.2), inf); + assert_eq!((-3.2f32).mul_add(2.4, neg_inf), neg_inf); + } + + #[test] + fn test_recip() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(1.0f32.recip(), 1.0); + assert_eq!(2.0f32.recip(), 0.5); + assert_eq!((-0.4f32).recip(), -2.5); + assert_eq!(0.0f32.recip(), inf); + assert!(nan.recip().is_nan()); + assert_eq!(inf.recip(), 0.0); + assert_eq!(neg_inf.recip(), 0.0); + } + + #[test] + fn test_powi() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(1.0f32.powi(1), 1.0); + assert_approx_eq!((-3.1f32).powi(2), 9.61); + assert_approx_eq!(5.9f32.powi(-2), 0.028727); + assert_eq!(8.3f32.powi(0), 1.0); + assert!(nan.powi(2).is_nan()); + assert_eq!(inf.powi(3), inf); + assert_eq!(neg_inf.powi(2), inf); + } + + #[test] + fn test_powf() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(1.0f32.powf(1.0), 1.0); + assert_approx_eq!(3.4f32.powf(4.5), 246.408218); + assert_approx_eq!(2.7f32.powf(-3.2), 0.041652); + assert_approx_eq!((-3.1f32).powf(2.0), 9.61); + assert_approx_eq!(5.9f32.powf(-2.0), 0.028727); + assert_eq!(8.3f32.powf(0.0), 1.0); + assert!(nan.powf(2.0).is_nan()); + assert_eq!(inf.powf(2.0), inf); + assert_eq!(neg_inf.powf(3.0), neg_inf); + } + + #[test] + fn test_sqrt_domain() { + assert!(NAN.sqrt().is_nan()); + assert!(NEG_INFINITY.sqrt().is_nan()); + assert!((-1.0f32).sqrt().is_nan()); + assert_eq!((-0.0f32).sqrt(), -0.0); + assert_eq!(0.0f32.sqrt(), 0.0); + assert_eq!(1.0f32.sqrt(), 1.0); + assert_eq!(INFINITY.sqrt(), INFINITY); + } + + #[test] + fn test_rsqrt() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert!(nan.rsqrt().is_nan()); + assert_eq!(inf.rsqrt(), 0.0); + assert!(neg_inf.rsqrt().is_nan()); + assert!((-1.0f32).rsqrt().is_nan()); + assert_eq!((-0.0f32).rsqrt(), neg_inf); + assert_eq!(0.0f32.rsqrt(), inf); + assert_eq!(1.0f32.rsqrt(), 1.0); + assert_eq!(4.0f32.rsqrt(), 0.5); + } + + #[test] + fn test_exp() { + assert_eq!(1.0, 0.0f32.exp()); + assert_approx_eq!(2.718282, 1.0f32.exp()); + assert_approx_eq!(148.413162, 5.0f32.exp()); let inf: f32 = Float::infinity(); let neg_inf: f32 = Float::neg_infinity(); @@ -582,6 +1890,172 @@ mod tests { assert!(nan.exp2().is_nan()); } + #[test] + fn test_ln() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_approx_eq!(1.0f32.exp().ln(), 1.0); + assert!(nan.ln().is_nan()); + assert_eq!(inf.ln(), inf); + assert!(neg_inf.ln().is_nan()); + assert!((-2.3f32).ln().is_nan()); + assert_eq!((-0.0f32).ln(), neg_inf); + assert_eq!(0.0f32.ln(), neg_inf); + assert_approx_eq!(4.0f32.ln(), 1.386294); + } + + #[test] + fn test_log() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(10.0f32.log(10.0), 1.0); + assert_approx_eq!(2.3f32.log(3.5), 0.664858); + assert_eq!(1.0f32.exp().log(1.0.exp()), 1.0); + assert!(1.0f32.log(1.0).is_nan()); + assert!(1.0f32.log(-13.9).is_nan()); + assert!(nan.log(2.3).is_nan()); + assert_eq!(inf.log(10.0), inf); + assert!(neg_inf.log(8.8).is_nan()); + assert!((-2.3f32).log(0.1).is_nan()); + assert_eq!((-0.0f32).log(2.0), neg_inf); + assert_eq!(0.0f32.log(7.0), neg_inf); + } + + #[test] + fn test_log2() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_approx_eq!(10.0f32.log2(), 3.321928); + assert_approx_eq!(2.3f32.log2(), 1.201634); + assert_approx_eq!(1.0f32.exp().log2(), 1.442695); + assert!(nan.log2().is_nan()); + assert_eq!(inf.log2(), inf); + assert!(neg_inf.log2().is_nan()); + assert!((-2.3f32).log2().is_nan()); + assert_eq!((-0.0f32).log2(), neg_inf); + assert_eq!(0.0f32.log2(), neg_inf); + } + + #[test] + fn test_log10() { + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(10.0f32.log10(), 1.0); + assert_approx_eq!(2.3f32.log10(), 0.361728); + assert_approx_eq!(1.0f32.exp().log10(), 0.434294); + assert_eq!(1.0f32.log10(), 0.0); + assert!(nan.log10().is_nan()); + assert_eq!(inf.log10(), inf); + assert!(neg_inf.log10().is_nan()); + assert!((-2.3f32).log10().is_nan()); + assert_eq!((-0.0f32).log10(), neg_inf); + assert_eq!(0.0f32.log10(), neg_inf); + } + + #[test] + fn test_to_degrees() { + let pi: f32 = consts::PI; + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(0.0f32.to_degrees(), 0.0); + assert_approx_eq!((-5.8f32).to_degrees(), -332.315521); + assert_eq!(pi.to_degrees(), 180.0); + assert!(nan.to_degrees().is_nan()); + assert_eq!(inf.to_degrees(), inf); + assert_eq!(neg_inf.to_degrees(), neg_inf); + } + + #[test] + fn test_to_radians() { + let pi: f32 = consts::PI; + let nan: f32 = Float::nan(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + assert_eq!(0.0f32.to_radians(), 0.0); + assert_approx_eq!(154.6f32.to_radians(), 2.698279); + assert_approx_eq!((-332.31f32).to_radians(), -5.799903); + assert_eq!(180.0f32.to_radians(), pi); + assert!(nan.to_radians().is_nan()); + assert_eq!(inf.to_radians(), inf); + assert_eq!(neg_inf.to_radians(), neg_inf); + } + + #[test] + fn test_ldexp() { + // We have to use from_str until base-2 exponents + // are supported in floating-point literals + let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); + let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); + let f3: f32 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap(); + assert_eq!(1f32.ldexp(-123), f1); + assert_eq!(1f32.ldexp(-111), f2); + assert_eq!(Float::ldexp(1.75f32, -12), f3); + + assert_eq!(Float::ldexp(0f32, -123), 0f32); + assert_eq!(Float::ldexp(-0f32, -123), -0f32); + + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = Float::nan(); + assert_eq!(Float::ldexp(inf, -123), inf); + assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); + assert!(Float::ldexp(nan, -123).is_nan()); + } + + #[test] + fn test_frexp() { + // We have to use from_str until base-2 exponents + // are supported in floating-point literals + let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); + let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); + let f3: f32 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap(); + let (x1, exp1) = f1.frexp(); + let (x2, exp2) = f2.frexp(); + let (x3, exp3) = f3.frexp(); + assert_eq!((x1, exp1), (0.5f32, -122)); + assert_eq!((x2, exp2), (0.5f32, -110)); + assert_eq!((x3, exp3), (0.875f32, -122)); + assert_eq!(Float::ldexp(x1, exp1), f1); + assert_eq!(Float::ldexp(x2, exp2), f2); + assert_eq!(Float::ldexp(x3, exp3), f3); + + assert_eq!(0f32.frexp(), (0f32, 0)); + assert_eq!((-0f32).frexp(), (-0f32, 0)); + } + + #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 + fn test_frexp_nowin() { + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = Float::nan(); + assert_eq!(match inf.frexp() { (x, _) => x }, inf); + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); + assert!(match nan.frexp() { (x, _) => x.is_nan() }) + } + + #[test] + fn test_abs_sub() { + assert_eq!((-1f32).abs_sub(1f32), 0f32); + assert_eq!(1f32.abs_sub(1f32), 0f32); + assert_eq!(1f32.abs_sub(0f32), 1f32); + assert_eq!(1f32.abs_sub(-1f32), 2f32); + assert_eq!(NEG_INFINITY.abs_sub(0f32), 0f32); + assert_eq!(INFINITY.abs_sub(1f32), INFINITY); + assert_eq!(0f32.abs_sub(NEG_INFINITY), INFINITY); + assert_eq!(0f32.abs_sub(INFINITY), 0f32); + } + + #[test] + fn test_abs_sub_nowin() { + assert!(NAN.abs_sub(-1f32).is_nan()); + assert!(1f32.abs_sub(NAN).is_nan()); + } + #[test] fn test_asinh() { assert_eq!(0.0f32.asinh(), 0.0f32); @@ -674,174 +2148,4 @@ mod tests { assert_approx_eq!(ln_2, 2f32.ln()); assert_approx_eq!(ln_10, 10f32.ln()); } - - #[test] - pub fn test_abs() { - assert_eq!(INFINITY.abs(), INFINITY); - assert_eq!(1f32.abs(), 1f32); - assert_eq!(0f32.abs(), 0f32); - assert_eq!((-0f32).abs(), 0f32); - assert_eq!((-1f32).abs(), 1f32); - assert_eq!(NEG_INFINITY.abs(), INFINITY); - assert_eq!((1f32/NEG_INFINITY).abs(), 0f32); - assert!(NAN.abs().is_nan()); - } - - #[test] - fn test_abs_sub() { - assert_eq!((-1f32).abs_sub(1f32), 0f32); - assert_eq!(1f32.abs_sub(1f32), 0f32); - assert_eq!(1f32.abs_sub(0f32), 1f32); - assert_eq!(1f32.abs_sub(-1f32), 2f32); - assert_eq!(NEG_INFINITY.abs_sub(0f32), 0f32); - assert_eq!(INFINITY.abs_sub(1f32), INFINITY); - assert_eq!(0f32.abs_sub(NEG_INFINITY), INFINITY); - assert_eq!(0f32.abs_sub(INFINITY), 0f32); - } - - #[test] - fn test_abs_sub_nowin() { - assert!(NAN.abs_sub(-1f32).is_nan()); - assert!(1f32.abs_sub(NAN).is_nan()); - } - - #[test] - fn test_signum() { - assert_eq!(INFINITY.signum(), 1f32); - assert_eq!(1f32.signum(), 1f32); - assert_eq!(0f32.signum(), 1f32); - assert_eq!((-0f32).signum(), -1f32); - assert_eq!((-1f32).signum(), -1f32); - assert_eq!(NEG_INFINITY.signum(), -1f32); - assert_eq!((1f32/NEG_INFINITY).signum(), -1f32); - assert!(NAN.signum().is_nan()); - } - - #[test] - fn test_is_positive() { - assert!(INFINITY.is_positive()); - assert!(1f32.is_positive()); - assert!(0f32.is_positive()); - assert!(!(-0f32).is_positive()); - assert!(!(-1f32).is_positive()); - assert!(!NEG_INFINITY.is_positive()); - assert!(!(1f32/NEG_INFINITY).is_positive()); - assert!(!NAN.is_positive()); - } - - #[test] - fn test_is_negative() { - assert!(!INFINITY.is_negative()); - assert!(!1f32.is_negative()); - assert!(!0f32.is_negative()); - assert!((-0f32).is_negative()); - assert!((-1f32).is_negative()); - assert!(NEG_INFINITY.is_negative()); - assert!((1f32/NEG_INFINITY).is_negative()); - assert!(!NAN.is_negative()); - } - - #[test] - fn test_is_normal() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let zero: f32 = Float::zero(); - let neg_zero: f32 = Float::neg_zero(); - assert!(!nan.is_normal()); - assert!(!inf.is_normal()); - assert!(!neg_inf.is_normal()); - assert!(!zero.is_normal()); - assert!(!neg_zero.is_normal()); - assert!(1f32.is_normal()); - assert!(1e-37f32.is_normal()); - assert!(!1e-38f32.is_normal()); - } - - #[test] - fn test_classify() { - let nan: f32 = Float::nan(); - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let zero: f32 = Float::zero(); - let neg_zero: f32 = Float::neg_zero(); - assert_eq!(nan.classify(), Fp::Nan); - assert_eq!(inf.classify(), Fp::Infinite); - assert_eq!(neg_inf.classify(), Fp::Infinite); - assert_eq!(zero.classify(), Fp::Zero); - assert_eq!(neg_zero.classify(), Fp::Zero); - assert_eq!(1f32.classify(), Fp::Normal); - assert_eq!(1e-37f32.classify(), Fp::Normal); - assert_eq!(1e-38f32.classify(), Fp::Subnormal); - } - - #[test] - fn test_ldexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - assert_eq!(Float::ldexp(1f32, -123), f1); - assert_eq!(Float::ldexp(1f32, -111), f2); - - assert_eq!(Float::ldexp(0f32, -123), 0f32); - assert_eq!(Float::ldexp(-0f32, -123), -0f32); - - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); - assert_eq!(Float::ldexp(inf, -123), inf); - assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); - assert!(Float::ldexp(nan, -123).is_nan()); - } - - #[test] - fn test_frexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - let (x1, exp1) = f1.frexp(); - let (x2, exp2) = f2.frexp(); - assert_eq!((x1, exp1), (0.5f32, -122)); - assert_eq!((x2, exp2), (0.5f32, -110)); - assert_eq!(Float::ldexp(x1, exp1), f1); - assert_eq!(Float::ldexp(x2, exp2), f2); - - assert_eq!(0f32.frexp(), (0f32, 0)); - assert_eq!((-0f32).frexp(), (-0f32, 0)); - } - - #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 - fn test_frexp_nowin() { - let inf: f32 = Float::infinity(); - let neg_inf: f32 = Float::neg_infinity(); - let nan: f32 = Float::nan(); - assert_eq!(match inf.frexp() { (x, _) => x }, inf); - assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); - assert!(match nan.frexp() { (x, _) => x.is_nan() }) - } - - #[test] - fn test_integer_decode() { - assert_eq!(3.14159265359f32.integer_decode(), (13176795u64, -22i16, 1i8)); - assert_eq!((-8573.5918555f32).integer_decode(), (8779358u64, -10i16, -1i8)); - assert_eq!(2f32.powf(100.0).integer_decode(), (8388608u64, 77i16, 1i8)); - assert_eq!(0f32.integer_decode(), (0u64, -150i16, 1i8)); - assert_eq!((-0f32).integer_decode(), (0u64, -150i16, -1i8)); - assert_eq!(INFINITY.integer_decode(), (8388608u64, 105i16, 1i8)); - assert_eq!(NEG_INFINITY.integer_decode(), (8388608u64, 105i16, -1i8)); - assert_eq!(NAN.integer_decode(), (12582912u64, 105i16, 1i8)); - } - - #[test] - fn test_sqrt_domain() { - assert!(NAN.sqrt().is_nan()); - assert!(NEG_INFINITY.sqrt().is_nan()); - assert!((-1.0f32).sqrt().is_nan()); - assert_eq!((-0.0f32).sqrt(), -0.0); - assert_eq!(0.0f32.sqrt(), 0.0); - assert_eq!(1.0f32.sqrt(), 1.0); - assert_eq!(INFINITY.sqrt(), INFINITY); - } } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 0ce56371c7..794853f6f7 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -83,6 +83,7 @@ mod cmath { } #[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated)] impl Float for f64 { // inlined methods from `num::Float` #[inline] @@ -101,27 +102,27 @@ impl Float for f64 { #[allow(deprecated)] #[inline] - fn mantissa_digits(unused_self: Option) -> uint { + fn mantissa_digits(unused_self: Option) -> usize { num::Float::mantissa_digits(unused_self) } #[allow(deprecated)] #[inline] - fn digits(unused_self: Option) -> uint { num::Float::digits(unused_self) } + fn digits(unused_self: Option) -> usize { num::Float::digits(unused_self) } #[allow(deprecated)] #[inline] fn epsilon() -> f64 { num::Float::epsilon() } #[allow(deprecated)] #[inline] - fn min_exp(unused_self: Option) -> int { num::Float::min_exp(unused_self) } + fn min_exp(unused_self: Option) -> isize { num::Float::min_exp(unused_self) } #[allow(deprecated)] #[inline] - fn max_exp(unused_self: Option) -> int { num::Float::max_exp(unused_self) } + fn max_exp(unused_self: Option) -> isize { num::Float::max_exp(unused_self) } #[allow(deprecated)] #[inline] - fn min_10_exp(unused_self: Option) -> int { num::Float::min_10_exp(unused_self) } + fn min_10_exp(unused_self: Option) -> isize { num::Float::min_10_exp(unused_self) } #[allow(deprecated)] #[inline] - fn max_10_exp(unused_self: Option) -> int { num::Float::max_10_exp(unused_self) } + fn max_10_exp(unused_self: Option) -> isize { num::Float::max_10_exp(unused_self) } #[allow(deprecated)] #[inline] fn min_value() -> f64 { num::Float::min_value() } @@ -200,8 +201,8 @@ impl Float for f64 { fn to_radians(self) -> f64 { num::Float::to_radians(self) } #[inline] - fn ldexp(x: f64, exp: int) -> f64 { - unsafe { cmath::ldexp(x, exp as c_int) } + fn ldexp(self, exp: isize) -> f64 { + unsafe { cmath::ldexp(self, exp as c_int) } } /// Breaks the number into a normalized fraction and a base-2 exponent, @@ -210,11 +211,11 @@ impl Float for f64 { /// - `self = x * pow(2, exp)` /// - `0.5 <= abs(x) < 1.0` #[inline] - fn frexp(self) -> (f64, int) { + fn frexp(self) -> (f64, isize) { unsafe { let mut exp = 0; let x = cmath::frexp(self, &mut exp); - (x, exp as int) + (x, exp as isize) } } @@ -366,211 +367,1468 @@ impl Float for f64 { } } -// -// Section: String Conversions -// - -/// Converts a float to a string -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_string(num: f64) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigAll, ExpNone, false); - r -} +#[cfg(not(test))] +#[lang = "f64"] +#[stable(feature = "rust1", since = "1.0.0")] +impl f64 { + /// Returns `true` if this value is `NaN` and false otherwise. + /// + /// ``` + /// use std::f64; + /// + /// let nan = f64::NAN; + /// let f = 7.0_f64; + /// + /// assert!(nan.is_nan()); + /// assert!(!f.is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_nan(self) -> bool { num::Float::is_nan(self) } -/// Converts a float to a string in hexadecimal format -/// -/// # Arguments -/// -/// * num - The float value -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_hex(num: f64) -> String { - let (r, _) = strconv::float_to_str_common( - num, 16, true, SignNeg, DigAll, ExpNone, false); - r -} + /// Returns `true` if this value is positive infinity or negative infinity and + /// false otherwise. + /// + /// ``` + /// use std::f64; + /// + /// let f = 7.0f64; + /// let inf = f64::INFINITY; + /// let neg_inf = f64::NEG_INFINITY; + /// let nan = f64::NAN; + /// + /// assert!(!f.is_infinite()); + /// assert!(!nan.is_infinite()); + /// + /// assert!(inf.is_infinite()); + /// assert!(neg_inf.is_infinite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) } -/// Converts a float to a string in a given radix, and a flag indicating -/// whether it's a special value -/// -/// # Arguments -/// -/// * num - The float value -/// * radix - The base to use -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_radix_special(num: f64, rdx: u32) -> (String, bool) { - strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false) -} + /// Returns `true` if this number is neither infinite nor `NaN`. + /// + /// ``` + /// use std::f64; + /// + /// let f = 7.0f64; + /// let inf: f64 = f64::INFINITY; + /// let neg_inf: f64 = f64::NEG_INFINITY; + /// let nan: f64 = f64::NAN; + /// + /// assert!(f.is_finite()); + /// + /// assert!(!nan.is_finite()); + /// assert!(!inf.is_finite()); + /// assert!(!neg_inf.is_finite()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_finite(self) -> bool { num::Float::is_finite(self) } -/// Converts a float to a string with exactly the number of -/// provided significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exact(num: f64, dig: uint) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpNone, false); - r -} + /// Returns `true` if the number is neither zero, infinite, + /// [subnormal][subnormal], or `NaN`. + /// + /// ``` + /// use std::f32; + /// + /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f64 + /// let max = f32::MAX; + /// let lower_than_min = 1.0e-40_f32; + /// let zero = 0.0f32; + /// + /// assert!(min.is_normal()); + /// assert!(max.is_normal()); + /// + /// assert!(!zero.is_normal()); + /// assert!(!f32::NAN.is_normal()); + /// assert!(!f32::INFINITY.is_normal()); + /// // Values between `0` and `min` are Subnormal. + /// assert!(!lower_than_min.is_normal()); + /// ``` + /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_normal(self) -> bool { num::Float::is_normal(self) } + + /// Returns the floating point category of the number. If only one property + /// is going to be tested, it is generally faster to use the specific + /// predicate instead. + /// + /// ``` + /// use std::num::FpCategory; + /// use std::f64; + /// + /// let num = 12.4_f64; + /// let inf = f64::INFINITY; + /// + /// assert_eq!(num.classify(), FpCategory::Normal); + /// assert_eq!(inf.classify(), FpCategory::Infinite); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn classify(self) -> FpCategory { num::Float::classify(self) } -/// Converts a float to a string with a maximum number of -/// significant digits -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of significant digits -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_digits(num: f64, dig: uint) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpNone, false); - r -} + /// Returns the mantissa, base 2 exponent, and sign as integers, respectively. + /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`. + /// The floating point encoding is documented in the [Reference][floating-point]. + /// + /// ``` + /// # #![feature(std_misc)] + /// let num = 2.0f64; + /// + /// // (8388608, -22, 1) + /// let (mantissa, exponent, sign) = num.integer_decode(); + /// let sign_f = sign as f64; + /// let mantissa_f = mantissa as f64; + /// let exponent_f = num.powf(exponent as f64); + /// + /// // 1 * 8388608 * 2^(-22) == 2 + /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + /// [floating-point]: ../../../../../reference.html#machine-types + #[unstable(feature = "std_misc", reason = "signature is undecided")] + #[inline] + pub fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) } -/// Converts a float to a string using the exponential notation with exactly the number of -/// provided digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigExact(dig), ExpDec, upper); - r -} + /// Returns the largest integer less than or equal to a number. + /// + /// ``` + /// let f = 3.99_f64; + /// let g = 3.0_f64; + /// + /// assert_eq!(f.floor(), 3.0); + /// assert_eq!(g.floor(), 3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn floor(self) -> f64 { num::Float::floor(self) } -/// Converts a float to a string using the exponential notation with the maximum number of -/// digits after the decimal point in the significand -/// -/// # Arguments -/// -/// * num - The float value -/// * digits - The number of digits after the decimal point -/// * upper - Use `E` instead of `e` for the exponent sign -#[inline] -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] -pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String { - let (r, _) = strconv::float_to_str_common( - num, 10, true, SignNeg, DigMax(dig), ExpDec, upper); - r -} + /// Returns the smallest integer greater than or equal to a number. + /// + /// ``` + /// let f = 3.01_f64; + /// let g = 4.0_f64; + /// + /// assert_eq!(f.ceil(), 4.0); + /// assert_eq!(g.ceil(), 4.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ceil(self) -> f64 { num::Float::ceil(self) } -#[cfg(test)] -mod tests { - use f64::*; - use num::*; - use num::FpCategory as Fp; + /// Returns the nearest integer to a number. Round half-way cases away from + /// `0.0`. + /// + /// ``` + /// let f = 3.3_f64; + /// let g = -3.3_f64; + /// + /// assert_eq!(f.round(), 3.0); + /// assert_eq!(g.round(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn round(self) -> f64 { num::Float::round(self) } - #[test] - fn test_min_nan() { - assert_eq!(NAN.min(2.0), 2.0); - assert_eq!(2.0f64.min(NAN), 2.0); - } + /// Return the integer part of a number. + /// + /// ``` + /// let f = 3.3_f64; + /// let g = -3.7_f64; + /// + /// assert_eq!(f.trunc(), 3.0); + /// assert_eq!(g.trunc(), -3.0); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn trunc(self) -> f64 { num::Float::trunc(self) } - #[test] - fn test_max_nan() { - assert_eq!(NAN.max(2.0), 2.0); - assert_eq!(2.0f64.max(NAN), 2.0); - } + /// Returns the fractional part of a number. + /// + /// ``` + /// let x = 3.5_f64; + /// let y = -3.5_f64; + /// let abs_difference_x = (x.fract() - 0.5).abs(); + /// let abs_difference_y = (y.fract() - (-0.5)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn fract(self) -> f64 { num::Float::fract(self) } - #[test] - fn test_num_f64() { - test_num(10f64, 2f64); - } + /// Computes the absolute value of `self`. Returns `NAN` if the + /// number is `NAN`. + /// + /// ``` + /// use std::f64; + /// + /// let x = 3.5_f64; + /// let y = -3.5_f64; + /// + /// let abs_difference_x = (x.abs() - x).abs(); + /// let abs_difference_y = (y.abs() - (-y)).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// + /// assert!(f64::NAN.abs().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs(self) -> f64 { num::Float::abs(self) } - #[test] - fn test_floor() { - assert_approx_eq!(1.0f64.floor(), 1.0f64); - assert_approx_eq!(1.3f64.floor(), 1.0f64); - assert_approx_eq!(1.5f64.floor(), 1.0f64); - assert_approx_eq!(1.7f64.floor(), 1.0f64); - assert_approx_eq!(0.0f64.floor(), 0.0f64); - assert_approx_eq!((-0.0f64).floor(), -0.0f64); - assert_approx_eq!((-1.0f64).floor(), -1.0f64); - assert_approx_eq!((-1.3f64).floor(), -2.0f64); - assert_approx_eq!((-1.5f64).floor(), -2.0f64); - assert_approx_eq!((-1.7f64).floor(), -2.0f64); - } + /// Returns a number that represents the sign of `self`. + /// + /// - `1.0` if the number is positive, `+0.0` or `INFINITY` + /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` + /// - `NAN` if the number is `NAN` + /// + /// ``` + /// use std::f64; + /// + /// let f = 3.5_f64; + /// + /// assert_eq!(f.signum(), 1.0); + /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0); + /// + /// assert!(f64::NAN.signum().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn signum(self) -> f64 { num::Float::signum(self) } - #[test] - fn test_ceil() { - assert_approx_eq!(1.0f64.ceil(), 1.0f64); - assert_approx_eq!(1.3f64.ceil(), 2.0f64); - assert_approx_eq!(1.5f64.ceil(), 2.0f64); - assert_approx_eq!(1.7f64.ceil(), 2.0f64); - assert_approx_eq!(0.0f64.ceil(), 0.0f64); - assert_approx_eq!((-0.0f64).ceil(), -0.0f64); - assert_approx_eq!((-1.0f64).ceil(), -1.0f64); - assert_approx_eq!((-1.3f64).ceil(), -1.0f64); - assert_approx_eq!((-1.5f64).ceil(), -1.0f64); - assert_approx_eq!((-1.7f64).ceil(), -1.0f64); - } + /// Returns `true` if `self`'s sign bit is positive, including + /// `+0.0` and `INFINITY`. + /// + /// ``` + /// use std::f64; + /// + /// let nan: f64 = f64::NAN; + /// + /// let f = 7.0_f64; + /// let g = -7.0_f64; + /// + /// assert!(f.is_sign_positive()); + /// assert!(!g.is_sign_positive()); + /// // Requires both tests to determine if is `NaN` + /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_positive(self) -> bool { num::Float::is_positive(self) } - #[test] - fn test_round() { - assert_approx_eq!(1.0f64.round(), 1.0f64); - assert_approx_eq!(1.3f64.round(), 1.0f64); - assert_approx_eq!(1.5f64.round(), 2.0f64); - assert_approx_eq!(1.7f64.round(), 2.0f64); - assert_approx_eq!(0.0f64.round(), 0.0f64); - assert_approx_eq!((-0.0f64).round(), -0.0f64); - assert_approx_eq!((-1.0f64).round(), -1.0f64); - assert_approx_eq!((-1.3f64).round(), -1.0f64); - assert_approx_eq!((-1.5f64).round(), -2.0f64); - assert_approx_eq!((-1.7f64).round(), -2.0f64); - } + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")] + #[inline] + pub fn is_positive(self) -> bool { num::Float::is_positive(self) } - #[test] - fn test_trunc() { - assert_approx_eq!(1.0f64.trunc(), 1.0f64); - assert_approx_eq!(1.3f64.trunc(), 1.0f64); - assert_approx_eq!(1.5f64.trunc(), 1.0f64); - assert_approx_eq!(1.7f64.trunc(), 1.0f64); - assert_approx_eq!(0.0f64.trunc(), 0.0f64); - assert_approx_eq!((-0.0f64).trunc(), -0.0f64); - assert_approx_eq!((-1.0f64).trunc(), -1.0f64); - assert_approx_eq!((-1.3f64).trunc(), -1.0f64); - assert_approx_eq!((-1.5f64).trunc(), -1.0f64); - assert_approx_eq!((-1.7f64).trunc(), -1.0f64); - } + /// Returns `true` if `self`'s sign is negative, including `-0.0` + /// and `NEG_INFINITY`. + /// + /// ``` + /// use std::f64; + /// + /// let nan = f64::NAN; + /// + /// let f = 7.0_f64; + /// let g = -7.0_f64; + /// + /// assert!(!f.is_sign_negative()); + /// assert!(g.is_sign_negative()); + /// // Requires both tests to determine if is `NaN`. + /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_sign_negative(self) -> bool { num::Float::is_negative(self) } - #[test] - fn test_fract() { - assert_approx_eq!(1.0f64.fract(), 0.0f64); - assert_approx_eq!(1.3f64.fract(), 0.3f64); - assert_approx_eq!(1.5f64.fract(), 0.5f64); - assert_approx_eq!(1.7f64.fract(), 0.7f64); - assert_approx_eq!(0.0f64.fract(), 0.0f64); - assert_approx_eq!((-0.0f64).fract(), -0.0f64); - assert_approx_eq!((-1.0f64).fract(), -0.0f64); - assert_approx_eq!((-1.3f64).fract(), -0.3f64); - assert_approx_eq!((-1.5f64).fract(), -0.5f64); - assert_approx_eq!((-1.7f64).fract(), -0.7f64); - } + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")] + #[inline] + pub fn is_negative(self) -> bool { num::Float::is_negative(self) } - #[test] - fn test_exp() { - assert_eq!(1.0, 0.0f64.exp()); - assert_approx_eq!(2.718282, 1.0f64.exp()); - assert_approx_eq!(148.413159, 5.0f64.exp()); + /// Fused multiply-add. Computes `(self * a) + b` with only one rounding + /// error. This produces a more accurate result with better performance than + /// a separate multiplication operation followed by an add. + /// + /// ``` + /// let m = 10.0_f64; + /// let x = 4.0_f64; + /// let b = 60.0_f64; + /// + /// // 100.0 + /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) } - let inf: f64 = Float::infinity(); + /// Take the reciprocal (inverse) of a number, `1/x`. + /// + /// ``` + /// let x = 2.0_f64; + /// let abs_difference = (x.recip() - (1.0/x)).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn recip(self) -> f64 { num::Float::recip(self) } + + /// Raise a number to an integer power. + /// + /// Using this function is generally faster than using `powf` + /// + /// ``` + /// let x = 2.0_f64; + /// let abs_difference = (x.powi(2) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) } + + /// Raise a number to a floating point power. + /// + /// ``` + /// let x = 2.0_f64; + /// let abs_difference = (x.powf(2.0) - x*x).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) } + + /// Take the square root of a number. + /// + /// Returns NaN if `self` is a negative number. + /// + /// ``` + /// let positive = 4.0_f64; + /// let negative = -4.0_f64; + /// + /// let abs_difference = (positive.sqrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// assert!(negative.sqrt().is_nan()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sqrt(self) -> f64 { num::Float::sqrt(self) } + + /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. + /// + /// ``` + /// # #![feature(std_misc)] + /// let f = 4.0_f64; + /// + /// let abs_difference = (f.rsqrt() - 0.5).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")] + #[inline] + pub fn rsqrt(self) -> f64 { num::Float::rsqrt(self) } + + /// Returns `e^(self)`, (the exponential function). + /// + /// ``` + /// let one = 1.0_f64; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp(self) -> f64 { num::Float::exp(self) } + + /// Returns `2^(self)`. + /// + /// ``` + /// let f = 2.0_f64; + /// + /// // 2^2 - 4 == 0 + /// let abs_difference = (f.exp2() - 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp2(self) -> f64 { num::Float::exp2(self) } + + /// Returns the natural logarithm of the number. + /// + /// ``` + /// let one = 1.0_f64; + /// // e^1 + /// let e = one.exp(); + /// + /// // ln(e) - 1 == 0 + /// let abs_difference = (e.ln() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln(self) -> f64 { num::Float::ln(self) } + + /// Returns the logarithm of the number with respect to an arbitrary base. + /// + /// ``` + /// let ten = 10.0_f64; + /// let two = 2.0_f64; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs(); + /// + /// // log2(2) - 1 == 0 + /// let abs_difference_2 = (two.log(2.0) - 1.0).abs(); + /// + /// assert!(abs_difference_10 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log(self, base: f64) -> f64 { num::Float::log(self, base) } + + /// Returns the base 2 logarithm of the number. + /// + /// ``` + /// let two = 2.0_f64; + /// + /// // log2(2) - 1 == 0 + /// let abs_difference = (two.log2() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log2(self) -> f64 { num::Float::log2(self) } + + /// Returns the base 10 logarithm of the number. + /// + /// ``` + /// let ten = 10.0_f64; + /// + /// // log10(10) - 1 == 0 + /// let abs_difference = (ten.log10() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn log10(self) -> f64 { num::Float::log10(self) } + + /// Convert radians to degrees. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = consts::PI; + /// + /// let abs_difference = (angle.to_degrees() - 180.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) } + + /// Convert degrees to radians. + /// + /// ``` + /// use std::f64::consts; + /// + /// let angle = 180.0_f64; + /// + /// let abs_difference = (angle.to_radians() - consts::PI).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_radians(self) -> f64 { num::Float::to_radians(self) } + + /// Constructs a floating point number of `x*2^exp`. + /// + /// ``` + /// # #![feature(std_misc)] + /// // 3*2^2 - 12 == 0 + /// let abs_difference = (f64::ldexp(3.0, 2) - 12.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn ldexp(x: f64, exp: isize) -> f64 { + unsafe { cmath::ldexp(x, exp as c_int) } + } + + /// Breaks the number into a normalized fraction and a base-2 exponent, + /// satisfying: + /// + /// * `self = x * 2^exp` + /// * `0.5 <= abs(x) < 1.0` + /// + /// ``` + /// # #![feature(std_misc)] + /// let x = 4.0_f64; + /// + /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0 + /// let f = x.frexp(); + /// let abs_difference_0 = (f.0 - 0.5).abs(); + /// let abs_difference_1 = (f.1 as f64 - 3.0).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_1 < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "pending integer conventions")] + #[inline] + pub fn frexp(self) -> (f64, isize) { + unsafe { + let mut exp = 0; + let x = cmath::frexp(self, &mut exp); + (x, exp as isize) + } + } + + /// Returns the next representable floating-point value in the direction of + /// `other`. + /// + /// ``` + /// # #![feature(std_misc)] + /// + /// let x = 1.0f32; + /// + /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs(); + /// + /// assert!(abs_diff < 1e-10); + /// ``` + #[unstable(feature = "std_misc", + reason = "unsure about its place in the world")] + #[inline] + pub fn next_after(self, other: f64) -> f64 { + unsafe { cmath::nextafter(self, other) } + } + + /// Returns the maximum of the two numbers. + /// + /// ``` + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.max(y), y); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn max(self, other: f64) -> f64 { + unsafe { cmath::fmax(self, other) } + } + + /// Returns the minimum of the two numbers. + /// + /// ``` + /// let x = 1.0_f64; + /// let y = 2.0_f64; + /// + /// assert_eq!(x.min(y), x); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn min(self, other: f64) -> f64 { + unsafe { cmath::fmin(self, other) } + } + + /// The positive difference of two numbers. + /// + /// * If `self <= other`: `0:0` + /// * Else: `self - other` + /// + /// ``` + /// let x = 3.0_f64; + /// let y = -3.0_f64; + /// + /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs(); + /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs(); + /// + /// assert!(abs_difference_x < 1e-10); + /// assert!(abs_difference_y < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn abs_sub(self, other: f64) -> f64 { + unsafe { cmath::fdim(self, other) } + } + + /// Take the cubic root of a number. + /// + /// ``` + /// let x = 8.0_f64; + /// + /// // x^(1/3) - 2 == 0 + /// let abs_difference = (x.cbrt() - 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cbrt(self) -> f64 { + unsafe { cmath::cbrt(self) } + } + + /// Calculate the length of the hypotenuse of a right-angle triangle given + /// legs of length `x` and `y`. + /// + /// ``` + /// let x = 2.0_f64; + /// let y = 3.0_f64; + /// + /// // sqrt(x^2 + y^2) + /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn hypot(self, other: f64) -> f64 { + unsafe { cmath::hypot(self, other) } + } + + /// Computes the sine of a number (in radians). + /// + /// ``` + /// use std::f64; + /// + /// let x = f64::consts::PI/2.0; + /// + /// let abs_difference = (x.sin() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin(self) -> f64 { + unsafe { intrinsics::sinf64(self) } + } + + /// Computes the cosine of a number (in radians). + /// + /// ``` + /// use std::f64; + /// + /// let x = 2.0*f64::consts::PI; + /// + /// let abs_difference = (x.cos() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cos(self) -> f64 { + unsafe { intrinsics::cosf64(self) } + } + + /// Computes the tangent of a number (in radians). + /// + /// ``` + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let abs_difference = (x.tan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-14); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tan(self) -> f64 { + unsafe { cmath::tan(self) } + } + + /// Computes the arcsine of a number. Return value is in radians in + /// the range [-pi/2, pi/2] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::f64; + /// + /// let f = f64::consts::PI / 2.0; + /// + /// // asin(sin(pi/2)) + /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asin(self) -> f64 { + unsafe { cmath::asin(self) } + } + + /// Computes the arccosine of a number. Return value is in radians in + /// the range [0, pi] or NaN if the number is outside the range + /// [-1, 1]. + /// + /// ``` + /// use std::f64; + /// + /// let f = f64::consts::PI / 4.0; + /// + /// // acos(cos(pi/4)) + /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acos(self) -> f64 { + unsafe { cmath::acos(self) } + } + + /// Computes the arctangent of a number. Return value is in radians in the + /// range [-pi/2, pi/2]; + /// + /// ``` + /// let f = 1.0_f64; + /// + /// // atan(tan(1)) + /// let abs_difference = (f.tan().atan() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan(self) -> f64 { + unsafe { cmath::atan(self) } + } + + /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`). + /// + /// * `x = 0`, `y = 0`: `0` + /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]` + /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` + /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` + /// + /// ``` + /// use std::f64; + /// + /// let pi = f64::consts::PI; + /// // All angles from horizontal right (+x) + /// // 45 deg counter-clockwise + /// let x1 = 3.0_f64; + /// let y1 = -3.0_f64; + /// + /// // 135 deg clockwise + /// let x2 = -3.0_f64; + /// let y2 = 3.0_f64; + /// + /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs(); + /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs(); + /// + /// assert!(abs_difference_1 < 1e-10); + /// assert!(abs_difference_2 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atan2(self, other: f64) -> f64 { + unsafe { cmath::atan2(self, other) } + } + + /// Simultaneously computes the sine and cosine of the number, `x`. Returns + /// `(sin(x), cos(x))`. + /// + /// ``` + /// use std::f64; + /// + /// let x = f64::consts::PI/4.0; + /// let f = x.sin_cos(); + /// + /// let abs_difference_0 = (f.0 - x.sin()).abs(); + /// let abs_difference_1 = (f.1 - x.cos()).abs(); + /// + /// assert!(abs_difference_0 < 1e-10); + /// assert!(abs_difference_0 < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sin_cos(self) -> (f64, f64) { + (self.sin(), self.cos()) + } + + /// Returns `e^(self) - 1` in a way that is accurate even if the + /// number is close to zero. + /// + /// ``` + /// let x = 7.0_f64; + /// + /// // e^(ln(7)) - 1 + /// let abs_difference = (x.ln().exp_m1() - 6.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn exp_m1(self) -> f64 { + unsafe { cmath::expm1(self) } + } + + /// Returns `ln(1+n)` (natural logarithm) more accurately than if + /// the operations were performed separately. + /// + /// ``` + /// use std::f64; + /// + /// let x = f64::consts::E - 1.0; + /// + /// // ln(1 + (e - 1)) == ln(e) == 1 + /// let abs_difference = (x.ln_1p() - 1.0).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn ln_1p(self) -> f64 { + unsafe { cmath::log1p(self) } + } + + /// Hyperbolic sine function. + /// + /// ``` + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0_f64; + /// + /// let f = x.sinh(); + /// // Solving sinh() at 1 gives `(e^2-1)/(2e)` + /// let g = (e*e - 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn sinh(self) -> f64 { + unsafe { cmath::sinh(self) } + } + + /// Hyperbolic cosine function. + /// + /// ``` + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0_f64; + /// let f = x.cosh(); + /// // Solving cosh() at 1 gives this result + /// let g = (e*e + 1.0)/(2.0*e); + /// let abs_difference = (f - g).abs(); + /// + /// // Same result + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn cosh(self) -> f64 { + unsafe { cmath::cosh(self) } + } + + /// Hyperbolic tangent function. + /// + /// ``` + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let x = 1.0_f64; + /// + /// let f = x.tanh(); + /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))` + /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2)); + /// let abs_difference = (f - g).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn tanh(self) -> f64 { + unsafe { cmath::tanh(self) } + } + + /// Inverse hyperbolic sine function. + /// + /// ``` + /// let x = 1.0_f64; + /// let f = x.sinh().asinh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn asinh(self) -> f64 { + match self { + NEG_INFINITY => NEG_INFINITY, + x => (x + ((x * x) + 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic cosine function. + /// + /// ``` + /// let x = 1.0_f64; + /// let f = x.cosh().acosh(); + /// + /// let abs_difference = (f - x).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn acosh(self) -> f64 { + match self { + x if x < 1.0 => Float::nan(), + x => (x + ((x * x) - 1.0).sqrt()).ln(), + } + } + + /// Inverse hyperbolic tangent function. + /// + /// ``` + /// use std::f64; + /// + /// let e = f64::consts::E; + /// let f = e.tanh().atanh(); + /// + /// let abs_difference = (f - e).abs(); + /// + /// assert!(abs_difference < 1.0e-10); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn atanh(self) -> f64 { + 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() + } +} + +// +// Section: String Conversions +// + +/// Converts a float to a string +/// +/// # Arguments +/// +/// * num - The float value +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")] +pub fn to_string(num: f64) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigAll, ExpNone, false); + r +} + +/// Converts a float to a string in hexadecimal format +/// +/// # Arguments +/// +/// * num - The float value +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[deprecated(since = "1.0.0", reason = "use format! instead")] +pub fn to_str_hex(num: f64) -> String { + let (r, _) = strconv::float_to_str_common( + num, 16, true, SignNeg, DigAll, ExpNone, false); + r +} + +/// Converts a float to a string in a given radix, and a flag indicating +/// whether it's a special value +/// +/// # Arguments +/// +/// * num - The float value +/// * radix - The base to use +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[deprecated(since = "1.0.0", reason = "use format! instead")] +pub fn to_str_radix_special(num: f64, rdx: u32) -> (String, bool) { + strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false) +} + +/// Converts a float to a string with exactly the number of +/// provided significant digits +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of significant digits +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_exact(num: f64, dig: usize) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigExact(dig), ExpNone, false); + r +} + +/// Converts a float to a string with a maximum number of +/// significant digits +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of significant digits +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_digits(num: f64, dig: usize) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigMax(dig), ExpNone, false); + r +} + +/// Converts a float to a string using the exponential notation with exactly the number of +/// provided digits after the decimal point in the significand +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of digits after the decimal point +/// * upper - Use `E` instead of `e` for the exponent sign +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_exp_exact(num: f64, dig: usize, upper: bool) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigExact(dig), ExpDec, upper); + r +} + +/// Converts a float to a string using the exponential notation with the maximum number of +/// digits after the decimal point in the significand +/// +/// # Arguments +/// +/// * num - The float value +/// * digits - The number of digits after the decimal point +/// * upper - Use `E` instead of `e` for the exponent sign +#[inline] +#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +pub fn to_str_exp_digits(num: f64, dig: usize, upper: bool) -> String { + let (r, _) = strconv::float_to_str_common( + num, 10, true, SignNeg, DigMax(dig), ExpDec, upper); + r +} + +#[cfg(test)] +mod tests { + use f64::*; + use num::*; + use num::FpCategory as Fp; + + #[test] + fn test_num_f64() { + test_num(10f64, 2f64); + } + + #[test] + fn test_min_nan() { + assert_eq!(NAN.min(2.0), 2.0); + assert_eq!(2.0f64.min(NAN), 2.0); + } + + #[test] + fn test_max_nan() { + assert_eq!(NAN.max(2.0), 2.0); + assert_eq!(2.0f64.max(NAN), 2.0); + } + + #[test] + fn test_nan() { + let nan: f64 = Float::nan(); + assert!(nan.is_nan()); + assert!(!nan.is_infinite()); + assert!(!nan.is_finite()); + assert!(!nan.is_normal()); + assert!(!nan.is_sign_positive()); + assert!(!nan.is_sign_negative()); + assert_eq!(Fp::Nan, nan.classify()); + } + + #[test] + fn test_infinity() { + let inf: f64 = Float::infinity(); + assert!(inf.is_infinite()); + assert!(!inf.is_finite()); + assert!(inf.is_sign_positive()); + assert!(!inf.is_sign_negative()); + assert!(!inf.is_nan()); + assert!(!inf.is_normal()); + assert_eq!(Fp::Infinite, inf.classify()); + } + + #[test] + fn test_neg_infinity() { + let neg_inf: f64 = Float::neg_infinity(); + assert!(neg_inf.is_infinite()); + assert!(!neg_inf.is_finite()); + assert!(!neg_inf.is_sign_positive()); + assert!(neg_inf.is_sign_negative()); + assert!(!neg_inf.is_nan()); + assert!(!neg_inf.is_normal()); + assert_eq!(Fp::Infinite, neg_inf.classify()); + } + + #[test] + fn test_zero() { + let zero: f64 = Float::zero(); + assert_eq!(0.0, zero); + assert!(!zero.is_infinite()); + assert!(zero.is_finite()); + assert!(zero.is_sign_positive()); + assert!(!zero.is_sign_negative()); + assert!(!zero.is_nan()); + assert!(!zero.is_normal()); + assert_eq!(Fp::Zero, zero.classify()); + } + + #[test] + fn test_neg_zero() { + let neg_zero: f64 = Float::neg_zero(); + assert_eq!(0.0, neg_zero); + assert!(!neg_zero.is_infinite()); + assert!(neg_zero.is_finite()); + assert!(!neg_zero.is_sign_positive()); + assert!(neg_zero.is_sign_negative()); + assert!(!neg_zero.is_nan()); + assert!(!neg_zero.is_normal()); + assert_eq!(Fp::Zero, neg_zero.classify()); + } + + #[test] + fn test_one() { + let one: f64 = Float::one(); + assert_eq!(1.0, one); + assert!(!one.is_infinite()); + assert!(one.is_finite()); + assert!(one.is_sign_positive()); + assert!(!one.is_sign_negative()); + assert!(!one.is_nan()); + assert!(one.is_normal()); + assert_eq!(Fp::Normal, one.classify()); + } + + #[test] + fn test_is_nan() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert!(nan.is_nan()); + assert!(!0.0f64.is_nan()); + assert!(!5.3f64.is_nan()); + assert!(!(-10.732f64).is_nan()); + assert!(!inf.is_nan()); + assert!(!neg_inf.is_nan()); + } + + #[test] + fn test_is_infinite() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert!(!nan.is_infinite()); + assert!(inf.is_infinite()); + assert!(neg_inf.is_infinite()); + assert!(!0.0f64.is_infinite()); + assert!(!42.8f64.is_infinite()); + assert!(!(-109.2f64).is_infinite()); + } + + #[test] + fn test_is_finite() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert!(!nan.is_finite()); + assert!(!inf.is_finite()); + assert!(!neg_inf.is_finite()); + assert!(0.0f64.is_finite()); + assert!(42.8f64.is_finite()); + assert!((-109.2f64).is_finite()); + } + + #[test] + fn test_is_normal() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let zero: f64 = Float::zero(); + let neg_zero: f64 = Float::neg_zero(); + assert!(!nan.is_normal()); + assert!(!inf.is_normal()); + assert!(!neg_inf.is_normal()); + assert!(!zero.is_normal()); + assert!(!neg_zero.is_normal()); + assert!(1f64.is_normal()); + assert!(1e-307f64.is_normal()); + assert!(!1e-308f64.is_normal()); + } + + #[test] + fn test_classify() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let zero: f64 = Float::zero(); + let neg_zero: f64 = Float::neg_zero(); + assert_eq!(nan.classify(), Fp::Nan); + assert_eq!(inf.classify(), Fp::Infinite); + assert_eq!(neg_inf.classify(), Fp::Infinite); + assert_eq!(zero.classify(), Fp::Zero); + assert_eq!(neg_zero.classify(), Fp::Zero); + assert_eq!(1e-307f64.classify(), Fp::Normal); + assert_eq!(1e-308f64.classify(), Fp::Subnormal); + } + + #[test] + fn test_integer_decode() { + assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906, -51, 1)); + assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931, -39, -1)); + assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496, 48, 1)); + assert_eq!(0f64.integer_decode(), (0, -1075, 1)); + assert_eq!((-0f64).integer_decode(), (0, -1075, -1)); + assert_eq!(INFINITY.integer_decode(), (4503599627370496, 972, 1)); + assert_eq!(NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1)); + assert_eq!(NAN.integer_decode(), (6755399441055744, 972, 1)); + } + + #[test] + fn test_floor() { + assert_approx_eq!(1.0f64.floor(), 1.0f64); + assert_approx_eq!(1.3f64.floor(), 1.0f64); + assert_approx_eq!(1.5f64.floor(), 1.0f64); + assert_approx_eq!(1.7f64.floor(), 1.0f64); + assert_approx_eq!(0.0f64.floor(), 0.0f64); + assert_approx_eq!((-0.0f64).floor(), -0.0f64); + assert_approx_eq!((-1.0f64).floor(), -1.0f64); + assert_approx_eq!((-1.3f64).floor(), -2.0f64); + assert_approx_eq!((-1.5f64).floor(), -2.0f64); + assert_approx_eq!((-1.7f64).floor(), -2.0f64); + } + + #[test] + fn test_ceil() { + assert_approx_eq!(1.0f64.ceil(), 1.0f64); + assert_approx_eq!(1.3f64.ceil(), 2.0f64); + assert_approx_eq!(1.5f64.ceil(), 2.0f64); + assert_approx_eq!(1.7f64.ceil(), 2.0f64); + assert_approx_eq!(0.0f64.ceil(), 0.0f64); + assert_approx_eq!((-0.0f64).ceil(), -0.0f64); + assert_approx_eq!((-1.0f64).ceil(), -1.0f64); + assert_approx_eq!((-1.3f64).ceil(), -1.0f64); + assert_approx_eq!((-1.5f64).ceil(), -1.0f64); + assert_approx_eq!((-1.7f64).ceil(), -1.0f64); + } + + #[test] + fn test_round() { + assert_approx_eq!(1.0f64.round(), 1.0f64); + assert_approx_eq!(1.3f64.round(), 1.0f64); + assert_approx_eq!(1.5f64.round(), 2.0f64); + assert_approx_eq!(1.7f64.round(), 2.0f64); + assert_approx_eq!(0.0f64.round(), 0.0f64); + assert_approx_eq!((-0.0f64).round(), -0.0f64); + assert_approx_eq!((-1.0f64).round(), -1.0f64); + assert_approx_eq!((-1.3f64).round(), -1.0f64); + assert_approx_eq!((-1.5f64).round(), -2.0f64); + assert_approx_eq!((-1.7f64).round(), -2.0f64); + } + + #[test] + fn test_trunc() { + assert_approx_eq!(1.0f64.trunc(), 1.0f64); + assert_approx_eq!(1.3f64.trunc(), 1.0f64); + assert_approx_eq!(1.5f64.trunc(), 1.0f64); + assert_approx_eq!(1.7f64.trunc(), 1.0f64); + assert_approx_eq!(0.0f64.trunc(), 0.0f64); + assert_approx_eq!((-0.0f64).trunc(), -0.0f64); + assert_approx_eq!((-1.0f64).trunc(), -1.0f64); + assert_approx_eq!((-1.3f64).trunc(), -1.0f64); + assert_approx_eq!((-1.5f64).trunc(), -1.0f64); + assert_approx_eq!((-1.7f64).trunc(), -1.0f64); + } + + #[test] + fn test_fract() { + assert_approx_eq!(1.0f64.fract(), 0.0f64); + assert_approx_eq!(1.3f64.fract(), 0.3f64); + assert_approx_eq!(1.5f64.fract(), 0.5f64); + assert_approx_eq!(1.7f64.fract(), 0.7f64); + assert_approx_eq!(0.0f64.fract(), 0.0f64); + assert_approx_eq!((-0.0f64).fract(), -0.0f64); + assert_approx_eq!((-1.0f64).fract(), -0.0f64); + assert_approx_eq!((-1.3f64).fract(), -0.3f64); + assert_approx_eq!((-1.5f64).fract(), -0.5f64); + assert_approx_eq!((-1.7f64).fract(), -0.7f64); + } + + #[test] + fn test_abs() { + assert_eq!(INFINITY.abs(), INFINITY); + assert_eq!(1f64.abs(), 1f64); + assert_eq!(0f64.abs(), 0f64); + assert_eq!((-0f64).abs(), 0f64); + assert_eq!((-1f64).abs(), 1f64); + assert_eq!(NEG_INFINITY.abs(), INFINITY); + assert_eq!((1f64/NEG_INFINITY).abs(), 0f64); + assert!(NAN.abs().is_nan()); + } + + #[test] + fn test_signum() { + assert_eq!(INFINITY.signum(), 1f64); + assert_eq!(1f64.signum(), 1f64); + assert_eq!(0f64.signum(), 1f64); + assert_eq!((-0f64).signum(), -1f64); + assert_eq!((-1f64).signum(), -1f64); + assert_eq!(NEG_INFINITY.signum(), -1f64); + assert_eq!((1f64/NEG_INFINITY).signum(), -1f64); + assert!(NAN.signum().is_nan()); + } + + #[test] + fn test_is_sign_positive() { + assert!(INFINITY.is_sign_positive()); + assert!(1f64.is_sign_positive()); + assert!(0f64.is_sign_positive()); + assert!(!(-0f64).is_sign_positive()); + assert!(!(-1f64).is_sign_positive()); + assert!(!NEG_INFINITY.is_sign_positive()); + assert!(!(1f64/NEG_INFINITY).is_sign_positive()); + assert!(!NAN.is_sign_positive()); + } + + #[test] + fn test_is_sign_negative() { + assert!(!INFINITY.is_sign_negative()); + assert!(!1f64.is_sign_negative()); + assert!(!0f64.is_sign_negative()); + assert!((-0f64).is_sign_negative()); + assert!((-1f64).is_sign_negative()); + assert!(NEG_INFINITY.is_sign_negative()); + assert!((1f64/NEG_INFINITY).is_sign_negative()); + assert!(!NAN.is_sign_negative()); + } + + #[test] + fn test_mul_add() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05); + assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65); + assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2); + assert_approx_eq!(3.4f64.mul_add(-0.0, 5.6), 5.6); + assert!(nan.mul_add(7.8, 9.0).is_nan()); + assert_eq!(inf.mul_add(7.8, 9.0), inf); + assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf); + assert_eq!(8.9f64.mul_add(inf, 3.2), inf); + assert_eq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf); + } + + #[test] + fn test_recip() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(1.0f64.recip(), 1.0); + assert_eq!(2.0f64.recip(), 0.5); + assert_eq!((-0.4f64).recip(), -2.5); + assert_eq!(0.0f64.recip(), inf); + assert!(nan.recip().is_nan()); + assert_eq!(inf.recip(), 0.0); + assert_eq!(neg_inf.recip(), 0.0); + } + + #[test] + fn test_powi() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(1.0f64.powi(1), 1.0); + assert_approx_eq!((-3.1f64).powi(2), 9.61); + assert_approx_eq!(5.9f64.powi(-2), 0.028727); + assert_eq!(8.3f64.powi(0), 1.0); + assert!(nan.powi(2).is_nan()); + assert_eq!(inf.powi(3), inf); + assert_eq!(neg_inf.powi(2), inf); + } + + #[test] + fn test_powf() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(1.0f64.powf(1.0), 1.0); + assert_approx_eq!(3.4f64.powf(4.5), 246.408183); + assert_approx_eq!(2.7f64.powf(-3.2), 0.041652); + assert_approx_eq!((-3.1f64).powf(2.0), 9.61); + assert_approx_eq!(5.9f64.powf(-2.0), 0.028727); + assert_eq!(8.3f64.powf(0.0), 1.0); + assert!(nan.powf(2.0).is_nan()); + assert_eq!(inf.powf(2.0), inf); + assert_eq!(neg_inf.powf(3.0), neg_inf); + } + + #[test] + fn test_sqrt_domain() { + assert!(NAN.sqrt().is_nan()); + assert!(NEG_INFINITY.sqrt().is_nan()); + assert!((-1.0f64).sqrt().is_nan()); + assert_eq!((-0.0f64).sqrt(), -0.0); + assert_eq!(0.0f64.sqrt(), 0.0); + assert_eq!(1.0f64.sqrt(), 1.0); + assert_eq!(INFINITY.sqrt(), INFINITY); + } + + #[test] + fn test_rsqrt() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert!(nan.rsqrt().is_nan()); + assert_eq!(inf.rsqrt(), 0.0); + assert!(neg_inf.rsqrt().is_nan()); + assert!((-1.0f64).rsqrt().is_nan()); + assert_eq!((-0.0f64).rsqrt(), neg_inf); + assert_eq!(0.0f64.rsqrt(), inf); + assert_eq!(1.0f64.rsqrt(), 1.0); + assert_eq!(4.0f64.rsqrt(), 0.5); + } + + #[test] + fn test_exp() { + assert_eq!(1.0, 0.0f64.exp()); + assert_approx_eq!(2.718282, 1.0f64.exp()); + assert_approx_eq!(148.413159, 5.0f64.exp()); + + let inf: f64 = Float::infinity(); let neg_inf: f64 = Float::neg_infinity(); let nan: f64 = Float::nan(); assert_eq!(inf, inf.exp()); @@ -591,6 +1849,172 @@ mod tests { assert!(nan.exp2().is_nan()); } + #[test] + fn test_ln() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_approx_eq!(1.0f64.exp().ln(), 1.0); + assert!(nan.ln().is_nan()); + assert_eq!(inf.ln(), inf); + assert!(neg_inf.ln().is_nan()); + assert!((-2.3f64).ln().is_nan()); + assert_eq!((-0.0f64).ln(), neg_inf); + assert_eq!(0.0f64.ln(), neg_inf); + assert_approx_eq!(4.0f64.ln(), 1.386294); + } + + #[test] + fn test_log() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(10.0f64.log(10.0), 1.0); + assert_approx_eq!(2.3f64.log(3.5), 0.664858); + assert_eq!(1.0f64.exp().log(1.0.exp()), 1.0); + assert!(1.0f64.log(1.0).is_nan()); + assert!(1.0f64.log(-13.9).is_nan()); + assert!(nan.log(2.3).is_nan()); + assert_eq!(inf.log(10.0), inf); + assert!(neg_inf.log(8.8).is_nan()); + assert!((-2.3f64).log(0.1).is_nan()); + assert_eq!((-0.0f64).log(2.0), neg_inf); + assert_eq!(0.0f64.log(7.0), neg_inf); + } + + #[test] + fn test_log2() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_approx_eq!(10.0f64.log2(), 3.321928); + assert_approx_eq!(2.3f64.log2(), 1.201634); + assert_approx_eq!(1.0f64.exp().log2(), 1.442695); + assert!(nan.log2().is_nan()); + assert_eq!(inf.log2(), inf); + assert!(neg_inf.log2().is_nan()); + assert!((-2.3f64).log2().is_nan()); + assert_eq!((-0.0f64).log2(), neg_inf); + assert_eq!(0.0f64.log2(), neg_inf); + } + + #[test] + fn test_log10() { + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(10.0f64.log10(), 1.0); + assert_approx_eq!(2.3f64.log10(), 0.361728); + assert_approx_eq!(1.0f64.exp().log10(), 0.434294); + assert_eq!(1.0f64.log10(), 0.0); + assert!(nan.log10().is_nan()); + assert_eq!(inf.log10(), inf); + assert!(neg_inf.log10().is_nan()); + assert!((-2.3f64).log10().is_nan()); + assert_eq!((-0.0f64).log10(), neg_inf); + assert_eq!(0.0f64.log10(), neg_inf); + } + + #[test] + fn test_to_degrees() { + let pi: f64 = consts::PI; + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(0.0f64.to_degrees(), 0.0); + assert_approx_eq!((-5.8f64).to_degrees(), -332.315521); + assert_eq!(pi.to_degrees(), 180.0); + assert!(nan.to_degrees().is_nan()); + assert_eq!(inf.to_degrees(), inf); + assert_eq!(neg_inf.to_degrees(), neg_inf); + } + + #[test] + fn test_to_radians() { + let pi: f64 = consts::PI; + let nan: f64 = Float::nan(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + assert_eq!(0.0f64.to_radians(), 0.0); + assert_approx_eq!(154.6f64.to_radians(), 2.698279); + assert_approx_eq!((-332.31f64).to_radians(), -5.799903); + assert_eq!(180.0f64.to_radians(), pi); + assert!(nan.to_radians().is_nan()); + assert_eq!(inf.to_radians(), inf); + assert_eq!(neg_inf.to_radians(), neg_inf); + } + + #[test] + fn test_ldexp() { + // We have to use from_str until base-2 exponents + // are supported in floating-point literals + let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); + let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); + let f3: f64 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap(); + assert_eq!(1f64.ldexp(-123), f1); + assert_eq!(1f64.ldexp(-111), f2); + assert_eq!(Float::ldexp(1.75f64, -12), f3); + + assert_eq!(Float::ldexp(0f64, -123), 0f64); + assert_eq!(Float::ldexp(-0f64, -123), -0f64); + + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::nan(); + assert_eq!(Float::ldexp(inf, -123), inf); + assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); + assert!(Float::ldexp(nan, -123).is_nan()); + } + + #[test] + fn test_frexp() { + // We have to use from_str until base-2 exponents + // are supported in floating-point literals + let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); + let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); + let f3: f64 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap(); + let (x1, exp1) = f1.frexp(); + let (x2, exp2) = f2.frexp(); + let (x3, exp3) = f3.frexp(); + assert_eq!((x1, exp1), (0.5f64, -122)); + assert_eq!((x2, exp2), (0.5f64, -110)); + assert_eq!((x3, exp3), (0.875f64, -122)); + assert_eq!(Float::ldexp(x1, exp1), f1); + assert_eq!(Float::ldexp(x2, exp2), f2); + assert_eq!(Float::ldexp(x3, exp3), f3); + + assert_eq!(0f64.frexp(), (0f64, 0)); + assert_eq!((-0f64).frexp(), (-0f64, 0)); + } + + #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 + fn test_frexp_nowin() { + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::nan(); + assert_eq!(match inf.frexp() { (x, _) => x }, inf); + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); + assert!(match nan.frexp() { (x, _) => x.is_nan() }) + } + + #[test] + fn test_abs_sub() { + assert_eq!((-1f64).abs_sub(1f64), 0f64); + assert_eq!(1f64.abs_sub(1f64), 0f64); + assert_eq!(1f64.abs_sub(0f64), 1f64); + assert_eq!(1f64.abs_sub(-1f64), 2f64); + assert_eq!(NEG_INFINITY.abs_sub(0f64), 0f64); + assert_eq!(INFINITY.abs_sub(1f64), INFINITY); + assert_eq!(0f64.abs_sub(NEG_INFINITY), INFINITY); + assert_eq!(0f64.abs_sub(INFINITY), 0f64); + } + + #[test] + fn test_abs_sub_nowin() { + assert!(NAN.abs_sub(-1f64).is_nan()); + assert!(1f64.abs_sub(NAN).is_nan()); + } + #[test] fn test_asinh() { assert_eq!(0.0f64.asinh(), 0.0f64); @@ -677,173 +2101,4 @@ mod tests { assert_approx_eq!(ln_2, 2f64.ln()); assert_approx_eq!(ln_10, 10f64.ln()); } - - #[test] - pub fn test_abs() { - assert_eq!(INFINITY.abs(), INFINITY); - assert_eq!(1f64.abs(), 1f64); - assert_eq!(0f64.abs(), 0f64); - assert_eq!((-0f64).abs(), 0f64); - assert_eq!((-1f64).abs(), 1f64); - assert_eq!(NEG_INFINITY.abs(), INFINITY); - assert_eq!((1f64/NEG_INFINITY).abs(), 0f64); - assert!(NAN.abs().is_nan()); - } - - #[test] - fn test_abs_sub() { - assert_eq!((-1f64).abs_sub(1f64), 0f64); - assert_eq!(1f64.abs_sub(1f64), 0f64); - assert_eq!(1f64.abs_sub(0f64), 1f64); - assert_eq!(1f64.abs_sub(-1f64), 2f64); - assert_eq!(NEG_INFINITY.abs_sub(0f64), 0f64); - assert_eq!(INFINITY.abs_sub(1f64), INFINITY); - assert_eq!(0f64.abs_sub(NEG_INFINITY), INFINITY); - assert_eq!(0f64.abs_sub(INFINITY), 0f64); - } - - #[test] - fn test_abs_sub_nowin() { - assert!(NAN.abs_sub(-1f64).is_nan()); - assert!(1f64.abs_sub(NAN).is_nan()); - } - - #[test] - fn test_signum() { - assert_eq!(INFINITY.signum(), 1f64); - assert_eq!(1f64.signum(), 1f64); - assert_eq!(0f64.signum(), 1f64); - assert_eq!((-0f64).signum(), -1f64); - assert_eq!((-1f64).signum(), -1f64); - assert_eq!(NEG_INFINITY.signum(), -1f64); - assert_eq!((1f64/NEG_INFINITY).signum(), -1f64); - assert!(NAN.signum().is_nan()); - } - - #[test] - fn test_is_positive() { - assert!(INFINITY.is_positive()); - assert!(1f64.is_positive()); - assert!(0f64.is_positive()); - assert!(!(-0f64).is_positive()); - assert!(!(-1f64).is_positive()); - assert!(!NEG_INFINITY.is_positive()); - assert!(!(1f64/NEG_INFINITY).is_positive()); - assert!(!NAN.is_positive()); - } - - #[test] - fn test_is_negative() { - assert!(!INFINITY.is_negative()); - assert!(!1f64.is_negative()); - assert!(!0f64.is_negative()); - assert!((-0f64).is_negative()); - assert!((-1f64).is_negative()); - assert!(NEG_INFINITY.is_negative()); - assert!((1f64/NEG_INFINITY).is_negative()); - assert!(!NAN.is_negative()); - } - - #[test] - fn test_is_normal() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let zero: f64 = Float::zero(); - let neg_zero: f64 = Float::neg_zero(); - assert!(!nan.is_normal()); - assert!(!inf.is_normal()); - assert!(!neg_inf.is_normal()); - assert!(!zero.is_normal()); - assert!(!neg_zero.is_normal()); - assert!(1f64.is_normal()); - assert!(1e-307f64.is_normal()); - assert!(!1e-308f64.is_normal()); - } - - #[test] - fn test_classify() { - let nan: f64 = Float::nan(); - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let zero: f64 = Float::zero(); - let neg_zero: f64 = Float::neg_zero(); - assert_eq!(nan.classify(), Fp::Nan); - assert_eq!(inf.classify(), Fp::Infinite); - assert_eq!(neg_inf.classify(), Fp::Infinite); - assert_eq!(zero.classify(), Fp::Zero); - assert_eq!(neg_zero.classify(), Fp::Zero); - assert_eq!(1e-307f64.classify(), Fp::Normal); - assert_eq!(1e-308f64.classify(), Fp::Subnormal); - } - - #[test] - fn test_ldexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - assert_eq!(Float::ldexp(1f64, -123), f1); - assert_eq!(Float::ldexp(1f64, -111), f2); - - assert_eq!(Float::ldexp(0f64, -123), 0f64); - assert_eq!(Float::ldexp(-0f64, -123), -0f64); - - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); - assert_eq!(Float::ldexp(inf, -123), inf); - assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); - assert!(Float::ldexp(nan, -123).is_nan()); - } - - #[test] - fn test_frexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap(); - let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap(); - let (x1, exp1) = f1.frexp(); - let (x2, exp2) = f2.frexp(); - assert_eq!((x1, exp1), (0.5f64, -122)); - assert_eq!((x2, exp2), (0.5f64, -110)); - assert_eq!(Float::ldexp(x1, exp1), f1); - assert_eq!(Float::ldexp(x2, exp2), f2); - - assert_eq!(0f64.frexp(), (0f64, 0)); - assert_eq!((-0f64).frexp(), (-0f64, 0)); - } - - #[test] #[cfg_attr(windows, ignore)] // FIXME #8755 - fn test_frexp_nowin() { - let inf: f64 = Float::infinity(); - let neg_inf: f64 = Float::neg_infinity(); - let nan: f64 = Float::nan(); - assert_eq!(match inf.frexp() { (x, _) => x }, inf); - assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); - assert!(match nan.frexp() { (x, _) => x.is_nan() }) - } - - #[test] - fn test_integer_decode() { - assert_eq!(3.14159265359f64.integer_decode(), (7074237752028906u64, -51i16, 1i8)); - assert_eq!((-8573.5918555f64).integer_decode(), (4713381968463931u64, -39i16, -1i8)); - assert_eq!(2f64.powf(100.0).integer_decode(), (4503599627370496u64, 48i16, 1i8)); - assert_eq!(0f64.integer_decode(), (0u64, -1075i16, 1i8)); - assert_eq!((-0f64).integer_decode(), (0u64, -1075i16, -1i8)); - assert_eq!(INFINITY.integer_decode(), (4503599627370496u64, 972i16, 1i8)); - assert_eq!(NEG_INFINITY.integer_decode(), (4503599627370496, 972, -1)); - assert_eq!(NAN.integer_decode(), (6755399441055744u64, 972i16, 1i8)); - } - - #[test] - fn test_sqrt_domain() { - assert!(NAN.sqrt().is_nan()); - assert!(NEG_INFINITY.sqrt().is_nan()); - assert!((-1.0f64).sqrt().is_nan()); - assert_eq!((-0.0f64).sqrt(), -0.0); - assert_eq!(0.0f64.sqrt(), 0.0); - assert_eq!(1.0f64.sqrt(), 1.0); - assert_eq!(INFINITY.sqrt(), INFINITY); - } } diff --git a/src/libstd/num/float_macros.rs b/src/libstd/num/float_macros.rs index 2b730cd6f9..60a548b596 100644 --- a/src/libstd/num/float_macros.rs +++ b/src/libstd/num/float_macros.rs @@ -13,7 +13,6 @@ macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ - use num::Float; let (a, b) = (&$a, &$b); assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs deleted file mode 100644 index 669952eee3..0000000000 --- a/src/libstd/num/int.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Deprecated: replaced by `isize`. -//! -//! The rollout of the new type will gradually take place over the -//! alpha cycle along with the development of clearer conventions -//! around integer types. - -#![unstable(feature = "std_misc")] -#![deprecated(since = "1.0.0", reason = "replaced by isize")] - -pub use core::int::{BITS, BYTES, MIN, MAX}; - -int_module! { int } diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index c94c164983..2de03e2e72 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -11,10 +11,11 @@ //! Numeric traits and functions for generic mathematics //! //! These are implemented for the primitive numeric types in `std::{u8, u16, -//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64}`. +//! u32, u64, usize, i8, i16, i32, i64, isize, f32, f64}`. #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] +#![allow(deprecated)] #[cfg(test)] use fmt::Debug; use ops::{Add, Sub, Mul, Div, Rem, Neg}; @@ -23,21 +24,24 @@ use marker::Copy; use clone::Clone; use cmp::{PartialOrd, PartialEq}; -pub use core::num::{Int, SignedInt, UnsignedInt}; +pub use core::num::{Int, SignedInt, Zero, One}; pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; pub use core::num::{from_f32, from_f64}; pub use core::num::{FromStrRadix, from_str_radix}; pub use core::num::{FpCategory, ParseIntError, ParseFloatError}; +pub use core::num::{wrapping, Wrapping}; use option::Option; -#[unstable(feature = "std_misc", reason = "may be removed or relocated")] +#[unstable(feature = "std_misc", reason = "likely to be removed")] pub mod strconv; /// Mathematical operations on primitive floating point numbers. #[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", + reason = "replaced by inherent methods; use rust-lang/num for generics")] pub trait Float : Copy + Clone + NumCast @@ -54,6 +58,7 @@ pub trait Float /// Returns the `NaN` value. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let nan: f32 = Float::nan(); @@ -66,6 +71,7 @@ pub trait Float /// Returns the infinite value. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f32; /// @@ -81,6 +87,7 @@ pub trait Float /// Returns the negative infinite value. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f32; /// @@ -96,6 +103,7 @@ pub trait Float /// Returns `0.0`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let inf: f32 = Float::infinity(); @@ -112,6 +120,7 @@ pub trait Float /// Returns `-0.0`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let inf: f32 = Float::infinity(); @@ -128,6 +137,7 @@ pub trait Float /// Returns `1.0`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let one: f32 = Float::one(); @@ -146,12 +156,12 @@ pub trait Float #[deprecated(since = "1.0.0", reason = "use `std::f32::MANTISSA_DIGITS` or \ `std::f64::MANTISSA_DIGITS` as appropriate")] - fn mantissa_digits(unused_self: Option) -> uint; + fn mantissa_digits(unused_self: Option) -> usize; /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead. #[unstable(feature = "std_misc")] #[deprecated(since = "1.0.0", reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")] - fn digits(unused_self: Option) -> uint; + fn digits(unused_self: Option) -> usize; /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead. #[unstable(feature = "std_misc")] #[deprecated(since = "1.0.0", @@ -161,26 +171,27 @@ pub trait Float #[unstable(feature = "std_misc")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")] - fn min_exp(unused_self: Option) -> int; + fn min_exp(unused_self: Option) -> isize; /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead. #[unstable(feature = "std_misc")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")] - fn max_exp(unused_self: Option) -> int; + fn max_exp(unused_self: Option) -> isize; /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead. #[unstable(feature = "std_misc")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")] - fn min_10_exp(unused_self: Option) -> int; + fn min_10_exp(unused_self: Option) -> isize; /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead. #[unstable(feature = "std_misc")] #[deprecated(since = "1.0.0", reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")] - fn max_10_exp(unused_self: Option) -> int; + fn max_10_exp(unused_self: Option) -> isize; /// Returns the smallest finite value that this type can represent. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f64; /// @@ -198,6 +209,7 @@ pub trait Float /// Returns the largest finite value that this type can represent. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f64; /// @@ -210,6 +222,7 @@ pub trait Float /// Returns `true` if this value is `NaN` and false otherwise. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f64; /// @@ -225,6 +238,7 @@ pub trait Float /// false otherwise. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f32; /// @@ -244,6 +258,7 @@ pub trait Float /// Returns `true` if this number is neither infinite nor `NaN`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f32; /// @@ -260,10 +275,12 @@ pub trait Float /// ``` #[unstable(feature = "std_misc", reason = "position is undecided")] fn is_finite(self) -> bool; + /// Returns `true` if the number is neither zero, infinite, /// [subnormal][subnormal], or `NaN`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f32; /// @@ -290,6 +307,7 @@ pub trait Float /// predicate instead. /// /// ``` + /// # #![feature(core)] /// use std::num::{Float, FpCategory}; /// use std::f32; /// @@ -307,11 +325,12 @@ pub trait Float /// The floating point encoding is documented in the [Reference][floating-point]. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let num = 2.0f32; /// - /// // (8388608u64, -22i16, 1i8) + /// // (8388608, -22, 1) /// let (mantissa, exponent, sign) = num.integer_decode(); /// let sign_f = sign as f32; /// let mantissa_f = mantissa as f32; @@ -398,6 +417,7 @@ pub trait Float /// number is `Float::nan()`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f64; /// @@ -421,6 +441,7 @@ pub trait Float /// - `Float::nan()` if the number is `Float::nan()` /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// use std::f64; /// @@ -477,6 +498,7 @@ pub trait Float /// a separate multiplication operation followed by an add. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let m = 10.0; @@ -494,6 +516,7 @@ pub trait Float /// Take the reciprocal (inverse) of a number, `1/x`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 2.0; @@ -536,6 +559,7 @@ pub trait Float /// Returns NaN if `self` is a negative number. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let positive = 4.0; @@ -552,6 +576,7 @@ pub trait Float /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let f = 4.0; @@ -661,6 +686,7 @@ pub trait Float /// Convert radians to degrees. /// /// ``` + /// # #![feature(std_misc, core)] /// use std::num::Float; /// use std::f64::consts; /// @@ -675,6 +701,7 @@ pub trait Float /// Convert degrees to radians. /// /// ``` + /// # #![feature(std_misc, core)] /// use std::num::Float; /// use std::f64::consts; /// @@ -689,6 +716,7 @@ pub trait Float /// Constructs a floating point number of `x*2^exp`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// // 3*2^2 - 12 == 0 @@ -698,7 +726,7 @@ pub trait Float /// ``` #[unstable(feature = "std_misc", reason = "pending integer conventions")] - fn ldexp(x: Self, exp: int) -> Self; + fn ldexp(self, exp: isize) -> Self; /// Breaks the number into a normalized fraction and a base-2 exponent, /// satisfying: /// @@ -706,6 +734,7 @@ pub trait Float /// * `0.5 <= abs(x) < 1.0` /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 4.0; @@ -720,11 +749,12 @@ pub trait Float /// ``` #[unstable(feature = "std_misc", reason = "pending integer conventions")] - fn frexp(self) -> (Self, int); + fn frexp(self) -> (Self, isize); /// Returns the next representable floating-point value in the direction of /// `other`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 1.0f32; @@ -768,6 +798,7 @@ pub trait Float /// * Else: `self - other` /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 3.0; @@ -784,6 +815,7 @@ pub trait Float /// Take the cubic root of a number. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 8.0; @@ -799,6 +831,7 @@ pub trait Float /// legs of length `x` and `y`. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 2.0; @@ -816,6 +849,7 @@ pub trait Float /// Computes the sine of a number (in radians). /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -830,6 +864,7 @@ pub trait Float /// Computes the cosine of a number (in radians). /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -844,6 +879,7 @@ pub trait Float /// Computes the tangent of a number (in radians). /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -859,6 +895,7 @@ pub trait Float /// [-1, 1]. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -876,6 +913,7 @@ pub trait Float /// [-1, 1]. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -911,6 +949,7 @@ pub trait Float /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -936,6 +975,7 @@ pub trait Float /// `(sin(x), cos(x))`. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -955,6 +995,7 @@ pub trait Float /// number is close to zero. /// /// ``` + /// # #![feature(std_misc)] /// use std::num::Float; /// /// let x = 7.0; @@ -970,6 +1011,7 @@ pub trait Float /// the operations were performed separately. /// /// ``` + /// # #![feature(std_misc, core)] /// use std::num::Float; /// use std::f64; /// @@ -986,6 +1028,7 @@ pub trait Float /// Hyperbolic sine function. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -1004,6 +1047,7 @@ pub trait Float /// Hyperbolic cosine function. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -1022,6 +1066,7 @@ pub trait Float /// Hyperbolic tangent function. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -1068,6 +1113,7 @@ pub trait Float /// Inverse hyperbolic tangent function. /// /// ``` + /// # #![feature(core)] /// use std::num::Float; /// use std::f64; /// @@ -1106,18 +1152,19 @@ pub fn test_num(ten: T, two: T) where #[cfg(test)] mod tests { - use prelude::v1::*; + use core::prelude::*; use super::*; use i8; use i16; use i32; use i64; - use int; + use isize; use u8; use u16; use u32; use u64; - use uint; + use usize; + use string::ToString; macro_rules! test_cast_20 { ($_20:expr) => ({ @@ -1179,25 +1226,25 @@ mod tests { #[test] fn test_cast_range_int_min() { - assert_eq!(int::MIN.to_int(), Some(int::MIN as int)); - assert_eq!(int::MIN.to_i8(), None); - assert_eq!(int::MIN.to_i16(), None); - // int::MIN.to_i32() is word-size specific - assert_eq!(int::MIN.to_i64(), Some(int::MIN as i64)); - assert_eq!(int::MIN.to_uint(), None); - assert_eq!(int::MIN.to_u8(), None); - assert_eq!(int::MIN.to_u16(), None); - assert_eq!(int::MIN.to_u32(), None); - assert_eq!(int::MIN.to_u64(), None); + assert_eq!(isize::MIN.to_int(), Some(isize::MIN as isize)); + assert_eq!(isize::MIN.to_i8(), None); + assert_eq!(isize::MIN.to_i16(), None); + // isize::MIN.to_i32() is word-size specific + assert_eq!(isize::MIN.to_i64(), Some(isize::MIN as i64)); + assert_eq!(isize::MIN.to_uint(), None); + assert_eq!(isize::MIN.to_u8(), None); + assert_eq!(isize::MIN.to_u16(), None); + assert_eq!(isize::MIN.to_u32(), None); + assert_eq!(isize::MIN.to_u64(), None); #[cfg(target_pointer_width = "32")] fn check_word_size() { - assert_eq!(int::MIN.to_i32(), Some(int::MIN as i32)); + assert_eq!(isize::MIN.to_i32(), Some(isize::MIN as i32)); } #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(int::MIN.to_i32(), None); + assert_eq!(isize::MIN.to_i32(), None); } check_word_size(); @@ -1205,7 +1252,7 @@ mod tests { #[test] fn test_cast_range_i8_min() { - assert_eq!(i8::MIN.to_int(), Some(i8::MIN as int)); + assert_eq!(i8::MIN.to_int(), Some(i8::MIN as isize)); assert_eq!(i8::MIN.to_i8(), Some(i8::MIN as i8)); assert_eq!(i8::MIN.to_i16(), Some(i8::MIN as i16)); assert_eq!(i8::MIN.to_i32(), Some(i8::MIN as i32)); @@ -1219,7 +1266,7 @@ mod tests { #[test] fn test_cast_range_i16_min() { - assert_eq!(i16::MIN.to_int(), Some(i16::MIN as int)); + assert_eq!(i16::MIN.to_int(), Some(i16::MIN as isize)); assert_eq!(i16::MIN.to_i8(), None); assert_eq!(i16::MIN.to_i16(), Some(i16::MIN as i16)); assert_eq!(i16::MIN.to_i32(), Some(i16::MIN as i32)); @@ -1233,7 +1280,7 @@ mod tests { #[test] fn test_cast_range_i32_min() { - assert_eq!(i32::MIN.to_int(), Some(i32::MIN as int)); + assert_eq!(i32::MIN.to_int(), Some(i32::MIN as isize)); assert_eq!(i32::MIN.to_i8(), None); assert_eq!(i32::MIN.to_i16(), None); assert_eq!(i32::MIN.to_i32(), Some(i32::MIN as i32)); @@ -1265,7 +1312,7 @@ mod tests { #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(i64::MIN.to_int(), Some(i64::MIN as int)); + assert_eq!(i64::MIN.to_int(), Some(i64::MIN as isize)); } check_word_size(); @@ -1273,26 +1320,26 @@ mod tests { #[test] fn test_cast_range_int_max() { - assert_eq!(int::MAX.to_int(), Some(int::MAX as int)); - assert_eq!(int::MAX.to_i8(), None); - assert_eq!(int::MAX.to_i16(), None); - // int::MAX.to_i32() is word-size specific - assert_eq!(int::MAX.to_i64(), Some(int::MAX as i64)); - assert_eq!(int::MAX.to_u8(), None); - assert_eq!(int::MAX.to_u16(), None); - // int::MAX.to_u32() is word-size specific - assert_eq!(int::MAX.to_u64(), Some(int::MAX as u64)); + assert_eq!(isize::MAX.to_int(), Some(isize::MAX as isize)); + assert_eq!(isize::MAX.to_i8(), None); + assert_eq!(isize::MAX.to_i16(), None); + // isize::MAX.to_i32() is word-size specific + assert_eq!(isize::MAX.to_i64(), Some(isize::MAX as i64)); + assert_eq!(isize::MAX.to_u8(), None); + assert_eq!(isize::MAX.to_u16(), None); + // isize::MAX.to_u32() is word-size specific + assert_eq!(isize::MAX.to_u64(), Some(isize::MAX as u64)); #[cfg(target_pointer_width = "32")] fn check_word_size() { - assert_eq!(int::MAX.to_i32(), Some(int::MAX as i32)); - assert_eq!(int::MAX.to_u32(), Some(int::MAX as u32)); + assert_eq!(isize::MAX.to_i32(), Some(isize::MAX as i32)); + assert_eq!(isize::MAX.to_u32(), Some(isize::MAX as u32)); } #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(int::MAX.to_i32(), None); - assert_eq!(int::MAX.to_u32(), None); + assert_eq!(isize::MAX.to_i32(), None); + assert_eq!(isize::MAX.to_u32(), None); } check_word_size(); @@ -1300,12 +1347,12 @@ mod tests { #[test] fn test_cast_range_i8_max() { - assert_eq!(i8::MAX.to_int(), Some(i8::MAX as int)); + assert_eq!(i8::MAX.to_int(), Some(i8::MAX as isize)); assert_eq!(i8::MAX.to_i8(), Some(i8::MAX as i8)); assert_eq!(i8::MAX.to_i16(), Some(i8::MAX as i16)); assert_eq!(i8::MAX.to_i32(), Some(i8::MAX as i32)); assert_eq!(i8::MAX.to_i64(), Some(i8::MAX as i64)); - assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as uint)); + assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as usize)); assert_eq!(i8::MAX.to_u8(), Some(i8::MAX as u8)); assert_eq!(i8::MAX.to_u16(), Some(i8::MAX as u16)); assert_eq!(i8::MAX.to_u32(), Some(i8::MAX as u32)); @@ -1314,12 +1361,12 @@ mod tests { #[test] fn test_cast_range_i16_max() { - assert_eq!(i16::MAX.to_int(), Some(i16::MAX as int)); + assert_eq!(i16::MAX.to_int(), Some(i16::MAX as isize)); assert_eq!(i16::MAX.to_i8(), None); assert_eq!(i16::MAX.to_i16(), Some(i16::MAX as i16)); assert_eq!(i16::MAX.to_i32(), Some(i16::MAX as i32)); assert_eq!(i16::MAX.to_i64(), Some(i16::MAX as i64)); - assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as uint)); + assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as usize)); assert_eq!(i16::MAX.to_u8(), None); assert_eq!(i16::MAX.to_u16(), Some(i16::MAX as u16)); assert_eq!(i16::MAX.to_u32(), Some(i16::MAX as u32)); @@ -1328,12 +1375,12 @@ mod tests { #[test] fn test_cast_range_i32_max() { - assert_eq!(i32::MAX.to_int(), Some(i32::MAX as int)); + assert_eq!(i32::MAX.to_int(), Some(i32::MAX as isize)); assert_eq!(i32::MAX.to_i8(), None); assert_eq!(i32::MAX.to_i16(), None); assert_eq!(i32::MAX.to_i32(), Some(i32::MAX as i32)); assert_eq!(i32::MAX.to_i64(), Some(i32::MAX as i64)); - assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as uint)); + assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as usize)); assert_eq!(i32::MAX.to_u8(), None); assert_eq!(i32::MAX.to_u16(), None); assert_eq!(i32::MAX.to_u32(), Some(i32::MAX as u32)); @@ -1361,8 +1408,8 @@ mod tests { #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(i64::MAX.to_int(), Some(i64::MAX as int)); - assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as uint)); + assert_eq!(i64::MAX.to_int(), Some(i64::MAX as isize)); + assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as usize)); } check_word_size(); @@ -1370,26 +1417,26 @@ mod tests { #[test] fn test_cast_range_uint_min() { - assert_eq!(uint::MIN.to_int(), Some(uint::MIN as int)); - assert_eq!(uint::MIN.to_i8(), Some(uint::MIN as i8)); - assert_eq!(uint::MIN.to_i16(), Some(uint::MIN as i16)); - assert_eq!(uint::MIN.to_i32(), Some(uint::MIN as i32)); - assert_eq!(uint::MIN.to_i64(), Some(uint::MIN as i64)); - assert_eq!(uint::MIN.to_uint(), Some(uint::MIN as uint)); - assert_eq!(uint::MIN.to_u8(), Some(uint::MIN as u8)); - assert_eq!(uint::MIN.to_u16(), Some(uint::MIN as u16)); - assert_eq!(uint::MIN.to_u32(), Some(uint::MIN as u32)); - assert_eq!(uint::MIN.to_u64(), Some(uint::MIN as u64)); + assert_eq!(usize::MIN.to_int(), Some(usize::MIN as isize)); + assert_eq!(usize::MIN.to_i8(), Some(usize::MIN as i8)); + assert_eq!(usize::MIN.to_i16(), Some(usize::MIN as i16)); + assert_eq!(usize::MIN.to_i32(), Some(usize::MIN as i32)); + assert_eq!(usize::MIN.to_i64(), Some(usize::MIN as i64)); + assert_eq!(usize::MIN.to_uint(), Some(usize::MIN as usize)); + assert_eq!(usize::MIN.to_u8(), Some(usize::MIN as u8)); + assert_eq!(usize::MIN.to_u16(), Some(usize::MIN as u16)); + assert_eq!(usize::MIN.to_u32(), Some(usize::MIN as u32)); + assert_eq!(usize::MIN.to_u64(), Some(usize::MIN as u64)); } #[test] fn test_cast_range_u8_min() { - assert_eq!(u8::MIN.to_int(), Some(u8::MIN as int)); + assert_eq!(u8::MIN.to_int(), Some(u8::MIN as isize)); assert_eq!(u8::MIN.to_i8(), Some(u8::MIN as i8)); assert_eq!(u8::MIN.to_i16(), Some(u8::MIN as i16)); assert_eq!(u8::MIN.to_i32(), Some(u8::MIN as i32)); assert_eq!(u8::MIN.to_i64(), Some(u8::MIN as i64)); - assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as uint)); + assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as usize)); assert_eq!(u8::MIN.to_u8(), Some(u8::MIN as u8)); assert_eq!(u8::MIN.to_u16(), Some(u8::MIN as u16)); assert_eq!(u8::MIN.to_u32(), Some(u8::MIN as u32)); @@ -1398,12 +1445,12 @@ mod tests { #[test] fn test_cast_range_u16_min() { - assert_eq!(u16::MIN.to_int(), Some(u16::MIN as int)); + assert_eq!(u16::MIN.to_int(), Some(u16::MIN as isize)); assert_eq!(u16::MIN.to_i8(), Some(u16::MIN as i8)); assert_eq!(u16::MIN.to_i16(), Some(u16::MIN as i16)); assert_eq!(u16::MIN.to_i32(), Some(u16::MIN as i32)); assert_eq!(u16::MIN.to_i64(), Some(u16::MIN as i64)); - assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as uint)); + assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as usize)); assert_eq!(u16::MIN.to_u8(), Some(u16::MIN as u8)); assert_eq!(u16::MIN.to_u16(), Some(u16::MIN as u16)); assert_eq!(u16::MIN.to_u32(), Some(u16::MIN as u32)); @@ -1412,12 +1459,12 @@ mod tests { #[test] fn test_cast_range_u32_min() { - assert_eq!(u32::MIN.to_int(), Some(u32::MIN as int)); + assert_eq!(u32::MIN.to_int(), Some(u32::MIN as isize)); assert_eq!(u32::MIN.to_i8(), Some(u32::MIN as i8)); assert_eq!(u32::MIN.to_i16(), Some(u32::MIN as i16)); assert_eq!(u32::MIN.to_i32(), Some(u32::MIN as i32)); assert_eq!(u32::MIN.to_i64(), Some(u32::MIN as i64)); - assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as uint)); + assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as usize)); assert_eq!(u32::MIN.to_u8(), Some(u32::MIN as u8)); assert_eq!(u32::MIN.to_u16(), Some(u32::MIN as u16)); assert_eq!(u32::MIN.to_u32(), Some(u32::MIN as u32)); @@ -1426,12 +1473,12 @@ mod tests { #[test] fn test_cast_range_u64_min() { - assert_eq!(u64::MIN.to_int(), Some(u64::MIN as int)); + assert_eq!(u64::MIN.to_int(), Some(u64::MIN as isize)); assert_eq!(u64::MIN.to_i8(), Some(u64::MIN as i8)); assert_eq!(u64::MIN.to_i16(), Some(u64::MIN as i16)); assert_eq!(u64::MIN.to_i32(), Some(u64::MIN as i32)); assert_eq!(u64::MIN.to_i64(), Some(u64::MIN as i64)); - assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as uint)); + assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as usize)); assert_eq!(u64::MIN.to_u8(), Some(u64::MIN as u8)); assert_eq!(u64::MIN.to_u16(), Some(u64::MIN as u16)); assert_eq!(u64::MIN.to_u32(), Some(u64::MIN as u32)); @@ -1440,26 +1487,26 @@ mod tests { #[test] fn test_cast_range_uint_max() { - assert_eq!(uint::MAX.to_int(), None); - assert_eq!(uint::MAX.to_i8(), None); - assert_eq!(uint::MAX.to_i16(), None); - assert_eq!(uint::MAX.to_i32(), None); - // uint::MAX.to_i64() is word-size specific - assert_eq!(uint::MAX.to_u8(), None); - assert_eq!(uint::MAX.to_u16(), None); - // uint::MAX.to_u32() is word-size specific - assert_eq!(uint::MAX.to_u64(), Some(uint::MAX as u64)); + assert_eq!(usize::MAX.to_int(), None); + assert_eq!(usize::MAX.to_i8(), None); + assert_eq!(usize::MAX.to_i16(), None); + assert_eq!(usize::MAX.to_i32(), None); + // usize::MAX.to_i64() is word-size specific + assert_eq!(usize::MAX.to_u8(), None); + assert_eq!(usize::MAX.to_u16(), None); + // usize::MAX.to_u32() is word-size specific + assert_eq!(usize::MAX.to_u64(), Some(usize::MAX as u64)); #[cfg(target_pointer_width = "32")] fn check_word_size() { - assert_eq!(uint::MAX.to_u32(), Some(uint::MAX as u32)); - assert_eq!(uint::MAX.to_i64(), Some(uint::MAX as i64)); + assert_eq!(usize::MAX.to_u32(), Some(usize::MAX as u32)); + assert_eq!(usize::MAX.to_i64(), Some(usize::MAX as i64)); } #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(uint::MAX.to_u32(), None); - assert_eq!(uint::MAX.to_i64(), None); + assert_eq!(usize::MAX.to_u32(), None); + assert_eq!(usize::MAX.to_i64(), None); } check_word_size(); @@ -1467,12 +1514,12 @@ mod tests { #[test] fn test_cast_range_u8_max() { - assert_eq!(u8::MAX.to_int(), Some(u8::MAX as int)); + assert_eq!(u8::MAX.to_int(), Some(u8::MAX as isize)); assert_eq!(u8::MAX.to_i8(), None); assert_eq!(u8::MAX.to_i16(), Some(u8::MAX as i16)); assert_eq!(u8::MAX.to_i32(), Some(u8::MAX as i32)); assert_eq!(u8::MAX.to_i64(), Some(u8::MAX as i64)); - assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as uint)); + assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as usize)); assert_eq!(u8::MAX.to_u8(), Some(u8::MAX as u8)); assert_eq!(u8::MAX.to_u16(), Some(u8::MAX as u16)); assert_eq!(u8::MAX.to_u32(), Some(u8::MAX as u32)); @@ -1481,12 +1528,12 @@ mod tests { #[test] fn test_cast_range_u16_max() { - assert_eq!(u16::MAX.to_int(), Some(u16::MAX as int)); + assert_eq!(u16::MAX.to_int(), Some(u16::MAX as isize)); assert_eq!(u16::MAX.to_i8(), None); assert_eq!(u16::MAX.to_i16(), None); assert_eq!(u16::MAX.to_i32(), Some(u16::MAX as i32)); assert_eq!(u16::MAX.to_i64(), Some(u16::MAX as i64)); - assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as uint)); + assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as usize)); assert_eq!(u16::MAX.to_u8(), None); assert_eq!(u16::MAX.to_u16(), Some(u16::MAX as u16)); assert_eq!(u16::MAX.to_u32(), Some(u16::MAX as u32)); @@ -1500,7 +1547,7 @@ mod tests { assert_eq!(u32::MAX.to_i16(), None); assert_eq!(u32::MAX.to_i32(), None); assert_eq!(u32::MAX.to_i64(), Some(u32::MAX as i64)); - assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as uint)); + assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as usize)); assert_eq!(u32::MAX.to_u8(), None); assert_eq!(u32::MAX.to_u16(), None); assert_eq!(u32::MAX.to_u32(), Some(u32::MAX as u32)); @@ -1513,7 +1560,7 @@ mod tests { #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(u32::MAX.to_int(), Some(u32::MAX as int)); + assert_eq!(u32::MAX.to_int(), Some(u32::MAX as isize)); } check_word_size(); @@ -1539,7 +1586,7 @@ mod tests { #[cfg(target_pointer_width = "64")] fn check_word_size() { - assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as uint)); + assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as usize)); } check_word_size(); @@ -1547,7 +1594,7 @@ mod tests { #[test] fn test_saturating_add_uint() { - use uint::MAX; + use usize::MAX; assert_eq!(3_usize.saturating_add(5_usize), 8_usize); assert_eq!(3_usize.saturating_add(MAX-1), MAX); assert_eq!(MAX.saturating_add(MAX), MAX); @@ -1556,7 +1603,7 @@ mod tests { #[test] fn test_saturating_sub_uint() { - use uint::MAX; + use usize::MAX; assert_eq!(5_usize.saturating_sub(3_usize), 2_usize); assert_eq!(3_usize.saturating_sub(5_usize), 0_usize); assert_eq!(0_usize.saturating_sub(1_usize), 0_usize); @@ -1565,7 +1612,7 @@ mod tests { #[test] fn test_saturating_add_int() { - use int::{MIN,MAX}; + use isize::{MIN,MAX}; assert_eq!(3.saturating_add(5), 8); assert_eq!(3.saturating_add(MAX-1), MAX); assert_eq!(MAX.saturating_add(MAX), MAX); @@ -1577,7 +1624,7 @@ mod tests { #[test] fn test_saturating_sub_int() { - use int::{MIN,MAX}; + use isize::{MIN,MAX}; assert_eq!(3.saturating_sub(5), -2); assert_eq!(MIN.saturating_sub(1), MIN); assert_eq!((-2).saturating_sub(MAX), MIN); @@ -1589,13 +1636,13 @@ mod tests { #[test] fn test_checked_add() { - let five_less = uint::MAX - 5; - assert_eq!(five_less.checked_add(0), Some(uint::MAX - 5)); - assert_eq!(five_less.checked_add(1), Some(uint::MAX - 4)); - assert_eq!(five_less.checked_add(2), Some(uint::MAX - 3)); - assert_eq!(five_less.checked_add(3), Some(uint::MAX - 2)); - assert_eq!(five_less.checked_add(4), Some(uint::MAX - 1)); - assert_eq!(five_less.checked_add(5), Some(uint::MAX)); + let five_less = usize::MAX - 5; + assert_eq!(five_less.checked_add(0), Some(usize::MAX - 5)); + assert_eq!(five_less.checked_add(1), Some(usize::MAX - 4)); + assert_eq!(five_less.checked_add(2), Some(usize::MAX - 3)); + assert_eq!(five_less.checked_add(3), Some(usize::MAX - 2)); + assert_eq!(five_less.checked_add(4), Some(usize::MAX - 1)); + assert_eq!(five_less.checked_add(5), Some(usize::MAX)); assert_eq!(five_less.checked_add(6), None); assert_eq!(five_less.checked_add(7), None); } @@ -1614,7 +1661,7 @@ mod tests { #[test] fn test_checked_mul() { - let third = uint::MAX / 3; + let third = usize::MAX / 3; assert_eq!(third.checked_mul(0), Some(0)); assert_eq!(third.checked_mul(1), Some(third)); assert_eq!(third.checked_mul(2), Some(third * 2)); @@ -1632,7 +1679,7 @@ mod tests { assert_eq!((3 as $T).is_power_of_two(), false); assert_eq!((4 as $T).is_power_of_two(), true); assert_eq!((5 as $T).is_power_of_two(), false); - assert!(($T::MAX / 2 + 1).is_power_of_two(), true); + assert_eq!(($T::MAX / 2 + 1).is_power_of_two(), true); } ) } @@ -1641,7 +1688,7 @@ mod tests { test_is_power_of_two!{ test_is_power_of_two_u16, u16 } test_is_power_of_two!{ test_is_power_of_two_u32, u32 } test_is_power_of_two!{ test_is_power_of_two_u64, u64 } - test_is_power_of_two!{ test_is_power_of_two_uint, uint } + test_is_power_of_two!{ test_is_power_of_two_uint, usize } macro_rules! test_next_power_of_two { ($test_name:ident, $T:ident) => ( @@ -1649,7 +1696,7 @@ mod tests { #![test] assert_eq!((0 as $T).next_power_of_two(), 1); let mut next_power = 1; - for i in range::<$T>(1, 40) { + for i in 1 as $T..40 { assert_eq!(i.next_power_of_two(), next_power); if i == next_power { next_power *= 2 } } @@ -1661,7 +1708,7 @@ mod tests { test_next_power_of_two! { test_next_power_of_two_u16, u16 } test_next_power_of_two! { test_next_power_of_two_u32, u32 } test_next_power_of_two! { test_next_power_of_two_u64, u64 } - test_next_power_of_two! { test_next_power_of_two_uint, uint } + test_next_power_of_two! { test_next_power_of_two_uint, usize } macro_rules! test_checked_next_power_of_two { ($test_name:ident, $T:ident) => ( @@ -1672,7 +1719,7 @@ mod tests { assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None); assert_eq!($T::MAX.checked_next_power_of_two(), None); let mut next_power = 1; - for i in range::<$T>(1, 40) { + for i in 1 as $T..40 { assert_eq!(i.checked_next_power_of_two(), Some(next_power)); if i == next_power { next_power *= 2 } } @@ -1684,10 +1731,10 @@ mod tests { test_checked_next_power_of_two! { test_checked_next_power_of_two_u16, u16 } test_checked_next_power_of_two! { test_checked_next_power_of_two_u32, u32 } test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 } - test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, uint } + test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize } #[derive(PartialEq, Debug)] - struct Value { x: int } + struct Value { x: isize } impl ToPrimitive for Value { fn to_i64(&self) -> Option { self.x.to_i64() } @@ -1695,8 +1742,8 @@ mod tests { } impl FromPrimitive for Value { - fn from_i64(n: i64) -> Option { Some(Value { x: n as int }) } - fn from_u64(n: u64) -> Option { Some(Value { x: n as int }) } + fn from_i64(n: i64) -> Option { Some(Value { x: n as isize }) } + fn from_u64(n: u64) -> Option { Some(Value { x: n as isize }) } } #[test] @@ -1734,7 +1781,7 @@ mod tests { #[test] fn test_pow() { - fn naive_pow(base: T, exp: uint) -> T { + fn naive_pow(base: T, exp: usize) -> T { let one: T = Int::one(); (0..exp).fold(one, |acc, _| acc * base) } @@ -1751,6 +1798,72 @@ mod tests { assert_pow!((8, 3 ) => 512); assert_pow!((2u64, 50) => 1125899906842624); } + + #[test] + fn test_uint_to_str_overflow() { + let mut u8_val: u8 = 255; + assert_eq!(u8_val.to_string(), "255"); + + u8_val = u8_val.wrapping_add(1); + assert_eq!(u8_val.to_string(), "0"); + + let mut u16_val: u16 = 65_535; + assert_eq!(u16_val.to_string(), "65535"); + + u16_val = u16_val.wrapping_add(1); + assert_eq!(u16_val.to_string(), "0"); + + let mut u32_val: u32 = 4_294_967_295; + assert_eq!(u32_val.to_string(), "4294967295"); + + u32_val = u32_val.wrapping_add(1); + assert_eq!(u32_val.to_string(), "0"); + + let mut u64_val: u64 = 18_446_744_073_709_551_615; + assert_eq!(u64_val.to_string(), "18446744073709551615"); + + u64_val = u64_val.wrapping_add(1); + assert_eq!(u64_val.to_string(), "0"); + } + + fn from_str(t: &str) -> Option { + ::str::FromStr::from_str(t).ok() + } + + #[test] + fn test_uint_from_str_overflow() { + let mut u8_val: u8 = 255; + assert_eq!(from_str::("255"), Some(u8_val)); + assert_eq!(from_str::("256"), None); + + u8_val = u8_val.wrapping_add(1); + assert_eq!(from_str::("0"), Some(u8_val)); + assert_eq!(from_str::("-1"), None); + + let mut u16_val: u16 = 65_535; + assert_eq!(from_str::("65535"), Some(u16_val)); + assert_eq!(from_str::("65536"), None); + + u16_val = u16_val.wrapping_add(1); + assert_eq!(from_str::("0"), Some(u16_val)); + assert_eq!(from_str::("-1"), None); + + let mut u32_val: u32 = 4_294_967_295; + assert_eq!(from_str::("4294967295"), Some(u32_val)); + assert_eq!(from_str::("4294967296"), None); + + u32_val = u32_val.wrapping_add(1); + assert_eq!(from_str::("0"), Some(u32_val)); + assert_eq!(from_str::("-1"), None); + + let mut u64_val: u64 = 18_446_744_073_709_551_615; + assert_eq!(from_str::("18446744073709551615"), Some(u64_val)); + assert_eq!(from_str::("18446744073709551616"), None); + + u64_val = u64_val.wrapping_add(1); + assert_eq!(from_str::("0"), Some(u64_val)); + assert_eq!(from_str::("-1"), None); + } } @@ -1764,6 +1877,6 @@ mod bench { #[bench] fn bench_pow_function(b: &mut Bencher) { let v = (0..1024).collect::>(); - b.iter(|| {v.iter().fold(0, |old, new| old.pow(*new));}); + b.iter(|| {v.iter().fold(0, |old, new| old.pow(*new as u32));}); } } diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index f6d05f961e..ea869ebae1 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -11,22 +11,21 @@ // ignore-lexer-test FIXME #15679 #![allow(missing_docs)] +#![allow(deprecated)] use self::ExponentFormat::*; use self::SignificantDigits::*; use self::SignFormat::*; -use char::{self, CharExt}; +use char; use num::{self, Int, Float, ToPrimitive}; use num::FpCategory as Fp; use ops::FnMut; -use slice::SliceExt; -use str::StrExt; use string::String; use vec::Vec; /// A flag that specifies whether to use exponential (scientific) notation. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum ExponentFormat { /// Do not use exponential notation. ExpNone, @@ -41,7 +40,7 @@ pub enum ExponentFormat { /// The number of digits used for emitting the fractional part of a number, if /// any. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum SignificantDigits { /// All calculable digits will be printed. /// @@ -51,14 +50,14 @@ pub enum SignificantDigits { /// At most the given number of digits will be printed, truncating any /// trailing zeroes. - DigMax(uint), + DigMax(usize), /// Precisely the given number of digits will be printed. - DigExact(uint) + DigExact(usize) } /// How to emit the sign of a number. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum SignFormat { /// No sign will be printed. The exponent sign will also be emitted. SignNone, @@ -89,7 +88,7 @@ pub enum SignFormat { /// # Panics /// /// - Panics if `radix` < 2 or `radix` > 36. -fn int_to_str_bytes_common(num: T, radix: uint, sign: SignFormat, mut f: F) where +fn int_to_str_bytes_common(num: T, radix: usize, sign: SignFormat, mut f: F) where T: Int, F: FnMut(u8), { @@ -104,7 +103,7 @@ fn int_to_str_bytes_common(num: T, radix: uint, sign: SignFormat, mut f: F // This is just for integral types, the largest of which is a u64. The // smallest base that we can have is 2, so the most number of digits we're // ever going to have is 64 - let mut buf = [0u8; 64]; + let mut buf = [0; 64]; let mut cur = 0; // Loop at least once to make sure at least a `0` gets emitted. @@ -218,13 +217,13 @@ pub fn float_to_str_bytes_common( let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity()); let mut buf = Vec::new(); - let radix_gen: T = num::cast(radix as int).unwrap(); + let radix_gen: T = num::cast(radix as isize).unwrap(); let (num, exp) = match exp_format { - ExpNone => (num, 0i32), + ExpNone => (num, 0), ExpDec | ExpBin => { if num == _0 { - (num, 0i32) + (num, 0) } else { let (exp, exp_base) = match exp_format { ExpDec => (num.abs().log10().floor(), num::cast::(10.0f64).unwrap()), @@ -253,7 +252,7 @@ pub fn float_to_str_bytes_common( deccum = deccum / radix_gen; deccum = deccum.trunc(); - buf.push(char::from_digit(current_digit.to_int().unwrap() as u32, radix) + buf.push(char::from_digit(current_digit.to_isize().unwrap() as u32, radix) .unwrap() as u8); // No more digits to calculate for the non-fractional part -> break @@ -310,7 +309,7 @@ pub fn float_to_str_bytes_common( let current_digit = deccum.trunc().abs(); buf.push(char::from_digit( - current_digit.to_int().unwrap() as u32, radix).unwrap() as u8); + current_digit.to_isize().unwrap() as u32, radix).unwrap() as u8); // Decrease the deccumulator one fractional digit at a time deccum = deccum.fract(); @@ -330,28 +329,28 @@ pub fn float_to_str_bytes_common( let extra_digit = ascii2value(buf.pop().unwrap()); if extra_digit >= radix / 2 { // -> need to round - let mut i: int = buf.len() as int - 1; + let mut i: isize = buf.len() as isize - 1; loop { // If reached left end of number, have to // insert additional digit: if i < 0 - || buf[i as uint] == b'-' - || buf[i as uint] == b'+' { - buf.insert((i + 1) as uint, value2ascii(1)); + || buf[i as usize] == b'-' + || buf[i as usize] == b'+' { + buf.insert((i + 1) as usize, value2ascii(1)); break; } // Skip the '.' - if buf[i as uint] == b'.' { i -= 1; continue; } + if buf[i as usize] == b'.' { i -= 1; continue; } // Either increment the digit, // or set to 0 if max and carry the 1. - let current_digit = ascii2value(buf[i as uint]); + let current_digit = ascii2value(buf[i as usize]); if current_digit < (radix - 1) { - buf[i as uint] = value2ascii(current_digit+1); + buf[i as usize] = value2ascii(current_digit+1); break; } else { - buf[i as uint] = value2ascii(0); + buf[i as usize] = value2ascii(0); i -= 1; } } @@ -422,37 +421,38 @@ pub fn float_to_str_common( // Some constants for from_str_bytes_common's input validation, // they define minimum radix values for which the character is a valid digit. -static DIGIT_P_RADIX: u32 = ('p' as u32) - ('a' as u32) + 11; -static DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11; +const DIGIT_P_RADIX: u32 = ('p' as u32) - ('a' as u32) + 11; +const DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11; #[cfg(test)] mod tests { + use core::num::wrapping::WrappingOps; use string::ToString; #[test] fn test_int_to_str_overflow() { - let mut i8_val: i8 = 127_i8; + let mut i8_val: i8 = 127; assert_eq!(i8_val.to_string(), "127"); - i8_val += 1 as i8; + i8_val = i8_val.wrapping_add(1); assert_eq!(i8_val.to_string(), "-128"); - let mut i16_val: i16 = 32_767_i16; + let mut i16_val: i16 = 32_767; assert_eq!(i16_val.to_string(), "32767"); - i16_val += 1 as i16; + i16_val = i16_val.wrapping_add(1); assert_eq!(i16_val.to_string(), "-32768"); - let mut i32_val: i32 = 2_147_483_647_i32; + let mut i32_val: i32 = 2_147_483_647; assert_eq!(i32_val.to_string(), "2147483647"); - i32_val += 1 as i32; + i32_val = i32_val.wrapping_add(1); assert_eq!(i32_val.to_string(), "-2147483648"); - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + let mut i64_val: i64 = 9_223_372_036_854_775_807; assert_eq!(i64_val.to_string(), "9223372036854775807"); - i64_val += 1 as i64; + i64_val = i64_val.wrapping_add(1); assert_eq!(i64_val.to_string(), "-9223372036854775808"); } } @@ -462,85 +462,85 @@ mod bench { #![allow(deprecated)] // rand extern crate test; - mod uint { + mod usize { use super::test::Bencher; use rand::{weak_rng, Rng}; use std::fmt; #[inline] - fn to_string(x: uint, base: u8) { + fn to_string(x: usize, base: u8) { format!("{}", fmt::radix(x, base)); } #[bench] fn to_str_bin(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 2); }) + b.iter(|| { to_string(rng.gen::(), 2); }) } #[bench] fn to_str_oct(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 8); }) + b.iter(|| { to_string(rng.gen::(), 8); }) } #[bench] fn to_str_dec(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 10); }) + b.iter(|| { to_string(rng.gen::(), 10); }) } #[bench] fn to_str_hex(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 16); }) + b.iter(|| { to_string(rng.gen::(), 16); }) } #[bench] fn to_str_base_36(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 36); }) + b.iter(|| { to_string(rng.gen::(), 36); }) } } - mod int { + mod isize { use super::test::Bencher; use rand::{weak_rng, Rng}; use std::fmt; #[inline] - fn to_string(x: int, base: u8) { + fn to_string(x: isize, base: u8) { format!("{}", fmt::radix(x, base)); } #[bench] fn to_str_bin(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 2); }) + b.iter(|| { to_string(rng.gen::(), 2); }) } #[bench] fn to_str_oct(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 8); }) + b.iter(|| { to_string(rng.gen::(), 8); }) } #[bench] fn to_str_dec(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 10); }) + b.iter(|| { to_string(rng.gen::(), 10); }) } #[bench] fn to_str_hex(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 16); }) + b.iter(|| { to_string(rng.gen::(), 16); }) } #[bench] fn to_str_base_36(b: &mut Bencher) { let mut rng = weak_rng(); - b.iter(|| { to_string(rng.gen::(), 36); }) + b.iter(|| { to_string(rng.gen::(), 36); }) } } diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs deleted file mode 100644 index c7b491381f..0000000000 --- a/src/libstd/num/uint.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Deprecated: replaced by `usize`. -//! -//! The rollout of the new type will gradually take place over the -//! alpha cycle along with the development of clearer conventions -//! around integer types. - -#![unstable(feature = "std_misc")] -#![deprecated(since = "1.0.0", reason = "replaced by usize")] - -pub use core::uint::{BITS, BYTES, MIN, MAX}; - -uint_module! { uint } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 8d4f0344be..c9e6a8f66d 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -48,68 +48,6 @@ mod tests { assert_eq!(FromStrRadix::from_str_radix("Z", 10).ok(), None::<$T>); assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$T>); } - - #[test] - fn test_uint_to_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert_eq!(u8_val.to_string(), "255"); - - u8_val += 1 as u8; - assert_eq!(u8_val.to_string(), "0"); - - let mut u16_val: u16 = 65_535_u16; - assert_eq!(u16_val.to_string(), "65535"); - - u16_val += 1 as u16; - assert_eq!(u16_val.to_string(), "0"); - - let mut u32_val: u32 = 4_294_967_295_u32; - assert_eq!(u32_val.to_string(), "4294967295"); - - u32_val += 1 as u32; - assert_eq!(u32_val.to_string(), "0"); - - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert_eq!(u64_val.to_string(), "18446744073709551615"); - - u64_val += 1 as u64; - assert_eq!(u64_val.to_string(), "0"); - } - - #[test] - fn test_uint_from_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert_eq!(from_str::("255"), Some(u8_val)); - assert_eq!(from_str::("256"), None); - - u8_val += 1 as u8; - assert_eq!(from_str::("0"), Some(u8_val)); - assert_eq!(from_str::("-1"), None); - - let mut u16_val: u16 = 65_535_u16; - assert_eq!(from_str::("65535"), Some(u16_val)); - assert_eq!(from_str::("65536"), None); - - u16_val += 1 as u16; - assert_eq!(from_str::("0"), Some(u16_val)); - assert_eq!(from_str::("-1"), None); - - let mut u32_val: u32 = 4_294_967_295_u32; - assert_eq!(from_str::("4294967295"), Some(u32_val)); - assert_eq!(from_str::("4294967296"), None); - - u32_val += 1 as u32; - assert_eq!(from_str::("0"), Some(u32_val)); - assert_eq!(from_str::("-1"), None); - - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert_eq!(from_str::("18446744073709551615"), Some(u64_val)); - assert_eq!(from_str::("18446744073709551616"), None); - - u64_val += 1 as u64; - assert_eq!(from_str::("0"), Some(u64_val)); - assert_eq!(from_str::("-1"), None); - } } ) } diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs index 2d2d0d8b33..68aa7e4770 100644 --- a/src/libstd/old_io/buffered.rs +++ b/src/libstd/old_io/buffered.rs @@ -15,12 +15,11 @@ use cmp; use fmt; use old_io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; -use iter::{IteratorExt, ExactSizeIterator, repeat}; +use iter::{Iterator, ExactSizeIterator, repeat}; use ops::Drop; use option::Option; use option::Option::{Some, None}; use result::Result::Ok; -use slice::{SliceExt}; use slice; use vec::Vec; @@ -31,10 +30,12 @@ use vec::Vec; /// `BufferedReader` performs large, infrequent reads on the underlying /// `Reader` and maintains an in-memory buffer of the results. /// -/// # Example +/// # Examples /// -/// ```rust -/// use std::old_io::{BufferedReader, File}; +/// ``` +/// # #![feature(old_io, old_path)] +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let file = File::open(&Path::new("message.txt")); /// let mut reader = BufferedReader::new(file); @@ -48,8 +49,8 @@ use vec::Vec; pub struct BufferedReader { inner: R, buf: Vec, - pos: uint, - cap: uint, + pos: usize, + cap: usize, } #[stable(feature = "rust1", since = "1.0.0")] @@ -62,7 +63,7 @@ impl fmt::Debug for BufferedReader where R: fmt::Debug { impl BufferedReader { /// Creates a new `BufferedReader` with the specified buffer capacity - pub fn with_capacity(cap: uint, inner: R) -> BufferedReader { + pub fn with_capacity(cap: usize, inner: R) -> BufferedReader { BufferedReader { inner: inner, // We can't use the same trick here as we do for BufferedWriter, @@ -103,21 +104,21 @@ impl Buffer for BufferedReader { Ok(&self.buf[self.pos..self.cap]) } - fn consume(&mut self, amt: uint) { + fn consume(&mut self, amt: usize) { self.pos += amt; assert!(self.pos <= self.cap); } } impl Reader for BufferedReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { if self.pos == self.cap && buf.len() >= self.buf.len() { return self.inner.read(buf); } let nread = { let available = try!(self.fill_buf()); let nread = cmp::min(available.len(), buf.len()); - slice::bytes::copy_memory(buf, &available[..nread]); + slice::bytes::copy_memory(&available[..nread], buf); nread }; self.pos += nread; @@ -134,10 +135,12 @@ impl Reader for BufferedReader { /// /// This writer will be flushed when it is dropped. /// -/// # Example +/// # Examples /// -/// ```rust -/// use std::old_io::{BufferedWriter, File}; +/// ``` +/// # #![feature(old_io, old_path)] +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let file = File::create(&Path::new("message.txt")).unwrap(); /// let mut writer = BufferedWriter::new(file); @@ -145,14 +148,14 @@ impl Reader for BufferedReader { /// writer.write_str("hello, world").unwrap(); /// writer.flush().unwrap(); /// ``` -pub struct BufferedWriter { +pub struct BufferedWriter { inner: Option, buf: Vec, - pos: uint + pos: usize } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for BufferedWriter where W: fmt::Debug { +impl fmt::Debug for BufferedWriter where W: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}", self.inner.as_ref().unwrap(), self.pos, self.buf.len()) @@ -161,7 +164,7 @@ impl fmt::Debug for BufferedWriter where W: fmt::Debug { impl BufferedWriter { /// Creates a new `BufferedWriter` with the specified buffer capacity - pub fn with_capacity(cap: uint, inner: W) -> BufferedWriter { + pub fn with_capacity(cap: usize, inner: W) -> BufferedWriter { // It's *much* faster to create an uninitialized buffer than it is to // fill everything in with 0. This buffer is entirely an implementation // detail and is never exposed, so we're safe to not initialize @@ -222,7 +225,7 @@ impl Writer for BufferedWriter { self.inner.as_mut().unwrap().write_all(buf) } else { let dst = &mut self.buf[self.pos..]; - slice::bytes::copy_memory(dst, buf); + slice::bytes::copy_memory(buf, dst); self.pos += buf.len(); Ok(()) } @@ -247,12 +250,12 @@ impl Drop for BufferedWriter { /// `'\n'`) is detected. /// /// This writer will be flushed when it is dropped. -pub struct LineBufferedWriter { +pub struct LineBufferedWriter { inner: BufferedWriter, } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for LineBufferedWriter where W: fmt::Debug { +impl fmt::Debug for LineBufferedWriter where W: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}", self.inner.inner, self.inner.pos, self.inner.buf.len()) @@ -296,17 +299,17 @@ impl Writer for LineBufferedWriter { fn flush(&mut self) -> IoResult<()> { self.inner.flush() } } -struct InternalBufferedWriter(BufferedWriter); +struct InternalBufferedWriter(BufferedWriter); -impl InternalBufferedWriter { +impl InternalBufferedWriter { fn get_mut<'a>(&'a mut self) -> &'a mut BufferedWriter { let InternalBufferedWriter(ref mut w) = *self; return w; } } -impl Reader for InternalBufferedWriter { - fn read(&mut self, buf: &mut [u8]) -> IoResult { +impl Reader for InternalBufferedWriter { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.get_mut().inner.as_mut().unwrap().read(buf) } } @@ -320,11 +323,13 @@ impl Reader for InternalBufferedWriter { /// /// The output half will be flushed when this stream is dropped. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// # #![allow(unused_must_use)] -/// use std::old_io::{BufferedStream, File}; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let file = File::open(&Path::new("message.txt")); /// let mut stream = BufferedStream::new(file); @@ -338,12 +343,12 @@ impl Reader for InternalBufferedWriter { /// Err(e) => println!("error reading: {}", e) /// } /// ``` -pub struct BufferedStream { +pub struct BufferedStream { inner: BufferedReader> } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for BufferedStream where S: fmt::Debug { +impl fmt::Debug for BufferedStream where S: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let reader = &self.inner; let writer = &self.inner.inner.0; @@ -357,7 +362,7 @@ impl fmt::Debug for BufferedStream where S: fmt::Debug { impl BufferedStream { /// Creates a new buffered stream with explicitly listed capacities for the /// reader/writer buffer. - pub fn with_capacities(reader_cap: uint, writer_cap: uint, inner: S) + pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S) -> BufferedStream { let writer = BufferedWriter::with_capacity(writer_cap, inner); let internal_writer = InternalBufferedWriter(writer); @@ -402,11 +407,11 @@ impl BufferedStream { impl Buffer for BufferedStream { fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() } - fn consume(&mut self, amt: uint) { self.inner.consume(amt) } + fn consume(&mut self, amt: usize) { self.inner.consume(amt) } } impl Reader for BufferedStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } } @@ -423,7 +428,7 @@ impl Writer for BufferedStream { #[cfg(test)] mod test { extern crate test; - use old_io; + use old_io::{self, Reader, Writer, Buffer, BufferPrelude}; use prelude::v1::*; use super::*; use super::super::{IoResult, EndOfFile}; @@ -437,7 +442,7 @@ mod test { pub struct NullStream; impl Reader for NullStream { - fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { Err(old_io::standard_error(old_io::EndOfFile)) } } @@ -448,11 +453,11 @@ mod test { /// A dummy reader intended at testing short-reads propagation. pub struct ShortReader { - lengths: Vec, + lengths: Vec, } impl Reader for ShortReader { - fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { if self.lengths.is_empty() { Err(old_io::standard_error(old_io::EndOfFile)) } else { @@ -505,37 +510,37 @@ mod test { writer.write_all(&[0, 1]).unwrap(); let b: &[_] = &[]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.write_all(&[2]).unwrap(); let b: &[_] = &[0, 1]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.write_all(&[3]).unwrap(); - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.flush().unwrap(); let a: &[_] = &[0, 1, 2, 3]; - assert_eq!(a, &writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[..]); writer.write_all(&[4]).unwrap(); writer.write_all(&[5]).unwrap(); - assert_eq!(a, &writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[..]); writer.write_all(&[6]).unwrap(); let a: &[_] = &[0, 1, 2, 3, 4, 5]; - assert_eq!(a, &writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[..]); writer.write_all(&[7, 8]).unwrap(); let a: &[_] = &[0, 1, 2, 3, 4, 5, 6]; - assert_eq!(a, &writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[..]); writer.write_all(&[9, 10, 11]).unwrap(); let a: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; - assert_eq!(a, &writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[..]); writer.flush().unwrap(); - assert_eq!(a, &writer.get_ref()[]); + assert_eq!(a, &writer.get_ref()[..]); } #[test] @@ -543,7 +548,7 @@ mod test { let mut w = BufferedWriter::with_capacity(3, Vec::new()); w.write_all(&[0, 1]).unwrap(); let a: &[_] = &[]; - assert_eq!(a, &w.get_ref()[]); + assert_eq!(&w.get_ref()[..], a); let w = w.into_inner(); let a: &[_] = &[0, 1]; assert_eq!(a, &w[..]); @@ -560,7 +565,7 @@ mod test { } impl old_io::Reader for S { - fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { Err(old_io::standard_error(old_io::EndOfFile)) } } @@ -588,21 +593,21 @@ mod test { let mut writer = LineBufferedWriter::new(Vec::new()); writer.write_all(&[0]).unwrap(); let b: &[_] = &[]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.write_all(&[1]).unwrap(); - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.flush().unwrap(); let b: &[_] = &[0, 1]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.write_all(&[0, b'\n', 1, b'\n', 2]).unwrap(); let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n']; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.flush().unwrap(); let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n', 2]; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); writer.write_all(&[3, b'\n']).unwrap(); let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']; - assert_eq!(&writer.get_ref()[], b); + assert_eq!(&writer.get_ref()[..], b); } #[test] @@ -642,14 +647,14 @@ mod test { #[test] fn read_char_buffered() { - let buf = [195u8, 159u8]; + let buf = [195, 159]; let mut reader = BufferedReader::with_capacity(1, &buf[..]); assert_eq!(reader.read_char(), Ok('ß')); } #[test] fn test_chars() { - let buf = [195u8, 159u8, b'a']; + let buf = [195, 159, b'a']; let mut reader = BufferedReader::with_capacity(1, &buf[..]); let mut it = reader.chars(); assert_eq!(it.next(), Some(Ok('ß'))); @@ -658,7 +663,7 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn dont_panic_in_drop_on_panicked_flush() { struct FailFlushWriter; diff --git a/src/libstd/old_io/comm_adapters.rs b/src/libstd/old_io/comm_adapters.rs index 207d3d3916..5ebf931e95 100644 --- a/src/libstd/old_io/comm_adapters.rs +++ b/src/libstd/old_io/comm_adapters.rs @@ -14,23 +14,24 @@ use sync::mpsc::{Sender, Receiver}; use old_io; use option::Option::{None, Some}; use result::Result::{Ok, Err}; -use slice::{bytes, SliceExt}; +use slice::bytes; use super::{Buffer, Reader, Writer, IoResult}; use vec::Vec; /// Allows reading from a rx. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(old_io)] /// use std::sync::mpsc::channel; -/// use std::old_io::ChanReader; +/// use std::old_io::*; /// /// let (tx, rx) = channel(); /// # drop(tx); /// let mut reader = ChanReader::new(rx); /// -/// let mut buf = [0u8; 100]; +/// let mut buf = [0; 100]; /// match reader.read(&mut buf) { /// Ok(nread) => println!("Read {} bytes", nread), /// Err(e) => println!("read error: {}", e), @@ -38,7 +39,7 @@ use vec::Vec; /// ``` pub struct ChanReader { buf: Vec, // A buffer of bytes received but not consumed. - pos: uint, // How many of the buffered bytes have already be consumed. + pos: usize, // How many of the buffered bytes have already be consumed. rx: Receiver>, // The Receiver to pull data from. closed: bool, // Whether the channel this Receiver connects to has been closed. } @@ -76,21 +77,21 @@ impl Buffer for ChanReader { } } - fn consume(&mut self, amt: uint) { + fn consume(&mut self, amt: usize) { self.pos += amt; assert!(self.pos <= self.buf.len()); } } impl Reader for ChanReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let mut num_read = 0; loop { let count = match self.fill_buf().ok() { Some(src) => { let dst = &mut buf[num_read..]; let count = cmp::min(src.len(), dst.len()); - bytes::copy_memory(dst, &src[..count]); + bytes::copy_memory(&src[..count], dst); count }, None => 0, @@ -111,12 +112,13 @@ impl Reader for ChanReader { /// Allows writing to a tx. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(old_io, io)] /// # #![allow(unused_must_use)] /// use std::sync::mpsc::channel; -/// use std::old_io::ChanWriter; +/// use std::old_io::*; /// /// let (tx, rx) = channel(); /// # drop(rx); @@ -160,22 +162,22 @@ mod test { use sync::mpsc::channel; use super::*; - use old_io; + use old_io::{self, Reader, Writer, Buffer}; use thread; #[test] fn test_rx_reader() { let (tx, rx) = channel(); thread::spawn(move|| { - tx.send(vec![1u8, 2u8]).unwrap(); + tx.send(vec![1, 2]).unwrap(); tx.send(vec![]).unwrap(); - tx.send(vec![3u8, 4u8]).unwrap(); - tx.send(vec![5u8, 6u8]).unwrap(); - tx.send(vec![7u8, 8u8]).unwrap(); + tx.send(vec![3, 4]).unwrap(); + tx.send(vec![5, 6]).unwrap(); + tx.send(vec![7, 8]).unwrap(); }); let mut reader = ChanReader::new(rx); - let mut buf = [0u8; 3]; + let mut buf = [0; 3]; assert_eq!(Ok(0), reader.read(&mut [])); @@ -233,7 +235,7 @@ mod test { let mut writer = ChanWriter::new(tx); writer.write_be_u32(42).unwrap(); - let wanted = vec![0u8, 0u8, 0u8, 42u8]; + let wanted = vec![0, 0, 0, 42]; let got = thread::scoped(move|| { rx.recv().unwrap() }).join(); assert_eq!(wanted, got); diff --git a/src/libstd/old_io/extensions.rs b/src/libstd/old_io/extensions.rs index c2a6c515ac..73973d0db2 100644 --- a/src/libstd/old_io/extensions.rs +++ b/src/libstd/old_io/extensions.rs @@ -11,6 +11,10 @@ //! Utility mixins that apply to all Readers and Writers #![allow(missing_docs)] +#![unstable(feature = "old_io")] +#![deprecated(since = "1.0.0", + reason = "functionality will be removed with no immediate \ + replacement")] // FIXME: Not sure how this should be structured // FIXME: Iteration should probably be considered separately @@ -22,9 +26,7 @@ use num::Int; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; -use ptr::PtrExt; use result::Result::{Ok, Err}; -use slice::SliceExt; /// An iterator that reads a single byte on each iteration, /// until `.read_byte()` returns `EndOfFile`. @@ -79,7 +81,7 @@ impl<'r, R: Reader> Iterator for Bytes<'r, R> { /// * `f`: A callback that receives the value. /// /// This function returns the value returned by the callback, for convenience. -pub fn u64_to_le_bytes(n: u64, size: uint, f: F) -> T where +pub fn u64_to_le_bytes(n: u64, size: usize, f: F) -> T where F: FnOnce(&[u8]) -> T, { use mem::transmute; @@ -97,7 +99,7 @@ pub fn u64_to_le_bytes(n: u64, size: uint, f: F) -> T where let mut i = size; let mut n = n; while i > 0 { - bytes.push((n & 255_u64) as u8); + bytes.push((n & 255) as u8); n >>= 8; i -= 1; } @@ -120,7 +122,7 @@ pub fn u64_to_le_bytes(n: u64, size: uint, f: F) -> T where /// * `f`: A callback that receives the value. /// /// This function returns the value returned by the callback, for convenience. -pub fn u64_to_be_bytes(n: u64, size: uint, f: F) -> T where +pub fn u64_to_be_bytes(n: u64, size: usize, f: F) -> T where F: FnOnce(&[u8]) -> T, { use mem::transmute; @@ -156,9 +158,8 @@ pub fn u64_to_be_bytes(n: u64, size: uint, f: F) -> T where /// less, or task panic occurs. If this is less than 8, then only /// that many bytes are parsed. For example, if `size` is 4, then a /// 32-bit value is parsed. -pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { - use ptr::{copy_nonoverlapping_memory}; - use slice::SliceExt; +pub fn u64_from_be_bytes(data: &[u8], start: usize, size: usize) -> u64 { + use ptr::{copy_nonoverlapping}; assert!(size <= 8); @@ -166,11 +167,11 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { panic!("index out of bounds"); } - let mut buf = [0u8; 8]; + let mut buf = [0; 8]; unsafe { - let ptr = data.as_ptr().offset(start as int); + let ptr = data.as_ptr().offset(start as isize); let out = buf.as_mut_ptr(); - copy_nonoverlapping_memory(out.offset((8 - size) as int), ptr, size); + copy_nonoverlapping(ptr, out.offset((8 - size) as isize), size); (*(out as *const u64)).to_be() } } @@ -178,15 +179,15 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { #[cfg(test)] mod test { use prelude::v1::*; - use old_io; + use old_io::{self, Reader, Writer}; use old_io::{MemReader, BytesReader}; struct InitialZeroByteReader { - count: int, + count: isize, } impl Reader for InitialZeroByteReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { if self.count == 0 { self.count = 1; Ok(0) @@ -200,7 +201,7 @@ mod test { struct EofReader; impl Reader for EofReader { - fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { Err(old_io::standard_error(old_io::EndOfFile)) } } @@ -208,17 +209,17 @@ mod test { struct ErroringReader; impl Reader for ErroringReader { - fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, _: &mut [u8]) -> old_io::IoResult { Err(old_io::standard_error(old_io::InvalidInput)) } } struct PartialReader { - count: int, + count: isize, } impl Reader for PartialReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { if self.count == 0 { self.count = 1; buf[0] = 10; @@ -233,11 +234,11 @@ mod test { } struct ErroringLaterReader { - count: int, + count: isize, } impl Reader for ErroringLaterReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { if self.count == 0 { self.count = 1; buf[0] = 10; @@ -249,11 +250,11 @@ mod test { } struct ThreeChunkReader { - count: int, + count: isize, } impl Reader for ThreeChunkReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { if self.count == 0 { self.count = 1; buf[0] = 10; @@ -328,7 +329,7 @@ mod test { fn read_bytes() { let mut reader = MemReader::new(vec!(10, 11, 12, 13)); let bytes = reader.read_exact(4).unwrap(); - assert!(bytes == vec!(10, 11, 12, 13)); + assert_eq!(bytes, [10, 11, 12, 13]); } #[test] @@ -337,7 +338,7 @@ mod test { count: 0, }; let bytes = reader.read_exact(4).unwrap(); - assert!(bytes == vec!(10, 11, 12, 13)); + assert_eq!(bytes, [10, 11, 12, 13]); } #[test] @@ -351,7 +352,7 @@ mod test { let mut reader = MemReader::new(vec![10, 11, 12, 13]); let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_ok()); - assert!(buf == vec![8, 9, 10, 11, 12, 13]); + assert_eq!(buf, [8, 9, 10, 11, 12, 13]); } #[test] @@ -361,7 +362,7 @@ mod test { }; let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_ok()); - assert!(buf == vec![8, 9, 10, 11, 12, 13]); + assert_eq!(buf, [8, 9, 10, 11, 12, 13]); } #[test] @@ -369,7 +370,7 @@ mod test { let mut reader = MemReader::new(vec![10, 11]); let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_err()); - assert!(buf == vec![8, 9, 10, 11]); + assert_eq!(buf, [8, 9, 10, 11]); } #[test] @@ -379,7 +380,7 @@ mod test { }; let mut buf = vec![8, 9]; assert!(reader.push_at_least(4, 4, &mut buf).is_err()); - assert!(buf == vec![8, 9, 10]); + assert_eq!(buf, [8, 9, 10]); } #[test] @@ -388,17 +389,17 @@ mod test { count: 0, }; let buf = reader.read_to_end().unwrap(); - assert!(buf == vec!(10, 11, 12, 13)); + assert_eq!(buf, [10, 11, 12, 13]); } #[test] - #[should_fail] + #[should_panic] fn read_to_end_error() { let mut reader = ThreeChunkReader { count: 0, }; let buf = reader.read_to_end().unwrap(); - assert!(buf == vec!(10, 11)); + assert_eq!(buf, [10, 11]); } #[test] @@ -518,8 +519,9 @@ mod bench { ({ use super::u64_from_be_bytes; - let data = (0u8..$stride*100+$start_index).collect::>(); - let mut sum = 0u64; + let len = ($stride as u8).wrapping_mul(100).wrapping_add($start_index); + let data = (0..len).collect::>(); + let mut sum = 0; $b.iter(|| { let mut i = $start_index; while i < data.len() { diff --git a/src/libstd/old_io/fs.rs b/src/libstd/old_io/fs.rs index 4e9c1b3605..509daa46ef 100644 --- a/src/libstd/old_io/fs.rs +++ b/src/libstd/old_io/fs.rs @@ -27,12 +27,14 @@ //! the metadata of a file. This includes getting the `stat` information, //! reading off particular bits of it, etc. //! -//! # Example +//! # Examples //! //! ```rust +//! # #![feature(old_io, io, old_path)] //! # #![allow(unused_must_use)] //! use std::old_io::fs::PathExtensions; -//! use std::old_io::{File, fs}; +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let path = Path::new("foo.txt"); //! @@ -64,7 +66,6 @@ use option::Option::{Some, None}; use old_path::{Path, GenericPath}; use old_path; use result::Result::{Err, Ok}; -use slice::SliceExt; use string::String; use vec::Vec; @@ -82,10 +83,12 @@ use sys_common; /// attempted against it for which its underlying file descriptor was not /// configured at creation time, via the `FileAccess` parameter to /// `File::open_mode()`. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::File")] +#[unstable(feature = "old_io")] pub struct File { fd: fs_imp::FileDesc, path: Path, - last_nread: int, + last_nread: isize, } impl sys_common::AsInner for File { @@ -94,14 +97,18 @@ impl sys_common::AsInner for File { } } +#[deprecated(since = "1.0.0", reason = "replaced with std::fs")] +#[unstable(feature = "old_io")] impl File { /// Open a file at `path` in the mode specified by the `mode` and `access` /// arguments /// - /// # Example + /// # Examples /// - /// ```rust,should_fail - /// use std::old_io::{File, Open, ReadWrite}; + /// ```rust,should_panic + /// # #![feature(old_io, old_path)] + /// use std::old_io::*; + /// use std::old_path::Path; /// /// let p = Path::new("/some/file/path.txt"); /// @@ -133,6 +140,8 @@ impl File { /// * Attempting to open a file with a `FileAccess` that the user lacks /// permissions for /// * Filesystem-level errors (full disk, etc) + #[deprecated(since = "1.0.0", reason = "replaced with std::fs::OpenOptions")] + #[unstable(feature = "old_io")] pub fn open_mode(path: &Path, mode: FileMode, access: FileAccess) -> IoResult { @@ -167,13 +176,17 @@ impl File { /// /// For more information, see the `File::open_mode` function. /// - /// # Example + /// # Examples /// - /// ```rust - /// use std::old_io::File; + /// ``` + /// # #![feature(old_io, old_path)] + /// use std::old_io::*; + /// use std::old_path::Path; /// /// let contents = File::open(&Path::new("foo.txt")).read_to_end(); /// ``` + #[deprecated(since = "1.0.0", reason = "replaced with std::fs::File::open")] + #[unstable(feature = "old_io")] pub fn open(path: &Path) -> IoResult { File::open_mode(path, Open, Read) } @@ -184,23 +197,29 @@ impl File { /// /// For more information, see the `File::open_mode` function. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(old_io, old_path, io)] /// # #![allow(unused_must_use)] - /// use std::old_io::File; + /// use std::old_io::*; + /// use std::old_path::Path; /// /// let mut f = File::create(&Path::new("foo.txt")); /// f.write(b"This is a sample file"); /// # drop(f); /// # ::std::old_io::fs::unlink(&Path::new("foo.txt")); /// ``` + #[deprecated(since = "1.0.0", reason = "replaced with std::fs::File::create")] + #[unstable(feature = "old_io")] pub fn create(path: &Path) -> IoResult { File::open_mode(path, Truncate, Write) .update_desc("couldn't create file") } /// Returns the original path that was used to open this file. + #[deprecated(since = "1.0.0", reason = "replaced with std::fs")] + #[unstable(feature = "old_io")] pub fn path<'a>(&'a self) -> &'a Path { &self.path } @@ -208,6 +227,8 @@ impl File { /// Synchronizes all modifications to this file to its permanent storage /// device. This will flush any internal buffers necessary to perform this /// operation. + #[deprecated(since = "1.0.0", reason = "replaced with std::fs")] + #[unstable(feature = "old_io")] pub fn fsync(&mut self) -> IoResult<()> { self.fd.fsync() .update_err("couldn't fsync file", @@ -218,6 +239,8 @@ impl File { /// file metadata to the filesystem. This is intended for use cases that /// must synchronize content, but don't need the metadata on disk. The goal /// of this method is to reduce disk operations. + #[deprecated(since = "1.0.0", reason = "replaced with std::fs")] + #[unstable(feature = "old_io")] pub fn datasync(&mut self) -> IoResult<()> { self.fd.datasync() .update_err("couldn't datasync file", @@ -232,6 +255,8 @@ impl File { /// be shrunk. If it is greater than the current file's size, then the file /// will be extended to `size` and have all of the intermediate data filled /// in with 0s. + #[deprecated(since = "1.0.0", reason = "replaced with std::fs")] + #[unstable(feature = "old_io")] pub fn truncate(&mut self, size: i64) -> IoResult<()> { self.fd.truncate(size) .update_err("couldn't truncate file", |e| @@ -247,11 +272,15 @@ impl File { /// until you have attempted to read past the end of the file, so if /// you've read _exactly_ the number of bytes in the file, this will /// return `false`, not `true`. + #[deprecated(since = "1.0.0", reason = "replaced with std::fs")] + #[unstable(feature = "old_io")] pub fn eof(&self) -> bool { self.last_nread == 0 } /// Queries information about the underlying file. + #[deprecated(since = "1.0.0", reason = "replaced with std::fs")] + #[unstable(feature = "old_io")] pub fn stat(&self) -> IoResult { self.fd.fstat() .update_err("couldn't fstat file", |e| @@ -261,11 +290,13 @@ impl File { /// Unlink a file from the underlying filesystem. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// # #![allow(unused_must_use)] -/// use std::old_io::fs; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let p = Path::new("/some/file/path.txt"); /// fs::unlink(&p); @@ -280,6 +311,8 @@ impl File { /// This function will return an error if `path` points to a directory, if the /// user lacks permissions to remove the file, or if some other filesystem-level /// error occurs. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::remove_file")] +#[unstable(feature = "old_io")] pub fn unlink(path: &Path) -> IoResult<()> { fs_imp::unlink(path) .update_err("couldn't unlink path", |e| @@ -290,10 +323,12 @@ pub fn unlink(path: &Path) -> IoResult<()> { /// directory, etc. This function will traverse symlinks to query /// information about the destination file. /// -/// # Example +/// # Examples /// -/// ```rust -/// use std::old_io::fs; +/// ``` +/// # #![feature(old_io, old_path)] +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let p = Path::new("/some/file/path.txt"); /// match fs::stat(&p) { @@ -307,6 +342,8 @@ pub fn unlink(path: &Path) -> IoResult<()> { /// This function will return an error if the user lacks the requisite permissions /// to perform a `stat` call on the given `path` or if there is no entry in the /// filesystem at the provided path. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::metadata")] +#[unstable(feature = "old_io")] pub fn stat(path: &Path) -> IoResult { fs_imp::stat(path) .update_err("couldn't stat path", |e| @@ -321,6 +358,7 @@ pub fn stat(path: &Path) -> IoResult { /// # Error /// /// See `stat` +#[unstable(feature = "old_fs")] pub fn lstat(path: &Path) -> IoResult { fs_imp::lstat(path) .update_err("couldn't lstat path", |e| @@ -329,11 +367,13 @@ pub fn lstat(path: &Path) -> IoResult { /// Rename a file or directory to a new name. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// # #![allow(unused_must_use)] -/// use std::old_io::fs; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// fs::rename(&Path::new("foo"), &Path::new("bar")); /// ``` @@ -343,6 +383,8 @@ pub fn lstat(path: &Path) -> IoResult { /// This function will return an error if the provided `from` doesn't exist, if /// the process lacks permissions to view the contents, or if some other /// intermittent I/O error occurs. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::rename")] +#[unstable(feature = "old_io")] pub fn rename(from: &Path, to: &Path) -> IoResult<()> { fs_imp::rename(from, to) .update_err("couldn't rename path", |e| @@ -355,11 +397,13 @@ pub fn rename(from: &Path, to: &Path) -> IoResult<()> { /// Note that if `from` and `to` both point to the same file, then the file /// will likely get truncated by this operation. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// # #![allow(unused_must_use)] -/// use std::old_io::fs; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt")); /// ``` @@ -377,6 +421,8 @@ pub fn rename(from: &Path, to: &Path) -> IoResult<()> { /// Note that this copy is not atomic in that once the destination is /// ensured to not exist, there is nothing preventing the destination from /// being created and then destroyed by this operation. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::copy")] +#[unstable(feature = "old_io")] pub fn copy(from: &Path, to: &Path) -> IoResult<()> { fn update_err(result: IoResult, from: &Path, to: &Path) -> IoResult { result.update_err("couldn't copy path", |e| { @@ -403,12 +449,14 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> { /// Changes the permission mode bits found on a file or a directory. This /// function takes a mask from the `io` module /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// # #![allow(unused_must_use)] /// use std::old_io; -/// use std::old_io::fs; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// fs::chmod(&Path::new("file.txt"), old_io::USER_FILE); /// fs::chmod(&Path::new("file.txt"), old_io::USER_READ | old_io::USER_WRITE); @@ -421,14 +469,17 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> { /// This function will return an error if the provided `path` doesn't exist, if /// the process lacks permissions to change the attributes of the file, or if /// some other I/O error is encountered. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::set_permissions")] +#[unstable(feature = "old_io")] pub fn chmod(path: &Path, mode: old_io::FilePermission) -> IoResult<()> { - fs_imp::chmod(path, mode.bits() as uint) + fs_imp::chmod(path, mode.bits() as usize) .update_err("couldn't chmod path", |e| format!("{}; path={}; mode={:?}", e, path.display(), mode)) } /// Change the user and group owners of a file at the specified path. -pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { +#[unstable(feature = "old_fs")] +pub fn chown(path: &Path, uid: isize, gid: isize) -> IoResult<()> { fs_imp::chown(path, uid, gid) .update_err("couldn't chown path", |e| format!("{}; path={}; uid={}; gid={}", e, path.display(), uid, gid)) @@ -437,6 +488,8 @@ pub fn chown(path: &Path, uid: int, gid: int) -> IoResult<()> { /// Creates a new hard link on the filesystem. The `dst` path will be a /// link pointing to the `src` path. Note that systems often require these /// two paths to both be located on the same filesystem. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::hard_link")] +#[unstable(feature = "old_io")] pub fn link(src: &Path, dst: &Path) -> IoResult<()> { fs_imp::link(src, dst) .update_err("couldn't link path", |e| @@ -445,6 +498,8 @@ pub fn link(src: &Path, dst: &Path) -> IoResult<()> { /// Creates a new symbolic link on the filesystem. The `dst` path will be a /// symlink pointing to the `src` path. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::soft_link")] +#[unstable(feature = "old_io")] pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { fs_imp::symlink(src, dst) .update_err("couldn't symlink path", |e| @@ -457,6 +512,8 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { /// /// This function will return an error on failure. Failure conditions include /// reading a file that does not exist or reading a file that is not a symlink. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::read_link")] +#[unstable(feature = "old_io")] pub fn readlink(path: &Path) -> IoResult { fs_imp::readlink(path) .update_err("couldn't resolve symlink for path", |e| @@ -465,12 +522,14 @@ pub fn readlink(path: &Path) -> IoResult { /// Create a new, empty directory at the provided path /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path, old_fs)] /// # #![allow(unused_must_use)] /// use std::old_io; -/// use std::old_io::fs; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let p = Path::new("/some/dir"); /// fs::mkdir(&p, old_io::USER_RWX); @@ -480,19 +539,22 @@ pub fn readlink(path: &Path) -> IoResult { /// /// This function will return an error if the user lacks permissions to make a /// new directory at the provided `path`, or if the directory already exists. +#[unstable(feature = "old_fs")] pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { - fs_imp::mkdir(path, mode.bits() as uint) + fs_imp::mkdir(path, mode.bits() as usize) .update_err("couldn't create directory", |e| format!("{}; path={}; mode={}", e, path.display(), mode)) } /// Remove an existing, empty directory /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// # #![allow(unused_must_use)] -/// use std::old_io::fs; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// let p = Path::new("/some/dir"); /// fs::rmdir(&p); @@ -502,6 +564,8 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> { /// /// This function will return an error if the user lacks permissions to remove /// the directory at the provided `path`, or if the directory isn't empty. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::remove_dir")] +#[unstable(feature = "old_io")] pub fn rmdir(path: &Path) -> IoResult<()> { fs_imp::rmdir(path) .update_err("couldn't remove directory", |e| @@ -510,12 +574,14 @@ pub fn rmdir(path: &Path) -> IoResult<()> { /// Retrieve a vector containing all entries within a provided directory /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, old_path)] /// use std::old_io::fs::PathExtensions; -/// use std::old_io::fs; /// use std::old_io; +/// use std::old_io::*; +/// use std::old_path::Path; /// /// // one possible implementation of fs::walk_dir only visiting files /// fn visit_dirs(dir: &Path, cb: &mut F) -> old_io::IoResult<()> where @@ -542,6 +608,8 @@ pub fn rmdir(path: &Path) -> IoResult<()> { /// This function will return an error if the provided `path` doesn't exist, if /// the process lacks permissions to view the contents or if the `path` points /// at a non-directory file +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::read_dir")] +#[unstable(feature = "old_io")] pub fn readdir(path: &Path) -> IoResult> { fs_imp::readdir(path) .update_err("couldn't read directory", @@ -552,6 +620,8 @@ pub fn readdir(path: &Path) -> IoResult> { /// rooted at `path`. The path given will not be iterated over, and this will /// perform iteration in some top-down order. The contents of unreadable /// subdirectories are ignored. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::walk_dir")] +#[unstable(feature = "old_io")] pub fn walk_dir(path: &Path) -> IoResult { Ok(Directories { stack: try!(readdir(path).update_err("couldn't walk directory", @@ -561,6 +631,8 @@ pub fn walk_dir(path: &Path) -> IoResult { /// An iterator that walks over a directory #[derive(Clone)] +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::ReadDir")] +#[unstable(feature = "old_io")] pub struct Directories { stack: Vec, } @@ -590,6 +662,7 @@ impl Iterator for Directories { /// # Error /// /// See `fs::mkdir`. +#[unstable(feature = "old_fs")] pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> { // tjc: if directory exists but with different permissions, // should we return false? @@ -627,6 +700,8 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) -> IoResult<()> { /// # Error /// /// See `file::unlink` and `fs::readdir` +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::remove_dir_all")] +#[unstable(feature = "old_io")] pub fn rmdir_recursive(path: &Path) -> IoResult<()> { let mut rm_stack = Vec::new(); rm_stack.push(path.clone()); @@ -689,6 +764,8 @@ pub fn rmdir_recursive(path: &Path) -> IoResult<()> { /// `atime` and its modification time set to `mtime`. The times specified should /// be in milliseconds. // FIXME(#10301) these arguments should not be u64 +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::set_file_times")] +#[unstable(feature = "old_io")] pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> { fs_imp::utime(path, atime, mtime) .update_err("couldn't change_file_times", |e| @@ -696,7 +773,7 @@ pub fn change_file_times(path: &Path, atime: u64, mtime: u64) -> IoResult<()> { } impl Reader for File { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { fn update_err(result: IoResult, file: &File) -> IoResult { result.update_err("couldn't read file", |e| format!("{}; path={}", @@ -707,10 +784,10 @@ impl Reader for File { match result { Ok(read) => { - self.last_nread = read as int; + self.last_nread = read as isize; match read { 0 => update_err(Err(standard_error(old_io::EndOfFile)), self), - _ => Ok(read as uint) + _ => Ok(read as usize) } }, Err(e) => Err(e) @@ -748,6 +825,8 @@ impl Seek for File { } /// Utility methods for paths. +#[deprecated(since = "1.0.0", reason = "replaced with std::fs::PathExt")] +#[unstable(feature = "old_io")] pub trait PathExtensions { /// Get information on the file, directory, etc at this path. /// @@ -826,7 +905,8 @@ fn access_string(access: FileAccess) -> &'static str { mod test { use prelude::v1::*; use old_io::{SeekSet, SeekCur, SeekEnd, Read, Open, ReadWrite, FileType}; - use old_io; + use old_io::{self, Reader, Writer, Seek}; + use old_path::{Path, GenericPath}; use str; use old_io::fs::*; @@ -871,7 +951,8 @@ mod test { pub fn tmpdir() -> TempDir { use os; use rand; - let ret = os::tmpdir().join(format!("rust-{}", rand::random::())); + let temp = Path::new(::env::temp_dir().to_str().unwrap()); + let ret = temp.join(format!("rust-{}", rand::random::())); check!(old_io::fs::mkdir(&ret, old_io::USER_RWX)); TempDir(ret) } @@ -889,7 +970,7 @@ mod test { let mut read_stream = File::open_mode(filename, Open, Read); let mut read_buf = [0; 1028]; let read_str = match check!(read_stream.read(&mut read_buf)) { - -1|0 => panic!("shouldn't happen"), + 0 => panic!("shouldn't happen"), n => str::from_utf8(&read_buf[..n]).unwrap().to_string() }; assert_eq!(read_str, message); @@ -1110,7 +1191,7 @@ mod test { check!(w.write(msg)); } let files = check!(readdir(dir)); - let mut mem = [0u8; 4]; + let mut mem = [0; 4]; for f in &files { { let n = f.filestem_str(); @@ -1142,13 +1223,13 @@ mod test { check!(File::create(&dir2.join("14"))); let mut files = check!(walk_dir(dir)); - let mut cur = [0u8; 2]; + let mut cur = [0; 2]; for f in files { let stem = f.filestem_str().unwrap(); let root = stem.as_bytes()[0] - b'0'; let name = stem.as_bytes()[1] - b'0'; - assert!(cur[root as uint] < name); - cur[root as uint] = name; + assert!(cur[root as usize] < name); + cur[root as usize] = name; } check!(rmdir_recursive(dir)); @@ -1452,7 +1533,7 @@ mod test { b"foobar\0\0\0\0".to_vec()); // Truncate to a smaller length, don't seek, and then write something. - // Ensure that the intermediate zeroes are all filled in (we're seeked + // Ensure that the intermediate zeroes are all filled in (we have `seek`ed // past the end of the file). check!(file.truncate(2)); assert_eq!(check!(file.stat()).size, 2); @@ -1553,13 +1634,13 @@ mod test { use rand::{StdRng, Rng}; let mut bytes = [0; 1024]; - StdRng::new().ok().unwrap().fill_bytes(&mut bytes); + StdRng::new().unwrap().fill_bytes(&mut bytes); let tmpdir = tmpdir(); check!(File::create(&tmpdir.join("test")).write(&bytes)); let actual = check!(File::open(&tmpdir.join("test")).read_to_end()); - assert!(actual == bytes.as_slice()); + assert!(actual == &bytes[..]); } #[test] diff --git a/src/libstd/old_io/mem.rs b/src/libstd/old_io/mem.rs index 1fd527014a..c92e74fbc5 100644 --- a/src/libstd/old_io/mem.rs +++ b/src/libstd/old_io/mem.rs @@ -17,12 +17,12 @@ use option::Option::None; use result::Result::{Err, Ok}; use old_io; use old_io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult}; -use slice::{self, SliceExt}; +use slice; use vec::Vec; -const BUF_CAPACITY: uint = 128; +const BUF_CAPACITY: usize = 128; -fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult { +fn combine(seek: SeekStyle, cur: usize, end: usize, offset: i64) -> IoResult { // compute offset as signed and clamp to prevent overflow let pos = match seek { old_io::SeekSet => 0, @@ -51,16 +51,17 @@ impl Writer for Vec { /// Writes to an owned, growable byte vector /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, io)] /// # #![allow(unused_must_use)] -/// use std::old_io::MemWriter; +/// use std::old_io::*; /// /// let mut w = MemWriter::new(); /// w.write(&[0, 1, 2]); /// -/// assert_eq!(w.into_inner(), vec!(0, 1, 2)); +/// assert_eq!(w.into_inner(), [0, 1, 2]); /// ``` #[unstable(feature = "io")] #[deprecated(since = "1.0.0", @@ -81,7 +82,7 @@ impl MemWriter { /// Create a new `MemWriter`, allocating at least `n` bytes for /// the internal buffer. #[inline] - pub fn with_capacity(n: uint) -> MemWriter { + pub fn with_capacity(n: usize) -> MemWriter { MemWriter::from_vec(Vec::with_capacity(n)) } /// Create a new `MemWriter` that will append to an existing `Vec`. @@ -102,6 +103,7 @@ impl MemWriter { impl Writer for MemWriter { #[inline] + #[allow(deprecated)] fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { self.buf.push_all(buf); Ok(()) @@ -110,19 +112,20 @@ impl Writer for MemWriter { /// Reads from an owned byte vector /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io)] /// # #![allow(unused_must_use)] -/// use std::old_io::MemReader; +/// use std::old_io::*; /// /// let mut r = MemReader::new(vec!(0, 1, 2)); /// -/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2)); +/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); /// ``` pub struct MemReader { buf: Vec, - pos: uint + pos: usize } impl MemReader { @@ -157,7 +160,7 @@ impl MemReader { impl Reader for MemReader { #[inline] - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { if self.eof() { return Err(old_io::standard_error(old_io::EndOfFile)) } let write_len = min(buf.len(), self.buf.len() - self.pos); @@ -165,7 +168,7 @@ impl Reader for MemReader { let input = &self.buf[self.pos.. self.pos + write_len]; let output = &mut buf[..write_len]; assert_eq!(input.len(), output.len()); - slice::bytes::copy_memory(output, input); + slice::bytes::copy_memory(input, output); } self.pos += write_len; assert!(self.pos <= self.buf.len()); @@ -181,7 +184,7 @@ impl Seek for MemReader { #[inline] fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { let new = try!(combine(style, self.pos, self.buf.len(), pos)); - self.pos = new as uint; + self.pos = new as usize; Ok(()) } } @@ -197,19 +200,19 @@ impl Buffer for MemReader { } #[inline] - fn consume(&mut self, amt: uint) { self.pos += amt; } + fn consume(&mut self, amt: usize) { self.pos += amt; } } impl<'a> Reader for &'a [u8] { #[inline] - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { if self.is_empty() { return Err(old_io::standard_error(old_io::EndOfFile)); } let write_len = min(buf.len(), self.len()); { let input = &self[..write_len]; let output = &mut buf[.. write_len]; - slice::bytes::copy_memory(output, input); + slice::bytes::copy_memory(input, output); } *self = &self[write_len..]; @@ -229,7 +232,7 @@ impl<'a> Buffer for &'a [u8] { } #[inline] - fn consume(&mut self, amt: uint) { + fn consume(&mut self, amt: usize) { *self = &self[amt..]; } } @@ -240,11 +243,12 @@ impl<'a> Buffer for &'a [u8] { /// If a write will not fit in the buffer, it returns an error and does not /// write any data. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io, io)] /// # #![allow(unused_must_use)] -/// use std::old_io::BufWriter; +/// use std::old_io::*; /// /// let mut buf = [0; 4]; /// { @@ -255,7 +259,7 @@ impl<'a> Buffer for &'a [u8] { /// ``` pub struct BufWriter<'a> { buf: &'a mut [u8], - pos: uint + pos: usize } impl<'a> BufWriter<'a> { @@ -283,13 +287,13 @@ impl<'a> Writer for BufWriter<'a> { let src_len = src.len(); if dst_len >= src_len { - slice::bytes::copy_memory(dst, src); + slice::bytes::copy_memory(src, dst); self.pos += src_len; Ok(()) } else { - slice::bytes::copy_memory(dst, &src[..dst_len]); + slice::bytes::copy_memory(&src[..dst_len], dst); self.pos += dst_len; @@ -305,27 +309,28 @@ impl<'a> Seek for BufWriter<'a> { #[inline] fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { let new = try!(combine(style, self.pos, self.buf.len(), pos)); - self.pos = min(new as uint, self.buf.len()); + self.pos = min(new as usize, self.buf.len()); Ok(()) } } /// Reads from a fixed-size byte slice /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(old_io)] /// # #![allow(unused_must_use)] -/// use std::old_io::BufReader; +/// use std::old_io::*; /// /// let buf = [0, 1, 2, 3]; /// let mut r = BufReader::new(&buf); /// -/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]); +/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]); /// ``` pub struct BufReader<'a> { buf: &'a [u8], - pos: uint + pos: usize } impl<'a> BufReader<'a> { @@ -347,7 +352,7 @@ impl<'a> BufReader<'a> { impl<'a> Reader for BufReader<'a> { #[inline] - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { if self.eof() { return Err(old_io::standard_error(old_io::EndOfFile)) } let write_len = min(buf.len(), self.buf.len() - self.pos); @@ -355,7 +360,7 @@ impl<'a> Reader for BufReader<'a> { let input = &self.buf[self.pos.. self.pos + write_len]; let output = &mut buf[..write_len]; assert_eq!(input.len(), output.len()); - slice::bytes::copy_memory(output, input); + slice::bytes::copy_memory(input, output); } self.pos += write_len; assert!(self.pos <= self.buf.len()); @@ -371,7 +376,7 @@ impl<'a> Seek for BufReader<'a> { #[inline] fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> { let new = try!(combine(style, self.pos, self.buf.len(), pos)); - self.pos = new as uint; + self.pos = new as usize; Ok(()) } } @@ -387,15 +392,15 @@ impl<'a> Buffer for BufReader<'a> { } #[inline] - fn consume(&mut self, amt: uint) { self.pos += amt; } + fn consume(&mut self, amt: usize) { self.pos += amt; } } #[cfg(test)] mod test { - extern crate "test" as test_crate; - use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek}; - use prelude::v1::{Ok, Err, range, Vec, Buffer, AsSlice, SliceExt}; - use prelude::v1::IteratorExt; + extern crate test as test_crate; + use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek, Buffer}; + use prelude::v1::{Ok, Err, Vec}; + use prelude::v1::Iterator; use old_io; use iter::repeat; use self::test_crate::Bencher; @@ -504,8 +509,8 @@ mod test { assert_eq!(&buf[..3], b); assert!(reader.read(&mut buf).is_err()); let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); - assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); - assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7)); + assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]); + assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]); assert!(reader.read(&mut buf).is_err()); } @@ -530,8 +535,8 @@ mod test { assert_eq!(&buf[..3], b); assert!(reader.read(&mut buf).is_err()); let mut reader = &mut &*in_buf; - assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); - assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7)); + assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]); + assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]); assert!(reader.read(&mut buf).is_err()); } @@ -557,8 +562,8 @@ mod test { assert_eq!(&buf[..3], b); assert!(reader.read(&mut buf).is_err()); let mut reader = BufReader::new(&in_buf); - assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3)); - assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7)); + assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]); + assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]); assert!(reader.read(&mut buf).is_err()); } @@ -658,7 +663,7 @@ mod test { assert_eq!(buf, b); } - fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) { + fn do_bench_mem_writer(b: &mut Bencher, times: usize, len: usize) { let src: Vec = repeat(5).take(len).collect(); b.bytes = (times * len) as u64; @@ -739,7 +744,7 @@ mod test { wr.write(&[5; 10]).unwrap(); } } - assert_eq!(buf.as_slice(), [5; 100].as_slice()); + assert_eq!(&buf[..], &[5; 100][..]); }); } diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index fc3deb67f4..98ff6e82c6 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -48,7 +48,9 @@ //! * Read lines from stdin //! //! ```rust +//! # #![feature(old_io, old_path)] //! use std::old_io as io; +//! use std::old_io::*; //! //! let mut stdin = io::stdin(); //! for line in stdin.lock().lines() { @@ -59,7 +61,9 @@ //! * Read a complete file //! //! ```rust -//! use std::old_io::File; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let contents = File::open(&Path::new("message.txt")).read_to_end(); //! ``` @@ -67,8 +71,10 @@ //! * Write a line to a file //! //! ```rust +//! # #![feature(old_io, old_path)] //! # #![allow(unused_must_use)] -//! use std::old_io::File; +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let mut file = File::create(&Path::new("message.txt")); //! file.write_all(b"hello, file!\n"); @@ -79,8 +85,9 @@ //! * Iterate over the lines of a file //! //! ```rust,no_run -//! use std::old_io::BufferedReader; -//! use std::old_io::File; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let path = Path::new("message.txt"); //! let mut file = BufferedReader::new(File::open(&path)); @@ -92,8 +99,9 @@ //! * Pull the lines of a file into a vector of strings //! //! ```rust,no_run -//! use std::old_io::BufferedReader; -//! use std::old_io::File; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! let path = Path::new("message.txt"); //! let mut file = BufferedReader::new(File::open(&path)); @@ -103,8 +111,9 @@ //! * Make a simple TCP client connection and request //! //! ```rust +//! # #![feature(old_io)] //! # #![allow(unused_must_use)] -//! use std::old_io::TcpStream; +//! use std::old_io::*; //! //! # // connection doesn't fail if a server is running on 8080 //! # // locally, we still want to be type checking this code, so lets @@ -119,11 +128,11 @@ //! * Make a simple TCP server //! //! ```rust +//! # #![feature(old_io)] //! # fn main() { } //! # fn foo() { //! # #![allow(dead_code)] -//! use std::old_io::{TcpListener, TcpStream}; -//! use std::old_io::{Acceptor, Listener}; +//! use std::old_io::*; //! use std::thread; //! //! let listener = TcpListener::bind("127.0.0.1:80"); @@ -184,8 +193,10 @@ //! If you wanted to handle the error though you might write: //! //! ```rust +//! # #![feature(old_io, old_path)] //! # #![allow(unused_must_use)] -//! use std::old_io::File; +//! use std::old_io::*; +//! use std::old_path::Path; //! //! match File::create(&Path::new("diary.txt")).write_all(b"Met a girl.\n") { //! Ok(()) => (), // succeeded @@ -218,7 +229,9 @@ //! If you wanted to read several `u32`s from a file and return their product: //! //! ```rust -//! use std::old_io::{File, IoResult}; +//! # #![feature(old_io, old_path)] +//! use std::old_io::*; +//! use std::old_path::Path; //! //! fn file_product(p: &Path) -> IoResult { //! let mut f = File::open(p); @@ -240,30 +253,32 @@ #![unstable(feature = "old_io")] #![deny(unused_must_use)] +#![allow(deprecated)] // seriously this is all deprecated +#![allow(unused_imports)] +#![deprecated(since = "1.0.0", + reasons = "APIs have been replaced with new I/O modules such as \ + std::{io, fs, net, process}")] pub use self::SeekStyle::*; pub use self::FileMode::*; pub use self::FileAccess::*; pub use self::IoErrorKind::*; -use char::CharExt; use default::Default; use error::Error; use fmt; use isize; -use iter::{Iterator, IteratorExt}; +use iter::Iterator; use marker::{PhantomFn, Sized}; use mem::transmute; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; -use os; +use sys::os; use boxed::Box; use result::Result; use result::Result::{Ok, Err}; use sys; -use slice::SliceExt; -use str::StrExt; use str; use string::String; use usize; @@ -311,7 +326,7 @@ pub mod test; /// The default buffer size for various I/O operations // libuv recommends 64k buffers to maximize throughput // https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA -const DEFAULT_BUF_SIZE: uint = 1024 * 64; +const DEFAULT_BUF_SIZE: usize = 1024 * 64; /// A convenient typedef of the return value of any I/O action. pub type IoResult = Result; @@ -341,8 +356,7 @@ impl IoError { pub fn from_errno(errno: i32, detail: bool) -> IoError { let mut err = sys::decode_error(errno as i32); if detail && err.kind == OtherIoError { - err.detail = Some(os::error_string(errno).chars() - .map(|c| c.to_lowercase()).collect()) + err.detail = Some(os::error_string(errno).to_lowercase()); } err } @@ -377,7 +391,7 @@ impl Error for IoError { } /// A list specifying general categories of I/O error. -#[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum IoErrorKind { /// Any I/O error not part of this list. OtherIoError, @@ -427,7 +441,7 @@ pub enum IoErrorKind { /// /// The payload contained as part of this variant is the number of bytes /// which are known to have been successfully written. - ShortWrite(uint), + ShortWrite(usize), /// The Reader returned 0 bytes from `read()` too many times. NoProgress, } @@ -469,7 +483,7 @@ impl UpdateIoError for IoResult { } } -static NO_PROGRESS_LIMIT: uint = 1000; +static NO_PROGRESS_LIMIT: usize = 1000; /// A trait for objects which are byte-oriented streams. Readers are defined by /// one method, `read`. This function will block until data is available, @@ -497,7 +511,7 @@ pub trait Reader { /// /// When implementing this method on a new Reader, you are strongly encouraged /// not to return 0 if you can avoid it. - fn read(&mut self, buf: &mut [u8]) -> IoResult; + fn read(&mut self, buf: &mut [u8]) -> IoResult; // Convenient helper methods based on the above methods @@ -512,7 +526,7 @@ pub trait Reader { /// /// If an error occurs at any point, that error is returned, and no further /// bytes are read. - fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult { + fn read_at_least(&mut self, min: usize, buf: &mut [u8]) -> IoResult { if min > buf.len() { return Err(IoError { detail: Some(String::from_str("the buffer is too short")), @@ -556,7 +570,7 @@ pub trait Reader { /// /// If an error occurs during this I/O operation, then it is returned /// as `Err(IoError)`. See `read()` for more details. - fn push(&mut self, len: uint, buf: &mut Vec) -> IoResult { + fn push(&mut self, len: usize, buf: &mut Vec) -> IoResult { let start_len = buf.len(); buf.reserve(len); @@ -580,7 +594,7 @@ pub trait Reader { /// /// If an error occurs at any point, that error is returned, and no further /// bytes are read. - fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec) -> IoResult { + fn push_at_least(&mut self, min: usize, len: usize, buf: &mut Vec) -> IoResult { if min > len { return Err(IoError { detail: Some(String::from_str("the buffer is too short")), @@ -615,7 +629,7 @@ pub trait Reader { /// have already been consumed from the underlying reader, and they are lost /// (not returned as part of the error). If this is unacceptable, then it is /// recommended to use the `push_at_least` or `read` methods. - fn read_exact(&mut self, len: uint) -> IoResult> { + fn read_exact(&mut self, len: usize) -> IoResult> { let mut buf = Vec::with_capacity(len); match self.push_at_least(len, len, &mut buf) { Ok(_) => Ok(buf), @@ -665,10 +679,10 @@ pub trait Reader { /// Reads `n` little-endian unsigned integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult { + fn read_le_uint_n(&mut self, nbytes: usize) -> IoResult { assert!(nbytes > 0 && nbytes <= 8); - let mut val = 0u64; + let mut val = 0; let mut pos = 0; let mut i = nbytes; while i > 0 { @@ -682,17 +696,17 @@ pub trait Reader { /// Reads `n` little-endian signed integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_le_int_n(&mut self, nbytes: uint) -> IoResult { + fn read_le_int_n(&mut self, nbytes: usize) -> IoResult { self.read_le_uint_n(nbytes).map(|i| extend_sign(i, nbytes)) } /// Reads `n` big-endian unsigned integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult { + fn read_be_uint_n(&mut self, nbytes: usize) -> IoResult { assert!(nbytes > 0 && nbytes <= 8); - let mut val = 0u64; + let mut val = 0; let mut i = nbytes; while i > 0 { i -= 1; @@ -704,36 +718,36 @@ pub trait Reader { /// Reads `n` big-endian signed integer bytes. /// /// `n` must be between 1 and 8, inclusive. - fn read_be_int_n(&mut self, nbytes: uint) -> IoResult { + fn read_be_int_n(&mut self, nbytes: usize) -> IoResult { self.read_be_uint_n(nbytes).map(|i| extend_sign(i, nbytes)) } /// Reads a little-endian unsigned integer. /// /// The number of bytes returned is system-dependent. - fn read_le_uint(&mut self) -> IoResult { - self.read_le_uint_n(usize::BYTES).map(|i| i as uint) + fn read_le_uint(&mut self) -> IoResult { + self.read_le_uint_n(usize::BYTES as usize).map(|i| i as usize) } /// Reads a little-endian integer. /// /// The number of bytes returned is system-dependent. - fn read_le_int(&mut self) -> IoResult { - self.read_le_int_n(isize::BYTES).map(|i| i as int) + fn read_le_int(&mut self) -> IoResult { + self.read_le_int_n(isize::BYTES as usize).map(|i| i as isize) } /// Reads a big-endian unsigned integer. /// /// The number of bytes returned is system-dependent. - fn read_be_uint(&mut self) -> IoResult { - self.read_be_uint_n(usize::BYTES).map(|i| i as uint) + fn read_be_uint(&mut self) -> IoResult { + self.read_be_uint_n(usize::BYTES as usize).map(|i| i as usize) } /// Reads a big-endian integer. /// /// The number of bytes returned is system-dependent. - fn read_be_int(&mut self) -> IoResult { - self.read_be_int_n(isize::BYTES).map(|i| i as int) + fn read_be_int(&mut self) -> IoResult { + self.read_be_int_n(isize::BYTES as usize).map(|i| i as isize) } /// Reads a big-endian `u64`. @@ -905,14 +919,14 @@ impl BytesReader for T { } impl<'a> Reader for Box { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let reader: &mut Reader = &mut **self; reader.read(buf) } } impl<'a> Reader for &'a mut (Reader+'a) { - fn read(&mut self, buf: &mut [u8]) -> IoResult { (*self).read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { (*self).read(buf) } } /// Returns a slice of `v` between `start` and `end`. @@ -926,16 +940,15 @@ impl<'a> Reader for &'a mut (Reader+'a) { /// `start` > `end`. // Private function here because we aren't sure if we want to expose this as // API yet. If so, it should be a method on Vec. -unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec, start: uint, end: uint) -> &'a mut [T] { - use raw::Slice; - use ptr::PtrExt; +unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec, start: usize, end: usize) -> &'a mut [T] { + use slice; assert!(start <= end); assert!(end <= v.capacity()); - transmute(Slice { - data: v.as_ptr().offset(start as int), - len: end - start - }) + slice::from_raw_parts_mut( + v.as_mut_ptr().offset(start as isize), + end - start + ) } /// A `RefReader` is a struct implementing `Reader` which contains a reference @@ -944,8 +957,9 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec, start: uint, end: uint) - /// # Examples /// /// ``` +/// # #![feature(old_io)] /// use std::old_io as io; -/// use std::old_io::ByRefReader; +/// use std::old_io::*; /// use std::old_io::util::LimitReader; /// /// fn process_input(r: R) {} @@ -966,15 +980,15 @@ pub struct RefReader<'a, R:'a> { } impl<'a, R: Reader> Reader for RefReader<'a, R> { - fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } } impl<'a, R: Buffer> Buffer for RefReader<'a, R> { fn fill_buf(&mut self) -> IoResult<&[u8]> { self.inner.fill_buf() } - fn consume(&mut self, amt: uint) { self.inner.consume(amt) } + fn consume(&mut self, amt: usize) { self.inner.consume(amt) } } -fn extend_sign(val: u64, nbytes: uint) -> i64 { +fn extend_sign(val: u64, nbytes: usize) -> i64 { let shift = (8 - nbytes) * 8; (val << shift) as i64 >> shift } @@ -1076,45 +1090,45 @@ pub trait Writer { /// Write a single char, encoded as UTF-8. #[inline] fn write_char(&mut self, c: char) -> IoResult<()> { - let mut buf = [0u8; 4]; + let mut buf = [0; 4]; let n = c.encode_utf8(&mut buf).unwrap_or(0); self.write_all(&buf[..n]) } - /// Write the result of passing n through `int::to_str_bytes`. + /// Write the result of passing n through `isize::to_str_bytes`. #[inline] - fn write_int(&mut self, n: int) -> IoResult<()> { + fn write_int(&mut self, n: isize) -> IoResult<()> { write!(self, "{}", n) } - /// Write the result of passing n through `uint::to_str_bytes`. + /// Write the result of passing n through `usize::to_str_bytes`. #[inline] - fn write_uint(&mut self, n: uint) -> IoResult<()> { + fn write_uint(&mut self, n: usize) -> IoResult<()> { write!(self, "{}", n) } - /// Write a little-endian uint (number of bytes depends on system). + /// Write a little-endian usize (number of bytes depends on system). #[inline] - fn write_le_uint(&mut self, n: uint) -> IoResult<()> { - extensions::u64_to_le_bytes(n as u64, usize::BYTES, |v| self.write_all(v)) + fn write_le_uint(&mut self, n: usize) -> IoResult<()> { + extensions::u64_to_le_bytes(n as u64, usize::BYTES as usize, |v| self.write_all(v)) } - /// Write a little-endian int (number of bytes depends on system). + /// Write a little-endian isize (number of bytes depends on system). #[inline] - fn write_le_int(&mut self, n: int) -> IoResult<()> { - extensions::u64_to_le_bytes(n as u64, isize::BYTES, |v| self.write_all(v)) + fn write_le_int(&mut self, n: isize) -> IoResult<()> { + extensions::u64_to_le_bytes(n as u64, isize::BYTES as usize, |v| self.write_all(v)) } - /// Write a big-endian uint (number of bytes depends on system). + /// Write a big-endian usize (number of bytes depends on system). #[inline] - fn write_be_uint(&mut self, n: uint) -> IoResult<()> { - extensions::u64_to_be_bytes(n as u64, usize::BYTES, |v| self.write_all(v)) + fn write_be_uint(&mut self, n: usize) -> IoResult<()> { + extensions::u64_to_be_bytes(n as u64, usize::BYTES as usize, |v| self.write_all(v)) } - /// Write a big-endian int (number of bytes depends on system). + /// Write a big-endian isize (number of bytes depends on system). #[inline] - fn write_be_int(&mut self, n: int) -> IoResult<()> { - extensions::u64_to_be_bytes(n as u64, isize::BYTES, |v| self.write_all(v)) + fn write_be_int(&mut self, n: isize) -> IoResult<()> { + extensions::u64_to_be_bytes(n as u64, isize::BYTES as usize, |v| self.write_all(v)) } /// Write a big-endian u64 (8 bytes). @@ -1275,11 +1289,12 @@ impl<'a> Writer for &'a mut (Writer+'a) { /// A `RefWriter` is a struct implementing `Writer` which contains a reference /// to another writer. This is often useful when composing streams. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(old_io)] /// use std::old_io::util::TeeReader; -/// use std::old_io::{stdin, ByRefWriter}; +/// use std::old_io::*; /// /// fn process_input(r: R) {} /// @@ -1394,16 +1409,17 @@ pub trait Buffer: Reader { /// Tells this buffer that `amt` bytes have been consumed from the buffer, /// so they should no longer be returned in calls to `read`. - fn consume(&mut self, amt: uint); + fn consume(&mut self, amt: usize); /// Reads the next line of input, interpreted as a sequence of UTF-8 /// encoded Unicode codepoints. If a newline is encountered, then the /// newline is contained in the returned string. /// - /// # Example + /// # Examples /// - /// ```rust - /// use std::old_io::BufReader; + /// ``` + /// # #![feature(old_io)] + /// use std::old_io::*; /// /// let mut reader = BufReader::new(b"hello\nworld"); /// assert_eq!("hello\n", &*reader.read_line().unwrap()); @@ -1537,7 +1553,7 @@ impl BufferPrelude for T { /// When seeking, the resulting cursor is offset from a base by the offset given /// to the `seek` function. The base used is specified by this enumeration. -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum SeekStyle { /// Seek from the beginning of the stream SeekSet, @@ -1572,9 +1588,7 @@ pub trait Seek { /// connections. /// /// Doing so produces some sort of Acceptor. -pub trait Listener> - : PhantomFn // FIXME should be an assoc type anyhow -{ +pub trait Listener { /// Spin up the listener and start queuing incoming connections /// /// # Error @@ -1585,13 +1599,16 @@ pub trait Listener> } /// An acceptor is a value that presents incoming connections -pub trait Acceptor { +pub trait Acceptor { + /// Type of connection that is accepted by this acceptor. + type Connection; + /// Wait for and accept an incoming connection /// /// # Error /// /// Returns `Err` if an I/O error is encountered. - fn accept(&mut self) -> IoResult; + fn accept(&mut self) -> IoResult; /// Create an iterator over incoming connection attempts. /// @@ -1612,11 +1629,10 @@ pub struct IncomingConnections<'a, A: ?Sized +'a> { inc: &'a mut A, } -#[old_impl_check] -impl<'a, T, A: ?Sized + Acceptor> Iterator for IncomingConnections<'a, A> { - type Item = IoResult; +impl<'a, A: ?Sized + Acceptor> Iterator for IncomingConnections<'a, A> { + type Item = IoResult; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { Some(self.inc.accept()) } } @@ -1624,9 +1640,10 @@ impl<'a, T, A: ?Sized + Acceptor> Iterator for IncomingConnections<'a, A> { /// Creates a standard error for a commonly used flavor of error. The `detail` /// field of the returned error will always be `None`. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(old_io)] /// use std::old_io as io; /// /// let eof = io::standard_error(io::EndOfFile); @@ -1715,8 +1732,10 @@ pub enum FileType { /// # Examples /// /// ```no_run +/// # #![feature(old_io, old_path)] /// /// use std::old_io::fs::PathExtensions; +/// use std::old_path::Path; /// /// let info = match Path::new("foo.txt").stat() { /// Ok(stat) => stat, @@ -1725,7 +1744,7 @@ pub enum FileType { /// /// println!("byte size: {}", info.size); /// ``` -#[derive(Copy, Hash)] +#[derive(Copy, Clone, Hash)] pub struct FileStat { /// The size of the file, in bytes pub size: u64, @@ -1764,7 +1783,7 @@ pub struct FileStat { /// structure. This information is not necessarily platform independent, and may /// have different meanings or no meaning at all on some platforms. #[unstable(feature = "io")] -#[derive(Copy, Hash)] +#[derive(Copy, Clone, Hash)] pub struct UnstableFileStat { /// The ID of the device containing the file. pub device: u64, @@ -1845,13 +1864,14 @@ impl fmt::Display for FilePermission { mod tests { use self::BadReaderBehavior::*; use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer}; - use prelude::v1::{Ok, Vec, Buffer, SliceExt}; + use super::Buffer; + use prelude::v1::{Ok, Vec}; use usize; #[derive(Clone, PartialEq, Debug)] enum BadReaderBehavior { - GoodBehavior(uint), - BadBehavior(uint) + GoodBehavior(usize), + BadBehavior(usize) } struct BadReader { @@ -1866,7 +1886,7 @@ mod tests { } impl Reader for BadReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let BadReader { ref mut behavior, ref mut r } = *self; loop { if behavior.is_empty() { @@ -1894,7 +1914,7 @@ mod tests { fn test_read_at_least() { let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), vec![GoodBehavior(usize::MAX)]); - let buf = &mut [0u8; 5]; + let buf = &mut [0; 5]; assert!(r.read_at_least(1, buf).unwrap() >= 1); assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least assert!(r.read_at_least(0, buf).is_ok()); diff --git a/src/libstd/old_io/net/addrinfo.rs b/src/libstd/old_io/net/addrinfo.rs index 2b7506b5c3..c5fa775ab4 100644 --- a/src/libstd/old_io/net/addrinfo.rs +++ b/src/libstd/old_io/net/addrinfo.rs @@ -19,8 +19,8 @@ pub use self::SocketType::*; pub use self::Flag::*; pub use self::Protocol::*; -use iter::IteratorExt; -use old_io::{IoResult}; +use iter::Iterator; +use old_io::IoResult; use old_io::net::ip::{SocketAddr, IpAddr}; use option::Option; use option::Option::{Some, None}; @@ -29,7 +29,7 @@ use sys; use vec::Vec; /// Hints to the types of sockets that are desired when looking up hosts -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum SocketType { Stream, Datagram, Raw } @@ -38,7 +38,7 @@ pub enum SocketType { /// to manipulate how a query is performed. /// /// The meaning of each of these flags can be found with `man -s 3 getaddrinfo` -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum Flag { AddrConfig, All, @@ -51,7 +51,7 @@ pub enum Flag { /// A transport protocol associated with either a hint or a return value of /// `lookup` -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum Protocol { TCP, UDP } @@ -61,21 +61,21 @@ pub enum Protocol { /// /// For details on these fields, see their corresponding definitions via /// `man -s 3 getaddrinfo` -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub struct Hint { - pub family: uint, + pub family: usize, pub socktype: Option, pub protocol: Option, - pub flags: uint, + pub flags: usize, } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub struct Info { pub address: SocketAddr, - pub family: uint, + pub family: usize, pub socktype: Option, pub protocol: Option, - pub flags: uint, + pub flags: usize, } /// Easy name resolution. Given a hostname, returns the list of IP addresses for diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs index 9c89c94399..099fe657f2 100644 --- a/src/libstd/old_io/net/ip.rs +++ b/src/libstd/old_io/net/ip.rs @@ -21,13 +21,12 @@ use boxed::Box; use fmt; use old_io::{self, IoResult, IoError}; use old_io::net; -use iter::{Iterator, IteratorExt}; +use iter::Iterator; use ops::{FnOnce, FnMut}; use option::Option; use option::Option::{None, Some}; use result::Result::{self, Ok, Err}; -use slice::SliceExt; -use str::{FromStr, StrExt}; +use str::FromStr; use vec::Vec; pub type Port = u16; @@ -83,7 +82,7 @@ impl fmt::Display for SocketAddr { struct Parser<'a> { // parsing as ASCII, so can use byte array s: &'a [u8], - pos: uint, + pos: usize, } impl<'a> Parser<'a> { @@ -198,7 +197,7 @@ impl<'a> Parser<'a> { } fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option { - let mut r = 0u32; + let mut r = 0; let mut digit_count = 0; loop { match self.read_digit(radix) { @@ -226,7 +225,7 @@ impl<'a> Parser<'a> { } fn read_ipv4_addr_impl(&mut self) -> Option { - let mut bs = [0u8; 4]; + let mut bs = [0; 4]; let mut i = 0; while i < 4 { if i != 0 && self.read_given_char('.').is_none() { @@ -251,13 +250,13 @@ impl<'a> Parser<'a> { fn read_ipv6_addr_impl(&mut self) -> Option { fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr { assert!(head.len() + tail.len() <= 8); - let mut gs = [0u16; 8]; + let mut gs = [0; 8]; gs.clone_from_slice(head); gs[(8 - tail.len()) .. 8].clone_from_slice(tail); Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) } - fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: uint) -> (uint, bool) { + fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize) -> (usize, bool) { let mut i = 0; while i < limit { if i < limit - 1 { @@ -294,7 +293,7 @@ impl<'a> Parser<'a> { (i, false) } - let mut head = [0u16; 8]; + let mut head = [0; 8]; let (head_size, head_ipv4) = read_groups(self, &mut head, 8); if head_size == 8 { @@ -313,7 +312,7 @@ impl<'a> Parser<'a> { return None; } - let mut tail = [0u16; 8]; + let mut tail = [0; 8]; let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size); Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size])) } @@ -323,22 +322,22 @@ impl<'a> Parser<'a> { } fn read_ip_addr(&mut self) -> Option { - let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr(); - let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr(); - self.read_or(&mut [box ipv4_addr, box ipv6_addr]) + let ipv4_addr: Box<_> = box |p: &mut Parser| p.read_ipv4_addr(); + let ipv6_addr: Box<_> = box |p: &mut Parser| p.read_ipv6_addr(); + self.read_or(&mut [ipv4_addr, ipv6_addr]) } fn read_socket_addr(&mut self) -> Option { 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: Box<_> = box |p: &mut Parser| p.read_ip_addr(); + let ipv6_p: Box<_> = box |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::(open_br, ip_addr, clos_br) .map(|t| match t { (_, ip, _) => ip }) }; - p.read_or(&mut [box ipv4_p, box ipv6_p]) + p.read_or(&mut [ipv4_p, 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); @@ -415,6 +414,7 @@ pub struct ParseError; /// Some examples: /// /// ```rust,no_run +/// # #![feature(old_io, core, convert)] /// # #![allow(unused_must_use)] /// /// use std::old_io::{TcpStream, TcpListener}; @@ -425,17 +425,17 @@ pub struct ParseError; /// // The following lines are equivalent modulo possible "localhost" name resolution /// // differences /// let tcp_s = TcpStream::connect(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 12345 }); -/// let tcp_s = TcpStream::connect((Ipv4Addr(127, 0, 0, 1), 12345u16)); -/// let tcp_s = TcpStream::connect(("127.0.0.1", 12345u16)); -/// let tcp_s = TcpStream::connect(("localhost", 12345u16)); +/// let tcp_s = TcpStream::connect((Ipv4Addr(127, 0, 0, 1), 12345)); +/// let tcp_s = TcpStream::connect(("127.0.0.1", 12345)); +/// let tcp_s = TcpStream::connect(("localhost", 12345)); /// let tcp_s = TcpStream::connect("127.0.0.1:12345"); /// let tcp_s = TcpStream::connect("localhost:12345"); /// /// // TcpListener::bind(), UdpSocket::bind() and UdpSocket::send_to() behave similarly /// let tcp_l = TcpListener::bind("localhost:12345"); /// -/// let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451u16)).unwrap(); -/// udp_s.send_to([7u8, 7u8, 7u8].as_slice(), (Ipv4Addr(127, 0, 0, 1), 23451u16)); +/// let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451)).unwrap(); +/// udp_s.send_to([7, 7, 7].as_ref(), (Ipv4Addr(127, 0, 0, 1), 23451)); /// } /// ``` pub trait ToSocketAddr { @@ -674,7 +674,7 @@ mod test { #[test] fn to_socket_addr_ipaddr_u16() { let a = Ipv4Addr(77, 88, 21, 11); - let p = 12345u16; + let p = 12345; let e = SocketAddr { ip: a, port: p }; assert_eq!(Ok(e), (a, p).to_socket_addr()); assert_eq!(Ok(vec![e]), (a, p).to_socket_addr_all()); @@ -683,15 +683,15 @@ mod test { #[test] fn to_socket_addr_str_u16() { let a = SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 24352 }; - assert_eq!(Ok(a), ("77.88.21.11", 24352u16).to_socket_addr()); - assert_eq!(Ok(vec![a]), ("77.88.21.11", 24352u16).to_socket_addr_all()); + assert_eq!(Ok(a), ("77.88.21.11", 24352).to_socket_addr()); + assert_eq!(Ok(vec![a]), ("77.88.21.11", 24352).to_socket_addr_all()); let a = SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }; assert_eq!(Ok(a), ("2a02:6b8:0:1::1", 53).to_socket_addr()); assert_eq!(Ok(vec![a]), ("2a02:6b8:0:1::1", 53).to_socket_addr_all()); let a = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 23924 }; - assert!(("localhost", 23924u16).to_socket_addr_all().unwrap().contains(&a)); + assert!(("localhost", 23924).to_socket_addr_all().unwrap().contains(&a)); } #[test] diff --git a/src/libstd/old_io/net/mod.rs b/src/libstd/old_io/net/mod.rs index bbe3a71dcc..a3567290b0 100644 --- a/src/libstd/old_io/net/mod.rs +++ b/src/libstd/old_io/net/mod.rs @@ -10,6 +10,10 @@ //! Networking I/O +#![deprecated(since = "1.0.0", + reason = "replaced with new I/O primitives in `std::net`")] +#![unstable(feature = "old_io")] + use old_io::{IoError, IoResult, InvalidInput}; use ops::FnMut; use option::Option::None; diff --git a/src/libstd/old_io/net/pipe.rs b/src/libstd/old_io/net/pipe.rs index d05669d32b..3a071e832a 100644 --- a/src/libstd/old_io/net/pipe.rs +++ b/src/libstd/old_io/net/pipe.rs @@ -19,12 +19,19 @@ //! instances as clients. #![allow(missing_docs)] +#![deprecated(since = "1.0.0", + reason = "will be removed to be reintroduced at a later date; \ + in the meantime consider using the `unix_socket` crate \ + for unix sockets; there is currently no replacement \ + for named pipes")] +#![unstable(feature = "old_io")] use prelude::v1::*; use ffi::CString; use old_path::BytesContainer; use old_io::{Listener, Acceptor, IoResult, TimedOut, standard_error}; +use old_io::{Reader, Writer}; use sys::pipe::UnixAcceptor as UnixAcceptorImp; use sys::pipe::UnixListener as UnixListenerImp; use sys::pipe::UnixStream as UnixStreamImp; @@ -44,11 +51,14 @@ impl UnixStream { /// /// The returned stream will be closed when the object falls out of scope. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(old_io, old_path, io)] /// # #![allow(unused_must_use)] /// use std::old_io::net::pipe::UnixStream; + /// use std::old_io::*; + /// use std::old_path::Path; /// /// let server = Path::new("path/to/my/socket"); /// let mut stream = UnixStream::connect(&server); @@ -140,7 +150,7 @@ impl Clone for UnixStream { } impl Reader for UnixStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } } @@ -169,12 +179,14 @@ impl UnixListener { /// /// This listener will be closed when it falls out of scope. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_io, io, old_path)] /// # fn foo() { /// use std::old_io::net::pipe::UnixListener; - /// use std::old_io::{Listener, Acceptor}; + /// use std::old_io::*; + /// use std::old_path::Path; /// /// let server = Path::new("/path/to/my/socket"); /// let stream = UnixListener::bind(&server); @@ -190,7 +202,7 @@ impl UnixListener { } } -impl Listener for UnixListener { +impl Listener for UnixListener { fn listen(self) -> IoResult { self.inner.listen() .map(|inner| UnixAcceptor { inner: inner }) @@ -238,7 +250,8 @@ impl UnixAcceptor { } } -impl Acceptor for UnixAcceptor { +impl Acceptor for UnixAcceptor { + type Connection = UnixStream; fn accept(&mut self) -> IoResult { self.inner.accept().map(|s| { UnixStream { inner: s } @@ -279,6 +292,7 @@ mod tests { use old_io::{EndOfFile, TimedOut, ShortWrite, IoError, ConnectionReset}; use old_io::{NotConnected, BrokenPipe, FileNotFound, InvalidInput, OtherIoError}; use old_io::{PermissionDenied, Acceptor, Listener}; + use old_io::{Reader, Writer}; use old_io::test::*; use super::*; use sync::mpsc::channel; diff --git a/src/libstd/old_io/net/tcp.rs b/src/libstd/old_io/net/tcp.rs index 19a6f6e3de..7fc460c16e 100644 --- a/src/libstd/old_io/net/tcp.rs +++ b/src/libstd/old_io/net/tcp.rs @@ -38,10 +38,11 @@ use sys_common; /// /// The socket will be closed when the value is dropped. /// -/// # Example +/// # Examples /// /// ```no_run -/// use std::old_io::TcpStream; +/// # #![feature(old_io, io)] +/// use std::old_io::*; /// /// { /// let mut stream = TcpStream::connect("127.0.0.1:34254"); @@ -121,7 +122,7 @@ impl TcpStream { /// this connection. Otherwise, the keepalive timeout will be set to the /// specified time, in seconds. #[unstable(feature = "io")] - pub fn set_keepalive(&mut self, delay_in_seconds: Option) -> IoResult<()> { + pub fn set_keepalive(&mut self, delay_in_seconds: Option) -> IoResult<()> { self.inner.set_keepalive(delay_in_seconds) } @@ -130,12 +131,12 @@ impl TcpStream { /// This method will close the reading portion of this connection, causing /// all pending and future reads to immediately return with an error. /// - /// # Example + /// # Examples /// /// ```no_run + /// # #![feature(old_io, std_misc)] /// # #![allow(unused_must_use)] - /// use std::old_io::timer; - /// use std::old_io::TcpStream; + /// use std::old_io::*; /// use std::time::Duration; /// use std::thread; /// @@ -256,7 +257,7 @@ impl Clone for TcpStream { } impl Reader for TcpStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } } @@ -279,9 +280,9 @@ impl sys_common::AsInner for TcpStream { /// # Examples /// /// ``` +/// # #![feature(old_io)] /// # fn foo() { -/// use std::old_io::{TcpListener, TcpStream}; -/// use std::old_io::{Acceptor, Listener}; +/// use std::old_io::*; /// use std::thread; /// /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); @@ -337,7 +338,7 @@ impl TcpListener { } } -impl Listener for TcpListener { +impl Listener for TcpListener { fn listen(self) -> IoResult { self.inner.listen(128).map(|a| TcpAcceptor { inner: a }) } @@ -373,11 +374,11 @@ impl TcpAcceptor { /// regardless of whether the timeout has expired or not (the accept will /// not block in this case). /// - /// # Example + /// # Examples /// /// ```no_run - /// use std::old_io::TcpListener; - /// use std::old_io::{Listener, Acceptor, TimedOut}; + /// # #![feature(old_io, io)] + /// use std::old_io::*; /// /// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap(); /// @@ -417,10 +418,11 @@ impl TcpAcceptor { /// This is useful for waking up a thread in an accept loop to indicate that /// it should exit. /// - /// # Example + /// # Examples /// /// ``` - /// use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile}; + /// # #![feature(old_io, io)] + /// use std::old_io::*; /// use std::thread; /// /// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap(); @@ -451,7 +453,8 @@ impl TcpAcceptor { } } -impl Acceptor for TcpAcceptor { +impl Acceptor for TcpAcceptor { + type Connection = TcpStream; fn accept(&mut self) -> IoResult { self.inner.accept().map(TcpStream::new) } @@ -496,6 +499,7 @@ mod test { use old_io::{ConnectionReset, NotConnected, PermissionDenied, OtherIoError}; use old_io::{InvalidInput}; use old_io::{Acceptor, Listener}; + use old_io::{Reader, Writer}; // FIXME #11530 this fails on android because tests are run as root #[cfg_attr(any(windows, target_os = "android"), ignore)] @@ -786,12 +790,12 @@ mod test { #[test] fn multiple_connect_interleaved_greedy_schedule_ip4() { let addr = next_test_ip4(); - static MAX: int = 10; + static MAX: isize = 10; let acceptor = TcpListener::bind(addr).listen(); let _t = thread::spawn(move|| { let mut acceptor = acceptor; - for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) { + for (i, stream) in acceptor.incoming().enumerate().take(MAX as usize) { // Start another task to handle the connection let _t = thread::spawn(move|| { let mut stream = stream; @@ -805,7 +809,7 @@ mod test { connect(0, addr); - fn connect(i: int, addr: SocketAddr) { + fn connect(i: isize, addr: SocketAddr) { if i == MAX { return } let _t = thread::spawn(move|| { @@ -822,12 +826,12 @@ mod test { #[test] fn multiple_connect_interleaved_greedy_schedule_ip6() { let addr = next_test_ip6(); - static MAX: int = 10; + static MAX: isize = 10; let acceptor = TcpListener::bind(addr).listen(); let _t = thread::spawn(move|| { let mut acceptor = acceptor; - for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) { + for (i, stream) in acceptor.incoming().enumerate().take(MAX as usize) { // Start another task to handle the connection let _t = thread::spawn(move|| { let mut stream = stream; @@ -841,7 +845,7 @@ mod test { connect(0, addr); - fn connect(i: int, addr: SocketAddr) { + fn connect(i: isize, addr: SocketAddr) { if i == MAX { return } let _t = thread::spawn(move|| { @@ -857,13 +861,13 @@ mod test { #[test] fn multiple_connect_interleaved_lazy_schedule_ip4() { - static MAX: int = 10; + static MAX: isize = 10; let addr = next_test_ip4(); let acceptor = TcpListener::bind(addr).listen(); let _t = thread::spawn(move|| { let mut acceptor = acceptor; - for stream in acceptor.incoming().take(MAX as uint) { + for stream in acceptor.incoming().take(MAX as usize) { // Start another task to handle the connection let _t = thread::spawn(move|| { let mut stream = stream; @@ -877,7 +881,7 @@ mod test { connect(0, addr); - fn connect(i: int, addr: SocketAddr) { + fn connect(i: isize, addr: SocketAddr) { if i == MAX { return } let _t = thread::spawn(move|| { @@ -893,13 +897,13 @@ mod test { #[test] fn multiple_connect_interleaved_lazy_schedule_ip6() { - static MAX: int = 10; + static MAX: isize = 10; let addr = next_test_ip6(); let acceptor = TcpListener::bind(addr).listen(); let _t = thread::spawn(move|| { let mut acceptor = acceptor; - for stream in acceptor.incoming().take(MAX as uint) { + for stream in acceptor.incoming().take(MAX as usize) { // Start another task to handle the connection let _t = thread::spawn(move|| { let mut stream = stream; @@ -913,7 +917,7 @@ mod test { connect(0, addr); - fn connect(i: int, addr: SocketAddr) { + fn connect(i: isize, addr: SocketAddr) { if i == MAX { return } let _t = thread::spawn(move|| { @@ -1162,7 +1166,7 @@ mod test { tx.send(TcpStream::connect(addr).unwrap()).unwrap(); }); let _l = rx.recv().unwrap(); - for i in 0i32..1001 { + for i in 0..1001 { match a.accept() { Ok(..) => break, Err(ref e) if e.kind == TimedOut => {} @@ -1262,7 +1266,7 @@ mod test { assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut); s.set_timeout(Some(20)); - for i in 0i32..1001 { + for i in 0..1001 { match s.write(&[0; 128 * 1024]) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, @@ -1320,7 +1324,7 @@ mod test { let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); - for i in 0i32..1001 { + for i in 0..1001 { match s.write(&[0; 128 * 1024]) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, diff --git a/src/libstd/old_io/net/udp.rs b/src/libstd/old_io/net/udp.rs index 67b57b2508..196447d71e 100644 --- a/src/libstd/old_io/net/udp.rs +++ b/src/libstd/old_io/net/udp.rs @@ -28,9 +28,10 @@ use sys_common; /// IPv6 addresses, and there is no corresponding notion of a server because UDP /// is a datagram protocol. /// -/// # Example +/// # Examples /// /// ```rust,no_run +/// # #![feature(old_io)] /// # #![allow(unused_must_use)] /// /// use std::old_io::net::udp::UdpSocket; @@ -72,7 +73,7 @@ impl UdpSocket { /// Receives data from the socket. On success, returns the number of bytes /// read and the address from whence the data came. - pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> { + pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(usize, SocketAddr)> { self.inner.recv_from(buf) } @@ -112,13 +113,13 @@ impl UdpSocket { /// Sets the multicast TTL #[unstable(feature = "io")] - pub fn set_multicast_ttl(&mut self, ttl: int) -> IoResult<()> { + pub fn set_multicast_ttl(&mut self, ttl: isize) -> IoResult<()> { self.inner.multicast_time_to_live(ttl) } /// Sets this socket's TTL #[unstable(feature = "io")] - pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> { + pub fn set_ttl(&mut self, ttl: isize) -> IoResult<()> { self.inner.time_to_live(ttl) } diff --git a/src/libstd/old_io/pipe.rs b/src/libstd/old_io/pipe.rs index b7b626db03..fd1df49473 100644 --- a/src/libstd/old_io/pipe.rs +++ b/src/libstd/old_io/pipe.rs @@ -17,7 +17,7 @@ use prelude::v1::*; -use old_io::IoResult; +use old_io::{IoResult, Reader, Writer}; use libc; use sync::Arc; @@ -43,13 +43,14 @@ impl PipeStream { /// This operation consumes ownership of the file descriptor and it will be /// closed once the object is deallocated. /// - /// # Example + /// # Examples /// /// ```{rust,no_run} + /// # #![feature(old_io, libc, io)] /// # #![allow(unused_must_use)] /// extern crate libc; /// - /// use std::old_io::pipe::PipeStream; + /// use std::old_io::*; /// /// fn main() { /// let mut pipe = PipeStream::open(libc::STDERR_FILENO); @@ -99,7 +100,7 @@ impl Clone for PipeStream { } impl Reader for PipeStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.read(buf) } } @@ -114,6 +115,7 @@ impl Writer for PipeStream { mod test { use prelude::v1::*; + use old_io::{Writer, Reader}; use sync::mpsc::channel; use thread; @@ -122,9 +124,9 @@ mod test { use os; use old_io::pipe::PipeStream; - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let out = PipeStream::open(writer); - let mut input = PipeStream::open(reader); + let (reader, writer) = unsafe { ::sys::os::pipe().unwrap() }; + let out = PipeStream::open(writer.unwrap()); + let mut input = PipeStream::open(reader.unwrap()); let (tx, rx) = channel(); let _t = thread::spawn(move|| { let mut out = out; diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index c803cfbcb7..ad2d5b4681 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -11,6 +11,9 @@ //! Bindings for executing child processes #![allow(non_upper_case_globals)] +#![unstable(feature = "old_io")] +#![deprecated(since = "1.0.0", + reason = "replaced with the std::process module")] pub use self::StdioContainer::*; pub use self::ProcessExit::*; @@ -21,8 +24,9 @@ use collections::HashMap; use ffi::CString; use fmt; use old_io::pipe::{PipeStream, PipePair}; -use old_io::{IoResult, IoError}; +use old_io::{IoResult, IoError, Reader, Writer}; use old_io; +use old_path::{Path, GenericPath}; use libc; use os; use old_path::BytesContainer; @@ -37,16 +41,16 @@ use thread; /// Signal a process to exit, without forcibly killing it. Corresponds to /// SIGTERM on unix platforms. -#[cfg(windows)] pub const PleaseExitSignal: int = 15; +#[cfg(windows)] pub const PleaseExitSignal: isize = 15; /// Signal a process to exit immediately, forcibly killing it. Corresponds to /// SIGKILL on unix platforms. -#[cfg(windows)] pub const MustDieSignal: int = 9; +#[cfg(windows)] pub const MustDieSignal: isize = 9; /// Signal a process to exit, without forcibly killing it. Corresponds to /// SIGTERM on unix platforms. -#[cfg(not(windows))] pub const PleaseExitSignal: int = libc::SIGTERM as int; +#[cfg(not(windows))] pub const PleaseExitSignal: isize = libc::SIGTERM as isize; /// Signal a process to exit immediately, forcibly killing it. Corresponds to /// SIGKILL on unix platforms. -#[cfg(not(windows))] pub const MustDieSignal: int = libc::SIGKILL as int; +#[cfg(not(windows))] pub const MustDieSignal: isize = libc::SIGKILL as isize; /// Representation of a running or exited child process. /// @@ -54,10 +58,11 @@ use thread; /// process is created via the `Command` struct, which configures the spawning /// process and can itself be constructed using a builder-style interface. /// -/// # Example +/// # Examples /// -/// ```should_fail -/// use std::old_io::Command; +/// ```should_panic +/// # #![feature(old_io)] +/// use std::old_io::*; /// /// let mut child = match Command::new("/bin/cat").arg("file.txt").spawn() { /// Ok(child) => child, @@ -75,7 +80,7 @@ pub struct Process { exit_code: Option, /// Manually delivered signal - exit_signal: Option, + exit_signal: Option, /// Deadline after which wait() will return deadline: u64, @@ -104,25 +109,14 @@ struct EnvKey(CString); #[derive(Eq, Clone, Debug)] struct EnvKey(CString); -#[cfg(all(windows, stage0))] -impl hash::Hash for EnvKey { - fn hash(&self, state: &mut H) { - let &EnvKey(ref x) = self; - match str::from_utf8(x.as_bytes()) { - Ok(s) => for ch in s.chars() { - (ch as u8 as char).to_lowercase().hash(state); - }, - Err(..) => x.hash(state) - } - } -} -#[cfg(all(windows, not(stage0)))] +#[cfg(windows)] impl hash::Hash for EnvKey { fn hash(&self, state: &mut H) { + use ascii::AsciiExt; let &EnvKey(ref x) = self; match str::from_utf8(x.as_bytes()) { Ok(s) => for ch in s.chars() { - (ch as u8 as char).to_lowercase().hash(state); + ch.to_ascii_lowercase().hash(state); }, Err(..) => x.hash(state) } @@ -132,6 +126,7 @@ impl hash::Hash for EnvKey { #[cfg(windows)] impl PartialEq for EnvKey { fn eq(&self, other: &EnvKey) -> bool { + use ascii::AsciiExt; let &EnvKey(ref x) = self; let &EnvKey(ref y) = other; match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) { @@ -140,7 +135,7 @@ impl PartialEq for EnvKey { return false } else { for (xch, ych) in xs.chars().zip(ys.chars()) { - if xch.to_lowercase() != ych.to_lowercase() { + if xch.to_ascii_lowercase() != ych.to_ascii_lowercase() { return false; } } @@ -170,7 +165,8 @@ pub type EnvMap = HashMap; /// to be changed (for example, by adding arguments) prior to spawning: /// /// ``` -/// use std::old_io::Command; +/// # #![feature(old_io)] +/// use std::old_io::*; /// /// let mut process = match Command::new("sh").arg("-c").arg("echo hello").spawn() { /// Ok(p) => p, @@ -190,8 +186,8 @@ pub struct Command { stdin: StdioContainer, stdout: StdioContainer, stderr: StdioContainer, - uid: Option, - gid: Option, + uid: Option, + gid: Option, detach: bool, } @@ -250,7 +246,7 @@ impl Command { 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)| { + self.env = Some(::env::vars().map(|(k, v)| { (EnvKey(CString::new(k).unwrap()), CString::new(v).unwrap()) }).collect()); @@ -325,14 +321,14 @@ impl Command { /// the child process. Setting this value on windows will cause the spawn to /// fail. Failure in the `setuid` call on unix will also cause the spawn to /// fail. - pub fn uid<'a>(&'a mut self, id: uint) -> &'a mut Command { + pub fn uid<'a>(&'a mut self, id: usize) -> &'a mut Command { self.uid = Some(id); self } /// Similar to `uid`, but sets the group id of the child process. This has /// the same semantics as the `uid` field. - pub fn gid<'a>(&'a mut self, id: uint) -> &'a mut Command { + pub fn gid<'a>(&'a mut self, id: usize) -> &'a mut Command { self.gid = Some(id); self } @@ -368,9 +364,10 @@ impl Command { /// Executes the command as a child process, waiting for it to finish and /// collecting all of its output. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_io, core, convert)] /// use std::old_io::Command; /// /// let output = match Command::new("cat").arg("foot.txt").output() { @@ -379,8 +376,8 @@ impl Command { /// }; /// /// println!("status: {}", output.status); - /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice())); - /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice())); + /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_ref())); + /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_ref())); /// ``` pub fn output(&self) -> IoResult { self.spawn().and_then(|p| p.wait_with_output()) @@ -389,9 +386,10 @@ impl Command { /// Executes a command as a child process, waiting for it to finish and /// collecting its exit status. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_io)] /// use std::old_io::Command; /// /// let status = match Command::new("ls").status() { @@ -460,10 +458,10 @@ impl sys::process::ProcessConfig for Command { fn cwd(&self) -> Option<&CString> { self.cwd.as_ref() } - fn uid(&self) -> Option { + fn uid(&self) -> Option { self.uid.clone() } - fn gid(&self) -> Option { + fn gid(&self) -> Option { self.gid.clone() } fn detach(&self) -> bool { @@ -509,10 +507,10 @@ pub enum StdioContainer { #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum ProcessExit { /// Normal termination with an exit status. - ExitStatus(int), + ExitStatus(isize), /// Termination by signal, with the signal number. - ExitSignal(int), + ExitSignal(isize), } #[stable(feature = "rust1", since = "1.0.0")] @@ -535,7 +533,7 @@ impl ProcessExit { /// Checks whether this ProcessExit matches the given exit status. /// Termination by signal will never match an exit code. - pub fn matches_exit_status(&self, wanted: int) -> bool { + pub fn matches_exit_status(&self, wanted: isize) -> bool { *self == ExitStatus(wanted) } } @@ -551,7 +549,7 @@ impl Process { /// process. Note, though, that on some platforms signals will continue to /// be successfully delivered if the child has exited, but not yet been /// reaped. - pub fn kill(id: libc::pid_t, signal: int) -> IoResult<()> { + pub fn kill(id: libc::pid_t, signal: isize) -> IoResult<()> { unsafe { ProcessImp::killpid(id, signal) } } @@ -573,7 +571,7 @@ impl Process { /// # Errors /// /// If the signal delivery fails, the corresponding error is returned. - pub fn signal(&mut self, signal: int) -> IoResult<()> { + pub fn signal(&mut self, signal: isize) -> IoResult<()> { #[cfg(unix)] fn collect_status(p: &mut Process) { // On Linux (and possibly other unices), a process that has exited will // continue to accept signals because it is "defunct". The delivery of @@ -663,9 +661,10 @@ impl Process { /// A value of `None` will clear any previous timeout, and a value of `Some` /// will override any previously set timeout. /// - /// # Example + /// # Examples /// /// ```no_run + /// # #![feature(old_io, io)] /// use std::old_io::{Command, IoResult}; /// use std::old_io::process::ProcessExit; /// @@ -765,10 +764,10 @@ impl Drop for Process { #[cfg(test)] mod tests { + use prelude::v1::*; use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound}; - use prelude::v1::{Ok, Err, range, drop, Some, None, Vec}; - use prelude::v1::{Path, String, Reader, Writer, Clone}; - use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; + use old_io::{Reader, Writer}; + use old_path::{GenericPath, Path}; use old_io::fs::PathExtensions; use old_io::timer::*; use rt::running_on_valgrind; @@ -887,8 +886,8 @@ mod tests { use libc; let mut p = Command::new("/bin/sh") .arg("-c").arg("true") - .uid(unsafe { libc::getuid() as uint }) - .gid(unsafe { libc::getgid() as uint }) + .uid(unsafe { libc::getuid() as usize }) + .gid(unsafe { libc::getgid() as usize }) .spawn().unwrap(); assert!(p.wait().unwrap().success()); } @@ -1002,7 +1001,7 @@ mod tests { let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let parent_dir = os::getcwd().unwrap(); + let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap()); let child_dir = Path::new(output.trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -1017,7 +1016,7 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().unwrap().dir_path(); + let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap()); let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); @@ -1057,11 +1056,11 @@ mod tests { let prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + let r = ::env::vars(); + for (k, v) in r { // don't check windows magical empty-named variables assert!(k.is_empty() || - output.contains(&format!("{}={}", *k, *v)), + output.contains(&format!("{}={}", k, v)), "output doesn't contain `{}={}`\n{}", k, v, output); } @@ -1075,16 +1074,12 @@ mod tests { let mut prog = env_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + let r = ::env::vars(); + for (k, v) in r { // don't check android RANDOM variables - if *k != "RANDOM".to_string() { - assert!(output.contains(&format!("{}={}", - *k, - *v)) || - output.contains(&format!("{}=\'{}\'", - *k, - *v))); + if k != "RANDOM".to_string() { + assert!(output.contains(&format!("{}={}", k, v)) || + output.contains(&format!("{}=\'{}\'", k, v))); } } } @@ -1099,9 +1094,9 @@ mod tests { // PATH to our sub-process. let path_val: String; let mut new_env = vec![("RUN_TEST_NEW_ENV", "123")]; - match os::getenv("PATH") { - None => {} - Some(val) => { + match ::env::var("PATH") { + Err(..) => {} + Ok(val) => { path_val = val; new_env.push(("PATH", &path_val)) } @@ -1238,7 +1233,7 @@ mod tests { cmd.env("path", "foo"); cmd.env("Path", "bar"); let env = &cmd.env.unwrap(); - let val = env.get(&EnvKey(CString::new(b"PATH").unwrap())); - assert!(val.unwrap() == &CString::new(b"bar").unwrap()); + let val = env.get(&EnvKey(CString::new("PATH").unwrap())); + assert!(val.unwrap() == &CString::new("bar").unwrap()); } } diff --git a/src/libstd/old_io/result.rs b/src/libstd/old_io/result.rs index f42cb6ce8c..e1037f26b7 100644 --- a/src/libstd/old_io/result.rs +++ b/src/libstd/old_io/result.rs @@ -35,7 +35,7 @@ impl Writer for IoResult { } impl Reader for IoResult { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { match *self { Ok(ref mut reader) => reader.read(buf), Err(ref e) => Err(e.clone()), @@ -58,7 +58,7 @@ impl Seek for IoResult { } } -impl, L: Listener> Listener for IoResult { +impl> Listener for IoResult { fn listen(self) -> IoResult { match self { Ok(listener) => listener.listen(), @@ -67,8 +67,9 @@ impl, L: Listener> Listener for IoResult { } } -impl> Acceptor for IoResult { - fn accept(&mut self) -> IoResult { +impl Acceptor for IoResult { + type Connection = A::Connection; + fn accept(&mut self) -> IoResult { match *self { Ok(ref mut acceptor) => acceptor.accept(), Err(ref e) => Err(e.clone()), @@ -80,14 +81,14 @@ impl> Acceptor for IoResult { mod test { use prelude::v1::*; use super::super::mem::*; - use old_io; + use old_io::{self, Reader, Writer}; #[test] fn test_option_writer() { let mut writer: old_io::IoResult> = Ok(Vec::new()); writer.write_all(&[0, 1, 2]).unwrap(); writer.flush().unwrap(); - assert_eq!(writer.unwrap(), vec!(0, 1, 2)); + assert_eq!(writer.unwrap(), [0, 1, 2]); } #[test] diff --git a/src/libstd/old_io/stdio.rs b/src/libstd/old_io/stdio.rs index e3d0232684..b4924c7b78 100644 --- a/src/libstd/old_io/stdio.rs +++ b/src/libstd/old_io/stdio.rs @@ -15,11 +15,13 @@ //! inspected for information about terminal dimensions or for related information //! about the stream or terminal to which it is attached. //! -//! # Example +//! # Examples //! //! ```rust +//! # #![feature(old_io)] //! # #![allow(unused_must_use)] //! use std::old_io; +//! use std::old_io::*; //! //! let mut out = old_io::stdout(); //! out.write_all(b"Hello, world!"); @@ -27,13 +29,13 @@ use self::StdSource::*; +use boxed; use boxed::Box; use cell::RefCell; use clone::Clone; -use panicking::LOCAL_STDERR; use fmt; use old_io::{Reader, Writer, IoResult, IoError, OtherIoError, Buffer, - standard_error, EndOfFile, LineBufferedWriter, BufferedReader}; + standard_error, EndOfFile, LineBufferedWriter, BufferedReader}; use marker::{Sync, Send}; use libc; use mem; @@ -43,8 +45,6 @@ use ops::{Deref, DerefMut, FnOnce}; use ptr; use result::Result::{Ok, Err}; use rt; -use slice::SliceExt; -use str::StrExt; use string::String; use sys::{fs, tty}; use sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT}; @@ -140,8 +140,10 @@ impl StdinReader { /// /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(old_io)] /// use std::old_io; + /// use std::old_io::*; /// /// let mut stdin = old_io::stdin(); /// for line in stdin.lock().lines() { @@ -180,7 +182,7 @@ impl StdinReader { } impl Reader for StdinReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { self.inner.lock().unwrap().0.read(buf) } @@ -188,11 +190,11 @@ impl Reader for StdinReader { // read more than once and we don't want those calls to interleave (or // incur the costs of repeated locking). - fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult { + fn read_at_least(&mut self, min: usize, buf: &mut [u8]) -> IoResult { self.inner.lock().unwrap().0.read_at_least(min, buf) } - fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec) -> IoResult { + fn push_at_least(&mut self, min: usize, len: usize, buf: &mut Vec) -> IoResult { self.inner.lock().unwrap().0.push_at_least(min, len, buf) } @@ -200,11 +202,11 @@ impl Reader for StdinReader { self.inner.lock().unwrap().0.read_to_end() } - fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult { + fn read_le_uint_n(&mut self, nbytes: usize) -> IoResult { self.inner.lock().unwrap().0.read_le_uint_n(nbytes) } - fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult { + fn read_be_uint_n(&mut self, nbytes: usize) -> IoResult { self.inner.lock().unwrap().0.read_be_uint_n(nbytes) } } @@ -218,15 +220,15 @@ impl Reader for StdinReader { /// See `stdout()` for more notes about this function. pub fn stdin() -> StdinReader { // We're following the same strategy as kimundi's lazy_static library - static mut STDIN: *const StdinReader = 0 as *const StdinReader; + static mut STDIN: *mut StdinReader = 0 as *mut StdinReader; static ONCE: Once = ONCE_INIT; unsafe { ONCE.call_once(|| { - // The default buffer capacity is 64k, but apparently windows doesn't like - // 64k reads on stdin. See #13304 for details, but the idea is that on - // windows we use a slightly smaller buffer that's been seen to be - // acceptable. + // The default buffer capacity is 64k, but apparently windows + // doesn't like 64k reads on stdin. See #13304 for details, but the + // idea is that on windows we use a slightly smaller buffer that's + // been seen to be acceptable. let stdin = if cfg!(windows) { BufferedReader::with_capacity(8 * 1024, stdin_raw()) } else { @@ -235,12 +237,12 @@ pub fn stdin() -> StdinReader { let stdin = StdinReader { inner: Arc::new(Mutex::new(RaceBox(stdin))) }; - STDIN = mem::transmute(box stdin); + STDIN = boxed::into_raw(box stdin); // Make sure to free it at exit - rt::at_exit(|| { - mem::transmute::<_, Box>(STDIN); - STDIN = ptr::null(); + let _ = rt::at_exit(|| { + Box::from_raw(STDIN); + STDIN = ptr::null_mut(); }); }); @@ -318,14 +320,10 @@ pub fn set_stdout(stdout: Box) -> Option> { /// /// Note that this does not need to be called for all new tasks; the default /// output handle is to the process's stderr stream. -pub fn set_stderr(stderr: Box) -> Option> { - let mut new = Some(stderr); - LOCAL_STDERR.with(|slot| { - mem::replace(&mut *slot.borrow_mut(), new.take()) - }).and_then(|mut s| { - let _ = s.flush(); - Some(s) - }) +#[unstable(feature = "old_io")] +#[deprecated(since = "1.0.0", reason = "replaced with std::io::set_panic")] +pub fn set_stderr(_stderr: Box) -> Option> { + None } // Helper to access the local task's stdout handle @@ -339,10 +337,10 @@ pub fn set_stderr(stderr: Box) -> Option> { // }) // }) fn with_task_stdout(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> { - let mut my_stdout = LOCAL_STDOUT.with(|slot| { + let mut my_stdout: Box = LOCAL_STDOUT.with(|slot| { slot.borrow_mut().take() }).unwrap_or_else(|| { - box stdout() as Box + box stdout() }); let result = f(&mut *my_stdout); let mut var = Some(my_stdout); @@ -412,16 +410,16 @@ impl StdReader { } impl Reader for StdReader { - fn read(&mut self, buf: &mut [u8]) -> IoResult { + fn read(&mut self, buf: &mut [u8]) -> IoResult { let ret = match self.inner { TTY(ref mut tty) => { // Flush the task-local stdout so that weird issues like a // print!'d prompt not being shown until after the user hits // enter. flush(); - tty.read(buf).map(|i| i as uint) + tty.read(buf).map(|i| i as usize) }, - File(ref mut file) => file.read(buf).map(|i| i as uint), + File(ref mut file) => file.read(buf).map(|i| i as usize), }; match ret { // When reading a piped stdin, libuv will return 0-length reads when @@ -454,7 +452,7 @@ impl StdWriter { /// /// This function will return an error if the output stream is not actually /// connected to a TTY instance, or if querying the TTY instance fails. - pub fn winsize(&mut self) -> IoResult<(int, int)> { + pub fn winsize(&mut self) -> IoResult<(isize, isize)> { match self.inner { TTY(ref mut tty) => { tty.get_winsize() @@ -539,31 +537,4 @@ mod tests { stdout(); stderr(); } - - #[test] - fn capture_stdout() { - use old_io::{ChanReader, ChanWriter}; - - let (tx, rx) = channel(); - let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - let _t = thread::spawn(move|| { - set_stdout(box w); - println!("hello!"); - }); - assert_eq!(r.read_to_string().unwrap(), "hello!\n"); - } - - #[test] - fn capture_stderr() { - use old_io::{ChanReader, ChanWriter, Reader}; - - let (tx, rx) = channel(); - let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - let _t = thread::spawn(move || -> () { - set_stderr(box w); - panic!("my special message"); - }); - let s = r.read_to_string().unwrap(); - assert!(s.contains("my special message")); - } } diff --git a/src/libstd/old_io/tempfile.rs b/src/libstd/old_io/tempfile.rs index 42317c7a2d..94faa5540b 100644 --- a/src/libstd/old_io/tempfile.rs +++ b/src/libstd/old_io/tempfile.rs @@ -12,7 +12,7 @@ #![allow(deprecated)] // rand use env; -use iter::{IteratorExt}; +use iter::Iterator; use old_io::{fs, IoError, IoErrorKind, IoResult}; use old_io; use ops::Drop; @@ -21,7 +21,6 @@ use option::Option; use old_path::{Path, GenericPath}; use rand::{Rng, thread_rng}; use result::Result::{Ok, Err}; -use str::StrExt; use string::String; /// A wrapper for a path to temporary directory implementing automatic @@ -30,7 +29,9 @@ use string::String; /// # Examples /// /// ```no_run -/// use std::old_io::TempDir; +/// # #![feature(old_io, old_path)] +/// use std::old_io::*; +/// use std::old_path::{Path, GenericPath}; /// /// { /// // create a temporary directory @@ -88,7 +89,7 @@ const NUM_RETRIES: u32 = 1 << 31; // 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; +const NUM_RAND_CHARS: usize = 12; impl TempDir { /// Attempts to make a temporary directory inside of `tmpdir` whose name @@ -96,9 +97,11 @@ impl TempDir { /// deleted once the returned wrapper is destroyed. /// /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult { if !tmpdir.is_absolute() { - let cur_dir = try!(env::current_dir()); + let cur_dir = ::env::current_dir().unwrap(); + let cur_dir = Path::new(cur_dir.to_str().unwrap()); return TempDir::new_in(&cur_dir.join(tmpdir), prefix); } @@ -132,8 +135,10 @@ impl TempDir { /// deleted once the returned wrapper is destroyed. /// /// If no directory can be created, `Err` is returned. + #[allow(deprecated)] pub fn new(prefix: &str) -> IoResult { - TempDir::new_in(&env::temp_dir(), prefix) + let tmp = Path::new(::env::temp_dir().to_str().unwrap()); + TempDir::new_in(&tmp, prefix) } /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper. diff --git a/src/libstd/old_io/test.rs b/src/libstd/old_io/test.rs index ee72beccfa..312e1c814d 100644 --- a/src/libstd/old_io/test.rs +++ b/src/libstd/old_io/test.rs @@ -14,7 +14,8 @@ use prelude::v1::*; use env; use libc; -use std::old_io::net::ip::*; +use old_io::net::ip::*; +use old_path::{Path, GenericPath}; use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; /// Get a port number, starting at 9600, for use in tests @@ -38,10 +39,11 @@ fn next_test_unix_socket() -> String { /// Get a temporary path which could be the location of a unix socket #[cfg(not(target_os = "ios"))] +#[allow(deprecated)] pub fn next_test_unix() -> Path { let string = next_test_unix_socket(); if cfg!(unix) { - env::temp_dir().join(string) + Path::new(::env::temp_dir().to_str().unwrap()).join(string) } else { Path::new(format!("{}{}", r"\\.\pipe\", string)) } @@ -72,8 +74,8 @@ it is running in and assigns a port range based on it. */ fn base_port() -> u16 { - let base = 9600u16; - let range = 1000u16; + let base = 9600; + let range = 1000; let bases = [ ("32-opt", base + range * 1), @@ -88,7 +90,7 @@ fn base_port() -> u16 { // FIXME (#9639): This needs to handle non-utf8 paths let path = env::current_dir().unwrap(); - let path_s = path.as_str().unwrap(); + let path_s = path.to_str().unwrap(); let mut final_base = base; @@ -139,7 +141,7 @@ mod darwin_fd_limit { // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value. use ptr::null_mut; use mem::size_of_val; - use os::last_os_error; + use io; // Fetch the kern.maxfilesperproc value let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; @@ -147,14 +149,14 @@ mod darwin_fd_limit { let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size, null_mut(), 0) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling sysctl: {}", err); } // Fetch the current resource limits let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0}; if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling getrlimit: {}", err); } @@ -163,7 +165,7 @@ mod darwin_fd_limit { // Set our newly-increased resource limit if setrlimit(RLIMIT_NOFILE, &rlim) != 0 { - let err = last_os_error(); + let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling setrlimit: {}", err); } } diff --git a/src/libstd/old_io/timer.rs b/src/libstd/old_io/timer.rs index 1f2ef50fca..f8cba04444 100644 --- a/src/libstd/old_io/timer.rs +++ b/src/libstd/old_io/timer.rs @@ -15,6 +15,7 @@ // FIXME: These functions take Durations but only pass ms to the backend impls. +use boxed::Box; use sync::mpsc::{Receiver, Sender, channel}; use time::Duration; use old_io::IoResult; @@ -30,6 +31,7 @@ use sys::timer::Timer as TimerImp; /// # Examples /// /// ``` +/// # #![feature(old_io, std_misc)] /// # fn foo() { /// use std::old_io::Timer; /// use std::time::Duration; @@ -53,6 +55,7 @@ use sys::timer::Timer as TimerImp; /// the `old_io::timer` module. /// /// ``` +/// # #![feature(old_io, std_misc)] /// # fn foo() { /// use std::old_io::timer; /// use std::time::Duration; @@ -112,9 +115,10 @@ impl Timer { /// invalidated at the end of that statement, and all `recv` calls will /// fail. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(old_io, std_misc)] /// use std::old_io::Timer; /// use std::time::Duration; /// @@ -127,7 +131,8 @@ impl Timer { /// ten_milliseconds.recv().unwrap(); /// ``` /// - /// ```rust + /// ``` + /// # #![feature(old_io, std_misc)] /// use std::old_io::Timer; /// use std::time::Duration; /// @@ -143,7 +148,7 @@ impl Timer { let (tx, rx) = channel(); // Short-circuit the timer backend for 0 duration if in_ms_u64(duration) != 0 { - self.inner.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx }); + self.inner.oneshot(in_ms_u64(duration), Box::new(TimerCallback { tx: tx })); } else { tx.send(()).unwrap(); } @@ -164,9 +169,10 @@ impl Timer { /// invalidated at the end of that statement, and all `recv` calls will /// fail. /// - /// # Example + /// # Examples /// - /// ```rust + /// ``` + /// # #![feature(old_io, std_misc)] /// use std::old_io::Timer; /// use std::time::Duration; /// @@ -185,7 +191,8 @@ impl Timer { /// ten_milliseconds.recv().unwrap(); /// ``` /// - /// ```rust + /// ``` + /// # #![feature(old_io, std_misc)] /// use std::old_io::Timer; /// use std::time::Duration; /// @@ -204,7 +211,7 @@ impl Timer { // not clear what use a 0ms period is anyway... let ms = if ms == 0 { 1 } else { ms }; let (tx, rx) = channel(); - self.inner.period(ms, box TimerCallback { tx: tx }); + self.inner.period(ms, Box::new(TimerCallback { tx: tx })); return rx } } @@ -332,7 +339,7 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn oneshot_fail() { let mut timer = Timer::new().unwrap(); let _rx = timer.oneshot(Duration::milliseconds(1)); @@ -340,7 +347,7 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn period_fail() { let mut timer = Timer::new().unwrap(); let _rx = timer.periodic(Duration::milliseconds(1)); @@ -348,7 +355,7 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn normal_fail() { let _timer = Timer::new().unwrap(); panic!(); diff --git a/src/libstd/old_io/util.rs b/src/libstd/old_io/util.rs index 5ae239014d..818c8e76d6 100644 --- a/src/libstd/old_io/util.rs +++ b/src/libstd/old_io/util.rs @@ -10,21 +10,29 @@ //! Utility implementations of Reader and Writer +#![allow(deprecated)] + use prelude::v1::*; use cmp; -use old_io; +use old_io::{self, Reader, Writer, Buffer}; use slice::bytes::MutableByteVector; /// Wraps a `Reader`, limiting the number of bytes that can be read from it. #[derive(Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Take")] +#[unstable(feature = "old_io")] pub struct LimitReader { - limit: uint, + limit: usize, inner: R } +#[deprecated(since = "1.0.0", reason = "use std::io::Take")] +#[unstable(feature = "old_io")] impl LimitReader { /// Creates a new `LimitReader` - pub fn new(r: R, limit: uint) -> LimitReader { + #[deprecated(since = "1.0.0", reason = "use std::io's take method instead")] + #[unstable(feature = "old_io")] + pub fn new(r: R, limit: usize) -> LimitReader { LimitReader { limit: limit, inner: r } } @@ -38,11 +46,13 @@ impl LimitReader { /// /// The reader may reach EOF after reading fewer bytes than indicated by /// this method if the underlying reader reaches EOF. - pub fn limit(&self) -> uint { self.limit } + pub fn limit(&self) -> usize { self.limit } } +#[deprecated(since = "1.0.0", reason = "use std::io's take method instead")] +#[unstable(feature = "old_io")] impl Reader for LimitReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { if self.limit == 0 { return Err(old_io::standard_error(old_io::EndOfFile)); } @@ -57,6 +67,8 @@ impl Reader for LimitReader { } } +#[deprecated(since = "1.0.0", reason = "use std::io's take method instead")] +#[unstable(feature = "old_io")] impl Buffer for LimitReader { fn fill_buf<'a>(&'a mut self) -> old_io::IoResult<&'a [u8]> { let amt = try!(self.inner.fill_buf()); @@ -68,7 +80,7 @@ impl Buffer for LimitReader { } } - fn consume(&mut self, amt: uint) { + fn consume(&mut self, amt: usize) { // Don't let callers reset the limit by passing an overlarge value let amt = cmp::min(amt, self.limit); self.limit -= amt; @@ -78,51 +90,67 @@ impl Buffer for LimitReader { } /// A `Writer` which ignores bytes written to it, like /dev/null. -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::sink() instead")] +#[unstable(feature = "old_io")] pub struct NullWriter; +#[deprecated(since = "1.0.0", reason = "use std::io::sink() instead")] +#[unstable(feature = "old_io")] impl Writer for NullWriter { #[inline] fn write_all(&mut self, _buf: &[u8]) -> old_io::IoResult<()> { Ok(()) } } /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero. -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")] +#[unstable(feature = "old_io")] pub struct ZeroReader; +#[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")] +#[unstable(feature = "old_io")] impl Reader for ZeroReader { #[inline] - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { buf.set_memory(0); Ok(buf.len()) } } +#[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")] +#[unstable(feature = "old_io")] impl Buffer for ZeroReader { fn fill_buf<'a>(&'a mut self) -> old_io::IoResult<&'a [u8]> { static DATA: [u8; 64] = [0; 64]; Ok(&DATA) } - fn consume(&mut self, _amt: uint) {} + fn consume(&mut self, _amt: usize) {} } /// A `Reader` which is always at EOF, like /dev/null. -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")] +#[unstable(feature = "old_io")] pub struct NullReader; +#[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")] +#[unstable(feature = "old_io")] impl Reader for NullReader { #[inline] - fn read(&mut self, _buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, _buf: &mut [u8]) -> old_io::IoResult { Err(old_io::standard_error(old_io::EndOfFile)) } } +#[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")] +#[unstable(feature = "old_io")] impl Buffer for NullReader { fn fill_buf<'a>(&'a mut self) -> old_io::IoResult<&'a [u8]> { Err(old_io::standard_error(old_io::EndOfFile)) } - fn consume(&mut self, _amt: uint) {} + fn consume(&mut self, _amt: usize) {} } /// A `Writer` which multiplexes writes to a set of `Writer`s. @@ -130,17 +158,23 @@ impl Buffer for NullReader { /// The `Writer`s are delegated to in order. If any `Writer` returns an error, /// that error is returned immediately and remaining `Writer`s are not called. #[derive(Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Broadcast instead")] +#[unstable(feature = "old_io")] pub struct MultiWriter { writers: Vec } impl MultiWriter where W: Writer { /// Creates a new `MultiWriter` + #[deprecated(since = "1.0.0", reason = "use std::io's broadcast method instead")] + #[unstable(feature = "old_io")] pub fn new(writers: Vec) -> MultiWriter { MultiWriter { writers: writers } } } +#[deprecated(since = "1.0.0", reason = "use std::io::Broadcast instead")] +#[unstable(feature = "old_io")] impl Writer for MultiWriter where W: Writer { #[inline] fn write_all(&mut self, buf: &[u8]) -> old_io::IoResult<()> { @@ -162,6 +196,8 @@ impl Writer for MultiWriter where W: Writer { /// A `Reader` which chains input from multiple `Reader`s, reading each to /// completion before moving onto the next. #[derive(Clone, Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Chain instead")] +#[unstable(feature = "old_io")] pub struct ChainedReader { readers: I, cur_reader: Option, @@ -169,14 +205,18 @@ pub struct ChainedReader { impl> ChainedReader { /// Creates a new `ChainedReader` + #[deprecated(since = "1.0.0", reason = "use std::io's chain method instead")] + #[unstable(feature = "old_io")] pub fn new(mut readers: I) -> ChainedReader { let r = readers.next(); ChainedReader { readers: readers, cur_reader: r } } } +#[deprecated(since = "1.0.0", reason = "use std::io::Chain instead")] +#[unstable(feature = "old_io")] impl> Reader for ChainedReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { loop { let err = match self.cur_reader { Some(ref mut r) => { @@ -201,13 +241,19 @@ impl> Reader for ChainedReader { /// A `Reader` which forwards input from another `Reader`, passing it along to /// a `Writer` as well. Similar to the `tee(1)` command. #[derive(Debug)] +#[deprecated(since = "1.0.0", reason = "use std::io::Tee instead")] +#[unstable(feature = "old_io")] pub struct TeeReader { reader: R, writer: W, } +#[deprecated(since = "1.0.0", reason = "use std::io::Tee instead")] +#[unstable(feature = "old_io")] impl TeeReader { /// Creates a new `TeeReader` + #[deprecated(since = "1.0.0", reason = "use std::io's tee method instead")] + #[unstable(feature = "old_io")] pub fn new(r: R, w: W) -> TeeReader { TeeReader { reader: r, writer: w } } @@ -220,8 +266,10 @@ impl TeeReader { } } +#[deprecated(since = "1.0.0", reason = "use std::io::Tee instead")] +#[unstable(feature = "old_io")] impl Reader for TeeReader { - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { self.reader.read(buf).and_then(|len| { self.writer.write_all(&mut buf[..len]).map(|()| len) }) @@ -229,6 +277,8 @@ impl Reader for TeeReader { } /// Copies all data from a `Reader` to a `Writer`. +#[deprecated(since = "1.0.0", reason = "use std::io's copy function instead")] +#[unstable(feature = "old_io")] pub fn copy(r: &mut R, w: &mut W) -> old_io::IoResult<()> { let mut buf = [0; super::DEFAULT_BUF_SIZE]; loop { @@ -257,7 +307,7 @@ impl> IterReader { impl> Reader for IterReader { #[inline] - fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { + fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult { let mut len = 0; for (slot, elt) in buf.iter_mut().zip(self.iter.by_ref()) { *slot = elt; @@ -275,7 +325,7 @@ impl> Reader for IterReader { mod test { use prelude::v1::*; - use old_io::{MemReader, ByRefReader}; + use old_io::{MemReader, ByRefReader, Reader, Writer, Buffer}; use old_io; use super::*; @@ -284,7 +334,7 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 4); - assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); } } @@ -293,9 +343,9 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2)); { let mut r = LimitReader::new(r.by_ref(), 2); - assert_eq!(vec!(0, 1), r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1]); } - assert_eq!(vec!(2), r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [2]); } #[test] @@ -305,7 +355,7 @@ mod test { assert_eq!(3, r.limit()); assert_eq!(0, r.read_byte().unwrap()); assert_eq!(2, r.limit()); - assert_eq!(vec!(1, 2), r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [1, 2]); assert_eq!(0, r.limit()); } @@ -314,7 +364,7 @@ mod test { let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]); let mut r = LimitReader::new(r.by_ref(), 1); r.consume(2); - assert_eq!(vec![], r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), []); } #[test] @@ -330,7 +380,7 @@ mod test { let mut s = ZeroReader; let mut buf = vec![1, 2, 3]; assert_eq!(s.read(&mut buf), Ok(3)); - assert_eq!(vec![0, 0, 0], buf); + assert_eq!(buf, [0, 0, 0]); } #[test] @@ -342,8 +392,8 @@ mod test { #[test] fn test_multi_writer() { - static mut writes: uint = 0; - static mut flushes: uint = 0; + static mut writes: usize = 0; + static mut flushes: usize = 0; struct TestWriter; impl Writer for TestWriter { @@ -373,16 +423,16 @@ mod test { let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()), MemReader::new(vec!(2, 3))); let mut r = ChainedReader::new(rs.into_iter()); - assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]); } #[test] fn test_tee_reader() { let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)), Vec::new()); - assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap()); + assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]); let (_, w) = r.into_inner(); - assert_eq!(vec!(0, 1, 2), w); + assert_eq!(w, [0, 1, 2]); } #[test] @@ -390,12 +440,13 @@ mod test { let mut r = MemReader::new(vec!(0, 1, 2, 3, 4)); let mut w = Vec::new(); copy(&mut r, &mut w).unwrap(); - assert_eq!(vec!(0, 1, 2, 3, 4), w); + assert_eq!(w, [0, 1, 2, 3, 4]); } #[test] fn limit_reader_buffer() { - let r = &mut b"0123456789\n0123456789\n"; + let mut r: &[u8] = b"0123456789\n0123456789\n"; + let r = &mut r; { let mut r = LimitReader::new(r.by_ref(), 3); assert_eq!(r.read_line(), Ok("012".to_string())); @@ -418,7 +469,7 @@ mod test { #[test] fn test_iter_reader() { - let mut r = IterReader::new(0u8..8); + let mut r = IterReader::new(0..8); let mut buf = [0, 0, 0]; let len = r.read(&mut buf).unwrap(); assert_eq!(len, 3); @@ -437,7 +488,7 @@ mod test { #[test] fn iter_reader_zero_length() { - let mut r = IterReader::new(0u8..8); + let mut r = IterReader::new(0..8); let mut buf = []; assert_eq!(Ok(0), r.read(&mut buf)); } diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index e9005aa22b..9c88533d3b 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -46,10 +46,12 @@ //! suitable for passing to any API that actually operates on the path; it is only intended for //! display. //! -//! ## Example +//! ## Examples //! //! ```rust +//! # #![feature(old_path, old_io)] //! use std::old_io::fs::PathExtensions; +//! use std::old_path::{Path, GenericPath}; //! //! let mut path = Path::new("/tmp/path"); //! println!("path: {}", path.display()); @@ -60,18 +62,20 @@ //! ``` #![unstable(feature = "old_path")] +#![deprecated(since = "1.0.0", reason = "use std::path instead")] +#![allow(deprecated)] // seriously this is all deprecated +#![allow(unused_imports)] use core::marker::Sized; use ffi::CString; use clone::Clone; +use borrow::Cow; use fmt; -use iter::IteratorExt; +use iter::Iterator; use option::Option; use option::Option::{None, Some}; use str; -use str::StrExt; -use string::{String, CowString}; -use slice::SliceExt; +use string::String; use vec::Vec; /// Typedef for POSIX file paths. @@ -138,9 +142,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Creates a new Path from a byte vector or string. /// The resulting Path will always be normalized. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -162,9 +168,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Creates a new Path from a byte vector or string, if possible. /// The resulting Path will always be normalized. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -184,9 +192,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the path as a string, if possible. /// If the path is not representable in utf-8, this returns None. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -201,9 +211,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the path as a byte vector /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -215,9 +227,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Converts the Path into an owned byte vector /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -230,9 +244,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns an object that implements `Display` for printing paths /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -248,9 +264,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// /// If there is no filename, nothing will be printed. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -265,9 +283,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the directory component of `self`, as a byte vector (with no trailing separator). /// If `self` has no directory component, returns ['.']. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -280,9 +300,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the directory component of `self`, as a string, if possible. /// See `dirname` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -299,14 +321,16 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// If `self` represents the root of the file hierarchy, returns None. /// If `self` is "." or "..", returns None. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let p = Path::new("abc/def/ghi"); - /// assert_eq!(p.filename(), Some(b"ghi")); + /// assert_eq!(p.filename(), Some(&b"ghi"[..])); /// # } /// ``` fn filename<'a>(&'a self) -> Option<&'a [u8]>; @@ -314,9 +338,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the file component of `self`, as a string, if possible. /// See `filename` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -333,14 +359,16 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// The stem is the portion of the filename just before the last '.'. /// If there is no '.', the entire filename is returned. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let p = Path::new("/abc/def.txt"); - /// assert_eq!(p.filestem(), Some(b"def")); + /// assert_eq!(p.filestem(), Some(&b"def"[..])); /// # } /// ``` fn filestem<'a>(&'a self) -> Option<&'a [u8]> { @@ -360,9 +388,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the stem of the filename of `self`, as a string, if possible. /// See `filestem` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -380,14 +410,16 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// If there is no extension, None is returned. /// If the filename ends in '.', the empty vector is returned. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { /// let p = Path::new("abc/def.txt"); - /// assert_eq!(p.extension(), Some(b"txt")); + /// assert_eq!(p.extension(), Some(&b"txt"[..])); /// # } /// ``` fn extension<'a>(&'a self) -> Option<&'a [u8]> { @@ -407,9 +439,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the extension of the filename of `self`, as a string, if possible. /// See `extension` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -425,9 +459,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Replaces the filename portion of the path with the given byte vector or string. /// If the replacement name is [], this is equivalent to popping the path. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -451,9 +487,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// If the argument is [] or "", this removes the extension. /// If `self` has no filename, this is a no-op. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -501,9 +539,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// byte vector or string. /// See `set_filename` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -526,9 +566,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// byte vector or string. /// See `set_extension` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -550,9 +592,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns the directory component of `self`, as a Path. /// If `self` represents the root of the filesystem hierarchy, returns `self`. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -569,9 +613,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// /// If `self` is not absolute, or vol/cwd-relative in the case of Windows, this returns None. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -584,9 +630,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Pushes a path (as a byte vector or string) onto `self`. /// If the argument represents an absolute path, it replaces `self`. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -608,9 +656,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Pushes multiple paths (as byte vectors or strings) onto `self`. /// See `push` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -637,9 +687,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns `true` if the receiver was modified, or `false` if it already /// represented the root of the file hierarchy. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -654,9 +706,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// (as a byte vector or string). /// If the given path is absolute, the new Path will represent just that. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -679,9 +733,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// (as byte vectors or strings). /// See `join` for details. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -701,9 +757,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// An absolute path is defined as one that, when joined to another path, will /// yield back the same absolute path. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -718,9 +776,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// But for Windows paths, it also means the path is not volume-relative or /// relative to the current working directory. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -736,9 +796,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// If both paths are relative, they are compared as though they are relative /// to the same parent path. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -755,9 +817,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// If `self` is absolute and `base` is relative, or on Windows if both /// paths refer to separate drives, an absolute path is returned. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -771,9 +835,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe { /// Returns whether the relative path `child` is a suffix of `self`. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// # foo(); /// # #[cfg(windows)] fn foo() {} /// # #[cfg(unix)] fn foo() { @@ -842,7 +908,7 @@ impl<'a, P: GenericPath> Display<'a, P> { /// If the path is not UTF-8, invalid sequences will be replaced with the /// Unicode replacement char. This involves allocation. #[inline] - pub fn as_cow(&self) -> CowString<'a> { + pub fn as_cow(&self) -> Cow<'a, str> { String::from_utf8_lossy(if self.filename { match self.path.filename() { None => { diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index 15eee9e4a0..c517fab257 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -16,12 +16,12 @@ use fmt; use hash; use old_io::Writer; use iter::{AdditiveIterator, Extend}; -use iter::{Iterator, IteratorExt, Map}; +use iter::{Iterator, Map}; use marker::Sized; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; -use slice::{AsSlice, Split, SliceExt, SliceConcatExt}; -use str::{self, FromStr, StrExt}; +use slice::{Split, SliceConcatExt}; +use str::{self, FromStr}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; @@ -37,7 +37,7 @@ pub type StrComponents<'a> = #[derive(Clone)] pub struct Path { repr: Vec, // assumed to never be empty or contain NULs - sepidx: Option // index of the final separator in repr + sepidx: Option // index of the final separator in repr } /// The standard path separator character @@ -100,14 +100,6 @@ impl FromStr for Path { #[derive(Debug, Clone, PartialEq, Copy)] pub struct ParsePathError; -#[cfg(stage0)] -impl hash::Hash for Path { - #[inline] - fn hash(&self, state: &mut S) { - self.repr.hash(state) - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl hash::Hash for Path { #[inline] @@ -134,7 +126,7 @@ impl GenericPathUnsafe for Path { unsafe fn set_filename_unchecked(&mut self, filename: T) { let filename = filename.container_as_bytes(); match self.sepidx { - None if b".." == self.repr => { + None if self.repr == b".." => { let mut v = Vec::with_capacity(3 + filename.len()); v.push_all(dot_dot_static); v.push(SEP_BYTE); @@ -194,7 +186,7 @@ impl GenericPath for Path { fn dirname<'a>(&'a self) -> &'a [u8] { match self.sepidx { - None if b".." == self.repr => &self.repr, + None if self.repr == b".." => &self.repr, None => dot_static, Some(0) => &self.repr[..1], Some(idx) if &self.repr[idx+1..] == b".." => &self.repr, @@ -204,8 +196,7 @@ impl GenericPath for Path { fn filename<'a>(&'a self) -> Option<&'a [u8]> { match self.sepidx { - None if b"." == self.repr || - b".." == self.repr => None, + None if self.repr == b"." || self.repr == b".." => None, None => Some(&self.repr), Some(idx) if &self.repr[idx+1..] == b".." => None, Some(0) if self.repr[1..].is_empty() => None, @@ -215,13 +206,13 @@ impl GenericPath for Path { fn pop(&mut self) -> bool { match self.sepidx { - None if b"." == self.repr => false, + None if self.repr == b"." => false, None => { self.repr = vec![b'.']; self.sepidx = None; true } - Some(0) if b"/" == self.repr => false, + Some(0) if self.repr == b"/" => false, Some(idx) => { if idx == 0 { self.repr.truncate(idx+1); @@ -253,7 +244,7 @@ impl GenericPath for Path { } else { let mut ita = self.components(); let mut itb = other.components(); - if b"." == self.repr { + if self.repr == b"." { return match itb.next() { None => true, Some(b) => b != b".." @@ -347,11 +338,11 @@ impl Path { /// Returns a normalized byte vector representation of a path, by removing all empty /// components, and unnecessary . and .. components. - fn normalize>(v: &V) -> Vec { + fn normalize(v: &[u8]) -> Vec { // borrowck is being very picky let val = { - let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE; - let v_ = if is_abs { &v.as_slice()[1..] } else { v.as_slice() }; + let is_abs = !v.is_empty() && v[0] == SEP_BYTE; + let v_ = if is_abs { &v[1..] } else { v }; let comps = normalize_helper(v_, is_abs); match comps { None => None, @@ -379,7 +370,7 @@ impl Path { } }; match val { - None => v.as_slice().to_vec(), + None => v.to_vec(), Some(val) => val } } @@ -452,13 +443,12 @@ mod tests { use super::*; use clone::Clone; - use iter::IteratorExt; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::{AsSlice, SliceExt}; - use str::{self, Str, StrExt}; + use str; use string::ToString; use vec::Vec; + use iter::Iterator; macro_rules! t { (s: $path:expr, $exp:expr) => ( @@ -479,11 +469,11 @@ mod tests { fn test_paths() { let empty: &[u8] = &[]; t!(v: Path::new(empty), b"."); - t!(v: Path::new(b"/"), b"/"); - t!(v: Path::new(b"a/b/c"), b"a/b/c"); - t!(v: Path::new(b"a/b/c\xFF"), b"a/b/c\xFF"); - t!(v: Path::new(b"\xFF/../foo\x80"), b"foo\x80"); - let p = Path::new(b"a/b/c\xFF"); + t!(v: Path::new(&b"/"[..]), b"/"); + t!(v: Path::new(&b"a/b/c"[..]), b"a/b/c"); + t!(v: Path::new(&b"a/b/c\xFF"[..]), b"a/b/c\xFF"); + t!(v: Path::new(&b"\xFF/../foo\x80"[..]), b"foo\x80"); + let p = Path::new(&b"a/b/c\xFF"[..]); assert!(p.as_str().is_none()); t!(s: Path::new(""), "."); @@ -509,18 +499,18 @@ mod tests { t!(s: Path::new("foo/../../.."), "../.."); t!(s: Path::new("foo/../../bar"), "../bar"); - assert_eq!(Path::new(b"foo/bar").into_vec(), b"foo/bar"); - assert_eq!(Path::new(b"/foo/../../bar").into_vec(), + assert_eq!(Path::new(&b"foo/bar"[..]).into_vec(), b"foo/bar"); + assert_eq!(Path::new(&b"/foo/../../bar"[..]).into_vec(), b"/bar"); - let p = Path::new(b"foo/bar\x80"); + let p = Path::new(&b"foo/bar\x80"[..]); assert!(p.as_str().is_none()); } #[test] fn test_opt_paths() { - assert!(Path::new_opt(b"foo/bar\0").is_none()); - t!(v: Path::new_opt(b"foo/bar").unwrap(), b"foo/bar"); + assert!(Path::new_opt(&b"foo/bar\0"[..]).is_none()); + t!(v: Path::new_opt(&b"foo/bar"[..]).unwrap(), b"foo/bar"); assert!(Path::new_opt("foo/bar\0").is_none()); t!(s: Path::new_opt("foo/bar").unwrap(), "foo/bar"); } @@ -529,17 +519,17 @@ mod tests { fn test_null_byte() { use thread; let result = thread::spawn(move|| { - Path::new(b"foo/bar\0"); + Path::new(&b"foo/bar\0"[..]); }).join(); assert!(result.is_err()); let result = thread::spawn(move|| { - Path::new("test").set_filename(b"f\0o") + Path::new("test").set_filename(&b"f\0o"[..]) }).join(); assert!(result.is_err()); let result = thread::spawn(move|| { - Path::new("test").push(b"f\0o"); + Path::new("test").push(&b"f\0o"[..]); }).join(); assert!(result.is_err()); } @@ -555,11 +545,11 @@ mod tests { ) } t!("foo", display, "foo"); - t!(b"foo\x80", display, "foo\u{FFFD}"); - t!(b"foo\xFFbar", display, "foo\u{FFFD}bar"); - t!(b"foo\xFF/bar", filename_display, "bar"); - t!(b"foo/\xFFbar", filename_display, "\u{FFFD}bar"); - t!(b"/", filename_display, ""); + t!(&b"foo\x80"[..], display, "foo\u{FFFD}"); + t!(&b"foo\xFFbar"[..], display, "foo\u{FFFD}bar"); + t!(&b"foo\xFF/bar"[..], filename_display, "bar"); + t!(&b"foo/\xFFbar"[..], filename_display, "\u{FFFD}bar"); + t!(&b"/"[..], filename_display, ""); macro_rules! t { ($path:expr, $exp:expr) => ( @@ -579,11 +569,11 @@ mod tests { } t!("foo", "foo"); - t!(b"foo\x80", "foo\u{FFFD}"); - t!(b"foo\xFFbar", "foo\u{FFFD}bar"); - t!(b"foo\xFF/bar", "bar", filename); - t!(b"foo/\xFFbar", "\u{FFFD}bar", filename); - t!(b"/", "", filename); + t!(&b"foo\x80"[..], "foo\u{FFFD}"); + t!(&b"foo\xFFbar"[..], "foo\u{FFFD}bar"); + t!(&b"foo\xFF/bar"[..], "bar", filename); + t!(&b"foo/\xFFbar"[..], "\u{FFFD}bar", filename); + t!(&b"/"[..], "", filename); } #[test] @@ -600,13 +590,13 @@ mod tests { ) } - t!(b"foo", "foo", "foo"); - t!(b"foo/bar", "foo/bar", "bar"); - t!(b"/", "/", ""); - t!(b"foo\xFF", "foo\u{FFFD}", "foo\u{FFFD}"); - t!(b"foo\xFF/bar", "foo\u{FFFD}/bar", "bar"); - t!(b"foo/\xFFbar", "foo/\u{FFFD}bar", "\u{FFFD}bar"); - t!(b"\xFFfoo/bar\xFF", "\u{FFFD}foo/bar\u{FFFD}", "bar\u{FFFD}"); + t!(&b"foo"[..], "foo", "foo"); + t!(&b"foo/bar"[..], "foo/bar", "bar"); + t!(&b"/"[..], "/", ""); + t!(&b"foo\xFF"[..], "foo\u{FFFD}", "foo\u{FFFD}"); + t!(&b"foo\xFF/bar"[..], "foo\u{FFFD}/bar", "bar"); + t!(&b"foo/\xFFbar"[..], "foo/\u{FFFD}bar", "\u{FFFD}bar"); + t!(&b"\xFFfoo/bar\xFF"[..], "\u{FFFD}foo/bar\u{FFFD}", "bar\u{FFFD}"); } #[test] @@ -634,9 +624,9 @@ mod tests { ); } - t!(v: b"a/b/c", filename, Some(b"c")); - t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF")); - t!(v: b"a/b\xFF/c", filename, Some(b"c")); + t!(v: &b"a/b/c"[..], filename, Some(&b"c"[..])); + t!(v: &b"a/b/c\xFF"[..], filename, Some(&b"c\xFF"[..])); + t!(v: &b"a/b\xFF/c"[..], filename, Some(&b"c"[..])); t!(s: "a/b/c", filename, Some("c"), opt); t!(s: "/a/b/c", filename, Some("c"), opt); t!(s: "a", filename, Some("a"), opt); @@ -646,9 +636,9 @@ mod tests { t!(s: "..", filename, None, opt); t!(s: "../..", filename, None, opt); - t!(v: b"a/b/c", dirname, b"a/b"); - t!(v: b"a/b/c\xFF", dirname, b"a/b"); - t!(v: b"a/b\xFF/c", dirname, b"a/b\xFF"); + t!(v: &b"a/b/c"[..], dirname, b"a/b"); + t!(v: &b"a/b/c\xFF"[..], dirname, b"a/b"); + t!(v: &b"a/b\xFF/c"[..], dirname, b"a/b\xFF"); t!(s: "a/b/c", dirname, "a/b"); t!(s: "/a/b/c", dirname, "/a/b"); t!(s: "a", dirname, "."); @@ -658,9 +648,9 @@ mod tests { t!(s: "..", dirname, ".."); t!(s: "../..", dirname, "../.."); - t!(v: b"hi/there.txt", filestem, Some(b"there")); - t!(v: b"hi/there\x80.txt", filestem, Some(b"there\x80")); - t!(v: b"hi/there.t\x80xt", filestem, Some(b"there")); + t!(v: &b"hi/there.txt"[..], filestem, Some(&b"there"[..])); + t!(v: &b"hi/there\x80.txt"[..], filestem, Some(&b"there\x80"[..])); + t!(v: &b"hi/there.t\x80xt"[..], filestem, Some(&b"there"[..])); t!(s: "hi/there.txt", filestem, Some("there"), opt); t!(s: "hi/there", filestem, Some("there"), opt); t!(s: "there.txt", filestem, Some("there"), opt); @@ -674,11 +664,11 @@ mod tests { t!(s: "..", filestem, None, opt); t!(s: "../..", filestem, None, opt); - t!(v: b"hi/there.txt", extension, Some(b"txt")); - t!(v: b"hi/there\x80.txt", extension, Some(b"txt")); - t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt")); - t!(v: b"hi/there", extension, None); - t!(v: b"hi/there\x80", extension, None); + t!(v: &b"hi/there.txt"[..], extension, Some(&b"txt"[..])); + t!(v: &b"hi/there\x80.txt"[..], extension, Some(&b"txt"[..])); + t!(v: &b"hi/there.t\x80xt"[..], extension, Some(&b"t\x80xt"[..])); + t!(v: &b"hi/there"[..], extension, None); + t!(v: &b"hi/there\x80"[..], extension, None); t!(s: "hi/there.txt", extension, Some("txt"), opt); t!(s: "hi/there", extension, None, opt); t!(s: "there.txt", extension, Some("txt"), opt); @@ -758,9 +748,9 @@ mod tests { t!(s: "a/b/c", ["d", "/e"], "/e"); t!(s: "a/b/c", ["d", "/e", "f"], "/e/f"); t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e"); - t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e"); - t!(v: b"a/b/c", [b"d", b"/e", b"f"], b"/e/f"); - t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e"); + t!(v: &b"a/b/c"[..], [&b"d"[..], &b"e"[..]], b"a/b/c/d/e"); + t!(v: &b"a/b/c"[..], [&b"d"[..], &b"/e"[..], &b"f"[..]], b"/e/f"); + t!(v: &b"a/b/c"[..], [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e"); } #[test] @@ -784,15 +774,15 @@ mod tests { ) } - t!(b: b"a/b/c", b"a/b", true); - t!(b: b"a", b".", true); - t!(b: b".", b".", false); - t!(b: b"/a", b"/", true); - t!(b: b"/", b"/", false); - t!(b: b"a/b/c\x80", b"a/b", true); - t!(b: b"a/b\x80/c", b"a/b\x80", true); - t!(b: b"\xFF", b".", true); - t!(b: b"/\xFF", b"/", true); + t!(b: &b"a/b/c"[..], b"a/b", true); + t!(b: &b"a"[..], b".", true); + t!(b: &b"."[..], b".", false); + t!(b: &b"/a"[..], b"/", true); + t!(b: &b"/"[..], b"/", false); + t!(b: &b"a/b/c\x80"[..], b"a/b", true); + t!(b: &b"a/b\x80/c"[..], b"a/b\x80", true); + t!(b: &b"\xFF"[..], b".", true); + t!(b: &b"/\xFF"[..], b"/", true); t!(s: "a/b/c", "a/b", true); t!(s: "a", ".", true); t!(s: ".", ".", false); @@ -802,15 +792,15 @@ mod tests { #[test] fn test_root_path() { - assert_eq!(Path::new(b"a/b/c").root_path(), None); - assert_eq!(Path::new(b"/a/b/c").root_path(), Some(Path::new("/"))); + assert_eq!(Path::new(&b"a/b/c"[..]).root_path(), None); + assert_eq!(Path::new(&b"/a/b/c"[..]).root_path(), Some(Path::new("/"))); } #[test] fn test_join() { - t!(v: Path::new(b"a/b/c").join(b".."), b"a/b"); - t!(v: Path::new(b"/a/b/c").join(b"d"), b"/a/b/c/d"); - t!(v: Path::new(b"a/\x80/c").join(b"\xFF"), b"a/\x80/c/\xFF"); + t!(v: Path::new(&b"a/b/c"[..]).join(&b".."[..]), b"a/b"); + t!(v: Path::new(&b"/a/b/c"[..]).join(&b"d"[..]), b"/a/b/c/d"); + t!(v: Path::new(&b"a/\x80/c"[..]).join(&b"\xFF"[..]), b"a/\x80/c/\xFF"); t!(s: Path::new("a/b/c").join(".."), "a/b"); t!(s: Path::new("/a/b/c").join("d"), "/a/b/c/d"); t!(s: Path::new("a/b").join("c/d"), "a/b/c/d"); @@ -863,17 +853,17 @@ mod tests { t!(s: "a/b/c", ["..", "d"], "a/b/d"); t!(s: "a/b/c", ["d", "/e", "f"], "/e/f"); t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e"); - t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e"); - t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e"); + t!(v: &b"a/b/c"[..], [&b"d"[..], &b"e"[..]], b"a/b/c/d/e"); + t!(v: &b"a/b/c"[..], [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e"); } #[test] fn test_with_helpers() { let empty: &[u8] = &[]; - t!(v: Path::new(b"a/b/c").with_filename(b"d"), b"a/b/d"); - t!(v: Path::new(b"a/b/c\xFF").with_filename(b"\x80"), b"a/b/\x80"); - t!(v: Path::new(b"/\xFF/foo").with_filename(b"\xCD"), + t!(v: Path::new(&b"a/b/c"[..]).with_filename(&b"d"[..]), b"a/b/d"); + t!(v: Path::new(&b"a/b/c\xFF"[..]).with_filename(&b"\x80"[..]), b"a/b/\x80"); + t!(v: Path::new(&b"/\xFF/foo"[..]).with_filename(&b"\xCD"[..]), b"/\xFF/\xCD"); t!(s: Path::new("a/b/c").with_filename("d"), "a/b/d"); t!(s: Path::new(".").with_filename("foo"), "foo"); @@ -895,13 +885,13 @@ mod tests { t!(s: Path::new("..").with_filename(""), ".."); t!(s: Path::new("../..").with_filename(""), "../.."); - t!(v: Path::new(b"hi/there\x80.txt").with_extension(b"exe"), + t!(v: Path::new(&b"hi/there\x80.txt"[..]).with_extension(&b"exe"[..]), b"hi/there\x80.exe"); - t!(v: Path::new(b"hi/there.txt\x80").with_extension(b"\xFF"), + t!(v: Path::new(&b"hi/there.txt\x80"[..]).with_extension(&b"\xFF"[..]), b"hi/there.\xFF"); - t!(v: Path::new(b"hi/there\x80").with_extension(b"\xFF"), + t!(v: Path::new(&b"hi/there\x80"[..]).with_extension(&b"\xFF"[..]), b"hi/there\x80.\xFF"); - t!(v: Path::new(b"hi/there.\xFF").with_extension(empty), b"hi/there"); + t!(v: Path::new(&b"hi/there.\xFF"[..]).with_extension(empty), b"hi/there"); t!(s: Path::new("hi/there.txt").with_extension("exe"), "hi/there.exe"); t!(s: Path::new("hi/there.txt").with_extension(""), "hi/there"); t!(s: Path::new("hi/there.txt").with_extension("."), "hi/there.."); @@ -943,17 +933,17 @@ mod tests { ) } - t!(v: b"a/b/c", set_filename, with_filename, b"d"); - t!(v: b"/", set_filename, with_filename, b"foo"); - t!(v: b"\x80", set_filename, with_filename, b"\xFF"); + t!(v: &b"a/b/c"[..], set_filename, with_filename, &b"d"[..]); + t!(v: &b"/"[..], set_filename, with_filename, &b"foo"[..]); + t!(v: &b"\x80"[..], set_filename, with_filename, &b"\xFF"[..]); t!(s: "a/b/c", set_filename, with_filename, "d"); t!(s: "/", set_filename, with_filename, "foo"); t!(s: ".", set_filename, with_filename, "foo"); t!(s: "a/b", set_filename, with_filename, ""); t!(s: "a", set_filename, with_filename, ""); - t!(v: b"hi/there.txt", set_extension, with_extension, b"exe"); - t!(v: b"hi/there.t\x80xt", set_extension, with_extension, b"exe\xFF"); + t!(v: &b"hi/there.txt"[..], set_extension, with_extension, &b"exe"[..]); + t!(v: &b"hi/there.t\x80xt"[..], set_extension, with_extension, &b"exe\xFF"[..]); t!(s: "hi/there.txt", set_extension, with_extension, "exe"); t!(s: "hi/there.", set_extension, with_extension, "txt"); t!(s: "hi/there", set_extension, with_extension, "txt"); @@ -985,10 +975,10 @@ mod tests { ) } - t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None); - t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None); - t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi", - Some(b"there"), Some(b"\xFF")); + t!(v: Path::new(&b"a/b/c"[..]), Some(&b"c"[..]), b"a/b", Some(&b"c"[..]), None); + t!(v: Path::new(&b"a/b/\xFF"[..]), Some(&b"\xFF"[..]), b"a/b", Some(&b"\xFF"[..]), None); + t!(v: Path::new(&b"hi/there.\xFF"[..]), Some(&b"there.\xFF"[..]), b"hi", + Some(&b"there"[..]), Some(&b"\xFF"[..])); t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None); t!(s: Path::new("."), None, Some("."), None, None); t!(s: Path::new("/"), None, Some("/"), None, None); @@ -1002,16 +992,16 @@ mod tests { t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None); t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"), Some("."), Some("there")); - t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None); - t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt")); - t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None); - t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None); + t!(s: Path::new(&b"a/b/\xFF"[..]), None, Some("a/b"), None, None); + t!(s: Path::new(&b"a/b/\xFF.txt"[..]), None, Some("a/b"), None, Some("txt")); + t!(s: Path::new(&b"a/b/c.\x80"[..]), None, Some("a/b"), Some("c"), None); + t!(s: Path::new(&b"\xFF/b"[..]), Some("b"), None, Some("b"), None); } #[test] fn test_dir_path() { - t!(v: Path::new(b"hi/there\x80").dir_path(), b"hi"); - t!(v: Path::new(b"hi\xFF/there").dir_path(), b"hi\xFF"); + t!(v: Path::new(&b"hi/there\x80"[..]).dir_path(), b"hi"); + t!(v: Path::new(&b"hi\xFF/there"[..]).dir_path(), b"hi\xFF"); t!(s: Path::new("hi/there").dir_path(), "hi"); t!(s: Path::new("hi").dir_path(), "."); t!(s: Path::new("/hi").dir_path(), "/"); @@ -1109,9 +1099,9 @@ mod tests { t!(s: "/a/b/c", "d/e/f", false); t!(s: "a/b/c", "a/b", false); t!(s: "a/b/c", "b", false); - t!(v: b"a/b/c", b"b/c", true); - t!(v: b"a/b/\xFF", b"\xFF", true); - t!(v: b"a/b/\xFF", b"b/\xFF", true); + t!(v: &b"a/b/c"[..], &b"b/c"[..], true); + t!(v: &b"a/b/\xFF"[..], &b"\xFF"[..], true); + t!(v: &b"a/b/\xFF"[..], &b"b/\xFF"[..], true); } #[test] @@ -1187,9 +1177,9 @@ mod tests { ) } - t!(b: b"a/b/c", [b"a", b"b", b"c"]); - t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]); - t!(b: b"../../foo\xCDbar", [b"..", b"..", b"foo\xCDbar"]); + t!(b: &b"a/b/c"[..], [b"a", b"b", b"c"]); + t!(b: &b"/\xFF/a/\x80"[..], [b"\xFF", b"a", b"\x80"]); + t!(b: &b"../../foo\xCDbar"[..], [b"..", b"..", b"foo\xCDbar"]); t!(s: "a/b/c", ["a", "b", "c"]); t!(s: "a/b/d", ["a", "b", "d"]); t!(s: "a/b/cd", ["a", "b", "cd"]); @@ -1219,9 +1209,9 @@ mod tests { ) } - t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]); - t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]); - t!(b: b"../../foo\xCDbar", [Some(".."), Some(".."), None]); + t!(b: &b"a/b/c"[..], [Some("a"), Some("b"), Some("c")]); + t!(b: &b"/\xFF/a/\x80"[..], [None, Some("a"), None]); + t!(b: &b"../../foo\xCDbar"[..], [Some(".."), Some(".."), None]); // str_components is a wrapper around components, so no need to do // the full set of tests } @@ -1232,7 +1222,8 @@ mod bench { extern crate test; use self::test::Bencher; use super::*; - use prelude::v1::{Clone, GenericPath}; + use old_path::GenericPath; + use prelude::v1::Clone; #[bench] fn join_home_dir(b: &mut Bencher) { diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index 887dc804c7..0b88f368b3 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -15,19 +15,18 @@ use self::PathPrefix::*; use ascii::AsciiExt; -use char::CharExt; use clone::Clone; use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd}; use fmt; use hash; use old_io::Writer; use iter::{AdditiveIterator, Extend}; -use iter::{Iterator, IteratorExt, Map, repeat}; +use iter::{Iterator, Map, repeat}; use mem; use option::Option::{self, Some, None}; use result::Result::{self, Ok, Err}; -use slice::{SliceExt, SliceConcatExt}; -use str::{SplitTerminator, FromStr, StrExt}; +use slice::SliceConcatExt; +use str::{SplitTerminator, FromStr}; use string::{String, ToString}; use vec::Vec; @@ -82,7 +81,7 @@ pub type Components<'a> = pub struct Path { repr: String, // assumed to never be empty prefix: Option, - sepidx: Option // index of the final separator in the non-prefix portion of repr + sepidx: Option // index of the final separator in the non-prefix portion of repr } #[stable(feature = "rust1", since = "1.0.0")] @@ -127,21 +126,6 @@ impl FromStr for Path { #[derive(Debug, Clone, PartialEq, Copy)] pub struct ParsePathError; -#[cfg(stage0)] -impl hash::Hash for Path { - #[cfg(not(test))] - #[inline] - fn hash(&self, state: &mut S) { - self.repr.hash(state) - } - - #[cfg(test)] - #[inline] - fn hash(&self, _: &mut S) { - // No-op because the `hash` implementation will be wrong. - } -} -#[cfg(not(stage0))] #[stable(feature = "rust1", since = "1.0.0")] impl hash::Hash for Path { #[cfg(not(test))] @@ -522,7 +506,7 @@ impl GenericPath for Path { fn path_relative_from(&self, base: &Path) -> Option { fn comp_requires_verbatim(s: &str) -> bool { - s == "." || s == ".." || s.contains_char(SEP2) + s == "." || s == ".." || s.contains(SEP2) } if !self.equiv_prefix(base) { @@ -618,9 +602,11 @@ impl Path { /// /// Panics if the vector contains a `NUL`, or if it contains invalid UTF-8. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// println!("{}", Path::new(r"C:\some\path").display()); /// ``` #[inline] @@ -632,9 +618,11 @@ impl Path { /// /// Returns `None` if the vector contains a `NUL`, or if it contains invalid UTF-8. /// - /// # Example + /// # Examples /// /// ``` + /// # #![feature(old_path)] + /// use std::old_path::{Path, GenericPath}; /// let path = Path::new_opt(r"C:\some\path"); /// /// match path { @@ -761,7 +749,7 @@ impl Path { if prefix.is_some() && comps.is_empty() { match prefix.unwrap() { DiskPrefix => { - let len = prefix_len(prefix) + is_abs as uint; + let len = prefix_len(prefix) + is_abs as usize; let mut s = String::from_str(&s[..len]); unsafe { let v = s.as_mut_vec(); @@ -776,7 +764,7 @@ impl Path { Some(s) } VerbatimDiskPrefix => { - let len = prefix_len(prefix) + is_abs as uint; + let len = prefix_len(prefix) + is_abs as usize; let mut s = String::from_str(&s[..len]); unsafe { let v = s.as_mut_vec(); @@ -850,7 +838,7 @@ impl Path { self.sepidx = idx.and_then(|x| if x < prefixlen { None } else { Some(x) }); } - fn prefix_len(&self) -> uint { + fn prefix_len(&self) -> usize { prefix_len(self.prefix) } @@ -859,7 +847,7 @@ impl Path { // end is the length of the string, normally, or the index of the final character if it is // a non-semantic trailing separator in a verbatim string. // If the prefix is considered the separator, before and after are the same. - fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> { + fn sepidx_or_prefix_len(&self) -> Option<(usize,usize,usize)> { match self.sepidx { None => match self.prefix_len() { 0 => None, x => Some((x,x,self.repr.len())) }, Some(x) => { @@ -985,16 +973,16 @@ pub fn is_sep_byte_verbatim(u: &u8) -> bool { /// Prefix types for Path #[derive(Copy, PartialEq, Clone, Debug)] pub enum PathPrefix { - /// Prefix `\\?\`, uint is the length of the following component - VerbatimPrefix(uint), + /// Prefix `\\?\`, usize is the length of the following component + VerbatimPrefix(usize), /// Prefix `\\?\UNC\`, uints are the lengths of the UNC components - VerbatimUNCPrefix(uint, uint), + VerbatimUNCPrefix(usize, usize), /// Prefix `\\?\C:\` (for any alphabetic character) VerbatimDiskPrefix, - /// Prefix `\\.\`, uint is the length of the following component - DeviceNSPrefix(uint), + /// Prefix `\\.\`, usize is the length of the following component + DeviceNSPrefix(usize), /// UNC prefix `\\server\share`, uints are the lengths of the server/share - UNCPrefix(uint, uint), + UNCPrefix(usize, usize), /// Prefix `C:` for any alphabetic character DiskPrefix } @@ -1049,7 +1037,7 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { } return None; - fn parse_two_comps(mut path: &str, f: fn(char) -> bool) -> Option<(uint, uint)> { + fn parse_two_comps(mut path: &str, f: fn(char) -> bool) -> Option<(usize, usize)> { let idx_a = match path.find(f) { None => return None, Some(x) => x @@ -1119,7 +1107,7 @@ fn prefix_is_verbatim(p: Option) -> bool { } } -fn prefix_len(p: Option) -> uint { +fn prefix_len(p: Option) -> usize { match p { None => 0, Some(VerbatimPrefix(x)) => 4 + x, @@ -1138,11 +1126,9 @@ mod tests { use super::*; use clone::Clone; - use iter::IteratorExt; + use iter::Iterator; use option::Option::{self, Some, None}; use old_path::GenericPath; - use slice::{AsSlice, SliceExt}; - use str::Str; use string::ToString; use vec::Vec; @@ -1225,8 +1211,8 @@ mod tests { fn test_paths() { let empty: &[u8] = &[]; t!(v: Path::new(empty), b"."); - t!(v: Path::new(b"\\"), b"\\"); - t!(v: Path::new(b"a\\b\\c"), b"a\\b\\c"); + t!(v: Path::new(&b"\\"[..]), b"\\"); + t!(v: Path::new(&b"a\\b\\c"[..]), b"a\\b\\c"); t!(s: Path::new(""), "."); t!(s: Path::new("\\"), "\\"); @@ -1258,8 +1244,8 @@ mod tests { t!(s: Path::new("foo\\..\\..\\.."), "..\\.."); t!(s: Path::new("foo\\..\\..\\bar"), "..\\bar"); - assert_eq!(Path::new(b"foo\\bar").into_vec(), b"foo\\bar"); - assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec(), b"\\bar"); + assert_eq!(Path::new(&b"foo\\bar"[..]).into_vec(), b"foo\\bar"); + assert_eq!(Path::new(&b"\\foo\\..\\..\\bar"[..]).into_vec(), b"\\bar"); t!(s: Path::new("\\\\a"), "\\a"); t!(s: Path::new("\\\\a\\"), "\\a"); @@ -1312,9 +1298,9 @@ mod tests { #[test] fn test_opt_paths() { - assert!(Path::new_opt(b"foo\\bar\0") == None); - assert!(Path::new_opt(b"foo\\bar\x80") == None); - t!(v: Path::new_opt(b"foo\\bar").unwrap(), b"foo\\bar"); + assert!(Path::new_opt(&b"foo\\bar\0"[..]) == None); + assert!(Path::new_opt(&b"foo\\bar\x80"[..]) == None); + t!(v: Path::new_opt(&b"foo\\bar"[..]).unwrap(), b"foo\\bar"); assert!(Path::new_opt("foo\\bar\0") == None); t!(s: Path::new_opt("foo\\bar").unwrap(), "foo\\bar"); } @@ -1323,38 +1309,38 @@ mod tests { fn test_null_byte() { use thread; let result = thread::spawn(move|| { - Path::new(b"foo/bar\0"); + Path::new(&b"foo/bar\0"[..]); }).join(); assert!(result.is_err()); let result = thread::spawn(move|| { - Path::new("test").set_filename(b"f\0o") + Path::new("test").set_filename(&b"f\0o"[..]) }).join(); assert!(result.is_err()); let result = thread::spawn(move || { - Path::new("test").push(b"f\0o"); + Path::new("test").push(&b"f\0o"[..]); }).join(); assert!(result.is_err()); } #[test] - #[should_fail] + #[should_panic] fn test_not_utf8_panics() { - Path::new(b"hello\x80.txt"); + Path::new(&b"hello\x80.txt"[..]); } #[test] fn test_display_str() { let path = Path::new("foo"); assert_eq!(path.display().to_string(), "foo"); - let path = Path::new(b"\\"); + let path = Path::new(&b"\\"[..]); assert_eq!(path.filename_display().to_string(), ""); let path = Path::new("foo"); let mo = path.display().as_cow(); assert_eq!(mo, "foo"); - let path = Path::new(b"\\"); + let path = Path::new(&b"\\"[..]); let mo = path.filename_display().as_cow(); assert_eq!(mo, ""); } @@ -1405,7 +1391,7 @@ mod tests { ) } - t!(v: b"a\\b\\c", filename, Some(b"c")); + t!(v: &b"a\\b\\c"[..], filename, Some(&b"c"[..])); t!(s: "a\\b\\c", filename_str, "c"); t!(s: "\\a\\b\\c", filename_str, "c"); t!(s: "a", filename_str, "a"); @@ -1438,7 +1424,7 @@ mod tests { t!(s: "\\\\.\\", filename_str, None, opt); t!(s: "\\\\?\\a\\b\\", filename_str, "b"); - t!(v: b"a\\b\\c", dirname, b"a\\b"); + t!(v: &b"a\\b\\c"[..], dirname, b"a\\b"); t!(s: "a\\b\\c", dirname_str, "a\\b"); t!(s: "\\a\\b\\c", dirname_str, "\\a\\b"); t!(s: "a", dirname_str, "."); @@ -1469,7 +1455,7 @@ mod tests { t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo"); t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a"); - t!(v: b"hi\\there.txt", filestem, Some(b"there")); + t!(v: &b"hi\\there.txt"[..], filestem, Some(&b"there"[..])); t!(s: "hi\\there.txt", filestem_str, "there"); t!(s: "hi\\there", filestem_str, "there"); t!(s: "there.txt", filestem_str, "there"); @@ -1484,8 +1470,8 @@ mod tests { t!(s: "..\\..", filestem_str, None, opt); // filestem is based on filename, so we don't need the full set of prefix tests - t!(v: b"hi\\there.txt", extension, Some(b"txt")); - t!(v: b"hi\\there", extension, None); + t!(v: &b"hi\\there.txt"[..], extension, Some(&b"txt"[..])); + t!(v: &b"hi\\there"[..], extension, None); t!(s: "hi\\there.txt", extension_str, Some("txt"), opt); t!(s: "hi\\there", extension_str, None, opt); t!(s: "there.txt", extension_str, Some("txt"), opt); @@ -1611,9 +1597,9 @@ mod tests { t!(s: "a\\b\\c", ["d", "\\e"], "\\e"); t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f"); t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e"); - t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e"); - t!(v: b"a\\b\\c", [b"d", b"\\e", b"f"], b"\\e\\f"); - t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()], + t!(v: &b"a\\b\\c"[..], [&b"d"[..], &b"e"[..]], b"a\\b\\c\\d\\e"); + t!(v: &b"a\\b\\c"[..], [&b"d"[..], &b"\\e"[..], &b"f"[..]], b"\\e\\f"); + t!(v: &b"a\\b\\c"[..], [b"d".to_vec(), b"e".to_vec()], b"a\\b\\c\\d\\e"); } @@ -1645,11 +1631,11 @@ mod tests { t!(s: ".", ".", false); t!(s: "\\a", "\\", true); t!(s: "\\", "\\", false); - t!(b: b"a\\b\\c", b"a\\b", true); - t!(b: b"a", b".", true); - t!(b: b".", b".", false); - t!(b: b"\\a", b"\\", true); - t!(b: b"\\", b"\\", false); + t!(b: &b"a\\b\\c"[..], b"a\\b", true); + t!(b: &b"a"[..], b".", true); + t!(b: &b"."[..], b".", false); + t!(b: &b"\\a"[..], b"\\", true); + t!(b: &b"\\"[..], b"\\", false); t!(s: "C:\\a\\b", "C:\\a", true); t!(s: "C:\\a", "C:\\", true); @@ -1698,8 +1684,8 @@ mod tests { t!(s: Path::new("a\\b").join("\\c\\d"), "\\c\\d"); t!(s: Path::new(".").join("a\\b"), "a\\b"); t!(s: Path::new("\\").join("a\\b"), "\\a\\b"); - t!(v: Path::new(b"a\\b\\c").join(b".."), b"a\\b"); - t!(v: Path::new(b"\\a\\b\\c").join(b"d"), b"\\a\\b\\c\\d"); + t!(v: Path::new(&b"a\\b\\c"[..]).join(&b".."[..]), b"a\\b"); + t!(v: Path::new(&b"\\a\\b\\c"[..]).join(&b"d"[..]), b"\\a\\b\\c\\d"); // full join testing is covered under test_push_path, so no need for // the full set of prefix tests } @@ -1750,8 +1736,8 @@ mod tests { t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d"); t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f"); t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e"); - t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e"); - t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()], + t!(v: &b"a\\b\\c"[..], [&b"d"[..], &b"e"[..]], b"a\\b\\c\\d\\e"); + t!(v: &b"a\\b\\c"[..], [b"d".to_vec(), b"e".to_vec()], b"a\\b\\c\\d\\e"); } @@ -1863,15 +1849,15 @@ mod tests { ) } - t!(v: b"a\\b\\c", set_filename, with_filename, b"d"); - t!(v: b"\\", set_filename, with_filename, b"foo"); + t!(v: &b"a\\b\\c"[..], set_filename, with_filename, &b"d"[..]); + t!(v: &b"\\"[..], set_filename, with_filename, &b"foo"[..]); t!(s: "a\\b\\c", set_filename, with_filename, "d"); t!(s: "\\", set_filename, with_filename, "foo"); t!(s: ".", set_filename, with_filename, "foo"); t!(s: "a\\b", set_filename, with_filename, ""); t!(s: "a", set_filename, with_filename, ""); - t!(v: b"hi\\there.txt", set_extension, with_extension, b"exe"); + t!(v: &b"hi\\there.txt"[..], set_extension, with_extension, &b"exe"[..]); t!(s: "hi\\there.txt", set_extension, with_extension, "exe"); t!(s: "hi\\there.", set_extension, with_extension, "txt"); t!(s: "hi\\there", set_extension, with_extension, "txt"); @@ -1906,7 +1892,7 @@ mod tests { ) } - t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None); + t!(v: Path::new(&b"a\\b\\c"[..]), Some(&b"c"[..]), b"a\\b", Some(&b"c"[..]), None); t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None); t!(s: Path::new("."), None, Some("."), None, None); t!(s: Path::new("\\"), None, Some("\\"), None, None); @@ -2248,7 +2234,7 @@ mod tests { ); } - t!(s: b"a\\b\\c", ["a", "b", "c"]); + t!(s: &b"a\\b\\c"[..], ["a", "b", "c"]); t!(s: "a\\b\\c", ["a", "b", "c"]); t!(s: "a\\b\\d", ["a", "b", "d"]); t!(s: "a\\b\\cd", ["a", "b", "cd"]); diff --git a/src/libstd/os.rs b/src/libstd/os.rs index f181fc5df5..ee0f04cb99 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -8,1744 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Higher-level interfaces to libc::* functions and operating system services. -//! -//! In general these take and return rust types, use rust idioms (enums, -//! closures, vectors) rather than C idioms, and do more extensive safety -//! checks. -//! -//! This module is not meant to only contain 1:1 mappings to libc entries; any -//! os-interface code that is reasonably useful and broadly applicable can go -//! here. Including utility routines that merely build on other os code. -//! -//! We assume the general case is that users do not care, and do not want to be -//! made to care, which operating system they are on. While they may want to -//! special case various special cases -- and so we will not _hide_ the facts of -//! which OS the user is on -- they should be given the opportunity to write -//! OS-ignorant code by default. +//! OS-specific functionality -#![unstable(feature = "os")] - -#![allow(missing_docs)] -#![allow(non_snake_case)] -#![allow(unused_imports)] - -use self::MemoryMapKind::*; -use self::MapOption::*; -use self::MapError::*; - -use boxed::Box; -use clone::Clone; -use env; -use error::{FromError, Error}; -use ffi::{OsString, OsStr}; -use fmt; -use iter::{Iterator, IteratorExt}; -use libc::{c_void, c_int, c_char}; -use libc; -use marker::{Copy, Send}; -use old_io::{IoResult, IoError}; -use ops::{Drop, FnOnce}; -use option::Option::{Some, None}; -use option::Option; -use old_path::{Path, GenericPath, BytesContainer}; -use ptr::PtrExt; -use ptr; -use result::Result::{Err, Ok}; -use result::Result; -use slice::{AsSlice, SliceExt}; -use str::{Str, StrExt}; -use str; -use string::{String, ToString}; -use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering}; -use sys::os as os_imp; -use sys; -use vec::Vec; - -#[cfg(unix)] use ffi::{self, CString}; +#![stable(feature = "os", since = "1.0.0")] #[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 { - unsafe { - return rust_get_num_cpus() as uint; - } - - extern { - fn rust_get_num_cpus() -> libc::uintptr_t; - } -} - -pub const TMPBUF_SZ : uint = 1000; - -/// Returns the current working directory as a `Path`. -/// -/// # Errors -/// -/// Returns an `Err` if the current working directory value is invalid. -/// Possible cases: -/// -/// * Current directory does not exist. -/// * There are insufficient permissions to access the current directory. -/// * The internal buffer is not large enough to hold the path. -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// // We assume that we are in a valid directory. -/// let current_working_directory = os::getcwd().unwrap(); -/// println!("The current directory is {:?}", current_working_directory.display()); -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")] -#[unstable(feature = "os")] -pub fn getcwd() -> IoResult { - env::current_dir() -} - -/// Returns a vector of (variable, value) pairs, for all the environment -/// variables of the current process. -/// -/// Invalid UTF-8 bytes are replaced with \uFFFD. See `String::from_utf8_lossy()` -/// for details. -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// // We will iterate through the references to the element returned by os::env(); -/// for &(ref key, ref value) in os::env().iter() { -/// println!("'{}': '{}'", key, value ); -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::vars instead")] -#[unstable(feature = "os")] -pub fn env() -> Vec<(String,String)> { - env::vars_os().map(|(k, v)| { - (k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned()) - }).collect() -} - -/// Returns a vector of (variable, value) byte-vector pairs for all the -/// environment variables of the current process. -#[deprecated(since = "1.0.0", reason = "use env::vars_os instead")] -#[unstable(feature = "os")] -pub fn env_as_bytes() -> Vec<(Vec, Vec)> { - env::vars_os().map(|(k, v)| (byteify(k), byteify(v))).collect() -} - -/// Fetches the environment variable `n` from the current process, returning -/// None if the variable isn't set. -/// -/// Any invalid UTF-8 bytes in the value are replaced by \uFFFD. See -/// `String::from_utf8_lossy()` for details. -/// -/// # Panics -/// -/// Panics if `n` has any interior NULs. -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// let key = "HOME"; -/// match os::getenv(key) { -/// Some(val) => println!("{}: {}", key, val), -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::var instead")] -#[unstable(feature = "os")] -pub fn getenv(n: &str) -> Option { - env::var(n).ok() -} - -/// Fetches the environment variable `n` byte vector from the current process, -/// returning None if the variable isn't set. -/// -/// # Panics -/// -/// Panics if `n` has any interior NULs. -#[deprecated(since = "1.0.0", reason = "use env::var_os instead")] -#[unstable(feature = "os")] -pub fn getenv_as_bytes(n: &str) -> Option> { - env::var_os(n).map(byteify) -} - -#[cfg(unix)] -fn byteify(s: OsString) -> Vec { - use os::unix::*; - s.into_vec() -} -#[cfg(windows)] -fn byteify(s: OsString) -> Vec { - s.to_string_lossy().as_bytes().to_vec() -} - -/// Sets the environment variable `n` to the value `v` for the currently running -/// process. -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// let key = "KEY"; -/// os::setenv(key, "VALUE"); -/// match os::getenv(key) { -/// Some(ref val) => println!("{}: {}", key, val), -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")] -#[unstable(feature = "os")] -pub fn setenv(n: &str, v: T) { - #[cfg(unix)] - fn _setenv(n: &str, v: &[u8]) { - use os::unix::*; - let v: OsString = OsStringExt::from_vec(v.to_vec()); - env::set_var(n, &v) - } - - #[cfg(windows)] - fn _setenv(n: &str, v: &[u8]) { - let v = str::from_utf8(v).unwrap(); - env::set_var(n, v) - } - - _setenv(n, v.container_as_bytes()) -} - -/// Remove a variable from the environment entirely. -#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")] -#[unstable(feature = "os")] -pub fn unsetenv(n: &str) { - env::remove_var(n) -} - -/// Parses input according to platform conventions for the `PATH` -/// environment variable. -/// -/// # Example -/// ```rust -/// use std::os; -/// -/// let key = "PATH"; -/// match os::getenv_as_bytes(key) { -/// Some(paths) => { -/// for path in os::split_paths(paths).iter() { -/// println!("'{}'", path.display()); -/// } -/// } -/// None => println!("{} is not defined in the environment.", key) -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")] -#[unstable(feature = "os")] -pub fn split_paths(unparsed: T) -> Vec { - let b = unparsed.container_as_bytes(); - let s = str::from_utf8(b).unwrap(); - env::split_paths(s).collect() -} - -/// Joins a collection of `Path`s appropriately for the `PATH` -/// environment variable. -/// -/// Returns a `Vec` on success, since `Path`s are not utf-8 -/// encoded on all platforms. -/// -/// Returns an `Err` (containing an error message) if one of the input -/// `Path`s contains an invalid character for constructing the `PATH` -/// variable (a double quote on Windows or a colon on Unix). -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// use std::old_path::Path; -/// -/// let key = "PATH"; -/// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths); -/// paths.push(Path::new("/home/xyz/bin")); -/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap()); -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")] -#[unstable(feature = "os")] -pub fn join_paths(paths: &[T]) -> Result, &'static str> { - env::join_paths(paths.iter().map(|s| { - str::from_utf8(s.container_as_bytes()).unwrap() - })).map(|s| { - s.to_string_lossy().into_owned().into_bytes() - }).map_err(|_| "failed to join paths") -} - -/// A low-level OS in-memory pipe. -#[derive(Copy)] -pub struct Pipe { - /// A file descriptor representing the reading end of the pipe. Data written - /// on the `out` file descriptor can be read from this file descriptor. - pub reader: c_int, - /// A file descriptor representing the write end of the pipe. Data written - /// to this file descriptor can be read from the `input` file descriptor. - pub writer: c_int, -} - -/// Creates a new low-level OS in-memory pipe. -/// -/// This function can fail to succeed if there are no more resources available -/// to allocate a pipe. -/// -/// This function is also unsafe as there is no destructor associated with the -/// `Pipe` structure will return. If it is not arranged for the returned file -/// descriptors to be closed, the file descriptors will leak. For safe handling -/// of this scenario, use `std::old_io::PipeStream` instead. -pub unsafe fn pipe() -> IoResult { - let (reader, writer) = try!(sys::os::pipe()); - Ok(Pipe { - reader: reader.unwrap(), - writer: writer.unwrap(), - }) -} - -/// Returns the proper dll filename for the given basename of a file -/// as a String. -#[cfg(not(target_os="ios"))] -#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")] -#[unstable(feature = "os")] -#[allow(deprecated)] -pub fn dll_filename(base: &str) -> String { - format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX) -} - -/// Optionally returns the filesystem path to the current executable which is -/// running but with the executable name. -/// -/// # Examples -/// -/// ```rust -/// use std::os; -/// -/// match os::self_exe_name() { -/// Some(exe_path) => println!("Path of this executable is: {}", exe_path.display()), -/// None => println!("Unable to get the path of this executable!") -/// }; -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")] -#[unstable(feature = "os")] -pub fn self_exe_name() -> Option { - env::current_exe().ok() -} - -/// Optionally returns the filesystem path to the current executable which is -/// running. -/// -/// Like self_exe_name() but without the binary's name. -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// match os::self_exe_path() { -/// Some(exe_path) => println!("Executable's Path is: {}", exe_path.display()), -/// None => println!("Impossible to fetch the path of this executable.") -/// }; -/// ``` -#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")] -#[unstable(feature = "os")] -pub fn self_exe_path() -> Option { - env::current_exe().ok().map(|mut p| { p.pop(); p }) -} - -/// Optionally returns the path to the current user's home directory if known. -/// -/// # Unix -/// -/// Returns the value of the 'HOME' environment variable if it is set -/// and not equal to the empty string. -/// -/// # Windows -/// -/// Returns the value of the 'HOME' environment variable if it is -/// set and not equal to the empty string. Otherwise, returns the value of the -/// 'USERPROFILE' environment variable if it is set and not equal to the empty -/// string. -/// -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// match os::homedir() { -/// Some(ref p) => println!("{}", p.display()), -/// None => println!("Impossible to get your home dir!") -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")] -#[allow(deprecated)] -#[unstable(feature = "os")] -pub fn homedir() -> Option { - #[inline] - #[cfg(unix)] - fn _homedir() -> Option { - aux_homedir("HOME") - } - - #[inline] - #[cfg(windows)] - fn _homedir() -> Option { - aux_homedir("HOME").or(aux_homedir("USERPROFILE")) - } - - #[inline] - fn aux_homedir(home_name: &str) -> Option { - match getenv_as_bytes(home_name) { - Some(p) => { - if p.is_empty() { None } else { Path::new_opt(p) } - }, - _ => None - } - } - _homedir() -} - -/// Returns the path to a temporary directory. -/// -/// On Unix, returns the value of the 'TMPDIR' environment variable if it is -/// set, otherwise for non-Android it returns '/tmp'. If Android, since there -/// is no global temporary folder (it is usually allocated per-app), we return -/// '/data/local/tmp'. -/// -/// On Windows, returns the value of, in order, the 'TMP', 'TEMP', -/// 'USERPROFILE' environment variable if any are set and not the empty -/// string. Otherwise, tmpdir returns the path to the Windows directory. -#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")] -#[allow(deprecated)] -#[unstable(feature = "os")] -pub fn tmpdir() -> Path { - return lookup(); - - fn getenv_nonempty(v: &str) -> Option { - match getenv(v) { - Some(x) => - if x.is_empty() { - None - } else { - Path::new_opt(x) - }, - _ => None - } - } - - #[cfg(unix)] - fn lookup() -> Path { - let default = if cfg!(target_os = "android") { - Path::new("/data/local/tmp") - } else { - Path::new("/tmp") - }; - - getenv_nonempty("TMPDIR").unwrap_or(default) - } - - #[cfg(windows)] - fn lookup() -> Path { - getenv_nonempty("TMP").or( - getenv_nonempty("TEMP").or( - getenv_nonempty("USERPROFILE").or( - getenv_nonempty("WINDIR")))).unwrap_or(Path::new("C:\\Windows")) - } -} - -/// Convert a relative path to an absolute path -/// -/// If the given path is relative, return it prepended with the current working -/// directory. If the given path is already an absolute path, return it -/// as is. -/// -/// # Example -/// ```rust -/// use std::os; -/// use std::old_path::Path; -/// -/// // Assume we're in a path like /home/someuser -/// let rel_path = Path::new(".."); -/// let abs_path = os::make_absolute(&rel_path).unwrap(); -/// println!("The absolute path is {}", abs_path.display()); -/// // Prints "The absolute path is /home" -/// ``` -// NB: this is here rather than in path because it is a form of environment -// querying; what it does depends on the process working directory, not just -// the input paths. -#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")] -#[unstable(feature = "os")] -pub fn make_absolute(p: &Path) -> IoResult { - if p.is_absolute() { - Ok(p.clone()) - } else { - env::current_dir().map(|mut cwd| { - cwd.push(p); - cwd - }) - } -} - -/// Changes the current working directory to the specified path, returning -/// whether the change was completed successfully or not. -/// -/// # Example -/// ```rust -/// use std::os; -/// use std::old_path::Path; -/// -/// let root = Path::new("/"); -/// assert!(os::change_dir(&root).is_ok()); -/// println!("Successfully changed working directory to {}!", root.display()); -/// ``` -#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")] -#[unstable(feature = "os")] -pub fn change_dir(p: &Path) -> IoResult<()> { - return sys::os::chdir(p); -} - -/// Returns the platform-specific value of errno -pub fn errno() -> i32 { - sys::os::errno() as i32 -} - -/// Return the string corresponding to an `errno()` value of `errnum`. -/// -/// # Example -/// ```rust -/// use std::os; -/// -/// // Same as println!("{}", last_os_error()); -/// println!("{}", os::error_string(os::errno() as i32)); -/// ``` -pub fn error_string(errnum: i32) -> String { - return sys::os::error_string(errnum); -} - -/// Get a string representing the platform-dependent last error -pub fn last_os_error() -> String { - error_string(errno()) -} - -/// Sets the process exit code -/// -/// Sets the exit code returned by the process if all supervised tasks -/// terminate successfully (without panicking). If the current root task panics -/// and is supervised by the scheduler then any user-specified exit status is -/// ignored and the process exits with the default panic status. -/// -/// Note that this is not synchronized against modifications of other threads. -#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")] -#[unstable(feature = "os")] -pub fn set_exit_status(code: int) { - env::set_exit_status(code as i32) -} - -/// Fetches the process's current exit code. This defaults to 0 and can change -/// by calling `set_exit_status`. -#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")] -#[unstable(feature = "os")] -pub fn get_exit_status() -> int { - env::get_exit_status() as isize -} - -#[cfg(target_os = "macos")] -unsafe fn load_argc_and_argv(argc: int, - argv: *const *const c_char) -> Vec> { - use ffi::CStr; - use iter::range; - - (0..argc).map(|i| { - CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec() - }).collect() -} - -/// Returns the command line arguments -/// -/// Returns a list of the command line arguments. -#[cfg(target_os = "macos")] -fn real_args_as_bytes() -> Vec> { - unsafe { - let (argc, argv) = (*_NSGetArgc() as int, - *_NSGetArgv() as *const *const c_char); - load_argc_and_argv(argc, argv) - } -} - -// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs -// and use underscores in their names - they're most probably -// are considered private and therefore should be avoided -// Here is another way to get arguments using Objective C -// runtime -// -// In general it looks like: -// res = Vec::new() -// let args = [[NSProcessInfo processInfo] arguments] -// for i in 0..[args count] -// res.push([args objectAtIndex:i]) -// res -#[cfg(target_os = "ios")] -fn real_args_as_bytes() -> Vec> { - use ffi::c_str_to_bytes; - use iter::range; - use mem; - - #[link(name = "objc")] - extern { - fn sel_registerName(name: *const libc::c_uchar) -> Sel; - fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; - fn objc_getClass(class_name: *const libc::c_uchar) -> NsId; - } - - #[link(name = "Foundation", kind = "framework")] - extern {} - - type Sel = *const libc::c_void; - type NsId = *const libc::c_void; - - let mut res = Vec::new(); - - unsafe { - let processInfoSel = sel_registerName("processInfo\0".as_ptr()); - let argumentsSel = sel_registerName("arguments\0".as_ptr()); - let utf8Sel = sel_registerName("UTF8String\0".as_ptr()); - let countSel = sel_registerName("count\0".as_ptr()); - let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr()); - - let klass = objc_getClass("NSProcessInfo\0".as_ptr()); - let info = objc_msgSend(klass, processInfoSel); - let args = objc_msgSend(info, argumentsSel); - - let cnt: int = mem::transmute(objc_msgSend(args, countSel)); - for i in 0..cnt { - let tmp = objc_msgSend(args, objectAtSel, i); - let utf_c_str: *const libc::c_char = - mem::transmute(objc_msgSend(tmp, utf8Sel)); - res.push(c_str_to_bytes(&utf_c_str).to_vec()); - } - } - - res -} - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd"))] -fn real_args_as_bytes() -> Vec> { - use rt; - rt::args::clone().unwrap_or_else(|| vec![]) -} - -#[cfg(not(windows))] -fn real_args() -> Vec { - real_args_as_bytes().into_iter() - .map(|v| { - String::from_utf8_lossy(&v).into_owned() - }).collect() -} - -#[cfg(windows)] -fn real_args() -> Vec { - use slice; - use iter::range; - - let mut nArgs: c_int = 0; - let lpArgCount: *mut c_int = &mut nArgs; - let lpCmdLine = unsafe { GetCommandLineW() }; - let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) }; - - let args: Vec<_> = (0..nArgs as uint).map(|i| unsafe { - // Determine the length of this argument. - let ptr = *szArgList.offset(i as int); - let mut len = 0; - while *ptr.offset(len as int) != 0 { len += 1; } - - // Push it onto the list. - let ptr = ptr as *const u16; - let buf = slice::from_raw_parts(ptr, len); - let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf)); - opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") - }).collect(); - - unsafe { - LocalFree(szArgList as *mut c_void); - } - - return args -} - -#[cfg(windows)] -fn real_args_as_bytes() -> Vec> { - real_args().into_iter().map(|s| s.into_bytes()).collect() -} - -type LPCWSTR = *const u16; - -#[cfg(windows)] -#[link_name="kernel32"] -extern "system" { - fn GetCommandLineW() -> LPCWSTR; - fn LocalFree(ptr: *mut c_void); -} - -#[cfg(windows)] -#[link_name="shell32"] -extern "system" { - fn CommandLineToArgvW(lpCmdLine: LPCWSTR, - pNumArgs: *mut c_int) -> *mut *mut u16; -} - -/// Returns the arguments which this program was started with (normally passed -/// via the command line). -/// -/// The first element is traditionally the path to the executable, but it can be -/// set to arbitrary text, and it may not even exist, so this property should not -/// be relied upon for security purposes. -/// -/// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD. -/// See `String::from_utf8_lossy` for details. -/// # Example -/// -/// ```rust -/// use std::os; -/// -/// // Prints each argument on a separate line -/// for argument in os::args().iter() { -/// println!("{}", argument); -/// } -/// ``` -#[deprecated(since = "1.0.0", reason = "use std::env::args() instead")] -#[unstable(feature = "os")] -pub fn args() -> Vec { - real_args() -} - -/// Returns the arguments which this program was started with (normally passed -/// via the command line) as byte vectors. -#[deprecated(since = "1.0.0", reason = "use env::args_os instead")] -#[unstable(feature = "os")] -pub fn args_as_bytes() -> Vec> { - real_args_as_bytes() -} - -#[cfg(target_os = "macos")] -extern { - // These functions are in crt_externs.h. - fn _NSGetArgc() -> *mut c_int; - fn _NSGetArgv() -> *mut *mut *mut c_char; -} - -/// Returns the page size of the current architecture in bytes. -#[deprecated(since = "1.0.0", reason = "renamed to env::page_size")] -#[unstable(feature = "os")] -pub fn page_size() -> uint { - sys::os::page_size() -} - -/// A memory mapped file or chunk of memory. This is a very system-specific -/// interface to the OS's memory mapping facilities (`mmap` on POSIX, -/// `VirtualAlloc`/`CreateFileMapping` on Windows). It makes no attempt at -/// abstracting platform differences, besides in error values returned. Consider -/// yourself warned. -/// -/// The memory map is released (unmapped) when the destructor is run, so don't -/// let it leave scope by accident if you want it to stick around. -pub struct MemoryMap { - data: *mut u8, - len: uint, - kind: MemoryMapKind, -} - -/// Type of memory map -#[allow(raw_pointer_derive)] -#[derive(Copy)] -pub enum MemoryMapKind { - /// Virtual memory map. Usually used to change the permissions of a given - /// chunk of memory. Corresponds to `VirtualAlloc` on Windows. - MapFile(*const u8), - /// Virtual memory map. Usually used to change the permissions of a given - /// chunk of memory, or for allocation. Corresponds to `VirtualAlloc` on - /// Windows. - MapVirtual -} - -/// Options the memory map is created with -#[allow(raw_pointer_derive)] -#[derive(Copy)] -pub enum MapOption { - /// The memory should be readable - MapReadable, - /// The memory should be writable - MapWritable, - /// The memory should be executable - MapExecutable, - /// Create a map for a specific address range. Corresponds to `MAP_FIXED` on - /// POSIX. - MapAddr(*const u8), - /// Create a memory mapping for a file with a given HANDLE. - #[cfg(windows)] - MapFd(libc::HANDLE), - /// Create a memory mapping for a file with a given fd. - #[cfg(not(windows))] - MapFd(c_int), - /// When using `MapFd`, the start of the map is `uint` bytes from the start - /// of the file. - MapOffset(uint), - /// On POSIX, this can be used to specify the default flags passed to - /// `mmap`. By default it uses `MAP_PRIVATE` and, if not using `MapFd`, - /// `MAP_ANON`. This will override both of those. This is platform-specific - /// (the exact values used) and ignored on Windows. - MapNonStandardFlags(c_int), -} - -/// Possible errors when creating a map. -#[derive(Copy, Debug)] -pub enum MapError { - /// # The following are POSIX-specific - /// - /// fd was not open for reading or, if using `MapWritable`, was not open for - /// writing. - ErrFdNotAvail, - /// fd was not valid - ErrInvalidFd, - /// Either the address given by `MapAddr` or offset given by `MapOffset` was - /// not a multiple of `MemoryMap::granularity` (unaligned to page size). - ErrUnaligned, - /// With `MapFd`, the fd does not support mapping. - ErrNoMapSupport, - /// If using `MapAddr`, the address + `min_len` was outside of the process's - /// address space. If using `MapFd`, the target of the fd didn't have enough - /// resources to fulfill the request. - ErrNoMem, - /// A zero-length map was requested. This is invalid according to - /// [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html). - /// Not all platforms obey this, but this wrapper does. - ErrZeroLength, - /// Unrecognized error. The inner value is the unrecognized errno. - ErrUnknown(int), - /// # The following are Windows-specific - /// - /// Unsupported combination of protection flags - /// (`MapReadable`/`MapWritable`/`MapExecutable`). - ErrUnsupProt, - /// When using `MapFd`, `MapOffset` was given (Windows does not support this - /// at all) - ErrUnsupOffset, - /// When using `MapFd`, there was already a mapping to the file. - ErrAlreadyExists, - /// Unrecognized error from `VirtualAlloc`. The inner value is the return - /// value of GetLastError. - ErrVirtualAlloc(i32), - /// Unrecognized error from `CreateFileMapping`. The inner value is the - /// return value of `GetLastError`. - ErrCreateFileMappingW(i32), - /// Unrecognized error from `MapViewOfFile`. The inner value is the return - /// value of `GetLastError`. - ErrMapViewOfFile(i32) -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for MapError { - fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result { - let str = match *self { - ErrFdNotAvail => "fd not available for reading or writing", - ErrInvalidFd => "Invalid fd", - ErrUnaligned => { - "Unaligned address, invalid flags, negative length or \ - unaligned offset" - } - ErrNoMapSupport=> "File doesn't support mapping", - ErrNoMem => "Invalid address, or not enough available memory", - ErrUnsupProt => "Protection mode unsupported", - ErrUnsupOffset => "Offset in virtual memory mode is unsupported", - ErrAlreadyExists => "File mapping for specified file already exists", - ErrZeroLength => "Zero-length mapping not allowed", - ErrUnknown(code) => { - return write!(out, "Unknown error = {}", code) - }, - ErrVirtualAlloc(code) => { - return write!(out, "VirtualAlloc failure = {}", code) - }, - ErrCreateFileMappingW(code) => { - return write!(out, "CreateFileMappingW failure = {}", code) - }, - ErrMapViewOfFile(code) => { - return write!(out, "MapViewOfFile failure = {}", code) - } - }; - write!(out, "{}", str) - } -} - -impl Error for MapError { - fn description(&self) -> &str { "memory map error" } -} - -// Round up `from` to be divisible by `to` -fn round_up(from: uint, to: uint) -> uint { - let r = if from % to == 0 { - from - } else { - from + to - (from % to) - }; - if r == 0 { - to - } else { - r - } -} - -#[cfg(unix)] -impl MemoryMap { - /// Create a new mapping with the given `options`, at least `min_len` bytes - /// long. `min_len` must be greater than zero; see the note on - /// `ErrZeroLength`. - pub fn new(min_len: uint, options: &[MapOption]) -> Result { - use libc::off_t; - - if min_len == 0 { - return Err(ErrZeroLength) - } - let mut addr: *const u8 = ptr::null(); - let mut prot = 0; - let mut flags = libc::MAP_PRIVATE; - let mut fd = -1; - let mut offset = 0; - let mut custom_flags = false; - let len = round_up(min_len, env::page_size()); - - for &o in options { - match o { - MapReadable => { prot |= libc::PROT_READ; }, - MapWritable => { prot |= libc::PROT_WRITE; }, - MapExecutable => { prot |= libc::PROT_EXEC; }, - MapAddr(addr_) => { - flags |= libc::MAP_FIXED; - addr = addr_; - }, - MapFd(fd_) => { - flags |= libc::MAP_FILE; - fd = fd_; - }, - MapOffset(offset_) => { offset = offset_ as off_t; }, - MapNonStandardFlags(f) => { custom_flags = true; flags = f }, - } - } - if fd == -1 && !custom_flags { flags |= libc::MAP_ANON; } - - let r = unsafe { - libc::mmap(addr as *mut c_void, len as libc::size_t, prot, flags, - fd, offset) - }; - if r == libc::MAP_FAILED { - Err(match errno() as c_int { - libc::EACCES => ErrFdNotAvail, - libc::EBADF => ErrInvalidFd, - libc::EINVAL => ErrUnaligned, - libc::ENODEV => ErrNoMapSupport, - libc::ENOMEM => ErrNoMem, - code => ErrUnknown(code as int) - }) - } else { - Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: if fd == -1 { - MapVirtual - } else { - MapFile(ptr::null()) - } - }) - } - } - - /// Granularity that the offset or address must be for `MapOffset` and - /// `MapAddr` respectively. - pub fn granularity() -> uint { - env::page_size() - } -} - -#[cfg(unix)] -impl Drop for MemoryMap { - /// Unmap the mapping. Panics the task if `munmap` panics. - fn drop(&mut self) { - if self.len == 0 { /* workaround for dummy_stack */ return; } - - unsafe { - // `munmap` only panics due to logic errors - libc::munmap(self.data as *mut c_void, self.len as libc::size_t); - } - } -} - -#[cfg(windows)] -impl MemoryMap { - /// Create a new mapping with the given `options`, at least `min_len` bytes long. - pub fn new(min_len: uint, options: &[MapOption]) -> Result { - use libc::types::os::arch::extra::{LPVOID, DWORD, SIZE_T, HANDLE}; - - let mut lpAddress: LPVOID = ptr::null_mut(); - let mut readable = false; - let mut writable = false; - let mut executable = false; - let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE; - let mut offset: uint = 0; - let len = round_up(min_len, env::page_size()); - - for &o in options { - match o { - MapReadable => { readable = true; }, - MapWritable => { writable = true; }, - MapExecutable => { executable = true; } - MapAddr(addr_) => { lpAddress = addr_ as LPVOID; }, - MapFd(handle_) => { handle = handle_; }, - MapOffset(offset_) => { offset = offset_; }, - MapNonStandardFlags(..) => {} - } - } - - let flProtect = match (executable, readable, writable) { - (false, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_NOACCESS, - (false, true, false) => libc::PAGE_READONLY, - (false, true, true) => libc::PAGE_READWRITE, - (true, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_EXECUTE, - (true, true, false) => libc::PAGE_EXECUTE_READ, - (true, true, true) => libc::PAGE_EXECUTE_READWRITE, - _ => return Err(ErrUnsupProt) - }; - - if handle == libc::INVALID_HANDLE_VALUE { - if offset != 0 { - return Err(ErrUnsupOffset); - } - let r = unsafe { - libc::VirtualAlloc(lpAddress, - len as SIZE_T, - libc::MEM_COMMIT | libc::MEM_RESERVE, - flProtect) - }; - match r as uint { - 0 => Err(ErrVirtualAlloc(errno())), - _ => Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: MapVirtual - }) - } - } else { - let dwDesiredAccess = match (executable, readable, writable) { - (false, true, false) => libc::FILE_MAP_READ, - (false, true, true) => libc::FILE_MAP_WRITE, - (true, true, false) => libc::FILE_MAP_READ | libc::FILE_MAP_EXECUTE, - (true, true, true) => libc::FILE_MAP_WRITE | libc::FILE_MAP_EXECUTE, - _ => return Err(ErrUnsupProt) // Actually, because of the check above, - // we should never get here. - }; - unsafe { - let hFile = handle; - let mapping = libc::CreateFileMappingW(hFile, - ptr::null_mut(), - flProtect, - 0, - 0, - ptr::null()); - if mapping == ptr::null_mut() { - return Err(ErrCreateFileMappingW(errno())); - } - if errno() as c_int == libc::ERROR_ALREADY_EXISTS { - return Err(ErrAlreadyExists); - } - let r = libc::MapViewOfFile(mapping, - dwDesiredAccess, - ((len as u64) >> 32) as DWORD, - (offset & 0xffff_ffff) as DWORD, - 0); - match r as uint { - 0 => Err(ErrMapViewOfFile(errno())), - _ => Ok(MemoryMap { - data: r as *mut u8, - len: len, - kind: MapFile(mapping as *const u8) - }) - } - } - } - } - - /// Granularity of MapAddr() and MapOffset() parameter values. - /// This may be greater than the value returned by page_size(). - pub fn granularity() -> uint { - use mem; - unsafe { - let mut info = mem::zeroed(); - libc::GetSystemInfo(&mut info); - - return info.dwAllocationGranularity as uint; - } - } -} - -#[cfg(windows)] -impl Drop for MemoryMap { - /// Unmap the mapping. Panics the task if any of `VirtualFree`, - /// `UnmapViewOfFile`, or `CloseHandle` fail. - fn drop(&mut self) { - use libc::types::os::arch::extra::{LPCVOID, HANDLE}; - use libc::consts::os::extra::FALSE; - if self.len == 0 { return } - - unsafe { - match self.kind { - MapVirtual => { - if libc::VirtualFree(self.data as *mut c_void, 0, - libc::MEM_RELEASE) == 0 { - println!("VirtualFree failed: {}", errno()); - } - }, - MapFile(mapping) => { - if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE { - println!("UnmapViewOfFile failed: {}", errno()); - } - if libc::CloseHandle(mapping as HANDLE) == FALSE { - println!("CloseHandle failed: {}", errno()); - } - } - } - } - } -} - -impl MemoryMap { - /// Returns the pointer to the memory created or modified by this map. - pub fn data(&self) -> *mut u8 { self.data } - /// Returns the number of bytes this map applies to. - pub fn len(&self) -> uint { self.len } - /// Returns the type of mapping this represents. - pub fn kind(&self) -> MemoryMapKind { self.kind } -} - -#[cfg(target_os = "linux")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `linux`. - pub const SYSNAME: &'static str = "linux"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "macos")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `macos`. - pub const SYSNAME: &'static str = "macos"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dylib`. - pub const DLL_SUFFIX: &'static str = ".dylib"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dylib`. - pub const DLL_EXTENSION: &'static str = "dylib"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "ios")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `ios`. - pub const SYSNAME: &'static str = "ios"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "freebsd")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `freebsd`. - pub const SYSNAME: &'static str = "freebsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "dragonfly")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `dragonfly`. - pub const SYSNAME: &'static str = "dragonfly"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "openbsd")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `openbsd`. - pub const SYSNAME: &'static str = "openbsd"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "android")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "unix"; - - /// A string describing the specific operating system in use: in this - /// case, `android`. - pub const SYSNAME: &'static str = "android"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, `lib`. - pub const DLL_PREFIX: &'static str = "lib"; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.so`. - pub const DLL_SUFFIX: &'static str = ".so"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `so`. - pub const DLL_EXTENSION: &'static str = "so"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, the empty string. - pub const EXE_SUFFIX: &'static str = ""; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, the empty string. - pub const EXE_EXTENSION: &'static str = ""; -} - -#[cfg(target_os = "windows")] -#[deprecated(since = "1.0.0", reason = "renamed to env::consts")] -#[unstable(feature = "os")] -pub mod consts { - pub use os::arch_consts::ARCH; - - pub const FAMILY: &'static str = "windows"; - - /// A string describing the specific operating system in use: in this - /// case, `windows`. - pub const SYSNAME: &'static str = "windows"; - - /// Specifies the filename prefix used for shared libraries on this - /// platform: in this case, the empty string. - pub const DLL_PREFIX: &'static str = ""; - - /// Specifies the filename suffix used for shared libraries on this - /// platform: in this case, `.dll`. - pub const DLL_SUFFIX: &'static str = ".dll"; - - /// Specifies the file extension used for shared libraries on this - /// platform that goes after the dot: in this case, `dll`. - pub const DLL_EXTENSION: &'static str = "dll"; - - /// Specifies the filename suffix used for executable binaries on this - /// platform: in this case, `.exe`. - pub const EXE_SUFFIX: &'static str = ".exe"; - - /// Specifies the file extension, if any, used for executable binaries - /// on this platform: in this case, `exe`. - pub const EXE_EXTENSION: &'static str = "exe"; -} - -#[cfg(target_arch = "x86")] -mod arch_consts { - pub const ARCH: &'static str = "x86"; -} - -#[cfg(target_arch = "x86_64")] -mod arch_consts { - pub const ARCH: &'static str = "x86_64"; -} - -#[cfg(target_arch = "arm")] -mod arch_consts { - pub const ARCH: &'static str = "arm"; -} - -#[cfg(target_arch = "aarch64")] -mod arch_consts { - pub const ARCH: &'static str = "aarch64"; -} - -#[cfg(target_arch = "mips")] -mod arch_consts { - pub const ARCH: &'static str = "mips"; -} - -#[cfg(target_arch = "mipsel")] -mod arch_consts { - pub const ARCH: &'static str = "mipsel"; -} - -#[cfg(target_arch = "powerpc")] -mod arch_consts { - pub const ARCH: &'static str = "powerpc"; -} - -#[cfg(test)] -mod tests { - #![allow(deprecated)] // rand - - use prelude::v1::*; - - use iter::repeat; - use os::{env, getcwd, getenv, make_absolute}; - use os::{split_paths, join_paths, setenv, unsetenv}; - use os; - use rand::Rng; - use rand; - - #[test] - pub fn last_os_error() { - debug!("{}", os::last_os_error()); - } - - fn make_rand_name() -> String { - let mut rng = rand::thread_rng(); - let n = format!("TEST{}", rng.gen_ascii_chars().take(10) - .collect::()); - assert!(getenv(&n).is_none()); - n - } - - #[test] - fn test_num_cpus() { - assert!(os::num_cpus() > 0); - } - - #[test] - fn test_setenv() { - let n = make_rand_name(); - setenv(&n, "VALUE"); - assert_eq!(getenv(&n), Some("VALUE".to_string())); - } - - #[test] - fn test_unsetenv() { - let n = make_rand_name(); - setenv(&n, "VALUE"); - unsetenv(&n); - assert_eq!(getenv(&n), None); - } - - #[test] - #[ignore] - fn test_setenv_overwrite() { - let n = make_rand_name(); - setenv(&n, "1"); - setenv(&n, "2"); - assert_eq!(getenv(&n), Some("2".to_string())); - setenv(&n, ""); - assert_eq!(getenv(&n), Some("".to_string())); - } - - // Windows GetEnvironmentVariable requires some extra work to make sure - // the buffer the variable is copied into is the right size - #[test] - #[ignore] - fn test_getenv_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - setenv(&n, &s); - debug!("{}", s.clone()); - assert_eq!(getenv(&n), Some(s)); - } - - #[test] - fn test_self_exe_name() { - let path = os::self_exe_name(); - assert!(path.is_some()); - let path = path.unwrap(); - debug!("{}", path.display()); - - // Hard to test this function - assert!(path.is_absolute()); - } - - #[test] - fn test_self_exe_path() { - let path = os::self_exe_path(); - assert!(path.is_some()); - let path = path.unwrap(); - debug!("{}", path.display()); - - // Hard to test this function - assert!(path.is_absolute()); - } - - #[test] - #[ignore] - fn test_env_getenv() { - let e = env(); - assert!(e.len() > 0); - for p in &e { - let (n, v) = (*p).clone(); - debug!("{}", n); - let v2 = getenv(&n); - // MingW seems to set some funky environment variables like - // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned - // from env() but not visible from getenv(). - assert!(v2.is_none() || v2 == Some(v)); - } - } - - #[test] - fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = repeat("x").take(10000).collect::(); - setenv(&n, &s); - assert_eq!(getenv(&n), Some(s)); - unsetenv(&n); - assert_eq!(getenv(&n), None); - } - - #[test] - fn test_env_setenv() { - let n = make_rand_name(); - - let mut e = env(); - setenv(&n, "VALUE"); - assert!(!e.contains(&(n.clone(), "VALUE".to_string()))); - - e = env(); - assert!(e.contains(&(n, "VALUE".to_string()))); - } - - #[test] - fn test() { - assert!((!Path::new("test-path").is_absolute())); - - let cwd = getcwd().unwrap(); - debug!("Current working directory: {}", cwd.display()); - - debug!("{}", make_absolute(&Path::new("test-path")).unwrap().display()); - debug!("{}", make_absolute(&Path::new("/usr/bin")).unwrap().display()); - } - - #[test] - #[cfg(unix)] - fn homedir() { - let oldhome = getenv("HOME"); - - setenv("HOME", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", ""); - assert!(os::homedir().is_none()); - - if let Some(s) = oldhome { - setenv("HOME", s); - } - } - - #[test] - #[cfg(windows)] - fn homedir() { - - let oldhome = getenv("HOME"); - let olduserprofile = getenv("USERPROFILE"); - - setenv("HOME", ""); - setenv("USERPROFILE", ""); - - assert!(os::homedir().is_none()); - - setenv("HOME", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", ""); - - setenv("USERPROFILE", "/home/MountainView"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - setenv("HOME", "/home/MountainView"); - setenv("USERPROFILE", "/home/PaloAlto"); - assert!(os::homedir() == Some(Path::new("/home/MountainView"))); - - if let Some(s) = oldhome { - setenv("HOME", &s); - } - if let Some(s) = olduserprofile { - setenv("USERPROFILE", &s); - } - } - - #[test] - fn memory_map_rw() { - use result::Result::{Ok, Err}; - - let chunk = match os::MemoryMap::new(16, &[ - os::MapOption::MapReadable, - os::MapOption::MapWritable - ]) { - Ok(chunk) => chunk, - Err(msg) => panic!("{:?}", msg) - }; - assert!(chunk.len >= 16); - - unsafe { - *chunk.data = 0xBE; - assert!(*chunk.data == 0xBE); - } - } - - #[test] - fn memory_map_file() { - use libc; - use os::*; - use old_io::fs::{File, unlink}; - use old_io::SeekStyle::SeekSet; - use old_io::FileMode::Open; - use old_io::FileAccess::ReadWrite; - - #[cfg(not(windows))] - fn get_fd(file: &File) -> libc::c_int { - use os::unix::AsRawFd; - file.as_raw_fd() - } - - #[cfg(windows)] - fn get_fd(file: &File) -> libc::HANDLE { - use os::windows::AsRawHandle; - file.as_raw_handle() - } - - let mut path = tmpdir(); - path.push("mmap_file.tmp"); - let size = MemoryMap::granularity() * 2; - let mut file = File::open_mode(&path, Open, ReadWrite).unwrap(); - file.seek(size as i64, SeekSet).unwrap(); - file.write_u8(0).unwrap(); - - let chunk = MemoryMap::new(size / 2, &[ - MapOption::MapReadable, - MapOption::MapWritable, - MapOption::MapFd(get_fd(&file)), - MapOption::MapOffset(size / 2) - ]).unwrap(); - assert!(chunk.len > 0); - - unsafe { - *chunk.data = 0xbe; - assert!(*chunk.data == 0xbe); - } - drop(chunk); - - unlink(&path).unwrap(); - } - - #[test] - #[cfg(windows)] - fn split_paths_windows() { - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed) == - parsed.iter().map(|s| Path::new(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse(r#""""#, &mut [""])); - assert!(check_parse(";;", &mut ["", "", ""])); - assert!(check_parse(r"c:\", &mut [r"c:\"])); - assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); - assert!(check_parse(r"c:\;c:\Program Files\", - &mut [r"c:\", r"c:\Program Files\"])); - assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); - assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, - &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); - } - - #[test] - #[cfg(unix)] - fn split_paths_unix() { - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed) == - parsed.iter().map(|s| Path::new(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse("::", &mut ["", "", ""])); - assert!(check_parse("/", &mut ["/"])); - assert!(check_parse("/:", &mut ["/", ""])); - assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); - } - - #[test] - #[cfg(unix)] - fn join_paths_unix() { - fn test_eq(input: &[&str], output: &str) -> bool { - join_paths(input).unwrap() == output.as_bytes() - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], - "/bin:/usr/bin:/usr/local/bin")); - assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], - ":/bin:::/usr/bin:")); - assert!(join_paths(&["/te:st"]).is_err()); - } - - #[test] - #[cfg(windows)] - fn join_paths_windows() { - fn test_eq(input: &[&str], output: &str) -> bool { - join_paths(input).unwrap() == output.as_bytes() - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&[r"c:\windows", r"c:\"], - r"c:\windows;c:\")); - assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], - r";c:\windows;;;c:\;")); - assert!(test_eq(&[r"c:\te;st", r"c:\"], - r#""c:\te;st";c:\"#)); - assert!(join_paths(&[r#"c:\te"st"#]).is_err()); - } - - // More recursive_mkdir tests are in extra::tempfile -} diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 2e05f6d974..3e0584d9ab 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -11,29 +11,22 @@ #![unstable(feature = "std_misc")] use prelude::v1::*; +use io::prelude::*; use any::Any; use cell::RefCell; -use old_io::IoResult; use rt::{backtrace, unwind}; -use rt::util::{Stderr, Stdio}; +use sys::stdio::Stderr; use thread; // Defined in this module instead of old_io::stdio so that the unwinding thread_local! { - pub static LOCAL_STDERR: RefCell>> = { + pub static LOCAL_STDERR: RefCell>> = { RefCell::new(None) } } -impl Writer for Stdio { - fn write_all(&mut self, bytes: &[u8]) -> IoResult<()> { - let _ = self.write_bytes(bytes); - Ok(()) - } -} - -pub fn on_panic(obj: &(Any+Send), file: &'static str, line: uint) { +pub fn on_panic(obj: &(Any+Send), file: &'static str, line: usize) { let msg = match obj.downcast_ref::<&'static str>() { Some(s) => *s, None => match obj.downcast_ref::() { @@ -41,7 +34,7 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: uint) { None => "Box", } }; - let mut err = Stderr; + let mut err = Stderr::new(); let thread = thread::current(); let name = thread.name().unwrap_or(""); let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take()); diff --git a/src/libstd/path.rs b/src/libstd/path.rs old mode 100755 new mode 100644 index 49a5efec7c..4471b5afa8 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -17,7 +17,7 @@ //! //! ## Simple usage //! -//! Path manipulation involves both parsing components from slices and building +//! Path manipulation includes both parsing components from slices and building //! new owned paths. //! //! To parse a path, you can create a `Path` slice from a `str` @@ -37,7 +37,7 @@ //! ```rust //! use std::path::PathBuf; //! -//! let mut path = PathBuf::new("c:\\"); +//! let mut path = PathBuf::from("c:\\"); //! path.push("windows"); //! path.push("system32"); //! path.set_extension("dll"); @@ -50,9 +50,9 @@ //! `\`). The APIs for path parsing are largely specified in terms of the path's //! components, so it's important to clearly understand how those are determined. //! -//! A path can always be reconstructed into an equivalent path by putting -//! together its components via `push`. Syntactically, the paths may differ by -//! the normalization described below. +//! A path can always be reconstructed into an *equivalent* path by +//! putting together its components via `push`. Syntactically, the +//! paths may differ by the normalization described below. //! //! ### Component types //! @@ -62,13 +62,13 @@ //! directories. The path `a/b` has two normal components, `a` and `b`. //! //! * Current directory components represent the `.` character. For example, -//! `a/.` has a normal component `a` and a current directory component. +//! `./a` has a current directory component and a normal component `a`. //! //! * The root directory component represents a separator that designates //! starting from root. For example, `/a/b` has a root directory component //! followed by normal components `a` and `b`. //! -//! On Windows, two additional component types come into play: +//! On Windows, an additional component type comes into play: //! //! * Prefix components, of which there is a large variety. For example, `C:` //! and `\\server\share` are prefixes. The path `C:windows` has a prefix @@ -76,12 +76,6 @@ //! prefix component `C:`, a root directory component, and a normal component //! `windows`. //! -//! * Empty components, a special case for so-called "verbatim" paths where very -//! little normalization is allowed. For example, `\\?\C:\` has a "verbatim" -//! prefix `\\?\C:`, a root component, and an empty component (as a way of -//! representing the trailing `\`. Such a trailing `\` is in fact the only -//! situation in which an empty component is produced. -//! //! ### Normalization //! //! Aside from splitting on the separator(s), there is a small amount of @@ -90,29 +84,29 @@ //! * Repeated separators are ignored: `a/b` and `a//b` both have components `a` //! and `b`. //! -//! * Paths ending in a separator are treated as if they has a current directory -//! component at the end (or, in verbatim paths, an empty component). For -//! example, while `a/b` has components `a` and `b`, the paths `a/b/` and -//! `a/b/.` both have components `a`, `b`, and `.` (current directory). The -//! reason for this normalization is that `a/b` and `a/b/` are treated -//! differently in some contexts, but `a/b/` and `a/b/.` are always treated -//! the same. +//! * Occurrences of `.` are normalized away, *except* if they are at +//! the beginning of the path (in which case they are often meaningful +//! in terms of path searching). So, for example, `a/./b`, `a/b/`, +//! `/a/b/.` and `a/b` all have components `a` and `b`, but `./a/b` +//! has a leading current directory component. //! -//! No other normalization takes place by default. In particular, `a/./b/` and -//! `a/b` are treated distinctly in terms of components, as are `a/c` and -//! `a/b/../c`. Further normalization is possible to build on top of the -//! components APIs, and will be included in this library very soon. +//! No other normalization takes place by default. In particular, +//! `a/c` and `a/b/../c` are distinct, to account for the possibility +//! that `b` is a symbolic link (so its parent isn't `a`). Further +//! normalization is possible to build on top of the components APIs, +//! and will be included in this library in the near future. -#![unstable(feature = "path")] +#![stable(feature = "rust1", since = "1.0.0")] use core::prelude::*; use ascii::*; -use borrow::{Borrow, ToOwned, Cow}; +use borrow::{Borrow, IntoCow, ToOwned, Cow}; use cmp; use iter::{self, IntoIterator}; use mem; use ops::{self, Deref}; +use string::String; use vec::Vec; use fmt; @@ -166,7 +160,6 @@ mod platform { use core::prelude::*; use ascii::*; - use char::CharExt as UnicodeCharExt; use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix}; use ffi::OsStr; @@ -270,23 +263,30 @@ mod platform { /// `/` is *not* treated as a separator and essentially no normalization is /// performed. #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Prefix<'a> { /// Prefix `\\?\`, together with the given component immediately following it. + #[stable(feature = "rust1", since = "1.0.0")] Verbatim(&'a OsStr), /// Prefix `\\?\UNC\`, with the "server" and "share" components following it. + #[stable(feature = "rust1", since = "1.0.0")] VerbatimUNC(&'a OsStr, &'a OsStr), /// Prefix like `\\?\C:\`, for the given drive letter + #[stable(feature = "rust1", since = "1.0.0")] VerbatimDisk(u8), /// Prefix `\\.\`, together with the given component immediately following it. + #[stable(feature = "rust1", since = "1.0.0")] DeviceNS(&'a OsStr), /// Prefix `\\server\share`, with the given "server" and "share" components. + #[stable(feature = "rust1", since = "1.0.0")] UNC(&'a OsStr, &'a OsStr), /// Prefix `C:` for the given disk drive. + #[stable(feature = "rust1", since = "1.0.0")] Disk(u8), } @@ -314,6 +314,7 @@ impl<'a> Prefix<'a> { /// Determine if the prefix is verbatim, i.e. begins `\\?\`. #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_verbatim(&self) -> bool { use self::Prefix::*; match *self { @@ -342,12 +343,23 @@ impl<'a> Prefix<'a> { /// Determine whether the character is one of the permitted path /// separators for the current platform. +/// +/// # Examples +/// +/// ``` +/// use std::path; +/// +/// assert!(path::is_separator('/')); +/// assert!(!path::is_separator('❤')); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub fn is_separator(c: char) -> bool { use ascii::*; c.is_ascii() && is_sep_byte(c as u8) } /// The primary sperator for the current platform +#[stable(feature = "rust1", since = "1.0.0")] pub const MAIN_SEPARATOR: char = platform::MAIN_SEP; //////////////////////////////////////////////////////////////////////////////// @@ -383,37 +395,15 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { } //////////////////////////////////////////////////////////////////////////////// -// Cross-platform parsing +// Cross-platform, iterator-independent parsing //////////////////////////////////////////////////////////////////////////////// -/// Says whether the path ends in a separator character and therefore needs to -/// be treated as if it ended with an additional `.` -fn has_suffix(s: &[u8], prefix: Option) -> bool { - let (prefix_len, verbatim) = if let Some(p) = prefix { - (p.len(), p.is_verbatim()) - } else { (0, false) }; - if prefix_len > 0 && prefix_len == s.len() && !verbatim { return true; } - let mut splits = s[prefix_len..].split(|b| is_sep_byte(*b)); - let last = splits.next_back().unwrap(); - let more = splits.next_back().is_some(); - more && last == b"" -} - /// Says whether the first byte after the prefix is a separator. fn has_physical_root(s: &[u8], prefix: Option) -> bool { let path = if let Some(p) = prefix { &s[p.len()..] } else { s }; path.len() > 0 && is_sep_byte(path[0]) } -fn parse_single_component(comp: &[u8]) -> Option { - match comp { - b"." => Some(Component::CurDir), - b".." => Some(Component::ParentDir), - b"" => None, - _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })) - } -} - // basic workhorse for splitting stem and extension #[allow(unused_unsafe)] // FIXME fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { @@ -425,7 +415,7 @@ fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { // contents of the encoding and (2) new &OsStr values are produced // only from ASCII-bounded slices of existing &OsStr values. - let mut iter = os_str_as_u8_slice(file).rsplitn(1, |b| *b == b'.'); + let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.'); let after = iter.next(); let before = iter.next(); if before == Some(b"") { @@ -445,16 +435,62 @@ fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { /// front and back of the path each keep track of what parts of the path have /// been consumed so far. /// -/// Going front to back, a path is made up of a prefix, a root component, a body -/// (of normal components), and a suffix/emptycomponent (normalized `.` or `` -/// for a path ending with the separator) +/// Going front to back, a path is made up of a prefix, a starting +/// directory component, and a body (of normal components) #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] enum State { Prefix = 0, // c: - Root = 1, // / + StartDir = 1, // / or . or nothing Body = 2, // foo/bar/baz - Suffix = 3, // . - Done = 4, + Done = 3, +} + +/// A Windows path prefix, e.g. `C:` or `\server\share`. +/// +/// Does not occur on Unix. +#[stable(feature = "rust1", since = "1.0.0")] +#[derive(Copy, Clone, Eq, Hash, Debug)] +pub struct PrefixComponent<'a> { + /// The prefix as an unparsed `OsStr` slice. + raw: &'a OsStr, + + /// The parsed prefix data. + parsed: Prefix<'a>, +} + +impl<'a> PrefixComponent<'a> { + /// The parsed prefix data. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn kind(&self) -> Prefix<'a> { + self.parsed + } + + /// The raw `OsStr` slice for this prefix. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_os_str(&self) -> &'a OsStr { + self.raw + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> cmp::PartialEq for PrefixComponent<'a> { + fn eq(&self, other: &PrefixComponent<'a>) -> bool { + cmp::PartialEq::eq(&self.parsed, &other.parsed) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> cmp::PartialOrd for PrefixComponent<'a> { + fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option { + cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> cmp::Ord for PrefixComponent<'a> { + fn cmp(&self, other: &PrefixComponent<'a>) -> cmp::Ordering { + cmp::Ord::cmp(&self.parsed, &other.parsed) + } } /// A single component of a path. @@ -462,55 +498,70 @@ enum State { /// See the module documentation for an in-depth explanation of components and /// their role in the API. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Component<'a> { /// A Windows path prefix, e.g. `C:` or `\server\share`. /// /// Does not occur on Unix. - Prefix { - /// The prefix as an unparsed `OsStr` slice. - raw: &'a OsStr, - - /// The parsed prefix data. - parsed: Prefix<'a> - }, - - /// An empty component. Only used on Windows for the last component of - /// verbatim paths ending with a separator (e.g. the last component of - /// `\\?\C:\windows\` but not `\\?\C:\windows` or `C:\windows`). - Empty, + #[stable(feature = "rust1", since = "1.0.0")] + Prefix(PrefixComponent<'a>), /// The root directory component, appears after any prefix and before anything else + #[stable(feature = "rust1", since = "1.0.0")] RootDir, /// A reference to the current directory, i.e. `.` + #[stable(feature = "rust1", since = "1.0.0")] CurDir, /// A reference to the parent directory, i.e. `..` + #[stable(feature = "rust1", since = "1.0.0")] ParentDir, /// A normal component, i.e. `a` and `b` in `a/b` + #[stable(feature = "rust1", since = "1.0.0")] Normal(&'a OsStr), } impl<'a> Component<'a> { /// Extract the underlying `OsStr` slice + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_os_str(self) -> &'a OsStr { match self { - Component::Prefix { raw, .. } => &raw, - Component::Empty => OsStr::from_str(""), - Component::RootDir => OsStr::from_str(MAIN_SEP_STR), - Component::CurDir => OsStr::from_str("."), - Component::ParentDir => OsStr::from_str(".."), + Component::Prefix(p) => p.as_os_str(), + Component::RootDir => OsStr::new(MAIN_SEP_STR), + Component::CurDir => OsStr::new("."), + Component::ParentDir => OsStr::new(".."), Component::Normal(path) => path, } } } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> AsRef for Component<'a> { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + /// The core iterator giving the components of a path. /// /// See the module documentation for an in-depth explanation of components and /// their role in the API. +/// +/// # Examples +/// +/// ``` +/// use std::path::Path; +/// +/// let path = Path::new("/tmp/foo/bar.txt"); +/// +/// for component in path.components() { +/// println!("{:?}", component); +/// } +/// ``` #[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Components<'a> { // The path left to parse components from path: &'a [u8], @@ -531,6 +582,7 @@ pub struct Components<'a> { /// An iterator over the components of a path, as `OsStr` slices. #[derive(Clone)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a> { inner: Components<'a> } @@ -554,9 +606,12 @@ impl<'a> Components<'a> { else { 0 } } - fn prefix_and_root(&self) -> usize { - let root = if self.front <= State::Root && self.has_physical_root { 1 } else { 0 }; - self.prefix_remaining() + root + // Given the iteration so far, how much of the pre-State::Body path is left? + #[inline] + fn len_before_body(&self) -> usize { + let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 }; + let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 }; + self.prefix_remaining() + root + cur_dir } // is the iteration complete? @@ -575,15 +630,22 @@ impl<'a> Components<'a> { } /// Extract a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp/foo/bar.txt"); + /// + /// println!("{:?}", path.components().as_path()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_path(&self) -> &'a Path { let mut comps = self.clone(); if comps.front == State::Body { comps.trim_left(); } if comps.back == State::Body { comps.trim_right(); } - if comps.path.is_empty() && comps.front < comps.back && comps.back == State::Suffix { - Path::new(".") - } else { - unsafe { Path::from_u8_slice(comps.path) } - } + unsafe { Path::from_u8_slice(comps.path) } } /// Is the *original* path rooted? @@ -595,6 +657,30 @@ impl<'a> Components<'a> { false } + /// Should the normalized path include a leading . ? + fn include_cur_dir(&self) -> bool { + if self.has_root() { return false } + let mut iter = self.path[self.prefix_len()..].iter(); + match (iter.next(), iter.next()) { + (Some(&b'.'), None) => true, + (Some(&b'.'), Some(&b)) => self.is_sep_byte(b), + _ => false + } + } + + // parse a given byte sequence into the corresponding path component + fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option> { + match comp { + b"." if self.prefix_verbatim() => Some(Component::CurDir), + b"." => None, // . components are normalized away, except at + // the beginning of a path, which is treated + // separately via `include_cur_dir` + b".." => Some(Component::ParentDir), + b"" => None, + _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })) + } + } + // parse a component from the left, saying how many bytes to consume to // remove the component fn parse_next_component(&self) -> (usize, Option>) { @@ -603,19 +689,19 @@ impl<'a> Components<'a> { None => (0, self.path), Some(i) => (1, &self.path[.. i]), }; - (comp.len() + extra, parse_single_component(comp)) + (comp.len() + extra, self.parse_single_component(comp)) } // parse a component from the right, saying how many bytes to consume to // remove the component fn parse_next_component_back(&self) -> (usize, Option>) { debug_assert!(self.back == State::Body); - let start = self.prefix_and_root(); + let start = self.len_before_body(); let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) { None => (0, &self.path[start ..]), Some(i) => (1, &self.path[start + i + 1 ..]), }; - (comp.len() + extra, parse_single_component(comp)) + (comp.len() + extra, self.parse_single_component(comp)) } // trim away repeated separators (i.e. emtpy components) on the left @@ -632,7 +718,7 @@ impl<'a> Components<'a> { // trim away repeated separators (i.e. emtpy components) on the right fn trim_right(&mut self) { - while self.path.len() > self.prefix_and_root() { + while self.path.len() > self.len_before_body() { let (size, comp) = self.parse_next_component_back(); if comp.is_some() { return; @@ -643,18 +729,49 @@ impl<'a> Components<'a> { } /// Examine the next component without consuming it. + #[unstable(feature = "path_components_peek")] pub fn peek(&self) -> Option> { self.clone().next() } } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> AsRef for Components<'a> { + fn as_ref(&self) -> &Path { + self.as_path() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> AsRef for Components<'a> { + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + impl<'a> Iter<'a> { /// Extract a slice corresponding to the portion of the path remaining for iteration. + #[stable(feature = "rust1", since = "1.0.0")] pub fn as_path(&self) -> &'a Path { self.inner.as_path() } } +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> AsRef for Iter<'a> { + fn as_ref(&self) -> &Path { + self.as_path() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> AsRef for Iter<'a> { + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Iter<'a> { type Item = &'a OsStr; @@ -663,12 +780,14 @@ impl<'a> Iterator for Iter<'a> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> DoubleEndedIterator for Iter<'a> { fn next_back(&mut self) -> Option<&'a OsStr> { self.inner.next_back().map(Component::as_os_str) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Components<'a> { type Item = Component<'a>; @@ -676,19 +795,19 @@ impl<'a> Iterator for Components<'a> { while !self.finished() { match self.front { State::Prefix if self.prefix_len() > 0 => { - self.front = State::Root; + self.front = State::StartDir; debug_assert!(self.prefix_len() <= self.path.len()); let raw = &self.path[.. self.prefix_len()]; self.path = &self.path[self.prefix_len() .. ]; - return Some(Component::Prefix { + return Some(Component::Prefix(PrefixComponent { raw: unsafe { u8_slice_as_os_str(raw) }, parsed: self.prefix.unwrap() - }) + })) } State::Prefix => { - self.front = State::Root; + self.front = State::StartDir; } - State::Root => { + State::StartDir => { self.front = State::Body; if self.has_physical_root { debug_assert!(self.path.len() > 0); @@ -698,6 +817,10 @@ impl<'a> Iterator for Components<'a> { if p.has_implicit_root() && !p.is_verbatim() { return Some(Component::RootDir) } + } else if self.include_cur_dir() { + debug_assert!(self.path.len() > 0); + self.path = &self.path[1..]; + return Some(Component::CurDir) } } State::Body if !self.path.is_empty() => { @@ -706,15 +829,7 @@ impl<'a> Iterator for Components<'a> { if comp.is_some() { return comp } } State::Body => { - self.front = State::Suffix; - } - State::Suffix => { self.front = State::Done; - if self.prefix_verbatim() { - return Some(Component::Empty) - } else { - return Some(Component::CurDir) - } } State::Done => unreachable!() } @@ -723,27 +838,20 @@ impl<'a> Iterator for Components<'a> { } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> DoubleEndedIterator for Components<'a> { fn next_back(&mut self) -> Option> { while !self.finished() { match self.back { - State::Suffix => { - self.back = State::Body; - if self.prefix_verbatim() { - return Some(Component::Empty) - } else { - return Some(Component::CurDir) - } - } - State::Body if self.path.len() > self.prefix_and_root() => { + State::Body if self.path.len() > self.len_before_body() => { let (size, comp) = self.parse_next_component_back(); self.path = &self.path[.. self.path.len() - size]; if comp.is_some() { return comp } } State::Body => { - self.back = State::Root; + self.back = State::StartDir; } - State::Root => { + State::StartDir => { self.back = State::Prefix; if self.has_physical_root { self.path = &self.path[.. self.path.len() - 1]; @@ -752,14 +860,17 @@ impl<'a> DoubleEndedIterator for Components<'a> { if p.has_implicit_root() && !p.is_verbatim() { return Some(Component::RootDir) } + } else if self.include_cur_dir() { + self.path = &self.path[.. self.path.len() - 1]; + return Some(Component::CurDir) } } State::Prefix if self.prefix_len() > 0 => { self.back = State::Done; - return Some(Component::Prefix { + return Some(Component::Prefix(PrefixComponent { raw: unsafe { u8_slice_as_os_str(self.path) }, parsed: self.prefix.unwrap() - }) + })) } State::Prefix => { self.back = State::Done; @@ -772,24 +883,24 @@ impl<'a> DoubleEndedIterator for Components<'a> { } } -fn optional_path(path: &Path) -> Option<&Path> { - if path.as_u8_slice().is_empty() { None } else { Some(path) } -} - +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> cmp::PartialEq for Components<'a> { fn eq(&self, other: &Components<'a>) -> bool { iter::order::eq(self.clone(), other.clone()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> cmp::Eq for Components<'a> {} +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> cmp::PartialOrd for Components<'a> { fn partial_cmp(&self, other: &Components<'a>) -> Option { iter::order::partial_cmp(self.clone(), other.clone()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> cmp::Ord for Components<'a> { fn cmp(&self, other: &Components<'a>) -> cmp::Ordering { iter::order::cmp(self.clone(), other.clone()) @@ -809,17 +920,18 @@ impl<'a> cmp::Ord for Components<'a> { /// More details about the overall approach can be found in /// the module documentation. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::path::PathBuf; /// -/// let mut path = PathBuf::new("c:\\"); +/// let mut path = PathBuf::from("c:\\"); /// path.push("windows"); /// path.push("system32"); /// path.set_extension("dll"); /// ``` #[derive(Clone, Hash)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { inner: OsString } @@ -829,10 +941,16 @@ impl PathBuf { unsafe { mem::transmute(self) } } - /// Allocate a `PathBuf` with initial contents given by the - /// argument. - pub fn new(s: &S) -> PathBuf { - PathBuf { inner: s.as_os_str().to_os_string() } + /// Allocate an empty `PathBuf`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> PathBuf { + PathBuf { inner: OsString::new() } + } + + /// Coerce to a `Path` slice. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_path(&self) -> &Path { + self } /// Extend `self` with `path`. @@ -844,7 +962,10 @@ impl PathBuf { /// * if `path` has a root but no prefix (e.g. `\windows`), it /// replaces everything except for the prefix (if any) of `self`. /// * if `path` has a prefix but no root, it replaces `self. - pub fn push(&mut self, path: &P) where P: AsPath { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push>(&mut self, path: P) { + let path = path.as_ref(); + // in general, a separator is needed if the rightmost byte is not a separator let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false); @@ -859,8 +980,6 @@ impl PathBuf { } } - let path = path.as_path(); - // absolute `path` replaces `self` if path.is_absolute() || path.prefix().is_some() { self.as_mut_vec().truncate(0); @@ -872,16 +991,17 @@ impl PathBuf { // `path` is a pure relative path } else if need_sep { - self.inner.push_os_str(OsStr::from_str(MAIN_SEP_STR)); + self.inner.push(MAIN_SEP_STR); } - self.inner.push_os_str(path.as_os_str()); + self.inner.push(path); } /// Truncate `self` to `self.parent()`. /// - /// Returns `false` and does nothing if `self.parent()` is `None`. + /// Returns false and does nothing if `self.file_name()` is `None`. /// Otherwise, returns `true`. + #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> bool { match self.parent().map(|p| p.as_u8_slice().len()) { Some(len) => { @@ -899,26 +1019,24 @@ impl PathBuf { /// /// # Examples /// - /// ```rust - /// use std::path::{Path, PathBuf}; + /// ``` + /// use std::path::PathBuf; /// - /// let mut buf = PathBuf::new("/foo/"); + /// let mut buf = PathBuf::from("/"); /// assert!(buf.file_name() == None); /// buf.set_file_name("bar"); - /// assert!(buf == PathBuf::new("/foo/bar")); + /// assert!(buf == PathBuf::from("/bar")); /// assert!(buf.file_name().is_some()); /// buf.set_file_name("baz.txt"); - /// assert!(buf == PathBuf::new("/foo/baz.txt")); + /// assert!(buf == PathBuf::from("/baz.txt")); /// ``` - pub fn set_file_name(&mut self, file_name: &S) where S: AsOsStr { - if self.file_name().is_some() && !self.pop() { - // Given that there is a file name, this is reachable only for - // Windows paths like c:file or paths like `foo`, but not `c:\` or - // `/`. - let prefix_len = self.components().prefix_remaining(); - self.as_mut_vec().truncate(prefix_len); + #[stable(feature = "rust1", since = "1.0.0")] + pub fn set_file_name>(&mut self, file_name: S) { + if self.file_name().is_some() { + let popped = self.pop(); + debug_assert!(popped); } - self.push(file_name.as_os_str()); + self.push(file_name.as_ref()); } /// Updates `self.extension()` to `extension`. @@ -927,18 +1045,19 @@ impl PathBuf { /// /// Otherwise, returns `true`; if `self.extension()` is `None`, the extension /// is added; otherwise it is replaced. - pub fn set_extension(&mut self, extension: &S) -> bool { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn set_extension>(&mut self, extension: S) -> bool { if self.file_name().is_none() { return false; } let mut stem = match self.file_stem() { Some(stem) => stem.to_os_string(), - None => OsString::from_str(""), + None => OsString::new(), }; - let extension = extension.as_os_str(); + let extension = extension.as_ref(); if os_str_as_u8_slice(extension).len() > 0 { - stem.push_os_str(OsStr::from_str(".")); - stem.push_os_str(extension.as_os_str()); + stem.push("."); + stem.push(extension); } self.set_file_name(&stem); @@ -946,33 +1065,59 @@ impl PathBuf { } /// Consume the `PathBuf`, yielding its internal `OsString` storage + #[stable(feature = "rust1", since = "1.0.0")] pub fn into_os_string(self) -> OsString { self.inner } } -impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath { - fn from_iter>(iter: I) -> PathBuf { - let mut buf = PathBuf::new(""); +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized + AsRef> From<&'a T> for PathBuf { + fn from(s: &'a T) -> PathBuf { + PathBuf::from(s.as_ref().to_os_string()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From for PathBuf { + fn from(s: OsString) -> PathBuf { + PathBuf { inner: s } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From for PathBuf { + fn from(s: String) -> PathBuf { + PathBuf::from(OsString::from(s)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl> iter::FromIterator

for PathBuf { + fn from_iter>(iter: I) -> PathBuf { + let mut buf = PathBuf::new(); buf.extend(iter); buf } } -impl<'a, P: ?Sized + 'a> iter::Extend<&'a P> for PathBuf where P: AsPath { - fn extend>(&mut self, iter: I) { +#[stable(feature = "rust1", since = "1.0.0")] +impl> iter::Extend

for PathBuf { + fn extend>(&mut self, iter: I) { for p in iter { self.push(p) } } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for PathBuf { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Debug::fmt(&**self, formatter) } } +#[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for PathBuf { type Target = Path; @@ -981,43 +1126,79 @@ impl ops::Deref for PathBuf { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Borrow for PathBuf { fn borrow(&self) -> &Path { self.deref() } } +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoCow<'static, Path> for PathBuf { + fn into_cow(self) -> Cow<'static, Path> { + Cow::Owned(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> IntoCow<'a, Path> for &'a Path { + fn into_cow(self) -> Cow<'a, Path> { + Cow::Borrowed(self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for Path { type Owned = PathBuf; fn to_owned(&self) -> PathBuf { self.to_path_buf() } } +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::PartialEq for PathBuf { fn eq(&self, other: &PathBuf) -> bool { self.components() == other.components() } } +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::Eq for PathBuf {} +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::PartialOrd for PathBuf { fn partial_cmp(&self, other: &PathBuf) -> Option { self.components().partial_cmp(&other.components()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::Ord for PathBuf { fn cmp(&self, other: &PathBuf) -> cmp::Ordering { self.components().cmp(&other.components()) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for PathBuf { + fn as_ref(&self) -> &OsStr { + &self.inner[..] + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for PathBuf { fn as_os_str(&self) -> &OsStr { &self.inner[..] } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Into for PathBuf { + fn into(self) -> OsString { + self.inner + } +} + /// A slice of a path (akin to `str`). /// /// This type supports a number of operations for inspecting a path, including @@ -1029,9 +1210,9 @@ impl AsOsStr for PathBuf { /// This is an *unsized* type, meaning that it must always be used with behind a /// pointer like `&` or `Box`. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::path::Path; /// /// let path = Path::new("/tmp/foo/bar.txt"); @@ -1041,6 +1222,7 @@ impl AsOsStr for PathBuf { /// ``` /// #[derive(Hash)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Path { inner: OsStr } @@ -1059,13 +1241,45 @@ impl Path { /// Directly wrap a string slice as a `Path` slice. /// /// This is a cost-free conversion. - pub fn new(s: &S) -> &Path { - unsafe { mem::transmute(s.as_os_str()) } + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// Path::new("foo.txt"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new + ?Sized>(s: &S) -> &Path { + unsafe { mem::transmute(s.as_ref()) } + } + + /// Yield the underlying `OsStr` slice. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let os_str = Path::new("foo.txt").as_os_str(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn as_os_str(&self) -> &OsStr { + &self.inner } /// Yield a `&str` slice if the `Path` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path_str = Path::new("foo.txt").to_str(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_str(&self) -> Option<&str> { self.inner.to_str() } @@ -1073,13 +1287,31 @@ impl Path { /// Convert a `Path` to a `Cow`. /// /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path_str = Path::new("foo.txt").to_string_lossy(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() } /// Convert a `Path` to an owned `PathBuf`. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path_str = Path::new("foo.txt").to_path_buf(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_path_buf(&self) -> PathBuf { - PathBuf::new(self) + PathBuf::from(self.inner.to_os_string()) } /// A path is *absolute* if it is independent of the current directory. @@ -1090,12 +1322,30 @@ impl Path { /// * On Windows, a path is absolute if it has a prefix and starts with the /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. In /// other words, `path.is_absolute() == path.prefix().is_some() && path.has_root()`. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// assert_eq!(false, Path::new("foo.txt").is_absolute()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_absolute(&self) -> bool { self.has_root() && (cfg!(unix) || self.prefix().is_some()) } /// A path is *relative* if it is not absolute. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// assert!(Path::new("foo.txt").is_relative()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn is_relative(&self) -> bool { !self.is_absolute() } @@ -1105,12 +1355,9 @@ impl Path { /// Prefixes are relevant only for Windows paths, and consist of volumes /// like `C:`, UNC prefixes like `\\server`, and others described in more /// detail in `std::os::windows::PathExt`. - pub fn prefix(&self) -> Option<&Path> { - let iter = self.components(); - optional_path(unsafe { - Path::from_u8_slice( - &self.as_u8_slice()[.. iter.prefix_remaining()]) - }) + #[unstable(feature = "path_prefix", reason = "uncertain whether to expose this convenience")] + pub fn prefix(&self) -> Option { + self.components().prefix } /// A path has a root if the body of the path begins with the directory separator. @@ -1121,69 +1368,113 @@ impl Path { /// * has no prefix and begins with a separator, e.g. `\\windows` /// * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows` /// * has any non-disk prefix, e.g. `\\server\share` + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// assert!(Path::new("/etc/passwd").has_root()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn has_root(&self) -> bool { self.components().has_root() } - /// The path without its final component. + /// The path without its final component, if any. /// - /// Does nothing, returning `None` if the path consists of just a prefix - /// and/or root directory reference. + /// Returns `None` if the path terminates in a root or prefix. /// /// # Examples /// - /// ```rust + /// ``` /// use std::path::Path; /// /// let path = Path::new("/foo/bar"); /// let foo = path.parent().unwrap(); + /// /// assert!(foo == Path::new("/foo")); + /// /// let root = foo.parent().unwrap(); + /// /// assert!(root == Path::new("/")); /// assert!(root.parent() == None); /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn parent(&self) -> Option<&Path> { let mut comps = self.components(); let comp = comps.next_back(); - let rest = optional_path(comps.as_path()); - - match (comp, comps.next_back()) { - (Some(Component::CurDir), Some(Component::RootDir)) => None, - (Some(Component::CurDir), Some(Component::Prefix { .. })) => None, - (Some(Component::Empty), Some(Component::RootDir)) => None, - (Some(Component::Empty), Some(Component::Prefix { .. })) => None, - (Some(Component::Prefix { .. }), None) => None, - (Some(Component::RootDir), Some(Component::Prefix { .. })) => None, - _ => rest - } + comp.and_then(|p| match p { + Component::Normal(_) | + Component::CurDir | + Component::ParentDir => Some(comps.as_path()), + _ => None + }) } /// The final component of the path, if it is a normal file. /// /// If the path terminates in `.`, `..`, or consists solely or a root of - /// prefix, `file` will return `None`. + /// prefix, `file_name` will return `None`. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("hello_world.rs"); + /// let filename = "hello_world.rs"; + /// + /// assert_eq!(filename, path.file_name().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn file_name(&self) -> Option<&OsStr> { self.components().next_back().and_then(|p| match p { - Component::Normal(p) => Some(p.as_os_str()), + Component::Normal(p) => Some(p.as_ref()), _ => None }) } /// Returns a path that, when joined onto `base`, yields `self`. - pub fn relative_from<'a, P: ?Sized>(&'a self, base: &'a P) -> Option<&Path> where - P: AsPath + /// + /// If `base` is not a prefix of `self` (i.e. `starts_with` + /// returns false), then `relative_from` returns `None`. + #[unstable(feature = "path_relative_from", reason = "see #23284")] + pub fn relative_from<'a, P: ?Sized + AsRef>(&'a self, base: &'a P) -> Option<&Path> { - iter_after(self.components(), base.as_path().components()).map(|c| c.as_path()) + iter_after(self.components(), base.as_ref().components()).map(|c| c.as_path()) } /// Determines whether `base` is a prefix of `self`. - pub fn starts_with(&self, base: &P) -> bool where P: AsPath { - iter_after(self.components(), base.as_path().components()).is_some() + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/etc/passwd"); + /// + /// assert!(path.starts_with("/etc")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn starts_with>(&self, base: P) -> bool { + iter_after(self.components(), base.as_ref().components()).is_some() } - /// Determines whether `base` is a suffix of `self`. - pub fn ends_with(&self, child: &P) -> bool where P: AsPath { - iter_after(self.components().rev(), child.as_path().components().rev()).is_some() + /// Determines whether `child` is a suffix of `self`. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/etc/passwd"); + /// + /// assert!(path.ends_with("passwd")); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ends_with>(&self, child: P) -> bool { + iter_after(self.components().rev(), child.as_ref().components().rev()).is_some() } /// Extract the stem (non-extension) portion of `self.file()`. @@ -1194,6 +1485,17 @@ impl Path { /// * The entire file name if there is no embedded `.`; /// * The entire file name if the file name begins with `.` and has no other `.`s within; /// * Otherwise, the portion of the file name before the final `.` + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("foo.rs"); + /// + /// assert_eq!("foo", path.file_stem().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn file_stem(&self) -> Option<&OsStr> { self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after)) } @@ -1206,6 +1508,17 @@ impl Path { /// * None, if there is no embedded `.`; /// * None, if the file name begins with `.` and has no other `.`s within; /// * Otherwise, the portion of the file name after the final `.` + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("foo.rs"); + /// + /// assert_eq!("rs", path.extension().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn extension(&self) -> Option<&OsStr> { self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after)) } @@ -1213,7 +1526,18 @@ impl Path { /// Creates an owned `PathBuf` with `path` adjoined to `self`. /// /// See `PathBuf::push` for more details on what it means to adjoin a path. - pub fn join(&self, path: &P) -> PathBuf where P: AsPath { + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp"); + /// + /// let new_path = path.join("foo"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join>(&self, path: P) -> PathBuf { let mut buf = self.to_path_buf(); buf.push(path); buf @@ -1222,7 +1546,18 @@ impl Path { /// Creates an owned `PathBuf` like `self` but with the given file name. /// /// See `PathBuf::set_file_name` for more details. - pub fn with_file_name(&self, file_name: &S) -> PathBuf where S: AsOsStr { + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp/foo.rs"); + /// + /// let new_path = path.with_file_name("bar.rs"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_file_name>(&self, file_name: S) -> PathBuf { let mut buf = self.to_path_buf(); buf.set_file_name(file_name); buf @@ -1231,13 +1566,37 @@ impl Path { /// Creates an owned `PathBuf` like `self` but with the given extension. /// /// See `PathBuf::set_extension` for more details. - pub fn with_extension(&self, extension: &S) -> PathBuf where S: AsOsStr { + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp/foo.rs"); + /// + /// let new_path = path.with_extension("foo.txt"); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_extension>(&self, extension: S) -> PathBuf { let mut buf = self.to_path_buf(); buf.set_extension(extension); buf } /// Produce an iterator over the components of the path. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp/foo.rs"); + /// + /// for component in path.components() { + /// println!("{:?}", component); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn components(&self) -> Components { let prefix = parse_prefix(self.as_os_str()); Components { @@ -1245,29 +1604,62 @@ impl Path { prefix: prefix, has_physical_root: has_physical_root(self.as_u8_slice(), prefix), front: State::Prefix, - back: if has_suffix(self.as_u8_slice(), prefix) { State::Suffix } - else { State::Body }, + back: State::Body, } } /// Produce an iterator over the path's components viewed as `OsStr` slices. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp/foo.rs"); + /// + /// for component in path.iter() { + /// println!("{:?}", component); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter { Iter { inner: self.components() } } /// Returns an object that implements `Display` for safely printing paths /// that may contain non-Unicode data. + /// + /// # Examples + /// + /// ``` + /// use std::path::Path; + /// + /// let path = Path::new("/tmp/foo.rs"); + /// + /// println!("{}", path.display()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] pub fn display(&self) -> Display { Display { path: self } } } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for Path { + fn as_ref(&self) -> &OsStr { + &self.inner + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[deprecated(since = "1.0.0", reason = "trait is deprecated")] impl AsOsStr for Path { fn as_os_str(&self) -> &OsStr { &self.inner } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Path { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.inner.fmt(formatter) @@ -1275,36 +1667,43 @@ impl fmt::Debug for Path { } /// Helper struct for safely printing paths with `format!()` and `{}` +#[stable(feature = "rust1", since = "1.0.0")] pub struct Display<'a> { path: &'a Path } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> fmt::Debug for Display<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.path.to_string_lossy(), f) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> fmt::Display for Display<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.path.to_string_lossy(), f) } } +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::PartialEq for Path { fn eq(&self, other: &Path) -> bool { iter::order::eq(self.components(), other.components()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::Eq for Path {} +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::PartialOrd for Path { fn partial_cmp(&self, other: &Path) -> Option { self.components().partial_cmp(&other.components()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl cmp::Ord for Path { fn cmp(&self, other: &Path) -> cmp::Ordering { self.components().cmp(&other.components()) @@ -1312,19 +1711,54 @@ impl cmp::Ord for Path { } /// Freely convertible to a `Path`. +#[unstable(feature = "std_misc")] +#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef instead")] pub trait AsPath { /// Convert to a `Path`. + #[unstable(feature = "std_misc")] fn as_path(&self) -> &Path; } +#[unstable(feature = "std_misc")] +#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef instead")] +#[allow(deprecated)] impl AsPath for T { fn as_path(&self) -> &Path { Path::new(self.as_os_str()) } } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for Path { + fn as_ref(&self) -> &Path { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for OsStr { + fn as_ref(&self) -> &Path { Path::new(self) } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for OsString { + fn as_ref(&self) -> &Path { Path::new(self) } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for str { + fn as_ref(&self) -> &Path { Path::new(self) } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for String { + fn as_ref(&self) -> &Path { Path::new(self) } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef for PathBuf { + fn as_ref(&self) -> &Path { self } +} + #[cfg(test)] mod tests { use super::*; - use ffi::OsStr; use core::prelude::*; use string::{ToString, String}; use vec::Vec; @@ -1412,6 +1846,26 @@ mod tests { ); ); + #[test] + fn into_cow() { + use borrow::{Cow, IntoCow}; + + let static_path = Path::new("/home/foo"); + let static_cow_path: Cow<'static, Path> = static_path.into_cow(); + let pathbuf = PathBuf::from("/home/foo"); + + { + let path: &Path = &pathbuf; + let borrowed_cow_path: Cow = path.into_cow(); + + assert_eq!(static_cow_path, borrowed_cow_path); + } + + let owned_cow_path: Cow<'static, Path> = pathbuf.into_cow(); + + assert_eq!(static_cow_path, owned_cow_path); + } + #[test] #[cfg(unix)] pub fn test_decompositions_unix() { @@ -1429,14 +1883,14 @@ mod tests { iter: ["foo"], has_root: false, is_absolute: false, - parent: None, + parent: Some(""), file_name: Some("foo"), file_stem: Some("foo"), extension: None ); t!("/", - iter: ["/", "."], + iter: ["/"], has_root: true, is_absolute: true, parent: None, @@ -1456,22 +1910,22 @@ mod tests { ); t!("foo/", - iter: ["foo", "."], + iter: ["foo"], has_root: false, is_absolute: false, - parent: Some("foo"), - file_name: None, - file_stem: None, + parent: Some(""), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); t!("/foo/", - iter: ["/", "foo", "."], + iter: ["/", "foo"], has_root: true, is_absolute: true, - parent: Some("/foo"), - file_name: None, - file_stem: None, + parent: Some("/"), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); @@ -1496,12 +1950,12 @@ mod tests { ); t!("///foo///", - iter: ["/", "foo", "."], + iter: ["/", "foo"], has_root: true, is_absolute: true, - parent: Some("///foo"), - file_name: None, - file_stem: None, + parent: Some("/"), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); @@ -1516,20 +1970,10 @@ mod tests { ); t!("./.", - iter: [".", "."], - has_root: false, - is_absolute: false, - parent: Some("."), - file_name: None, - file_stem: None, - extension: None - ); - - t!("./.", - iter: [".", "."], + iter: ["."], has_root: false, is_absolute: false, - parent: Some("."), + parent: Some(""), file_name: None, file_stem: None, extension: None @@ -1546,22 +1990,22 @@ mod tests { ); t!("../", - iter: ["..", "."], + iter: [".."], has_root: false, is_absolute: false, - parent: Some(".."), + parent: Some(""), file_name: None, file_stem: None, extension: None ); t!("foo/.", - iter: ["foo", "."], + iter: ["foo"], has_root: false, is_absolute: false, - parent: Some("foo"), - file_name: None, - file_stem: None, + parent: Some(""), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); @@ -1576,30 +2020,30 @@ mod tests { ); t!("foo/./", - iter: ["foo", ".", "."], + iter: ["foo"], has_root: false, is_absolute: false, - parent: Some("foo/."), - file_name: None, - file_stem: None, + parent: Some(""), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); t!("foo/./bar", - iter: ["foo", ".", "bar"], + iter: ["foo", "bar"], has_root: false, is_absolute: false, - parent: Some("foo/."), + parent: Some("foo"), file_name: Some("bar"), file_stem: Some("bar"), extension: None ); t!("foo/../", - iter: ["foo", "..", "."], + iter: ["foo", ".."], has_root: false, is_absolute: false, - parent: Some("foo/.."), + parent: Some("foo"), file_name: None, file_stem: None, extension: None @@ -1629,17 +2073,17 @@ mod tests { iter: ["."], has_root: false, is_absolute: false, - parent: None, + parent: Some(""), file_name: None, file_stem: None, extension: None ); t!("./", - iter: [".", "."], + iter: ["."], has_root: false, is_absolute: false, - parent: Some("."), + parent: Some(""), file_name: None, file_stem: None, extension: None @@ -1666,10 +2110,10 @@ mod tests { ); t!("a/./b", - iter: ["a", ".", "b"], + iter: ["a", "b"], has_root: false, is_absolute: false, - parent: Some("a/."), + parent: Some("a"), file_name: Some("b"), file_stem: Some("b"), extension: None @@ -1684,6 +2128,16 @@ mod tests { file_stem: Some("c"), extension: None ); + + t!(".foo", + iter: [".foo"], + has_root: false, + is_absolute: false, + parent: Some(""), + file_name: Some(".foo"), + file_stem: Some(".foo"), + extension: None + ); } #[test] @@ -1703,14 +2157,14 @@ mod tests { iter: ["foo"], has_root: false, is_absolute: false, - parent: None, + parent: Some(""), file_name: Some("foo"), file_stem: Some("foo"), extension: None ); t!("/", - iter: ["\\", "."], + iter: ["\\"], has_root: true, is_absolute: false, parent: None, @@ -1720,7 +2174,7 @@ mod tests { ); t!("\\", - iter: ["\\", "."], + iter: ["\\"], has_root: true, is_absolute: false, parent: None, @@ -1730,7 +2184,7 @@ mod tests { ); t!("c:", - iter: ["c:", "."], + iter: ["c:"], has_root: false, is_absolute: false, parent: None, @@ -1740,17 +2194,7 @@ mod tests { ); t!("c:\\", - iter: ["c:", "\\", "."], - has_root: true, - is_absolute: true, - parent: None, - file_name: None, - file_stem: None, - extension: None - ); - - t!("c:\\", - iter: ["c:", "\\", "."], + iter: ["c:", "\\"], has_root: true, is_absolute: true, parent: None, @@ -1760,7 +2204,7 @@ mod tests { ); t!("c:/", - iter: ["c:", "\\", "."], + iter: ["c:", "\\"], has_root: true, is_absolute: true, parent: None, @@ -1780,22 +2224,22 @@ mod tests { ); t!("foo/", - iter: ["foo", "."], + iter: ["foo"], has_root: false, is_absolute: false, - parent: Some("foo"), - file_name: None, - file_stem: None, + parent: Some(""), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); t!("/foo/", - iter: ["\\", "foo", "."], + iter: ["\\", "foo"], has_root: true, is_absolute: false, - parent: Some("/foo"), - file_name: None, - file_stem: None, + parent: Some("/"), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); @@ -1820,12 +2264,12 @@ mod tests { ); t!("///foo///", - iter: ["\\", "foo", "."], + iter: ["\\", "foo"], has_root: true, is_absolute: false, - parent: Some("///foo"), - file_name: None, - file_stem: None, + parent: Some("/"), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); @@ -1840,20 +2284,10 @@ mod tests { ); t!("./.", - iter: [".", "."], - has_root: false, - is_absolute: false, - parent: Some("."), - file_name: None, - file_stem: None, - extension: None - ); - - t!("./.", - iter: [".", "."], + iter: ["."], has_root: false, is_absolute: false, - parent: Some("."), + parent: Some(""), file_name: None, file_stem: None, extension: None @@ -1870,22 +2304,22 @@ mod tests { ); t!("../", - iter: ["..", "."], + iter: [".."], has_root: false, is_absolute: false, - parent: Some(".."), + parent: Some(""), file_name: None, file_stem: None, extension: None ); t!("foo/.", - iter: ["foo", "."], + iter: ["foo"], has_root: false, is_absolute: false, - parent: Some("foo"), - file_name: None, - file_stem: None, + parent: Some(""), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); @@ -1900,30 +2334,30 @@ mod tests { ); t!("foo/./", - iter: ["foo", ".", "."], + iter: ["foo"], has_root: false, is_absolute: false, - parent: Some("foo/."), - file_name: None, - file_stem: None, + parent: Some(""), + file_name: Some("foo"), + file_stem: Some("foo"), extension: None ); t!("foo/./bar", - iter: ["foo", ".", "bar"], + iter: ["foo", "bar"], has_root: false, is_absolute: false, - parent: Some("foo/."), + parent: Some("foo"), file_name: Some("bar"), file_stem: Some("bar"), extension: None ); t!("foo/../", - iter: ["foo", "..", "."], + iter: ["foo", ".."], has_root: false, is_absolute: false, - parent: Some("foo/.."), + parent: Some("foo"), file_name: None, file_stem: None, extension: None @@ -1953,17 +2387,17 @@ mod tests { iter: ["."], has_root: false, is_absolute: false, - parent: None, + parent: Some(""), file_name: None, file_stem: None, extension: None ); t!("./", - iter: [".", "."], + iter: ["."], has_root: false, is_absolute: false, - parent: Some("."), + parent: Some(""), file_name: None, file_stem: None, extension: None @@ -1990,10 +2424,10 @@ mod tests { ); t!("a/./b", - iter: ["a", ".", "b"], + iter: ["a", "b"], has_root: false, is_absolute: false, - parent: Some("a/."), + parent: Some("a"), file_name: Some("b"), file_stem: Some("b"), extension: None @@ -2049,7 +2483,7 @@ mod tests { ); t!("\\\\server\\share", - iter: ["\\\\server\\share", "\\", "."], + iter: ["\\\\server\\share", "\\"], has_root: true, is_absolute: true, parent: None, @@ -2140,7 +2574,7 @@ mod tests { t!("\\\\?\\C:\\", - iter: ["\\\\?\\C:", "\\", ""], + iter: ["\\\\?\\C:", "\\"], has_root: true, is_absolute: true, parent: None, @@ -2195,7 +2629,7 @@ mod tests { t!("\\\\.\\foo", - iter: ["\\\\.\\foo", "\\", "."], + iter: ["\\\\.\\foo", "\\"], has_root: true, is_absolute: true, parent: None, @@ -2206,7 +2640,7 @@ mod tests { t!("\\\\.\\foo/bar", - iter: ["\\\\.\\foo/bar", "\\", "."], + iter: ["\\\\.\\foo/bar", "\\"], has_root: true, is_absolute: true, parent: None, @@ -2228,7 +2662,7 @@ mod tests { t!("\\\\.\\", - iter: ["\\\\.\\", "\\", "."], + iter: ["\\\\.\\", "\\"], has_root: true, is_absolute: true, parent: None, @@ -2238,12 +2672,12 @@ mod tests { ); t!("\\\\?\\a\\b\\", - iter: ["\\\\?\\a", "\\", "b", ""], + iter: ["\\\\?\\a", "\\", "b"], has_root: true, is_absolute: true, - parent: Some("\\\\?\\a\\b"), - file_name: None, - file_stem: None, + parent: Some("\\\\?\\a\\"), + file_name: Some("b"), + file_stem: Some("b"), extension: None ); } @@ -2300,7 +2734,7 @@ mod tests { pub fn test_push() { macro_rules! tp( ($path:expr, $push:expr, $expected:expr) => ( { - let mut actual = PathBuf::new($path); + let mut actual = PathBuf::from($path); actual.push($push); assert!(actual.to_str() == Some($expected), "pushing {:?} onto {:?}: Expected {:?}, got {:?}", @@ -2388,7 +2822,7 @@ mod tests { pub fn test_pop() { macro_rules! tp( ($path:expr, $expected:expr, $output:expr) => ( { - let mut actual = PathBuf::new($path); + let mut actual = PathBuf::from($path); let output = actual.pop(); assert!(actual.to_str() == Some($expected) && output == $output, "popping from {:?}: Expected {:?}/{:?}, got {:?}/{:?}", @@ -2399,12 +2833,12 @@ mod tests { tp!("", "", false); tp!("/", "/", false); - tp!("foo", "foo", false); - tp!(".", ".", false); + tp!("foo", "", true); + tp!(".", "", true); tp!("/foo", "/", true); tp!("/foo/bar", "/foo", true); tp!("foo/bar", "foo", true); - tp!("foo/.", "foo", true); + tp!("foo/.", "", true); tp!("foo//bar", "foo", true); if cfg!(windows) { @@ -2434,7 +2868,7 @@ mod tests { tp!("\\\\.\\a\\b", "\\\\.\\a\\", true); tp!("\\\\.\\a", "\\\\.\\a", false); - tp!("\\\\?\\a\\b\\", "\\\\?\\a\\b", true); + tp!("\\\\?\\a\\b\\", "\\\\?\\a\\", true); } } @@ -2442,7 +2876,7 @@ mod tests { pub fn test_set_file_name() { macro_rules! tfn( ($path:expr, $file:expr, $expected:expr) => ( { - let mut p = PathBuf::new($path); + let mut p = PathBuf::from($path); p.set_file_name($file); assert!(p.to_str() == Some($expected), "setting file name of {:?} to {:?}: Expected {:?}, got {:?}", @@ -2457,15 +2891,15 @@ mod tests { tfn!("", "foo", "foo"); if cfg!(unix) { tfn!(".", "foo", "./foo"); - tfn!("foo/", "bar", "foo/bar"); - tfn!("foo/.", "bar", "foo/./bar"); + tfn!("foo/", "bar", "bar"); + tfn!("foo/.", "bar", "bar"); tfn!("..", "foo", "../foo"); tfn!("foo/..", "bar", "foo/../bar"); tfn!("/", "foo", "/foo"); } else { tfn!(".", "foo", r".\foo"); - tfn!(r"foo\", "bar", r"foo\bar"); - tfn!(r"foo\.", "bar", r"foo\.\bar"); + tfn!(r"foo\", "bar", r"bar"); + tfn!(r"foo\.", "bar", r"bar"); tfn!("..", "foo", r"..\foo"); tfn!(r"foo\..", "bar", r"foo\..\bar"); tfn!(r"\", "foo", r"\foo"); @@ -2476,7 +2910,7 @@ mod tests { pub fn test_set_extension() { macro_rules! tfe( ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( { - let mut p = PathBuf::new($path); + let mut p = PathBuf::from($path); let output = p.set_extension($ext); assert!(p.to_str() == Some($expected) && output == $output, "setting extension of {:?} to {:?}: Expected {:?}/{:?}, got {:?}/{:?}", @@ -2493,8 +2927,8 @@ mod tests { tfe!("foo", "", "foo", true); tfe!("", "foo", "", false); tfe!(".", "foo", ".", false); - tfe!("foo/", "bar", "foo/", false); - tfe!("foo/.", "bar", "foo/.", false); + tfe!("foo/", "bar", "foo.bar", true); + tfe!("foo/.", "bar", "foo.bar", true); tfe!("..", "foo", "..", false); tfe!("foo/..", "bar", "foo/..", false); tfe!("/", "foo", "/", false); @@ -2560,10 +2994,10 @@ mod tests { ); tc!("foo/", "foo", - eq: false, + eq: true, starts_with: true, - ends_with: false, - relative_from: Some(".") + ends_with: true, + relative_from: Some("") ); tc!("foo/bar", "foo", @@ -2590,8 +3024,25 @@ mod tests { tc!("./foo/bar/", ".", eq: false, starts_with: true, - ends_with: true, - relative_from: Some("foo/bar/") + ends_with: false, + relative_from: Some("foo/bar") ); + + if cfg!(windows) { + tc!(r"C:\src\rust\cargo-test\test\Cargo.toml", + r"c:\src\rust\cargo-test\test", + eq: false, + starts_with: true, + ends_with: false, + relative_from: Some("Cargo.toml") + ); + + tc!(r"c:\foo", r"C:\foo", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + } } } diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index d2dc334512..84a4508676 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -23,41 +23,30 @@ #[doc(no_inline)] pub use mem::drop; // Reexported types and traits - #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use boxed::Box; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use char::CharExt; -#[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use clone::Clone; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; +#[unstable(feature = "convert")] +#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use iter::DoubleEndedIterator; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use iter::ExactSizeIterator; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend}; +#[doc(no_inline)] pub use iter::{Iterator, Extend}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use option::Option::{self, Some, None}; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; -#[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use result::Result::{self, Ok, Err}; #[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use slice::AsSlice; -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt}; -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] pub use str::{Str, StrExt}; +#[doc(no_inline)] pub use slice::SliceConcatExt; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use string::{String, ToString}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use vec::Vec; -// NB: remove when path reform lands -#[doc(no_inline)] pub use old_path::{Path, GenericPath}; -// NB: remove when I/O reform lands -#[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude}; -// NB: remove when range syntax lands -#[doc(no_inline)] pub use iter::range; +#[allow(deprecated)] pub use slice::AsSlice; +#[allow(deprecated)] pub use str::Str; diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 5baa095d35..52f5965db8 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -10,21 +10,21 @@ //! Working with processes. -#![unstable(feature = "process", reason = "recently added via RFC 579")] +#![stable(feature = "process", since = "1.0.0")] #![allow(non_upper_case_globals)] use prelude::v1::*; use io::prelude::*; -use ffi::AsOsStr; +use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; -use path::AsPath; use libc; +use path; use sync::mpsc::{channel, Receiver}; use sys::pipe2::{self, AnonPipe}; -use sys::process2::Process as ProcessImp; use sys::process2::Command as CommandImp; +use sys::process2::Process as ProcessImp; use sys::process2::ExitStatus as ExitStatusImp; use sys_common::{AsInner, AsInnerMut}; use thread; @@ -35,9 +35,9 @@ use thread; /// process is created via the `Command` struct, which configures the spawning /// process and can itself be constructed using a builder-style interface. /// -/// # Example +/// # Examples /// -/// ```should_fail +/// ```should_panic /// # #![feature(process)] /// /// use std::process::Command; @@ -48,6 +48,7 @@ use thread; /// let contents = output.stdout; /// assert!(output.status.success()); /// ``` +#[stable(feature = "process", since = "1.0.0")] pub struct Child { handle: ProcessImp, @@ -55,20 +56,25 @@ pub struct Child { status: Option, /// The handle for writing to the child's stdin, if it has been captured + #[stable(feature = "process", since = "1.0.0")] pub stdin: Option, /// The handle for reading from the child's stdout, if it has been captured + #[stable(feature = "process", since = "1.0.0")] pub stdout: Option, /// The handle for reading from the child's stderr, if it has been captured + #[stable(feature = "process", since = "1.0.0")] pub stderr: Option, } /// A handle to a child procesess's stdin +#[stable(feature = "process", since = "1.0.0")] pub struct ChildStdin { inner: AnonPipe } +#[stable(feature = "process", since = "1.0.0")] impl Write for ChildStdin { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) @@ -80,10 +86,12 @@ impl Write for ChildStdin { } /// A handle to a child procesess's stdout +#[stable(feature = "process", since = "1.0.0")] pub struct ChildStdout { inner: AnonPipe } +#[stable(feature = "process", since = "1.0.0")] impl Read for ChildStdout { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) @@ -91,10 +99,12 @@ impl Read for ChildStdout { } /// A handle to a child procesess's stderr +#[stable(feature = "process", since = "1.0.0")] pub struct ChildStderr { inner: AnonPipe } +#[stable(feature = "process", since = "1.0.0")] impl Read for ChildStderr { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) @@ -108,8 +118,6 @@ impl Read for ChildStderr { /// to be changed (for example, by adding arguments) prior to spawning: /// /// ``` -/// # #![feature(process)] -/// /// use std::process::Command; /// /// let output = Command::new("sh").arg("-c").arg("echo hello").output().unwrap_or_else(|e| { @@ -117,6 +125,7 @@ impl Read for ChildStderr { /// }); /// let hello = output.stdout; /// ``` +#[stable(feature = "process", since = "1.0.0")] pub struct Command { inner: CommandImp, @@ -137,9 +146,10 @@ impl Command { /// /// Builder methods are provided to change these defaults and /// otherwise configure the process. - pub fn new(program: &S) -> Command { + #[stable(feature = "process", since = "1.0.0")] + pub fn new>(program: S) -> Command { Command { - inner: CommandImp::new(program.as_os_str()), + inner: CommandImp::new(program.as_ref()), stdin: None, stdout: None, stderr: None, @@ -147,14 +157,16 @@ impl Command { } /// Add an argument to pass to the program. - pub fn arg(&mut self, arg: &S) -> &mut Command { - self.inner.arg(arg.as_os_str()); + #[stable(feature = "process", since = "1.0.0")] + pub fn arg>(&mut self, arg: S) -> &mut Command { + self.inner.arg(arg.as_ref()); self } /// Add multiple arguments to pass to the program. - pub fn args(&mut self, args: &[S]) -> &mut Command { - self.inner.args(args.iter().map(AsOsStr::as_os_str)); + #[stable(feature = "process", since = "1.0.0")] + pub fn args>(&mut self, args: &[S]) -> &mut Command { + self.inner.args(args.iter().map(AsRef::as_ref)); self } @@ -162,33 +174,38 @@ impl Command { /// /// Note that environment variable names are case-insensitive (but case-preserving) on Windows, /// and case-sensitive on all other platforms. - pub fn env(&mut self, key: &S, val: &T) -> &mut Command where - S: AsOsStr, T: AsOsStr + #[stable(feature = "process", since = "1.0.0")] + pub fn env(&mut self, key: K, val: V) -> &mut Command + where K: AsRef, V: AsRef { - self.inner.env(key.as_os_str(), val.as_os_str()); + self.inner.env(key.as_ref(), val.as_ref()); self } /// Removes an environment variable mapping. - pub fn env_remove(&mut self, key: &S) -> &mut Command { - self.inner.env_remove(key.as_os_str()); + #[stable(feature = "process", since = "1.0.0")] + pub fn env_remove>(&mut self, key: K) -> &mut Command { + self.inner.env_remove(key.as_ref()); self } /// Clears the entire environment map for the child process. + #[stable(feature = "process", since = "1.0.0")] pub fn env_clear(&mut self) -> &mut Command { self.inner.env_clear(); self } /// Set the working directory for the child process. - pub fn current_dir(&mut self, dir: &P) -> &mut Command { - self.inner.cwd(dir.as_path().as_os_str()); + #[stable(feature = "process", since = "1.0.0")] + pub fn current_dir>(&mut self, dir: P) -> &mut Command { + self.inner.cwd(dir.as_ref().as_ref()); self } /// Configuration for the child process's stdin handle (file descriptor 0). /// Defaults to `CreatePipe(true, false)` so the input can be written to. + #[stable(feature = "process", since = "1.0.0")] pub fn stdin(&mut self, cfg: Stdio) -> &mut Command { self.stdin = Some(cfg.0); self @@ -196,6 +213,7 @@ impl Command { /// Configuration for the child process's stdout handle (file descriptor 1). /// Defaults to `CreatePipe(false, true)` so the output can be collected. + #[stable(feature = "process", since = "1.0.0")] pub fn stdout(&mut self, cfg: Stdio) -> &mut Command { self.stdout = Some(cfg.0); self @@ -203,6 +221,7 @@ impl Command { /// Configuration for the child process's stderr handle (file descriptor 2). /// Defaults to `CreatePipe(false, true)` so the output can be collected. + #[stable(feature = "process", since = "1.0.0")] pub fn stderr(&mut self, cfg: Stdio) -> &mut Command { self.stderr = Some(cfg.0); self @@ -234,6 +253,7 @@ impl Command { /// Executes the command as a child process, returning a handle to it. /// /// By default, stdin, stdout and stderr are inherited by the parent. + #[stable(feature = "process", since = "1.0.0")] pub fn spawn(&mut self) -> io::Result { self.spawn_inner(StdioImp::Inherit) } @@ -244,7 +264,7 @@ impl Command { /// By default, stdin, stdout and stderr are captured (and used to /// provide the resulting output). /// - /// # Example + /// # Examples /// /// ``` /// # #![feature(process)] @@ -255,11 +275,12 @@ impl Command { /// }); /// /// println!("status: {}", output.status); - /// println!("stdout: {}", String::from_utf8_lossy(output.stdout.as_slice())); - /// println!("stderr: {}", String::from_utf8_lossy(output.stderr.as_slice())); + /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); /// ``` + #[stable(feature = "process", since = "1.0.0")] pub fn output(&mut self) -> io::Result { - self.spawn_inner(StdioImp::Capture).and_then(|p| p.wait_with_output()) + self.spawn_inner(StdioImp::Piped).and_then(|p| p.wait_with_output()) } /// Executes a command as a child process, waiting for it to finish and @@ -267,7 +288,7 @@ impl Command { /// /// By default, stdin, stdout and stderr are inherited by the parent. /// - /// # Example + /// # Examples /// /// ``` /// # #![feature(process)] @@ -279,6 +300,7 @@ impl Command { /// /// println!("process exited with: {}", status); /// ``` + #[stable(feature = "process", since = "1.0.0")] pub fn status(&mut self) -> io::Result { self.spawn().and_then(|mut p| p.wait()) } @@ -317,7 +339,7 @@ fn setup_io(io: &StdioImp, fd: libc::c_int, readable: bool) Inherit => { (Some(AnonPipe::from_fd(fd)), None) } - Capture => { + Piped => { let (reader, writer) = try!(unsafe { pipe2::anon_pipe() }); if readable { (Some(reader), Some(writer)) @@ -330,45 +352,55 @@ fn setup_io(io: &StdioImp, fd: libc::c_int, readable: bool) /// The output of a finished process. #[derive(PartialEq, Eq, Clone)] +#[stable(feature = "process", since = "1.0.0")] pub struct Output { /// The status (exit code) of the process. + #[stable(feature = "process", since = "1.0.0")] pub status: ExitStatus, /// The data that the process wrote to stdout. + #[stable(feature = "process", since = "1.0.0")] pub stdout: Vec, /// The data that the process wrote to stderr. + #[stable(feature = "process", since = "1.0.0")] pub stderr: Vec, } /// Describes what to do with a standard io stream for a child process. +#[stable(feature = "process", since = "1.0.0")] pub struct Stdio(StdioImp); // The internal enum for stdio setup; see below for descriptions. #[derive(Clone)] enum StdioImp { - Capture, + Piped, Inherit, Null, } impl Stdio { /// A new pipe should be arranged to connect the parent and child processes. - pub fn capture() -> Stdio { Stdio(StdioImp::Capture) } + #[stable(feature = "process", since = "1.0.0")] + pub fn piped() -> Stdio { Stdio(StdioImp::Piped) } /// The child inherits from the corresponding parent descriptor. - pub fn inherit() -> Stdio { Stdio(StdioImp::Capture) } + #[stable(feature = "process", since = "1.0.0")] + pub fn inherit() -> Stdio { Stdio(StdioImp::Inherit) } /// This stream will be ignored. This is the equivalent of attaching the /// stream to `/dev/null` - pub fn null() -> Stdio { Stdio(StdioImp::Capture) } + #[stable(feature = "process", since = "1.0.0")] + pub fn null() -> Stdio { Stdio(StdioImp::Null) } } /// Describes the result of a process after it has terminated. #[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[stable(feature = "process", since = "1.0.0")] pub struct ExitStatus(ExitStatusImp); impl ExitStatus { /// Was termination successful? Signal termination not considered a success, /// and success is defined as a zero exit status. + #[stable(feature = "process", since = "1.0.0")] pub fn success(&self) -> bool { self.0.success() } @@ -378,6 +410,7 @@ impl ExitStatus { /// On Unix, this will return `None` if the process was terminated /// by a signal; `std::os::unix` provides an extension trait for /// extracting the signal and other details from the `ExitStatus`. + #[stable(feature = "process", since = "1.0.0")] pub fn code(&self) -> Option { self.0.code() } @@ -387,6 +420,7 @@ impl AsInner for ExitStatus { fn as_inner(&self) -> &ExitStatusImp { &self.0 } } +#[stable(feature = "process", since = "1.0.0")] impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) @@ -396,6 +430,7 @@ impl fmt::Display for ExitStatus { impl Child { /// Forces the child to exit. This is equivalent to sending a /// SIGKILL on unix platforms. + #[stable(feature = "process", since = "1.0.0")] pub fn kill(&mut self) -> io::Result<()> { #[cfg(unix)] fn collect_status(p: &mut Child) { // On Linux (and possibly other unices), a process that has exited will @@ -421,7 +456,6 @@ impl Child { return Err(Error::new( ErrorKind::InvalidInput, "invalid argument: can't kill an exited process", - None )) } @@ -436,6 +470,7 @@ impl Child { /// before waiting. This helps avoid deadlock: it ensures that the /// child does not block waiting for input from the parent, while /// the parent waits for the child to exit. + #[stable(feature = "process", since = "1.0.0")] pub fn wait(&mut self) -> io::Result { drop(self.stdin.take()); match self.status { @@ -456,6 +491,7 @@ impl Child { /// before waiting. This helps avoid deadlock: it ensures that the /// child does not block waiting for input from the parent, while /// the parent waits for the child to exit. + #[stable(feature = "process", since = "1.0.0")] pub fn wait_with_output(mut self) -> io::Result { drop(self.stdin.take()); fn read(stream: Option) -> Receiver>> { @@ -485,22 +521,33 @@ impl Child { } } +/// Terminates the current process with the specified exit code. +/// +/// This function will never return and will immediately terminate the current +/// process. The exit code is passed through to the underlying OS and will be +/// available for consumption by another process. +/// +/// Note that because this function never returns, and that it terminates the +/// process, no destructors on the current stack or any other thread's stack +/// will be run. If a clean shutdown is needed it is recommended to only call +/// this function at a known point where there are no more destructors left +/// to run. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn exit(code: i32) -> ! { + ::sys::os::exit(code) +} + #[cfg(test)] mod tests { - use io::ErrorKind; + use prelude::v1::*; use io::prelude::*; - use prelude::v1::{Ok, Err, range, drop, Some, None, Vec}; - use prelude::v1::{String, Clone}; - use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath}; - use path::Path; - use old_path; + + use io::ErrorKind; + use old_path::{self, GenericPath}; use old_io::fs::PathExtensions; use rt::running_on_valgrind; use str; - use super::{Child, Command, Output, ExitStatus, Stdio}; - use sync::mpsc::channel; - use thread; - use time::Duration; + use super::{Command, Output, Stdio}; // FIXME(#10380) these tests should not all be ignored on android. @@ -529,13 +576,13 @@ mod tests { assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().unwrap().code() == Some(1)); - drop(p.wait().clone()); + drop(p.wait()); } #[cfg(all(unix, not(target_os="android")))] #[test] fn signal_reported_right() { - use os::unix::ExitStatusExt; + use os::unix::process::ExitStatusExt; let p = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn(); assert!(p.is_ok()); @@ -561,7 +608,7 @@ mod tests { #[test] fn stdout_works() { let mut cmd = Command::new("echo"); - cmd.arg("foobar").stdout(Stdio::capture()); + cmd.arg("foobar").stdout(Stdio::piped()); assert_eq!(run_output(cmd), "foobar\n"); } @@ -571,7 +618,7 @@ mod tests { let mut cmd = Command::new("/bin/sh"); cmd.arg("-c").arg("pwd") .current_dir("/") - .stdout(Stdio::capture()); + .stdout(Stdio::piped()); assert_eq!(run_output(cmd), "/\n"); } @@ -580,8 +627,8 @@ mod tests { fn stdin_works() { let mut p = Command::new("/bin/sh") .arg("-c").arg("read line; echo $line") - .stdin(Stdio::capture()) - .stdout(Stdio::capture()) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) .spawn().unwrap(); p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap(); drop(p.stdin.take()); @@ -595,7 +642,7 @@ mod tests { #[cfg(all(unix, not(target_os="android")))] #[test] fn uid_works() { - use os::unix::*; + use os::unix::prelude::*; use libc; let mut p = Command::new("/bin/sh") .arg("-c").arg("true") @@ -608,7 +655,7 @@ mod tests { #[cfg(all(unix, not(target_os="android")))] #[test] fn uid_to_root_fails() { - use os::unix::*; + use os::unix::prelude::*; use libc; // if we're already root, this isn't a valid test. Most of the bots run @@ -630,7 +677,7 @@ mod tests { #[test] fn test_process_output_fail_to_start() { match Command::new("/no-binary-by-this-name-should-exist").output() { - Err(e) => assert_eq!(e.kind(), ErrorKind::FileNotFound), + Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound), Ok(..) => panic!() } } @@ -640,7 +687,7 @@ mod tests { fn test_process_output_output() { let Output {status, stdout, stderr} = Command::new("echo").arg("hello").output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -679,10 +726,10 @@ mod tests { #[cfg(not(target_os="android"))] #[test] fn test_wait_with_output_once() { - let prog = Command::new("echo").arg("hello").stdout(Stdio::capture()) + let prog = Command::new("echo").arg("hello").stdout(Stdio::piped()) .spawn().unwrap(); let Output {status, stdout, stderr} = prog.wait_with_output().unwrap(); - let output_str = str::from_utf8(stdout.as_slice()).unwrap(); + let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); assert_eq!(output_str.trim().to_string(), "hello"); @@ -710,13 +757,15 @@ mod tests { cmd } + #[cfg(not(target_arch = "aarch64"))] #[test] fn test_keep_current_working_dir() { use os; let prog = pwd_cmd().spawn().unwrap(); let output = String::from_utf8(prog.wait_with_output().unwrap().stdout).unwrap(); - let parent_dir = os::getcwd().unwrap(); + let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string(); + let parent_dir = old_path::Path::new(parent_dir); let child_dir = old_path::Path::new(output.trim()); let parent_stat = parent_dir.stat().unwrap(); @@ -731,8 +780,9 @@ mod tests { use os; // test changing to the parent of os::getcwd() because we know // the path exists (and os::getcwd() is not expected to be root) - let parent_dir = os::getcwd().unwrap().dir_path(); - let result = pwd_cmd().current_dir(&parent_dir).output().unwrap(); + let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string(); + let parent_dir = old_path::Path::new(parent_dir).dir_path(); + let result = pwd_cmd().current_dir(parent_dir.as_str().unwrap()).output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); let child_dir = old_path::Path::new(output.trim()); @@ -765,17 +815,16 @@ mod tests { #[cfg(not(target_os="android"))] #[test] fn test_inherit_env() { - use os; + use std::env; if running_on_valgrind() { return; } let result = env_cmd().output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + for (ref k, ref v) in env::vars() { // don't check windows magical empty-named variables assert!(k.is_empty() || - output.contains(format!("{}={}", *k, *v).as_slice()), + output.contains(&format!("{}={}", *k, *v)), "output doesn't contain `{}={}`\n{}", k, v, output); } @@ -783,22 +832,21 @@ mod tests { #[cfg(target_os="android")] #[test] fn test_inherit_env() { - use os; + use std::env; if running_on_valgrind() { return; } let mut result = env_cmd().output().unwrap(); let output = String::from_utf8(result.stdout).unwrap(); - let r = os::env(); - for &(ref k, ref v) in &r { + for (ref k, ref v) in env::vars() { // don't check android RANDOM variables if *k != "RANDOM".to_string() { - assert!(output.contains(format!("{}={}", - *k, - *v).as_slice()) || - output.contains(format!("{}=\'{}\'", - *k, - *v).as_slice())); + assert!(output.contains(&format!("{}={}", + *k, + *v)) || + output.contains(&format!("{}=\'{}\'", + *k, + *v))); } } } @@ -817,7 +865,7 @@ mod tests { cmd.env("PATH", &p); } let result = cmd.output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); @@ -826,7 +874,7 @@ mod tests { #[test] fn test_add_to_env() { let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap(); - let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string(); + let output = String::from_utf8_lossy(&result.stdout).to_string(); assert!(output.contains("RUN_TEST_NEW_ENV=123"), "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output); diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 5c89144119..fad57323d3 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -58,16 +58,18 @@ //! # Examples //! //! ```rust +//! # #![feature(rand)] //! use std::rand; //! use std::rand::Rng; //! //! let mut rng = rand::thread_rng(); //! if rng.gen() { // random bool -//! println!("int: {}, uint: {}", rng.gen::(), rng.gen::()) +//! println!("isize: {}, usize: {}", rng.gen::(), rng.gen::()) //! } //! ``` //! //! ```rust +//! # #![feature(rand)] //! use std::rand; //! //! let tuple = rand::random::<(f64, char)>(); @@ -92,6 +94,7 @@ //! multiply this fraction by 4. //! //! ``` +//! # #![feature(rand)] //! use std::rand; //! use std::rand::distributions::{IndependentSample, Range}; //! @@ -134,6 +137,7 @@ //! [Monty Hall Problem]: http://en.wikipedia.org/wiki/Monty_Hall_problem //! //! ``` +//! # #![feature(rand)] //! use std::rand; //! use std::rand::Rng; //! use std::rand::distributions::{IndependentSample, Range}; @@ -144,7 +148,7 @@ //! } //! //! // Run a single simulation of the Monty Hall problem. -//! fn simulate(random_door: &Range, rng: &mut R) -> SimulationResult { +//! fn simulate(random_door: &Range, rng: &mut R) -> SimulationResult { //! let car = random_door.ind_sample(rng); //! //! // This is our initial choice @@ -164,18 +168,18 @@ //! //! // Returns the door the game host opens given our choice and knowledge of //! // where the car is. The game host will never open the door with the car. -//! fn game_host_open(car: uint, choice: uint, rng: &mut R) -> uint { +//! fn game_host_open(car: usize, choice: usize, rng: &mut R) -> usize { //! let choices = free_doors(&[car, choice]); //! rand::sample(rng, choices.into_iter(), 1)[0] //! } //! //! // Returns the door we switch to, given our current choice and //! // the open door. There will only be one valid door. -//! fn switch_door(choice: uint, open: uint) -> uint { +//! fn switch_door(choice: usize, open: usize) -> usize { //! free_doors(&[choice, open])[0] //! } //! -//! fn free_doors(blocked: &[uint]) -> Vec { +//! fn free_doors(blocked: &[usize]) -> Vec { //! (0..3).filter(|x| !blocked.contains(x)).collect() //! } //! @@ -227,7 +231,7 @@ use cell::RefCell; use clone::Clone; use old_io::IoResult; -use iter::{Iterator, IteratorExt}; +use iter::Iterator; use mem; use rc::Rc; use result::Result::{Ok, Err}; @@ -321,7 +325,7 @@ impl reseeding::Reseeder for ThreadRngReseeder { } } } -static THREAD_RNG_RESEED_THRESHOLD: usize = 32_768; +const THREAD_RNG_RESEED_THRESHOLD: usize = 32_768; type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. @@ -332,7 +336,7 @@ pub struct ThreadRng { /// Retrieve the lazily-initialized thread-local random number /// generator, seeded by the system. Intended to be used in method -/// chaining style, e.g. `thread_rng().gen::()`. +/// chaining style, e.g. `thread_rng().gen::()`. /// /// The RNG provided will reseed itself from the operating system /// after generating a certain amount of randomness. @@ -384,10 +388,11 @@ impl Rng for ThreadRng { /// # Examples /// /// ``` +/// # #![feature(rand)] /// use std::rand; /// -/// let x = rand::random(); -/// println!("{}", 2u8 * x); +/// let x: u8 = rand::random(); +/// println!("{}", 2 * x as u16); /// /// let y = rand::random::(); /// println!("{}", y); @@ -400,6 +405,7 @@ impl Rng for ThreadRng { /// Caching the thread local random number generator: /// /// ``` +/// # #![feature(rand)] /// use std::rand; /// use std::rand::Rng; /// @@ -424,9 +430,10 @@ pub fn random() -> T { /// Randomly sample up to `amount` elements from an iterator. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand)] /// use std::rand::{thread_rng, sample}; /// /// let mut rng = thread_rng(); @@ -468,7 +475,7 @@ mod test { let lengths = [0, 1, 2, 3, 4, 5, 6, 7, 80, 81, 82, 83, 84, 85, 86, 87]; for &n in &lengths { - let mut v = repeat(0u8).take(n).collect::>(); + let mut v = repeat(0).take(n).collect::>(); r.fill_bytes(&mut v); // use this to get nicer error messages. @@ -500,14 +507,14 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn test_gen_range_panic_int() { let mut r = thread_rng(); r.gen_range(5, -2); } #[test] - #[should_fail] + #[should_panic] fn test_gen_range_panic_uint() { let mut r = thread_rng(); r.gen_range(5, 2); @@ -549,14 +556,14 @@ mod test { let mut r = thread_rng(); assert_eq!(r.choose(&[1, 1, 1]).cloned(), Some(1)); - let v: &[int] = &[]; + let v: &[isize] = &[]; assert_eq!(r.choose(v), None); } #[test] fn test_shuffle() { let mut r = thread_rng(); - let empty: &mut [int] = &mut []; + let empty: &mut [isize] = &mut []; r.shuffle(empty); let mut one = [1]; r.shuffle(&mut one); @@ -576,7 +583,7 @@ mod test { #[test] fn test_thread_rng() { let mut r = thread_rng(); - r.gen::(); + r.gen::(); let mut v = [1, 1, 1]; r.shuffle(&mut v); let b: &[_] = &[1, 1, 1]; @@ -587,12 +594,12 @@ mod test { #[test] fn test_random() { // not sure how to test this aside from just getting some values - let _n : uint = random(); + let _n : usize = random(); let _f : f32 = random(); let _o : Option> = random(); let _many : ((), - (uint, - int, + (usize, + isize, Option<(u32, (bool,))>), (u8, i8, u16, i16, u32, i32, u64, i64), (f32, (f64, (f64,)))) = random(); @@ -604,7 +611,7 @@ mod test { let max_val = 100; let mut r = thread_rng(); - let vals = (min_val..max_val).collect::>(); + let vals = (min_val..max_val).collect::>(); let small_sample = sample(&mut r, vals.iter(), 5); let large_sample = sample(&mut r, vals.iter(), vals.len() + 5); @@ -618,7 +625,7 @@ mod test { #[test] fn test_std_rng_seeded() { - let s = thread_rng().gen_iter::().take(256).collect::>(); + let s = thread_rng().gen_iter::().take(256).collect::>(); let mut ra: StdRng = SeedableRng::from_seed(&*s); let mut rb: StdRng = SeedableRng::from_seed(&*s); assert!(order::equals(ra.gen_ascii_chars().take(100), @@ -627,7 +634,7 @@ mod test { #[test] fn test_std_rng_reseed() { - let s = thread_rng().gen_iter::().take(256).collect::>(); + let s = thread_rng().gen_iter::().take(256).collect::>(); let mut r: StdRng = SeedableRng::from_seed(&*s); let string1 = r.gen_ascii_chars().take(100).collect::(); @@ -638,28 +645,27 @@ mod test { } } -#[cfg(test)] -static RAND_BENCH_N: u64 = 100; - #[cfg(test)] mod bench { extern crate test; use prelude::v1::*; use self::test::Bencher; - use super::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N}; + use super::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng}; use super::{OsRng, weak_rng}; use mem::size_of; + const RAND_BENCH_N: u64 = 100; + #[bench] fn rand_xorshift(b: &mut Bencher) { let mut rng: XorShiftRng = OsRng::new().unwrap().gen(); b.iter(|| { for _ in 0..RAND_BENCH_N { - rng.gen::(); + rng.gen::(); } }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * RAND_BENCH_N; } #[bench] @@ -667,10 +673,10 @@ mod bench { let mut rng: IsaacRng = OsRng::new().unwrap().gen(); b.iter(|| { for _ in 0..RAND_BENCH_N { - rng.gen::(); + rng.gen::(); } }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * RAND_BENCH_N; } #[bench] @@ -678,10 +684,10 @@ mod bench { let mut rng: Isaac64Rng = OsRng::new().unwrap().gen(); b.iter(|| { for _ in 0..RAND_BENCH_N { - rng.gen::(); + rng.gen::(); } }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * RAND_BENCH_N; } #[bench] @@ -689,16 +695,16 @@ mod bench { let mut rng = StdRng::new().unwrap(); b.iter(|| { for _ in 0..RAND_BENCH_N { - rng.gen::(); + rng.gen::(); } }); - b.bytes = size_of::() as u64 * RAND_BENCH_N; + b.bytes = size_of::() as u64 * RAND_BENCH_N; } #[bench] fn rand_shuffle_100(b: &mut Bencher) { let mut rng = weak_rng(); - let x : &mut[uint] = &mut [1; 100]; + let x : &mut[usize] = &mut [1; 100]; b.iter(|| { rng.shuffle(x); }) diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 0e2766f388..38c57eec68 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -15,18 +15,16 @@ pub use self::imp::OsRng; #[cfg(all(unix, not(target_os = "ios")))] mod imp { - extern crate libc; - + use prelude::v1::*; use self::OsRngInner::*; + use libc; + use mem; use old_io::{IoResult, File}; use old_path::Path; use rand::Rng; use rand::reader::ReaderRng; - use result::Result::Ok; - use slice::SliceExt; - use mem; - use os::errno; + use sys::os::errno; #[cfg(all(target_os = "linux", any(target_arch = "x86_64", @@ -80,13 +78,13 @@ mod imp { } fn getrandom_next_u32() -> u32 { - let mut buf: [u8; 4] = [0u8; 4]; + let mut buf: [u8; 4] = [0; 4]; getrandom_fill_bytes(&mut buf); unsafe { mem::transmute::<[u8; 4], u32>(buf) } } fn getrandom_next_u64() -> u64 { - let mut buf: [u8; 8] = [0u8; 8]; + let mut buf: [u8; 8] = [0; 8]; getrandom_fill_bytes(&mut buf); unsafe { mem::transmute::<[u8; 8], u64>(buf) } } @@ -185,16 +183,13 @@ mod imp { #[cfg(target_os = "ios")] mod imp { - extern crate libc; + use prelude::v1::*; - use old_io::{IoResult}; - use marker::Sync; + use io; + use old_io::IoResult; use mem; - use os; use rand::Rng; - use result::Result::{Ok}; - use self::libc::{c_int, size_t}; - use slice::SliceExt; + use libc::{c_int, size_t}; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -214,10 +209,8 @@ mod imp { #[repr(C)] struct SecRandom; - unsafe impl Sync for *const SecRandom {} - #[allow(non_upper_case_globals)] - static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom; + const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom; #[link(name = "Security", kind = "framework")] extern "C" { @@ -234,12 +227,12 @@ mod imp { impl Rng for OsRng { fn next_u32(&mut self) -> u32 { - let mut v = [0u8; 4]; + let mut v = [0; 4]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } fn next_u64(&mut self) -> u64 { - let mut v = [0u8; 8]; + let mut v = [0; 8]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } @@ -248,7 +241,7 @@ mod imp { SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr()) }; if ret == -1 { - panic!("couldn't generate random bytes: {}", os::last_os_error()); + panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); } } } @@ -256,17 +249,14 @@ mod imp { #[cfg(windows)] mod imp { - extern crate libc; + use prelude::v1::*; - use old_io::{IoResult, IoError}; + use io; use mem; - use ops::Drop; - use os; + use old_io::{IoResult, IoError}; use rand::Rng; - use result::Result::{Ok, Err}; - use self::libc::{DWORD, BYTE, LPCSTR, BOOL}; - use self::libc::types::os::arch::extra::{LONG_PTR}; - use slice::SliceExt; + use libc::types::os::arch::extra::{LONG_PTR}; + use libc::{DWORD, BYTE, LPCSTR, BOOL}; type HCRYPTPROV = LONG_PTR; @@ -284,9 +274,9 @@ mod imp { hcryptprov: HCRYPTPROV } - static PROV_RSA_FULL: DWORD = 1; - static CRYPT_SILENT: DWORD = 64; - static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000; + const PROV_RSA_FULL: DWORD = 1; + const CRYPT_SILENT: DWORD = 64; + const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000; #[allow(non_snake_case)] extern "system" { @@ -321,12 +311,12 @@ mod imp { impl Rng for OsRng { fn next_u32(&mut self) -> u32 { - let mut v = [0u8; 4]; + let mut v = [0; 4]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } fn next_u64(&mut self) -> u64 { - let mut v = [0u8; 8]; + let mut v = [0; 8]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } @@ -336,7 +326,8 @@ mod imp { v.as_mut_ptr()) }; if ret == 0 { - panic!("couldn't generate random bytes: {}", os::last_os_error()); + panic!("couldn't generate random bytes: {}", + io::Error::last_os_error()); } } } @@ -347,7 +338,8 @@ mod imp { CryptReleaseContext(self.hcryptprov, 0) }; if ret == 0 { - panic!("couldn't release context: {}", os::last_os_error()); + panic!("couldn't release context: {}", + io::Error::last_os_error()); } } } @@ -369,7 +361,7 @@ mod test { r.next_u32(); r.next_u64(); - let mut v = [0u8; 1000]; + let mut v = [0; 1000]; r.fill_bytes(&mut v); } @@ -389,7 +381,7 @@ mod test { // as possible (XXX: is this a good test?) let mut r = OsRng::new().unwrap(); thread::yield_now(); - let mut v = [0u8; 1000]; + let mut v = [0; 1000]; for _ in 0..100 { r.next_u32(); diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index b71e8b4fd6..ece6867ddc 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -13,7 +13,6 @@ use old_io::Reader; use rand::Rng; use result::Result::{Ok, Err}; -use slice::SliceExt; /// An RNG that reads random bytes straight from a `Reader`. This will /// work best with an infinite reader, but this is not required. @@ -22,14 +21,15 @@ use slice::SliceExt; /// /// It will panic if it there is insufficient data to fulfill a request. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(rand, old_io)] /// use std::rand::{reader, Rng}; /// use std::old_io::MemReader; /// /// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8))); -/// println!("{:x}", rng.gen::()); +/// println!("{:x}", rng.gen::()); /// ``` pub struct ReaderRng { reader: R @@ -84,28 +84,28 @@ mod test { #[test] fn test_reader_rng_u64() { // transmute from the target to avoid endianness concerns. - let v = vec![0u8, 0, 0, 0, 0, 0, 0, 1, + let v = vec![0, 0, 0, 0, 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3]; let mut rng = ReaderRng::new(MemReader::new(v)); - assert_eq!(rng.next_u64(), 1_u64.to_be()); - assert_eq!(rng.next_u64(), 2_u64.to_be()); - assert_eq!(rng.next_u64(), 3_u64.to_be()); + assert_eq!(rng.next_u64(), 1.to_be()); + assert_eq!(rng.next_u64(), 2.to_be()); + assert_eq!(rng.next_u64(), 3.to_be()); } #[test] fn test_reader_rng_u32() { - let v = vec![0u8, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3]; + let v = vec![0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3]; let mut rng = ReaderRng::new(MemReader::new(v)); - assert_eq!(rng.next_u32(), 1_u32.to_be()); - assert_eq!(rng.next_u32(), 2_u32.to_be()); - assert_eq!(rng.next_u32(), 3_u32.to_be()); + assert_eq!(rng.next_u32(), 1.to_be()); + assert_eq!(rng.next_u32(), 2.to_be()); + assert_eq!(rng.next_u32(), 3.to_be()); } #[test] fn test_reader_rng_fill_bytes() { - let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let mut w = [0u8; 8]; + let v = [1, 2, 3, 4, 5, 6, 7, 8]; + let mut w = [0; 8]; let mut rng = ReaderRng::new(MemReader::new(v.to_vec())); rng.fill_bytes(&mut w); @@ -114,10 +114,10 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn test_reader_rng_insufficient_bytes() { let mut rng = ReaderRng::new(MemReader::new(vec!())); - let mut v = [0u8; 3]; + let mut v = [0; 3]; rng.fill_bytes(&mut v); } } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 61f5bd0f01..2329861f29 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -23,7 +23,7 @@ use core::prelude::*; use vec::Vec; /// One-time global initialization. -pub unsafe fn init(argc: int, argv: *const *const u8) { imp::init(argc, argv) } +pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) } /// One-time global cleanup. pub unsafe fn cleanup() { imp::cleanup() } @@ -43,6 +43,7 @@ pub fn clone() -> Option>> { imp::clone() } target_os = "android", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] mod imp { use prelude::v1::*; @@ -53,10 +54,10 @@ mod imp { use sync::{StaticMutex, MUTEX_INIT}; - static mut GLOBAL_ARGS_PTR: uint = 0; + static mut GLOBAL_ARGS_PTR: usize = 0; static LOCK: StaticMutex = MUTEX_INIT; - pub unsafe fn init(argc: int, argv: *const *const u8) { + pub unsafe fn init(argc: isize, argv: *const *const u8) { let args = load_argc_and_argv(argc, argv); put(args); } @@ -107,7 +108,6 @@ mod imp { #[cfg(test)] mod tests { use prelude::v1::*; - use finally::Finally; use super::*; @@ -126,14 +126,11 @@ mod imp { assert!(take() == Some(expected.clone())); assert!(take() == None); - (|| { - }).finally(|| { - // Restore the actual global state. - match saved_value { - Some(ref args) => put(args.clone()), - None => () - } - }) + // Restore the actual global state. + match saved_value { + Some(ref args) => put(args.clone()), + None => () + } } } } @@ -145,7 +142,7 @@ mod imp { use core::prelude::*; use vec::Vec; - pub unsafe fn init(_argc: int, _argv: *const *const u8) { + pub unsafe fn init(_argc: isize, _argv: *const *const u8) { } pub fn cleanup() { diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index 72486fc55d..beb2870807 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -12,11 +12,13 @@ //! //! Documentation can be found on the `rt::at_exit` function. -use core::prelude::*; +// FIXME: switch this to use atexit. Currently this +// segfaults (the queue's memory is mysteriously gone), so +// instead the cleanup is tied to the `std::rt` entry point. +use boxed; use boxed::Box; use vec::Vec; -use mem; use thunk::Thunk; use sys_common::mutex::{Mutex, MUTEX_INIT}; @@ -29,47 +31,56 @@ type Queue = Vec>; static LOCK: Mutex = MUTEX_INIT; static mut QUEUE: *mut Queue = 0 as *mut Queue; -unsafe fn init() { +// The maximum number of times the cleanup routines will be run. While running +// the at_exit closures new ones may be registered, and this count is the number +// of times the new closures will be allowed to register successfully. After +// this number of iterations all new registrations will return `false`. +const ITERS: usize = 10; + +unsafe fn init() -> bool { if QUEUE.is_null() { let state: Box = box Vec::new(); - QUEUE = mem::transmute(state); - } else { + QUEUE = boxed::into_raw(state); + } else if QUEUE as usize == 1 { // can't re-init after a cleanup - rtassert!(QUEUE as uint != 1); + return false } - // FIXME: switch this to use atexit as below. Currently this - // segfaults (the queue's memory is mysteriously gone), so - // instead the cleanup is tied to the `std::rt` entry point. - // - // ::libc::atexit(cleanup); + return true } pub fn cleanup() { - unsafe { - LOCK.lock(); - let queue = QUEUE; - QUEUE = 1 as *mut _; - LOCK.unlock(); + for i in 0..ITERS { + unsafe { + LOCK.lock(); + let queue = QUEUE; + QUEUE = if i == ITERS - 1 {1} else {0} as *mut _; + LOCK.unlock(); - // make sure we're not recursively cleaning up - rtassert!(queue as uint != 1); + // make sure we're not recursively cleaning up + rtassert!(queue as usize != 1); - // If we never called init, not need to cleanup! - if queue as uint != 0 { - let queue: Box = mem::transmute(queue); - for to_run in *queue { - to_run.invoke(()); + // If we never called init, not need to cleanup! + if queue as usize != 0 { + let queue: Box = Box::from_raw(queue); + for to_run in *queue { + to_run(); + } } } } } -pub fn push(f: Thunk<'static>) { +pub fn push(f: Thunk<'static>) -> bool { + let mut ret = true; unsafe { LOCK.lock(); - init(); - (*QUEUE).push(f); + if init() { + (*QUEUE).push(f); + } else { + ret = false; + } LOCK.unlock(); } + return ret } diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs index 43e3a43f56..4b754bd5f5 100644 --- a/src/libstd/rt/libunwind.rs +++ b/src/libstd/rt/libunwind.rs @@ -25,7 +25,7 @@ use libc; #[cfg(any(not(target_arch = "arm"), target_os = "ios"))] #[repr(C)] -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum _Unwind_Action { _UA_SEARCH_PHASE = 1, _UA_CLEANUP_PHASE = 2, @@ -64,25 +64,25 @@ pub type _Unwind_Exception_Class = u64; pub type _Unwind_Word = libc::uintptr_t; #[cfg(target_arch = "x86")] -pub const unwinder_private_data_size: uint = 5; +pub const unwinder_private_data_size: usize = 5; #[cfg(target_arch = "x86_64")] -pub const unwinder_private_data_size: uint = 6; +pub const unwinder_private_data_size: usize = 6; #[cfg(all(target_arch = "arm", not(target_os = "ios")))] -pub const unwinder_private_data_size: uint = 20; +pub const unwinder_private_data_size: usize = 20; #[cfg(all(target_arch = "arm", target_os = "ios"))] -pub const unwinder_private_data_size: uint = 5; +pub const unwinder_private_data_size: usize = 5; #[cfg(target_arch = "aarch64")] -pub const unwinder_private_data_size: uint = 2; +pub const unwinder_private_data_size: usize = 2; #[cfg(any(target_arch = "mips", target_arch = "mipsel"))] -pub const unwinder_private_data_size: uint = 2; +pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "powerpc")] -pub const unwinder_private_data_size: uint = 2; +pub const unwinder_private_data_size: usize = 2; #[repr(C)] pub struct _Unwind_Exception { @@ -109,6 +109,10 @@ extern {} #[link(name = "gcc_pic")] extern {} +#[cfg(target_os = "bitrig")] +#[link(name = "c++abi")] +extern {} + extern "C" { // iOS on armv7 uses SjLj exceptions and requires to link // against corresponding routine (..._SjLj_...) diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 42cca73e5e..0d26206f26 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -17,19 +17,14 @@ //! time being. #![unstable(feature = "std_misc")] - -// FIXME: this should not be here. #![allow(missing_docs)] -#![allow(dead_code)] - -use marker::Send; -use ops::FnOnce; +use prelude::v1::*; use sys; -use thunk::Thunk; +use usize; // Reexport some of our utilities which are expected by other crates. -pub use self::util::{default_sched_threads, min_stack, running_on_valgrind}; +pub use self::util::{min_stack, running_on_valgrind}; pub use self::unwind::{begin_unwind, begin_unwind_fmt}; // Reexport some functionality from liballoc. @@ -52,16 +47,16 @@ mod libunwind; /// The default error code of the rust runtime if the main thread panics instead /// of exiting cleanly. -pub const DEFAULT_ERROR_CODE: int = 101; +pub const DEFAULT_ERROR_CODE: isize = 101; #[cfg(any(windows, android))] -const OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20; +const OS_DEFAULT_STACK_ESTIMATE: usize = 1 << 20; #[cfg(all(unix, not(android)))] -const OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20); +const OS_DEFAULT_STACK_ESTIMATE: usize = 2 * (1 << 20); #[cfg(not(test))] #[lang = "start"] -fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { +fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { use prelude::v1::*; use mem; @@ -72,13 +67,26 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { use thread::Thread; let something_around_the_top_of_the_stack = 1; - let addr = &something_around_the_top_of_the_stack as *const int; - let my_stack_top = addr as uint; + let addr = &something_around_the_top_of_the_stack as *const _ as *const isize; + let my_stack_top = addr as usize; // FIXME #11359 we just assume that this thread has a stack of a // certain size, and estimate that there's at most 20KB of stack // frames above our current position. - let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE; + const TWENTY_KB: usize = 20000; + + // saturating-add to sidestep overflow + let top_plus_spill = if usize::MAX - TWENTY_KB < my_stack_top { + usize::MAX + } else { + my_stack_top + TWENTY_KB + }; + // saturating-sub to sidestep underflow + let my_stack_bottom = if top_plus_spill < OS_DEFAULT_STACK_ESTIMATE { + 0 + } else { + top_plus_spill - OS_DEFAULT_STACK_ESTIMATE + }; let failed = unsafe { // First, make sure we don't trigger any __morestack overflow checks, @@ -94,9 +102,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { // but we just do this to name the main thread and to give it correct // info about the stack bounds. let thread: Thread = NewThread::new(Some("

".to_string())); - thread_info::set((my_stack_bottom, my_stack_top), - sys::thread::guard::main(), - thread); + thread_info::set(sys::thread::guard::main(), thread); // By default, some platforms will send a *signal* when a EPIPE error // would otherwise be delivered. This runtime doesn't install a SIGPIPE @@ -110,7 +116,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { use libc; use libc::funcs::posix01::signal::signal; unsafe { - assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1); + assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); } } ignore_sigpipe(); @@ -135,21 +141,18 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { } } -/// Enqueues a procedure to run when the runtime is cleaned up -/// -/// The procedure passed to this function will be executed as part of the -/// runtime cleanup phase. For normal rust programs, this means that it will run -/// after all other threads have exited. +/// Enqueues a procedure to run when the main thread exits. /// -/// The procedure is *not* executed with a local `Thread` available to it, so -/// primitives like logging, I/O, channels, spawning, etc, are *not* available. -/// This is meant for "bare bones" usage to clean up runtime details, this is -/// not meant as a general-purpose "let's clean everything up" function. +/// Currently these closures are only run once the main *Rust* thread exits. +/// Once the `at_exit` handlers begin running, more may be enqueued, but not +/// infinitely so. Eventually a handler registration will be forced to fail. /// -/// It is forbidden for procedures to register more `at_exit` handlers when they -/// are running, and doing so will lead to a process abort. -pub fn at_exit(f: F) { - at_exit_imp::push(Thunk::new(f)); +/// Returns `Ok` if the handler was successfully registered, meaning that the +/// closure will be run once the main thread exits. Returns `Err` to indicate +/// that the closure could not be registered, meaning that it is not scheduled +/// to be rune. +pub fn at_exit(f: F) -> Result<(), ()> { + if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } /// One-time runtime cleanup. @@ -164,8 +167,5 @@ pub fn at_exit(f: F) { pub unsafe fn cleanup() { args::cleanup(); sys::stack_overflow::cleanup(); - // FIXME: (#20012): the resources being cleaned up by at_exit - // currently are not prepared for cleanup to happen asynchronously - // with detached threads using the resources; for now, we leak. - // at_exit_imp::cleanup(); + at_exit_imp::cleanup(); } diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 1f5eb3af69..f71811b1ea 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -60,6 +60,7 @@ use prelude::v1::*; use any::Any; +use boxed; use cell::Cell; use cmp; use panicking; @@ -68,7 +69,7 @@ use intrinsics; use libc::c_void; use mem; use sync::atomic::{self, Ordering}; -use sync::{Once, ONCE_INIT}; +use sys_common::mutex::{Mutex, MUTEX_INIT}; use rt::libunwind as uw; @@ -77,12 +78,12 @@ struct Exception { cause: Option>, } -pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint); +pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: usize); // Variables used for invoking callbacks when a thread starts to unwind. // // For more information, see below. -const MAX_CALLBACKS: uint = 16; +const MAX_CALLBACKS: usize = 16; static CALLBACKS: [atomic::AtomicUsize; MAX_CALLBACKS] = [atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT, @@ -165,7 +166,7 @@ fn rust_panic(cause: Box) -> ! { rtdebug!("begin_unwind()"); unsafe { - let exception = box Exception { + let exception: Box<_> = box Exception { uwe: uw::_Unwind_Exception { exception_class: rust_exception_class(), exception_cleanup: exception_cleanup, @@ -173,15 +174,16 @@ fn rust_panic(cause: Box) -> ! { }, cause: Some(cause), }; - let error = uw::_Unwind_RaiseException(mem::transmute(exception)); - rtabort!("Could not unwind stack, error = {}", error as int) + let exception_param = boxed::into_raw(exception) as *mut uw::_Unwind_Exception; + let error = uw::_Unwind_RaiseException(exception_param); + rtabort!("Could not unwind stack, error = {}", error as isize) } extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code, exception: *mut uw::_Unwind_Exception) { rtdebug!("exception_cleanup()"); unsafe { - let _: Box = mem::transmute(exception); + let _: Box = Box::from_raw(exception as *mut Exception); } } } @@ -396,7 +398,7 @@ pub mod eabi { pub struct DISPATCHER_CONTEXT; #[repr(C)] - #[derive(Copy)] + #[derive(Copy, Clone)] pub enum EXCEPTION_DISPOSITION { ExceptionContinueExecution, ExceptionContinueSearch, @@ -482,7 +484,7 @@ pub mod eabi { /// Entry point of panic from the libcore crate. #[lang = "panic_fmt"] pub extern fn rust_begin_unwind(msg: fmt::Arguments, - file: &'static str, line: uint) -> ! { + file: &'static str, line: usize) -> ! { begin_unwind_fmt(msg, &(file, line)) } @@ -494,7 +496,7 @@ pub extern fn rust_begin_unwind(msg: fmt::Arguments, /// the actual formatting into this shared place. #[inline(never)] #[cold] #[stable(since = "1.0.0", feature = "rust1")] -pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! { +pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, usize)) -> ! { use fmt::Write; // We do two allocations here, unfortunately. But (a) they're @@ -504,13 +506,13 @@ pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) - let mut s = String::new(); let _ = write!(&mut s, "{}", msg); - begin_unwind_inner(box s, file_line) + begin_unwind_inner(Box::new(s), file_line) } /// This is the entry point of unwinding for panic!() and assert!(). #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible #[stable(since = "1.0.0", feature = "rust1")] -pub fn begin_unwind(msg: M, file_line: &(&'static str, uint)) -> ! { +pub fn begin_unwind(msg: M, file_line: &(&'static str, usize)) -> ! { // Note that this should be the only allocation performed in this code path. // Currently this means that panic!() on OOM will invoke this code path, // but then again we're not really ready for panic on OOM anyway. If @@ -519,7 +521,7 @@ pub fn begin_unwind(msg: M, file_line: &(&'static str, uint)) -> // panicking. // see below for why we do the `Any` coercion here. - begin_unwind_inner(box msg, file_line) + begin_unwind_inner(Box::new(msg), file_line) } /// The core of the unwinding. @@ -532,11 +534,22 @@ pub fn begin_unwind(msg: M, file_line: &(&'static str, uint)) -> /// Doing this split took the LLVM IR line counts of `fn main() { panic!() /// }` from ~1900/3700 (-O/no opts) to 180/590. #[inline(never)] #[cold] // this is the slow path, please never inline this -fn begin_unwind_inner(msg: Box, file_line: &(&'static str, uint)) -> ! { - // Make sure the default panic handler is registered before we look at the - // callbacks. - static INIT: Once = ONCE_INIT; - INIT.call_once(|| unsafe { register(panicking::on_panic); }); +fn begin_unwind_inner(msg: Box, + file_line: &(&'static str, usize)) -> ! { + // Make sure the default failure handler is registered before we look at the + // callbacks. We also use a raw sys-based mutex here instead of a + // `std::sync` one as accessing TLS can cause weird recursive problems (and + // we don't need poison checking). + unsafe { + static LOCK: Mutex = MUTEX_INIT; + static mut INIT: bool = false; + LOCK.lock(); + if !INIT { + register(panicking::on_panic); + INIT = true; + } + LOCK.unlock(); + } // First, invoke call the user-defined callbacks triggered on thread panic. // diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index a304f1f844..5a482fbb50 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -10,17 +10,14 @@ // // ignore-lexer-test FIXME #15677 -use prelude::v1::*; +use io::prelude::*; -use cmp; use env; use fmt; use intrinsics; -use libc::{self, uintptr_t}; -use os; -use slice; -use str; +use libc::uintptr_t; use sync::atomic::{self, Ordering}; +use sys::stdio::Stderr; /// Dynamically inquire about whether we're running under V. /// You should usually not use this unless your test definitely @@ -46,7 +43,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { (cfg!(target_os="macos")) && running_on_valgrind() } -pub fn min_stack() -> uint { +pub fn min_stack() -> usize { static MIN: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; match MIN.load(Ordering::SeqCst) { 0 => {} @@ -60,27 +57,6 @@ pub fn min_stack() -> uint { return amt; } -/// Get's the number of scheduler threads requested by the environment -/// either `RUST_THREADS` or `num_cpus`. -pub fn default_sched_threads() -> uint { - match env::var("RUST_THREADS") { - Ok(nstr) => { - let opt_n: Option = nstr.parse().ok(); - match opt_n { - Some(n) if n > 0 => n, - _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr) - } - } - Err(..) => { - if limit_thread_creation_due_to_osx_and_valgrind() { - 1 - } else { - os::num_cpus() - } - } - } -} - // Indicates whether we should perform expensive sanity checks, including rtassert! // // FIXME: Once the runtime matures remove the `true` below to turn off rtassert, @@ -88,76 +64,17 @@ pub fn default_sched_threads() -> uint { pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) || cfg!(rtassert); -pub struct Stdio(libc::c_int); - -#[allow(non_upper_case_globals)] -pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO); -#[allow(non_upper_case_globals)] -pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO); - -impl Stdio { - pub fn write_bytes(&mut self, data: &[u8]) { - #[cfg(unix)] - type WriteLen = libc::size_t; - #[cfg(windows)] - type WriteLen = libc::c_uint; - unsafe { - let Stdio(fd) = *self; - libc::write(fd, - data.as_ptr() as *const libc::c_void, - data.len() as WriteLen); - } - } -} - -impl fmt::Write for Stdio { - fn write_str(&mut self, data: &str) -> fmt::Result { - self.write_bytes(data.as_bytes()); - Ok(()) // yes, we're lying - } -} - pub fn dumb_print(args: fmt::Arguments) { - let _ = Stderr.write_fmt(args); + let _ = write!(&mut Stderr::new(), "{}", args); } pub fn abort(args: fmt::Arguments) -> ! { - use fmt::Write; - - struct BufWriter<'a> { - buf: &'a mut [u8], - pos: uint, - } - impl<'a> fmt::Write for BufWriter<'a> { - fn write_str(&mut self, bytes: &str) -> fmt::Result { - let left = &mut self.buf[self.pos..]; - let to_write = &bytes.as_bytes()[..cmp::min(bytes.len(), left.len())]; - slice::bytes::copy_memory(left, to_write); - self.pos += to_write.len(); - Ok(()) - } - } - - // Convert the arguments into a stack-allocated string - let mut msg = [0u8; 512]; - let mut w = BufWriter { buf: &mut msg, pos: 0 }; - let _ = write!(&mut w, "{}", args); - let msg = str::from_utf8(&w.buf[..w.pos]).unwrap_or("aborted"); - let msg = if msg.is_empty() {"aborted"} else {msg}; - rterrln!("fatal runtime error: {}", msg); + rterrln!("fatal runtime error: {}", args); unsafe { intrinsics::abort(); } } pub unsafe fn report_overflow() { use thread; - - // See the message below for why this is not emitted to the - // ^ Where did the message below go? - // task's logger. This has the additional conundrum of the - // logger may not be initialized just yet, meaning that an FFI - // call would happen to initialized it (calling out to libuv), - // and the FFI call needs 2MB of stack when we just ran out. - rterrln!("\nthread '{}' has overflowed its stack", thread::current().name().unwrap_or("")); } diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs index 1392bc815c..96c4bcec85 100644 --- a/src/libstd/rtdeps.rs +++ b/src/libstd/rtdeps.rs @@ -39,7 +39,9 @@ extern {} #[link(name = "pthread")] extern {} -#[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] +#[cfg(any(target_os = "dragonfly", + target_os = "bitrig", + target_os = "openbsd"))] #[link(name = "pthread")] extern {} diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index b036177af1..ebf4d33774 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -13,7 +13,7 @@ use sync::{Mutex, Condvar}; /// A barrier enables multiple tasks to synchronize the beginning /// of some computation. /// -/// ```rust +/// ``` /// use std::sync::{Arc, Barrier}; /// use std::thread; /// @@ -33,13 +33,13 @@ use sync::{Mutex, Condvar}; pub struct Barrier { lock: Mutex, cvar: Condvar, - num_threads: uint, + num_threads: usize, } // The inner state of a double barrier struct BarrierState { - count: uint, - generation_id: uint, + count: usize, + generation_id: usize, } /// A result returned from wait. @@ -54,7 +54,7 @@ impl Barrier { /// A barrier will block `n`-1 threads which call `wait` and then wake up /// all threads at once when the `n`th thread calls `wait`. #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(n: uint) -> Barrier { + pub fn new(n: usize) -> Barrier { Barrier { lock: Mutex::new(BarrierState { count: 0, @@ -115,7 +115,7 @@ mod tests { #[test] fn test_barrier() { - const N: uint = 10; + const N: usize = 10; let barrier = Arc::new(Barrier::new(N)); let (tx, rx) = channel(); diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 52561d482c..a7d8b287a6 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -34,7 +34,7 @@ use sync::{mutex, MutexGuard, PoisonError}; /// in a runtime panic. If this is not desired, then the unsafe primitives in /// `sys` do not have this restriction but may result in undefined behavior. /// -/// # Example +/// # Examples /// /// ``` /// use std::sync::{Arc, Mutex, Condvar}; @@ -61,17 +61,15 @@ use sync::{mutex, MutexGuard, PoisonError}; #[stable(feature = "rust1", since = "1.0.0")] pub struct Condvar { inner: Box } -unsafe impl Send for Condvar {} -unsafe impl Sync for Condvar {} - /// Statically allocated condition variables. /// /// This structure is identical to `Condvar` except that it is suitable for use /// in static initializers for other structures. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(std_misc)] /// use std::sync::{StaticCondvar, CONDVAR_INIT}; /// /// static CVAR: StaticCondvar = CONDVAR_INIT; @@ -83,9 +81,6 @@ pub struct StaticCondvar { mutex: AtomicUsize, } -unsafe impl Send for StaticCondvar {} -unsafe impl Sync for StaticCondvar {} - /// Constant initializer for a statically allocated condition variable. #[unstable(feature = "std_misc", reason = "may be merged with Condvar in the future")] @@ -145,33 +140,43 @@ impl Condvar { /// Wait on this condition variable for a notification, timing out after a /// specified duration. /// - /// The semantics of this function are equivalent to `wait()` except that - /// the thread will be blocked for roughly no longer than `dur`. This method - /// should not be used for precise timing due to anomalies such as - /// preemption or platform differences that may not cause the maximum amount - /// of time waited to be precisely `dur`. + /// The semantics of this function are equivalent to `wait()` + /// except that the thread will be blocked for roughly no longer + /// than `ms` milliseconds. This method should not be used for + /// precise timing due to anomalies such as preemption or platform + /// differences that may not cause the maximum amount of time + /// waited to be precisely `ms`. /// - /// If the wait timed out, then `false` will be returned. Otherwise if a - /// notification was received then `true` will be returned. + /// The returned boolean is `false` only if the timeout is known + /// to have elapsed. /// /// Like `wait`, the lock specified will be re-acquired when this function /// returns, regardless of whether the timeout elapsed or not. - #[unstable(feature = "std_misc")] - pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration) - -> LockResult<(MutexGuard<'a, T>, bool)> { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32) + -> LockResult<(MutexGuard<'a, T>, bool)> { unsafe { let me: &'static Condvar = &*(self as *const _); - me.inner.wait_timeout(guard, dur) + me.inner.wait_timeout_ms(guard, ms) } } + /// Deprecated: use `wait_timeout_ms` instead. + #[unstable(feature = "std_misc")] + #[deprecated(since = "1.0.0", reason = "use wait_timeout_ms instead")] + pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { + self.wait_timeout_ms(guard, dur.num_milliseconds() as u32) + } + /// Wait on this condition variable for a notification, timing out after a /// specified duration. /// /// The semantics of this function are equivalent to `wait_timeout` except /// that the implementation will repeatedly wait while the duration has not /// passed and the provided function returns `false`. - #[unstable(feature = "std_misc")] + #[unstable(feature = "wait_timeout_with", + reason = "unsure if this API is broadly needed or what form it should take")] pub fn wait_timeout_with<'a, T, F>(&self, guard: MutexGuard<'a, T>, dur: Duration, @@ -240,12 +245,12 @@ impl StaticCondvar { /// See `Condvar::wait_timeout`. #[unstable(feature = "std_misc", reason = "may be merged with Condvar in the future")] - pub fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration) - -> LockResult<(MutexGuard<'a, T>, bool)> { + pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32) + -> LockResult<(MutexGuard<'a, T>, bool)> { let (poisoned, success) = unsafe { let lock = mutex::guard_lock(&guard); self.verify(lock); - let success = self.inner.wait_timeout(lock, dur); + let success = self.inner.wait_timeout(lock, Duration::milliseconds(ms as i64)); (mutex::guard_poison(&guard).get(), success) }; if poisoned { @@ -280,7 +285,8 @@ impl StaticCondvar { let now = SteadyTime::now(); let consumed = &now - &start; let guard = guard_result.unwrap_or_else(|e| e.into_inner()); - let (new_guard_result, no_timeout) = match self.wait_timeout(guard, dur - consumed) { + let res = self.wait_timeout_ms(guard, (dur - consumed).num_milliseconds() as u32); + let (new_guard_result, no_timeout) = match res { Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout), Err(err) => { let (new_guard, no_timeout) = err.into_inner(); @@ -327,7 +333,7 @@ impl StaticCondvar { } fn verify(&self, mutex: &sys_mutex::Mutex) { - let addr = mutex as *const _ as uint; + let addr = mutex as *const _ as usize; match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) { // If we got out 0, then we have successfully bound the mutex to // this cvar. @@ -355,6 +361,7 @@ mod tests { use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use thread; use time::Duration; + use u32; #[test] fn smoke() { @@ -388,7 +395,7 @@ mod tests { #[test] fn notify_all() { - const N: uint = 10; + const N: usize = 10; let data = Arc::new((Mutex::new(0), Condvar::new())); let (tx, rx) = channel(); @@ -423,19 +430,19 @@ mod tests { } #[test] - fn wait_timeout() { + fn wait_timeout_ms() { static C: StaticCondvar = CONDVAR_INIT; static M: StaticMutex = MUTEX_INIT; let g = M.lock().unwrap(); - let (g, _no_timeout) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap(); + let (g, _no_timeout) = C.wait_timeout_ms(g, 1).unwrap(); // spurious wakeups mean this isn't necessarily true // assert!(!no_timeout); let _t = thread::spawn(move || { let _g = M.lock().unwrap(); C.notify_one(); }); - let (g, no_timeout) = C.wait_timeout(g, Duration::days(1)).unwrap(); + let (g, no_timeout) = C.wait_timeout_ms(g, u32::MAX).unwrap(); assert!(no_timeout); drop(g); unsafe { C.destroy(); M.destroy(); } @@ -485,7 +492,7 @@ mod tests { } #[test] - #[should_fail] + #[should_panic] fn two_mutexes() { static M1: StaticMutex = MUTEX_INIT; static M2: StaticMutex = MUTEX_INIT; diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index d60e273880..2cdde1aca9 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -14,6 +14,7 @@ //! # Examples //! //! ``` +//! # #![feature(std_misc)] //! use std::sync::Future; //! //! // a fake, for now @@ -35,9 +36,10 @@ use core::prelude::*; use core::mem::replace; +use boxed::Box; use self::FutureState::*; use sync::mpsc::{Receiver, channel}; -use thunk::{Thunk}; +use thunk::Thunk; use thread; /// A type encapsulating the result of a computation which may not be complete @@ -83,7 +85,7 @@ impl Future { match replace(&mut self.state, Evaluating) { Forced(_) | Evaluating => panic!("Logic error."), Pending(f) => { - self.state = Forced(f.invoke(())); + self.state = Forced(f()); self.get_ref() } } @@ -113,7 +115,7 @@ impl Future { * function. It is not spawned into another task. */ - Future {state: Pending(Thunk::new(f))} + Future {state: Pending(Box::new(f))} } } @@ -204,7 +206,7 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn test_future_panic() { let mut f = Future::spawn(move|| panic!()); let _x: String = f.get(); diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index f3b721438d..a5259a0039 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -31,7 +31,6 @@ pub use self::barrier::{Barrier, BarrierWaitResult}; pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; pub use self::future::Future; -pub use self::task_pool::TaskPool; pub mod mpsc; @@ -43,4 +42,3 @@ mod once; mod poison; mod rwlock; mod semaphore; -mod task_pool; diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index 69b1e242b1..2e4155ea35 100644 --- a/src/libstd/sync/mpsc/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -61,17 +61,17 @@ impl SignalToken { wake } - /// Convert to an unsafe uint value. Useful for storing in a pipe's state + /// Convert to an unsafe usize value. Useful for storing in a pipe's state /// flag. #[inline] - pub unsafe fn cast_to_uint(self) -> uint { + pub unsafe fn cast_to_usize(self) -> usize { mem::transmute(self.inner) } - /// Convert from an unsafe uint value. Useful for retrieving a pipe's state + /// Convert from an unsafe usize value. Useful for retrieving a pipe's state /// flag. #[inline] - pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken { + pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken { SignalToken { inner: mem::transmute(signal_ptr) } } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 21993e5166..c80182ec07 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -94,7 +94,7 @@ //! //! // The call to recv() will return an error because the channel has already //! // hung up (or been deallocated) -//! let (tx, rx) = channel::(); +//! let (tx, rx) = channel::(); //! drop(tx); //! assert!(rx.recv().is_err()); //! ``` @@ -105,7 +105,7 @@ //! use std::thread; //! use std::sync::mpsc::sync_channel; //! -//! let (tx, rx) = sync_channel::(0); +//! let (tx, rx) = sync_channel::(0); //! thread::spawn(move|| { //! // This will wait for the parent task to start receiving //! tx.send(53).unwrap(); @@ -114,16 +114,17 @@ //! ``` //! //! Reading from a channel with a timeout requires to use a Timer together -//! with the channel. You can use the select! macro to select either and +//! with the channel. You can use the `select!` macro to select either and //! handle the timeout case. This first example will break out of the loop //! after 10 seconds no matter what: //! //! ```no_run +//! # #![feature(std_misc, old_io)] //! use std::sync::mpsc::channel; //! use std::old_io::timer::Timer; //! use std::time::Duration; //! -//! let (tx, rx) = channel::(); +//! let (tx, rx) = channel::(); //! let mut timer = Timer::new().unwrap(); //! let timeout = timer.oneshot(Duration::seconds(10)); //! @@ -143,11 +144,12 @@ //! has been inactive for 5 seconds: //! //! ```no_run +//! # #![feature(std_misc, old_io)] //! use std::sync::mpsc::channel; //! use std::old_io::timer::Timer; //! use std::time::Duration; //! -//! let (tx, rx) = channel::(); +//! let (tx, rx) = channel::(); //! let mut timer = Timer::new().unwrap(); //! //! loop { @@ -318,6 +320,7 @@ use prelude::v1::*; use sync::Arc; +use error; use fmt; use mem; use cell::UnsafeCell; @@ -345,13 +348,13 @@ pub struct Receiver { // The receiver port can be sent from place to place, so long as it // is not used to receive non-sendable things. -unsafe impl Send for Receiver { } +unsafe impl Send for Receiver { } /// 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(feature = "rust1", since = "1.0.0")] -pub struct Iter<'a, T:'a> { +pub struct Iter<'a, T: 'a> { rx: &'a Receiver } @@ -364,7 +367,7 @@ pub struct Sender { // The send port can be sent from place to place, so long as it // is not used to send non-sendable things. -unsafe impl Send for Sender { } +unsafe impl Send for Sender { } /// 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. @@ -373,7 +376,7 @@ pub struct SyncSender { inner: Arc>>, } -unsafe impl Send for SyncSender {} +unsafe impl Send for SyncSender {} impl !Sync for SyncSender {} @@ -384,7 +387,7 @@ impl !Sync for SyncSender {} /// contains the data being sent as a payload so it can be recovered. #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, Clone, Copy)] -pub struct SendError(pub T); +pub struct SendError(#[stable(feature = "rust1", since = "1.0.0")] pub T); /// An error returned from the `recv` function on a `Receiver`. /// @@ -463,7 +466,7 @@ impl UnsafeFlavor for Receiver { /// All data sent on the sender will become available on the receiver, and no /// send will block the calling task (this channel has an "infinite buffer"). /// -/// # Example +/// # Examples /// /// ``` /// use std::sync::mpsc::channel; @@ -485,7 +488,7 @@ impl UnsafeFlavor for Receiver { /// println!("{:?}", rx.recv().unwrap()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn channel() -> (Sender, Receiver) { +pub fn channel() -> (Sender, Receiver) { let a = Arc::new(UnsafeCell::new(oneshot::Packet::new())); (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a))) } @@ -505,7 +508,7 @@ pub fn channel() -> (Sender, Receiver) { /// As with asynchronous channels, all senders will panic in `send` if the /// `Receiver` has been destroyed. /// -/// # Example +/// # Examples /// /// ``` /// use std::sync::mpsc::sync_channel; @@ -525,7 +528,7 @@ pub fn channel() -> (Sender, Receiver) { /// assert_eq!(rx.recv().unwrap(), 2); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn sync_channel(bound: uint) -> (SyncSender, Receiver) { +pub fn sync_channel(bound: usize) -> (SyncSender, Receiver) { let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound))); (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a))) } @@ -534,7 +537,7 @@ pub fn sync_channel(bound: uint) -> (SyncSender, Receiver< // Sender //////////////////////////////////////////////////////////////////////////////// -impl Sender { +impl Sender { fn new(inner: Flavor) -> Sender { Sender { inner: UnsafeCell::new(inner), @@ -554,7 +557,7 @@ impl Sender { /// /// This method will never block the current thread. /// - /// # Example + /// # Examples /// /// ``` /// use std::sync::mpsc::channel; @@ -591,7 +594,7 @@ impl Sender { // asleep (we're looking at it), so the receiver // can't go away. (*a.get()).send(t).ok().unwrap(); - token.signal(); + token.signal(); (a, Ok(())) } } @@ -616,7 +619,7 @@ impl Sender { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Sender { +impl Clone for Sender { fn clone(&self) -> Sender { let (packet, sleeper, guard) = match *unsafe { self.inner() } { Flavor::Oneshot(ref p) => { @@ -662,7 +665,7 @@ impl Clone for Sender { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Sender { +impl Drop for Sender { fn drop(&mut self) { match *unsafe { self.inner_mut() } { Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); }, @@ -677,7 +680,7 @@ impl Drop for Sender { // SyncSender //////////////////////////////////////////////////////////////////////////////// -impl SyncSender { +impl SyncSender { fn new(inner: Arc>>) -> SyncSender { SyncSender { inner: inner } } @@ -717,7 +720,7 @@ impl SyncSender { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for SyncSender { +impl Clone for SyncSender { fn clone(&self) -> SyncSender { unsafe { (*self.inner.get()).clone_chan(); } return SyncSender::new(self.inner.clone()); @@ -726,7 +729,7 @@ impl Clone for SyncSender { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for SyncSender { +impl Drop for SyncSender { fn drop(&mut self) { unsafe { (*self.inner.get()).drop_chan(); } } @@ -736,7 +739,7 @@ impl Drop for SyncSender { // Receiver //////////////////////////////////////////////////////////////////////////////// -impl Receiver { +impl Receiver { fn new(inner: Flavor) -> Receiver { Receiver { inner: UnsafeCell::new(inner) } } @@ -855,7 +858,7 @@ impl Receiver { } } -impl select::Packet for Receiver { +impl select::Packet for Receiver { fn can_recv(&self) -> bool { loop { let new_port = match *unsafe { self.inner() } { @@ -942,7 +945,7 @@ impl select::Packet for Receiver { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Send + 'static> Iterator for Iter<'a, T> { +impl<'a, T> Iterator for Iter<'a, T> { type Item = T; fn next(&mut self) -> Option { self.rx.recv().ok() } @@ -950,7 +953,7 @@ impl<'a, T: Send + 'static> Iterator for Iter<'a, T> { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Receiver { +impl Drop for Receiver { fn drop(&mut self) { match *unsafe { self.inner_mut() } { Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); }, @@ -975,6 +978,18 @@ impl fmt::Display for SendError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for SendError { + + fn description(&self) -> &str { + "sending on a closed channel" + } + + fn cause(&self) -> Option<&error::Error> { + None + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for TrySendError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -999,6 +1014,25 @@ impl fmt::Display for TrySendError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for TrySendError { + + fn description(&self) -> &str { + match *self { + TrySendError::Full(..) => { + "sending on a full channel" + } + TrySendError::Disconnected(..) => { + "sending on a closed channel" + } + } + } + + fn cause(&self) -> Option<&error::Error> { + None + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for RecvError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1006,6 +1040,18 @@ impl fmt::Display for RecvError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for RecvError { + + fn description(&self) -> &str { + "receiving on a closed channel" + } + + fn cause(&self) -> Option<&error::Error> { + None + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for TryRecvError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -1020,6 +1066,25 @@ impl fmt::Display for TryRecvError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl error::Error for TryRecvError { + + fn description(&self) -> &str { + match *self { + TryRecvError::Empty => { + "receiving on an empty channel" + } + TryRecvError::Disconnected => { + "receiving on a closed channel" + } + } + } + + fn cause(&self) -> Option<&error::Error> { + None + } +} + #[cfg(test)] mod test { use prelude::v1::*; @@ -1028,7 +1093,7 @@ mod test { use super::*; use thread; - pub fn stress_factor() -> uint { + pub fn stress_factor() -> usize { match env::var("RUST_TEST_STRESS") { Ok(val) => val.parse().unwrap(), Err(..) => 1, @@ -1037,20 +1102,20 @@ mod test { #[test] fn smoke() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); tx.send(1).unwrap(); assert_eq!(rx.recv().unwrap(), 1); } #[test] fn drop_full() { - let (tx, _rx) = channel(); + let (tx, _rx) = channel::>(); tx.send(box 1).unwrap(); } #[test] fn drop_full_shared() { - let (tx, _rx) = channel(); + let (tx, _rx) = channel::>(); drop(tx.clone()); drop(tx.clone()); tx.send(box 1).unwrap(); @@ -1058,7 +1123,7 @@ mod test { #[test] fn smoke_shared() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); tx.send(1).unwrap(); assert_eq!(rx.recv().unwrap(), 1); let tx = tx.clone(); @@ -1068,7 +1133,7 @@ mod test { #[test] fn smoke_threads() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { tx.send(1).unwrap(); }); @@ -1077,21 +1142,21 @@ mod test { #[test] fn smoke_port_gone() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); assert!(tx.send(1).is_err()); } #[test] fn smoke_shared_port_gone() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); assert!(tx.send(1).is_err()) } #[test] fn smoke_shared_port_gone2() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); let tx2 = tx.clone(); drop(tx); @@ -1100,7 +1165,7 @@ mod test { #[test] fn port_gone_concurrent() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { rx.recv().unwrap(); }); @@ -1109,7 +1174,7 @@ mod test { #[test] fn port_gone_concurrent_shared() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let tx2 = tx.clone(); let _t = thread::spawn(move|| { rx.recv().unwrap(); @@ -1119,7 +1184,7 @@ mod test { #[test] fn smoke_chan_gone() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(tx); assert!(rx.recv().is_err()); } @@ -1135,7 +1200,7 @@ mod test { #[test] fn chan_gone_concurrent() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { tx.send(1).unwrap(); tx.send(1).unwrap(); @@ -1145,7 +1210,7 @@ mod test { #[test] fn stress() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let t = thread::spawn(move|| { for _ in 0..10000 { tx.send(1).unwrap(); } }); @@ -1157,9 +1222,9 @@ mod test { #[test] fn stress_shared() { - static AMT: uint = 10000; - static NTHREADS: uint = 8; - let (tx, rx) = channel::(); + const AMT: u32 = 10000; + const NTHREADS: u32 = 8; + let (tx, rx) = channel::(); let t = thread::spawn(move|| { for _ in 0..AMT * NTHREADS { @@ -1184,7 +1249,7 @@ mod test { #[test] fn send_from_outside_runtime() { let (tx1, rx1) = channel::<()>(); - let (tx2, rx2) = channel::(); + let (tx2, rx2) = channel::(); let t1 = thread::spawn(move|| { tx1.send(()).unwrap(); for _ in 0..40 { @@ -1203,7 +1268,7 @@ mod test { #[test] fn recv_from_outside_runtime() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let t = thread::spawn(move|| { for _ in 0..40 { assert_eq!(rx.recv().unwrap(), 1); @@ -1217,8 +1282,8 @@ mod test { #[test] fn no_runtime() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); let t1 = thread::spawn(move|| { assert_eq!(rx1.recv().unwrap(), 1); tx2.send(2).unwrap(); @@ -1234,21 +1299,21 @@ mod test { #[test] fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending - let (_tx, rx) = channel::(); + let (_tx, rx) = channel::(); drop(rx); } #[test] fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending - let (tx, _rx) = channel::(); + let (tx, _rx) = channel::(); drop(tx); } #[test] fn oneshot_single_thread_send_port_close() { // Testing that the sender cleans up the payload if receiver is closed - let (tx, rx) = channel::>(); + let (tx, rx) = channel::>(); drop(rx); assert!(tx.send(box 0).is_err()); } @@ -1257,7 +1322,7 @@ mod test { fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = thread::spawn(move|| { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(tx); rx.recv().unwrap(); }).join(); @@ -1267,42 +1332,42 @@ mod test { #[test] fn oneshot_single_thread_send_then_recv() { - let (tx, rx) = channel::>(); + let (tx, rx) = channel::>(); tx.send(box 10).unwrap(); assert!(rx.recv().unwrap() == box 10); } #[test] fn oneshot_single_thread_try_send_open() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); assert!(tx.send(10).is_ok()); assert!(rx.recv().unwrap() == 10); } #[test] fn oneshot_single_thread_try_send_closed() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); assert!(tx.send(10).is_err()); } #[test] fn oneshot_single_thread_try_recv_open() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); tx.send(10).unwrap(); assert!(rx.recv() == Ok(10)); } #[test] fn oneshot_single_thread_try_recv_closed() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(tx); assert!(rx.recv().is_err()); } #[test] fn oneshot_single_thread_peek_data() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); tx.send(10).unwrap(); assert_eq!(rx.try_recv(), Ok(10)); @@ -1310,7 +1375,7 @@ mod test { #[test] fn oneshot_single_thread_peek_close() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(tx); assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); @@ -1318,13 +1383,13 @@ mod test { #[test] fn oneshot_single_thread_peek_open() { - let (_tx, rx) = channel::(); + let (_tx, rx) = channel::(); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); } #[test] fn oneshot_multi_task_recv_then_send() { - let (tx, rx) = channel::>(); + let (tx, rx) = channel::>(); let _t = thread::spawn(move|| { assert!(rx.recv().unwrap() == box 10); }); @@ -1334,7 +1399,7 @@ mod test { #[test] fn oneshot_multi_task_recv_then_close() { - let (tx, rx) = channel::>(); + let (tx, rx) = channel::>(); let _t = thread::spawn(move|| { drop(tx); }); @@ -1347,7 +1412,7 @@ mod test { #[test] fn oneshot_multi_thread_close_stress() { for _ in 0..stress_factor() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { drop(rx); }); @@ -1358,7 +1423,7 @@ mod test { #[test] fn oneshot_multi_thread_send_close_stress() { for _ in 0..stress_factor() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { drop(rx); }); @@ -1371,7 +1436,7 @@ mod test { #[test] fn oneshot_multi_thread_recv_close_stress() { for _ in 0..stress_factor() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); thread::spawn(move|| { let res = thread::spawn(move|| { rx.recv().unwrap(); @@ -1389,7 +1454,7 @@ mod test { #[test] fn oneshot_multi_thread_send_recv_stress() { for _ in 0..stress_factor() { - let (tx, rx) = channel(); + let (tx, rx) = channel::>(); let _t = thread::spawn(move|| { tx.send(box 10).unwrap(); }); @@ -1405,7 +1470,7 @@ mod test { send(tx, 0); recv(rx, 0); - fn send(tx: Sender>, i: int) { + fn send(tx: Sender>, i: i32) { if i == 10 { return } thread::spawn(move|| { @@ -1414,7 +1479,7 @@ mod test { }); } - fn recv(rx: Receiver>, i: int) { + fn recv(rx: Receiver>, i: i32) { if i == 10 { return } thread::spawn(move|| { @@ -1451,8 +1516,8 @@ mod test { #[test] fn test_nested_recv_iter() { - let (tx, rx) = channel::(); - let (total_tx, total_rx) = channel::(); + let (tx, rx) = channel::(); + let (total_tx, total_rx) = channel::(); let _t = thread::spawn(move|| { let mut acc = 0; @@ -1471,7 +1536,7 @@ mod test { #[test] fn test_recv_iter_break() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let (count_tx, count_rx) = channel(); let _t = thread::spawn(move|| { @@ -1496,7 +1561,7 @@ mod test { #[test] fn try_recv_states() { - let (tx1, rx1) = channel::(); + let (tx1, rx1) = channel::(); let (tx2, rx2) = channel::<()>(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -1550,7 +1615,7 @@ mod sync_tests { use thread; use super::*; - pub fn stress_factor() -> uint { + pub fn stress_factor() -> usize { match env::var("RUST_TEST_STRESS") { Ok(val) => val.parse().unwrap(), Err(..) => 1, @@ -1559,20 +1624,20 @@ mod sync_tests { #[test] fn smoke() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); tx.send(1).unwrap(); assert_eq!(rx.recv().unwrap(), 1); } #[test] fn drop_full() { - let (tx, _rx) = sync_channel(1); + let (tx, _rx) = sync_channel::>(1); tx.send(box 1).unwrap(); } #[test] fn smoke_shared() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); tx.send(1).unwrap(); assert_eq!(rx.recv().unwrap(), 1); let tx = tx.clone(); @@ -1582,7 +1647,7 @@ mod sync_tests { #[test] fn smoke_threads() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { tx.send(1).unwrap(); }); @@ -1591,14 +1656,14 @@ mod sync_tests { #[test] fn smoke_port_gone() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(rx); assert!(tx.send(1).is_err()); } #[test] fn smoke_shared_port_gone2() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(rx); let tx2 = tx.clone(); drop(tx); @@ -1607,7 +1672,7 @@ mod sync_tests { #[test] fn port_gone_concurrent() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { rx.recv().unwrap(); }); @@ -1616,7 +1681,7 @@ mod sync_tests { #[test] fn port_gone_concurrent_shared() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); let _t = thread::spawn(move|| { rx.recv().unwrap(); @@ -1626,7 +1691,7 @@ mod sync_tests { #[test] fn smoke_chan_gone() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(tx); assert!(rx.recv().is_err()); } @@ -1642,7 +1707,7 @@ mod sync_tests { #[test] fn chan_gone_concurrent() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); thread::spawn(move|| { tx.send(1).unwrap(); tx.send(1).unwrap(); @@ -1652,7 +1717,7 @@ mod sync_tests { #[test] fn stress() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); thread::spawn(move|| { for _ in 0..10000 { tx.send(1).unwrap(); } }); @@ -1663,9 +1728,9 @@ mod sync_tests { #[test] fn stress_shared() { - static AMT: uint = 1000; - static NTHREADS: uint = 8; - let (tx, rx) = sync_channel::(0); + const AMT: u32 = 1000; + const NTHREADS: u32 = 8; + let (tx, rx) = sync_channel::(0); let (dtx, drx) = sync_channel::<()>(0); thread::spawn(move|| { @@ -1692,21 +1757,21 @@ mod sync_tests { #[test] fn oneshot_single_thread_close_port_first() { // Simple test of closing without sending - let (_tx, rx) = sync_channel::(0); + let (_tx, rx) = sync_channel::(0); drop(rx); } #[test] fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending - let (tx, _rx) = sync_channel::(0); + let (tx, _rx) = sync_channel::(0); drop(tx); } #[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::>(0); + let (tx, rx) = sync_channel::>(0); drop(rx); assert!(tx.send(box 0).is_err()); } @@ -1715,7 +1780,7 @@ mod sync_tests { fn oneshot_single_thread_recv_chan_close() { // Receiving on a closed chan will panic let res = thread::spawn(move|| { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(tx); rx.recv().unwrap(); }).join(); @@ -1725,48 +1790,48 @@ mod sync_tests { #[test] fn oneshot_single_thread_send_then_recv() { - let (tx, rx) = sync_channel::>(1); + let (tx, rx) = sync_channel::>(1); tx.send(box 10).unwrap(); assert!(rx.recv().unwrap() == box 10); } #[test] fn oneshot_single_thread_try_send_open() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(10), Ok(())); assert!(rx.recv().unwrap() == 10); } #[test] fn oneshot_single_thread_try_send_closed() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(rx); assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10))); } #[test] fn oneshot_single_thread_try_send_closed2() { - let (tx, _rx) = sync_channel::(0); + let (tx, _rx) = sync_channel::(0); assert_eq!(tx.try_send(10), Err(TrySendError::Full(10))); } #[test] fn oneshot_single_thread_try_recv_open() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); tx.send(10).unwrap(); assert!(rx.recv() == Ok(10)); } #[test] fn oneshot_single_thread_try_recv_closed() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(tx); assert!(rx.recv().is_err()); } #[test] fn oneshot_single_thread_peek_data() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); tx.send(10).unwrap(); assert_eq!(rx.try_recv(), Ok(10)); @@ -1774,7 +1839,7 @@ mod sync_tests { #[test] fn oneshot_single_thread_peek_close() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(tx); assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected)); @@ -1782,13 +1847,13 @@ mod sync_tests { #[test] fn oneshot_single_thread_peek_open() { - let (_tx, rx) = sync_channel::(0); + let (_tx, rx) = sync_channel::(0); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); } #[test] fn oneshot_multi_task_recv_then_send() { - let (tx, rx) = sync_channel::>(0); + let (tx, rx) = sync_channel::>(0); let _t = thread::spawn(move|| { assert!(rx.recv().unwrap() == box 10); }); @@ -1798,7 +1863,7 @@ mod sync_tests { #[test] fn oneshot_multi_task_recv_then_close() { - let (tx, rx) = sync_channel::>(0); + let (tx, rx) = sync_channel::>(0); let _t = thread::spawn(move|| { drop(tx); }); @@ -1811,7 +1876,7 @@ mod sync_tests { #[test] fn oneshot_multi_thread_close_stress() { for _ in 0..stress_factor() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { drop(rx); }); @@ -1822,7 +1887,7 @@ mod sync_tests { #[test] fn oneshot_multi_thread_send_close_stress() { for _ in 0..stress_factor() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { drop(rx); }); @@ -1835,7 +1900,7 @@ mod sync_tests { #[test] fn oneshot_multi_thread_recv_close_stress() { for _ in 0..stress_factor() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { let res = thread::spawn(move|| { rx.recv().unwrap(); @@ -1853,7 +1918,7 @@ mod sync_tests { #[test] fn oneshot_multi_thread_send_recv_stress() { for _ in 0..stress_factor() { - let (tx, rx) = sync_channel::>(0); + let (tx, rx) = sync_channel::>(0); let _t = thread::spawn(move|| { tx.send(box 10).unwrap(); }); @@ -1864,12 +1929,12 @@ mod sync_tests { #[test] fn stream_send_recv_stress() { for _ in 0..stress_factor() { - let (tx, rx) = sync_channel::>(0); + let (tx, rx) = sync_channel::>(0); send(tx, 0); recv(rx, 0); - fn send(tx: SyncSender>, i: int) { + fn send(tx: SyncSender>, i: i32) { if i == 10 { return } thread::spawn(move|| { @@ -1878,7 +1943,7 @@ mod sync_tests { }); } - fn recv(rx: Receiver>, i: int) { + fn recv(rx: Receiver>, i: i32) { if i == 10 { return } thread::spawn(move|| { @@ -1915,8 +1980,8 @@ mod sync_tests { #[test] fn test_nested_recv_iter() { - let (tx, rx) = sync_channel::(0); - let (total_tx, total_rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); + let (total_tx, total_rx) = sync_channel::(0); let _t = thread::spawn(move|| { let mut acc = 0; @@ -1935,7 +2000,7 @@ mod sync_tests { #[test] fn test_recv_iter_break() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let (count_tx, count_rx) = sync_channel(0); let _t = thread::spawn(move|| { @@ -1960,7 +2025,7 @@ mod sync_tests { #[test] fn try_recv_states() { - let (tx1, rx1) = sync_channel::(1); + let (tx1, rx1) = sync_channel::(1); let (tx2, rx2) = sync_channel::<()>(1); let (tx3, rx3) = sync_channel::<()>(1); let _t = thread::spawn(move|| { @@ -2007,21 +2072,21 @@ mod sync_tests { #[test] fn send1() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { rx.recv().unwrap(); }); assert_eq!(tx.send(1), Ok(())); } #[test] fn send2() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { drop(rx); }); assert!(tx.send(1).is_err()); } #[test] fn send3() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); assert_eq!(tx.send(1), Ok(())); let _t =thread::spawn(move|| { drop(rx); }); assert!(tx.send(1).is_err()); @@ -2029,7 +2094,7 @@ mod sync_tests { #[test] fn send4() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let tx2 = tx.clone(); let (done, donerx) = channel(); let done2 = done.clone(); @@ -2048,20 +2113,20 @@ mod sync_tests { #[test] fn try_send1() { - let (tx, _rx) = sync_channel::(0); + let (tx, _rx) = sync_channel::(0); assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); } #[test] fn try_send2() { - let (tx, _rx) = sync_channel::(1); + let (tx, _rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); } #[test] fn try_send3() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); drop(rx); assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1))); diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs index a2accb128c..9b6c8f4dd9 100644 --- a/src/libstd/sync/mpsc/mpsc_queue.rs +++ b/src/libstd/sync/mpsc/mpsc_queue.rs @@ -44,8 +44,8 @@ pub use self::PopResult::*; use core::prelude::*; +use alloc::boxed; use alloc::boxed::Box; -use core::mem; use core::ptr; use core::cell::UnsafeCell; @@ -77,19 +77,19 @@ pub struct Queue { tail: UnsafeCell<*mut Node>, } -unsafe impl Send for Queue { } -unsafe impl Sync for Queue { } +unsafe impl Send for Queue { } +unsafe impl Sync for Queue { } impl Node { unsafe fn new(v: Option) -> *mut Node { - mem::transmute(box Node { + boxed::into_raw(box Node { next: AtomicPtr::new(ptr::null_mut()), value: v, }) } } -impl Queue { +impl Queue { /// Creates a new queue that is safe to share among multiple producers and /// one consumer. pub fn new() -> Queue { @@ -129,7 +129,7 @@ impl Queue { assert!((*tail).value.is_none()); assert!((*next).value.is_some()); let ret = (*next).value.take().unwrap(); - let _: Box> = mem::transmute(tail); + let _: Box> = Box::from_raw(tail); return Data(ret); } @@ -140,13 +140,13 @@ impl Queue { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Queue { +impl Drop for Queue { fn drop(&mut self) { unsafe { let mut cur = *self.tail.get(); while !cur.is_null() { let next = (*cur).next.load(Ordering::Relaxed); - let _: Box> = mem::transmute(cur); + let _: Box> = Box::from_raw(cur); cur = next; } } @@ -164,7 +164,7 @@ mod tests { #[test] fn test_full() { - let q = Queue::new(); + let q: Queue> = Queue::new(); q.push(box 1); q.push(box 2); } diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs index 55b2caf7c6..c6e8d87a22 100644 --- a/src/libstd/sync/mpsc/oneshot.rs +++ b/src/libstd/sync/mpsc/oneshot.rs @@ -22,7 +22,7 @@ /// /// # Implementation /// -/// Oneshots are implemented around one atomic uint variable. This variable +/// Oneshots are implemented around one atomic usize variable. This variable /// indicates both the state of the port/chan but also contains any tasks /// blocked on the port. All atomic operations happen on this one word. /// @@ -45,9 +45,9 @@ use core::mem; use sync::atomic::{AtomicUsize, Ordering}; // Various states you can find a port in. -const EMPTY: uint = 0; // initial state: no data, no blocked receiver -const DATA: uint = 1; // data ready for receiver to take -const DISCONNECTED: uint = 2; // channel is disconnected OR upgraded +const EMPTY: usize = 0; // initial state: no data, no blocked receiver +const DATA: usize = 1; // data ready for receiver to take +const DISCONNECTED: usize = 2; // channel is disconnected OR upgraded // Any other value represents a pointer to a SignalToken value. The // protocol ensures that when the state moves *to* a pointer, // ownership of the token is given to the packet, and when the state @@ -88,7 +88,7 @@ enum MyUpgrade { GoUp(Receiver), } -impl Packet { +impl Packet { pub fn new() -> Packet { Packet { data: None, @@ -123,7 +123,7 @@ impl Packet { // There is a thread waiting on the other end. We leave the 'DATA' // state inside so it'll pick it up on the other end. ptr => unsafe { - SignalToken::cast_from_uint(ptr).signal(); + SignalToken::cast_from_usize(ptr).signal(); Ok(()) } } @@ -143,7 +143,7 @@ impl Packet { // like we're not empty, then immediately go through to `try_recv`. if self.state.load(Ordering::SeqCst) == EMPTY { let (wait_token, signal_token) = blocking::tokens(); - let ptr = unsafe { signal_token.cast_to_uint() }; + let ptr = unsafe { signal_token.cast_to_usize() }; // race with senders to enter the blocking state if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY { @@ -151,7 +151,7 @@ impl Packet { debug_assert!(self.state.load(Ordering::SeqCst) != EMPTY); } else { // drop the signal token, since we never blocked - drop(unsafe { SignalToken::cast_from_uint(ptr) }); + drop(unsafe { SignalToken::cast_from_usize(ptr) }); } } @@ -220,7 +220,7 @@ impl Packet { DISCONNECTED => { self.upgrade = prev; UpDisconnected } // If someone's waiting, we gotta wake them up - ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) }) + ptr => UpWoke(unsafe { SignalToken::cast_from_usize(ptr) }) } } @@ -230,7 +230,7 @@ impl Packet { // If someone's waiting, we gotta wake them up ptr => unsafe { - SignalToken::cast_from_uint(ptr).signal(); + SignalToken::cast_from_usize(ptr).signal(); } } } @@ -283,15 +283,15 @@ impl Packet { // Attempts to start selection on this port. This can either succeed, fail // because there is data, or fail because there is an upgrade pending. pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult { - let ptr = unsafe { token.cast_to_uint() }; + let ptr = unsafe { token.cast_to_usize() }; match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) { EMPTY => SelSuccess, DATA => { - drop(unsafe { SignalToken::cast_from_uint(ptr) }); + drop(unsafe { SignalToken::cast_from_usize(ptr) }); SelCanceled } DISCONNECTED if self.data.is_some() => { - drop(unsafe { SignalToken::cast_from_uint(ptr) }); + drop(unsafe { SignalToken::cast_from_usize(ptr) }); SelCanceled } DISCONNECTED => { @@ -300,7 +300,7 @@ impl Packet { // propagate upwards whether the upgrade can receive // data GoUp(upgrade) => { - SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade) + SelUpgraded(unsafe { SignalToken::cast_from_usize(ptr) }, upgrade) } // If the other end disconnected without sending an @@ -308,7 +308,7 @@ impl Packet { // disconnected). up => { self.upgrade = up; - drop(unsafe { SignalToken::cast_from_uint(ptr) }); + drop(unsafe { SignalToken::cast_from_usize(ptr) }); SelCanceled } } @@ -360,7 +360,7 @@ impl Packet { // We woke ourselves up from select. ptr => unsafe { - drop(SignalToken::cast_from_uint(ptr)); + drop(SignalToken::cast_from_usize(ptr)); Ok(false) } } @@ -368,7 +368,7 @@ impl Packet { } #[unsafe_destructor] -impl Drop for Packet { +impl Drop for Packet { fn drop(&mut self) { assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED); } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 8fcedd2ab5..b509b3472e 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -24,9 +24,10 @@ //! received values of receivers in a much more natural syntax then usage of the //! `Select` structure directly. //! -//! # Example +//! # Examples //! //! ```rust +//! # #![feature(std_misc)] //! use std::sync::mpsc::channel; //! //! let (tx1, rx1) = channel(); @@ -71,7 +72,7 @@ use sync::mpsc::blocking::{self, SignalToken}; pub struct Select { head: *mut Handle<'static, ()>, tail: *mut Handle<'static, ()>, - next_id: Cell, + next_id: Cell, } impl !marker::Send for Select {} @@ -79,10 +80,10 @@ impl !marker::Send for Select {} /// A handle to a receiver which is currently a member of a `Select` set of /// receivers. This handle is used to keep the receiver in the set as well as /// interact with the underlying receiver. -pub struct Handle<'rx, T:'rx> { +pub struct Handle<'rx, T:Send+'rx> { /// The ID of this handle, used to compare against the return value of /// `Select::wait()` - id: uint, + id: usize, selector: &'rx Select, next: *mut Handle<'static, ()>, prev: *mut Handle<'static, ()>, @@ -119,6 +120,7 @@ impl Select { /// # Examples /// /// ``` + /// # #![feature(std_misc)] /// use std::sync::mpsc::Select; /// /// let select = Select::new(); @@ -134,7 +136,7 @@ impl Select { /// Creates a new handle into this receiver set for a new receiver. Note /// that this does *not* add the receiver to the receiver set, for that you /// must call the `add` method on the handle itself. - pub fn handle<'a, T: Send + 'static>(&'a self, rx: &'a Receiver) -> Handle<'a, T> { + pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver) -> Handle<'a, T> { let id = self.next_id.get(); self.next_id.set(id + 1); Handle { @@ -154,12 +156,12 @@ impl Select { /// the matching `id` will have some sort of event available on it. The /// event could either be that data is available or the corresponding /// channel has been closed. - pub fn wait(&self) -> uint { + pub fn wait(&self) -> usize { self.wait2(true) } /// Helper method for skipping the preflight checks during testing - fn wait2(&self, do_preflight_checks: bool) -> uint { + fn wait2(&self, do_preflight_checks: bool) -> usize { // Note that this is currently an inefficient implementation. We in // theory have knowledge about all receivers in the set ahead of time, // so this method shouldn't really have to iterate over all of them yet @@ -251,10 +253,10 @@ impl Select { fn iter(&self) -> Packets { Packets { cur: self.head } } } -impl<'rx, T: Send + 'static> Handle<'rx, T> { +impl<'rx, T: Send> Handle<'rx, T> { /// Retrieve the id of this handle. #[inline] - pub fn id(&self) -> uint { self.id } + pub fn id(&self) -> usize { self.id } /// Block to receive a value on the underlying receiver, returning `Some` on /// success or `None` if the channel disconnects. This function has the same @@ -322,7 +324,7 @@ impl Drop for Select { } #[unsafe_destructor] -impl<'rx, T: Send + 'static> Drop for Handle<'rx, T> { +impl<'rx, T: Send> Drop for Handle<'rx, T> { fn drop(&mut self) { unsafe { self.remove() } } @@ -369,8 +371,8 @@ mod test { #[test] fn smoke() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); tx1.send(1).unwrap(); select! { foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, @@ -394,11 +396,11 @@ mod test { #[test] fn smoke2() { - let (_tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (_tx3, rx3) = channel::(); - let (_tx4, rx4) = channel::(); - let (tx5, rx5) = channel::(); + let (_tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (_tx3, rx3) = channel::(); + let (_tx4, rx4) = channel::(); + let (tx5, rx5) = channel::(); tx5.send(4).unwrap(); select! { _foo = rx1.recv() => { panic!("1") }, @@ -411,8 +413,8 @@ mod test { #[test] fn closed() { - let (_tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); + let (_tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); drop(tx2); select! { @@ -423,9 +425,9 @@ mod test { #[test] fn unblocks() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::(); + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (tx3, rx3) = channel::(); let _t = thread::spawn(move|| { for _ in 0..20 { thread::yield_now(); } @@ -447,8 +449,8 @@ mod test { #[test] fn both_ready() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -473,9 +475,9 @@ mod test { #[test] fn stress() { - static AMT: int = 10000; - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); + const AMT: i32 = 10000; + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -500,8 +502,8 @@ mod test { #[test] fn cloning() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -522,8 +524,8 @@ mod test { #[test] fn cloning2() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -716,7 +718,7 @@ mod test { #[test] fn sync1() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); tx.send(1).unwrap(); select! { n = rx.recv() => { assert_eq!(n.unwrap(), 1); } @@ -725,7 +727,7 @@ mod test { #[test] fn sync2() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { for _ in 0..100 { thread::yield_now() } tx.send(1).unwrap(); @@ -737,8 +739,8 @@ mod test { #[test] fn sync3() { - let (tx1, rx1) = sync_channel::(0); - let (tx2, rx2): (Sender, Receiver) = channel(); + let (tx1, rx1) = sync_channel::(0); + let (tx2, rx2): (Sender, Receiver) = channel(); let _t = thread::spawn(move|| { tx1.send(1).unwrap(); }); let _t = thread::spawn(move|| { tx2.send(2).unwrap(); }); select! { diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs index bc9c73585c..5c1610bdc3 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -64,7 +64,7 @@ pub enum Failure { Disconnected, } -impl Packet { +impl Packet { // Creation of a packet *must* be followed by a call to postinit_lock // and later by inherit_blocker pub fn new() -> Packet { @@ -101,7 +101,7 @@ impl Packet { token.map(|token| { assert_eq!(self.cnt.load(Ordering::SeqCst), 0); assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); - self.to_wake.store(unsafe { token.cast_to_uint() }, Ordering::SeqCst); + self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst); self.cnt.store(-1, Ordering::SeqCst); // This store is a little sketchy. What's happening here is that @@ -241,7 +241,7 @@ impl Packet { // Returns true if blocking should proceed. fn decrement(&mut self, token: SignalToken) -> StartResult { assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); - let ptr = unsafe { token.cast_to_uint() }; + let ptr = unsafe { token.cast_to_usize() }; self.to_wake.store(ptr, Ordering::SeqCst); let steals = self.steals; @@ -258,7 +258,7 @@ impl Packet { } self.to_wake.store(0, Ordering::SeqCst); - drop(unsafe { SignalToken::cast_from_uint(ptr) }); + drop(unsafe { SignalToken::cast_from_usize(ptr) }); Abort } @@ -380,7 +380,7 @@ impl Packet { let ptr = self.to_wake.load(Ordering::SeqCst); self.to_wake.store(0, Ordering::SeqCst); assert!(ptr != 0); - unsafe { SignalToken::cast_from_uint(ptr) } + unsafe { SignalToken::cast_from_usize(ptr) } } //////////////////////////////////////////////////////////////////////////// @@ -398,7 +398,7 @@ impl Packet { } // increment the count on the channel (used for selection) - fn bump(&mut self, amt: int) -> int { + fn bump(&mut self, amt: isize) -> isize { match self.cnt.fetch_add(amt, Ordering::SeqCst) { DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); @@ -474,7 +474,7 @@ impl Packet { } #[unsafe_destructor] -impl Drop for Packet { +impl Drop for Packet { fn drop(&mut self) { // Note that this load is not only an assert for correctness about // disconnection, but also a proper fence before the read of diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index e1a8970650..c75ac13080 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -37,8 +37,8 @@ use core::prelude::*; +use alloc::boxed; use alloc::boxed::Box; -use core::mem; use core::ptr; use core::cell::UnsafeCell; @@ -69,19 +69,19 @@ pub struct Queue { // Cache maintenance fields. Additions and subtractions are stored // separately in order to allow them to use nonatomic addition/subtraction. - cache_bound: uint, + cache_bound: usize, cache_additions: AtomicUsize, cache_subtractions: AtomicUsize, } -unsafe impl Send for Queue { } +unsafe impl Send for Queue { } -unsafe impl Sync for Queue { } +unsafe impl Sync for Queue { } -impl Node { +impl Node { fn new() -> *mut Node { unsafe { - mem::transmute(box Node { + boxed::into_raw(box Node { value: None, next: AtomicPtr::new(ptr::null_mut::>()), }) @@ -89,7 +89,7 @@ impl Node { } } -impl Queue { +impl Queue { /// Creates a new queue. /// /// This is unsafe as the type system doesn't enforce a single @@ -107,7 +107,7 @@ impl Queue { /// cache (if desired). If the value is 0, then the cache has /// no bound. Otherwise, the cache will never grow larger than /// `bound` (although the queue itself could be much larger. - pub unsafe fn new(bound: uint) -> Queue { + pub unsafe fn new(bound: usize) -> Queue { let n1 = Node::new(); let n2 = Node::new(); (*n1).next.store(n2, Ordering::Relaxed); @@ -200,7 +200,7 @@ impl Queue { .next.store(next, Ordering::Relaxed); // We have successfully erased all references to 'tail', so // now we can safely drop it. - let _: Box> = mem::transmute(tail); + let _: Box> = Box::from_raw(tail); } } return ret; @@ -227,13 +227,13 @@ impl Queue { } #[unsafe_destructor] -impl Drop for Queue { +impl Drop for Queue { fn drop(&mut self) { unsafe { let mut cur = *self.first.get(); while !cur.is_null() { let next = (*cur).next.load(Ordering::Relaxed); - let _n: Box> = mem::transmute(cur); + let _n: Box> = Box::from_raw(cur); cur = next; } } @@ -289,7 +289,7 @@ mod test { #[test] fn drop_full() { unsafe { - let q = Queue::new(0); + let q: Queue> = Queue::new(0); q.push(box 1); q.push(box 2); } @@ -319,7 +319,7 @@ mod test { stress_bound(1); } - unsafe fn stress_bound(bound: uint) { + unsafe fn stress_bound(bound: usize) { let q = Arc::new(Queue::new(bound)); let (tx, rx) = channel(); diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs index a194c99669..f0363fae84 100644 --- a/src/libstd/sync/mpsc/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -43,7 +43,7 @@ pub struct Packet { queue: spsc::Queue>, // internal queue for all message cnt: AtomicIsize, // How many items are on this channel - steals: int, // How many times has a port received without blocking? + steals: isize, // How many times has a port received without blocking? to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up port_dropped: AtomicBool, // flag if the channel has been destroyed. @@ -74,7 +74,7 @@ enum Message { GoUp(Receiver), } -impl Packet { +impl Packet { pub fn new() -> Packet { Packet { queue: unsafe { spsc::Queue::new(128) }, @@ -146,7 +146,7 @@ impl Packet { let ptr = self.to_wake.load(Ordering::SeqCst); self.to_wake.store(0, Ordering::SeqCst); assert!(ptr != 0); - unsafe { SignalToken::cast_from_uint(ptr) } + unsafe { SignalToken::cast_from_usize(ptr) } } // Decrements the count on the channel for a sleeper, returning the sleeper @@ -154,7 +154,7 @@ impl Packet { // steals into account. fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> { assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); - let ptr = unsafe { token.cast_to_uint() }; + let ptr = unsafe { token.cast_to_usize() }; self.to_wake.store(ptr, Ordering::SeqCst); let steals = self.steals; @@ -171,7 +171,7 @@ impl Packet { } self.to_wake.store(0, Ordering::SeqCst); - Err(unsafe { SignalToken::cast_from_uint(ptr) }) + Err(unsafe { SignalToken::cast_from_usize(ptr) }) } pub fn recv(&mut self) -> Result> { @@ -350,7 +350,7 @@ impl Packet { } // increment the count on the channel (used for selection) - fn bump(&mut self, amt: int) -> int { + fn bump(&mut self, amt: isize) -> isize { match self.cnt.fetch_add(amt, Ordering::SeqCst) { DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); @@ -472,7 +472,7 @@ impl Packet { } #[unsafe_destructor] -impl Drop for Packet { +impl Drop for Packet { fn drop(&mut self) { // Note that this load is not only an assert for correctness about // disconnection, but also a proper fence before the read of diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index ae96a2491d..6221ca59b5 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -55,16 +55,16 @@ pub struct Packet { lock: Mutex>, } -unsafe impl Send for Packet { } +unsafe impl Send for Packet { } -unsafe impl Sync for Packet { } +unsafe impl Sync for Packet { } struct State { disconnected: bool, // Is the channel disconnected yet? queue: Queue, // queue of senders waiting to send data blocker: Blocker, // currently blocked task on this channel buf: Buffer, // storage for buffered messages - cap: uint, // capacity of this channel + cap: usize, // capacity of this channel /// A curious flag used to indicate whether a sender failed or succeeded in /// blocking. This is used to transmit information back to the task that it @@ -75,7 +75,7 @@ struct State { canceled: Option<&'static mut bool>, } -unsafe impl Send for State {} +unsafe impl Send for State {} /// Possible flavors of threads who can be blocked on this channel. enum Blocker { @@ -101,8 +101,8 @@ unsafe impl Send for Node {} /// A simple ring-buffer struct Buffer { buf: Vec>, - start: uint, - size: uint, + start: usize, + size: usize, } #[derive(Debug)] @@ -113,10 +113,10 @@ pub enum Failure { /// Atomically blocks the current thread, placing it into `slot`, unlocking `lock` /// in the meantime. This re-locks the mutex upon returning. -fn wait<'a, 'b, T: Send + 'static>(lock: &'a Mutex>, - mut guard: MutexGuard<'b, State>, - f: fn(SignalToken) -> Blocker) - -> MutexGuard<'a, State> +fn wait<'a, 'b, T>(lock: &'a Mutex>, + mut guard: MutexGuard<'b, State>, + f: fn(SignalToken) -> Blocker) + -> MutexGuard<'a, State> { let (wait_token, signal_token) = blocking::tokens(); match mem::replace(&mut guard.blocker, f(signal_token)) { @@ -136,8 +136,8 @@ fn wakeup(token: SignalToken, guard: MutexGuard>) { token.signal(); } -impl Packet { - pub fn new(cap: uint) -> Packet { +impl Packet { + pub fn new(cap: usize) -> Packet { Packet { channels: AtomicUsize::new(1), lock: Mutex::new(State { @@ -412,7 +412,7 @@ impl Packet { } #[unsafe_destructor] -impl Drop for Packet { +impl Drop for Packet { fn drop(&mut self) { assert_eq!(self.channels.load(Ordering::SeqCst), 0); let mut guard = self.lock.lock().unwrap(); @@ -442,8 +442,8 @@ impl Buffer { result.take().unwrap() } - fn size(&self) -> uint { self.size } - fn cap(&self) -> uint { self.buf.len() } + fn size(&self) -> usize { self.size } + fn cap(&self) -> usize { self.buf.len() } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index e77c4d2e5e..16e7f26541 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -15,6 +15,7 @@ use marker; use ops::{Deref, DerefMut}; use sync::poison::{self, TryLockError, TryLockResult, LockResult}; use sys_common::mutex as sys; +use fmt; /// A mutual exclusion primitive useful for protecting shared data /// @@ -39,18 +40,18 @@ use sys_common::mutex as sys; /// among threads to ensure that a possibly invalid invariant is not witnessed. /// /// A poisoned mutex, however, does not prevent all access to the underlying -/// data. The `PoisonError` type has an `into_guard` method which will return +/// data. The `PoisonError` type has an `into_inner` method which will return /// the guard that would have otherwise been returned on a successful lock. This /// allows access to the data, despite the lock being poisoned. /// /// # Examples /// -/// ```rust +/// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// use std::sync::mpsc::channel; /// -/// const N: uint = 10; +/// const N: usize = 10; /// /// // Spawn a few threads to increment a shared variable (non-atomically), and /// // let the main thread know once all increments are done. @@ -83,7 +84,8 @@ use sys_common::mutex as sys; /// /// To recover from a poisoned mutex: /// -/// ```rust +/// ``` +/// # #![feature(std_misc)] /// use std::sync::{Arc, Mutex}; /// use std::thread; /// @@ -104,7 +106,7 @@ use sys_common::mutex as sys; /// // pattern matched on to return the underlying guard on both branches. /// let mut guard = match lock.lock() { /// Ok(guard) => guard, -/// Err(poisoned) => poisoned.into_guard(), +/// Err(poisoned) => poisoned.into_inner(), /// }; /// /// *guard += 1; @@ -120,9 +122,11 @@ pub struct Mutex { data: UnsafeCell, } -unsafe impl Send for Mutex { } +// these are the only places where `T: Send` matters; all other +// functionality works fine on a single thread. +unsafe impl Send for Mutex { } -unsafe impl Sync for Mutex { } +unsafe impl Sync for Mutex { } /// The static mutex type is provided to allow for static allocation of mutexes. /// @@ -132,9 +136,10 @@ unsafe impl Sync for Mutex { } /// to a `Mutex`, a `destroy` method. This method is unsafe to call, and /// documentation can be found directly on the method. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` +/// # #![feature(std_misc)] /// use std::sync::{StaticMutex, MUTEX_INIT}; /// /// static LOCK: StaticMutex = MUTEX_INIT; @@ -152,8 +157,6 @@ pub struct StaticMutex { poison: poison::Flag, } -unsafe impl Sync for StaticMutex {} - /// An RAII implementation of a "scoped lock" of a mutex. When this structure is /// dropped (falls out of scope), the lock will be unlocked. /// @@ -180,7 +183,7 @@ pub const MUTEX_INIT: StaticMutex = StaticMutex { poison: poison::FLAG_INIT, }; -impl Mutex { +impl Mutex { /// Creates a new mutex in an unlocked state ready for use. #[stable(feature = "rust1", since = "1.0.0")] pub fn new(t: T) -> Mutex { @@ -243,7 +246,7 @@ impl Mutex { #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Mutex { +impl Drop for Mutex { fn drop(&mut self) { // This is actually safe b/c we know that there is no further usage of // this mutex (it's up to the user to arrange for a mutex to get @@ -252,6 +255,19 @@ impl Drop for Mutex { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Mutex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.try_lock() { + Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard), + Err(TryLockError::Poisoned(err)) => { + write!(f, "Mutex {{ data: Poisoned({:?}) }}", **err.get_ref()) + }, + Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ }}") + } + } +} + struct Dummy(UnsafeCell<()>); unsafe impl Sync for Dummy {} static DUMMY: Dummy = Dummy(UnsafeCell { value: () }); @@ -352,9 +368,9 @@ mod test { use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar}; use thread; - struct Packet(Arc<(Mutex, Condvar)>); + struct Packet(Arc<(Mutex, Condvar)>); - unsafe impl Send for Packet {} + unsafe impl Send for Packet {} unsafe impl Sync for Packet {} #[test] @@ -377,9 +393,9 @@ mod test { #[test] fn lots_and_lots() { static M: StaticMutex = MUTEX_INIT; - static mut CNT: uint = 0; - static J: uint = 1000; - static K: uint = 3; + static mut CNT: u32 = 0; + const J: u32 = 1000; + const K: u32 = 3; fn inc() { for _ in 0..J { @@ -501,7 +517,7 @@ mod test { let arc2 = arc.clone(); let _ = thread::spawn(move|| -> () { struct Unwinder { - i: Arc>, + i: Arc>, } impl Drop for Unwinder { fn drop(&mut self) { diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 97f985e21e..258cf1d38a 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -13,10 +13,9 @@ //! This primitive is meant to be used to run one-time initialization. An //! example use case would be for initializing an FFI library. +use prelude::v1::*; + use isize; -use marker::Sync; -use mem::drop; -use ops::FnOnce; use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT}; use sync::{StaticMutex, MUTEX_INIT}; @@ -25,9 +24,9 @@ use sync::{StaticMutex, MUTEX_INIT}; /// functionality. This type can only be constructed with the `ONCE_INIT` /// value. /// -/// # Example +/// # Examples /// -/// ```rust +/// ``` /// use std::sync::{Once, ONCE_INIT}; /// /// static START: Once = ONCE_INIT; @@ -43,8 +42,6 @@ pub struct Once { lock_cnt: AtomicIsize, } -unsafe impl Sync for Once {} - /// Initialization value for static `Once` values. #[stable(feature = "rust1", since = "1.0.0")] pub const ONCE_INIT: Once = Once { diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index 32c8150ba4..347cd0b464 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -11,11 +11,17 @@ use prelude::v1::*; use cell::UnsafeCell; -use error::{Error, FromError}; +use error::{Error}; use fmt; use thread; pub struct Flag { failed: UnsafeCell } + +// This flag is only ever accessed with a lock previously held. Note that this +// a totally private structure. +unsafe impl Send for Flag {} +unsafe impl Sync for Flag {} + pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } }; impl Flag { @@ -99,11 +105,11 @@ impl fmt::Debug for PoisonError { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for PoisonError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) + "poisoned lock: another task failed inside".fmt(f) } } -impl Error for PoisonError { +impl Error for PoisonError { fn description(&self) -> &str { "poisoned lock: another task failed inside" } @@ -116,12 +122,6 @@ impl PoisonError { PoisonError { guard: guard } } - /// Consumes this error indicating that a lock is poisoned, returning the - /// underlying guard to allow access regardless. - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", reason = "renamed to into_inner")] - pub fn into_guard(self) -> T { self.guard } - /// Consumes this error indicating that a lock is poisoned, returning the /// underlying guard to allow access regardless. #[unstable(feature = "std_misc")] @@ -138,8 +138,8 @@ impl PoisonError { pub fn get_mut(&mut self) -> &mut T { &mut self.guard } } -impl FromError> for TryLockError { - fn from_error(err: PoisonError) -> TryLockError { +impl From> for TryLockError { + fn from(err: PoisonError) -> TryLockError { TryLockError::Poisoned(err) } } @@ -155,13 +155,13 @@ impl fmt::Debug for TryLockError { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for TryLockError { +impl fmt::Display for TryLockError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } } -impl Error for TryLockError { +impl Error for TryLockError { fn description(&self) -> &str { match *self { TryLockError::Poisoned(ref p) => p.description(), diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index cd833b1786..d70350bc7d 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -15,6 +15,7 @@ use marker; use ops::{Deref, DerefMut}; use sync::poison::{self, LockResult, TryLockError, TryLockResult}; use sys_common::rwlock as sys; +use fmt; /// A reader-writer lock /// @@ -64,8 +65,8 @@ pub struct RwLock { data: UnsafeCell, } -unsafe impl Send for RwLock {} -unsafe impl Sync for RwLock {} +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} /// Structure representing a statically allocated RwLock. /// @@ -73,9 +74,10 @@ unsafe impl Sync for RwLock {} /// automatic global access as well as lazy initialization. The internal /// resources of this RwLock, however, must be manually deallocated. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(std_misc)] /// use std::sync::{StaticRwLock, RW_LOCK_INIT}; /// /// static LOCK: StaticRwLock = RW_LOCK_INIT; @@ -97,9 +99,6 @@ pub struct StaticRwLock { poison: poison::Flag, } -unsafe impl Send for StaticRwLock {} -unsafe impl Sync for StaticRwLock {} - /// Constant initialization for a statically-initialized rwlock. #[unstable(feature = "std_misc", reason = "may be merged with RwLock in the future")] @@ -131,7 +130,7 @@ pub struct RwLockWriteGuard<'a, T: 'a> { impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {} -impl RwLock { +impl RwLock { /// Creates a new instance of an `RwLock` which is unlocked. /// /// # Examples @@ -258,6 +257,19 @@ impl Drop for RwLock { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for RwLock { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.try_read() { + Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", *guard), + Err(TryLockError::Poisoned(err)) => { + write!(f, "RwLock {{ data: Poisoned({:?}) }}", **err.get_ref()) + }, + Err(TryLockError::WouldBlock) => write!(f, "RwLock {{ }}") + } + } +} + struct Dummy(UnsafeCell<()>); unsafe impl Sync for Dummy {} static DUMMY: Dummy = Dummy(UnsafeCell { value: () }); @@ -425,8 +437,8 @@ mod tests { #[test] fn frob() { static R: StaticRwLock = RW_LOCK_INIT; - static N: usize = 10; - static M: usize = 1000; + const N: usize = 10; + const M: usize = 1000; let (tx, rx) = channel::<()>(); for _ in 0..N { @@ -539,7 +551,7 @@ mod tests { let arc2 = arc.clone(); let _ = thread::spawn(move|| -> () { struct Unwinder { - i: Arc>, + i: Arc>, } impl Drop for Unwinder { fn drop(&mut self) { diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs index 410e1c11bb..be521095aa 100644 --- a/src/libstd/sync/semaphore.rs +++ b/src/libstd/sync/semaphore.rs @@ -22,9 +22,10 @@ use sync::{Mutex, Condvar}; /// until the counter is positive, and each release will increment the counter /// and unblock any threads if necessary. /// -/// # Example +/// # Examples /// /// ``` +/// # #![feature(std_misc)] /// use std::sync::Semaphore; /// /// // Create a semaphore that represents 5 resources @@ -43,7 +44,7 @@ use sync::{Mutex, Condvar}; /// sem.release(); /// ``` pub struct Semaphore { - lock: Mutex, + lock: Mutex, cvar: Condvar, } @@ -59,7 +60,7 @@ impl Semaphore { /// The count specified can be thought of as a number of resources, and a /// call to `acquire` or `access` will block until at least one resource is /// available. It is valid to initialize a semaphore with a negative count. - pub fn new(count: int) -> Semaphore { + pub fn new(count: isize) -> Semaphore { Semaphore { lock: Mutex::new(count), cvar: Condvar::new(), diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs deleted file mode 100644 index a45048be24..0000000000 --- a/src/libstd/sync/task_pool.rs +++ /dev/null @@ -1,214 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Abstraction of a thread pool for basic parallelism. - -#![unstable(feature = "std_misc", - reason = "the semantics of a failing task and whether a thread is \ - re-attached to a thread pool are somewhat unclear, and the \ - utility of this type in `std::sync` is questionable with \ - respect to the jobs of other primitives")] - -use core::prelude::*; - -use sync::{Arc, Mutex}; -use sync::mpsc::{channel, Sender, Receiver}; -use thread; -use thunk::Thunk; - -struct Sentinel<'a> { - jobs: &'a Arc>>>, - active: bool -} - -impl<'a> Sentinel<'a> { - fn new(jobs: &'a Arc>>>) -> Sentinel<'a> { - Sentinel { - jobs: jobs, - active: true - } - } - - // Cancel and destroy this sentinel. - fn cancel(mut self) { - self.active = false; - } -} - -#[unsafe_destructor] -impl<'a> Drop for Sentinel<'a> { - fn drop(&mut self) { - if self.active { - spawn_in_pool(self.jobs.clone()) - } - } -} - -/// A thread pool used to execute functions in parallel. -/// -/// Spawns `n` worker threads and replenishes the pool if any worker threads -/// panic. -/// -/// # Example -/// -/// ```rust -/// use std::sync::TaskPool; -/// use std::iter::AdditiveIterator; -/// use std::sync::mpsc::channel; -/// -/// let pool = TaskPool::new(4); -/// -/// let (tx, rx) = channel(); -/// for _ in 0..8 { -/// let tx = tx.clone(); -/// pool.execute(move|| { -/// tx.send(1_u32).unwrap(); -/// }); -/// } -/// -/// assert_eq!(rx.iter().take(8).sum(), 8); -/// ``` -pub struct TaskPool { - // How the threadpool communicates with subthreads. - // - // This is the only such Sender, so when it is dropped all subthreads will - // quit. - jobs: Sender> -} - -impl TaskPool { - /// Spawns a new thread pool with `threads` threads. - /// - /// # Panics - /// - /// This function will panic if `threads` is 0. - pub fn new(threads: uint) -> TaskPool { - assert!(threads >= 1); - - let (tx, rx) = channel::(); - let rx = Arc::new(Mutex::new(rx)); - - // Threadpool threads - for _ in 0..threads { - spawn_in_pool(rx.clone()); - } - - TaskPool { jobs: tx } - } - - /// Executes the function `job` on a thread in the pool. - pub fn execute(&self, job: F) - where F : FnOnce(), F : Send + 'static - { - self.jobs.send(Thunk::new(job)).unwrap(); - } -} - -fn spawn_in_pool(jobs: Arc>>>) { - thread::spawn(move || { - // Will spawn a new thread on panic unless it is cancelled. - let sentinel = Sentinel::new(&jobs); - - loop { - let message = { - // Only lock jobs for the time it takes - // to get a job, not run it. - let lock = jobs.lock().unwrap(); - lock.recv() - }; - - match message { - Ok(job) => job.invoke(()), - - // The Taskpool was dropped. - Err(..) => break - } - } - - sentinel.cancel(); - }); -} - -#[cfg(test)] -mod test { - use prelude::v1::*; - use super::*; - use sync::mpsc::channel; - - const TEST_TASKS: uint = 4; - - #[test] - fn test_works() { - use iter::AdditiveIterator; - - let pool = TaskPool::new(TEST_TASKS); - - let (tx, rx) = channel(); - for _ in 0..TEST_TASKS { - let tx = tx.clone(); - pool.execute(move|| { - tx.send(1).unwrap(); - }); - } - - assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); - } - - #[test] - #[should_fail] - fn test_zero_tasks_panic() { - TaskPool::new(0); - } - - #[test] - fn test_recovery_from_subtask_panic() { - use iter::AdditiveIterator; - - let pool = TaskPool::new(TEST_TASKS); - - // Panic all the existing threads. - for _ in 0..TEST_TASKS { - pool.execute(move|| -> () { panic!() }); - } - - // Ensure new threads were spawned to compensate. - let (tx, rx) = channel(); - for _ in 0..TEST_TASKS { - let tx = tx.clone(); - pool.execute(move|| { - tx.send(1).unwrap(); - }); - } - - assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS); - } - - #[test] - fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() { - use sync::{Arc, Barrier}; - - let pool = TaskPool::new(TEST_TASKS); - let waiter = Arc::new(Barrier::new(TEST_TASKS + 1)); - - // Panic all the existing threads in a bit. - for _ in 0..TEST_TASKS { - let waiter = waiter.clone(); - pool.execute(move|| { - waiter.wait(); - panic!(); - }); - } - - drop(pool); - - // Kick off the failure. - waiter.wait(); - } -} diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index 50a9f20479..cd118b3c9e 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -9,14 +9,15 @@ // except according to those terms. use prelude::v1::*; +use io::prelude::*; -use old_io::IoResult; +use io; #[cfg(target_pointer_width = "64")] -pub const HEX_WIDTH: uint = 18; +pub const HEX_WIDTH: usize = 18; #[cfg(target_pointer_width = "32")] -pub const HEX_WIDTH: uint = 10; +pub const HEX_WIDTH: usize = 10; // All rust symbols are in theory lists of "::"-separated identifiers. Some // assemblers, however, can't handle these characters in symbol names. To get @@ -35,7 +36,7 @@ pub const HEX_WIDTH: uint = 10; // Note that this demangler isn't quite as fancy as it could be. We have lots // of other information in our symbols like hashes, version, type information, // etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { +pub fn demangle(writer: &mut Write, s: &str) -> io::Result<()> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-rust // symbols because we could have any function in the backtrace. @@ -56,7 +57,7 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { let mut i = 0; for c in chars.by_ref() { if c.is_numeric() { - i = i * 10 + c as uint - '0' as uint; + i = i * 10 + c as usize - '0' as usize; } else { break } @@ -72,12 +73,12 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { // Alright, let's do this. if !valid { - try!(writer.write_str(s)); + try!(writer.write_all(s.as_bytes())); } else { let mut first = true; while inner.len() > 0 { if !first { - try!(writer.write_str("::")); + try!(writer.write_all(b"::")); } else { first = false; } @@ -85,7 +86,7 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { while rest.char_at(0).is_numeric() { rest = &rest[1..]; } - let i: uint = inner[.. (inner.len() - rest.len())].parse().unwrap(); + let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap(); inner = &rest[i..]; rest = &rest[..i]; while rest.len() > 0 { @@ -93,11 +94,11 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { macro_rules! demangle { ($($pat:expr, => $demangled:expr),*) => ({ $(if rest.starts_with($pat) { - try!(writer.write_str($demangled)); + try!(writer.write_all($demangled)); rest = &rest[$pat.len()..]; } else)* { - try!(writer.write_str(rest)); + try!(writer.write_all(rest.as_bytes())); break; } @@ -106,29 +107,29 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { // see src/librustc/back/link.rs for these mappings demangle! ( - "$SP$", => "@", - "$BP$", => "*", - "$RF$", => "&", - "$LT$", => "<", - "$GT$", => ">", - "$LP$", => "(", - "$RP$", => ")", - "$C$", => ",", + "$SP$", => b"@", + "$BP$", => b"*", + "$RF$", => b"&", + "$LT$", => b"<", + "$GT$", => b">", + "$LP$", => b"(", + "$RP$", => b")", + "$C$", => b",", // in theory we can demangle any Unicode code point, but // for simplicity we just catch the common ones. - "$u7e$", => "~", - "$u20$", => " ", - "$u27$", => "'", - "$u5b$", => "[", - "$u5d$", => "]" + "$u7e$", => b"~", + "$u20$", => b" ", + "$u27$", => b"'", + "$u5b$", => b"[", + "$u5d$", => b"]" ) } else { let idx = match rest.find('$') { None => rest.len(), Some(i) => i, }; - try!(writer.write_str(&rest[..idx])); + try!(writer.write_all(rest[..idx].as_bytes())); rest = &rest[idx..]; } } diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs index dc1ae85efe..34a58f6c83 100644 --- a/src/libstd/sys/common/helper_thread.rs +++ b/src/libstd/sys/common/helper_thread.rs @@ -22,9 +22,8 @@ use prelude::v1::*; +use boxed; use cell::UnsafeCell; -use mem; -use ptr; use rt; use sync::{StaticMutex, StaticCondvar}; use sync::mpsc::{channel, Sender, Receiver}; @@ -39,7 +38,7 @@ use thread; /// /// The fields of this helper are all public, but they should not be used, this /// is for static initialization. -pub struct Helper { +pub struct Helper { /// Internal lock which protects the remaining fields pub lock: StaticMutex, pub cond: StaticCondvar, @@ -52,7 +51,7 @@ pub struct Helper { pub chan: UnsafeCell<*mut Sender>, /// OS handle used to wake up a blocked helper thread - pub signal: UnsafeCell, + pub signal: UnsafeCell, /// Flag if this helper thread has booted and been initialized yet. pub initialized: UnsafeCell, @@ -70,6 +69,17 @@ struct RaceBox(helper_signal::signal); unsafe impl Send for RaceBox {} unsafe impl Sync for RaceBox {} +macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( + static $name: Helper<$m> = Helper { + lock: ::sync::MUTEX_INIT, + cond: ::sync::CONDVAR_INIT, + chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, + signal: ::cell::UnsafeCell { value: 0 }, + initialized: ::cell::UnsafeCell { value: false }, + shutdown: ::cell::UnsafeCell { value: false }, + }; +) } + impl Helper { /// Lazily boots a helper thread, becoming a no-op if the helper has already /// been spawned. @@ -86,11 +96,11 @@ impl Helper { { unsafe { let _guard = self.lock.lock().unwrap(); - if !*self.initialized.get() { + if *self.chan.get() as usize == 0 { let (tx, rx) = channel(); - *self.chan.get() = mem::transmute(box tx); + *self.chan.get() = boxed::into_raw(box tx); let (receive, send) = helper_signal::new(); - *self.signal.get() = send as uint; + *self.signal.get() = send as usize; let receive = RaceBox(receive); @@ -102,8 +112,10 @@ impl Helper { self.cond.notify_one() }); - rt::at_exit(move|| { self.shutdown() }); + let _ = rt::at_exit(move || { self.shutdown() }); *self.initialized.get() = true; + } else if *self.chan.get() as usize == 1 { + panic!("cannot continue usage after shutdown"); } } } @@ -118,7 +130,9 @@ impl Helper { // Must send and *then* signal to ensure that the child receives the // message. Otherwise it could wake up and go to sleep before we // send the message. - assert!(!self.chan.get().is_null()); + assert!(*self.chan.get() as usize != 0); + assert!(*self.chan.get() as usize != 1, + "cannot continue usage after shutdown"); (**self.chan.get()).send(msg).unwrap(); helper_signal::signal(*self.signal.get() as helper_signal::signal); } @@ -131,9 +145,13 @@ impl Helper { // returns. let mut guard = self.lock.lock().unwrap(); + let ptr = *self.chan.get(); + if ptr as usize == 1 { + panic!("cannot continue usage after shutdown"); + } // Close the channel by destroying it - let chan: Box> = mem::transmute(*self.chan.get()); - *self.chan.get() = ptr::null_mut(); + let chan = Box::from_raw(*self.chan.get()); + *self.chan.get() = 1 as *mut Sender; drop(chan); helper_signal::signal(*self.signal.get() as helper_signal::signal); diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index 5054f72ea9..d2e2f1044d 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -9,19 +9,23 @@ // except according to those terms. #![allow(missing_docs)] -#![allow(dead_code)] use old_io::{self, IoError, IoResult}; use prelude::v1::*; use sys::{last_error, retry}; use ffi::CString; +#[allow(deprecated)] // Int use num::Int; + +#[allow(deprecated)] use old_path::BytesContainer; + use collections; +#[macro_use] pub mod helper_thread; + pub mod backtrace; pub mod condvar; -pub mod helper_thread; pub mod mutex; pub mod net; pub mod net2; @@ -34,6 +38,7 @@ pub mod wtf8; // common error constructors +#[allow(deprecated)] pub fn eof() -> IoError { IoError { kind: old_io::EndOfFile, @@ -42,6 +47,7 @@ pub fn eof() -> IoError { } } +#[allow(deprecated)] pub fn timeout(desc: &'static str) -> IoError { IoError { kind: old_io::TimedOut, @@ -50,7 +56,8 @@ pub fn timeout(desc: &'static str) -> IoError { } } -pub fn short_write(n: uint, desc: &'static str) -> IoError { +#[allow(deprecated)] +pub fn short_write(n: usize, desc: &'static str) -> IoError { IoError { kind: if n == 0 { old_io::TimedOut } else { old_io::ShortWrite(n) }, desc: desc, @@ -58,6 +65,7 @@ pub fn short_write(n: uint, desc: &'static str) -> IoError { } } +#[allow(deprecated)] pub fn unimpl() -> IoError { IoError { kind: old_io::IoUnavailable, @@ -67,6 +75,7 @@ pub fn unimpl() -> IoError { } // unix has nonzero values as errors +#[allow(deprecated)] pub fn mkerr_libc(ret: T) -> IoResult<()> { if ret != Int::zero() { Err(last_error()) @@ -76,7 +85,7 @@ pub fn mkerr_libc(ret: T) -> IoResult<()> { } pub fn keep_going(data: &[u8], mut f: F) -> i64 where - F: FnMut(*const u8, uint) -> i64, + F: FnMut(*const u8, usize) -> i64, { let origamt = data.len(); let mut data = data.as_ptr(); @@ -86,8 +95,8 @@ pub fn keep_going(data: &[u8], mut f: F) -> i64 where if ret == 0 { break } else if ret != -1 { - amt -= ret as uint; - data = unsafe { data.offset(ret as int) }; + amt -= ret as usize; + data = unsafe { data.offset(ret as isize) }; } else { return ret; } @@ -120,12 +129,13 @@ pub trait FromInner { } #[doc(hidden)] +#[allow(deprecated)] pub trait ProcessConfig { fn program(&self) -> &CString; fn args(&self) -> &[CString]; fn env(&self) -> Option<&collections::HashMap>; fn cwd(&self) -> Option<&CString>; - fn uid(&self) -> Option; - fn gid(&self) -> Option; + fn uid(&self) -> Option; + fn gid(&self) -> Option; fn detach(&self) -> bool; } diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index e2ac5ac24f..fc21effb45 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use self::SocketStatus::*; use self::InAddr::*; @@ -24,7 +26,9 @@ 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}; -use sync::{Arc, Mutex, MutexGuard}; +use sync::{Arc, Mutex}; +#[cfg(not(target_os = "linux"))] +use sync::MutexGuard; use sys_common::{self, keep_going, short_write, timeout}; use cmp; use old_io; @@ -111,9 +115,9 @@ pub fn socket(addr: SocketAddr, ty: libc::c_int) -> IoResult { Ipv4Addr(..) => libc::AF_INET, Ipv6Addr(..) => libc::AF_INET6, }; - match libc::socket(fam, ty, 0) { + match libc::socket(fam, ty, 0) as i32 { -1 => Err(last_net_error()), - fd => Ok(fd), + fd => Ok(fd as sock_t), } } } @@ -144,7 +148,7 @@ pub fn getsockopt(fd: sock_t, opt: libc::c_int, if ret != 0 { Err(last_net_error()) } else { - assert!(len as uint == mem::size_of::()); + assert!(len as usize == mem::size_of::()); Ok(slot) } } @@ -166,14 +170,14 @@ pub fn sockname(fd: sock_t, return Err(last_net_error()) } } - return sockaddr_to_addr(&storage, len as uint); + return sockaddr_to_addr(&storage, len as usize); } pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, - len: uint) -> IoResult { + len: usize) -> IoResult { match storage.ss_family as libc::c_int { libc::AF_INET => { - assert!(len as uint >= mem::size_of::()); + assert!(len as usize >= mem::size_of::()); let storage: &libc::sockaddr_in = unsafe { mem::transmute(storage) }; @@ -188,7 +192,7 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, }) } libc::AF_INET6 => { - assert!(len as uint >= mem::size_of::()); + assert!(len as usize >= mem::size_of::()); let storage: &libc::sockaddr_in6 = unsafe { mem::transmute(storage) }; @@ -279,13 +283,13 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, while !rp.is_null() { unsafe { let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr), - (*rp).ai_addrlen as uint)); + (*rp).ai_addrlen as usize)); addrs.push(addrinfo::Info { address: addr, - family: (*rp).ai_family as uint, + family: (*rp).ai_family as usize, socktype: None, protocol: None, - flags: (*rp).ai_flags as uint + flags: (*rp).ai_flags as usize }); rp = (*rp).ai_next as *mut libc::addrinfo; @@ -308,7 +312,7 @@ extern "system" { flags: c_int) -> c_int; } -const NI_MAXHOST: uint = 1025; +const NI_MAXHOST: usize = 1025; pub fn get_address_name(addr: IpAddr) -> Result { let addr = SocketAddr{ip: addr, port: 0}; @@ -389,7 +393,7 @@ pub fn get_address_name(addr: IpAddr) -> Result { // [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html // [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait -pub fn read(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult where +pub fn read(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult where L: FnMut() -> T, R: FnMut(bool) -> libc::c_int, { @@ -427,7 +431,7 @@ pub fn read(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoR match ret { 0 => Err(sys_common::eof()), n if n < 0 => Err(last_net_error()), - n => Ok(n as uint) + n => Ok(n as usize) } } @@ -436,9 +440,9 @@ pub fn write(fd: sock_t, buf: &[u8], write_everything: bool, mut lock: L, - mut write: W) -> IoResult where + mut write: W) -> IoResult where L: FnMut() -> T, - W: FnMut(bool, *const u8, uint) -> i64, + W: FnMut(bool, *const u8, usize) -> i64, { let mut ret = -1; let mut written = 0; @@ -450,7 +454,7 @@ pub fn write(fd: sock_t, }); } else { ret = retry(|| { write(false, buf.as_ptr(), buf.len()) }); - if ret > 0 { written = ret as uint; } + if ret > 0 { written = ret as usize; } } } @@ -479,7 +483,7 @@ pub fn write(fd: sock_t, match retry(|| write(deadline.is_some(), ptr, len)) { -1 if wouldblock() => {} -1 => return Err(last_net_error()), - n => { written += n as uint; } + n => { written += n as usize; } } } ret = 0; @@ -503,14 +507,14 @@ pub fn connect_timeout(fd: sock_t, #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK; // Make sure the call to connect() doesn't block - try!(set_nonblocking(fd, true)); + set_nonblocking(fd, true); let ret = match unsafe { libc::connect(fd, addrp, len) } { // If the connection is in progress, then we need to wait for it to // finish (with a timeout). The current strategy for doing this is // to use select() with a timeout. - -1 if os::errno() as int == INPROGRESS as int || - os::errno() as int == WOULDBLOCK as int => { + -1 if os::errno() as isize == INPROGRESS as isize || + os::errno() as isize == WOULDBLOCK as isize => { let mut set: c::fd_set = unsafe { mem::zeroed() }; c::fd_set(&mut set, fd); match await(fd, &mut set, timeout_ms) { @@ -533,7 +537,7 @@ pub fn connect_timeout(fd: sock_t, }; // be sure to turn blocking I/O back on - try!(set_nonblocking(fd, false)); + set_nonblocking(fd, false); return ret; #[cfg(unix)] @@ -618,15 +622,17 @@ impl Drop for Inner { fn drop(&mut self) { unsafe { close_sock(self.fd); } } } +#[cfg(not(target_os = "linux"))] pub struct Guard<'a> { pub fd: sock_t, pub guard: MutexGuard<'a, ()>, } +#[cfg(not(target_os = "linux"))] #[unsafe_destructor] impl<'a> Drop for Guard<'a> { fn drop(&mut self) { - assert!(set_nonblocking(self.fd, false).is_ok()); + set_nonblocking(self.fd, false); } } @@ -680,7 +686,7 @@ impl TcpStream { nodelay as libc::c_int) } - pub fn set_keepalive(&mut self, seconds: Option) -> IoResult<()> { + pub fn set_keepalive(&mut self, seconds: Option) -> IoResult<()> { let ret = setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_KEEPALIVE, seconds.is_some() as libc::c_int); match seconds { @@ -690,17 +696,18 @@ impl TcpStream { } #[cfg(any(target_os = "macos", target_os = "ios"))] - fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { + fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, seconds as libc::c_int) } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { + #[cfg(any(target_os = "freebsd", + target_os = "dragonfly"))] + fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, seconds as libc::c_int) } #[cfg(target_os = "openbsd")] - fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { + fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> { setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE, seconds as libc::c_int) } @@ -709,7 +716,7 @@ impl TcpStream { target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))] - fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> { + fn set_tcp_keepalive(&mut self, _seconds: usize) -> IoResult<()> { Ok(()) } @@ -722,11 +729,11 @@ impl TcpStream { fd: self.fd(), guard: self.inner.lock.lock().unwrap(), }; - assert!(set_nonblocking(self.fd(), true).is_ok()); + set_nonblocking(self.fd(), true); ret } - pub fn read(&mut self, buf: &mut [u8]) -> IoResult { + pub fn read(&mut self, buf: &mut [u8]) -> IoResult { let fd = self.fd(); let dolock = || self.lock_nonblocking(); let doread = |nb| unsafe { @@ -742,7 +749,7 @@ impl TcpStream { pub fn write(&mut self, buf: &[u8]) -> IoResult<()> { let fd = self.fd(); let dolock = || self.lock_nonblocking(); - let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe { + let dowrite = |nb: bool, buf: *const u8, len: usize| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::send(fd, buf as *const _, @@ -861,7 +868,7 @@ impl UdpSocket { fd: self.fd(), guard: self.inner.lock.lock().unwrap(), }; - assert!(set_nonblocking(self.fd(), true).is_ok()); + set_nonblocking(self.fd(), true); ret } @@ -869,7 +876,7 @@ impl UdpSocket { sockname(self.fd(), libc::getsockname) } - pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> { + pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(usize, SocketAddr)> { let fd = self.fd(); let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; let storagep = &mut storage as *mut _ as *mut libc::sockaddr; @@ -886,9 +893,7 @@ impl UdpSocket { storagep, &mut addrlen) as libc::c_int })); - sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| { - Ok((n as uint, addr)) - }) + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize).unwrap())) } pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { @@ -898,7 +903,7 @@ impl UdpSocket { let fd = self.fd(); let dolock = || self.lock_nonblocking(); - let dowrite = |nb, buf: *const u8, len: uint| unsafe { + let dowrite = |nb, buf: *const u8, len: usize| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::sendto(fd, buf as *const libc::c_void, @@ -909,11 +914,8 @@ impl UdpSocket { }; let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite)); - if n != buf.len() { - Err(short_write(n, "couldn't send entire packet at once")) - } else { - Ok(()) - } + assert!(n == buf.len(), "UDP packet not completely written."); + Ok(()) } pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> { @@ -937,11 +939,11 @@ impl UdpSocket { } } - pub fn multicast_time_to_live(&mut self, ttl: int) -> IoResult<()> { + pub fn multicast_time_to_live(&mut self, ttl: isize) -> IoResult<()> { setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, ttl as libc::c_int) } - pub fn time_to_live(&mut self, ttl: int) -> IoResult<()> { + pub fn time_to_live(&mut self, ttl: isize) -> IoResult<()> { setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int) } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index 713f79c5d0..7d42d65d36 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -10,12 +10,12 @@ use prelude::v1::*; -use ffi::CString; +use ffi::{CStr, CString}; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; -use net::{IpAddr, SocketAddr, Shutdown}; -use num::Int; +use net::{SocketAddr, Shutdown, IpAddr}; +use str::from_utf8; use sys::c; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys_common::{AsInner, FromInner, IntoInner}; @@ -24,9 +24,6 @@ use sys_common::{AsInner, FromInner, IntoInner}; // sockaddr and misc bindings //////////////////////////////////////////////////////////////////////////////// -fn hton(i: I) -> I { i.to_be() } -fn ntoh(i: I) -> I { Int::from_be(i) } - fn setsockopt(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> { unsafe { @@ -39,7 +36,7 @@ fn setsockopt(sock: &Socket, opt: c_int, val: c_int, #[allow(dead_code)] fn getsockopt(sock: &Socket, opt: c_int, - val: c_int) -> io::Result { + val: c_int) -> io::Result { unsafe { let mut slot: T = mem::zeroed(); let mut len = mem::size_of::() as socklen_t; @@ -67,18 +64,18 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, match storage.ss_family as libc::c_int { libc::AF_INET => { assert!(len as usize >= mem::size_of::()); - Ok(FromInner::from_inner(unsafe { + Ok(SocketAddr::V4(FromInner::from_inner(unsafe { *(storage as *const _ as *const libc::sockaddr_in) - })) + }))) } libc::AF_INET6 => { assert!(len as usize >= mem::size_of::()); - Ok(FromInner::from_inner(unsafe { + Ok(SocketAddr::V6(FromInner::from_inner(unsafe { *(storage as *const _ as *const libc::sockaddr_in6) - })) + }))) } _ => { - Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) + Err(Error::new(ErrorKind::InvalidInput, "invalid argument")) } } } @@ -130,6 +127,41 @@ pub fn lookup_host(host: &str) -> io::Result { } } +//////////////////////////////////////////////////////////////////////////////// +// lookup_addr +//////////////////////////////////////////////////////////////////////////////// + +extern "system" { + fn getnameinfo(sa: *const libc::sockaddr, salen: socklen_t, + host: *mut c_char, hostlen: libc::size_t, + serv: *mut c_char, servlen: libc::size_t, + flags: c_int) -> c_int; +} + +const NI_MAXHOST: usize = 1025; + +pub fn lookup_addr(addr: &IpAddr) -> io::Result { + init(); + + let saddr = SocketAddr::new(*addr, 0); + let (inner, len) = saddr.into_inner(); + let mut hostbuf = [0 as c_char; NI_MAXHOST]; + + let data = unsafe { + try!(cvt_gai(getnameinfo(inner, len, + hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, + 0 as *mut _, 0, 0))); + + CStr::from_ptr(hostbuf.as_ptr()) + }; + + match from_utf8(data.to_bytes()) { + Ok(name) => Ok(name.to_string()), + Err(_) => Err(io::Error::new(io::ErrorKind::Other, + "failed to lookup address information")) + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP streams //////////////////////////////////////////////////////////////////////////////// @@ -226,6 +258,12 @@ impl TcpStream { } } +impl FromInner for TcpStream { + fn from_inner(socket: Socket) -> TcpStream { + TcpStream { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP listeners //////////////////////////////////////////////////////////////////////////////// @@ -279,6 +317,12 @@ impl TcpListener { } } +impl FromInner for TcpListener { + fn from_inner(socket: Socket) -> TcpListener { + TcpListener { inner: socket } + } +} + //////////////////////////////////////////////////////////////////////////////// // UDP //////////////////////////////////////////////////////////////////////////////// @@ -391,3 +435,9 @@ impl UdpSocket { self.inner.duplicate().map(|s| UdpSocket { inner: s }) } } + +impl FromInner for UdpSocket { + fn from_inner(socket: Socket) -> UdpSocket { + UdpSocket { inner: socket } + } +} diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys/common/rwlock.rs index fe374e1fd7..f7d7a5715b 100644 --- a/src/libstd/sys/common/rwlock.rs +++ b/src/libstd/sys/common/rwlock.rs @@ -25,7 +25,7 @@ impl RWLock { /// thread to do so. /// /// Behavior is undefined if the rwlock has been moved between this and any - /// previous methodo call. + /// previous method call. #[inline] pub unsafe fn read(&self) { self.0.read() } @@ -35,7 +35,7 @@ impl RWLock { /// This function does not block the current thread. /// /// Behavior is undefined if the rwlock has been moved between this and any - /// previous methodo call. + /// previous method call. #[inline] pub unsafe fn try_read(&self) -> bool { self.0.try_read() } @@ -43,7 +43,7 @@ impl RWLock { /// to do so. /// /// Behavior is undefined if the rwlock has been moved between this and any - /// previous methodo call. + /// previous method call. #[inline] pub unsafe fn write(&self) { self.0.write() } @@ -53,7 +53,7 @@ impl RWLock { /// This function does not block the current thread. /// /// Behavior is undefined if the rwlock has been moved between this and any - /// previous methodo call. + /// previous method call. #[inline] pub unsafe fn try_write(&self) -> bool { self.0.try_write() } diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs index 8dd2f154fa..8dc3407db7 100644 --- a/src/libstd/sys/common/stack.rs +++ b/src/libstd/sys/common/stack.rs @@ -46,7 +46,7 @@ // corresponding prolog, decision was taken to disable segmented // stack support on iOS. -pub const RED_ZONE: uint = 20 * 1024; +pub const RED_ZONE: usize = 20 * 1024; /// This function is invoked from rust's current __morestack function. Segmented /// stacks are currently not enabled as segmented stacks, but rather one giant @@ -117,41 +117,10 @@ extern fn stack_exhausted() { // On all other platforms both variants behave identically. #[inline(always)] -pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) { +pub unsafe fn record_os_managed_stack_bounds(stack_lo: usize, _stack_hi: usize) { record_sp_limit(stack_lo + RED_ZONE); } -#[inline(always)] -pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) { - // When the old runtime had segmented stacks, it used a calculation that was - // "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic - // symbol resolution, llvm function calls, etc. In theory this red zone - // value is 0, but it matters far less when we have gigantic stacks because - // we don't need to be so exact about our stack budget. The "fudge factor" - // was because LLVM doesn't emit a stack check for functions < 256 bytes in - // size. Again though, we have giant stacks, so we round all these - // calculations up to the nice round number of 20k. - record_sp_limit(stack_lo + RED_ZONE); - - return target_record_stack_bounds(stack_lo, stack_hi); - - #[cfg(not(windows))] #[inline(always)] - unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {} - - #[cfg(all(windows, target_arch = "x86"))] #[inline(always)] - unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) { - // stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom) - asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile"); - asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile"); - } - #[cfg(all(windows, target_arch = "x86_64"))] #[inline(always)] - unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) { - // stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom) - asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile"); - asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile"); - } -} - /// Records the current limit of the stack as specified by `end`. /// /// This is stored in an OS-dependent location, likely inside of the thread @@ -167,30 +136,31 @@ pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) { /// would be unfortunate for the functions themselves to trigger a morestack /// invocation (if they were an actual function call). #[inline(always)] -pub unsafe fn record_sp_limit(limit: uint) { +pub unsafe fn record_sp_limit(limit: usize) { return target_record_sp_limit(limit); // x86-64 #[cfg(all(target_arch = "x86_64", any(target_os = "macos", target_os = "ios")))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + unsafe fn target_record_sp_limit(limit: usize) { asm!("movq $$0x60+90*8, %rsi movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile") } #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + unsafe fn target_record_sp_limit(limit: usize) { asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile") } #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)] - unsafe fn target_record_sp_limit(_: uint) { + unsafe fn target_record_sp_limit(_: usize) { } #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + unsafe fn target_record_sp_limit(limit: usize) { asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile") } - #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] + #[inline(always)] + unsafe fn target_record_sp_limit(limit: usize) { asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile") } @@ -198,18 +168,18 @@ pub unsafe fn record_sp_limit(limit: uint) { #[cfg(all(target_arch = "x86", any(target_os = "macos", target_os = "ios")))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + unsafe fn target_record_sp_limit(limit: usize) { asm!("movl $$0x48+90*4, %eax movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile") } #[cfg(all(target_arch = "x86", any(target_os = "linux", target_os = "freebsd")))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + unsafe fn target_record_sp_limit(limit: usize) { asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile") } #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)] - unsafe fn target_record_sp_limit(_: uint) { + unsafe fn target_record_sp_limit(_: usize) { } // mips, arm - Some brave soul can port these to inline asm, but it's over @@ -218,7 +188,7 @@ pub unsafe fn record_sp_limit(limit: uint) { target_arch = "mipsel", all(target_arch = "arm", not(target_os = "ios"))))] #[inline(always)] - unsafe fn target_record_sp_limit(limit: uint) { + unsafe fn target_record_sp_limit(limit: usize) { use libc::c_void; return record_sp_limit(limit as *const c_void); extern { @@ -233,8 +203,9 @@ pub unsafe fn record_sp_limit(limit: uint) { #[cfg(any(target_arch = "aarch64", target_arch = "powerpc", all(target_arch = "arm", target_os = "ios"), + target_os = "bitrig", target_os = "openbsd"))] - unsafe fn target_record_sp_limit(_: uint) { + unsafe fn target_record_sp_limit(_: usize) { } } @@ -247,48 +218,48 @@ pub unsafe fn record_sp_limit(limit: uint) { /// As with the setter, this function does not have a __morestack header and can /// therefore be called in a "we're out of stack" situation. #[inline(always)] -pub unsafe fn get_sp_limit() -> uint { +pub unsafe fn get_sp_limit() -> usize { return target_get_sp_limit(); // x86-64 #[cfg(all(target_arch = "x86_64", any(target_os = "macos", target_os = "ios")))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { let limit; asm!("movq $$0x60+90*8, %rsi movq %gs:(%rsi), $0" : "=r"(limit) :: "rsi" : "volatile"); return limit; } #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { let limit; asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile"); return limit; } #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { return 1024; } #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { let limit; asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile"); return limit; } - #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] + #[inline(always)] + unsafe fn target_get_sp_limit() -> usize { let limit; asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile"); return limit; } - // x86 #[cfg(all(target_arch = "x86", any(target_os = "macos", target_os = "ios")))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { let limit; asm!("movl $$0x48+90*4, %eax movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile"); @@ -297,13 +268,13 @@ pub unsafe fn get_sp_limit() -> uint { #[cfg(all(target_arch = "x86", any(target_os = "linux", target_os = "freebsd")))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { let limit; asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile"); return limit; } #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { return 1024; } @@ -313,9 +284,9 @@ pub unsafe fn get_sp_limit() -> uint { target_arch = "mipsel", all(target_arch = "arm", not(target_os = "ios"))))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { use libc::c_void; - return get_sp_limit() as uint; + return get_sp_limit() as usize; extern { fn get_sp_limit() -> *const c_void; } @@ -331,9 +302,10 @@ pub unsafe fn get_sp_limit() -> uint { #[cfg(any(target_arch = "aarch64", target_arch = "powerpc", all(target_arch = "arm", target_os = "ios"), + target_os = "bitrig", target_os = "openbsd"))] #[inline(always)] - unsafe fn target_get_sp_limit() -> uint { + unsafe fn target_get_sp_limit() -> usize { 1024 } } diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs index b725b6c7e6..1845b6266e 100644 --- a/src/libstd/sys/common/thread.rs +++ b/src/libstd/sys/common/thread.rs @@ -8,28 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::prelude::*; +use prelude::v1::*; -use boxed::Box; -use mem; use usize; use libc; use thunk::Thunk; use sys_common::stack; -use sys::{thread, stack_overflow}; +use sys::stack_overflow; // This is the starting point of rust os threads. The first thing we do // is make sure that we don't trigger __morestack (also why this has a // no_stack_check annotation), and then we extract the main function // and invoke it. #[no_stack_check] -pub fn start_thread(main: *mut libc::c_void) -> thread::rust_thread_return { +pub fn start_thread(main: *mut libc::c_void) { unsafe { stack::record_os_managed_stack_bounds(0, usize::MAX); - let handler = stack_overflow::Handler::new(); - let f: Box = mem::transmute(main); - f.invoke(()); - drop(handler); - mem::transmute(0 as thread::rust_thread_return) + let _handler = stack_overflow::Handler::new(); + let main: Box = Box::from_raw(main as *mut Thunk); + main(); } } diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs index 65c706033f..22cb594337 100644 --- a/src/libstd/sys/common/thread_info.rs +++ b/src/libstd/sys/common/thread_info.rs @@ -8,19 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] // stack_guard isn't used right now on all platforms + use core::prelude::*; use cell::RefCell; use string::String; use thread::Thread; -use thread_local::State; +use thread::LocalKeyState; struct ThreadInfo { - // This field holds the known bounds of the stack in (lo, hi) - // form. Not all threads necessarily know their precise bounds, - // hence this is optional. - stack_bounds: (uint, uint), - stack_guard: uint, + stack_guard: usize, thread: Thread, } @@ -28,7 +26,7 @@ thread_local! { static THREAD_INFO: RefCell> = RefCell::new(N impl ThreadInfo { fn with(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R { - if THREAD_INFO.state() == State::Destroyed { + if THREAD_INFO.state() == LocalKeyState::Destroyed { panic!("Use of std::thread::current() is not possible after \ the thread's local data has been destroyed"); } @@ -36,7 +34,6 @@ impl ThreadInfo { THREAD_INFO.with(move |c| { if c.borrow().is_none() { *c.borrow_mut() = Some(ThreadInfo { - stack_bounds: (0, 0), stack_guard: 0, thread: NewThread::new(None), }) @@ -50,14 +47,13 @@ pub fn current_thread() -> Thread { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> uint { +pub fn stack_guard() -> usize { ThreadInfo::with(|info| info.stack_guard) } -pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) { +pub fn set(stack_guard: usize, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ - stack_bounds: stack_bounds, stack_guard: stack_guard, thread: thread, })); diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs index 27b8784e39..5995d7ac10 100644 --- a/src/libstd/sys/common/thread_local.rs +++ b/src/libstd/sys/common/thread_local.rs @@ -28,7 +28,7 @@ //! more useful in practice than this OS-based version which likely requires //! unsafe code to interoperate with. //! -//! # Example +//! # Examples //! //! Using a dynamically allocated TLS key. Note that this key can be shared //! among many threads via an `Arc`. @@ -55,11 +55,12 @@ //! ``` #![allow(non_camel_case_types)] +#![unstable(feature = "thread_local_internals")] +#![allow(dead_code)] // sys isn't exported yet use prelude::v1::*; use sync::atomic::{self, AtomicUsize, Ordering}; -use sync::{Mutex, Once, ONCE_INIT}; use sys::thread_local as imp; @@ -72,7 +73,7 @@ use sys::thread_local as imp; /// time. The key is also deallocated when the Rust runtime exits or `destroy` /// is called, whichever comes first. /// -/// # Example +/// # Examples /// /// ```ignore /// use tls::os::{StaticKey, INIT}; @@ -84,17 +85,14 @@ use sys::thread_local as imp; /// KEY.set(1 as *mut u8); /// } /// ``` -#[stable(feature = "rust1", since = "1.0.0")] pub struct StaticKey { /// Inner static TLS key (internals), created with by `INIT_INNER` in this /// module. - #[stable(feature = "rust1", since = "1.0.0")] pub inner: StaticKeyInner, /// Destructor for the TLS value. /// /// See `Key::new` for information about when the destructor runs and how /// it runs. - #[stable(feature = "rust1", since = "1.0.0")] pub dtor: Option, } @@ -112,7 +110,7 @@ pub struct StaticKeyInner { /// Implementations will likely, however, contain unsafe code as this type only /// operates on `*mut u8`, an unsafe pointer. /// -/// # Example +/// # Examples /// /// ```rust,ignore /// use tls::os::Key; @@ -131,7 +129,6 @@ pub struct Key { /// Constant initialization value for static TLS keys. /// /// This value specifies no destructor by default. -#[stable(feature = "rust1", since = "1.0.0")] pub const INIT: StaticKey = StaticKey { inner: INIT_INNER, dtor: None, @@ -140,14 +137,10 @@ pub const INIT: StaticKey = StaticKey { /// Constant initialization value for the inner part of static TLS keys. /// /// This value allows specific configuration of the destructor for a TLS key. -#[stable(feature = "rust1", since = "1.0.0")] pub const INIT_INNER: StaticKeyInner = StaticKeyInner { key: atomic::ATOMIC_USIZE_INIT, }; -static INIT_KEYS: Once = ONCE_INIT; -static mut KEYS: *mut Mutex> = 0 as *mut _; - impl StaticKey { /// Gets the value associated with this TLS key /// @@ -185,7 +178,7 @@ impl StaticKey { } } - unsafe fn lazy_init(&self) -> uint { + unsafe fn lazy_init(&self) -> usize { // POSIX allows the key created here to be 0, but the compare_and_swap // below relies on using 0 as a sentinel value to check who won the // race to set the shared TLS key. As far as I know, there is no @@ -204,9 +197,9 @@ impl StaticKey { key2 }; assert!(key != 0); - match self.inner.key.compare_and_swap(0, key as uint, Ordering::SeqCst) { + match self.inner.key.compare_and_swap(0, key as usize, Ordering::SeqCst) { // The CAS succeeded, so we've created the actual key - 0 => key as uint, + 0 => key as usize, // If someone beat us to the punch, use their key instead n => { imp::destroy(key); n } } @@ -268,8 +261,8 @@ mod tests { assert!(k2.get().is_null()); k1.set(1 as *mut _); k2.set(2 as *mut _); - assert_eq!(k1.get() as uint, 1); - assert_eq!(k2.get() as uint, 2); + assert_eq!(k1.get() as usize, 1); + assert_eq!(k2.get() as usize, 2); } #[test] @@ -282,8 +275,8 @@ mod tests { assert!(K2.get().is_null()); K1.set(1 as *mut _); K2.set(2 as *mut _); - assert_eq!(K1.get() as uint, 1); - assert_eq!(K2.get() as uint, 2); + assert_eq!(K1.get() as usize, 1); + assert_eq!(K2.get() as usize, 2); } } } diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index ca3ae1a7a3..987a12293d 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -21,30 +21,33 @@ //! nor can it decode WTF-8 from arbitrary bytes. //! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points. +// this module is imported from @SimonSapin's repo and has tons of dead code on +// unix (it's mostly used on windows), so don't worry about dead code here. +#![allow(dead_code)] + use core::prelude::*; use core::char::{encode_utf8_raw, encode_utf16_raw}; use core::str::{char_range_at_raw, next_code_point}; -use core::raw::Slice as RawSlice; use ascii::*; use borrow::Cow; use cmp; use fmt; use hash::{Hash, Hasher}; -#[cfg(stage0)] use hash::Writer; use iter::{FromIterator, IntoIterator}; use mem; +#[allow(deprecated)] // Int use num::Int; use ops; use slice; use str; -use string::{String, CowString}; +use string::String; use sys_common::AsInner; use unicode::str::{Utf16Item, utf16_items}; use vec::Vec; -static UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD"; +const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD"; /// A Unicode code point: from U+0000 to U+10FFFF. /// @@ -156,7 +159,7 @@ impl Wtf8Buf { /// Create an new, empty WTF-8 string with pre-allocated capacity for `n` bytes. #[inline] - pub fn with_capacity(n: uint) -> Wtf8Buf { + pub fn with_capacity(n: usize) -> Wtf8Buf { Wtf8Buf { bytes: Vec::with_capacity(n) } } @@ -177,7 +180,7 @@ impl Wtf8Buf { /// Since WTF-8 is a superset of UTF-8, this always succeeds. #[inline] pub fn from_str(str: &str) -> Wtf8Buf { - Wtf8Buf { bytes: slice::SliceExt::to_vec(str.as_bytes()) } + Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) } } /// Create a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units. @@ -211,10 +214,10 @@ impl Wtf8Buf { unsafe { // Attempt to not use an intermediate buffer by just pushing bytes // directly onto this string. - let slice = RawSlice { - data: self.bytes.as_ptr().offset(cur_len as int), - len: 4, - }; + let slice = slice::from_raw_parts_mut( + self.bytes.as_mut_ptr().offset(cur_len as isize), + 4 + ); let used = encode_utf8_raw(code_point.value, mem::transmute(slice)) .unwrap_or(0); self.bytes.set_len(cur_len + used); @@ -232,15 +235,15 @@ impl Wtf8Buf { /// /// # Panics /// - /// Panics if the new capacity overflows `uint`. + /// Panics if the new capacity overflows `usize`. #[inline] - pub fn reserve(&mut self, additional: uint) { + pub fn reserve(&mut self, additional: usize) { self.bytes.reserve(additional) } /// Returns the number of bytes that this string buffer can hold without reallocating. #[inline] - pub fn capacity(&self) -> uint { + pub fn capacity(&self) -> usize { self.bytes.capacity() } @@ -311,7 +314,7 @@ impl Wtf8Buf { /// Panics if `new_len` > current length, /// or if `new_len` is not a code point boundary. #[inline] - pub fn truncate(&mut self, new_len: uint) { + pub fn truncate(&mut self, new_len: usize) { assert!(is_code_point_boundary(self, new_len)); self.bytes.truncate(new_len) } @@ -342,8 +345,8 @@ impl Wtf8Buf { Some((surrogate_pos, _)) => { pos = surrogate_pos + 3; slice::bytes::copy_memory( + UTF8_REPLACEMENT_CHARACTER, &mut self.bytes[surrogate_pos .. pos], - UTF8_REPLACEMENT_CHARACTER ); }, None => return unsafe { String::from_utf8_unchecked(self.bytes) } @@ -461,7 +464,7 @@ impl Wtf8 { /// Return the length, in WTF-8 bytes. #[inline] - pub fn len(&self) -> uint { + pub fn len(&self) -> usize { self.bytes.len() } @@ -472,7 +475,7 @@ impl Wtf8 { /// /// Panics if `position` is beyond the end of the string. #[inline] - pub fn ascii_byte_at(&self, position: uint) -> u8 { + pub fn ascii_byte_at(&self, position: usize) -> u8 { match self.bytes[position] { ascii_byte @ 0x00 ... 0x7F => ascii_byte, _ => 0xFF @@ -486,7 +489,7 @@ impl Wtf8 { /// Panics if `position` is not at a code point boundary, /// or is beyond the end of the string. #[inline] - pub fn code_point_at(&self, position: uint) -> CodePoint { + pub fn code_point_at(&self, position: usize) -> CodePoint { let (code_point, _) = self.code_point_range_at(position); code_point } @@ -499,7 +502,7 @@ impl Wtf8 { /// Panics if `position` is not at a code point boundary, /// or is beyond the end of the string. #[inline] - pub fn code_point_range_at(&self, position: uint) -> (CodePoint, uint) { + pub fn code_point_range_at(&self, position: usize) -> (CodePoint, usize) { let (c, n) = char_range_at_raw(&self.bytes, position); (CodePoint { value: c }, n) } @@ -531,7 +534,7 @@ impl Wtf8 { /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”). /// /// This only copies the data if necessary (if it contains any surrogate). - pub fn to_string_lossy(&self) -> CowString { + pub fn to_string_lossy(&self) -> Cow { let surrogate_pos = match self.next_surrogate(0) { None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }), Some((pos, _)) => pos, @@ -568,7 +571,7 @@ impl Wtf8 { } #[inline] - fn next_surrogate(&self, mut pos: uint) -> Option<(uint, u16)> { + fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> { let mut iter = self.bytes[pos..].iter(); loop { let b = match iter.next() { @@ -636,7 +639,7 @@ impl ops::Index> for Wtf8 { type Output = Wtf8; #[inline] - fn index(&self, range: &ops::Range) -> &Wtf8 { + fn index(&self, range: ops::Range) -> &Wtf8 { // is_code_point_boundary checks that the index is in [0, .len()] if range.start <= range.end && is_code_point_boundary(self, range.start) && @@ -658,7 +661,7 @@ impl ops::Index> for Wtf8 { type Output = Wtf8; #[inline] - fn index(&self, range: &ops::RangeFrom) -> &Wtf8 { + fn index(&self, range: ops::RangeFrom) -> &Wtf8 { // is_code_point_boundary checks that the index is in [0, .len()] if is_code_point_boundary(self, range.start) { unsafe { slice_unchecked(self, range.start, self.len()) } @@ -678,7 +681,7 @@ impl ops::Index> for Wtf8 { type Output = Wtf8; #[inline] - fn index(&self, range: &ops::RangeTo) -> &Wtf8 { + fn index(&self, range: ops::RangeTo) -> &Wtf8 { // is_code_point_boundary checks that the index is in [0, .len()] if is_code_point_boundary(self, range.end) { unsafe { slice_unchecked(self, 0, range.end) } @@ -692,7 +695,7 @@ impl ops::Index for Wtf8 { type Output = Wtf8; #[inline] - fn index(&self, _range: &ops::RangeFull) -> &Wtf8 { + fn index(&self, _range: ops::RangeFull) -> &Wtf8 { self } } @@ -711,26 +714,27 @@ fn decode_surrogate_pair(lead: u16, trail: u16) -> char { /// Copied from core::str::StrPrelude::is_char_boundary #[inline] -pub fn is_code_point_boundary(slice: &Wtf8, index: uint) -> bool { +pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool { if index == slice.len() { return true; } match slice.bytes.get(index) { None => false, - Some(&b) => b < 128u8 || b >= 192u8, + Some(&b) => b < 128 || b >= 192, } } /// Copied from core::str::raw::slice_unchecked #[inline] -pub unsafe fn slice_unchecked(s: &Wtf8, begin: uint, end: uint) -> &Wtf8 { - mem::transmute(RawSlice { - data: s.bytes.as_ptr().offset(begin as int), - len: end - begin, - }) +pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { + // memory layout of an &[u8] and &Wtf8 are the same + mem::transmute(slice::from_raw_parts( + s.bytes.as_ptr().offset(begin as isize), + end - begin + )) } /// Copied from core::str::raw::slice_error_fail #[inline(never)] -pub fn slice_error_fail(s: &Wtf8, begin: uint, end: uint) -> ! { +pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! { assert!(begin <= end); panic!("index {} and/or {} in `{:?}` do not lie on character boundary", begin, end, s); @@ -753,7 +757,7 @@ impl<'a> Iterator for Wtf8CodePoints<'a> { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (len, _) = self.bytes.size_hint(); (len.saturating_add(3) / 4, Some(len)) } @@ -777,7 +781,7 @@ impl<'a> Iterator for EncodeWide<'a> { return Some(tmp); } - let mut buf = [0u16; 2]; + let mut buf = [0; 2]; self.code_points.next().map(|code_point| { let n = encode_utf16_raw(code_point.value, &mut buf) .unwrap_or(0); @@ -787,7 +791,7 @@ impl<'a> Iterator for EncodeWide<'a> { } #[inline] - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { let (low, high) = self.code_points.size_hint(); // every code point gets either one u16 or two u16, // so this iterator is between 1 or 2 times as @@ -796,14 +800,6 @@ impl<'a> Iterator for EncodeWide<'a> { } } -#[cfg(stage0)] -impl Hash for CodePoint { - #[inline] - fn hash(&self, state: &mut S) { - self.value.hash(state) - } -} -#[cfg(not(stage0))] impl Hash for CodePoint { #[inline] fn hash(&self, state: &mut H) { @@ -811,15 +807,6 @@ impl Hash for CodePoint { } } -#[cfg(stage0)] -impl Hash for Wtf8Buf { - #[inline] - fn hash(&self, state: &mut S) { - state.write(&self.bytes); - 0xfeu8.hash(state) - } -} -#[cfg(not(stage0))] impl Hash for Wtf8Buf { #[inline] fn hash(&self, state: &mut H) { @@ -828,15 +815,6 @@ impl Hash for Wtf8Buf { } } -#[cfg(stage0)] -impl<'a, S: Writer + Hasher> Hash for Wtf8 { - #[inline] - fn hash(&self, state: &mut S) { - state.write(&self.bytes); - 0xfeu8.hash(state) - } -} -#[cfg(not(stage0))] impl Hash for Wtf8 { #[inline] fn hash(&self, state: &mut H) { @@ -871,7 +849,6 @@ mod tests { use borrow::Cow; use super::*; use mem::transmute; - use string::CowString; #[test] fn code_point_from_u32() { @@ -1058,14 +1035,14 @@ mod tests { } #[test] - #[should_fail] + #[should_panic] fn wtf8buf_truncate_fail_code_point_boundary() { let mut string = Wtf8Buf::from_str("aé"); string.truncate(2); } #[test] - #[should_fail] + #[should_panic] fn wtf8buf_truncate_fail_longer() { let mut string = Wtf8Buf::from_str("aé"); string.truncate(4); @@ -1161,7 +1138,7 @@ mod tests { } #[test] - #[should_fail] + #[should_panic] fn wtf8_slice_not_code_point_boundary() { &Wtf8::from_str("aé 💩")[2.. 4]; } @@ -1172,7 +1149,7 @@ mod tests { } #[test] - #[should_fail] + #[should_panic] fn wtf8_slice_from_not_code_point_boundary() { &Wtf8::from_str("aé 💩")[2..]; } @@ -1183,7 +1160,7 @@ mod tests { } #[test] - #[should_fail] + #[should_panic] fn wtf8_slice_to_not_code_point_boundary() { &Wtf8::from_str("aé 💩")[5..]; } @@ -1229,11 +1206,11 @@ mod tests { string.code_points().map(|c| c.to_char()).collect::>() } let mut string = Wtf8Buf::from_str("é "); - assert_eq!(cp(&string), vec![Some('é'), Some(' ')]); + assert_eq!(cp(&string), [Some('é'), Some(' ')]); string.push(c(0xD83D)); - assert_eq!(cp(&string), vec![Some('é'), Some(' '), None]); + assert_eq!(cp(&string), [Some('é'), Some(' '), None]); string.push(c(0xDCA9)); - assert_eq!(cp(&string), vec![Some('é'), Some(' '), Some('💩')]); + assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]); } #[test] @@ -1251,7 +1228,7 @@ mod tests { assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩")); let mut string = Wtf8Buf::from_str("aé 💩"); string.push(CodePoint::from_u32(0xD800).unwrap()); - let expected: CowString = Cow::Owned(String::from_str("aé 💩�")); + let expected: Cow = Cow::Owned(String::from_str("aé 💩�")); assert_eq!(string.to_string_lossy(), expected); } diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 8b560339f3..ca805ad024 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -84,9 +84,10 @@ /// all unix platforms we support right now, so it at least gets the job done. use prelude::v1::*; +use io::prelude::*; use ffi::CStr; -use old_io::IoResult; +use io; use libc; use mem; use str; @@ -105,7 +106,7 @@ use sys_common::backtrace::*; /// only viable option. #[cfg(all(target_os = "ios", target_arch = "arm"))] #[inline(never)] -pub fn write(w: &mut Writer) -> IoResult<()> { +pub fn write(w: &mut Write) -> io::Result<()> { use result; extern { @@ -117,17 +118,17 @@ pub fn write(w: &mut Writer) -> IoResult<()> { // local, it still displays much nicer backtraces when a // couple of tasks panic simultaneously static LOCK: StaticMutex = MUTEX_INIT; - let _g = unsafe { LOCK.lock() }; + let _g = LOCK.lock(); try!(writeln!(w, "stack backtrace:")); // 100 lines should be enough - const SIZE: uint = 100; + const SIZE: usize = 100; let mut buf: [*mut libc::c_void; SIZE] = unsafe {mem::zeroed()}; - let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as uint}; + let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as usize}; // skipping the first one as it is write itself let iter = (1..cnt).map(|i| { - print(w, i as int, buf[i]) + print(w, i as isize, buf[i], buf[i]) }); result::fold(iter, (), |_, _| ()) } @@ -135,13 +136,11 @@ pub fn write(w: &mut Writer) -> IoResult<()> { #[cfg(not(all(target_os = "ios", target_arch = "arm")))] #[inline(never)] // if we know this is a function call, we can skip it when // tracing -pub fn write(w: &mut Writer) -> IoResult<()> { - use old_io::IoError; - +pub fn write(w: &mut Write) -> io::Result<()> { struct Context<'a> { - idx: int, - writer: &'a mut (Writer+'a), - last_error: Option, + idx: isize, + writer: &'a mut (Write+'a), + last_error: Option, } // When using libbacktrace, we use some necessary global state, so we @@ -150,7 +149,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { // I/O done here is blocking I/O, not green I/O, so we don't have to // worry about this being a native vs green mutex. static LOCK: StaticMutex = MUTEX_INIT; - let _g = unsafe { LOCK.lock() }; + let _g = LOCK.lock(); try!(writeln!(w, "stack backtrace:")); @@ -171,7 +170,16 @@ pub fn write(w: &mut Writer) -> IoResult<()> { extern fn trace_fn(ctx: *mut uw::_Unwind_Context, arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { let cx: &mut Context = unsafe { mem::transmute(arg) }; - let ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut libc::c_void }; + let mut ip_before_insn = 0; + let mut ip = unsafe { + uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void + }; + if !ip.is_null() && ip_before_insn == 0 { + // this is a non-signaling frame, so `ip` refers to the address + // after the calling instruction. account for that. + ip = (ip as usize - 1) as *mut _; + } + // dladdr() on osx gets whiny when we use FindEnclosingFunction, and // it appears to work fine without it, so we only use // FindEnclosingFunction on non-osx platforms. In doing so, we get a @@ -182,7 +190,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { // instructions after it. This means that the return instruction // pointer points *outside* of the calling function, and by // unwinding it we go back to the original function. - let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { + let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { ip } else { unsafe { uw::_Unwind_FindEnclosingFunction(ip) } @@ -203,7 +211,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { // Once we hit an error, stop trying to print more frames if cx.last_error.is_some() { return uw::_URC_FAILURE } - match print(cx.writer, cx.idx, ip) { + match print(cx.writer, cx.idx, ip, symaddr) { Ok(()) => {} Err(e) => { cx.last_error = Some(e); } } @@ -214,7 +222,8 @@ pub fn write(w: &mut Writer) -> IoResult<()> { } #[cfg(any(target_os = "macos", target_os = "ios"))] -fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { +fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, + _symaddr: *mut libc::c_void) -> io::Result<()> { use intrinsics; #[repr(C)] struct Dl_info { @@ -239,8 +248,10 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { } #[cfg(not(any(target_os = "macos", target_os = "ios")))] -fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { +fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void, + symaddr: *mut libc::c_void) -> io::Result<()> { use env; + use os::unix::prelude::*; use ptr; //////////////////////////////////////////////////////////////////////// @@ -252,6 +263,12 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { symname: *const libc::c_char, symval: libc::uintptr_t, symsize: libc::uintptr_t); + type backtrace_full_callback = + extern "C" fn(data: *mut libc::c_void, + pc: libc::uintptr_t, + filename: *const libc::c_char, + lineno: libc::c_int, + function: *const libc::c_char) -> libc::c_int; type backtrace_error_callback = extern "C" fn(data: *mut libc::c_void, msg: *const libc::c_char, @@ -272,12 +289,19 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { cb: backtrace_syminfo_callback, error: backtrace_error_callback, data: *mut libc::c_void) -> libc::c_int; + fn backtrace_pcinfo(state: *mut backtrace_state, + addr: libc::uintptr_t, + cb: backtrace_full_callback, + error: backtrace_error_callback, + data: *mut libc::c_void) -> libc::c_int; } //////////////////////////////////////////////////////////////////////// // helper callbacks //////////////////////////////////////////////////////////////////////// + type FileLine = (*const libc::c_char, libc::c_int); + extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char, _errnum: libc::c_int) { // do nothing for now @@ -290,6 +314,25 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { let slot = data as *mut *const libc::c_char; unsafe { *slot = symname; } } + extern fn pcinfo_cb(data: *mut libc::c_void, + _pc: libc::uintptr_t, + filename: *const libc::c_char, + lineno: libc::c_int, + _function: *const libc::c_char) -> libc::c_int { + if !filename.is_null() { + let slot = data as *mut &mut [FileLine]; + let buffer = unsafe {ptr::read(slot)}; + + // if the buffer is not full, add file:line to the buffer + // and adjust the buffer for next possible calls to pcinfo_cb. + if !buffer.is_empty() { + buffer[0] = (filename, lineno); + unsafe { ptr::write(slot, &mut buffer[1..]); } + } + } + + 0 + } // The libbacktrace API supports creating a state, but it does not // support destroying a state. I personally take this to mean that a @@ -319,6 +362,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { if !STATE.is_null() { return STATE } let selfname = if cfg!(target_os = "freebsd") || cfg!(target_os = "dragonfly") || + cfg!(target_os = "bitrig") || cfg!(target_os = "openbsd") { env::current_exe().ok() } else { @@ -326,7 +370,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { }; let filename = match selfname { Some(path) => { - let bytes = path.as_vec(); + let bytes = path.as_os_str().as_bytes(); if bytes.len() < LAST_FILENAME.len() { let i = bytes.iter(); for (slot, val) in LAST_FILENAME.iter_mut().zip(i) { @@ -357,20 +401,47 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { let mut data = ptr::null(); let data_addr = &mut data as *mut *const libc::c_char; let ret = unsafe { - backtrace_syminfo(state, addr as libc::uintptr_t, + backtrace_syminfo(state, symaddr as libc::uintptr_t, syminfo_cb, error_cb, data_addr as *mut libc::c_void) }; if ret == 0 || data.is_null() { - output(w, idx, addr, None) + try!(output(w, idx, addr, None)); } else { - output(w, idx, addr, Some(unsafe { CStr::from_ptr(data).to_bytes() })) + try!(output(w, idx, addr, Some(unsafe { CStr::from_ptr(data).to_bytes() }))); + } + + // pcinfo may return an arbitrary number of file:line pairs, + // in the order of stack trace (i.e. inlined calls first). + // in order to avoid allocation, we stack-allocate a fixed size of entries. + const FILELINE_SIZE: usize = 32; + let mut fileline_buf = [(ptr::null(), -1); FILELINE_SIZE]; + let ret; + let fileline_count; + { + let mut fileline_win: &mut [FileLine] = &mut fileline_buf; + let fileline_addr = &mut fileline_win as *mut &mut [FileLine]; + ret = unsafe { + backtrace_pcinfo(state, addr as libc::uintptr_t, + pcinfo_cb, error_cb, + fileline_addr as *mut libc::c_void) + }; + fileline_count = FILELINE_SIZE - fileline_win.len(); + } + if ret == 0 { + for (i, &(file, line)) in fileline_buf[..fileline_count].iter().enumerate() { + if file.is_null() { continue; } // just to be sure + let file = unsafe { CStr::from_ptr(file).to_bytes() }; + try!(output_fileline(w, file, line, i == FILELINE_SIZE - 1)); + } } + + Ok(()) } // 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<&[u8]>) -> IoResult<()> { +fn output(w: &mut Write, idx: isize, addr: *mut libc::c_void, + s: Option<&[u8]>) -> io::Result<()> { try!(write!(w, " {:2}: {:2$?} - ", idx, addr, HEX_WIDTH)); match s.and_then(|s| str::from_utf8(s).ok()) { Some(string) => try!(demangle(w, string)), @@ -379,6 +450,18 @@ fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void, w.write_all(&['\n' as u8]) } +#[allow(dead_code)] +fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int, + more: bool) -> io::Result<()> { + let file = str::from_utf8(file).unwrap_or(""); + // prior line: " ##: {:2$} - func" + try!(write!(w, " {:3$}at {}:{}", "", file, line, HEX_WIDTH)); + if more { + try!(write!(w, " <... and possibly more>")); + } + w.write_all(&['\n' as u8]) +} + /// Unwind library interface used for backtraces /// /// Note that dead code is allowed as here are just bindings @@ -419,9 +502,12 @@ mod uw { trace_argument: *mut libc::c_void) -> _Unwind_Reason_Code; + // available since GCC 4.2.0, should be fine for our purpose #[cfg(all(not(all(target_os = "android", target_arch = "arm")), not(all(target_os = "linux", target_arch = "arm"))))] - pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t; + pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, + ip_before_insn: *mut libc::c_int) + -> libc::uintptr_t; #[cfg(all(not(target_os = "android"), not(all(target_os = "linux", target_arch = "arm"))))] @@ -477,6 +563,18 @@ mod uw { (val & !1) as libc::uintptr_t } + // This function doesn't exist on Android or ARM/Linux, so make it same + // to _Unwind_GetIP + #[cfg(any(all(target_os = "android", target_arch = "arm"), + all(target_os = "linux", target_arch = "arm")))] + pub unsafe fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context, + ip_before_insn: *mut libc::c_int) + -> libc::uintptr_t + { + *ip_before_insn = 0; + _Unwind_GetIP(ctx) + } + // This function also doesn't exist on Android or ARM/Linux, so make it // a no-op #[cfg(any(target_os = "android", diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index 345808189a..2514d4bf4a 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -24,6 +24,7 @@ use libc; target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub const FIONBIO: libc::c_ulong = 0x8004667e; #[cfg(any(all(target_os = "linux", @@ -43,6 +44,7 @@ pub const FIONBIO: libc::c_ulong = 0x667e; target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub const FIOCLEX: libc::c_ulong = 0x20006601; #[cfg(any(all(target_os = "linux", @@ -62,6 +64,7 @@ pub const FIOCLEX: libc::c_ulong = 0x6601; target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub const MSG_DONTWAIT: libc::c_int = 0x80; #[cfg(any(target_os = "linux", target_os = "android"))] @@ -75,7 +78,8 @@ pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70; target_os = "freebsd", target_os = "dragonfly"))] pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71; -#[cfg(target_os = "openbsd")] +#[cfg(any(target_os = "bitrig", + target_os = "openbsd"))] pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101; #[cfg(target_os = "android")] pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048; @@ -96,6 +100,7 @@ pub struct passwd { #[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub struct passwd { pub pw_name: *mut libc::c_char, @@ -162,7 +167,7 @@ extern { #[cfg(any(target_os = "macos", target_os = "ios"))] mod select { - pub const FD_SETSIZE: uint = 1024; + pub const FD_SETSIZE: usize = 1024; #[repr(C)] pub struct fd_set { @@ -170,13 +175,14 @@ mod select { } pub fn fd_set(set: &mut fd_set, fd: i32) { - set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint); + set.fds_bits[(fd / 32) as usize] |= 1 << ((fd % 32) as usize); } } #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd", target_os = "linux"))] mod select { @@ -188,12 +194,12 @@ mod select { #[repr(C)] pub struct fd_set { // FIXME: shouldn't this be a c_ulong? - fds_bits: [libc::uintptr_t; (FD_SETSIZE / usize::BITS)] + fds_bits: [libc::uintptr_t; (FD_SETSIZE / usize::BITS as usize)] } pub fn fd_set(set: &mut fd_set, fd: i32) { - let fd = fd as uint; - set.fds_bits[fd / usize::BITS] |= 1 << (fd % usize::BITS); + let fd = fd as usize; + set.fds_bits[fd / usize::BITS as usize] |= 1 << (fd % usize::BITS as usize); } } @@ -302,8 +308,7 @@ mod signal { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd"))] + target_os = "dragonfly"))] mod signal { use libc; @@ -317,8 +322,7 @@ mod signal { pub const SIGCHLD: libc::c_int = 20; #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "openbsd"))] + target_os = "ios"))] pub type sigset_t = u32; #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] #[repr(C)] @@ -345,3 +349,41 @@ mod signal { pub sa_mask: sigset_t, } } + +#[cfg(any(target_os = "bitrig", target_os = "openbsd"))] +mod signal { + use libc; + + pub const SA_ONSTACK: libc::c_int = 0x0001; + pub const SA_RESTART: libc::c_int = 0x0002; + pub const SA_RESETHAND: libc::c_int = 0x0004; + pub const SA_NOCLDSTOP: libc::c_int = 0x0008; + pub const SA_NODEFER: libc::c_int = 0x0010; + pub const SA_NOCLDWAIT: libc::c_int = 0x0020; + pub const SA_SIGINFO: libc::c_int = 0x0040; + pub const SIGCHLD: libc::c_int = 20; + + pub type sigset_t = libc::c_uint; + + // This structure has more fields, but we're not all that interested in + // them. + #[repr(C)] + pub struct siginfo { + pub si_signo: libc::c_int, + pub si_code: libc::c_int, + pub si_errno: libc::c_int, + // FIXME: Bitrig has a crazy union here in the siginfo, I think this + // layout will still work tho. The status might be off by the size of + // a clock_t by my reading, but we can fix this later. + pub pid: libc::pid_t, + pub uid: libc::uid_t, + pub status: libc::c_int, + } + + #[repr(C)] + pub struct sigaction { + pub sa_handler: extern fn(libc::c_int), + pub sa_mask: sigset_t, + pub sa_flags: libc::c_int, + } +} diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index 3bc4147315..90dfebc4c4 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use libc; use ptr; -use std::option::Option::{Some, None}; use sys::mutex::{self, Mutex}; use sys::time; use sys::sync as ffi; @@ -20,6 +21,9 @@ use num::{Int, NumCast}; pub struct Condvar { inner: UnsafeCell } +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + pub const CONDVAR_INIT: Condvar = Condvar { inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER }, }; diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index b8b9dcfb3c..fbfbb40701 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -29,171 +29,268 @@ //! } //! ``` -#![unstable(feature = "std_misc")] - -use prelude::v1::*; - -use ffi::{CString, NulError, OsStr, OsString}; -use fs::{self, Permissions, OpenOptions}; -use net; -use mem; -use process; -use sys; -use sys::os_str::Buf; -use sys_common::{AsInner, AsInnerMut, IntoInner, FromInner}; -use libc::{self, gid_t, uid_t}; - -use old_io; +#![stable(feature = "rust1", since = "1.0.0")] + +/// Unix-specific extensions to general I/O primitives +#[stable(feature = "rust1", since = "1.0.0")] +pub mod io { + #[allow(deprecated)] use old_io; + use fs; + use libc; + use net; + use sys_common::{net2, AsInner, FromInner}; + use sys; + + /// Raw file descriptors. + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawFd = libc::c_int; + + /// A trait to extract the raw unix file descriptor from an underlying + /// object. + /// + /// This is only available on unix platforms and must be imported in order + /// to call the method. Windows platforms have a corresponding `AsRawHandle` + /// and `AsRawSocket` set of traits. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait AsRawFd { + /// Extract the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guarantee to be valid while + /// the original object has not yet been destroyed. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_fd(&self) -> RawFd; + } -/// Raw file descriptors. -pub type Fd = libc::c_int; + /// A trait to express the ability to construct an object from a raw file + /// descriptor. + #[unstable(feature = "from_raw_os", + reason = "recent addition to std::os::unix::io")] + pub trait FromRawFd { + /// Constructs a new instances of `Self` from the given raw file + /// descriptor. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// Callers should normally only pass in a valid file descriptor to this + /// method or otherwise methods will return errors. + fn from_raw_fd(fd: RawFd) -> Self; + } -/// Extract raw file descriptor -pub trait AsRawFd { - /// Extract the raw file descriptor, without taking any ownership. - fn as_raw_fd(&self) -> Fd; -} + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for old_io::fs::File { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } + } -impl AsRawFd for old_io::fs::File { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for fs::File { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd().raw() + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for fs::File { + fn from_raw_fd(fd: RawFd) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(fd)) + } } -} -impl AsRawFd for fs::File { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd().raw() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for old_io::pipe::PipeStream { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::pipe::PipeStream { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for old_io::net::pipe::UnixStream { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::pipe::UnixStream { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for old_io::net::pipe::UnixListener { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::pipe::UnixListener { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for old_io::net::pipe::UnixAcceptor { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::pipe::UnixAcceptor { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] + impl AsRawFd for old_io::net::tcp::TcpStream { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::tcp::TcpStream { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] + impl AsRawFd for old_io::net::tcp::TcpListener { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::tcp::TcpListener { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[stable(feature = "rust1", since = "1.0.0")] + #[allow(deprecated)] + impl AsRawFd for old_io::net::tcp::TcpAcceptor { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::tcp::TcpAcceptor { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for old_io::net::udp::UdpSocket { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd() + } } -} -impl AsRawFd for old_io::net::udp::UdpSocket { - fn as_raw_fd(&self) -> Fd { - self.as_inner().fd() + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for net::TcpStream { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for net::TcpListener { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for net::UdpSocket { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } } -} -impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } -} -impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } -} -impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpStream { + fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(net2::TcpStream::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::TcpListener { + fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(net2::TcpListener::from_inner(socket)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawFd for net::UdpSocket { + fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket)) + } + } } //////////////////////////////////////////////////////////////////////////////// // OsString and OsStr //////////////////////////////////////////////////////////////////////////////// -/// Unix-specific extensions to `OsString`. -pub trait OsStringExt { - /// Create an `OsString` from a byte vector. - fn from_vec(vec: Vec) -> Self; - - /// Yield the underlying byte vector of this `OsString`. - fn into_vec(self) -> Vec; -} - -impl OsStringExt for OsString { - fn from_vec(vec: Vec) -> OsString { - FromInner::from_inner(Buf { inner: vec }) +/// Unix-specific extension to the primitives in the `std::ffi` module +#[stable(feature = "rust1", since = "1.0.0")] +pub mod ffi { + use ffi::{OsStr, OsString}; + use mem; + use prelude::v1::*; + use sys::os_str::Buf; + use sys_common::{FromInner, IntoInner, AsInner}; + + /// Unix-specific extensions to `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStringExt { + /// Create an `OsString` from a byte vector. + #[stable(feature = "rust1", since = "1.0.0")] + fn from_vec(vec: Vec) -> Self; + + /// Yield the underlying byte vector of this `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + fn into_vec(self) -> Vec; } - fn into_vec(self) -> Vec { - self.into_inner().inner + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStringExt for OsString { + fn from_vec(vec: Vec) -> OsString { + FromInner::from_inner(Buf { inner: vec }) + } + fn into_vec(self) -> Vec { + self.into_inner().inner + } } -} - -/// Unix-specific extensions to `OsStr`. -pub trait OsStrExt { - fn from_bytes(slice: &[u8]) -> &OsStr; - /// Get the underlying byte view of the `OsStr` slice. - fn as_bytes(&self) -> &[u8]; + /// Unix-specific extensions to `OsStr`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStrExt { + #[stable(feature = "rust1", since = "1.0.0")] + fn from_bytes(slice: &[u8]) -> &Self; - /// Convert the `OsStr` slice into a `CString`. - fn to_cstring(&self) -> Result; -} - -impl OsStrExt for OsStr { - fn from_bytes(slice: &[u8]) -> &OsStr { - unsafe { mem::transmute(slice) } - } - fn as_bytes(&self) -> &[u8] { - &self.as_inner().inner + /// Get the underlying byte view of the `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_bytes(&self) -> &[u8]; } - fn to_cstring(&self) -> Result { - CString::new(self.as_bytes()) + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStrExt for OsStr { + fn from_bytes(slice: &[u8]) -> &OsStr { + unsafe { mem::transmute(slice) } + } + fn as_bytes(&self) -> &[u8] { + &self.as_inner().inner + } } } -// Unix-specific extensions to `Permissions` -pub trait PermissionsExt { - fn set_mode(&mut self, mode: i32); -} +/// Unix-specific extensions to primitives in the `std::fs` module. +#[unstable(feature = "fs_ext", + reason = "may want a more useful mode abstraction")] +pub mod fs { + use sys_common::{FromInner, AsInner, AsInnerMut}; + use fs::{Permissions, OpenOptions}; + + /// Unix-specific extensions to `Permissions` + pub trait PermissionsExt { + fn mode(&self) -> i32; + fn set_mode(&mut self, mode: i32); + } -impl PermissionsExt for Permissions { - fn set_mode(&mut self, mode: i32) { - *self = FromInner::from_inner(FromInner::from_inner(mode)); + impl PermissionsExt for Permissions { + fn mode(&self) -> i32 { self.as_inner().mode() } + + fn set_mode(&mut self, mode: i32) { + *self = FromInner::from_inner(FromInner::from_inner(mode)); + } } -} -// Unix-specific extensions to `OpenOptions` -pub trait OpenOptionsExt { - /// Set the mode bits that a new file will be created with. - /// - /// If a new file is created as part of a `File::open_opts` call then this - /// specified `mode` will be used as the permission bits for the new file. - fn mode(&mut self, mode: i32) -> &mut Self; -} + /// Unix-specific extensions to `OpenOptions` + pub trait OpenOptionsExt { + /// Set the mode bits that a new file will be created with. + /// + /// If a new file is created as part of a `File::open_opts` call then this + /// specified `mode` will be used as the permission bits for the new file. + fn mode(&mut self, mode: i32) -> &mut Self; + } -impl OpenOptionsExt for OpenOptions { - fn mode(&mut self, mode: i32) -> &mut OpenOptions { - self.as_inner_mut().mode(mode); self + impl OpenOptionsExt for OpenOptions { + fn mode(&mut self, mode: i32) -> &mut OpenOptions { + self.as_inner_mut().mode(mode); self + } } } @@ -201,41 +298,58 @@ impl OpenOptionsExt for OpenOptions { // Process and Command //////////////////////////////////////////////////////////////////////////////// -/// Unix-specific extensions to the `std::process::Command` builder -pub trait CommandExt { - /// Sets the child process's user id. This translates to a - /// `setuid` call in the child process. Failure in the `setuid` - /// call will cause the spawn to fail. - fn uid(&mut self, id: uid_t) -> &mut process::Command; +/// Unix-specific extensions to primitives in the `std::process` module. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod process { + use prelude::v1::*; + use libc::{uid_t, gid_t}; + use process; + use sys; + use sys_common::{AsInnerMut, AsInner}; + + /// Unix-specific extensions to the `std::process::Command` builder + #[stable(feature = "rust1", since = "1.0.0")] + pub trait CommandExt { + /// Sets the child process's user id. This translates to a + /// `setuid` call in the child process. Failure in the `setuid` + /// call will cause the spawn to fail. + #[stable(feature = "rust1", since = "1.0.0")] + fn uid(&mut self, id: uid_t) -> &mut process::Command; + + /// Similar to `uid`, but sets the group id of the child process. This has + /// the same semantics as the `uid` field. + #[stable(feature = "rust1", since = "1.0.0")] + fn gid(&mut self, id: gid_t) -> &mut process::Command; + } - /// Similar to `uid`, but sets the group id of the child process. This has - /// the same semantics as the `uid` field. - fn gid(&mut self, id: gid_t) -> &mut process::Command; -} + #[stable(feature = "rust1", since = "1.0.0")] + impl CommandExt for process::Command { + fn uid(&mut self, id: uid_t) -> &mut process::Command { + self.as_inner_mut().uid = Some(id); + self + } -impl CommandExt for process::Command { - fn uid(&mut self, id: uid_t) -> &mut process::Command { - self.as_inner_mut().uid = Some(id); - self + fn gid(&mut self, id: gid_t) -> &mut process::Command { + self.as_inner_mut().gid = Some(id); + self + } } - fn gid(&mut self, id: gid_t) -> &mut process::Command { - self.as_inner_mut().gid = Some(id); - self + /// Unix-specific extensions to `std::process::ExitStatus` + #[stable(feature = "rust1", since = "1.0.0")] + pub trait ExitStatusExt { + /// If the process was terminated by a signal, returns that signal. + #[stable(feature = "rust1", since = "1.0.0")] + fn signal(&self) -> Option; } -} - -/// Unix-specific extensions to `std::process::ExitStatus` -pub trait ExitStatusExt { - /// If the process was terminated by a signal, returns that signal. - fn signal(&self) -> Option; -} -impl ExitStatusExt for process::ExitStatus { - fn signal(&self) -> Option { - match *self.as_inner() { - sys::process2::ExitStatus::Signal(s) => Some(s), - _ => None + #[stable(feature = "rust1", since = "1.0.0")] + impl ExitStatusExt for process::ExitStatus { + fn signal(&self) -> Option { + match *self.as_inner() { + sys::process2::ExitStatus::Signal(s) => Some(s), + _ => None + } } } } @@ -247,9 +361,14 @@ impl ExitStatusExt for process::ExitStatus { /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt}; + pub use super::io::{RawFd, AsRawFd}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] - pub use super::{CommandExt, ExitStatusExt}; + pub use super::fs::{PermissionsExt, OpenOptionsExt}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::process::{CommandExt, ExitStatusExt}; } diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 327d117823..f7c57c3f5e 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -9,7 +9,6 @@ // except according to those terms. use core::prelude::*; -use io::prelude::*; use io; use libc::{self, c_int, size_t, c_void}; diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 5c847002d2..6b085c8eb7 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -9,6 +9,9 @@ // except according to those terms. //! Blocking posix-based file I/O +#![allow(deprecated)] + +#![allow(deprecated)] // this module itself is essentially deprecated use prelude::v1::*; @@ -17,6 +20,7 @@ use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode use old_io::{IoResult, FileStat, SeekStyle}; use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append}; use old_io; +use old_path::{Path, GenericPath}; use libc::{self, c_int, c_void}; use mem; use ptr; @@ -38,7 +42,7 @@ impl FileDesc { FileDesc { fd: fd, close_on_drop: close_on_drop } } - pub fn read(&self, buf: &mut [u8]) -> IoResult { + pub fn read(&self, buf: &mut [u8]) -> IoResult { let ret = retry(|| unsafe { libc::read(self.fd(), buf.as_mut_ptr() as *mut libc::c_void, @@ -49,7 +53,7 @@ impl FileDesc { } else if ret < 0 { Err(super::last_error()) } else { - Ok(ret as uint) + Ok(ret as usize) } } pub fn write(&self, buf: &[u8]) -> IoResult<()> { @@ -177,7 +181,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { } } -pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> { +pub fn mkdir(p: &Path, mode: usize) -> IoResult<()> { let p = try!(cstr(p)); mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) }) } @@ -200,13 +204,13 @@ pub fn readdir(p: &Path) -> IoResult> { } let size = unsafe { rust_dirent_t_size() }; - let mut buf = Vec::::with_capacity(size as uint); + let mut buf = Vec::::with_capacity(size as usize); let ptr = buf.as_mut_ptr() as *mut dirent_t; let p = try!(CString::new(p.as_vec())); let dir_ptr = unsafe {opendir(p.as_ptr())}; - if dir_ptr as uint != 0 { + if dir_ptr as usize != 0 { let mut paths = vec!(); let mut entry_ptr = ptr::null_mut(); while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } { @@ -235,7 +239,7 @@ pub fn rename(old: &Path, new: &Path) -> IoResult<()> { }) } -pub fn chmod(p: &Path, mode: uint) -> IoResult<()> { +pub fn chmod(p: &Path, mode: usize) -> IoResult<()> { let p = try!(cstr(p)); mkerr_libc(retry(|| unsafe { libc::chmod(p.as_ptr(), mode as libc::mode_t) @@ -247,7 +251,7 @@ pub fn rmdir(p: &Path) -> IoResult<()> { mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) }) } -pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> { +pub fn chown(p: &Path, uid: isize, gid: isize) -> IoResult<()> { let p = try!(cstr(p)); mkerr_libc(retry(|| unsafe { libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) @@ -261,7 +265,7 @@ pub fn readlink(p: &Path) -> IoResult { if len == -1 { len = 1024; // FIXME: read PATH_MAX from C ffi? } - let mut buf: Vec = Vec::with_capacity(len as uint); + let mut buf: Vec = Vec::with_capacity(len as usize); match unsafe { libc::readlink(p, buf.as_ptr() as *mut libc::c_char, len as libc::size_t) as libc::c_int @@ -269,7 +273,7 @@ pub fn readlink(p: &Path) -> IoResult { -1 => Err(super::last_error()), n => { assert!(n > 0); - unsafe { buf.set_len(n as uint); } + unsafe { buf.set_len(n as usize); } Ok(Path::new(buf)) } } @@ -291,6 +295,18 @@ fn mkstat(stat: &libc::stat) -> FileStat { // FileStat times are in milliseconds fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 } + fn ctime(stat: &libc::stat) -> u64 { + mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64) + } + + fn atime(stat: &libc::stat) -> u64 { + mktime(stat.st_atime as u64, stat.st_atime_nsec as u64) + } + + fn mtime(stat: &libc::stat) -> u64 { + mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64) + } + #[cfg(not(any(target_os = "linux", target_os = "android")))] fn flags(stat: &libc::stat) -> u64 { stat.st_flags as u64 } #[cfg(any(target_os = "linux", target_os = "android"))] @@ -312,9 +328,9 @@ fn mkstat(stat: &libc::stat) -> FileStat { _ => old_io::FileType::Unknown, }, perm: FilePermission::from_bits_truncate(stat.st_mode as u32), - created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64), - modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64), - accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64), + created: ctime(stat), + modified: mtime(stat), + accessed: atime(stat), unstable: UnstableFileStat { device: stat.st_dev as u64, inode: stat.st_ino as u64, @@ -372,12 +388,10 @@ mod tests { fn test_file_desc() { // Run this test with some pipes so we don't have to mess around with // opening or closing files. - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let mut reader = FileDesc::new(reader, true); - let mut writer = FileDesc::new(writer, true); + let (mut reader, mut writer) = unsafe { ::sys::os::pipe().unwrap() }; - writer.write(b"test").ok().unwrap(); - let mut buf = [0u8; 4]; + writer.write(b"test").unwrap(); + let mut buf = [0; 4]; match reader.read(&mut buf) { Ok(4) => { assert_eq!(buf[0], 't' as u8); diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 92a47c6c38..c0426af051 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -12,13 +12,13 @@ use core::prelude::*; use io::prelude::*; use os::unix::prelude::*; -use ffi::{CString, CStr, OsString, AsOsStr, OsStr}; -use io::{self, Error, Seek, SeekFrom}; -use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t}; +use ffi::{CString, CStr, OsString, OsStr}; +use io::{self, Error, SeekFrom}; +use libc::{self, c_int, size_t, off_t, c_char, mode_t}; use mem; use path::{Path, PathBuf}; use ptr; -use rc::Rc; +use sync::Arc; use sys::fd::FileDesc; use sys::{c, cvt, cvt_r}; use sys_common::FromInner; @@ -31,14 +31,18 @@ pub struct FileAttr { } pub struct ReadDir { - dirp: *mut libc::DIR, - root: Rc, + dirp: Dir, + root: Arc, } +struct Dir(*mut libc::DIR); + +unsafe impl Send for Dir {} +unsafe impl Sync for Dir {} + pub struct DirEntry { - buf: Vec, - dirent: *mut libc::dirent_t, - root: Rc, + buf: Vec, // actually *mut libc::dirent_t + root: Arc, } #[derive(Clone)] @@ -86,6 +90,7 @@ impl FilePermissions { self.mode |= 0o222; } } + pub fn mode(&self) -> i32 { self.mode as i32 } } impl FromInner for FilePermissions { @@ -109,7 +114,7 @@ impl Iterator for ReadDir { let mut entry_ptr = ptr::null_mut(); loop { - if unsafe { libc::readdir_r(self.dirp, ptr, &mut entry_ptr) != 0 } { + if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } { return Some(Err(Error::last_os_error())) } if entry_ptr.is_null() { @@ -118,7 +123,6 @@ impl Iterator for ReadDir { let entry = DirEntry { buf: buf, - dirent: entry_ptr, root: self.root.clone() }; if entry.name_bytes() == b"." || entry.name_bytes() == b".." { @@ -130,9 +134,9 @@ impl Iterator for ReadDir { } } -impl Drop for ReadDir { +impl Drop for Dir { fn drop(&mut self) { - let r = unsafe { libc::closedir(self.dirp) }; + let r = unsafe { libc::closedir(self.0) }; debug_assert_eq!(r, 0); } } @@ -147,9 +151,13 @@ impl DirEntry { fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char; } unsafe { - CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes() + CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes() } } + + fn dirent(&self) -> *mut libc::dirent_t { + self.buf.as_ptr() as *mut _ + } } impl OpenOptions { @@ -268,8 +276,14 @@ impl File { } fn cstr(path: &Path) -> io::Result { - let cstring = try!(path.as_os_str().to_cstring()); - Ok(cstring) + path.as_os_str().to_cstring().ok_or( + io::Error::new(io::ErrorKind::InvalidInput, "path contained a null")) +} + +impl FromInner for File { + fn from_inner(fd: c_int) -> File { + File(FileDesc::new(fd)) + } } pub fn mkdir(p: &Path) -> io::Result<()> { @@ -279,14 +293,14 @@ pub fn mkdir(p: &Path) -> io::Result<()> { } pub fn readdir(p: &Path) -> io::Result { - let root = Rc::new(p.to_path_buf()); + let root = Arc::new(p.to_path_buf()); let p = try!(cstr(p)); unsafe { let ptr = libc::opendir(p.as_ptr()); if ptr.is_null() { Err(Error::last_os_error()) } else { - Ok(ReadDir { dirp: ptr, root: root }) + Ok(ReadDir { dirp: Dir(ptr), root: root }) } } } @@ -316,14 +330,6 @@ pub fn rmdir(p: &Path) -> io::Result<()> { Ok(()) } -pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> { - let p = try!(cstr(p)); - try!(cvt_r(|| unsafe { - libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) - })); - Ok(()) -} - pub fn readlink(p: &Path) -> io::Result { let c_path = try!(cstr(p)); let p = c_path.as_ptr(); @@ -338,8 +344,7 @@ pub fn readlink(p: &Path) -> io::Result { })); buf.set_len(n as usize); } - let s: OsString = OsStringExt::from_vec(buf); - Ok(PathBuf::new(&s)) + Ok(PathBuf::from(OsString::from_vec(buf))) } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { diff --git a/src/libstd/sys/unix/helper_signal.rs b/src/libstd/sys/unix/helper_signal.rs index ed9bd0a239..fe0ede80fc 100644 --- a/src/libstd/sys/unix/helper_signal.rs +++ b/src/libstd/sys/unix/helper_signal.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use libc; -use os; +use sys::os; use sys::fs::FileDesc; pub type signal = libc::c_int; pub fn new() -> (signal, signal) { - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - (reader, writer) + let (a, b) = unsafe { os::pipe().unwrap() }; + (a.unwrap(), b.unwrap()) } pub fn signal(fd: libc::c_int) { - FileDesc::new(fd, false).write(&[0]).ok().unwrap(); + FileDesc::new(fd, false).write(&[0]).unwrap(); } pub fn close(fd: libc::c_int) { diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index b79ad7031f..e8409bb4fd 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -10,10 +10,6 @@ #![allow(missing_docs)] #![allow(non_camel_case_types)] -#![allow(unused_imports)] -#![allow(dead_code)] -#![allow(unused_unsafe)] -#![allow(unused_mut)] use prelude::v1::*; @@ -21,22 +17,10 @@ use ffi::CStr; use io::{self, ErrorKind}; use libc; use num::{Int, SignedInt}; -use num; -use old_io::{self, IoResult, IoError}; +use old_io::{self, IoError}; use str; use sys_common::mkerr_libc; -macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( - static $name: Helper<$m> = Helper { - lock: ::sync::MUTEX_INIT, - cond: ::sync::CONDVAR_INIT, - chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, - signal: ::cell::UnsafeCell { value: 0 }, - initialized: ::cell::UnsafeCell { value: false }, - shutdown: ::cell::UnsafeCell { value: false }, - }; -) } - pub mod backtrace; pub mod c; pub mod condvar; @@ -63,6 +47,7 @@ pub mod time; pub mod timer; pub mod tty; pub mod udp; +pub mod stdio; pub mod addrinfo { pub use sys_common::net::get_host_addresses; @@ -75,10 +60,12 @@ pub type wrlen = libc::size_t; pub type msglen_t = libc::size_t; pub unsafe fn close_sock(sock: sock_t) { let _ = libc::close(sock); } +#[allow(deprecated)] pub fn last_error() -> IoError { decode_error_detailed(os::errno() as i32) } +#[allow(deprecated)] pub fn last_net_error() -> IoError { last_error() } @@ -87,6 +74,7 @@ extern "system" { fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char; } +#[allow(deprecated)] pub fn last_gai_error(s: libc::c_int) -> IoError { let mut err = decode_error(s); @@ -98,6 +86,7 @@ pub fn last_gai_error(s: libc::c_int) -> IoError { } /// Convert an `errno` value into a high-level error variant and description. +#[allow(deprecated)] pub fn decode_error(errno: i32) -> IoError { // FIXME: this should probably be a bit more descriptive... let (kind, desc) = match errno { @@ -134,12 +123,14 @@ pub fn decode_error(errno: i32) -> IoError { IoError { kind: kind, desc: desc, detail: None } } +#[allow(deprecated)] pub fn decode_error_detailed(errno: i32) -> IoError { let mut err = decode_error(errno); err.detail = Some(os::error_string(errno)); err } +#[allow(deprecated)] pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as libc::c_int { libc::ECONNREFUSED => ErrorKind::ConnectionRefused, @@ -148,28 +139,26 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::EPIPE => ErrorKind::BrokenPipe, libc::ENOTCONN => ErrorKind::NotConnected, libc::ECONNABORTED => ErrorKind::ConnectionAborted, - libc::EADDRNOTAVAIL => ErrorKind::ConnectionRefused, - libc::EADDRINUSE => ErrorKind::ConnectionRefused, - libc::ENOENT => ErrorKind::FileNotFound, - libc::EISDIR => ErrorKind::InvalidInput, + libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + libc::EADDRINUSE => ErrorKind::AddrInUse, + libc::ENOENT => ErrorKind::NotFound, libc::EINTR => ErrorKind::Interrupted, libc::EINVAL => ErrorKind::InvalidInput, - libc::ENOTTY => ErrorKind::MismatchedFileTypeForOperation, libc::ETIMEDOUT => ErrorKind::TimedOut, - libc::ECANCELED => ErrorKind::TimedOut, - libc::consts::os::posix88::EEXIST => ErrorKind::PathAlreadyExists, + libc::consts::os::posix88::EEXIST => ErrorKind::AlreadyExists, // These two constants can have the same value on some systems, // but different values on others, so we can't use a match // clause x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => - ErrorKind::ResourceUnavailable, + ErrorKind::WouldBlock, _ => ErrorKind::Other, } } #[inline] +#[allow(deprecated)] pub fn retry (mut f: F) -> T where T: SignedInt, F: FnMut() -> T, @@ -182,6 +171,7 @@ pub fn retry (mut f: F) -> T where } } +#[allow(deprecated)] pub fn cvt(t: T) -> io::Result { let one: T = Int::one(); if t == -one { @@ -191,6 +181,7 @@ pub fn cvt(t: T) -> io::Result { } } +#[allow(deprecated)] pub fn cvt_r(mut f: F) -> io::Result where T: SignedInt, F: FnMut() -> T { @@ -209,14 +200,16 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { } } +#[allow(deprecated)] pub fn wouldblock() -> bool { let err = os::errno(); err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32 } -pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { +#[allow(deprecated)] +pub fn set_nonblocking(fd: sock_t, nb: bool) { let set = nb as libc::c_int; - mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })) + mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap(); } // nothing needed on unix platforms diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs index 9e1527aef2..1c0ce29380 100644 --- a/src/libstd/sys/unix/mutex.rs +++ b/src/libstd/sys/unix/mutex.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; -use marker::Sync; use sys::sync as ffi; -use sys_common::mutex; pub struct Mutex { inner: UnsafeCell } @@ -24,8 +24,10 @@ pub const MUTEX_INIT: Mutex = Mutex { inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER }, }; +unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} +#[allow(dead_code)] // sys isn't exported yet impl Mutex { #[inline] pub unsafe fn new() -> Mutex { diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 83b6a14b78..908136a42a 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -15,9 +15,9 @@ use io; use libc::{self, c_int, size_t}; use str; use sys::c; -use net::{SocketAddr, IpAddr}; +use net::SocketAddr; use sys::fd::FileDesc; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub use sys::{cvt, cvt_r}; @@ -35,14 +35,15 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { .to_string() }; Err(io::Error::new(io::ErrorKind::Other, - "failed to lookup address information", Some(detail))) + &format!("failed to lookup address information: {}", + detail)[..])) } impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { - let fam = match addr.ip() { - IpAddr::V4(..) => libc::AF_INET, - IpAddr::V6(..) => libc::AF_INET6, + let fam = match *addr { + SocketAddr::V4(..) => libc::AF_INET, + SocketAddr::V6(..) => libc::AF_INET6, }; unsafe { let fd = try!(cvt(libc::socket(fam, ty, 0))); @@ -72,3 +73,7 @@ impl Socket { impl AsInner for Socket { fn as_inner(&self) -> &c_int { self.0.as_inner() } } + +impl FromInner for Socket { + fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) } +} diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 3d1ef3a2c3..d2220bdec3 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -10,18 +10,21 @@ //! Implementation of `std::os` functionality for unix systems +#![allow(unused_imports)] // lots of cfg code here + use prelude::v1::*; -use os::unix::*; +use os::unix::prelude::*; use error::Error as StdError; -use ffi::{CString, CStr, OsString, OsStr, AsOsStr}; +use ffi::{CString, CStr, OsString, OsStr}; use fmt; +use io; use iter; use libc::{self, c_int, c_char, c_void}; use mem; -use io; -use old_io::{IoResult, IoError, fs}; +#[allow(deprecated)] use old_io::{IoError, IoResult}; use ptr; +use path::{self, PathBuf}; use slice; use str; use sys::c; @@ -32,6 +35,14 @@ use vec; const BUF_BYTES: usize = 2048; const TMPBUF_SZ: usize = 128; +fn bytes2path(b: &[u8]) -> PathBuf { + PathBuf::from(::from_bytes(b)) +} + +fn os2path(os: OsString) -> PathBuf { + bytes2path(os.as_bytes()) +} + /// Returns the platform-specific value of errno pub fn errno() -> i32 { #[cfg(any(target_os = "macos", @@ -42,6 +53,16 @@ pub fn errno() -> i32 { __error() } + #[cfg(target_os = "bitrig")] + fn errno_location() -> *const c_int { + extern { + fn __errno() -> *const c_int; + } + unsafe { + __errno() + } + } + #[cfg(target_os = "dragonfly")] unsafe fn errno_location() -> *const c_int { extern { fn __dfly_error() -> *const c_int; } @@ -92,30 +113,31 @@ pub fn error_string(errno: i32) -> String { } } -pub fn getcwd() -> IoResult { +pub fn getcwd() -> io::Result { 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()) + Err(io::Error::last_os_error()) } else { - Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes())) + Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes())) } } } -pub fn chdir(p: &Path) -> IoResult<()> { - let p = CString::new(p.as_vec()).unwrap(); +pub fn chdir(p: &path::Path) -> io::Result<()> { + let p: &OsStr = p.as_ref(); + let p = try!(CString::new(p.as_bytes())); unsafe { match libc::chdir(p.as_ptr()) == (0 as c_int) { true => Ok(()), - false => Err(IoError::last_error()), + false => Err(io::Error::last_os_error()), } } } pub struct SplitPaths<'a> { iter: iter::Map bool>, - fn(&'a [u8]) -> Path>, + fn(&'a [u8]) -> PathBuf>, } pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> { @@ -123,13 +145,13 @@ pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> { let unparsed = unparsed.as_bytes(); SplitPaths { iter: unparsed.split(is_colon as fn(&u8) -> bool) - .map(Path::new as fn(&'a [u8]) -> Path) + .map(bytes2path as fn(&'a [u8]) -> PathBuf) } } impl<'a> Iterator for SplitPaths<'a> { - type Item = Path; - fn next(&mut self) -> Option { self.iter.next() } + type Item = PathBuf; + fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } @@ -137,13 +159,13 @@ impl<'a> Iterator for SplitPaths<'a> { pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: Iterator, T: AsRef { let mut joined = Vec::new(); let sep = b':'; for (i, path) in paths.enumerate() { - let path = path.as_os_str().as_bytes(); + let path = path.as_ref().as_bytes(); if i > 0 { joined.push(sep) } if path.contains(&sep) { return Err(JoinPathsError) @@ -164,7 +186,7 @@ impl StdError for JoinPathsError { } #[cfg(target_os = "freebsd")] -pub fn current_exe() -> IoResult { +pub fn current_exe() -> io::Result { unsafe { use libc::funcs::bsd44::*; use libc::consts::os::extra::*; @@ -176,28 +198,27 @@ pub fn current_exe() -> IoResult { let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, ptr::null_mut(), &mut sz, ptr::null_mut(), 0 as libc::size_t); - if err != 0 { return Err(IoError::last_error()); } - if sz == 0 { return Err(IoError::last_error()); } - let mut v: Vec = Vec::with_capacity(sz as uint); + if err != 0 { return Err(io::Error::last_os_error()); } + if sz == 0 { return Err(io::Error::last_os_error()); } + let mut v: Vec = Vec::with_capacity(sz as usize); let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint, v.as_mut_ptr() as *mut libc::c_void, &mut sz, ptr::null_mut(), 0 as libc::size_t); - if err != 0 { return Err(IoError::last_error()); } - if sz == 0 { return Err(IoError::last_error()); } - v.set_len(sz as uint - 1); // chop off trailing NUL - Ok(Path::new(v)) + if err != 0 { return Err(io::Error::last_os_error()); } + if sz == 0 { return Err(io::Error::last_os_error()); } + v.set_len(sz as usize - 1); // chop off trailing NUL + Ok(PathBuf::from(OsString::from_vec(v))) } } #[cfg(target_os = "dragonfly")] -pub fn current_exe() -> IoResult { - fs::readlink(&Path::new("/proc/curproc/file")) +pub fn current_exe() -> io::Result { + ::fs::read_link("/proc/curproc/file") } -#[cfg(target_os = "openbsd")] -pub fn current_exe() -> IoResult { +#[cfg(any(target_os = "bitrig", target_os = "openbsd"))] +pub fn current_exe() -> io::Result { use sync::{StaticMutex, MUTEX_INIT}; - static LOCK: StaticMutex = MUTEX_INIT; extern { @@ -209,30 +230,31 @@ pub fn current_exe() -> IoResult { unsafe { let v = rust_current_exe(); if v.is_null() { - Err(IoError::last_error()) + Err(io::Error::last_os_error()) } else { - Ok(Path::new(CStr::from_ptr(&v).to_bytes().to_vec())) + let vec = CStr::from_ptr(v).to_bytes().to_vec(); + Ok(PathBuf::from(OsString::from_vec(vec))) } } } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn current_exe() -> IoResult { - fs::readlink(&Path::new("/proc/self/exe")) +pub fn current_exe() -> io::Result { + ::fs::read_link("/proc/self/exe") } #[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn current_exe() -> IoResult { +pub fn current_exe() -> io::Result { unsafe { use libc::funcs::extra::_NSGetExecutablePath; let mut sz: u32 = 0; _NSGetExecutablePath(ptr::null_mut(), &mut sz); - if sz == 0 { return Err(IoError::last_error()); } - let mut v: Vec = Vec::with_capacity(sz as uint); + if sz == 0 { return Err(io::Error::last_os_error()); } + let mut v: Vec = Vec::with_capacity(sz as usize); let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); - if err != 0 { return Err(IoError::last_error()); } - v.set_len(sz as uint - 1); // chop off trailing NUL - Ok(Path::new(v)) + if err != 0 { return Err(io::Error::last_os_error()); } + v.set_len(sz as usize - 1); // chop off trailing NUL + Ok(PathBuf::from(OsString::from_vec(v))) } } @@ -265,7 +287,7 @@ pub fn args() -> Args { let vec = unsafe { let (argc, argv) = (*_NSGetArgc() as isize, *_NSGetArgv() as *const *const c_char); - range(0, argc as isize).map(|i| { + (0.. argc as isize).map(|i| { let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec(); OsStringExt::from_vec(bytes) }).collect::>() @@ -285,12 +307,11 @@ pub fn args() -> Args { // In general it looks like: // res = Vec::new() // let args = [[NSProcessInfo processInfo] arguments] -// for i in range(0, [args count]) +// for i in (0..[args count]) // res.push([args objectAtIndex:i]) // res #[cfg(target_os = "ios")] pub fn args() -> Args { - use iter::range; use mem; #[link(name = "objc")] @@ -319,13 +340,13 @@ pub fn args() -> Args { let info = objc_msgSend(klass, process_info_sel); let args = objc_msgSend(info, arguments_sel); - let cnt: int = mem::transmute(objc_msgSend(args, count_sel)); - for i in range(0, cnt) { + let cnt: usize = mem::transmute(objc_msgSend(args, count_sel)); + for i in (0..cnt) { let tmp = objc_msgSend(args, object_at_sel, i); let utf_c_str: *const libc::c_char = mem::transmute(objc_msgSend(tmp, utf8_sel)); let bytes = CStr::from_ptr(utf_c_str).to_bytes(); - res.push(OsString::from_str(str::from_utf8(bytes).unwrap())) + res.push(OsString::from(str::from_utf8(bytes).unwrap())) } } @@ -336,6 +357,7 @@ pub fn args() -> Args { target_os = "android", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub fn args() -> Args { use rt; @@ -376,7 +398,7 @@ pub fn env() -> Env { let mut environ = *environ(); if environ as usize == 0 { panic!("os::env() failure getting env string from OS: {}", - IoError::last_error()); + io::Error::last_os_error()); } let mut result = Vec::new(); while *environ != ptr::null() { @@ -387,7 +409,7 @@ pub fn env() -> Env { }; fn parse(input: &[u8]) -> (OsString, OsString) { - let mut it = input.splitn(1, |b| *b == b'='); + let mut it = input.splitn(2, |b| *b == b'='); let key = it.next().unwrap().to_vec(); let default: &[u8] = &[]; let val = it.next().unwrap_or(default).to_vec(); @@ -412,7 +434,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) { let k = k.to_cstring().unwrap(); let v = v.to_cstring().unwrap(); if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { - panic!("failed setenv: {}", IoError::last_error()); + panic!("failed setenv: {}", io::Error::last_os_error()); } } } @@ -421,11 +443,12 @@ pub fn unsetenv(n: &OsStr) { unsafe { let nbuf = n.to_cstring().unwrap(); if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { - panic!("failed unsetenv: {}", IoError::last_error()); + panic!("failed unsetenv: {}", io::Error::last_os_error()); } } } +#[allow(deprecated)] pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { let mut fds = [0; 2]; if libc::pipe(fds.as_mut_ptr()) == 0 { @@ -441,22 +464,20 @@ pub fn page_size() -> usize { } } -pub fn temp_dir() -> Path { - getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| { +pub fn temp_dir() -> PathBuf { + getenv("TMPDIR".as_ref()).map(os2path).unwrap_or_else(|| { if cfg!(target_os = "android") { - Path::new("/data/local/tmp") + PathBuf::from("/data/local/tmp") } else { - Path::new("/tmp") + PathBuf::from("/tmp") } }) } -pub fn home_dir() -> Option { - return getenv("HOME".as_os_str()).or_else(|| unsafe { +pub fn home_dir() -> Option { + return getenv("HOME".as_ref()).or_else(|| unsafe { fallback() - }).map(|os| { - Path::new(os.into_vec()) - }); + }).map(os2path); #[cfg(any(target_os = "android", target_os = "ios"))] @@ -464,7 +485,7 @@ pub fn home_dir() -> Option { #[cfg(not(any(target_os = "android", target_os = "ios")))] unsafe fn fallback() -> Option { - let mut amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { + let amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, }; @@ -485,3 +506,7 @@ pub fn home_dir() -> Option { } } } + +pub fn exit(code: i32) -> ! { + unsafe { libc::exit(code as c_int) } +} diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs index 023d951dc4..69d876a48a 100644 --- a/src/libstd/sys/unix/os_str.rs +++ b/src/libstd/sys/unix/os_str.rs @@ -13,11 +13,11 @@ use core::prelude::*; +use borrow::Cow; use fmt::{self, Debug}; use vec::Vec; -use slice::SliceExt as StdSliceExt; use str; -use string::{String, CowString}; +use string::String; use mem; #[derive(Clone, Hash)] @@ -46,10 +46,6 @@ impl Buf { Buf { inner: s.into_bytes() } } - pub fn from_str(s: &str) -> Buf { - Buf { inner: s.as_bytes().to_vec() } - } - pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } @@ -69,14 +65,14 @@ impl Slice { } pub fn from_str(s: &str) -> &Slice { - unsafe { mem::transmute(s.as_bytes()) } + Slice::from_u8_slice(s.as_bytes()) } pub fn to_str(&self) -> Option<&str> { str::from_utf8(&self.inner).ok() } - pub fn to_string_lossy(&self) -> CowString { + pub fn to_string_lossy(&self) -> Cow { String::from_utf8_lossy(&self.inner) } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 3c9cdc6597..f0071295bf 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use ffi::CString; @@ -143,13 +145,13 @@ impl UnixStream { fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { let ret = Guard { fd: self.fd(), - guard: unsafe { self.inner.lock.lock().unwrap() }, + guard: self.inner.lock.lock().unwrap(), }; - assert!(set_nonblocking(self.fd(), true).is_ok()); + set_nonblocking(self.fd(), true); ret } - pub fn read(&mut self, buf: &mut [u8]) -> IoResult { + pub fn read(&mut self, buf: &mut [u8]) -> IoResult { let fd = self.fd(); let dolock = || self.lock_nonblocking(); let doread = |nb| unsafe { @@ -165,7 +167,7 @@ impl UnixStream { pub fn write(&mut self, buf: &[u8]) -> IoResult<()> { let fd = self.fd(); let dolock = || self.lock_nonblocking(); - let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe { + let dowrite = |nb: bool, buf: *const u8, len: usize| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::send(fd, buf as *const _, @@ -235,9 +237,9 @@ impl UnixListener { _ => { let (reader, writer) = try!(unsafe { sys::os::pipe() }); - try!(set_nonblocking(reader.fd(), true)); - try!(set_nonblocking(writer.fd(), true)); - try!(set_nonblocking(self.fd(), true)); + set_nonblocking(reader.fd(), true); + set_nonblocking(writer.fd(), true); + set_nonblocking(self.fd(), true); Ok(UnixAcceptor { inner: Arc::new(AcceptorInner { listener: self, diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index b30ac88912..8095325f83 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -8,19 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] // this module itself is essentially deprecated + use prelude::v1::*; use self::Req::*; use collections::HashMap; -#[cfg(stage0)] -use collections::hash_map::Hasher; use ffi::CString; use hash::Hash; use old_io::process::{ProcessExit, ExitStatus, ExitSignal}; -use old_io::{self, IoResult, IoError, EndOfFile}; +use old_io::{IoResult, EndOfFile}; use libc::{self, pid_t, c_void, c_int}; +use io; use mem; -use os; +use sys::os; use old_path::BytesContainer; use ptr; use sync::mpsc::{channel, Sender, Receiver}; @@ -33,12 +34,6 @@ pub use sys_common::ProcessConfig; helper_init! { static HELPER: Helper } -/// Unix-specific extensions to the Command builder -pub struct CommandExt { - uid: Option, - gid: Option, -} - /// The unique id of the process (this should never be negative). pub struct Process { pub pid: pid_t @@ -55,21 +50,20 @@ impl Process { self.pid } - pub unsafe fn kill(&self, signal: int) -> IoResult<()> { + pub unsafe fn kill(&self, signal: isize) -> IoResult<()> { Process::killpid(self.pid, signal) } - pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> { + pub unsafe fn killpid(pid: pid_t, signal: isize) -> IoResult<()> { let r = libc::funcs::posix88::signal::kill(pid, signal as c_int); mkerr_libc(r) } - #[cfg(stage0)] pub fn spawn(cfg: &C, in_fd: Option

, out_fd: Option

, err_fd: Option

) -> IoResult where C: ProcessConfig, P: AsInner, - K: BytesContainer + Eq + Hash, V: BytesContainer + K: BytesContainer + Eq + Hash, V: BytesContainer { use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; @@ -79,6 +73,11 @@ impl Process { } } + unsafe fn set_cloexec(fd: c_int) { + let ret = c::ioctl(fd, c::FIOCLEX); + assert_eq!(ret, 0); + } + #[cfg(all(target_os = "android", target_arch = "aarch64"))] unsafe fn getdtablesize() -> c_int { libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int @@ -88,219 +87,6 @@ impl Process { libc::funcs::bsd44::getdtablesize() } - unsafe fn set_cloexec(fd: c_int) { - let ret = c::ioctl(fd, c::FIOCLEX); - assert_eq!(ret, 0); - } - - let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null()); - - // temporary until unboxed closures land - let cfg = unsafe { - mem::transmute::<&ProcessConfig,&'static ProcessConfig>(cfg) - }; - - with_envp(cfg.env(), move|envp: *const c_void| { - with_argv(cfg.program(), cfg.args(), move|argv: *const *const libc::c_char| unsafe { - let (input, mut output) = try!(sys::os::pipe()); - - // We may use this in the child, so perform allocations before the - // fork - let devnull = b"/dev/null\0"; - - set_cloexec(output.fd()); - - let pid = fork(); - if pid < 0 { - return Err(super::last_error()) - } else if pid > 0 { - #[inline] - fn combine(arr: &[u8]) -> i32 { - let a = arr[0] as u32; - let b = arr[1] as u32; - let c = arr[2] as u32; - let d = arr[3] as u32; - - ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32 - } - - let p = Process{ pid: pid }; - drop(output); - let mut bytes = [0; 8]; - return match input.read(&mut bytes) { - Ok(8) => { - assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]), - "Validation on the CLOEXEC pipe failed: {:?}", bytes); - let errno = combine(&bytes[0.. 4]); - assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); - Err(super::decode_error(errno)) - } - Err(ref e) if e.kind == EndOfFile => Ok(p), - Err(e) => { - assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); - panic!("the CLOEXEC pipe failed: {:?}", e) - }, - Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic - assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic"); - panic!("short read on the CLOEXEC pipe") - } - }; - } - - // And at this point we've reached a special time in the life of the - // child. The child must now be considered hamstrung and unable to - // do anything other than syscalls really. Consider the following - // scenario: - // - // 1. Thread A of process 1 grabs the malloc() mutex - // 2. Thread B of process 1 forks(), creating thread C - // 3. Thread C of process 2 then attempts to malloc() - // 4. The memory of process 2 is the same as the memory of - // process 1, so the mutex is locked. - // - // This situation looks a lot like deadlock, right? It turns out - // that this is what pthread_atfork() takes care of, which is - // presumably implemented across platforms. The first thing that - // threads to *before* forking is to do things like grab the malloc - // mutex, and then after the fork they unlock it. - // - // Despite this information, libnative's spawn has been witnessed to - // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but - // all collected backtraces point at malloc/free traffic in the - // child spawned process. - // - // For this reason, the block of code below should contain 0 - // invocations of either malloc of free (or their related friends). - // - // As an example of not having malloc/free traffic, we don't close - // this file descriptor by dropping the FileDesc (which contains an - // allocation). Instead we just close it manually. This will never - // have the drop glue anyway because this code never returns (the - // child will either exec() or invoke libc::exit) - let _ = libc::close(input.fd()); - - fn fail(output: &mut FileDesc) -> ! { - let errno = sys::os::errno() as u32; - let bytes = [ - (errno >> 24) as u8, - (errno >> 16) as u8, - (errno >> 8) as u8, - (errno >> 0) as u8, - CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1], - CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3] - ]; - // pipe I/O up to PIPE_BUF bytes should be atomic - assert!(output.write(&bytes).is_ok()); - unsafe { libc::_exit(1) } - } - - rustrt::rust_unset_sigprocmask(); - - // If a stdio file descriptor is set to be ignored (via a -1 file - // descriptor), then we don't actually close it, but rather open - // up /dev/null into that file descriptor. Otherwise, the first file - // descriptor opened up in the child would be numbered as one of the - // stdio file descriptors, which is likely to wreak havoc. - let setup = |src: Option

, dst: c_int| { - let src = match src { - None => { - let flags = if dst == libc::STDIN_FILENO { - libc::O_RDONLY - } else { - libc::O_RDWR - }; - libc::open(devnull.as_ptr() as *const _, flags, 0) - } - Some(obj) => { - let fd = obj.as_inner().fd(); - // Leak the memory and the file descriptor. We're in the - // child now an all our resources are going to be - // cleaned up very soon - mem::forget(obj); - fd - } - }; - src != -1 && retry(|| dup2(src, dst)) != -1 - }; - - if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) } - if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) } - if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) } - - // close all other fds - for fd in (3..getdtablesize()).rev() { - if fd != output.fd() { - let _ = close(fd as c_int); - } - } - - match cfg.gid() { - Some(u) => { - if libc::setgid(u as libc::gid_t) != 0 { - fail(&mut output); - } - } - None => {} - } - match cfg.uid() { - Some(u) => { - // When dropping privileges from root, the `setgroups` call - // will remove any extraneous groups. If we don't call this, - // then even though our uid has dropped, we may still have - // groups that enable us to do super-user things. This will - // fail if we aren't root, so don't bother checking the - // return value, this is just done as an optimistic - // privilege dropping function. - extern { - fn setgroups(ngroups: libc::c_int, - ptr: *const libc::c_void) -> libc::c_int; - } - let _ = setgroups(0, ptr::null()); - - if libc::setuid(u as libc::uid_t) != 0 { - fail(&mut output); - } - } - None => {} - } - if cfg.detach() { - // Don't check the error of setsid because it fails if we're the - // process leader already. We just forked so it shouldn't return - // error, but ignore it anyway. - let _ = libc::setsid(); - } - if !dirp.is_null() && chdir(dirp) == -1 { - fail(&mut output); - } - if !envp.is_null() { - *sys::os::environ() = envp as *const _; - } - let _ = execvp(*argv, argv as *mut _); - fail(&mut output); - }) - }) - } - #[cfg(not(stage0))] - pub fn spawn(cfg: &C, in_fd: Option

, - out_fd: Option

, err_fd: Option

) - -> IoResult - where C: ProcessConfig, P: AsInner, - K: BytesContainer + Eq + Hash, V: BytesContainer - { - use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; - use libc::funcs::bsd44::getdtablesize; - - mod rustrt { - extern { - pub fn rust_unset_sigprocmask(); - } - } - - unsafe fn set_cloexec(fd: c_int) { - let ret = c::ioctl(fd, c::FIOCLEX); - assert_eq!(ret, 0); - } - let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null()); // temporary until unboxed closures land @@ -541,7 +327,7 @@ impl Process { // The actual communication between the helper thread and this thread is // quite simple, just a channel moving data around. - unsafe { HELPER.boot(register_sigchld, waitpid_helper) } + HELPER.boot(register_sigchld, waitpid_helper); match self.try_wait() { Some(ret) => return Ok(ret), @@ -549,7 +335,7 @@ impl Process { } let (tx, rx) = channel(); - unsafe { HELPER.send(NewChild(self.pid, tx, deadline)); } + HELPER.send(NewChild(self.pid, tx, deadline)); return match rx.recv() { Ok(e) => Ok(e), Err(..) => Err(timeout("wait timed out")), @@ -564,8 +350,8 @@ impl Process { unsafe { let mut pipes = [0; 2]; assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0); - set_nonblocking(pipes[0], true).ok().unwrap(); - set_nonblocking(pipes[1], true).ok().unwrap(); + set_nonblocking(pipes[0], true); + set_nonblocking(pipes[1], true); WRITE_FD = pipes[1]; let mut old: c::sigaction = mem::zeroed(); @@ -581,7 +367,7 @@ impl Process { fn waitpid_helper(input: libc::c_int, messages: Receiver, (read_fd, old): (libc::c_int, c::sigaction)) { - set_nonblocking(input, true).ok().unwrap(); + set_nonblocking(input, true); let mut set: c::fd_set = unsafe { mem::zeroed() }; let mut tv: libc::timeval; let mut active = Vec::<(libc::pid_t, Sender, u64)>::new(); @@ -633,8 +419,15 @@ impl Process { Ok(NewChild(pid, tx, deadline)) => { active.push((pid, tx, deadline)); } + // Once we've been disconnected it means the main + // thread is exiting (at_exit has run). We could + // still have active waiter for other threads, so + // we're just going to drop them all on the floor. + // This means that they won't receive a "you're + // done" message in which case they'll be considered + // as timed out, but more generally errors will + // start propagating. Err(TryRecvError::Disconnected) => { - assert!(active.len() == 0); break 'outer; } Err(TryRecvError::Empty) => break, @@ -662,7 +455,7 @@ impl Process { // with process timeouts, but libgreen should get there first // (currently libuv doesn't handle old signal handlers). if drain(read_fd) { - let i: uint = unsafe { mem::transmute(old.sa_handler) }; + let i: usize = unsafe { mem::transmute(old.sa_handler) }; if i != 0 { assert!(old.sa_flags & c::SA_SIGINFO == 0); (old.sa_handler)(c::SIGCHLD); @@ -704,7 +497,8 @@ impl Process { n if n > 0 => { ret = true; } 0 => return true, -1 if wouldblock() => return ret, - n => panic!("bad read {:?} ({:?})", os::last_os_error(), n), + n => panic!("bad read {} ({})", + io::Error::last_os_error(), n), } } } @@ -766,45 +560,6 @@ fn with_argv(prog: &CString, args: &[CString], cb(ptrs.as_ptr()) } -#[cfg(stage0)] -fn with_envp(env: Option<&HashMap>, - cb: F) - -> T - where F : FnOnce(*const c_void) -> T, - K : BytesContainer + Eq + Hash, - V : BytesContainer -{ - // On posixy systems we can pass a char** for envp, which is a - // null-terminated array of "k=v\0" strings. Since we must create - // these strings locally, yet expose a raw pointer to them, we - // create a temporary vector to own the CStrings that outlives the - // call to cb. - match env { - Some(env) => { - let mut tmps = Vec::with_capacity(env.len()); - - for pair in env { - let mut kv = Vec::new(); - kv.push_all(pair.0.container_as_bytes()); - kv.push('=' as u8); - kv.push_all(pair.1.container_as_bytes()); - kv.push(0); // terminating null - tmps.push(kv); - } - - // As with `with_argv`, this is unsafe, since cb could leak the pointers. - let mut ptrs: Vec<*const libc::c_char> = - tmps.iter() - .map(|tmp| tmp.as_ptr() as *const libc::c_char) - .collect(); - ptrs.push(ptr::null()); - - cb(ptrs.as_ptr() as *const c_void) - } - _ => cb(ptr::null()) - } -} -#[cfg(not(stage0))] fn with_envp(env: Option<&HashMap>, cb: F) -> T @@ -856,6 +611,7 @@ fn translate_status(status: c_int) -> ProcessExit { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] mod imp { pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } @@ -864,8 +620,8 @@ fn translate_status(status: c_int) -> ProcessExit { } if imp::WIFEXITED(status) { - ExitStatus(imp::WEXITSTATUS(status) as int) + ExitStatus(imp::WEXITSTATUS(status) as isize) } else { - ExitSignal(imp::WTERMSIG(status) as int) + ExitSignal(imp::WTERMSIG(status) as isize) } } diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 06fa5c4bba..c2a8b26aef 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -9,23 +9,18 @@ // except according to those terms. use prelude::v1::*; +use os::unix::prelude::*; use collections::HashMap; use env; use ffi::{OsString, OsStr, CString}; use fmt; -use hash::Hash; use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_void, c_int, gid_t, uid_t}; use mem; -use old_io; -use os; -use os::unix::OsStrExt; use ptr; -use sync::mpsc::{channel, Sender, Receiver}; use sys::pipe2::AnonPipe; -use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, cvt}; -use sys_common::AsInner; +use sys::{self, retry, c, cvt}; //////////////////////////////////////////////////////////////////////////////// // Command @@ -59,7 +54,7 @@ impl Command { self.args.push(arg.to_cstring().unwrap()) } pub fn args<'a, I: Iterator>(&mut self, args: I) { - self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap())) + self.args.extend(args.map(|s| s.to_cstring().unwrap())) } fn init_env_map(&mut self) { if self.env.is_none() { @@ -127,10 +122,6 @@ pub struct Process { const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; impl Process { - pub fn id(&self) -> pid_t { - self.pid - } - pub unsafe fn kill(&self) -> io::Result<()> { try!(cvt(libc::funcs::posix88::signal::kill(self.pid, libc::SIGKILL))); Ok(()) @@ -141,7 +132,6 @@ impl Process { -> io::Result { use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; - use libc::funcs::bsd44::getdtablesize; mod rustrt { extern { @@ -154,6 +144,16 @@ impl Process { assert_eq!(ret, 0); } + #[cfg(all(target_os = "android", target_arch = "aarch64"))] + unsafe fn getdtablesize() -> c_int { + libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int + } + + #[cfg(not(all(target_os = "android", target_arch = "aarch64")))] + unsafe fn getdtablesize() -> c_int { + libc::funcs::bsd44::getdtablesize() + } + let dirp = cfg.cwd.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null()); with_envp(cfg.env.as_ref(), |envp: *const c_void| { @@ -265,7 +265,7 @@ impl Process { // file descriptor. Otherwise, the first file descriptor opened // up in the child would be numbered as one of the stdio file // descriptors, which is likely to wreak havoc. - let setup = |&: src: Option, dst: c_int| { + let setup = |src: Option, dst: c_int| { let src = match src { None => { let flags = if dst == libc::STDIN_FILENO { @@ -430,6 +430,7 @@ fn translate_status(status: c_int) -> ExitStatus { target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] mod imp { pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs index 54523e0076..adf9da2d06 100644 --- a/src/libstd/sys/unix/rwlock.rs +++ b/src/libstd/sys/unix/rwlock.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use sys::sync as ffi; @@ -17,13 +19,10 @@ pub const RWLOCK_INIT: RWLock = RWLock { inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER }, }; +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + impl RWLock { - #[inline] - pub unsafe fn new() -> RWLock { - // Might be moved and address is changing it is better to avoid - // initialization of potentially opaque OS data before it landed - RWLOCK_INIT - } #[inline] pub unsafe fn read(&self) { let r = ffi::pthread_rwlock_rdlock(self.inner.get()); diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 3512fa36eb..6887095c53 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -34,9 +34,9 @@ impl Drop for Handler { #[cfg(any(target_os = "linux", target_os = "macos", + target_os = "bitrig", target_os = "openbsd"))] mod imp { - use core::prelude::*; use sys_common::stack; use super::Handler; @@ -60,7 +60,7 @@ mod imp { // This is initialized in init() and only read from after - static mut PAGE_SIZE: uint = 0; + static mut PAGE_SIZE: usize = 0; #[no_stack_check] unsafe extern fn signal_handler(signum: libc::c_int, @@ -82,7 +82,7 @@ mod imp { stack::record_sp_limit(0); let guard = thread_info::stack_guard(); - let addr = (*info).si_addr as uint; + let addr = (*info).si_addr as usize; if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard { term(signum); @@ -101,7 +101,7 @@ mod imp { panic!("failed to get page size"); } - PAGE_SIZE = psize as uint; + PAGE_SIZE = psize as usize; let mut action: sigaction = mem::zeroed(); action.sa_flags = SA_SIGINFO | SA_ONSTACK; @@ -144,7 +144,7 @@ mod imp { munmap(handler._data, SIGSTKSZ); } - type sighandler_t = *mut libc::c_void; + pub type sighandler_t = *mut libc::c_void; #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match all(target_os = "linux", target_arch = "x86_64"), @@ -156,7 +156,7 @@ mod imp { target_os = "android"))] // may not match mod signal { use libc; - use super::sighandler_t; + pub use super::sighandler_t; pub static SA_ONSTACK: libc::c_int = 0x08000000; pub static SA_SIGINFO: libc::c_int = 0x00000004; @@ -205,10 +205,12 @@ mod imp { } - #[cfg(any(target_os = "macos", target_os = "openbsd"))] + #[cfg(any(target_os = "macos", + target_os = "bitrig", + target_os = "openbsd"))] mod signal { use libc; - use super::sighandler_t; + pub use super::sighandler_t; pub const SA_ONSTACK: libc::c_int = 0x0001; pub const SA_SIGINFO: libc::c_int = 0x0040; @@ -216,7 +218,7 @@ mod imp { #[cfg(target_os = "macos")] pub const SIGSTKSZ: libc::size_t = 131072; - #[cfg(target_os = "openbsd")] + #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] pub const SIGSTKSZ: libc::size_t = 40960; pub const SIG_DFL: sighandler_t = 0 as sighandler_t; @@ -237,14 +239,14 @@ mod imp { pub si_addr: *mut libc::c_void } - #[cfg(target_os = "openbsd")] + #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] #[repr(C)] pub struct siginfo { pub si_signo: libc::c_int, pub si_code: libc::c_int, pub si_errno: libc::c_int, - // union - pub si_addr: *mut libc::c_void, + //union + pub si_addr: *mut libc::c_void } #[repr(C)] @@ -277,6 +279,7 @@ mod imp { #[cfg(not(any(target_os = "linux", target_os = "macos", + target_os = "bitrig", target_os = "openbsd")))] mod imp { use libc; diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs new file mode 100644 index 0000000000..5f5101e96d --- /dev/null +++ b/src/libstd/sys/unix/stdio.rs @@ -0,0 +1,62 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use io; +use libc; +use sys::fd::FileDesc; + +pub struct Stdin(()); +pub struct Stdout(()); +pub struct Stderr(()); + +impl Stdin { + pub fn new() -> Stdin { Stdin(()) } + + pub fn read(&self, data: &mut [u8]) -> io::Result { + let fd = FileDesc::new(libc::STDIN_FILENO); + let ret = fd.read(data); + fd.into_raw(); + return ret; + } +} + +impl Stdout { + pub fn new() -> Stdout { Stdout(()) } + + pub fn write(&self, data: &[u8]) -> io::Result { + let fd = FileDesc::new(libc::STDOUT_FILENO); + let ret = fd.write(data); + fd.into_raw(); + return ret; + } +} + +impl Stderr { + pub fn new() -> Stderr { Stderr(()) } + + pub fn write(&self, data: &[u8]) -> io::Result { + let fd = FileDesc::new(libc::STDERR_FILENO); + let ret = fd.write(data); + fd.into_raw(); + return ret; + } +} + +// FIXME: right now this raw stderr handle is used in a few places because +// std::io::stderr_raw isn't exposed, but once that's exposed this impl +// should go away +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result { + Stderr::write(self, data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs index bc93513af6..3c05fd602b 100644 --- a/src/libstd/sys/unix/sync.rs +++ b/src/libstd/sys/unix/sync.rs @@ -46,6 +46,7 @@ extern { #[cfg(any(target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] mod os { use libc; @@ -65,24 +66,24 @@ mod os { #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] - const __PTHREAD_MUTEX_SIZE__: uint = 56; + const __PTHREAD_MUTEX_SIZE__: usize = 56; #[cfg(any(target_arch = "x86", target_arch = "arm"))] - const __PTHREAD_MUTEX_SIZE__: uint = 40; + const __PTHREAD_MUTEX_SIZE__: usize = 40; #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] - const __PTHREAD_COND_SIZE__: uint = 40; + const __PTHREAD_COND_SIZE__: usize = 40; #[cfg(any(target_arch = "x86", target_arch = "arm"))] - const __PTHREAD_COND_SIZE__: uint = 24; + const __PTHREAD_COND_SIZE__: usize = 24; #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] - const __PTHREAD_RWLOCK_SIZE__: uint = 192; + const __PTHREAD_RWLOCK_SIZE__: usize = 192; #[cfg(any(target_arch = "x86", target_arch = "arm"))] - const __PTHREAD_RWLOCK_SIZE__: uint = 124; + const __PTHREAD_RWLOCK_SIZE__: usize = 124; const _PTHREAD_MUTEX_SIG_INIT: libc::c_long = 0x32AAABA7; const _PTHREAD_COND_SIG_INIT: libc::c_long = 0x3CB0B1BB; @@ -124,15 +125,15 @@ mod os { // minus 8 because we have an 'align' field #[cfg(target_arch = "x86_64")] - const __SIZEOF_PTHREAD_MUTEX_T: uint = 40 - 8; + const __SIZEOF_PTHREAD_MUTEX_T: usize = 40 - 8; #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "mips", target_arch = "mipsel", target_arch = "powerpc"))] - const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8; + const __SIZEOF_PTHREAD_MUTEX_T: usize = 24 - 8; #[cfg(target_arch = "aarch64")] - const __SIZEOF_PTHREAD_MUTEX_T: uint = 48 - 8; + const __SIZEOF_PTHREAD_MUTEX_T: usize = 48 - 8; #[cfg(any(target_arch = "x86_64", target_arch = "x86", @@ -141,18 +142,18 @@ mod os { target_arch = "mips", target_arch = "mipsel", target_arch = "powerpc"))] - const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8; + const __SIZEOF_PTHREAD_COND_T: usize = 48 - 8; #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] - const __SIZEOF_PTHREAD_RWLOCK_T: uint = 56 - 8; + const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56 - 8; #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "mips", target_arch = "mipsel", target_arch = "powerpc"))] - const __SIZEOF_PTHREAD_RWLOCK_T: uint = 32 - 8; + const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32 - 8; #[repr(C)] pub struct pthread_mutex_t { diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs index c8f9d31848..a9f2198208 100644 --- a/src/libstd/sys/unix/tcp.rs +++ b/src/libstd/sys/unix/tcp.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use old_io::net::ip; @@ -62,14 +64,14 @@ impl TcpListener { pub fn fd(&self) -> sock_t { self.inner.fd() } - pub fn listen(self, backlog: int) -> IoResult { + pub fn listen(self, backlog: isize) -> IoResult { match unsafe { libc::listen(self.fd(), backlog as libc::c_int) } { -1 => Err(last_net_error()), _ => { let (reader, writer) = try!(unsafe { sys::os::pipe() }); - try!(set_nonblocking(reader.fd(), true)); - try!(set_nonblocking(writer.fd(), true)); - try!(set_nonblocking(self.fd(), true)); + set_nonblocking(reader.fd(), true); + set_nonblocking(writer.fd(), true); + set_nonblocking(self.fd(), true); Ok(TcpAcceptor { inner: Arc::new(AcceptorInner { listener: self, @@ -137,10 +139,6 @@ impl TcpAcceptor { Err(sys_common::eof()) } - pub fn socket_name(&mut self) -> IoResult { - net::sockname(self.fd(), libc::getsockname) - } - pub fn set_timeout(&mut self, timeout: Option) { self.deadline = timeout.map(|a| sys::timer::now() + a).unwrap_or(0); } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index c90ba7645f..eb61f21aac 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -8,71 +8,61 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(dead_code)] + use core::prelude::*; -use io; -use boxed::Box; use cmp; +use ffi::CString; +use io; +use libc::consts::os::posix01::PTHREAD_STACK_MIN; +use libc; use mem; use ptr; -use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN}; -use libc; +use sys::os; use thunk::Thunk; -use ffi::CString; +use time::Duration; use sys_common::stack::RED_ZONE; use sys_common::thread::*; pub type rust_thread = libc::pthread_t; -pub type rust_thread_return = *mut u8; -pub type StartFn = extern "C" fn(*mut libc::c_void) -> rust_thread_return; - -#[no_stack_check] -pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return { - return start_thread(main); -} #[cfg(all(not(target_os = "linux"), not(target_os = "macos"), + not(target_os = "bitrig"), not(target_os = "openbsd")))] pub mod guard { - pub unsafe fn current() -> uint { - 0 - } - - pub unsafe fn main() -> uint { - 0 - } - - pub unsafe fn init() { - } + pub unsafe fn current() -> usize { 0 } + pub unsafe fn main() -> usize { 0 } + pub unsafe fn init() {} } #[cfg(any(target_os = "linux", target_os = "macos", + target_os = "bitrig", target_os = "openbsd"))] +#[allow(unused_imports)] pub mod guard { - use super::*; - #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "openbsd"))] - use mem; - #[cfg(any(target_os = "linux", target_os = "android"))] - use ptr; - use libc; - use libc::funcs::posix88::mman::{mmap}; + use libc::{self, pthread_t}; + use libc::funcs::posix88::mman::mmap; use libc::consts::os::posix88::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED}; + use mem; + use ptr; + use super::{pthread_self, pthread_attr_destroy}; + use sys::os; // These are initialized in init() and only read from after - static mut PAGE_SIZE: uint = 0; - static mut GUARD_PAGE: uint = 0; + static mut GUARD_PAGE: usize = 0; - #[cfg(any(target_os = "macos", target_os = "openbsd"))] + #[cfg(any(target_os = "macos", + target_os = "bitrig", + target_os = "openbsd"))] unsafe fn get_stack_start() -> *mut libc::c_void { current() as *mut libc::c_void } @@ -80,28 +70,16 @@ pub mod guard { #[cfg(any(target_os = "linux", target_os = "android"))] unsafe fn get_stack_start() -> *mut libc::c_void { let mut attr: libc::pthread_attr_t = mem::zeroed(); - if pthread_getattr_np(pthread_self(), &mut attr) != 0 { - panic!("failed to get thread attributes"); - } + assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0); let mut stackaddr = ptr::null_mut(); let mut stacksize = 0; - if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 { - panic!("failed to get stack information"); - } - if pthread_attr_destroy(&mut attr) != 0 { - panic!("failed to destroy thread attributes"); - } + assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0); + assert_eq!(pthread_attr_destroy(&mut attr), 0); stackaddr } pub unsafe fn init() { - let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE); - if psize == -1 { - panic!("failed to get page size"); - } - - PAGE_SIZE = psize as uint; - + let psize = os::page_size(); let mut stackaddr = get_stack_start(); // Ensure stackaddr is page aligned! A parent process might @@ -110,9 +88,9 @@ pub mod guard { // stackaddr < stackaddr + stacksize, so if stackaddr is not // page-aligned, calculate the fix such that stackaddr < // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = (stackaddr as usize) % (PAGE_SIZE as usize); + let remainder = (stackaddr as usize) % psize; if remainder != 0 { - stackaddr = ((stackaddr as usize) + (PAGE_SIZE as usize) - remainder) + stackaddr = ((stackaddr as usize) + psize - remainder) as *mut libc::c_void; } @@ -120,7 +98,7 @@ pub mod guard { // This ensures SIGBUS will be raised on // stack overflow. let result = mmap(stackaddr, - PAGE_SIZE as libc::size_t, + psize as libc::size_t, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, @@ -130,138 +108,154 @@ pub mod guard { panic!("failed to allocate a guard page"); } - let offset = if cfg!(target_os = "linux") { - 2 - } else { - 1 - }; + let offset = if cfg!(target_os = "linux") {2} else {1}; - GUARD_PAGE = stackaddr as uint + offset * PAGE_SIZE; + GUARD_PAGE = stackaddr as usize + offset * psize; } - pub unsafe fn main() -> uint { + pub unsafe fn main() -> usize { GUARD_PAGE } #[cfg(target_os = "macos")] - pub unsafe fn current() -> uint { + pub unsafe fn current() -> usize { + extern { + fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void; + fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t; + } (pthread_get_stackaddr_np(pthread_self()) as libc::size_t - - pthread_get_stacksize_np(pthread_self())) as uint + pthread_get_stacksize_np(pthread_self())) as usize } - #[cfg(target_os = "openbsd")] - pub unsafe fn current() -> uint { - let mut current_stack: stack_t = mem::zeroed(); - if pthread_stackseg_np(pthread_self(), &mut current_stack) != 0 { - panic!("failed to get current stack: pthread_stackseg_np") + #[cfg(any(target_os = "openbsd", target_os = "bitrig"))] + pub unsafe fn current() -> usize { + #[repr(C)] + struct stack_t { + ss_sp: *mut libc::c_void, + ss_size: libc::size_t, + ss_flags: libc::c_int, + } + extern { + fn pthread_main_np() -> libc::c_uint; + fn pthread_stackseg_np(thread: pthread_t, + sinfo: *mut stack_t) -> libc::c_uint; } + let mut current_stack: stack_t = mem::zeroed(); + assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0); + + let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size(); if pthread_main_np() == 1 { // main thread - current_stack.ss_sp as uint - current_stack.ss_size as uint + 3 * PAGE_SIZE as uint - + current_stack.ss_sp as usize - current_stack.ss_size as usize + extra } else { // new thread - current_stack.ss_sp as uint - current_stack.ss_size as uint + current_stack.ss_sp as usize - current_stack.ss_size as usize } } #[cfg(any(target_os = "linux", target_os = "android"))] - pub unsafe fn current() -> uint { + pub unsafe fn current() -> usize { let mut attr: libc::pthread_attr_t = mem::zeroed(); - if pthread_getattr_np(pthread_self(), &mut attr) != 0 { - panic!("failed to get thread attributes"); - } + assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0); let mut guardsize = 0; - if pthread_attr_getguardsize(&attr, &mut guardsize) != 0 { - panic!("failed to get stack guard page"); - } + assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0); if guardsize == 0 { panic!("there is no guard page"); } let mut stackaddr = ptr::null_mut(); - let mut stacksize = 0; - if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 { - panic!("failed to get stack information"); - } - if pthread_attr_destroy(&mut attr) != 0 { - panic!("failed to destroy thread attributes"); - } + let mut size = 0; + assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0); + assert_eq!(pthread_attr_destroy(&mut attr), 0); - stackaddr as uint + guardsize as uint + stackaddr as usize + guardsize as usize + } + + #[cfg(any(target_os = "linux", target_os = "android"))] + extern { + fn pthread_getattr_np(native: libc::pthread_t, + attr: *mut libc::pthread_attr_t) -> libc::c_int; + fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t, + guardsize: *mut libc::size_t) -> libc::c_int; + fn pthread_attr_getstack(attr: *const libc::pthread_attr_t, + stackaddr: *mut *mut libc::c_void, + stacksize: *mut libc::size_t) -> libc::c_int; } } -pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { +pub unsafe fn create(stack: usize, p: Thunk) -> io::Result { + let p = box p; let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(pthread_attr_init(&mut attr), 0); - assert_eq!(pthread_attr_setdetachstate(&mut attr, - PTHREAD_CREATE_JOINABLE), 0); // Reserve room for the red zone, the runtime's stack of last resort. - let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint); + let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as usize); match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) { - 0 => { - }, - libc::EINVAL => { + 0 => {} + n => { + assert_eq!(n, libc::EINVAL); // EINVAL means |stack_size| is either too small or not a // multiple of the system page size. Because it's definitely // >= PTHREAD_STACK_MIN, it must be an alignment issue. // Round up to the nearest page and try again. - let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint; + let page_size = os::page_size(); let stack_size = (stack_size + page_size - 1) & - (-(page_size as int - 1) as uint - 1); - assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0); - }, - errno => { - // This cannot really happen. - panic!("pthread_attr_setstacksize() error: {}", errno); - }, + (-(page_size as isize - 1) as usize - 1); + assert_eq!(pthread_attr_setstacksize(&mut attr, + stack_size as libc::size_t), 0); + } }; - let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint - let ret = pthread_create(&mut native, &attr, thread_start, arg); + let ret = pthread_create(&mut native, &attr, thread_start, + &*p as *const _ as *mut _); assert_eq!(pthread_attr_destroy(&mut attr), 0); - if ret != 0 { - // be sure to not leak the closure - let _p: Box> = mem::transmute(arg); + return if ret != 0 { Err(io::Error::from_os_error(ret)) } else { + mem::forget(p); // ownership passed to pthread_create Ok(native) + }; + + #[no_stack_check] + extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { + start_thread(main); + 0 as *mut _ } } #[cfg(any(target_os = "linux", target_os = "android"))] pub unsafe fn set_name(name: &str) { - // pthread_setname_np() since glibc 2.12 - // availability autodetected via weak linkage - let cname = CString::new(name).unwrap(); - type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int; + // pthread wrapper only appeared in glibc 2.12, so we use syscall directly. extern { - #[linkage = "extern_weak"] - static pthread_setname_np: *const (); - } - if !pthread_setname_np.is_null() { - unsafe { - mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(), cname.as_ptr()); - } + fn prctl(option: libc::c_int, arg2: libc::c_ulong, arg3: libc::c_ulong, + arg4: libc::c_ulong, arg5: libc::c_ulong) -> libc::c_int; } + const PR_SET_NAME: libc::c_int = 15; + let cname = CString::new(name).unwrap_or_else(|_| { + panic!("thread name may not contain interior null bytes") + }); + prctl(PR_SET_NAME, cname.as_ptr() as libc::c_ulong, 0, 0, 0); } #[cfg(any(target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] pub unsafe fn set_name(name: &str) { - // pthread_set_name_np() since almost forever on all BSDs + extern { + fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char); + } let cname = CString::new(name).unwrap(); pthread_set_name_np(pthread_self(), cname.as_ptr()); } #[cfg(any(target_os = "macos", target_os = "ios"))] pub unsafe fn set_name(name: &str) { - // pthread_setname_np() since OS X 10.6 and iOS 3.2 + extern { + fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int; + } let cname = CString::new(name).unwrap(); pthread_setname_np(cname.as_ptr()); } @@ -274,90 +268,97 @@ pub unsafe fn detach(native: rust_thread) { assert_eq!(pthread_detach(native), 0); } -pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); } +pub unsafe fn yield_now() { + assert_eq!(sched_yield(), 0); +} + +pub fn sleep(dur: Duration) { + unsafe { + if dur < Duration::zero() { + return yield_now() + } + let seconds = dur.num_seconds(); + let ns = dur - Duration::seconds(seconds); + let mut ts = libc::timespec { + tv_sec: seconds as libc::time_t, + tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long, + }; + // If we're awoken with a signal then the return value will be -1 and + // nanosleep will fill in `ts` with the remaining time. + while dosleep(&mut ts) == -1 { + assert_eq!(os::errno(), libc::EINTR); + } + } + + #[cfg(target_os = "linux")] + unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int { + extern { + fn clock_nanosleep(clock_id: libc::c_int, flags: libc::c_int, + request: *const libc::timespec, + remain: *mut libc::timespec) -> libc::c_int; + } + clock_nanosleep(libc::CLOCK_MONOTONIC, 0, ts, ts) + } + #[cfg(not(target_os = "linux"))] + unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int { + libc::nanosleep(ts, ts) + } +} + // glibc >= 2.15 has a __pthread_get_minstack() function that returns // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local // storage. We need that information to avoid blowing up when a small stack // is created in an application with big thread-local storage requirements. // See #6233 for rationale and details. // -// Link weakly to the symbol for compatibility with older versions of glibc. -// Assumes that we've been dynamically linked to libpthread but that is -// currently always the case. Note that you need to check that the symbol -// is non-null before calling it! +// Use dlsym to get the symbol value at runtime, both for +// compatibility with older versions of glibc, and to avoid creating +// dependencies on GLIBC_PRIVATE symbols. Assumes that we've been +// dynamically linked to libpthread but that is currently always the +// case. We previously used weak linkage (under the same assumption), +// but that caused Debian to detect an unnecessarily strict versioned +// dependency on libc6 (#23628). #[cfg(target_os = "linux")] fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t { + use dynamic_lib::DynamicLibrary; + use sync::{Once, ONCE_INIT}; + type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t; - extern { - #[linkage = "extern_weak"] - static __pthread_get_minstack: *const (); - } - if __pthread_get_minstack.is_null() { - PTHREAD_STACK_MIN - } else { - unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) } + static INIT: Once = ONCE_INIT; + static mut __pthread_get_minstack: Option = None; + + INIT.call_once(|| { + let lib = DynamicLibrary::open(None).unwrap(); + unsafe { + if let Ok(f) = lib.symbol("__pthread_get_minstack") { + __pthread_get_minstack = Some(mem::transmute::<*const (), F>(f)); + } + } + }); + + match unsafe { __pthread_get_minstack } { + None => PTHREAD_STACK_MIN, + Some(f) => unsafe { f(attr) }, } } -// __pthread_get_minstack() is marked as weak but extern_weak linkage is -// not supported on OS X, hence this kludge... +// No point in looking up __pthread_get_minstack() on non-glibc +// platforms. #[cfg(not(target_os = "linux"))] fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t { PTHREAD_STACK_MIN } -#[cfg(any(target_os = "linux", target_os = "android"))] -extern { - pub fn pthread_self() -> libc::pthread_t; - pub fn pthread_getattr_np(native: libc::pthread_t, - attr: *mut libc::pthread_attr_t) -> libc::c_int; - pub fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t, - guardsize: *mut libc::size_t) -> libc::c_int; - pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t, - stackaddr: *mut *mut libc::c_void, - stacksize: *mut libc::size_t) -> libc::c_int; -} - -#[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd"))] -extern { - pub fn pthread_self() -> libc::pthread_t; - fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char); -} - -#[cfg(any(target_os = "macos", target_os = "ios"))] -extern { - pub fn pthread_self() -> libc::pthread_t; - pub fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *mut libc::c_void; - pub fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t; - fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int; -} - -#[cfg(target_os = "openbsd")] -extern { - pub fn pthread_stackseg_np(thread: libc::pthread_t, - sinfo: *mut stack_t) -> libc::c_uint; - pub fn pthread_main_np() -> libc::c_uint; -} - -#[cfg(target_os = "openbsd")] -#[repr(C)] -pub struct stack_t { - pub ss_sp: *mut libc::c_void, - pub ss_size: libc::size_t, - pub ss_flags: libc::c_int, -} - extern { + fn pthread_self() -> libc::pthread_t; fn pthread_create(native: *mut libc::pthread_t, attr: *const libc::pthread_attr_t, - f: StartFn, + f: extern fn(*mut libc::c_void) -> *mut libc::c_void, value: *mut libc::c_void) -> libc::c_int; fn pthread_join(native: libc::pthread_t, value: *mut *mut libc::c_void) -> libc::c_int; fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int; - pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int; + fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int; fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t, stack_size: libc::size_t) -> libc::c_int; fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t, diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs index 62d9a33c83..9b7079ee10 100644 --- a/src/libstd/sys/unix/thread_local.rs +++ b/src/libstd/sys/unix/thread_local.rs @@ -43,6 +43,7 @@ type pthread_key_t = ::libc::c_ulong; #[cfg(any(target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd"))] type pthread_key_t = ::libc::c_int; @@ -50,6 +51,7 @@ type pthread_key_t = ::libc::c_int; target_os = "ios", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd")))] type pthread_key_t = ::libc::c_uint; diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index bddf7b075d..d2f51678d4 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -58,11 +58,9 @@ mod inner { type Output = Duration; fn sub(self, other: &SteadyTime) -> Duration { - unsafe { - let info = info(); - let diff = self.t as i64 - other.t as i64; - Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64) - } + let info = info(); + let diff = self.t as i64 - other.t as i64; + Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64) } } } @@ -80,8 +78,11 @@ mod inner { } // Apparently android provides this in some other library? + // Bitrig's RT extensions are in the C library, not a separate librt // OpenBSD provide it via libc - #[cfg(not(any(target_os = "android", target_os = "openbsd")))] + #[cfg(not(any(target_os = "android", + target_os = "bitrig", + target_os = "openbsd")))] #[link(name = "rt")] extern {} diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index 4cd98f4442..9309147b15 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -46,13 +46,16 @@ //! //! Note that all time units in this file are in *milliseconds*. +#![allow(deprecated)] + use prelude::v1::*; use self::Req::*; use old_io::IoResult; use libc; use mem; -use os; +use sys::os; +use io; use ptr; use sync::atomic::{self, Ordering}; use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; @@ -67,7 +70,7 @@ pub trait Callback { } pub struct Timer { - id: uint, + id: usize, inner: Option>, } @@ -76,7 +79,7 @@ pub struct Inner { interval: u64, repeat: bool, target: u64, - id: uint, + id: usize, } pub enum Req { @@ -85,7 +88,7 @@ pub enum Req { // Remove a timer based on its id and then send it back on the channel // provided - RemoveTimer(uint, Sender>), + RemoveTimer(usize, Sender>), } // returns the current time (in milliseconds) @@ -100,7 +103,7 @@ pub fn now() -> u64 { fn helper(input: libc::c_int, messages: Receiver, _: ()) { let mut set: c::fd_set = unsafe { mem::zeroed() }; - let mut fd = FileDesc::new(input, true); + let fd = FileDesc::new(input, true); let mut timeout: libc::timeval = unsafe { mem::zeroed() }; // active timers are those which are able to be selected upon (and it's a @@ -119,7 +122,7 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { // signals the first requests in the queue, possible re-enqueueing it. fn signal(active: &mut Vec>, - dead: &mut Vec<(uint, Box)>) { + dead: &mut Vec<(usize, Box)>) { if active.is_empty() { return } let mut timer = active.remove(0); @@ -168,8 +171,15 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { 1 => { loop { match messages.try_recv() { + // Once we've been disconnected it means the main thread + // is exiting (at_exit has run). We could still have + // active timers for other threads, so we're just going + // to drop them all on the floor. This is all we can + // really do, however, to prevent resource leakage. The + // remaining timers will likely start panicking quickly + // as they attempt to re-use this thread but are + // disallowed to do so. Err(TryRecvError::Disconnected) => { - assert!(active.len() == 0); break 'outer; } @@ -195,19 +205,19 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { // drain the file descriptor let mut buf = [0]; - assert_eq!(fd.read(&mut buf).ok().unwrap(), 1); + assert_eq!(fd.read(&mut buf).unwrap(), 1); } -1 if os::errno() == libc::EINTR as i32 => {} n => panic!("helper thread failed in select() with error: {} ({})", - n, os::last_os_error()) + n, io::Error::last_os_error()) } } } impl Timer { pub fn new() -> IoResult { - // See notes above regarding using int return value + // See notes above regarding using isize return value // instead of () HELPER.boot(|| {}, helper); @@ -235,7 +245,7 @@ impl Timer { tv_nsec: ((ms % 1000) * 1000000) as libc::c_long, }; while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 { - if os::errno() as int != libc::EINTR as int { + if os::errno() as isize != libc::EINTR as isize { panic!("failed to sleep, but not because of EINTR?"); } } diff --git a/src/libstd/sys/unix/tty.rs b/src/libstd/sys/unix/tty.rs index 3a79047445..2f6fd713bf 100644 --- a/src/libstd/sys/unix/tty.rs +++ b/src/libstd/sys/unix/tty.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + use prelude::v1::*; use sys::fs::FileDesc; -use libc::{self, c_int, c_ulong, funcs}; +use libc::{self, c_int, c_ulong}; use old_io::{self, IoResult, IoError}; use sys::c; use sys_common; @@ -21,7 +23,10 @@ pub struct TTY { } #[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "dragonfly", target_os = "freebsd", + target_os = "bitrig", target_os = "openbsd"))] const TIOCGWINSZ: c_ulong = 0x40087468; @@ -41,7 +46,7 @@ impl TTY { } } - pub fn read(&mut self, buf: &mut [u8]) -> IoResult { + pub fn read(&mut self, buf: &mut [u8]) -> IoResult { self.fd.read(buf) } pub fn write(&mut self, buf: &[u8]) -> IoResult<()> { @@ -51,12 +56,7 @@ impl TTY { Err(sys_common::unimpl()) } - #[cfg(any(target_os = "linux", - target_os = "android", - target_os = "macos", - target_os = "freebsd", - target_os = "openbsd"))] - pub fn get_winsize(&mut self) -> IoResult<(int, int)> { + pub fn get_winsize(&mut self) -> IoResult<(isize, isize)> { unsafe { #[repr(C)] struct winsize { @@ -74,16 +74,8 @@ impl TTY { detail: None, }) } else { - Ok((size.ws_col as int, size.ws_row as int)) + Ok((size.ws_col as isize, size.ws_row as isize)) } } } - - #[cfg(any(target_os = "ios", - target_os = "dragonfly"))] - pub fn get_winsize(&mut self) -> IoResult<(int, int)> { - Err(sys_common::unimpl()) - } - - pub fn isatty(&self) -> bool { false } } diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 51cf303242..385834a622 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -24,19 +24,18 @@ #![allow(dead_code)] +use prelude::v1::*; +use io::prelude::*; + use dynamic_lib::DynamicLibrary; use ffi::CStr; use intrinsics; -use old_io::{IoResult, Writer}; +use io; use libc; use mem; -use ops::Drop; -use option::Option::{Some}; -use old_path::Path; +use path::Path; use ptr; -use result::Result::{Ok, Err}; -use slice::SliceExt; -use str::{self, StrExt}; +use str; use sync::{StaticMutex, MUTEX_INIT}; use sys_common::backtrace::*; @@ -63,7 +62,7 @@ type StackWalk64Fn = *mut libc::c_void, *mut libc::c_void, *mut libc::c_void, *mut libc::c_void) -> libc::BOOL; -const MAX_SYM_NAME: uint = 2000; +const MAX_SYM_NAME: usize = 2000; const IMAGE_FILE_MACHINE_I386: libc::DWORD = 0x014c; const IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200; const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664; @@ -105,7 +104,7 @@ struct ADDRESS64 { Mode: ADDRESS_MODE, } -struct STACKFRAME64 { +pub struct STACKFRAME64 { AddrPC: ADDRESS64, AddrReturn: ADDRESS64, AddrFrame: ADDRESS64, @@ -138,7 +137,7 @@ struct KDHELP64 { mod arch { use libc; - const MAXIMUM_SUPPORTED_EXTENSION: uint = 512; + const MAXIMUM_SUPPORTED_EXTENSION: usize = 512; #[repr(C)] pub struct CONTEXT { @@ -294,7 +293,7 @@ impl Drop for Cleanup { fn drop(&mut self) { (self.SymCleanup)(self.handle); } } -pub fn write(w: &mut Writer) -> IoResult<()> { +pub fn write(w: &mut Write) -> io::Result<()> { // According to windows documentation, all dbghelp functions are // single-threaded. static LOCK: StaticMutex = MUTEX_INIT; diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 2d1a5e10bd..4804f65044 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -48,6 +48,11 @@ pub const WSAESHUTDOWN: libc::c_int = 10058; pub const ERROR_NO_MORE_FILES: libc::DWORD = 18; pub const TOKEN_READ: libc::DWORD = 0x20008; +// Note that these are not actually HANDLEs, just values to pass to GetStdHandle +pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD; +pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; +pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD; + #[repr(C)] #[cfg(target_arch = "x86")] pub struct WSADATA { @@ -84,7 +89,6 @@ pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS; pub type WSAEVENT = libc::HANDLE; #[repr(C)] -#[derive(Copy)] pub struct WSAPROTOCOL_INFO { pub dwServiceFlags1: libc::DWORD, pub dwServiceFlags2: libc::DWORD, @@ -295,7 +299,7 @@ pub mod compat { /// Macro for creating a compatibility fallback for a Windows function /// - /// # Example + /// # Examples /// ``` /// compat_fn!(adll32::SomeFunctionW(_arg: LPCWSTR) { /// // Fallback implementation @@ -427,6 +431,8 @@ extern "system" { DesiredAccess: libc::DWORD, TokenHandle: *mut libc::HANDLE) -> libc::BOOL; pub fn GetCurrentProcess() -> libc::HANDLE; + pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + pub fn ExitProcess(uExitCode: libc::c_uint) -> !; } #[link(name = "userenv")] diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs index db8038006f..67552255fd 100644 --- a/src/libstd/sys/windows/condvar.rs +++ b/src/libstd/sys/windows/condvar.rs @@ -8,15 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use libc::{self, DWORD}; -use os; +use sys::os; use sys::mutex::{self, Mutex}; use sys::sync as ffi; use time::Duration; pub struct Condvar { inner: UnsafeCell } +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + pub const CONDVAR_INIT: Condvar = Condvar { inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT } }; @@ -41,7 +46,7 @@ impl Condvar { 0); if r == 0 { const ERROR_TIMEOUT: DWORD = 0x5B4; - debug_assert_eq!(os::errno() as uint, ERROR_TIMEOUT as uint); + debug_assert_eq!(os::errno() as usize, ERROR_TIMEOUT as usize); false } else { true diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs index ac1006e653..2dd61861bd 100644 --- a/src/libstd/sys/windows/ext.rs +++ b/src/libstd/sys/windows/ext.rs @@ -14,183 +14,301 @@ //! descriptors, and sockets, but its functionality will grow over //! time. -#![unstable(feature = "std_misc")] +#![stable(feature = "rust1", since = "1.0.0")] -pub use sys_common::wtf8::{Wtf8Buf, EncodeWide}; +#[stable(feature = "rust1", since = "1.0.0")] +pub mod io { + use fs; + use libc; + use net; + use sys_common::{net2, AsInner, FromInner}; + use sys; -use ffi::{OsStr, OsString}; -use fs::{self, OpenOptions}; -use libc; -use net; -use sys::os_str::Buf; -use sys_common::{AsInner, FromInner, AsInnerMut}; + #[allow(deprecated)] + use old_io; -use old_io; + /// Raw HANDLEs. + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawHandle = libc::HANDLE; -/// Raw HANDLEs. -pub type Handle = libc::HANDLE; + /// Raw SOCKETs. + #[stable(feature = "rust1", since = "1.0.0")] + pub type RawSocket = libc::SOCKET; -/// Raw SOCKETs. -pub type Socket = libc::SOCKET; + /// Extract raw handles. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait AsRawHandle { + /// Extract the raw handle, without taking any ownership. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_handle(&self) -> RawHandle; + } -/// Extract raw handles. -pub trait AsRawHandle { - /// Extract the raw handle, without taking any ownership. - fn as_raw_handle(&self) -> Handle; -} + /// Construct I/O objects from raw handles. + #[unstable(feature = "from_raw_os", + reason = "recent addition to the std::os::windows::io module")] + pub trait FromRawHandle { + /// Construct a new I/O object from the specified raw handle. + /// + /// This function will **consume ownership** of the handle given, + /// passing responsibility for closing the handle to the returned + /// object. + fn from_raw_handle(handle: RawHandle) -> Self; + } -impl AsRawHandle for old_io::fs::File { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawHandle for old_io::fs::File { + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle() + } } -} -impl AsRawHandle for fs::File { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle().raw() + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawHandle for fs::File { + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle().raw() + } } -} -impl AsRawHandle for old_io::pipe::PipeStream { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawHandle for fs::File { + fn from_raw_handle(handle: RawHandle) -> fs::File { + fs::File::from_inner(sys::fs2::File::from_inner(handle)) + } } -} -impl AsRawHandle for old_io::net::pipe::UnixStream { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawHandle for old_io::pipe::PipeStream { + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle() + } } -} -impl AsRawHandle for old_io::net::pipe::UnixListener { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawHandle for old_io::net::pipe::UnixStream { + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle() + } } -} -impl AsRawHandle for old_io::net::pipe::UnixAcceptor { - fn as_raw_handle(&self) -> Handle { - self.as_inner().handle() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawHandle for old_io::net::pipe::UnixListener { + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle() + } } -} -/// Extract raw sockets. -pub trait AsRawSocket { - fn as_raw_socket(&self) -> Socket; -} + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawHandle for old_io::net::pipe::UnixAcceptor { + fn as_raw_handle(&self) -> RawHandle { + self.as_inner().handle() + } + } -impl AsRawSocket for old_io::net::tcp::TcpStream { - fn as_raw_socket(&self) -> Socket { - self.as_inner().fd() + /// Extract raw sockets. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait AsRawSocket { + /// Extract the underlying raw socket from this object. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_socket(&self) -> RawSocket; } -} -impl AsRawSocket for old_io::net::tcp::TcpListener { - fn as_raw_socket(&self) -> Socket { - self.as_inner().socket() + /// Create I/O objects from raw sockets. + #[unstable(feature = "from_raw_os", reason = "recent addition to module")] + pub trait FromRawSocket { + /// Creates a new I/O object from the given raw socket. + /// + /// This function will **consume ownership** of the socket provided and + /// it will be closed when the returned object goes out of scope. + fn from_raw_socket(sock: RawSocket) -> Self; } -} -impl AsRawSocket for old_io::net::tcp::TcpAcceptor { - fn as_raw_socket(&self) -> Socket { - self.as_inner().socket() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for old_io::net::tcp::TcpStream { + fn as_raw_socket(&self) -> RawSocket { + self.as_inner().fd() + } } -} -impl AsRawSocket for old_io::net::udp::UdpSocket { - fn as_raw_socket(&self) -> Socket { - self.as_inner().fd() + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for old_io::net::tcp::TcpListener { + fn as_raw_socket(&self) -> RawSocket { + self.as_inner().socket() + } } -} -impl AsRawSocket for net::TcpStream { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } -} -impl AsRawSocket for net::TcpListener { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } -} -impl AsRawSocket for net::UdpSocket { - fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() } -} + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for old_io::net::tcp::TcpAcceptor { + fn as_raw_socket(&self) -> RawSocket { + self.as_inner().socket() + } + } -// Windows-specific extensions to `OsString`. -pub trait OsStringExt { - /// Create an `OsString` from a potentially ill-formed UTF-16 slice of 16-bit code units. - /// - /// This is lossless: calling `.encode_wide()` on the resulting string - /// will always return the original code units. - fn from_wide(wide: &[u16]) -> Self; -} + #[allow(deprecated)] + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for old_io::net::udp::UdpSocket { + fn as_raw_socket(&self) -> RawSocket { + self.as_inner().fd() + } + } -impl OsStringExt for OsString { - fn from_wide(wide: &[u16]) -> OsString { - FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for net::TcpStream { + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for net::TcpListener { + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } + } + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawSocket for net::UdpSocket { + fn as_raw_socket(&self) -> RawSocket { + *self.as_inner().socket().as_inner() + } } -} -// Windows-specific extensions to `OsStr`. -pub trait OsStrExt { - fn encode_wide(&self) -> EncodeWide; + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpStream { + fn from_raw_socket(sock: RawSocket) -> net::TcpStream { + let sock = sys::net::Socket::from_inner(sock); + net::TcpStream::from_inner(net2::TcpStream::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::TcpListener { + fn from_raw_socket(sock: RawSocket) -> net::TcpListener { + let sock = sys::net::Socket::from_inner(sock); + net::TcpListener::from_inner(net2::TcpListener::from_inner(sock)) + } + } + #[unstable(feature = "from_raw_os", reason = "trait is unstable")] + impl FromRawSocket for net::UdpSocket { + fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { + let sock = sys::net::Socket::from_inner(sock); + net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock)) + } + } } -impl OsStrExt for OsStr { - fn encode_wide(&self) -> EncodeWide { - self.as_inner().inner.encode_wide() +/// Windows-specific extensions to the primitives in the `std::ffi` module. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod ffi { + use ffi::{OsString, OsStr}; + use sys::os_str::Buf; + use sys_common::wtf8::Wtf8Buf; + use sys_common::{FromInner, AsInner}; + + pub use sys_common::wtf8::EncodeWide; + + /// Windows-specific extensions to `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStringExt { + /// Create an `OsString` from a potentially ill-formed UTF-16 slice of + /// 16-bit code units. + /// + /// This is lossless: calling `.encode_wide()` on the resulting string + /// will always return the original code units. + #[stable(feature = "rust1", since = "1.0.0")] + fn from_wide(wide: &[u16]) -> Self; } -} -// Windows-specific extensions to `OpenOptions` -pub trait OpenOptionsExt { - /// Override the `dwDesiredAccess` argument to the call to `CreateFile` with - /// the specified value. - fn desired_access(&mut self, access: i32) -> &mut Self; - - /// Override the `dwCreationDisposition` argument to the call to - /// `CreateFile` with the specified value. - /// - /// This will override any values of the standard `create` flags, for - /// example. - fn creation_disposition(&mut self, val: i32) -> &mut Self; - - /// Override the `dwFlagsAndAttributes` argument to the call to - /// `CreateFile` with the specified value. - /// - /// This will override any values of the standard flags on the `OpenOptions` - /// structure. - fn flags_and_attributes(&mut self, val: i32) -> &mut Self; - - /// Override the `dwShareMode` argument to the call to `CreateFile` with the - /// specified value. - /// - /// This will override any values of the standard flags on the `OpenOptions` - /// structure. - fn share_mode(&mut self, val: i32) -> &mut Self; -} + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStringExt for OsString { + fn from_wide(wide: &[u16]) -> OsString { + FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) }) + } + } -impl OpenOptionsExt for OpenOptions { - fn desired_access(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().desired_access(access); self + /// Windows-specific extensions to `OsStr`. + #[stable(feature = "rust1", since = "1.0.0")] + pub trait OsStrExt { + /// Re-encode an `OsStr` as a wide character sequence, + /// i.e. potentially ill-formed UTF-16. + /// + /// This is lossless. Note that the encoding does not include a final + /// null. + #[stable(feature = "rust1", since = "1.0.0")] + fn encode_wide(&self) -> EncodeWide; } - fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().creation_disposition(access); self + + #[stable(feature = "rust1", since = "1.0.0")] + impl OsStrExt for OsStr { + fn encode_wide(&self) -> EncodeWide { + self.as_inner().inner.encode_wide() + } } - fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().flags_and_attributes(access); self +} + +/// Windows-specific extensions for the primitives in `std::fs` +#[unstable(feature = "fs_ext", reason = "may require more thought/methods")] +pub mod fs { + use fs::OpenOptions; + use sys_common::AsInnerMut; + + /// Windows-specific extensions to `OpenOptions` + pub trait OpenOptionsExt { + /// Override the `dwDesiredAccess` argument to the call to `CreateFile` + /// with the specified value. + fn desired_access(&mut self, access: i32) -> &mut Self; + + /// Override the `dwCreationDisposition` argument to the call to + /// `CreateFile` with the specified value. + /// + /// This will override any values of the standard `create` flags, for + /// example. + fn creation_disposition(&mut self, val: i32) -> &mut Self; + + /// Override the `dwFlagsAndAttributes` argument to the call to + /// `CreateFile` with the specified value. + /// + /// This will override any values of the standard flags on the + /// `OpenOptions` structure. + fn flags_and_attributes(&mut self, val: i32) -> &mut Self; + + /// Override the `dwShareMode` argument to the call to `CreateFile` with + /// the specified value. + /// + /// This will override any values of the standard flags on the + /// `OpenOptions` structure. + fn share_mode(&mut self, val: i32) -> &mut Self; } - fn share_mode(&mut self, access: i32) -> &mut OpenOptions { - self.as_inner_mut().share_mode(access); self + + impl OpenOptionsExt for OpenOptions { + fn desired_access(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().desired_access(access); self + } + fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().creation_disposition(access); self + } + fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().flags_and_attributes(access); self + } + fn share_mode(&mut self, access: i32) -> &mut OpenOptions { + self.as_inner_mut().share_mode(access); self + } } } /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] pub mod prelude { #[doc(no_inline)] - pub use super::{Socket, Handle, AsRawSocket, AsRawHandle}; - #[doc(no_inline)] - pub use super::{OsStrExt, OsStringExt}; + pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] - pub use super::OpenOptionsExt; + pub use super::fs::OpenOptionsExt; } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 304d7e0153..0bbb1a9e92 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -10,6 +10,8 @@ //! Blocking Windows-based file I/O +#![allow(deprecated)] // this module itself is essentially deprecated + use libc::{self, c_int}; use mem; @@ -18,8 +20,9 @@ use old_io; use prelude::v1::*; use sys; -use sys_common::{mkerr_libc}; +use sys_common::{self, mkerr_libc}; +use old_path::{Path, GenericPath}; use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; use old_io::{IoResult, IoError, FileStat, SeekStyle}; use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append}; @@ -39,7 +42,7 @@ impl FileDesc { FileDesc { fd: fd, close_on_drop: close_on_drop } } - pub fn read(&self, buf: &mut [u8]) -> IoResult { + pub fn read(&self, buf: &mut [u8]) -> IoResult { let mut read = 0; let ret = unsafe { libc::ReadFile(self.handle(), buf.as_ptr() as libc::LPVOID, @@ -47,7 +50,7 @@ impl FileDesc { ptr::null_mut()) }; if ret != 0 { - Ok(read as uint) + Ok(read as usize) } else { Err(super::last_error()) } @@ -64,8 +67,8 @@ impl FileDesc { ptr::null_mut()) }; if ret != 0 { - remaining -= amt as uint; - cur = unsafe { cur.offset(amt as int) }; + remaining -= amt as usize; + cur = unsafe { cur.offset(amt as isize) }; } else { return Err(super::last_error()) } @@ -133,7 +136,7 @@ impl FileDesc { } } - /// Extract the actual filedescriptor without closing it. + #[allow(dead_code)] pub fn unwrap(self) -> fd_t { let fd = self.fd; unsafe { mem::forget(self) }; @@ -231,7 +234,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { } } -pub fn mkdir(p: &Path, _mode: uint) -> IoResult<()> { +pub fn mkdir(p: &Path, _mode: usize) -> IoResult<()> { let p = try!(to_utf16(p)); super::mkerr_winbool(unsafe { // FIXME: turn mode into something useful? #2623 @@ -305,11 +308,11 @@ pub fn unlink(p: &Path) -> IoResult<()> { }; if stat.perm.intersects(old_io::USER_WRITE) { return Err(e) } - match chmod(p, (stat.perm | old_io::USER_WRITE).bits() as uint) { + match chmod(p, (stat.perm | old_io::USER_WRITE).bits() as usize) { Ok(()) => do_unlink(&p_utf16), Err(..) => { // Try to put it back as we found it - let _ = chmod(p, stat.perm.bits() as uint); + let _ = chmod(p, stat.perm.bits() as usize); Err(e) } } @@ -328,7 +331,7 @@ pub fn rename(old: &Path, new: &Path) -> IoResult<()> { }) } -pub fn chmod(p: &Path, mode: uint) -> IoResult<()> { +pub fn chmod(p: &Path, mode: usize) -> IoResult<()> { let p = try!(to_utf16(p)); mkerr_libc(unsafe { libc::wchmod(p.as_ptr(), mode as libc::c_int) @@ -340,7 +343,7 @@ pub fn rmdir(p: &Path) -> IoResult<()> { super::mkerr_winbool(unsafe { libc::RemoveDirectoryW(p.as_ptr()) }) } -pub fn chown(_p: &Path, _uid: int, _gid: int) -> IoResult<()> { +pub fn chown(_p: &Path, _uid: isize, _gid: isize) -> IoResult<()> { // libuv has this as a no-op, so seems like this should as well? Ok(()) } @@ -368,7 +371,9 @@ pub fn readlink(p: &Path) -> IoResult { buf as *const u16, sz - 1, libc::VOLUME_NAME_DOS) - }, super::os2path); + }, |data| { + Path::new(String::from_utf16(data).unwrap()) + }); assert!(unsafe { libc::CloseHandle(handle) } != 0); return ret; } @@ -432,7 +437,7 @@ pub fn stat(p: &Path) -> IoResult { // FIXME: move this to platform-specific modules (for now)? pub fn lstat(_p: &Path) -> IoResult { // FIXME: implementation is missing - Err(super::unimpl()) + Err(sys_common::unimpl()) } pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> { diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 8abcd90efe..d03e45649e 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -19,20 +19,30 @@ use libc::{self, HANDLE}; use mem; use path::{Path, PathBuf}; use ptr; -use sys::handle::Handle as RawHandle; +use sync::Arc; +use sys::handle::Handle; use sys::{c, cvt}; +use sys_common::FromInner; use vec::Vec; -pub struct File { handle: RawHandle } +pub struct File { handle: Handle } pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA } pub struct ReadDir { - handle: libc::HANDLE, - root: PathBuf, + handle: FindNextFileHandle, + root: Arc, first: Option, } -pub struct DirEntry { path: PathBuf } +struct FindNextFileHandle(libc::HANDLE); + +unsafe impl Send for FindNextFileHandle {} +unsafe impl Sync for FindNextFileHandle {} + +pub struct DirEntry { + root: Arc, + data: libc::WIN32_FIND_DATAW, +} #[derive(Clone, Default)] pub struct OpenOptions { @@ -61,7 +71,7 @@ impl Iterator for ReadDir { unsafe { let mut wfd = mem::zeroed(); loop { - if libc::FindNextFileW(self.handle, &mut wfd) == 0 { + if libc::FindNextFileW(self.handle.0, &mut wfd) == 0 { if libc::GetLastError() == c::ERROR_NO_MORE_FILES as libc::DWORD { return None @@ -77,15 +87,15 @@ impl Iterator for ReadDir { } } -impl Drop for ReadDir { +impl Drop for FindNextFileHandle { fn drop(&mut self) { - let r = unsafe { libc::FindClose(self.handle) }; + let r = unsafe { libc::FindClose(self.0) }; debug_assert!(r != 0); } } impl DirEntry { - fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option { + fn new(root: &Arc, wfd: &libc::WIN32_FIND_DATAW) -> Option { match &wfd.cFileName[0..3] { // check for '.' and '..' [46, 0, ..] | @@ -93,13 +103,15 @@ impl DirEntry { _ => {} } - let filename = super::truncate_utf16_at_nul(&wfd.cFileName); - let filename: OsString = OsStringExt::from_wide(filename); - Some(DirEntry { path: root.join(&filename) }) + Some(DirEntry { + root: root.clone(), + data: *wfd, + }) } pub fn path(&self) -> PathBuf { - self.path.clone() + let filename = super::truncate_utf16_at_nul(&self.data.cFileName); + self.root.join(&::from_wide(filename)) } } @@ -181,7 +193,7 @@ impl File { if handle == libc::INVALID_HANDLE_VALUE { Err(Error::last_os_error()) } else { - Ok(File { handle: RawHandle::new(handle) }) + Ok(File { handle: Handle::new(handle) }) } } @@ -249,7 +261,13 @@ impl File { Ok(newpos as u64) } - pub fn handle(&self) -> &RawHandle { &self.handle } + pub fn handle(&self) -> &Handle { &self.handle } +} + +impl FromInner for File { + fn from_inner(handle: libc::HANDLE) -> File { + File { handle: Handle::new(handle) } + } } pub fn to_utf16(s: &Path) -> Vec { @@ -312,7 +330,11 @@ pub fn readdir(p: &Path) -> io::Result { let mut wfd = mem::zeroed(); let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd); if find_handle != libc::INVALID_HANDLE_VALUE { - Ok(ReadDir { handle: find_handle, root: root, first: Some(wfd) }) + Ok(ReadDir { + handle: FindNextFileHandle(find_handle), + root: Arc::new(root), + first: Some(wfd), + }) } else { Err(Error::last_os_error()) } @@ -357,7 +379,7 @@ pub fn readlink(p: &Path) -> io::Result { sz - 1, libc::VOLUME_NAME_DOS) }, |s| OsStringExt::from_wide(s))); - Ok(PathBuf::new(&ret)) + Ok(PathBuf::from(&ret)) } pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 99de659be4..0089dcad45 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -10,9 +10,10 @@ use prelude::v1::*; -use libc::{self, HANDLE}; -use io; use io::ErrorKind; +use io; +use libc::{self, HANDLE}; +use mem; use ptr; use sys::cvt; @@ -28,6 +29,12 @@ impl Handle { pub fn raw(&self) -> HANDLE { self.0 } + pub fn into_raw(self) -> HANDLE { + let ret = self.0; + unsafe { mem::forget(self) } + return ret; + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { read(self.0, buf) } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index a756fb29f8..e9d5fca531 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -14,26 +14,17 @@ use prelude::v1::*; -use ffi::OsStr; +use ffi::{OsStr, OsString}; use io::{self, ErrorKind}; use libc; use mem; -use old_io::{self, IoResult, IoError}; +#[allow(deprecated)] use num::Int; -use os::windows::OsStrExt; +use old_io::{self, IoResult, IoError}; +use os::windows::ffi::{OsStrExt, OsStringExt}; +use path::PathBuf; use sync::{Once, ONCE_INIT}; -macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( - static $name: Helper<$m> = Helper { - lock: ::sync::MUTEX_INIT, - cond: ::sync::CONDVAR_INIT, - chan: ::cell::UnsafeCell { value: 0 as *mut ::sync::mpsc::Sender<$m> }, - signal: ::cell::UnsafeCell { value: 0 }, - initialized: ::cell::UnsafeCell { value: false }, - shutdown: ::cell::UnsafeCell { value: false }, - }; -) } - pub mod backtrace; pub mod c; pub mod condvar; @@ -60,6 +51,7 @@ pub mod time; pub mod timer; pub mod tty; pub mod udp; +pub mod stdio; pub mod addrinfo { pub use sys_common::net::get_host_addresses; @@ -73,6 +65,7 @@ pub type msglen_t = libc::c_int; pub unsafe fn close_sock(sock: sock_t) { let _ = libc::closesocket(sock); } // windows has zero values as errors +#[allow(deprecated)] fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> { if ret == 0 { Err(last_error()) @@ -81,6 +74,7 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> { } } +#[allow(deprecated)] pub fn last_error() -> IoError { let errno = os::errno() as i32; let mut err = decode_error(errno); @@ -88,6 +82,7 @@ pub fn last_error() -> IoError { err } +#[allow(deprecated)] pub fn last_net_error() -> IoError { let errno = unsafe { c::WSAGetLastError() as i32 }; let mut err = decode_error(errno); @@ -95,11 +90,13 @@ pub fn last_net_error() -> IoError { err } +#[allow(deprecated)] pub fn last_gai_error(_errno: i32) -> IoError { last_net_error() } /// Convert an `errno` value into a high-level error variant and description. +#[allow(deprecated)] pub fn decode_error(errno: i32) -> IoError { let (kind, desc) = match errno { libc::EOF => (old_io::EndOfFile, "end of file"), @@ -143,6 +140,7 @@ pub fn decode_error(errno: i32) -> IoError { IoError { kind: kind, desc: desc, detail: None } } +#[allow(deprecated)] pub fn decode_error_detailed(errno: i32) -> IoError { let mut err = decode_error(errno); err.detail = Some(os::error_string(errno)); @@ -152,25 +150,21 @@ pub fn decode_error_detailed(errno: i32) -> IoError { pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno as libc::c_int { libc::ERROR_ACCESS_DENIED => ErrorKind::PermissionDenied, - libc::ERROR_ALREADY_EXISTS => ErrorKind::PathAlreadyExists, + libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists, libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe, - libc::ERROR_FILE_NOT_FOUND => ErrorKind::FileNotFound, - libc::ERROR_INVALID_FUNCTION => ErrorKind::InvalidInput, - libc::ERROR_INVALID_HANDLE => ErrorKind::MismatchedFileTypeForOperation, - libc::ERROR_INVALID_NAME => ErrorKind::InvalidInput, - libc::ERROR_NOTHING_TO_TERMINATE => ErrorKind::InvalidInput, + libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound, libc::ERROR_NO_DATA => ErrorKind::BrokenPipe, libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut, libc::WSAEACCES => ErrorKind::PermissionDenied, - libc::WSAEADDRINUSE => ErrorKind::ConnectionRefused, - libc::WSAEADDRNOTAVAIL => ErrorKind::ConnectionRefused, + libc::WSAEADDRINUSE => ErrorKind::AddrInUse, + libc::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable, libc::WSAECONNABORTED => ErrorKind::ConnectionAborted, libc::WSAECONNREFUSED => ErrorKind::ConnectionRefused, libc::WSAECONNRESET => ErrorKind::ConnectionReset, libc::WSAEINVAL => ErrorKind::InvalidInput, libc::WSAENOTCONN => ErrorKind::NotConnected, - libc::WSAEWOULDBLOCK => ErrorKind::ResourceUnavailable, + libc::WSAEWOULDBLOCK => ErrorKind::WouldBlock, _ => ErrorKind::Other, } @@ -187,17 +181,19 @@ pub fn ms_to_timeval(ms: u64) -> libc::timeval { } } +#[allow(deprecated)] pub fn wouldblock() -> bool { let err = os::errno(); err == libc::WSAEWOULDBLOCK as i32 } -pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> { +#[allow(deprecated)] +pub fn set_nonblocking(fd: sock_t, nb: bool) { let mut set = nb as libc::c_ulong; - if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } { - Err(last_error()) - } else { - Ok(()) + if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 { + // The above function should not return an error unless we passed it + // invalid parameters. Panic on errors. + panic!("set_nonblocking called with invalid parameters: {}", last_error()); } } @@ -214,15 +210,8 @@ pub fn init_net() { } } -pub fn unimpl() -> IoError { - IoError { - kind: old_io::IoUnavailable, - desc: "operation is not implemented", - detail: None, - } -} - -fn to_utf16(s: Option<&str>) -> IoResult> { +#[allow(deprecated)] +pub fn to_utf16(s: Option<&str>) -> IoResult> { match s { Some(s) => Ok(to_utf16_os(OsStr::from_str(s))), None => Err(IoError { @@ -300,6 +289,7 @@ fn fill_utf16_buf_base(mut f1: F1, f2: F2) -> Result } } +#[allow(deprecated)] fn fill_utf16_buf(f1: F1, f2: F2) -> IoResult where F1: FnMut(*mut u16, libc::DWORD) -> libc::DWORD, F2: FnOnce(&[u16]) -> T @@ -314,9 +304,8 @@ fn fill_utf16_buf_new(f1: F1, f2: F2) -> io::Result fill_utf16_buf_base(f1, f2).map_err(|()| io::Error::last_os_error()) } -fn os2path(s: &[u16]) -> Path { - // FIXME: this should not be a panicking conversion (aka path reform) - Path::new(String::from_utf16(s).unwrap()) +fn os2path(s: &[u16]) -> PathBuf { + PathBuf::from(OsString::from_wide(s)) } pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { @@ -327,6 +316,7 @@ pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] { } } +#[allow(deprecated)] fn cvt(i: I) -> io::Result { if i == Int::zero() { Err(io::Error::last_os_error()) diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 75495efc7c..0847f3b52b 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use marker::Sync; +use prelude::v1::*; + use cell::UnsafeCell; use sys::sync as ffi; @@ -18,6 +19,7 @@ pub const MUTEX_INIT: Mutex = Mutex { inner: UnsafeCell { value: ffi::SRWLOCK_INIT } }; +unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} #[inline] @@ -27,14 +29,15 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK { // So you might be asking why we're using SRWLock instead of CriticalSection? // -// 1. SRWLock is several times faster than CriticalSection according to benchmarks performed on both -// Windows 8 and Windows 7. +// 1. SRWLock is several times faster than CriticalSection according to +// benchmarks performed on both Windows 8 and Windows 7. // -// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix implementation -// deadlocks so consistency is preferred. See #19962 for more details. +// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix +// implementation deadlocks so consistency is preferred. See #19962 for more +// details. // -// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy is there there are -// no guarantees of fairness. +// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy +// is there there are no guarantees of fairness. impl Mutex { #[inline] diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 3451232f40..12a8ef99d7 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -14,17 +14,20 @@ use io; use libc::consts::os::extra::INVALID_SOCKET; use libc::{self, c_int, c_void}; use mem; -use net::{SocketAddr, IpAddr}; +use net::SocketAddr; +#[allow(deprecated)] use num::{SignedInt, Int}; use rt; use sync::{Once, ONCE_INIT}; use sys::c; -use sys_common::AsInner; +use sys_common::{AsInner, FromInner}; pub type wrlen_t = i32; pub struct Socket(libc::SOCKET); +/// Checks whether the Windows socket interface has been started already, and +/// if not, starts it. pub fn init() { static START: Once = ONCE_INIT; @@ -34,14 +37,21 @@ pub fn init() { &mut data); assert_eq!(ret, 0); - rt::at_exit(|| { c::WSACleanup(); }) + let _ = rt::at_exit(|| { c::WSACleanup(); }); }); } +/// Returns the last error from the Windows socket interface. fn last_error() -> io::Error { io::Error::from_os_error(unsafe { c::WSAGetLastError() }) } +/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1) +/// and if so, returns the last error from the Windows socket interface. . This +/// function must be called before another call to the socket API is made. +/// +/// FIXME: generics needed? +#[allow(deprecated)] pub fn cvt(t: T) -> io::Result { let one: T = Int::one(); if t == -one { @@ -51,20 +61,24 @@ pub fn cvt(t: T) -> io::Result { } } +/// Provides the functionality of `cvt` for the return values of `getaddrinfo` +/// and similar, meaning that they return an error if the return value is 0. pub fn cvt_gai(err: c_int) -> io::Result<()> { if err == 0 { return Ok(()) } cvt(err).map(|_| ()) } +/// Provides the functionality of `cvt` for a closure. +#[allow(deprecated)] pub fn cvt_r(mut f: F) -> io::Result where F: FnMut() -> T { cvt(f()) } impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { - let fam = match addr.ip() { - IpAddr::V4(..) => libc::AF_INET, - IpAddr::V6(..) => libc::AF_INET6, + let fam = match *addr { + SocketAddr::V4(..) => libc::AF_INET, + SocketAddr::V6(..) => libc::AF_INET6, }; match unsafe { libc::socket(fam, ty, 0) } { INVALID_SOCKET => Err(last_error()), @@ -112,10 +126,14 @@ impl Socket { impl Drop for Socket { fn drop(&mut self) { - unsafe { let _ = libc::closesocket(self.0); } + let _ = unsafe { libc::closesocket(self.0) }; } } impl AsInner for Socket { fn as_inner(&self) -> &libc::SOCKET { &self.0 } } + +impl FromInner for Socket { + fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) } +} diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 6520d30487..d5843a2f99 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -13,21 +13,25 @@ #![allow(bad_style)] use prelude::v1::*; -use os::windows::*; +use os::windows::prelude::*; use error::Error as StdError; -use ffi::{OsString, OsStr, AsOsStr}; +use ffi::{OsString, OsStr}; use fmt; -use ops::Range; +use io; use libc::types::os::arch::extra::LPWCH; use libc::{self, c_int, c_void}; use mem; +#[allow(deprecated)] use old_io::{IoError, IoResult}; +use ops::Range; +use os::windows::ffi::EncodeWide; +use path::{self, PathBuf}; use ptr; use slice; use sys::c; use sys::fs::FileDesc; -use sys::handle::Handle as RawHandle; +use sys::handle::Handle; use libc::funcs::extra::kernel32::{ GetEnvironmentStringsW, @@ -57,8 +61,8 @@ pub fn error_string(errnum: i32) -> String { -> DWORD; } - static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000; - static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200; + const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000; + const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200; // This value is calculated from the macro // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) @@ -105,7 +109,7 @@ impl Iterator for Env { if *self.cur == 0 { return None } let p = &*self.cur; let mut len = 0; - while *(p as *const _).offset(len) != 0 { + while *(p as *const u16).offset(len) != 0 { len += 1; } let p = p as *const u16; @@ -132,7 +136,7 @@ pub fn env() -> Env { let ch = GetEnvironmentStringsW(); if ch as usize == 0 { panic!("failure getting env string from OS: {}", - IoError::last_error()); + io::Error::last_os_error()); } Env { base: ch, cur: ch } } @@ -151,8 +155,8 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths { } impl<'a> Iterator for SplitPaths<'a> { - type Item = Path; - fn next(&mut self) -> Option { + type Item = PathBuf; + fn next(&mut self) -> Option { // On Windows, the PATH environment variable is semicolon separated. // Double quotes are used as a way of introducing literal semicolons // (since c:\some;dir is a valid Windows path). Double quotes are not @@ -186,7 +190,7 @@ impl<'a> Iterator for SplitPaths<'a> { if !must_yield && in_progress.is_empty() { None } else { - Some(super::os2path(&in_progress[..])) + Some(super::os2path(&in_progress)) } } } @@ -195,13 +199,13 @@ impl<'a> Iterator for SplitPaths<'a> { pub struct JoinPathsError; pub fn join_paths(paths: I) -> Result - where I: Iterator, T: AsOsStr + where I: Iterator, T: AsRef { let mut joined = Vec::new(); let sep = b';' as u16; for (i, path) in paths.enumerate() { - let path = path.as_os_str(); + let path = path.as_ref(); if i > 0 { joined.push(sep) } let v = path.encode_wide().collect::>(); if v.contains(&(b'"' as u16)) { @@ -228,33 +232,34 @@ impl StdError for JoinPathsError { fn description(&self) -> &str { "failed to join paths" } } -pub fn current_exe() -> IoResult { - super::fill_utf16_buf(|buf, sz| unsafe { +pub fn current_exe() -> io::Result { + super::fill_utf16_buf_new(|buf, sz| unsafe { libc::GetModuleFileNameW(ptr::null_mut(), buf, sz) }, super::os2path) } -pub fn getcwd() -> IoResult { - super::fill_utf16_buf(|buf, sz| unsafe { +pub fn getcwd() -> io::Result { + super::fill_utf16_buf_new(|buf, sz| unsafe { libc::GetCurrentDirectoryW(sz, buf) }, super::os2path) } -pub fn chdir(p: &Path) -> IoResult<()> { - let mut p = p.as_os_str().encode_wide().collect::>(); +pub fn chdir(p: &path::Path) -> io::Result<()> { + let p: &OsStr = p.as_ref(); + let mut p = p.encode_wide().collect::>(); p.push(0); unsafe { match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) { true => Ok(()), - false => Err(IoError::last_error()), + false => Err(io::Error::last_os_error()), } } } pub fn getenv(k: &OsStr) -> Option { let k = super::to_utf16_os(k); - super::fill_utf16_buf(|buf, sz| unsafe { + super::fill_utf16_buf_new(|buf, sz| unsafe { libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, |buf| { OsStringExt::from_wide(buf) @@ -267,7 +272,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) { unsafe { if libc::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) == 0 { - panic!("failed to set env: {}", IoError::last_error()); + panic!("failed to set env: {}", io::Error::last_os_error()); } } } @@ -276,7 +281,7 @@ pub fn unsetenv(n: &OsStr) { let v = super::to_utf16_os(n); unsafe { if libc::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) == 0 { - panic!("failed to unset env: {}", IoError::last_error()); + panic!("failed to unset env: {}", io::Error::last_os_error()); } } } @@ -331,6 +336,7 @@ pub fn page_size() -> usize { } } +#[allow(deprecated)] pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { // Windows pipes work subtly differently than unix pipes, and their // inheritance has to be handled in a different way that I do not @@ -349,26 +355,23 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { } } -pub fn temp_dir() -> Path { - super::fill_utf16_buf(|buf, sz| unsafe { +pub fn temp_dir() -> PathBuf { + super::fill_utf16_buf_new(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap() } -pub fn home_dir() -> Option { - getenv("HOME".as_os_str()).or_else(|| { - getenv("USERPROFILE".as_os_str()) - }).map(|os| { - // FIXME: OsString => Path - Path::new(os.to_str().unwrap()) - }).or_else(|| unsafe { +pub fn home_dir() -> Option { + getenv("HOME".as_ref()).or_else(|| { + getenv("USERPROFILE".as_ref()) + }).map(PathBuf::from).or_else(|| unsafe { let me = c::GetCurrentProcess(); let mut token = ptr::null_mut(); if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { return None } - let _handle = RawHandle::new(token); - super::fill_utf16_buf(|buf, mut sz| { + let _handle = Handle::new(token); + super::fill_utf16_buf_new(|buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { 0 if libc::GetLastError() != 0 => 0, 0 => sz, @@ -377,3 +380,7 @@ pub fn home_dir() -> Option { }, super::os2path).ok() }) } + +pub fn exit(code: i32) -> ! { + unsafe { c::ExitProcess(code as libc::c_uint) } +} diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs index af94b56bf1..91905ae748 100644 --- a/src/libstd/sys/windows/os_str.rs +++ b/src/libstd/sys/windows/os_str.rs @@ -11,9 +11,10 @@ /// The underlying OsString/OsStr implementation on Windows is a /// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. +use borrow::Cow; use fmt::{self, Debug}; use sys_common::wtf8::{Wtf8, Wtf8Buf}; -use string::{String, CowString}; +use string::String; use result::Result; use option::Option; use mem; @@ -44,10 +45,6 @@ impl Buf { Buf { inner: Wtf8Buf::from_string(s) } } - pub fn from_str(s: &str) -> Buf { - Buf { inner: Wtf8Buf::from_str(s) } - } - pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(self.inner.as_slice()) } } @@ -70,7 +67,7 @@ impl Slice { self.inner.as_str() } - pub fn to_string_lossy(&self) -> CowString { + pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() } diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 1f228b7d32..064c003bd1 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -84,6 +84,8 @@ //! the test suite passing (the suite is in libstd), and that's good enough for //! me! +#![allow(deprecated)] + use prelude::v1::*; use libc; @@ -113,7 +115,7 @@ impl Event { initial_state as libc::BOOL, ptr::null()) }; - if event as uint == 0 { + if event as usize == 0 { Err(super::last_error()) } else { Ok(Event(event)) @@ -179,7 +181,7 @@ unsafe fn pipe(name: *const u16, init: bool) -> libc::HANDLE { } pub fn await(handle: libc::HANDLE, deadline: u64, - events: &[libc::HANDLE]) -> IoResult { + events: &[libc::HANDLE]) -> IoResult { use libc::consts::os::extra::{WAIT_FAILED, WAIT_TIMEOUT, WAIT_OBJECT_0}; // If we've got a timeout, use WaitForSingleObject in tandem with CancelIo @@ -202,7 +204,7 @@ pub fn await(handle: libc::HANDLE, deadline: u64, let _ = c::CancelIo(handle); Err(sys_common::timeout("operation timed out")) }, - n => Ok((n - WAIT_OBJECT_0) as uint) + n => Ok((n - WAIT_OBJECT_0) as usize) } } @@ -312,7 +314,7 @@ impl UnixStream { // `WaitNamedPipe` function, and this is indicated with an error // code of ERROR_PIPE_BUSY. let code = unsafe { libc::GetLastError() }; - if code as int != libc::ERROR_PIPE_BUSY as int { + if code as isize != libc::ERROR_PIPE_BUSY as isize { return Err(super::last_error()) } @@ -360,7 +362,7 @@ impl UnixStream { } } - pub fn read(&mut self, buf: &mut [u8]) -> IoResult { + pub fn read(&mut self, buf: &mut [u8]) -> IoResult { if self.read.is_none() { self.read = Some(try!(Event::new(true, false))); } @@ -388,7 +390,7 @@ impl UnixStream { &mut bytes_read, &mut overlapped) }; - if ret != 0 { return Ok(bytes_read as uint) } + if ret != 0 { return Ok(bytes_read as usize) } // If our errno doesn't say that the I/O is pending, then we hit some // legitimate error and return immediately. @@ -416,7 +418,7 @@ impl UnixStream { }; // If we succeeded, or we failed for some reason other than // CancelIoEx, return immediately - if ret != 0 { return Ok(bytes_read as uint) } + if ret != 0 { return Ok(bytes_read as usize) } if os::errno() != libc::ERROR_OPERATION_ABORTED as i32 { return Err(super::last_error()) } @@ -485,7 +487,7 @@ impl UnixStream { return Err(super::last_error()) } if !wait_succeeded.is_ok() { - let amt = offset + bytes_written as uint; + let amt = offset + bytes_written as usize; return if amt > 0 { Err(IoError { kind: old_io::ShortWrite(amt), @@ -502,7 +504,7 @@ impl UnixStream { continue // retry } } - offset += bytes_written as uint; + offset += bytes_written as usize; } Ok(()) } @@ -755,10 +757,10 @@ impl UnixAcceptor { impl Clone for UnixAcceptor { fn clone(&self) -> UnixAcceptor { - let name = to_utf16(&self.listener.name).ok().unwrap(); + let name = to_utf16(&self.listener.name).unwrap(); UnixAcceptor { inner: self.inner.clone(), - event: Event::new(true, false).ok().unwrap(), + event: Event::new(true, false).unwrap(), deadline: 0, listener: UnixListener { name: self.listener.name.clone(), diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 60d24e6174..b10042090d 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] // this module itself is essentially deprecated + use prelude::v1::*; -#[cfg(stage0)] use collections::hash_map::Hasher; use collections; use env; use ffi::CString; @@ -18,17 +19,16 @@ use hash::Hash; use libc::{pid_t, c_void}; use libc; use mem; -use old_io::fs::PathExtensions; +#[allow(deprecated)] use old_io::fs::PathExtensions; use old_io::process::{ProcessExit, ExitStatus}; use old_io::{IoResult, IoError}; use old_io; -use os; -use old_path::BytesContainer; +use fs::PathExt; +use old_path::{BytesContainer, GenericPath}; use ptr; use str; use sync::{StaticMutex, MUTEX_INIT}; use sys::fs::FileDesc; - use sys::timer; use sys_common::{AsInner, timeout}; @@ -63,11 +63,11 @@ impl Process { self.pid } - pub unsafe fn kill(&self, signal: int) -> IoResult<()> { + pub unsafe fn kill(&self, signal: isize) -> IoResult<()> { Process::killpid(self.pid, signal) } - pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> { + pub unsafe fn killpid(pid: pid_t, signal: isize) -> IoResult<()> { let handle = libc::OpenProcess(libc::PROCESS_TERMINATE | libc::PROCESS_QUERY_INFORMATION, libc::FALSE, pid as libc::DWORD); @@ -106,170 +106,6 @@ impl Process { } #[allow(deprecated)] - #[cfg(stage0)] - pub fn spawn(cfg: &C, in_fd: Option

, - out_fd: Option

, err_fd: Option

) - -> IoResult - where C: ProcessConfig, P: AsInner, - K: BytesContainer + Eq + Hash, V: BytesContainer - { - use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO}; - use libc::consts::os::extra::{ - TRUE, FALSE, - STARTF_USESTDHANDLES, - INVALID_HANDLE_VALUE, - DUPLICATE_SAME_ACCESS - }; - use libc::funcs::extra::kernel32::{ - GetCurrentProcess, - DuplicateHandle, - CloseHandle, - CreateProcessW - }; - use libc::funcs::extra::msvcrt::get_osfhandle; - - use mem; - use iter::IteratorExt; - use str::StrExt; - - if cfg.gid().is_some() || cfg.uid().is_some() { - return Err(IoError { - kind: old_io::IoUnavailable, - desc: "unsupported gid/uid requested on windows", - detail: None, - }) - } - - // To have the spawning semantics of unix/windows stay the same, we need to - // read the *child's* PATH if one is provided. See #15149 for more details. - let program = cfg.env().and_then(|env| { - for (key, v) in env { - if b"PATH" != key.container_as_bytes() { continue } - - // Split the value and test each path to see if the - // program exists. - for path in os::split_paths(v.container_as_bytes()) { - let path = path.join(cfg.program().as_bytes()) - .with_extension(env::consts::EXE_EXTENSION); - if path.exists() { - return Some(CString::from_slice(path.as_vec())) - } - } - break - } - None - }); - - unsafe { - let mut si = zeroed_startupinfo(); - si.cb = mem::size_of::() as DWORD; - si.dwFlags = STARTF_USESTDHANDLES; - - let cur_proc = GetCurrentProcess(); - - // Similarly to unix, we don't actually leave holes for the stdio file - // descriptors, but rather open up /dev/null equivalents. These - // equivalents are drawn from libuv's windows process spawning. - let set_fd = |fd: &Option

, slot: &mut HANDLE, - is_stdin: bool| { - match *fd { - None => { - let access = if is_stdin { - libc::FILE_GENERIC_READ - } else { - libc::FILE_GENERIC_WRITE | libc::FILE_READ_ATTRIBUTES - }; - let size = mem::size_of::(); - let mut sa = libc::SECURITY_ATTRIBUTES { - nLength: size as libc::DWORD, - lpSecurityDescriptor: ptr::null_mut(), - bInheritHandle: 1, - }; - let mut filename: Vec = "NUL".utf16_units().collect(); - filename.push(0); - *slot = libc::CreateFileW(filename.as_ptr(), - access, - libc::FILE_SHARE_READ | - libc::FILE_SHARE_WRITE, - &mut sa, - libc::OPEN_EXISTING, - 0, - ptr::null_mut()); - if *slot == INVALID_HANDLE_VALUE { - return Err(super::last_error()) - } - } - Some(ref fd) => { - let orig = get_osfhandle(fd.as_inner().fd()) as HANDLE; - if orig == INVALID_HANDLE_VALUE { - return Err(super::last_error()) - } - if DuplicateHandle(cur_proc, orig, cur_proc, slot, - 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { - return Err(super::last_error()) - } - } - } - Ok(()) - }; - - try!(set_fd(&in_fd, &mut si.hStdInput, true)); - try!(set_fd(&out_fd, &mut si.hStdOutput, false)); - try!(set_fd(&err_fd, &mut si.hStdError, false)); - - let cmd_str = make_command_line(program.as_ref().unwrap_or(cfg.program()), - cfg.args()); - let mut pi = zeroed_process_information(); - let mut create_err = None; - - // stolen from the libuv code. - let mut flags = libc::CREATE_UNICODE_ENVIRONMENT; - if cfg.detach() { - flags |= libc::DETACHED_PROCESS | libc::CREATE_NEW_PROCESS_GROUP; - } - - with_envp(cfg.env(), |envp| { - with_dirp(cfg.cwd(), |dirp| { - let mut cmd_str: Vec = cmd_str.utf16_units().collect(); - cmd_str.push(0); - let _lock = CREATE_PROCESS_LOCK.lock().unwrap(); - let created = CreateProcessW(ptr::null(), - cmd_str.as_mut_ptr(), - ptr::null_mut(), - ptr::null_mut(), - TRUE, - flags, envp, dirp, - &mut si, &mut pi); - if created == FALSE { - create_err = Some(super::last_error()); - } - }) - }); - - assert!(CloseHandle(si.hStdInput) != 0); - assert!(CloseHandle(si.hStdOutput) != 0); - assert!(CloseHandle(si.hStdError) != 0); - - match create_err { - Some(err) => return Err(err), - None => {} - } - - // We close the thread handle because we don't care about keeping the - // thread id valid, and we aren't keeping the thread handle around to be - // able to close it later. We don't close the process handle however - // because std::we want the process id to stay valid at least until the - // calling code closes the process handle. - assert!(CloseHandle(pi.hThread) != 0); - - Ok(Process { - pid: pi.dwProcessId as pid_t, - handle: pi.hProcess as *mut () - }) - } - } - #[allow(deprecated)] - #[cfg(not(stage0))] pub fn spawn(cfg: &C, in_fd: Option

, out_fd: Option

, err_fd: Option

  • {} {}", - path_to_root.join(item.path.with_extension("html")).display(), + path_to_root.join(&item.path.with_extension("html")).display(), section, item.title)); if !item.children.is_empty() { try!(writeln!(out, "
      ")); - let _ = walk_items(&item.children[], section, path_to_root, out); + let _ = walk_items(&item.children[..], section, path_to_root, out); try!(writeln!(out, "
    ")); } try!(writeln!(out, "
  • ")); @@ -65,7 +67,7 @@ fn write_toc(book: &Book, path_to_root: &Path, out: &mut Writer) -> IoResult<()> try!(writeln!(out, "
    ")); try!(writeln!(out, "
      ")); - try!(walk_items(&book.chapters[], "", path_to_root, out)); + try!(walk_items(&book.chapters[..], "", path_to_root, out)); try!(writeln!(out, "
    ")); try!(writeln!(out, "
    ")); @@ -75,30 +77,35 @@ fn write_toc(book: &Book, path_to_root: &Path, out: &mut Writer) -> IoResult<()> fn render(book: &Book, tgt: &Path) -> CliResult<()> { let tmp = try!(TempDir::new("rust-book")); - for (section, item) in book.iter() { - println!("{} {}", section, item.title); - - let out_path = tgt.join(item.path.dirname()); + for (_section, item) in book.iter() { + let out_path = match item.path.parent() { + Some(p) => tgt.join(p), + None => tgt.to_path_buf(), + }; let src; if env::args().len() < 3 { - src = os::getcwd().unwrap().clone(); + src = env::current_dir().unwrap().clone(); } else { - src = Path::new(env::args().nth(2).unwrap().clone()); + src = PathBuf::from(&env::args().nth(2).unwrap()); } // preprocess the markdown, rerouting markdown references to html references - let markdown_data = try!(File::open(&src.join(&item.path)).read_to_string()); - let preprocessed_path = tmp.path().join(item.path.filename().unwrap()); + let mut markdown_data = String::new(); + try!(File::open(&src.join(&item.path)).and_then(|mut f| { + f.read_to_string(&mut markdown_data) + })); + let preprocessed_path = tmp.path().join(item.path.file_name().unwrap()); { let urls = markdown_data.replace(".md)", ".html)"); - try!(File::create(&preprocessed_path) - .write_str(&urls[..])); + try!(File::create(&preprocessed_path).and_then(|mut f| { + f.write_all(urls.as_bytes()) + })); } // write the prelude to a temporary HTML file for rustdoc inclusion let prelude = tmp.path().join("prelude.html"); { - let mut toc = BufferedWriter::new(try!(File::create(&prelude))); + let mut toc = BufWriter::new(try!(File::create(&prelude))); try!(writeln!(&mut toc, r#"

    ) -> IoResult @@ -292,8 +128,6 @@ impl Process { use libc::funcs::extra::msvcrt::get_osfhandle; use mem; - use iter::IteratorExt; - use str::StrExt; if cfg.gid().is_some() || cfg.uid().is_some() { return Err(IoError { @@ -308,14 +142,19 @@ impl Process { let program = cfg.env().and_then(|env| { for (key, v) in env { if b"PATH" != key.container_as_bytes() { continue } + let v = match ::str::from_utf8(v.container_as_bytes()) { + Ok(s) => s, + Err(..) => continue, + }; // Split the value and test each path to see if the // program exists. - for path in os::split_paths(v.container_as_bytes()) { - let path = path.join(cfg.program().as_bytes()) + for path in ::env::split_paths(v) { + let program = str::from_utf8(cfg.program().as_bytes()).unwrap(); + let path = path.join(program) .with_extension(env::consts::EXE_EXTENSION); if path.exists() { - return Some(CString::from_slice(path.as_vec())) + return Some(CString::new(path.to_str().unwrap()).unwrap()) } } break @@ -475,7 +314,7 @@ impl Process { } if status != STILL_ACTIVE { assert!(CloseHandle(process) != 0); - return Ok(ExitStatus(status as int)); + return Ok(ExitStatus(status as isize)); } let interval = if deadline == 0 { INFINITE @@ -560,7 +399,7 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String { } } - fn append_char_at(cmd: &mut String, arg: &[char], i: uint) { + fn append_char_at(cmd: &mut String, arg: &[char], i: usize) { match arg[i] { '"' => { // Escape quotes. @@ -581,7 +420,7 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String { } } - fn backslash_run_ends_in_quote(s: &[char], mut i: uint) -> bool { + fn backslash_run_ends_in_quote(s: &[char], mut i: usize) -> bool { while i < s.len() && s[i] == '\\' { i += 1; } @@ -589,35 +428,6 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String { } } -#[cfg(stage0)] -fn with_envp(env: Option<&collections::HashMap>, cb: F) -> T - where K: BytesContainer + Eq + Hash, - V: BytesContainer, - F: FnOnce(*mut c_void) -> T, -{ - // On Windows we pass an "environment block" which is not a char**, but - // rather a concatenation of null-terminated k=v\0 sequences, with a final - // \0 to terminate. - match env { - Some(env) => { - let mut blk = Vec::new(); - - for pair in env { - let kv = format!("{}={}", - pair.0.container_as_str().unwrap(), - pair.1.container_as_str().unwrap()); - blk.extend(kv.utf16_units()); - blk.push(0); - } - - blk.push(0); - - cb(blk.as_mut_ptr() as *mut c_void) - } - _ => cb(ptr::null_mut()) - } -} -#[cfg(not(stage0))] fn with_envp(env: Option<&collections::HashMap>, cb: F) -> T where K: BytesContainer + Eq + Hash, V: BytesContainer, @@ -677,9 +487,9 @@ mod tests { #[test] fn test_make_command_line() { fn test_wrapper(prog: &str, args: &[&str]) -> String { - make_command_line(&CString::from_slice(prog.as_bytes()), + make_command_line(&CString::new(prog).unwrap(), &args.iter() - .map(|a| CString::from_slice(a.as_bytes())) + .map(|a| CString::new(*a).unwrap()) .collect::>()) } diff --git a/src/libstd/sys/windows/process2.rs b/src/libstd/sys/windows/process2.rs index 19e38196d1..7e832b6384 100644 --- a/src/libstd/sys/windows/process2.rs +++ b/src/libstd/sys/windows/process2.rs @@ -16,16 +16,15 @@ use collections; use env; use ffi::{OsString, OsStr}; use fmt; +use fs; use io::{self, Error}; use libc::{self, c_void}; -use old_io::fs; -use old_path; -use os::windows::OsStrExt; +use os::windows::ffi::OsStrExt; use ptr; use sync::{StaticMutex, MUTEX_INIT}; +use sys::handle::Handle; use sys::pipe2::AnonPipe; use sys::{self, cvt}; -use sys::handle::Handle; use sys_common::{AsInner, FromInner}; //////////////////////////////////////////////////////////////////////////////// @@ -128,8 +127,7 @@ impl Process { use env::split_paths; use mem; - use iter::IteratorExt; - use str::StrExt; + use iter::Iterator; // To have the spawning semantics of unix/windows stay the same, we need to // read the *child's* PATH if one is provided. See #15149 for more details. @@ -142,9 +140,8 @@ impl Process { for path in split_paths(&v) { let path = path.join(cfg.program.to_str().unwrap()) .with_extension(env::consts::EXE_EXTENSION); - // FIXME: update with new fs module once it lands - if fs::stat(&old_path::Path::new(&path)).is_ok() { - return Some(OsString::from_str(path.as_str().unwrap())) + if fs::metadata(&path).is_ok() { + return Some(path.into_os_string()) } } break @@ -162,7 +159,7 @@ impl Process { // Similarly to unix, we don't actually leave holes for the stdio file // descriptors, but rather open up /dev/null equivalents. These // equivalents are drawn from libuv's windows process spawning. - let set_fd = |&: fd: &Option, slot: &mut HANDLE, + let set_fd = |fd: &Option, slot: &mut HANDLE, is_stdin: bool| { match *fd { None => { @@ -448,10 +445,9 @@ mod tests { fn test_wrapper(prog: &str, args: &[&str]) -> String { String::from_utf16( &make_command_line(OsStr::from_str(prog), - args.iter() - .map(|a| OsString::from_str(a)) - .collect::>() - .as_slice())).unwrap() + &args.iter() + .map(|a| OsString::from(a)) + .collect::>())).unwrap() } assert_eq!( diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs index 76fe352ed7..009605535a 100644 --- a/src/libstd/sys/windows/rwlock.rs +++ b/src/libstd/sys/windows/rwlock.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + use cell::UnsafeCell; use sys::sync as ffi; @@ -17,6 +19,9 @@ pub const RWLOCK_INIT: RWLock = RWLock { inner: UnsafeCell { value: ffi::SRWLOCK_INIT } }; +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + impl RWLock { #[inline] pub unsafe fn read(&self) { diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs index b0410701ee..79b7de4f34 100644 --- a/src/libstd/sys/windows/stack_overflow.rs +++ b/src/libstd/sys/windows/stack_overflow.rs @@ -31,7 +31,7 @@ impl Drop for Handler { } // This is initialized in init() and only read from after -static mut PAGE_SIZE: uint = 0; +static mut PAGE_SIZE: usize = 0; #[no_stack_check] extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG { @@ -56,7 +56,7 @@ extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> L pub unsafe fn init() { let mut info = mem::zeroed(); libc::GetSystemInfo(&mut info); - PAGE_SIZE = info.dwPageSize as uint; + PAGE_SIZE = info.dwPageSize as usize; if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() { panic!("failed to install exception handler"); @@ -96,7 +96,7 @@ pub type PVECTORED_EXCEPTION_HANDLER = extern "system" pub type ULONG = libc::c_ulong; const EXCEPTION_CONTINUE_SEARCH: LONG = 0; -const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15; +const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; extern "system" { diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs new file mode 100644 index 0000000000..91f6f328ff --- /dev/null +++ b/src/libstd/sys/windows/stdio.rs @@ -0,0 +1,164 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; +use io::prelude::*; + +use io::{self, Cursor}; +use iter::repeat; +use libc; +use ptr; +use str; +use sync::Mutex; +use sys::c; +use sys::cvt; +use sys::handle::Handle; + +struct NoClose(Option); + +enum Output { + Console(NoClose), + Pipe(NoClose), +} + +pub struct Stdin { + handle: Output, + utf8: Mutex>>, +} +pub struct Stdout(Output); +pub struct Stderr(Output); + +fn get(handle: libc::DWORD) -> io::Result { + let handle = unsafe { c::GetStdHandle(handle) }; + if handle == libc::INVALID_HANDLE_VALUE { + Err(io::Error::last_os_error()) + } else if handle.is_null() { + Err(io::Error::new(io::ErrorKind::Other, + "no stdio handle available for this process")) + } else { + let ret = NoClose::new(handle); + let mut out = 0; + match unsafe { c::GetConsoleMode(handle, &mut out) } { + 0 => Ok(Output::Pipe(ret)), + _ => Ok(Output::Console(ret)), + } + } +} + +fn write(out: &Output, data: &[u8]) -> io::Result { + let handle = match *out { + Output::Console(ref c) => c.get().raw(), + Output::Pipe(ref p) => return p.get().write(data), + }; + let utf16 = match str::from_utf8(data).ok() { + Some(utf8) => utf8.utf16_units().collect::>(), + None => return Err(invalid_encoding()), + }; + let mut written = 0; + try!(cvt(unsafe { + c::WriteConsoleW(handle, + utf16.as_ptr() as libc::LPCVOID, + utf16.len() as u32, + &mut written, + ptr::null_mut()) + })); + + // FIXME if this only partially writes the utf16 buffer then we need to + // figure out how many bytes of `data` were actually written + assert_eq!(written as usize, utf16.len()); + Ok(data.len()) +} + +impl Stdin { + pub fn new() -> Stdin { + Stdin { + handle: get(c::STD_INPUT_HANDLE).unwrap(), + utf8: Mutex::new(Cursor::new(Vec::new())), + } + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + let handle = match self.handle { + Output::Console(ref c) => c.get().raw(), + Output::Pipe(ref p) => return p.get().read(buf), + }; + let mut utf8 = self.utf8.lock().unwrap(); + // Read more if the buffer is empty + if utf8.position() as usize == utf8.get_ref().len() { + let mut utf16: Vec = repeat(0u16).take(0x1000).collect(); + let mut num = 0; + try!(cvt(unsafe { + c::ReadConsoleW(handle, + utf16.as_mut_ptr() as libc::LPVOID, + utf16.len() as u32, + &mut num, + ptr::null_mut()) + })); + utf16.truncate(num as usize); + // FIXME: what to do about this data that has already been read? + let data = match String::from_utf16(&utf16) { + Ok(utf8) => utf8.into_bytes(), + Err(..) => return Err(invalid_encoding()), + }; + *utf8 = Cursor::new(data); + } + + // MemReader shouldn't error here since we just filled it + utf8.read(buf) + } +} + +impl Stdout { + pub fn new() -> Stdout { + Stdout(get(c::STD_OUTPUT_HANDLE).unwrap()) + } + + pub fn write(&self, data: &[u8]) -> io::Result { + write(&self.0, data) + } +} + +impl Stderr { + pub fn new() -> Stderr { + Stderr(get(c::STD_ERROR_HANDLE).unwrap()) + } + + pub fn write(&self, data: &[u8]) -> io::Result { + write(&self.0, data) + } +} + +// FIXME: right now this raw stderr handle is used in a few places because +// std::io::stderr_raw isn't exposed, but once that's exposed this impl +// should go away +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result { + Stderr::write(self, data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +impl NoClose { + fn new(handle: libc::HANDLE) -> NoClose { + NoClose(Some(Handle::new(handle))) + } + + fn get(&self) -> &Handle { self.0.as_ref().unwrap() } +} + +impl Drop for NoClose { + fn drop(&mut self) { + self.0.take().unwrap().into_raw(); + } +} + +fn invalid_encoding() -> io::Error { + io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode") +} diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs index 4804ca510c..41e97dc847 100644 --- a/src/libstd/sys/windows/tcp.rs +++ b/src/libstd/sys/windows/tcp.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(deprecated)] + +use prelude::v1::*; + use old_io::net::ip; use old_io::IoResult; use libc; +use libc::consts::os::extra::INVALID_SOCKET; use mem; use ptr; -use prelude::v1::*; use super::{last_error, last_net_error, sock_t}; use sync::Arc; use sync::atomic::{AtomicBool, Ordering}; @@ -74,7 +78,7 @@ impl TcpListener { pub fn socket(&self) -> sock_t { self.sock } - pub fn listen(self, backlog: int) -> IoResult { + pub fn listen(self, backlog: isize) -> IoResult { match unsafe { libc::listen(self.socket(), backlog as libc::c_int) } { -1 => Err(last_net_error()), @@ -180,8 +184,8 @@ impl TcpAcceptor { match unsafe { libc::accept(self.socket(), ptr::null_mut(), ptr::null_mut()) } { - -1 if wouldblock() => {} - -1 => return Err(last_net_error()), + INVALID_SOCKET if wouldblock() => {} + INVALID_SOCKET => return Err(last_net_error()), // Accepted sockets inherit the same properties as the caller, // so we need to deregister our event and switch the socket back @@ -192,7 +196,7 @@ impl TcpAcceptor { c::WSAEventSelect(socket, events[1], 0) }; if ret != 0 { return Err(last_net_error()) } - try!(set_nonblocking(socket, false)); + set_nonblocking(socket, false); return Ok(stream) } } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index f3a27877e5..98e4a737c7 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -12,40 +12,26 @@ use prelude::v1::*; use cmp; use io; -use mem; -use ptr; -use libc; +use libc::{self, c_void}; use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL, LPVOID, DWORD, LPDWORD, HANDLE}; -use thunk::Thunk; +use mem; +use ptr; use sys_common::stack::RED_ZONE; use sys_common::thread::*; +use thunk::Thunk; +use time::Duration; pub type rust_thread = HANDLE; -pub type rust_thread_return = DWORD; - -pub type StartFn = extern "system" fn(*mut libc::c_void) -> rust_thread_return; - -#[no_stack_check] -pub extern "system" fn thread_start(main: *mut libc::c_void) -> rust_thread_return { - return start_thread(main); -} pub mod guard { - pub unsafe fn main() -> uint { - 0 - } - - pub unsafe fn current() -> uint { - 0 - } - - pub unsafe fn init() { - } + pub unsafe fn main() -> usize { 0 } + pub unsafe fn current() -> usize { 0 } + pub unsafe fn init() {} } -pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { - let arg: *mut libc::c_void = mem::transmute(box p); +pub unsafe fn create(stack: usize, p: Thunk) -> io::Result { + let p = box p; // FIXME On UNIX, we guard against stack sizes that are too small but // that's because pthreads enforces that stacks are at least // PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's @@ -57,14 +43,20 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { // 20 kB red zone, that makes for a 64 kB minimum stack. let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1); let ret = CreateThread(ptr::null_mut(), stack_size as libc::size_t, - thread_start, arg, 0, ptr::null_mut()); + thread_start, &*p as *const _ as *mut _, + 0, ptr::null_mut()); - if ret as uint == 0 { - // be sure to not leak the closure - let _p: Box = mem::transmute(arg); + return if ret as usize == 0 { Err(io::Error::last_os_error()) } else { + mem::forget(p); // ownership passed to CreateThread Ok(ret) + }; + + #[no_stack_check] + extern "system" fn thread_start(main: *mut libc::c_void) -> DWORD { + start_thread(main); + 0 } } @@ -91,14 +83,29 @@ pub unsafe fn yield_now() { SwitchToThread(); } +pub fn sleep(dur: Duration) { + unsafe { + if dur < Duration::zero() { + return yield_now() + } + let ms = dur.num_milliseconds(); + // if we have a fractional number of milliseconds then add an extra + // millisecond to sleep for + let extra = dur - Duration::milliseconds(ms); + let ms = ms + if extra.is_zero() {0} else {1}; + Sleep(ms as DWORD); + } +} + #[allow(non_snake_case)] extern "system" { fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, - lpStartAddress: StartFn, + lpStartAddress: extern "system" fn(*mut c_void) -> DWORD, lpParameter: LPVOID, dwCreationFlags: DWORD, lpThreadId: LPDWORD) -> HANDLE; fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; fn SwitchToThread() -> BOOL; + fn Sleep(dwMilliseconds: DWORD); } diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index 0c24ab1fa0..cbabab8acb 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -12,7 +12,7 @@ use prelude::v1::*; use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL}; -use mem; +use boxed; use ptr; use rt; use sys_common::mutex::{MUTEX_INIT, Mutex}; @@ -133,21 +133,28 @@ unsafe fn init_dtors() { if !DTORS.is_null() { return } let dtors = box Vec::<(Key, Dtor)>::new(); - DTORS = mem::transmute(dtors); - rt::at_exit(move|| { + let res = rt::at_exit(move|| { DTOR_LOCK.lock(); let dtors = DTORS; - DTORS = ptr::null_mut(); - mem::transmute::<_, Box>>(dtors); - assert!(DTORS.is_null()); // can't re-init after destructing + DTORS = 1 as *mut _; + Box::from_raw(dtors); + assert!(DTORS as usize == 1); // can't re-init after destructing DTOR_LOCK.unlock(); }); + if res.is_ok() { + DTORS = boxed::into_raw(dtors); + } else { + DTORS = 1 as *mut _; + } } unsafe fn register_dtor(key: Key, dtor: Dtor) { DTOR_LOCK.lock(); init_dtors(); + assert!(DTORS as usize != 0); + assert!(DTORS as usize != 1, + "cannot create new TLS keys after the main thread has exited"); (*DTORS).push((key, dtor)); DTOR_LOCK.unlock(); } @@ -155,6 +162,9 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) { unsafe fn unregister_dtor(key: Key) -> bool { DTOR_LOCK.lock(); init_dtors(); + assert!(DTORS as usize != 0); + assert!(DTORS as usize != 1, + "cannot unregister destructors after the main thread has exited"); let ret = { let dtors = &mut *DTORS; let before = dtors.len(); @@ -241,7 +251,7 @@ unsafe fn run_dtors() { any_run = false; let dtors = { DTOR_LOCK.lock(); - let ret = if DTORS.is_null() { + let ret = if DTORS as usize <= 1 { Vec::new() } else { (*DTORS).iter().map(|s| *s).collect() diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index 20ceff0aa6..209460df10 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -12,6 +12,8 @@ use ops::Sub; use time::Duration; use sync::{Once, ONCE_INIT}; +const NANOS_PER_SEC: i64 = 1_000_000_000; + pub struct SteadyTime { t: libc::LARGE_INTEGER, } @@ -24,7 +26,7 @@ impl SteadyTime { } pub fn ns(&self) -> u64 { - self.t as u64 * 1_000_000_000 / frequency() as u64 + mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64 } } @@ -45,6 +47,27 @@ impl<'a> Sub for &'a SteadyTime { fn sub(self, other: &SteadyTime) -> Duration { let diff = self.t as i64 - other.t as i64; - Duration::microseconds(diff * 1_000_000 / frequency() as i64) + Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64)) } } + +// Computes (value*numer)/denom without overflow, as long as both +// (numer*denom) and the overall result fit into i64 (which is the case +// for our time conversions). +fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 { + let q = value / denom; + let r = value % denom; + // Decompose value as (value/denom*denom + value%denom), + // substitute into (value*numer)/denom and simplify. + // r < denom, so (denom*numer) is the upper bound of (r*numer) + q * numer + r * numer / denom +} + +#[test] +fn test_muldiv() { + assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000), 1_000_000_000_001_000); + assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000); + assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000), 1_000_000_000_001_000); + assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000); + assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000), 1_000_000_000_001_000); +} diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index d156dd801f..8856cc26b2 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -20,15 +20,17 @@ //! Other than that, the implementation is pretty straightforward in terms of //! the other two implementations of timers with nothing *that* new showing up. -use self::Req::*; +#![allow(deprecated)] + use prelude::v1::*; +use self::Req::*; use libc; use ptr; use old_io::IoResult; -use sync::mpsc::{channel, Sender, Receiver, TryRecvError}; use sys_common::helper_thread::Helper; +use sync::mpsc::{channel, TryRecvError, Sender, Receiver}; helper_init! { static HELPER: Helper } @@ -78,9 +80,10 @@ fn helper(input: libc::HANDLE, messages: Receiver, _: ()) { None => {} } } + // See the comment in unix::timer for why we don't have any + // asserts here and why we're likely just leaving timers on + // the floor as we exit. Err(TryRecvError::Disconnected) => { - assert_eq!(objs.len(), 1); - assert_eq!(chans.len(), 0); break 'outer; } Err(..) => break @@ -88,13 +91,13 @@ fn helper(input: libc::HANDLE, messages: Receiver, _: ()) { } } else { let remove = { - match &mut chans[idx as uint - 1] { + match &mut chans[idx as usize - 1] { &mut (ref mut c, oneshot) => { c.call(); oneshot } } }; if remove { - drop(objs.remove(idx as uint)); - drop(chans.remove(idx as uint - 1)); + drop(objs.remove(idx as usize)); + drop(chans.remove(idx as usize - 1)); } } } diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index 8a8b530905..791c7532bd 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -25,9 +25,11 @@ //! wrapper that performs encoding/decoding, this implementation should switch //! to working in raw UTF-16, with such a wrapper around it. +#![allow(deprecated)] + use prelude::v1::*; -use old_io::{self, IoError, IoResult, MemReader}; +use old_io::{self, IoError, IoResult, MemReader, Reader}; use iter::repeat; use libc::types::os::arch::extra::LPCVOID; use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID}; @@ -38,9 +40,9 @@ use str::from_utf8; use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; -use super::c::{CONSOLE_SCREEN_BUFFER_INFO}; +use super::c::CONSOLE_SCREEN_BUFFER_INFO; use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; -use super::c::{GetConsoleScreenBufferInfo}; +use super::c::GetConsoleScreenBufferInfo; fn invalid_encoding() -> IoError { IoError { @@ -52,7 +54,7 @@ fn invalid_encoding() -> IoError { pub fn is_tty(fd: c_int) -> bool { let mut out: DWORD = 0; - // If this function doesn't panic then fd is a TTY + // If this function doesn't return an error, then fd is a TTY match unsafe { GetConsoleMode(get_osfhandle(fd) as HANDLE, &mut out as LPDWORD) } { 0 => false, @@ -90,7 +92,7 @@ impl TTY { } } - pub fn read(&mut self, buf: &mut [u8]) -> IoResult { + pub fn read(&mut self, buf: &mut [u8]) -> IoResult { // Read more if the buffer is empty if self.utf8.eof() { let mut utf16: Vec = repeat(0u16).take(0x1000).collect(); @@ -103,7 +105,7 @@ impl TTY { 0 => return Err(super::last_error()), _ => (), }; - utf16.truncate(num as uint); + utf16.truncate(num as usize); let utf8 = match String::from_utf16(&utf16) { Ok(utf8) => utf8.into_bytes(), Err(..) => return Err(invalid_encoding()), @@ -147,12 +149,12 @@ impl TTY { } } - pub fn get_winsize(&mut self) -> IoResult<(int, int)> { + pub fn get_winsize(&mut self) -> IoResult<(isize, isize)> { let mut info: CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() }; match unsafe { GetConsoleScreenBufferInfo(self.handle, &mut info as *mut _) } { 0 => Err(super::last_error()), - _ => Ok(((info.srWindow.Right + 1 - info.srWindow.Left) as int, - (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)), + _ => Ok(((info.srWindow.Right + 1 - info.srWindow.Left) as isize, + (info.srWindow.Bottom + 1 - info.srWindow.Top) as isize)), } } } diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread/local.rs similarity index 81% rename from src/libstd/thread_local/mod.rs rename to src/libstd/thread/local.rs index 2ed296e081..acd6970f11 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread/local.rs @@ -9,43 +9,16 @@ // except according to those terms. //! Thread local storage -//! -//! This module provides an implementation of thread local storage for Rust -//! programs. Thread local storage is a method of storing data into a global -//! variable which each thread in the program will have its own copy of. -//! Threads do not share this data, so accesses do not need to be synchronized. -//! -//! At a high level, this module provides two variants of storage: -//! -//! * Owning thread local storage. This is a type of thread local key which -//! owns the value that it contains, and will destroy the value when the -//! thread exits. This variant is created with the `thread_local!` macro and -//! can contain any value which is `'static` (no borrowed pointers. -//! -//! * Scoped thread local storage. This type of key is used to store a reference -//! to a value into local storage temporarily for the scope of a function -//! call. There are no restrictions on what types of values can be placed -//! into this key. -//! -//! Both forms of thread local storage provide an accessor function, `with`, -//! which will yield a shared reference to the value to the specified -//! closure. Thread local keys only allow shared access to values as there is no -//! way to guarantee uniqueness if a mutable borrow was allowed. Most values -//! will want to make use of some form of **interior mutability** through the -//! `Cell` or `RefCell` types. - -#![stable(feature = "rust1", since = "1.0.0")] + +#![unstable(feature = "thread_local_internals")] use prelude::v1::*; use cell::UnsafeCell; -#[macro_use] -pub mod scoped; - // Sure wish we had macro hygiene, no? #[doc(hidden)] -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "thread_local_internals")] pub mod __impl { pub use super::imp::Key as KeyInner; pub use super::imp::destroy_value; @@ -68,13 +41,13 @@ pub mod __impl { /// within a thread, and values support destructors which will be run when a /// thread exits. /// -/// # Example +/// # Examples /// /// ``` /// use std::cell::RefCell; /// use std::thread; /// -/// thread_local!(static FOO: RefCell = RefCell::new(1)); +/// thread_local!(static FOO: RefCell = RefCell::new(1)); /// /// FOO.with(|f| { /// assert_eq!(*f.borrow(), 1); @@ -95,7 +68,7 @@ pub mod __impl { /// }); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct Key { +pub struct LocalKey { // The key itself may be tagged with #[thread_local], and this `Key` is // stored as a `static`, and it's not valid for a static to reference the // address of another thread_local static. For this reason we kinda wonkily @@ -105,21 +78,24 @@ pub struct Key { // This is trivially devirtualizable by LLVM because we never store anything // to this field and rustc can declare the `static` as constant as well. #[doc(hidden)] + #[unstable(feature = "thread_local_internals")] pub inner: fn() -> &'static __impl::KeyInner>>, // initialization routine to invoke to create a value #[doc(hidden)] + #[unstable(feature = "thread_local_internals")] pub init: fn() -> T, } -/// Declare a new thread local storage key of type `std::thread_local::Key`. +/// Declare a new thread local storage key of type `std::thread::LocalKey`. #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable] macro_rules! thread_local { (static $name:ident: $t:ty = $init:expr) => ( - static $name: ::std::thread_local::Key<$t> = { + static $name: ::std::thread::LocalKey<$t> = { use std::cell::UnsafeCell as __UnsafeCell; - use std::thread_local::__impl::KeyInner as __KeyInner; + use std::thread::__local::__impl::KeyInner as __KeyInner; use std::option::Option as __Option; use std::option::Option::None as __None; @@ -130,13 +106,13 @@ macro_rules! thread_local { fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> { &__KEY } - ::std::thread_local::Key { inner: __getit, init: __init } + ::std::thread::LocalKey { inner: __getit, init: __init } }; ); (pub static $name:ident: $t:ty = $init:expr) => ( - pub static $name: ::std::thread_local::Key<$t> = { + pub static $name: ::std::thread::LocalKey<$t> = { use std::cell::UnsafeCell as __UnsafeCell; - use std::thread_local::__impl::KeyInner as __KeyInner; + use std::thread::__local::__impl::KeyInner as __KeyInner; use std::option::Option as __Option; use std::option::Option::None as __None; @@ -147,7 +123,7 @@ macro_rules! thread_local { fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> { &__KEY } - ::std::thread_local::Key { inner: __getit, init: __init } + ::std::thread::LocalKey { inner: __getit, init: __init } }; ); } @@ -174,42 +150,42 @@ macro_rules! thread_local { #[macro_export] #[doc(hidden)] +#[allow_internal_unstable] macro_rules! __thread_local_inner { (static $name:ident: $t:ty = $init:expr) => ( #[cfg_attr(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")), thread_local)] - static $name: ::std::thread_local::__impl::KeyInner<$t> = + static $name: ::std::thread::__local::__impl::KeyInner<$t> = __thread_local_inner!($init, $t); ); (pub static $name:ident: $t:ty = $init:expr) => ( #[cfg_attr(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")), thread_local)] - pub static $name: ::std::thread_local::__impl::KeyInner<$t> = + pub static $name: ::std::thread::__local::__impl::KeyInner<$t> = __thread_local_inner!($init, $t); ); ($init:expr, $t:ty) => ({ #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))] - const _INIT: ::std::thread_local::__impl::KeyInner<$t> = { - ::std::thread_local::__impl::KeyInner { + const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = { + ::std::thread::__local::__impl::KeyInner { inner: ::std::cell::UnsafeCell { value: $init }, dtor_registered: ::std::cell::UnsafeCell { value: false }, dtor_running: ::std::cell::UnsafeCell { value: false }, } }; + #[allow(trivial_casts)] #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))] - const _INIT: ::std::thread_local::__impl::KeyInner<$t> = { - unsafe extern fn __destroy(ptr: *mut u8) { - ::std::thread_local::__impl::destroy_value::<$t>(ptr); - } - - ::std::thread_local::__impl::KeyInner { + const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = { + ::std::thread::__local::__impl::KeyInner { inner: ::std::cell::UnsafeCell { value: $init }, - os: ::std::thread_local::__impl::OsStaticKey { - inner: ::std::thread_local::__impl::OS_INIT_INNER, - dtor: ::std::option::Option::Some(__destroy as unsafe extern fn(*mut u8)), + os: ::std::thread::__local::__impl::OsStaticKey { + inner: ::std::thread::__local::__impl::OS_INIT_INNER, + dtor: ::std::option::Option::Some( + ::std::thread::__local::__impl::destroy_value::<$t> + ), }, } }; @@ -221,8 +197,8 @@ macro_rules! __thread_local_inner { /// Indicator of the state of a thread local storage key. #[unstable(feature = "std_misc", reason = "state querying was recently added")] -#[derive(Eq, PartialEq, Copy)] -pub enum State { +#[derive(Eq, PartialEq, Copy, Clone)] +pub enum LocalKeyState { /// All keys are in this state whenever a thread starts. Keys will /// transition to the `Valid` state once the first call to `with` happens /// and the initialization expression succeeds. @@ -249,7 +225,7 @@ pub enum State { Destroyed, } -impl Key { +impl LocalKey { /// Acquire a reference to the value in this TLS key. /// /// This will lazily initialize the value if this thread has not referenced @@ -305,25 +281,19 @@ impl Key { /// any call to `with`. #[unstable(feature = "std_misc", reason = "state querying was recently added")] - pub fn state(&'static self) -> State { + pub fn state(&'static self) -> LocalKeyState { unsafe { match (self.inner)().get() { Some(cell) => { match *cell.get() { - Some(..) => State::Valid, - None => State::Uninitialized, + Some(..) => LocalKeyState::Valid, + None => LocalKeyState::Uninitialized, } } - None => State::Destroyed, + None => LocalKeyState::Destroyed, } } } - - /// Deprecated - #[unstable(feature = "std_misc")] - #[deprecated(since = "1.0.0", - reason = "function renamed to state() and returns more info")] - pub fn destroyed(&'static self) -> bool { self.state() == State::Destroyed } } #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))] @@ -335,7 +305,7 @@ mod imp { use ptr; #[doc(hidden)] - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub struct Key { // Place the inner bits in an `UnsafeCell` to currently get around the // "only Sync statics" restriction. This allows any type to be placed in @@ -343,14 +313,14 @@ mod imp { // // Note that all access requires `T: 'static` so it can't be a type with // any borrowed pointers still. - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub inner: UnsafeCell, // Metadata to keep track of the state of the destructor. Remember that // these variables are thread-local, not global. - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub dtor_registered: UnsafeCell, // should be Cell - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub dtor_running: UnsafeCell, // should be Cell } @@ -388,6 +358,7 @@ mod imp { // Due to rust-lang/rust#18804, make sure this is not generic! #[cfg(target_os = "linux")] unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { + use boxed; use mem; use libc; use sys_common::thread_local as os; @@ -422,14 +393,14 @@ mod imp { type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; if DTORS.get().is_null() { let v: Box = box Vec::new(); - DTORS.set(mem::transmute(v)); + DTORS.set(boxed::into_raw(v) as *mut u8); } let list: &mut List = &mut *(DTORS.get() as *mut List); list.push((t, dtor)); unsafe extern fn run_dtors(mut ptr: *mut u8) { while !ptr.is_null() { - let list: Box = mem::transmute(ptr); + let list: Box = Box::from_raw(ptr as *mut List); for &(ptr, dtor) in &*list { dtor(ptr); } @@ -452,7 +423,7 @@ mod imp { } #[doc(hidden)] - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "thread_local_internals")] pub unsafe extern fn destroy_value(ptr: *mut u8) { let ptr = ptr as *mut Key; // Right before we run the user destructor be sure to flag the @@ -467,21 +438,22 @@ mod imp { mod imp { use prelude::v1::*; + use alloc::boxed; use cell::UnsafeCell; use mem; use ptr; use sys_common::thread_local::StaticKey as OsStaticKey; #[doc(hidden)] - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub struct Key { // Statically allocated initialization expression, using an `UnsafeCell` // for the same reasons as above. - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub inner: UnsafeCell, // OS-TLS key that we'll use to key off. - #[stable(since = "1.0.0", feature = "rust1")] + #[unstable(feature = "thread_local_internals")] pub os: OsStaticKey, } @@ -501,7 +473,7 @@ mod imp { unsafe fn ptr(&'static self) -> Option<*mut T> { let ptr = self.os.get() as *mut Value; if !ptr.is_null() { - if ptr as uint == 1 { + if ptr as usize == 1 { return None } return Some(&mut (*ptr).value as *mut T); @@ -517,14 +489,14 @@ mod imp { key: self, value: mem::transmute_copy(&self.inner), }; - let ptr: *mut Value = mem::transmute(ptr); + let ptr: *mut Value = boxed::into_raw(ptr); self.os.set(ptr as *mut u8); Some(&mut (*ptr).value as *mut T) } } #[doc(hidden)] - #[stable(feature = "rust1", since = "1.0.0")] + #[unstable(feature = "thread_local_internals")] pub unsafe extern fn destroy_value(ptr: *mut u8) { // The OS TLS ensures that this key contains a NULL value when this // destructor starts to run. We set it back to a sentinel value of 1 to @@ -533,7 +505,7 @@ mod imp { // // Note that to prevent an infinite loop we reset it back to null right // before we return from the destructor ourselves. - let ptr: Box> = mem::transmute(ptr); + let ptr: Box> = Box::from_raw(ptr as *mut Value); let key = ptr.key; key.os.set(1 as *mut u8); drop(ptr); @@ -547,7 +519,7 @@ mod tests { use sync::mpsc::{channel, Sender}; use cell::UnsafeCell; - use super::State; + use super::LocalKeyState; use thread; struct Foo(Sender<()>); @@ -561,7 +533,7 @@ mod tests { #[test] fn smoke_no_dtor() { - thread_local!(static FOO: UnsafeCell = UnsafeCell { value: 1 }); + thread_local!(static FOO: UnsafeCell = UnsafeCell { value: 1 }); FOO.with(|f| unsafe { assert_eq!(*f.get(), 1); @@ -586,21 +558,21 @@ mod tests { struct Foo; impl Drop for Foo { fn drop(&mut self) { - assert!(FOO.state() == State::Destroyed); + assert!(FOO.state() == LocalKeyState::Destroyed); } } fn foo() -> Foo { - assert!(FOO.state() == State::Uninitialized); + assert!(FOO.state() == LocalKeyState::Uninitialized); Foo } thread_local!(static FOO: Foo = foo()); thread::spawn(|| { - assert!(FOO.state() == State::Uninitialized); + assert!(FOO.state() == LocalKeyState::Uninitialized); FOO.with(|_| { - assert!(FOO.state() == State::Valid); + assert!(FOO.state() == LocalKeyState::Valid); }); - assert!(FOO.state() == State::Valid); + assert!(FOO.state() == LocalKeyState::Valid); }).join().ok().unwrap(); } @@ -630,13 +602,13 @@ mod tests { thread_local!(static K2: UnsafeCell> = UnsafeCell { value: None }); - static mut HITS: uint = 0; + static mut HITS: u32 = 0; impl Drop for S1 { fn drop(&mut self) { unsafe { HITS += 1; - if K2.state() == State::Destroyed { + if K2.state() == LocalKeyState::Destroyed { assert_eq!(HITS, 3); } else { if HITS == 1 { @@ -652,7 +624,7 @@ mod tests { fn drop(&mut self) { unsafe { HITS += 1; - assert!(K1.state() != State::Destroyed); + assert!(K1.state() != LocalKeyState::Destroyed); assert_eq!(HITS, 2); K1.with(|s| *s.get() = Some(S1)); } @@ -673,7 +645,7 @@ mod tests { impl Drop for S1 { fn drop(&mut self) { - assert!(K1.state() == State::Destroyed); + assert!(K1.state() == LocalKeyState::Destroyed); } } @@ -696,7 +668,7 @@ mod tests { fn drop(&mut self) { let S1(ref tx) = *self; unsafe { - if K2.state() != State::Destroyed { + if K2.state() != LocalKeyState::Destroyed { K2.with(|s| *s.get() = Some(Foo(tx.clone()))); } } @@ -721,8 +693,8 @@ mod dynamic_tests { #[test] fn smoke() { - fn square(i: int) -> int { i * i } - thread_local!(static FOO: int = square(3)); + fn square(i: i32) -> i32 { i * i } + thread_local!(static FOO: i32 = square(3)); FOO.with(|f| { assert_eq!(*f, 9); @@ -731,21 +703,21 @@ mod dynamic_tests { #[test] fn hashmap() { - fn map() -> RefCell> { + fn map() -> RefCell> { let mut m = HashMap::new(); m.insert(1, 2); RefCell::new(m) } - thread_local!(static FOO: RefCell> = map()); + thread_local!(static FOO: RefCell> = map()); FOO.with(|map| { - assert_eq!(map.borrow()[1], 2); + assert_eq!(map.borrow()[&1], 2); }); } #[test] fn refcell_vec() { - thread_local!(static FOO: RefCell> = RefCell::new(vec![1, 2, 3])); + thread_local!(static FOO: RefCell> = RefCell::new(vec![1, 2, 3])); FOO.with(|vec| { assert_eq!(vec.borrow().len(), 3); diff --git a/src/libstd/thread.rs b/src/libstd/thread/mod.rs similarity index 71% rename from src/libstd/thread.rs rename to src/libstd/thread/mod.rs index 3653e7e31d..5fe6e80d6e 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread/mod.rs @@ -28,25 +28,25 @@ //! a thread will unwind the stack, running destructors and freeing //! owned resources. Thread panic is unrecoverable from within //! the panicking thread (i.e. there is no 'try/catch' in Rust), but -//! panic may optionally be detected from a different thread. If -//! the main thread panics the application will exit with a non-zero +//! the panic may optionally be detected from a different thread. If +//! the main thread panics, the application will exit with a non-zero //! exit code. //! //! When the main thread of a Rust program terminates, the entire program shuts //! down, even if other threads are still running. However, this module provides //! convenient facilities for automatically waiting for the termination of a -//! child thread (i.e., join), described below. +//! child thread (i.e., join). //! //! ## The `Thread` type //! -//! Already-running threads are represented via the `Thread` type, which you can +//! Threads are represented via the `Thread` type, which you can //! get in one of two ways: //! -//! * By spawning a new thread, e.g. using the `thread::spawn` constructor; +//! * By spawning a new thread, e.g. using the `thread::spawn` function. //! * By requesting the current thread, using the `thread::current` function. //! //! Threads can be named, and provide some built-in support for low-level -//! synchronization described below. +//! synchronization (described below). //! //! The `thread::current()` function is available even for threads not spawned //! by the APIs of this module. @@ -59,29 +59,27 @@ //! use std::thread; //! //! thread::spawn(move || { -//! println!("Hello, World!"); -//! // some computation here +//! // some work here //! }); //! ``` //! //! In this example, the spawned thread is "detached" from the current -//! thread, meaning that it can outlive the thread that spawned -//! it. (Note, however, that when the main thread terminates all -//! detached threads are terminated as well.) +//! thread. This means that it can outlive its parent (the thread that spawned +//! it), unless this parent is the main thread. //! //! ## Scoped threads //! //! Often a parent thread uses a child thread to perform some particular task, //! and at some point must wait for the child to complete before continuing. -//! For this scenario, use the `scoped` constructor: +//! For this scenario, use the `thread::scoped` function: //! //! ```rust //! use std::thread; //! //! let guard = thread::scoped(move || { -//! println!("Hello, World!"); -//! // some computation here +//! // some work here //! }); +//! //! // do some other work in the meantime //! let output = guard.join(); //! ``` @@ -92,11 +90,7 @@ //! terminates) when it is dropped. You can join the child thread in //! advance by calling the `join` method on the guard, which will also //! return the result produced by the thread. A handle to the thread -//! itself is available via the `thread` method on the join guard. -//! -//! (Note: eventually, the `scoped` constructor will allow the parent and child -//! threads to data that lives on the parent thread's stack, but some language -//! changes are needed before this is possible.) +//! itself is available via the `thread` method of the join guard. //! //! ## Configuring threads //! @@ -108,7 +102,7 @@ //! use std::thread; //! //! thread::Builder::new().name("child1".to_string()).spawn(move || { -//! println!("Hello, world!") +//! println!("Hello, world!"); //! }); //! ``` //! @@ -121,7 +115,7 @@ //! initially not present: //! //! * The `thread::park()` function blocks the current thread unless or until -//! the token is available for its thread handle, at which point It atomically +//! the token is available for its thread handle, at which point it atomically //! consumes the token. It may also return *spuriously*, without consuming the //! token. `thread::park_timeout()` does the same, but allows specifying a //! maximum time to block the thread for. @@ -143,10 +137,44 @@ //! * It avoids the need to allocate mutexes and condvars when building new //! synchronization primitives; the threads already provide basic blocking/signaling. //! -//! * It can be implemented highly efficiently on many platforms. +//! * It can be implemented very efficiently on many platforms. +//! +//! ## Thread-local storage +//! +//! This module also provides an implementation of thread local storage for Rust +//! programs. Thread local storage is a method of storing data into a global +//! variable which each thread in the program will have its own copy of. +//! Threads do not share this data, so accesses do not need to be synchronized. +//! +//! At a high level, this module provides two variants of storage: +//! +//! * Owned thread-local storage. This is a type of thread local key which +//! owns the value that it contains, and will destroy the value when the +//! thread exits. This variant is created with the `thread_local!` macro and +//! can contain any value which is `'static` (no borrowed pointers). +//! +//! * Scoped thread-local storage. This type of key is used to store a reference +//! to a value into local storage temporarily for the scope of a function +//! call. There are no restrictions on what types of values can be placed +//! into this key. +//! +//! Both forms of thread local storage provide an accessor function, `with`, +//! which will yield a shared reference to the value to the specified +//! closure. Thread-local keys only allow shared access to values as there is no +//! way to guarantee uniqueness if a mutable borrow was allowed. Most values +//! will want to make use of some form of **interior mutability** through the +//! `Cell` or `RefCell` types. #![stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::__local::{LocalKey, LocalKeyState}; + +#[unstable(feature = "scoped_tls", + reason = "scoped TLS has yet to have wide enough use to fully consider \ + stabilizing its interface")] +pub use self::__scoped::ScopedKey; + use prelude::v1::*; use any::Any; @@ -154,14 +182,28 @@ use cell::UnsafeCell; use fmt; use io; use marker::PhantomData; -use old_io::stdio; use rt::{self, unwind}; use sync::{Mutex, Condvar, Arc}; +use sys::thread as imp; +use sys_common::{stack, thread_info}; use thunk::Thunk; use time::Duration; -use sys::thread as imp; -use sys_common::{stack, thread_info}; +//////////////////////////////////////////////////////////////////////////////// +// Thread-local storage +//////////////////////////////////////////////////////////////////////////////// + +#[macro_use] +#[doc(hidden)] +#[path = "local.rs"] pub mod __local; + +#[macro_use] +#[doc(hidden)] +#[path = "scoped.rs"] pub mod __scoped; + +//////////////////////////////////////////////////////////////////////////////// +// Builder +//////////////////////////////////////////////////////////////////////////////// /// Thread configuration. Provides detailed control over the properties /// and behavior of new threads. @@ -170,11 +212,7 @@ pub struct Builder { // A name for the thread-to-be, for identification in panic messages name: Option, // The size of the stack for the spawned thread - stack_size: Option, - // Thread-local stdout - stdout: Option>, - // Thread-local stderr - stderr: Option>, + stack_size: Option, } impl Builder { @@ -185,8 +223,6 @@ impl Builder { Builder { name: None, stack_size: None, - stdout: None, - stderr: None, } } @@ -200,27 +236,11 @@ impl Builder { /// Set the size of the stack for the new thread. #[stable(feature = "rust1", since = "1.0.0")] - pub fn stack_size(mut self, size: uint) -> Builder { + pub fn stack_size(mut self, size: usize) -> Builder { self.stack_size = Some(size); self } - /// Redirect thread-local stdout. - #[unstable(feature = "std_misc", - reason = "Will likely go away after proc removal")] - pub fn stdout(mut self, stdout: Box) -> Builder { - self.stdout = Some(stdout); - self - } - - /// Redirect thread-local stderr. - #[unstable(feature = "std_misc", - reason = "Will likely go away after proc removal")] - pub fn stderr(mut self, stderr: Box) -> Builder { - self.stderr = Some(stderr); - self - } - /// Spawn a new thread, and return a join handle for it. /// /// The child thread may outlive the parent (unless the parent thread @@ -237,7 +257,7 @@ impl Builder { pub fn spawn(self, f: F) -> io::Result where F: FnOnce(), F: Send + 'static { - self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i)) + self.spawn_inner(Box::new(f)).map(|i| JoinHandle(i)) } /// Spawn a new child thread that must be joined within a given @@ -259,13 +279,13 @@ impl Builder { pub fn scoped<'a, T, F>(self, f: F) -> io::Result> where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a { - self.spawn_inner(Thunk::new(f)).map(|inner| { + self.spawn_inner(Box::new(f)).map(|inner| { JoinGuard { inner: inner, _marker: PhantomData } }) } fn spawn_inner(self, f: Thunk<(), T>) -> io::Result> { - let Builder { name, stack_size, stdout, stderr } = self; + let Builder { name, stack_size } = self; let stack_size = stack_size.unwrap_or(rt::min_stack()); @@ -283,33 +303,19 @@ impl Builder { // address at which our stack started). let main = move || { let something_around_the_top_of_the_stack = 1; - let addr = &something_around_the_top_of_the_stack as *const int; - let my_stack_top = addr as uint; + let addr = &something_around_the_top_of_the_stack as *const i32; + let my_stack_top = addr as usize; let my_stack_bottom = my_stack_top - stack_size + 1024; unsafe { - stack::record_os_managed_stack_bounds(my_stack_bottom, my_stack_top); - } - match their_thread.name() { - Some(name) => unsafe { imp::set_name(name.as_slice()); }, - None => {} + if let Some(name) = their_thread.name() { + imp::set_name(name); + } + stack::record_os_managed_stack_bounds(my_stack_bottom, + my_stack_top); + thread_info::set(imp::guard::current(), their_thread); } - thread_info::set( - (my_stack_bottom, my_stack_top), - unsafe { imp::guard::current() }, - their_thread - ); - - let mut output = None; - let f: Thunk<(), T> = if stdout.is_some() || stderr.is_some() { - Thunk::new(move || { - let _ = stdout.map(stdio::set_stdout); - let _ = stderr.map(stdio::set_stderr); - f.invoke(()) - }) - } else { - f - }; + let mut output: Option = None; let try_result = { let ptr = &mut output; @@ -321,7 +327,11 @@ impl Builder { // 'unwinding' flag in the thread itself. For these reasons, // this unsafety should be ok. unsafe { - unwind::try(move || *ptr = Some(f.invoke(()))) + unwind::try(move || { + let f: Thunk<(), T> = f; + let v: T = f(); + *ptr = Some(v) + }) } }; unsafe { @@ -334,7 +344,7 @@ impl Builder { }; Ok(JoinInner { - native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }), + native: try!(unsafe { imp::create(stack_size, Box::new(main)) }), thread: my_thread, packet: my_packet, joined: false, @@ -342,12 +352,19 @@ impl Builder { } } -/// Spawn a new, returning a join handle for it. +//////////////////////////////////////////////////////////////////////////////// +// Free functions +//////////////////////////////////////////////////////////////////////////////// + +/// Spawn a new thread, returning a `JoinHandle` for it. /// -/// The child thread may outlive the parent (unless the parent thread -/// is the main thread; the whole process is terminated when the main -/// thread finishes.) The join handle can be used to block on -/// termination of the child thread, including recovering its panics. +/// The join handle will implicitly *detach* the child thread upon being +/// dropped. In this case, the child thread may outlive the parent (unless +/// the parent thread is the main thread; the whole process is terminated when +/// the main thread finishes.) Additionally, the join handle provides a `join` +/// method that can be used to join the child thread. If the child thread +/// panics, `join` will return an `Err` containing the argument given to +/// `panic`. /// /// # Panics /// @@ -397,6 +414,75 @@ pub fn panicking() -> bool { unwind::panicking() } +/// Invoke a closure, capturing the cause of panic if one occurs. +/// +/// This function will return `Ok(())` if the closure does not panic, and will +/// return `Err(cause)` if the closure panics. The `cause` returned is the +/// object with which panic was originally invoked. +/// +/// It is currently undefined behavior to unwind from Rust code into foreign +/// code, so this function is particularly useful when Rust is called from +/// another language (normally C). This can run arbitrary Rust code, capturing a +/// panic and allowing a graceful handling of the error. +/// +/// It is **not** recommended to use this function for a general try/catch +/// mechanism. The `Result` type is more appropriate to use for functions that +/// can fail on a regular basis. +/// +/// The closure provided is required to adhere to the `'static` bound to ensure +/// that it cannot reference data in the parent stack frame, mitigating problems +/// with exception safety. Furthermore, a `Send` bound is also required, +/// providing the same safety guarantees as `thread::spawn` (ensuring the +/// closure is properly isolated from the parent). +/// +/// # Examples +/// +/// ``` +/// # #![feature(catch_panic)] +/// use std::thread; +/// +/// let result = thread::catch_panic(|| { +/// println!("hello!"); +/// }); +/// assert!(result.is_ok()); +/// +/// let result = thread::catch_panic(|| { +/// panic!("oh no!"); +/// }); +/// assert!(result.is_err()); +/// ``` +#[unstable(feature = "catch_panic", reason = "recent API addition")] +pub fn catch_panic(f: F) -> Result + where F: FnOnce() -> R + Send + 'static +{ + let mut result = None; + unsafe { + let result = &mut result; + try!(::rt::unwind::try(move || *result = Some(f()))) + } + Ok(result.unwrap()) +} + +/// Put the current thread to sleep for the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. Note that on unix platforms +/// this function will not return early due to a signal being received or a +/// spurious wakeup. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn sleep_ms(ms: u32) { + imp::sleep(Duration::milliseconds(ms as i64)) +} + +/// Deprecated: use `sleep_ms` instead. +#[unstable(feature = "thread_sleep", + reason = "recently added, needs an RFC, and `Duration` itself is \ + unstable")] +#[deprecated(since = "1.0.0", reason = "use sleep_ms instead")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + /// Block unless or until the current thread's token is made available (may wake spuriously). /// /// See the module doc for more detail. @@ -420,23 +506,34 @@ pub fn park() { /// the specified duration has been reached (may wake spuriously). /// /// The semantics of this function are equivalent to `park()` except that the -/// thread will be blocked for roughly no longer than dur. This method +/// thread will be blocked for roughly no longer than *duration*. This method /// should not be used for precise timing due to anomalies such as /// preemption or platform differences that may not cause the maximum -/// amount of time waited to be precisely dur +/// amount of time waited to be precisely *duration* long. /// /// See the module doc for more detail. -#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")] -pub fn park_timeout(dur: Duration) { +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park_timeout_ms(ms: u32) { let thread = current(); let mut guard = thread.inner.lock.lock().unwrap(); if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap(); + let (g, _) = thread.inner.cvar.wait_timeout_ms(guard, ms).unwrap(); guard = g; } *guard = false; } +/// Deprecated: use `park_timeout_ms` +#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")] +#[deprecated(since = "1.0.0", reason = "use park_timeout_ms instead")] +pub fn park_timeout(duration: Duration) { + park_timeout_ms(duration.num_milliseconds() as u32) +} + +//////////////////////////////////////////////////////////////////////////////// +// Thread +//////////////////////////////////////////////////////////////////////////////// + /// The internal representation of a `Thread` handle struct Inner { name: Option, @@ -465,71 +562,6 @@ impl Thread { } } - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn spawn(f: F) -> Thread where F: FnOnce(), F: Send + 'static { - Builder::new().spawn(f).unwrap().thread().clone() - } - - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where - T: Send + 'a, F: FnOnce() -> T, F: Send + 'a - { - Builder::new().scoped(f).unwrap() - } - - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn current() -> Thread { - thread_info::current_thread() - } - - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[unstable(feature = "std_misc", reason = "name may change")] - pub fn yield_now() { - unsafe { imp::yield_now() } - } - - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn panicking() -> bool { - unwind::panicking() - } - - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park() { - let thread = current(); - let mut guard = thread.inner.lock.lock().unwrap(); - while !*guard { - guard = thread.inner.cvar.wait(guard).unwrap(); - } - *guard = false; - } - - /// Deprecated: use module-level free fucntion. - #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] - #[unstable(feature = "std_misc", reason = "recently introduced")] - pub fn park_timeout(dur: Duration) { - let thread = current(); - let mut guard = thread.inner.lock.lock().unwrap(); - if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap(); - guard = g; - } - *guard = false; - } - /// Atomically makes the handle's token available if it is not already. /// /// See the module doc for more detail. @@ -561,6 +593,10 @@ impl thread_info::NewThread for Thread { fn new(name: Option) -> Thread { Thread::new(name) } } +//////////////////////////////////////////////////////////////////////////////// +// JoinHandle and JoinGuard +//////////////////////////////////////////////////////////////////////////////// + /// Indicates the manner in which a thread exited. /// /// A thread that completes without panicking is considered to exit successfully. @@ -638,9 +674,9 @@ impl Drop for JoinHandle { /// Due to platform restrictions, it is not possible to `Clone` this /// handle: the ability to join a child thread is a uniquely-owned /// permission. -#[must_use] +#[must_use = "thread will be immediately joined if `JoinGuard` is not used"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct JoinGuard<'a, T: 'a> { +pub struct JoinGuard<'a, T: Send + 'a> { inner: JoinInner, _marker: PhantomData<&'a T>, } @@ -655,8 +691,8 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { &self.inner.thread } - /// Wait for the associated thread to finish, returning the result of the thread's - /// calculation. + /// Wait for the associated thread to finish, returning the result of the + /// thread's calculation. /// /// # Panics /// @@ -670,17 +706,6 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl JoinGuard<'static, T> { - /// Detaches the child thread, allowing it to outlive its parent. - #[deprecated(since = "1.0.0", reason = "use spawn instead")] - #[unstable(feature = "std_misc")] - pub fn detach(mut self) { - unsafe { imp::detach(self.inner.native) }; - self.inner.joined = true; // avoid joining in the destructor - } -} - #[unsafe_destructor] #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { @@ -693,19 +718,23 @@ impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { } } +//////////////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////////////// + #[cfg(test)] mod test { use prelude::v1::*; use any::Any; use sync::mpsc::{channel, Sender}; - use boxed::BoxAny; use result; use std::old_io::{ChanReader, ChanWriter}; - use super::{Thread, Builder}; + use super::{Builder}; use thread; use thunk::Thunk; use time::Duration; + use u32; // !!! These tests are dangerous. If something is buggy, they will hang, !!! // !!! instead of exiting cleanly. This might wedge the buildbots. !!! @@ -759,15 +788,15 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn test_scoped_panic() { thread::scoped(|| panic!()).join(); } #[test] - #[should_fail] + #[should_panic] fn test_scoped_implicit_panic() { - thread::scoped(|| panic!()); + let _ = thread::scoped(|| panic!()); } #[test] @@ -776,7 +805,7 @@ mod test { let (tx, rx) = channel(); - fn f(i: int, tx: Sender<()>) { + fn f(i: i32, tx: Sender<()>) { let tx = tx.clone(); thread::spawn(move|| { if i == 0 { @@ -805,13 +834,13 @@ mod test { } fn avoid_copying_the_body(spawnfn: F) where F: FnOnce(Thunk<'static>) { - let (tx, rx) = channel::(); + let (tx, rx) = channel(); - let x = box 1; - let x_in_parent = (&*x) as *const int as uint; + let x: Box<_> = box 1; + let x_in_parent = (&*x) as *const i32 as usize; - spawnfn(Thunk::new(move|| { - let x_in_child = (&*x) as *const int as uint; + spawnfn(Box::new(move|| { + let x_in_child = (&*x) as *const i32 as usize; tx.send(x_in_child).unwrap(); })); @@ -822,7 +851,7 @@ mod test { #[test] fn test_avoid_copying_the_body_spawn() { avoid_copying_the_body(|v| { - thread::spawn(move || v.invoke(())); + thread::spawn(move || v()); }); } @@ -830,7 +859,7 @@ mod test { fn test_avoid_copying_the_body_thread_spawn() { avoid_copying_the_body(|f| { thread::spawn(move|| { - f.invoke(()); + f(); }); }) } @@ -839,7 +868,7 @@ mod test { fn test_avoid_copying_the_body_join() { avoid_copying_the_body(|f| { let _ = thread::spawn(move|| { - f.invoke(()) + f() }).join(); }) } @@ -850,15 +879,15 @@ mod test { // climbing the task tree to dereference each ancestor. (See #1789) // (well, it would if the constant were 8000+ - I lowered it to be more // valgrind-friendly. try this at home, instead..!) - static GENERATIONS: uint = 16; - fn child_no(x: uint) -> Thunk<'static> { - return Thunk::new(move|| { + const GENERATIONS: u32 = 16; + fn child_no(x: u32) -> Thunk<'static> { + return Box::new(move|| { if x < GENERATIONS { - thread::spawn(move|| child_no(x+1).invoke(())); + thread::spawn(move|| child_no(x+1)()); } }); } - thread::spawn(|| child_no(0).invoke(())); + thread::spawn(|| child_no(0)()); } #[test] @@ -874,7 +903,7 @@ mod test { Err(e) => { type T = &'static str; assert!(e.is::()); - assert_eq!(*e.downcast::().ok().unwrap(), "static string"); + assert_eq!(*e.downcast::().unwrap(), "static string"); } Ok(()) => panic!() } @@ -888,7 +917,7 @@ mod test { Err(e) => { type T = String; assert!(e.is::()); - assert_eq!(*e.downcast::().ok().unwrap(), "owned string".to_string()); + assert_eq!(*e.downcast::().unwrap(), "owned string".to_string()); } Ok(()) => panic!() } @@ -902,9 +931,9 @@ mod test { Err(e) => { type T = Box; assert!(e.is::()); - let any = e.downcast::().ok().unwrap(); + let any = e.downcast::().unwrap(); assert!(any.is::()); - assert_eq!(*any.downcast::().ok().unwrap(), 413u16); + assert_eq!(*any.downcast::().unwrap(), 413); } Ok(()) => panic!() } @@ -922,32 +951,18 @@ mod test { } } - #[test] - fn test_stdout() { - let (tx, rx) = channel(); - let mut reader = ChanReader::new(rx); - let stdout = ChanWriter::new(tx); - - Builder::new().stdout(box stdout as Box).scoped(move|| { - print!("Hello, world!"); - }).unwrap().join(); - - let output = reader.read_to_string().unwrap(); - assert_eq!(output, "Hello, world!".to_string()); - } - #[test] fn test_park_timeout_unpark_before() { for _ in 0..10 { thread::current().unpark(); - thread::park_timeout(Duration::seconds(10_000_000)); + thread::park_timeout_ms(u32::MAX); } } #[test] fn test_park_timeout_unpark_not_called() { for _ in 0..10 { - thread::park_timeout(Duration::milliseconds(10)); + thread::park_timeout_ms(10); } } @@ -963,10 +978,15 @@ mod test { th.unpark(); }); - thread::park_timeout(Duration::seconds(10_000_000)); + thread::park_timeout_ms(u32::MAX); } } + #[test] + fn sleep_ms_smoke() { + thread::sleep_ms(2); + } + // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due // to the test harness apparently interfering with stderr configuration. } diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread/scoped.rs similarity index 84% rename from src/libstd/thread_local/scoped.rs rename to src/libstd/thread/scoped.rs index 01220e7bc1..b384879d7a 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread/scoped.rs @@ -21,10 +21,11 @@ //! period of time and it is not required to relinquish ownership of the //! contents. //! -//! # Example +//! # Examples //! //! ``` -//! scoped_thread_local!(static FOO: uint); +//! # #![feature(scoped_tls)] +//! scoped_thread_local!(static FOO: u32); //! //! // Initially each scoped slot is empty. //! assert!(!FOO.is_set()); @@ -38,9 +39,7 @@ //! }); //! ``` -#![unstable(feature = "std_misc", - reason = "scoped TLS has yet to have wide enough use to fully consider \ - stabilizing its interface")] +#![unstable(feature = "thread_local_internals")] use prelude::v1::*; @@ -58,13 +57,17 @@ pub mod __impl { /// type `T` scoped to a particular lifetime. Keys provides two methods, `set` /// and `with`, both of which currently use closures to control the scope of /// their contents. -pub struct Key { #[doc(hidden)] pub inner: __impl::KeyInner } +#[unstable(feature = "scoped_tls", + reason = "scoped TLS has yet to have wide enough use to fully consider \ + stabilizing its interface")] +pub struct ScopedKey { #[doc(hidden)] pub inner: __impl::KeyInner } /// Declare a new scoped thread local storage key. /// /// This macro declares a `static` item on which methods are used to get and /// set the value stored within. #[macro_export] +#[allow_internal_unstable] macro_rules! scoped_thread_local { (static $name:ident: $t:ty) => ( __scoped_thread_local_inner!(static $name: $t); @@ -76,6 +79,7 @@ macro_rules! scoped_thread_local { #[macro_export] #[doc(hidden)] +#[allow_internal_unstable] macro_rules! __scoped_thread_local_inner { (static $name:ident: $t:ty) => ( #[cfg_attr(not(any(windows, @@ -84,7 +88,7 @@ macro_rules! __scoped_thread_local_inner { target_os = "openbsd", target_arch = "aarch64")), thread_local)] - static $name: ::std::thread_local::scoped::Key<$t> = + static $name: ::std::thread::ScopedKey<$t> = __scoped_thread_local_inner!($t); ); (pub static $name:ident: $t:ty) => ( @@ -94,11 +98,11 @@ macro_rules! __scoped_thread_local_inner { target_os = "openbsd", target_arch = "aarch64")), thread_local)] - pub static $name: ::std::thread_local::scoped::Key<$t> = + pub static $name: ::std::thread::ScopedKey<$t> = __scoped_thread_local_inner!($t); ); ($t:ty) => ({ - use std::thread_local::scoped::Key as __Key; + use std::thread::ScopedKey as __Key; #[cfg(not(any(windows, target_os = "android", @@ -106,7 +110,7 @@ macro_rules! __scoped_thread_local_inner { target_os = "openbsd", target_arch = "aarch64")))] const _INIT: __Key<$t> = __Key { - inner: ::std::thread_local::scoped::__impl::KeyInner { + inner: ::std::thread::__scoped::__impl::KeyInner { inner: ::std::cell::UnsafeCell { value: 0 as *mut _ }, } }; @@ -117,9 +121,9 @@ macro_rules! __scoped_thread_local_inner { target_os = "openbsd", target_arch = "aarch64"))] const _INIT: __Key<$t> = __Key { - inner: ::std::thread_local::scoped::__impl::KeyInner { - inner: ::std::thread_local::scoped::__impl::OS_INIT, - marker: ::std::marker::InvariantType, + inner: ::std::thread::__scoped::__impl::KeyInner { + inner: ::std::thread::__scoped::__impl::OS_INIT, + marker: ::std::marker::PhantomData::<::std::cell::Cell<$t>>, } }; @@ -127,7 +131,10 @@ macro_rules! __scoped_thread_local_inner { }) } -impl Key { +#[unstable(feature = "scoped_tls", + reason = "scoped TLS has yet to have wide enough use to fully consider \ + stabilizing its interface")] +impl ScopedKey { /// Insert a value into this scoped thread local storage slot for a /// duration of a closure. /// @@ -137,10 +144,11 @@ impl Key { /// Upon return, this function will restore the previous value, if any /// was available. /// - /// # Example + /// # Examples /// /// ``` - /// scoped_thread_local!(static FOO: uint); + /// # #![feature(scoped_tls)] + /// scoped_thread_local!(static FOO: u32); /// /// FOO.set(&100, || { /// let val = FOO.with(|v| *v); @@ -189,10 +197,11 @@ impl Key { /// /// This function will panic if `set` has not previously been called. /// - /// # Example + /// # Examples /// /// ```no_run - /// scoped_thread_local!(static FOO: uint); + /// # #![feature(scoped_tls)] + /// scoped_thread_local!(static FOO: u32); /// /// FOO.with(|slot| { /// // work with `slot` @@ -244,12 +253,13 @@ mod imp { target_arch = "aarch64"))] mod imp { use marker; + use std::cell::Cell; use sys_common::thread_local::StaticKey as OsStaticKey; #[doc(hidden)] pub struct KeyInner { pub inner: OsStaticKey, - pub marker: marker::InvariantType, + pub marker: marker::PhantomData>, } unsafe impl ::marker::Sync for KeyInner { } @@ -269,11 +279,11 @@ mod tests { use cell::Cell; use prelude::v1::*; - scoped_thread_local!(static FOO: uint); + scoped_thread_local!(static FOO: u32); #[test] fn smoke() { - scoped_thread_local!(static BAR: uint); + scoped_thread_local!(static BAR: u32); assert!(!BAR.is_set()); BAR.set(&1, || { @@ -287,7 +297,7 @@ mod tests { #[test] fn cell_allowed() { - scoped_thread_local!(static BAR: Cell); + scoped_thread_local!(static BAR: Cell); BAR.set(&Cell::new(1), || { BAR.with(|slot| { diff --git a/src/libstd/thunk.rs b/src/libstd/thunk.rs index fe39954f0d..6091794ed4 100644 --- a/src/libstd/thunk.rs +++ b/src/libstd/thunk.rs @@ -12,48 +12,9 @@ #![allow(missing_docs)] #![unstable(feature = "std_misc")] -use alloc::boxed::Box; +use alloc::boxed::{Box, FnBox}; use core::marker::Send; -use core::ops::FnOnce; -pub struct Thunk<'a, A=(),R=()> { - #[cfg(stage0)] - invoke: Box+Send>, - #[cfg(not(stage0))] - invoke: Box+Send + 'a>, -} +pub type Thunk<'a, A=(), R=()> = + Box + Send + 'a>; -impl<'a, R> Thunk<'a,(),R> { - pub fn new(func: F) -> Thunk<'a,(),R> - where F : FnOnce() -> R, F : Send + 'a - { - Thunk::with_arg(move|()| func()) - } -} - -impl<'a,A,R> Thunk<'a,A,R> { - pub fn with_arg(func: F) -> Thunk<'a,A,R> - where F : FnOnce(A) -> R, F : Send + 'a - { - Thunk { - invoke: box func - } - } - - pub fn invoke(self, arg: A) -> R { - self.invoke.invoke(arg) - } -} - -pub trait Invoke { - fn invoke(self: Box, arg: A) -> R; -} - -impl Invoke for F - where F : FnOnce(A) -> R -{ - fn invoke(self: Box, arg: A) -> R { - let f = *self; - f(arg) - } -} diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 42ef3459a0..9b79b483b2 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -16,6 +16,7 @@ use {fmt, i64}; use ops::{Add, Sub, Mul, Div, Neg, FnOnce}; use option::Option; use option::Option::{Some, None}; +#[allow(deprecated)] // Int use num::Int; use result::Result::Ok; @@ -68,7 +69,7 @@ pub const MAX: Duration = Duration { impl Duration { /// Makes a new `Duration` with given number of weeks. - /// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60), with overflow checks. + /// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60)` with overflow checks. /// Panics when the duration is out of bounds. #[inline] #[unstable(feature = "std_misc")] diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 988b13cd16..41b70889c9 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -53,7 +53,7 @@ //! assert!(b == c); //! //! let d : (u32, f32) = Default::default(); -//! assert_eq!(d, (0u32, 0.0f32)); +//! assert_eq!(d, (0, 0.0f32)); //! ``` #![doc(primitive = "tuple")] diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index de3fa1135b..27e331893e 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -15,7 +15,7 @@ pub use self::AbiArchitecture::*; use std::fmt; -#[derive(Copy, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Os { OsWindows, OsMacos, @@ -24,6 +24,7 @@ pub enum Os { OsFreebsd, OsiOS, OsDragonfly, + OsBitrig, OsOpenbsd, } @@ -48,7 +49,7 @@ pub enum Abi { } #[allow(non_camel_case_types)] -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Architecture { X86, X86_64, @@ -57,7 +58,7 @@ pub enum Architecture { Mipsel } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct AbiData { abi: Abi, @@ -65,7 +66,7 @@ pub struct AbiData { name: &'static str, } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum AbiArchitecture { /// Not a real ABI (e.g., intrinsic) RustArch, @@ -76,11 +77,11 @@ pub enum AbiArchitecture { } #[allow(non_upper_case_globals)] -static AbiDatas: &'static [AbiData] = &[ +const AbiDatas: &'static [AbiData] = &[ // Platform-specific ABIs AbiData {abi: Cdecl, name: "cdecl" }, AbiData {abi: Stdcall, name: "stdcall" }, - AbiData {abi: Fastcall, name:"fastcall" }, + AbiData {abi: Fastcall, name: "fastcall" }, AbiData {abi: Aapcs, name: "aapcs" }, AbiData {abi: Win64, name: "win64" }, @@ -136,6 +137,7 @@ impl fmt::Display for Os { OsAndroid => "android".fmt(f), OsFreebsd => "freebsd".fmt(f), OsDragonfly => "dragonfly".fmt(f), + OsBitrig => "bitrig".fmt(f), OsOpenbsd => "openbsd".fmt(f), } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 140e21b5d0..40390765dd 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -22,7 +22,7 @@ pub use self::Expr_::*; pub use self::FloatTy::*; pub use self::FunctionRetTy::*; pub use self::ForeignItem_::*; -pub use self::ImplItem::*; +pub use self::ImplItem_::*; pub use self::InlinedItem::*; pub use self::IntTy::*; pub use self::Item_::*; @@ -33,7 +33,6 @@ pub use self::LocalSource::*; pub use self::Mac_::*; pub use self::MacStmtStyle::*; pub use self::MetaItem_::*; -pub use self::Method_::*; pub use self::Mutability::*; pub use self::Pat_::*; pub use self::PathListItem_::*; @@ -44,7 +43,7 @@ pub use self::Stmt_::*; pub use self::StrStyle::*; pub use self::StructFieldKind::*; pub use self::TokenTree::*; -pub use self::TraitItem::*; +pub use self::TraitItem_::*; pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UintTy::*; @@ -58,12 +57,16 @@ pub use self::PathParameters::*; use codemap::{Span, Spanned, DUMMY_SP, ExpnId}; use abi::Abi; use ast_util; +use ext::base; +use ext::tt::macro_parser; use owned_slice::OwnedSlice; use parse::token::{InternedString, str_to_ident}; use parse::token; +use parse::lexer; use ptr::P; use std::fmt; +#[allow(deprecated)] use std::num::Int; use std::rc::Rc; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -148,7 +151,7 @@ impl PartialEq for Ident { /// A SyntaxContext represents a chain of macro-expandings /// and renamings. Each macro expansion corresponds to -/// a fresh usize +/// a fresh u32 // I'm representing this syntax context as an index into // a table, in order to work around a compiler bug @@ -213,6 +216,7 @@ pub struct Lifetime { pub name: Name } +/// A lifetime definition, eg `'a: 'b+'c+'d` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct LifetimeDef { pub lifetime: Lifetime, @@ -249,7 +253,9 @@ pub struct PathSegment { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PathParameters { + /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` AngleBracketedParameters(AngleBracketedParameterData), + /// The `(A,B)` and `C` in `Foo(A,B) -> C` ParenthesizedParameters(ParenthesizedParameterData), } @@ -382,7 +388,7 @@ pub const CRATE_NODE_ID: NodeId = 0; /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have /// small, positive ids. -pub const DUMMY_NODE_ID: NodeId = -1; +pub const DUMMY_NODE_ID: NodeId = !0; /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against @@ -434,27 +440,37 @@ impl Generics { } } +/// A `where` clause in a definition #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereClause { pub id: NodeId, pub predicates: Vec, } +/// A single predicate in a `where` clause #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum WherePredicate { + /// A type binding, eg `for<'c> Foo: Send+Clone+'c` BoundPredicate(WhereBoundPredicate), + /// A lifetime predicate, e.g. `'a: 'b+'c` RegionPredicate(WhereRegionPredicate), + /// An equality predicate (unsupported) EqPredicate(WhereEqPredicate) } +/// A type bound, eg `for<'c> Foo: Send+Clone+'c` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereBoundPredicate { pub span: Span, + /// Any lifetimes from a `for` binding pub bound_lifetimes: Vec, + /// The type being bounded pub bounded_ty: P, + /// Trait and lifetime bounds (`Clone+Send+'static`) pub bounds: OwnedSlice, } +/// A lifetime predicate, e.g. `'a: 'b+'c` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereRegionPredicate { pub span: Span, @@ -462,6 +478,7 @@ pub struct WhereRegionPredicate { pub bounds: Vec, } +/// An equality predicate (unsupported), e.g. `T=int` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereEqPredicate { pub id: NodeId, @@ -519,9 +536,13 @@ impl PartialEq for MetaItem_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Block { + /// Statements in a block pub stmts: Vec>, + /// An expression at the end of the block + /// without a semicolon, if any pub expr: Option>, pub id: NodeId, + /// Distinguishes between `unsafe { ... }` and `{ ... }` pub rules: BlockCheckMode, pub span: Span, } @@ -533,9 +554,16 @@ pub struct Pat { pub span: Span, } +/// A single field in a struct pattern +/// +/// Patterns like the fields of Foo `{ x, ref y, ref mut z }` +/// are treated the same as` x: x, y: ref y, z: ref mut z`, +/// except is_shorthand is true #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FieldPat { + /// The identifier for the field pub ident: Ident, + /// The pattern the field is destructured to pub pat: P, pub is_shorthand: bool, } @@ -563,6 +591,7 @@ pub enum Pat_ { /// A PatIdent may either be a new bound variable, /// or a nullary enum (in which case the third field /// is None). + /// /// In the nullary enum case, the parser can't determine /// which it is. The resolver determines this, and /// records this pattern's NodeId in an auxiliary @@ -572,15 +601,23 @@ pub enum Pat_ { /// "None" means a * pattern where we don't bind the fields to names. PatEnum(Path, Option>>), + /// Destructuring of a struct, e.g. `Foo {x, y, ..}` + /// The `bool` is `true` in the presence of a `..` PatStruct(Path, Vec>, bool), + /// A tuple pattern `(a, b)` PatTup(Vec>), + /// A `box` pattern PatBox(P), - PatRegion(P, Mutability), // reference pattern + /// A reference pattern, e.g. `&mut (a, b)` + PatRegion(P, Mutability), + /// A literal PatLit(P), + /// A range pattern, e.g. `1...2` PatRange(P, P), /// [a, b, ..i, y, z] is represented as: /// PatVec(box [a, b], Some(i), box [y, z]) PatVec(Vec>, Option>, Vec>), + /// A macro pattern; pre-expansion PatMac(Mac), } @@ -592,23 +629,41 @@ pub enum Mutability { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum BinOp_ { + /// The `+` operator (addition) BiAdd, + /// The `-` operator (subtraction) BiSub, + /// The `*` operator (multiplication) BiMul, + /// The `/` operator (division) BiDiv, + /// The `%` operator (modulus) BiRem, + /// The `&&` operator (logical and) BiAnd, + /// The `||` operator (logical or) BiOr, + /// The `^` operator (bitwise xor) BiBitXor, + /// The `&` operator (bitwise and) BiBitAnd, + /// The `|` operator (bitwise or) BiBitOr, + /// The `<<` operator (shift left) BiShl, + /// The `>>` operator (shift right) BiShr, + /// The `==` operator (equality) BiEq, + /// The `<` operator (less than) BiLt, + /// The `<=` operator (less than or equal to) BiLe, + /// The `!=` operator (not equal to) BiNe, + /// The `>=` operator (greater than or equal to) BiGe, + /// The `>` operator (greater than) BiGt, } @@ -616,12 +671,17 @@ pub type BinOp = Spanned; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum UnOp { + /// The `box` operator UnUniq, + /// The `*` operator for dereferencing UnDeref, + /// The `!` operator for logical inversion UnNot, + /// The `-` operator for negation UnNeg } +/// A statement pub type Stmt = Spanned; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -666,6 +726,7 @@ pub enum LocalSource { pub struct Local { pub pat: P, pub ty: Option>, + /// Initializer expression to set the value, if any pub init: Option>, pub id: NodeId, pub span: Span, @@ -712,6 +773,7 @@ pub enum UnsafeSource { UserProvided, } +/// An expression #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Expr { pub id: NodeId, @@ -723,71 +785,149 @@ pub struct Expr { pub enum Expr_ { /// First expr is the place; second expr is the value. ExprBox(Option>, P), + /// An array (`[a, b, c, d]`) ExprVec(Vec>), + /// A function call + /// + /// The first field resolves to the function itself, + /// and the second field is the list of arguments ExprCall(P, Vec>), + /// A method call (`x.foo::(a, b, c, d)`) + /// + /// The `SpannedIdent` is the identifier for the method name. + /// The vector of `Ty`s are the ascripted type parameters for the method + /// (within the angle brackets). + /// + /// The first element of the vector of `Expr`s is the expression that evaluates + /// to the object on which the method is being called on (the receiver), + /// and the remaining elements are the rest of the arguments. + /// + /// Thus, `x.foo::(a, b, c, d)` is represented as + /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. ExprMethodCall(SpannedIdent, Vec>, Vec>), + /// A tuple (`(a, b, c ,d)`) ExprTup(Vec>), + /// A binary operation (For example: `a + b`, `a * b`) ExprBinary(BinOp, P, P), + /// A unary operation (For example: `!x`, `*x`) ExprUnary(UnOp, P), + /// A literal (For example: `1u8`, `"foo"`) ExprLit(P), + /// A cast (`foo as f64`) ExprCast(P, P), + /// An `if` block, with an optional else block + /// + /// `if expr { block } else { expr }` ExprIf(P, P, Option>), + /// An `if let` expression with an optional else block + /// + /// `if let pat = expr { block } else { expr }` + /// + /// This is desugared to a `match` expression. ExprIfLet(P, P, P, Option>), // FIXME #6993: change to Option ... or not, if these are hygienic. + /// A while loop, with an optional label + /// + /// `'label: while expr { block }` ExprWhile(P, P, Option), // FIXME #6993: change to Option ... or not, if these are hygienic. + /// A while-let loop, with an optional label + /// + /// `'label: while let pat = expr { block }` + /// + /// This is desugared to a combination of `loop` and `match` expressions. ExprWhileLet(P, P, P, Option), // FIXME #6993: change to Option ... or not, if these are hygienic. + /// A for loop, with an optional label + /// + /// `'label: for pat in expr { block }` + /// + /// This is desugared to a combination of `loop` and `match` expressions. ExprForLoop(P, P, P, Option), - // Conditionless loop (can be exited with break, cont, or ret) + /// Conditionless loop (can be exited with break, continue, or return) + /// + /// `'label: loop { block }` // FIXME #6993: change to Option ... or not, if these are hygienic. ExprLoop(P, Option), + /// A `match` block, with a source that indicates whether or not it is + /// the result of a desugaring, and if so, which kind. ExprMatch(P, Vec, MatchSource), + /// A closure (for example, `move |a, b, c| {a + b + c}`) ExprClosure(CaptureClause, P, P), + /// A block (`{ ... }`) ExprBlock(P), + /// An assignment (`a = foo()`) ExprAssign(P, P), + /// An assignment with an operator + /// + /// For example, `a += 1`. ExprAssignOp(BinOp, P, P), + /// Access of a named struct field (`obj.foo`) ExprField(P, SpannedIdent), + /// Access of an unnamed field of a struct or tuple-struct + /// + /// For example, `foo.0`. ExprTupField(P, Spanned), + /// An indexing operation (`foo[2]`) ExprIndex(P, P), + /// A range (`1..2`, `1..`, or `..2`) ExprRange(Option>, Option>), - /// Variable reference, possibly containing `::` and/or - /// type parameters, e.g. foo::bar:: - ExprPath(Path), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - ExprQPath(P), + /// Variable reference, possibly containing `::` and/or type + /// parameters, e.g. foo::bar::. + /// + /// Optionally "qualified", + /// e.g. ` as SomeTrait>::SomeType`. + ExprPath(Option, Path), + /// A referencing operation (`&a` or `&mut a`) ExprAddrOf(Mutability, P), + /// A `break`, with an optional label to break ExprBreak(Option), + /// A `continue`, with an optional label ExprAgain(Option), + /// A `return`, with an optional value to be returned ExprRet(Option>), + /// Output of the `asm!()` macro ExprInlineAsm(InlineAsm), + /// A macro invocation; pre-expansion ExprMac(Mac), /// A struct literal expression. - ExprStruct(Path, Vec, Option> /* base */), + /// + /// For example, `Foo {x: 1, y: 2}`, or + /// `Foo {x: 1, .. base}`, where `base` is the `Option`. + ExprStruct(Path, Vec, Option>), /// A vector literal constructed from one repeated element. - ExprRepeat(P /* element */, P /* count */), + /// + /// For example, `[1u8; 5]`. The first expression is the element + /// to be repeated; the second is the number of times to repeat it. + ExprRepeat(P, P), /// No-op: used solely so we can pretty-print faithfully ExprParen(P) } -/// A "qualified path": +/// The explicit Self type in a "qualified path". The actual +/// path, including the trait and the associated item, is stored +/// separately. `position` represents the index of the associated +/// item qualified with this Self type. +/// +/// as a::b::Trait>::AssociatedItem +/// ^~~~~ ~~~~~~~~~~~~~~^ +/// ty position = 3 /// -/// as SomeTrait>::SomeAssociatedItem -/// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~ -/// self_type trait_name item_path +/// >::AssociatedItem +/// ^~~~~ ^ +/// ty position = 0 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct QPath { - pub self_type: P, - pub trait_ref: P, - pub item_path: PathSegment, +pub struct QSelf { + pub ty: P, + pub position: usize } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -873,7 +1013,6 @@ pub enum KleeneOp { /// The RHS of an MBE macro is the only place `SubstNt`s are substituted. /// Nothing special happens to misnamed or misplaced `SubstNt`s. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -#[doc="For macro invocations; parsing is delegated to the macro"] pub enum TokenTree { /// A single token TtToken(Span, token::Token), @@ -955,6 +1094,18 @@ impl TokenTree { TtSequence(span, _) => span, } } + + /// Use this token tree as a matcher to parse given tts. + pub fn parse(cx: &base::ExtCtxt, mtch: &[TokenTree], tts: &[TokenTree]) + -> macro_parser::NamedParseResult { + // `None` is because we're not interpolating + let arg_rdr = lexer::new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic, + None, + None, + tts.iter().cloned().collect(), + true); + macro_parser::parse(cx.parse_sess(), cx.cfg(), arg_rdr, mtch) + } } pub type Mac = Spanned; @@ -962,6 +1113,7 @@ pub type Mac = Spanned; /// Represents a macro invocation. The Path indicates which macro /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. +/// /// There's only one flavor, now, so this could presumably be simplified. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Mac_ { @@ -972,10 +1124,15 @@ pub enum Mac_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum StrStyle { + /// A regular string, like `"foo"` CookedStr, + /// A raw string, like `r##"foo"##` + /// + /// The uint is the number of `#` symbols used RawStr(usize) } +/// A literal pub type Lit = Spanned; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -985,6 +1142,7 @@ pub enum Sign { } impl Sign { + #[allow(deprecated)] // Int pub fn new(n: T) -> Sign { if n < Int::zero() { Minus @@ -1013,13 +1171,21 @@ impl LitIntType { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Lit_ { + /// A string literal (`"foo"`) LitStr(InternedString, StrStyle), + /// A byte string (`b"foo"`) LitBinary(Rc>), + /// A byte char (`b'f'`) LitByte(u8), + /// A character literal (`'a'`) LitChar(char), + /// An integer literal (`1u8`) LitInt(u64, LitIntType), + /// A float literal (`1f64` or `1E10f64`) LitFloat(InternedString, FloatTy), + /// A float literal without a suffix (`1.0 or 1.0E10`) LitFloatUnsuffixed(InternedString), + /// A boolean literal LitBool(bool), } @@ -1038,20 +1204,15 @@ pub struct TypeField { pub span: Span, } -/// Represents a required method in a trait declaration, -/// one without a default implementation +/// Represents a method's signature in a trait declaration, +/// or in an implementation. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TypeMethod { - pub ident: Ident, - pub attrs: Vec, +pub struct MethodSig { pub unsafety: Unsafety, pub abi: Abi, pub decl: P, pub generics: Generics, pub explicit_self: ExplicitSelf, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, } /// Represents a method declaration in a trait declaration, possibly including @@ -1059,57 +1220,46 @@ pub struct TypeMethod { /// doesn't have an implementation, just a signature) or provided (meaning it /// has a default implementation). #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitItem { - RequiredMethod(TypeMethod), - ProvidedMethod(P), - TypeTraitItem(P), -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum ImplItem { - MethodImplItem(P), - TypeImplItem(P), +pub struct TraitItem { + pub id: NodeId, + pub ident: Ident, + pub attrs: Vec, + pub node: TraitItem_, + pub span: Span, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct AssociatedType { - pub attrs: Vec, - pub ty_param: TyParam, +pub enum TraitItem_ { + MethodTraitItem(MethodSig, Option>), + TypeTraitItem(TyParamBounds, Option>), } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Typedef { +pub struct ImplItem { pub id: NodeId, - pub span: Span, pub ident: Ident, pub vis: Visibility, pub attrs: Vec, - pub typ: P, + pub node: ImplItem_, + pub span: Span, +} + +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum ImplItem_ { + MethodImplItem(MethodSig, P), + TypeImplItem(P), + MacImplItem(Mac), } -#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub enum IntTy { - TyIs(bool /* is this deprecated `int`? */), + TyIs, TyI8, TyI16, TyI32, TyI64, } -impl PartialEq for IntTy { - fn eq(&self, other: &IntTy) -> bool { - match (*self, *other) { - // true/false need to compare the same, so this can't be derived - (TyIs(_), TyIs(_)) | - (TyI8, TyI8) | - (TyI16, TyI16) | - (TyI32, TyI32) | - (TyI64, TyI64) => true, - _ => false - } - } -} - impl fmt::Debug for IntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) @@ -1125,41 +1275,25 @@ impl fmt::Display for IntTy { impl IntTy { pub fn suffix_len(&self) -> usize { match *self { - TyIs(true) /* i */ => 1, - TyIs(false) /* is */ | TyI8 => 2, + TyIs | TyI8 => 2, TyI16 | TyI32 | TyI64 => 3, } } } -#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub enum UintTy { - TyUs(bool /* is this deprecated uint? */), + TyUs, TyU8, TyU16, TyU32, TyU64, } -impl PartialEq for UintTy { - fn eq(&self, other: &UintTy) -> bool { - match (*self, *other) { - // true/false need to compare the same, so this can't be derived - (TyUs(_), TyUs(_)) | - (TyU8, TyU8) | - (TyU16, TyU16) | - (TyU32, TyU32) | - (TyU64, TyU64) => true, - _ => false - } - } -} - impl UintTy { pub fn suffix_len(&self) -> usize { match *self { - TyUs(true) /* u */ => 1, - TyUs(false) /* us */ | TyU8 => 2, + TyUs | TyU8 => 2, TyU16 | TyU32 | TyU64 => 3, } } @@ -1244,7 +1378,7 @@ pub struct BareFnTy { /// The different kinds of types recognized by the compiler pub enum Ty_ { TyVec(P), - /// A fixed length array (`[T, ..n]`) + /// A fixed length array (`[T; n]`) TyFixedLengthVec(P, P), /// A raw pointer (`*const T` or `*mut T`) TyPtr(MutTy), @@ -1254,16 +1388,15 @@ pub enum Ty_ { TyBareFn(P), /// A tuple (`(A, B, C, D,...)`) TyTup(Vec> ), - /// A path (`module::module::...::Type`) or primitive + /// A path (`module::module::...::Type`), optionally + /// "qualified", e.g. ` as SomeTrait>::SomeType`. /// /// Type parameters are stored in the Path itself - TyPath(Path, NodeId), + TyPath(Option, Path), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(P), /// No-op; kept solely so that we can pretty-print faithfully TyParen(P), /// Unused for now @@ -1320,7 +1453,7 @@ impl Arg { } } -/// represents the header (not the body) of a function declaration +/// Represents the header (not the body) of a function declaration #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FnDecl { pub inputs: Vec, @@ -1345,9 +1478,9 @@ impl fmt::Display for Unsafety { #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub enum ImplPolarity { - /// impl Trait for Type + /// `impl Trait for Type` Positive, - /// impl !Trait for Type + /// `impl !Trait for Type` Negative, } @@ -1363,10 +1496,12 @@ impl fmt::Debug for ImplPolarity { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum FunctionRetTy { - /// Functions with return type ! that always + /// Functions with return type `!`that always /// raise an error or exit (i.e. never return to the caller) NoReturn(Span), - /// Return type is not specified. Functions default to () and + /// Return type is not specified. + /// + /// Functions default to `()` and /// closures default to inference. Span points to where return /// type would be inserted. DefaultReturn(Span), @@ -1399,29 +1534,6 @@ pub enum ExplicitSelf_ { pub type ExplicitSelf = Spanned; -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Method { - pub attrs: Vec, - pub id: NodeId, - pub span: Span, - pub node: Method_, -} - -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum Method_ { - /// Represents a method declaration - MethDecl(Ident, - Generics, - Abi, - ExplicitSelf, - Unsafety, - P, - P, - Visibility), - /// Represents a macro in method position - MethMac(Mac), -} - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. @@ -1445,7 +1557,9 @@ pub struct VariantArg { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum VariantKind { + /// Tuple variant, e.g. `Foo(A, B)` TupleVariantKind(Vec), + /// Struct variant, e.g. `Foo {x: A, y: B}` StructVariantKind(P), } @@ -1460,6 +1574,7 @@ pub struct Variant_ { pub attrs: Vec, pub kind: VariantKind, pub id: NodeId, + /// Explicit discriminant, eg `Foo = 1` pub disr_expr: Option>, pub vis: Visibility, } @@ -1526,6 +1641,7 @@ pub struct Attribute_ { } /// TraitRef's appear in impls. +/// /// resolve maps each TraitRef's ref_id to its defining trait; that's all /// that the ref_id is for. The impl_id maps to the "self type" of this impl. /// If this impl is an ItemImpl, the impl_id is redundant (it could be the @@ -1610,6 +1726,9 @@ pub struct StructDef { FIXME (#3300): Should allow items to be anonymous. Right now we just use dummy names for anon items. */ +/// An item +/// +/// The name might be a dummy name in case of anonymous items #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Item { pub ident: Ident, @@ -1622,31 +1741,46 @@ pub struct Item { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Item_ { - // Optional location (containing arbitrary characters) from which - // to fetch the crate sources. - // For example, extern crate whatever = "github.com/rust-lang/rust". - ItemExternCrate(Option<(InternedString, StrStyle)>), + /// An`extern crate` item, with optional original crate name, + /// + /// e.g. `extern crate foo` or `extern crate foo_bar as foo` + ItemExternCrate(Option), + /// A `use` or `pub use` item ItemUse(P), + /// A `static` item ItemStatic(P, Mutability, P), + /// A `const` item ItemConst(P, P), + /// A function declaration ItemFn(P, Unsafety, Abi, Generics, P), + /// A module ItemMod(Mod), + /// An external module ItemForeignMod(ForeignMod), + /// A type alias, e.g. `type Foo = Bar` ItemTy(P, Generics), + /// An enum definition, e.g. `enum Foo {C, D}` ItemEnum(EnumDef, Generics), + /// A struct definition, e.g. `struct Foo {x: A}` ItemStruct(P, Generics), /// Represents a Trait Declaration ItemTrait(Unsafety, Generics, TyParamBounds, - Vec), + Vec>), + + // Default trait implementations + /// + // `impl Trait for .. {}` + ItemDefaultImpl(Unsafety, TraitRef), + /// An implementation, eg `impl Trait for Foo { .. }` ItemImpl(Unsafety, ImplPolarity, Generics, Option, // (optional) trait this impl implements P, // self - Vec), + Vec>), /// A macro invocation (which includes macro definition) ItemMac(Mac), } @@ -1666,7 +1800,8 @@ impl Item_ { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemMac(..) | - ItemImpl(..) => "item" + ItemImpl(..) | + ItemDefaultImpl(..) => "item" } } } @@ -1681,10 +1816,14 @@ pub struct ForeignItem { pub vis: Visibility, } +/// An item within an `extern` block #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum ForeignItem_ { + /// A foreign function ForeignItemFn(P, Generics), - ForeignItemStatic(P, /* is_mutbl */ bool), + /// A foreign static item (`static ext: u8`), with optional mutability + /// (the boolean is true when mutable) + ForeignItemStatic(P, bool), } impl ForeignItem_ { @@ -1702,8 +1841,8 @@ impl ForeignItem_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum InlinedItem { IIItem(P), - IITraitItem(DefId /* impl id */, TraitItem), - IIImplItem(DefId /* impl id */, ImplItem), + IITraitItem(DefId /* impl id */, P), + IIImplItem(DefId /* impl id */, P), IIForeign(P), } @@ -1719,6 +1858,7 @@ pub struct MacroDef { pub imported_from: Option, pub export: bool, pub use_locally: bool, + pub allow_internal_unstable: bool, pub body: Vec, } diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 1a537c7a5b..475970ac30 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -26,9 +26,8 @@ pub use self::Code::*; use abi; use ast::{Block, FnDecl, NodeId}; use ast; -use ast_map::{Node}; +use ast_map::Node; use ast_map; -use ast_util::PostExpansionMethod; use codemap::Span; use visit; @@ -41,7 +40,7 @@ use visit; /// - The default implementation for a trait method. /// /// To construct one, use the `Code::from_node` function. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct FnLikeNode<'a> { node: ast_map::Node<'a> } /// MaybeFnLike wraps a method that indicates if an object @@ -65,7 +64,7 @@ impl MaybeFnLike for ast::Item { impl MaybeFnLike for ast::TraitItem { fn is_fn_like(&self) -> bool { - match *self { ast::ProvidedMethod(_) => true, _ => false, } + match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, } } } @@ -81,7 +80,7 @@ impl MaybeFnLike for ast::Expr { /// Carries either an FnLikeNode or a Block, as these are the two /// constructs that correspond to "code" (as in, something from which /// we can construct a control-flow graph). -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Code<'a> { FnLikeCode(FnLikeNode<'a>), BlockCode(&'a Block), @@ -156,25 +155,25 @@ impl<'a> FnLikeNode<'a> { pub fn body(self) -> &'a Block { self.handle(|i: ItemFnParts<'a>| &*i.body, - |m: &'a ast::Method| m.pe_body(), + |_, _, _: &'a ast::MethodSig, body: &'a ast::Block, _| body, |c: ClosureParts<'a>| c.body) } pub fn decl(self) -> &'a FnDecl { self.handle(|i: ItemFnParts<'a>| &*i.decl, - |m: &'a ast::Method| m.pe_fn_decl(), + |_, _, sig: &'a ast::MethodSig, _, _| &sig.decl, |c: ClosureParts<'a>| c.decl) } pub fn span(self) -> Span { self.handle(|i: ItemFnParts| i.span, - |m: &'a ast::Method| m.span, + |_, _, _: &'a ast::MethodSig, _, span| span, |c: ClosureParts| c.span) } pub fn id(self) -> NodeId { self.handle(|i: ItemFnParts| i.id, - |m: &'a ast::Method| m.id, + |id, _, _: &'a ast::MethodSig, _, _| id, |c: ClosureParts| c.id) } @@ -185,15 +184,15 @@ impl<'a> FnLikeNode<'a> { let closure = |_: ClosureParts| { visit::FkFnBlock }; - let method = |m: &'a ast::Method| { - visit::FkMethod(m.pe_ident(), m.pe_generics(), m) + let method = |_, ident, sig: &'a ast::MethodSig, _, _| { + visit::FkMethod(ident, sig) }; self.handle(item, method, closure) } fn handle(self, item_fn: I, method: M, closure: C) -> A where I: FnOnce(ItemFnParts<'a>) -> A, - M: FnOnce(&'a ast::Method) -> A, + M: FnOnce(NodeId, ast::Ident, &'a ast::MethodSig, &'a ast::Block, Span) -> A, C: FnOnce(ClosureParts<'a>) -> A, { match self.node { @@ -205,14 +204,19 @@ impl<'a> FnLikeNode<'a> { }), _ => panic!("item FnLikeNode that is not fn-like"), }, - ast_map::NodeTraitItem(t) => match *t { - ast::ProvidedMethod(ref m) => method(&**m), + ast_map::NodeTraitItem(ti) => match ti.node { + ast::MethodTraitItem(ref sig, Some(ref body)) => { + method(ti.id, ti.ident, sig, body, ti.span) + } _ => panic!("trait method FnLikeNode that is not fn-like"), }, ast_map::NodeImplItem(ii) => { - match *ii { - ast::MethodImplItem(ref m) => method(&**m), - ast::TypeImplItem(_) => { + match ii.node { + ast::MethodImplItem(ref sig, ref body) => { + method(ii.id, ii.ident, sig, body, ii.span) + } + ast::TypeImplItem(_) | + ast::MacImplItem(_) => { panic!("impl method FnLikeNode that is not fn-like") } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index ba08f61b55..2a9a609ecd 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -19,13 +19,12 @@ use codemap::{DUMMY_SP, Span, Spanned}; use fold::Folder; use parse::token; use print::pprust; -use ptr::P; use visit::{self, Visitor}; use arena::TypedArena; use std::cell::RefCell; use std::fmt; -use std::old_io::IoResult; +use std::io; use std::iter::{self, repeat}; use std::mem; use std::slice; @@ -54,18 +53,29 @@ impl fmt::Display for PathElem { } #[derive(Clone)] -struct LinkedPathNode<'a> { +pub struct LinkedPathNode<'a> { node: PathElem, next: LinkedPath<'a>, } -type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>; +#[derive(Copy, Clone)] +pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>); + +impl<'a> LinkedPath<'a> { + pub fn empty() -> LinkedPath<'a> { + LinkedPath(None) + } + + pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> { + LinkedPath(Some(node)) + } +} impl<'a> Iterator for LinkedPath<'a> { type Item = PathElem; fn next(&mut self) -> Option { - match *self { + match self.0 { Some(node) => { *self = node.next; Some(node.node) @@ -91,7 +101,7 @@ pub fn path_to_string>(path: PI) -> String { }) } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] pub enum Node<'ast> { NodeItem(&'ast Item), NodeForeignItem(&'ast ForeignItem), @@ -375,35 +385,8 @@ impl<'ast> Map<'ast> { } } NodeForeignItem(i) => PathName(i.ident.name), - NodeImplItem(ii) => { - match *ii { - MethodImplItem(ref m) => { - match m.node { - MethDecl(ident, _, _, _, _, _, _, _) => { - PathName(ident.name) - } - MethMac(_) => { - panic!("no path elem for {:?}", node) - } - } - } - TypeImplItem(ref t) => PathName(t.ident.name), - } - }, - NodeTraitItem(tm) => match *tm { - RequiredMethod(ref m) => PathName(m.ident.name), - ProvidedMethod(ref m) => { - match m.node { - MethDecl(ident, _, _, _, _, _, _, _) => { - PathName(ident.name) - } - MethMac(_) => panic!("no path elem for {:?}", node), - } - } - TypeTraitItem(ref m) => { - PathName(m.ty_param.ident.name) - } - }, + NodeImplItem(ii) => PathName(ii.ident.name), + NodeTraitItem(ti) => PathName(ti.ident.name), NodeVariant(v) => PathName(v.node.name.name), _ => panic!("no path elem for {:?}", node) } @@ -412,7 +395,7 @@ impl<'ast> Map<'ast> { pub fn with_path(&self, id: NodeId, f: F) -> T where F: FnOnce(PathElems) -> T, { - self.with_path_next(id, None, f) + self.with_path_next(id, LinkedPath::empty(), f) } pub fn path_to_string(&self, id: NodeId) -> String { @@ -450,42 +433,30 @@ impl<'ast> Map<'ast> { _ => f([].iter().cloned().chain(next)) } } else { - self.with_path_next(parent, Some(&LinkedPathNode { + self.with_path_next(parent, LinkedPath::from(&LinkedPathNode { node: self.get_path_elem(id), next: next }), f) } } - /// Given a node ID and a closure, apply the closure to the array - /// of attributes associated with the AST corresponding to the Node ID - pub fn with_attrs(&self, id: NodeId, f: F) -> T where - F: FnOnce(Option<&[Attribute]>) -> T, - { - let attrs = match self.get(id) { - NodeItem(i) => Some(&i.attrs[..]), - NodeForeignItem(fi) => Some(&fi.attrs[..]), - NodeTraitItem(ref tm) => match **tm { - RequiredMethod(ref type_m) => Some(&type_m.attrs[..]), - ProvidedMethod(ref m) => Some(&m.attrs[..]), - TypeTraitItem(ref typ) => Some(&typ.attrs[..]), - }, - NodeImplItem(ref ii) => { - match **ii { - MethodImplItem(ref m) => Some(&m.attrs[..]), - TypeImplItem(ref t) => Some(&t.attrs[..]), - } - } - NodeVariant(ref v) => Some(&v.node.attrs[..]), + /// Given a node ID, get a list of of attributes associated with the AST + /// corresponding to the Node ID + pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] { + let attrs = match self.find(id) { + Some(NodeItem(i)) => Some(&i.attrs[..]), + Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]), + Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), + Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]), + Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]), // unit/tuple structs take the attributes straight from // the struct definition. - // FIXME(eddyb) make this work again (requires access to the map). - NodeStructCtor(_) => { - return self.with_attrs(self.get_parent(id), f); + Some(NodeStructCtor(_)) => { + return self.attrs(self.get_parent(id)); } _ => None }; - f(attrs) + attrs.unwrap_or(&[]) } /// Returns an iterator that yields the node id's with paths that @@ -509,19 +480,8 @@ impl<'ast> Map<'ast> { let sp = match self.find(id) { Some(NodeItem(item)) => item.span, Some(NodeForeignItem(foreign_item)) => foreign_item.span, - Some(NodeTraitItem(trait_method)) => { - match *trait_method { - RequiredMethod(ref type_method) => type_method.span, - ProvidedMethod(ref method) => method.span, - TypeTraitItem(ref typedef) => typedef.ty_param.span, - } - } - Some(NodeImplItem(ref impl_item)) => { - match **impl_item { - MethodImplItem(ref method) => method.span, - TypeImplItem(ref typedef) => typedef.span, - } - } + Some(NodeTraitItem(trait_method)) => trait_method.span, + Some(NodeImplItem(ref impl_item)) => impl_item.span, Some(NodeVariant(variant)) => variant.span, Some(NodeExpr(expr)) => expr.span, Some(NodeStmt(stmt)) => stmt.span, @@ -654,31 +614,8 @@ impl Named for Spanned { fn name(&self) -> Name { self.node.name() } impl Named for Item { fn name(&self) -> Name { self.ident.name } } impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } impl Named for Variant_ { fn name(&self) -> Name { self.name.name } } -impl Named for TraitItem { - fn name(&self) -> Name { - match *self { - RequiredMethod(ref tm) => tm.ident.name, - ProvidedMethod(ref m) => m.name(), - TypeTraitItem(ref at) => at.ty_param.ident.name, - } - } -} -impl Named for ImplItem { - fn name(&self) -> Name { - match *self { - MethodImplItem(ref m) => m.name(), - TypeImplItem(ref td) => td.ident.name, - } - } -} -impl Named for Method { - fn name(&self) -> Name { - match self.node { - MethDecl(i, _, _, _, _, _, _, _) => i.name, - MethMac(_) => panic!("encountered unexpanded method macro."), - } - } -} +impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } +impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } pub trait FoldOps { fn new_id(&self, id: NodeId) -> NodeId { @@ -743,15 +680,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.parent = i.id; match i.node { ItemImpl(_, _, _, _, _, ref impl_items) => { - for impl_item in impl_items { - match *impl_item { - MethodImplItem(ref m) => { - self.insert(m.id, NodeImplItem(impl_item)); - } - TypeImplItem(ref t) => { - self.insert(t.id, NodeImplItem(impl_item)); - } - } + for ii in impl_items { + self.insert(ii.id, NodeImplItem(ii)); } } ItemEnum(ref enum_definition, _) => { @@ -780,18 +710,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } } - for tm in trait_items { - match *tm { - RequiredMethod(ref m) => { - self.insert(m.id, NodeTraitItem(tm)); - } - ProvidedMethod(ref m) => { - self.insert(m.id, NodeTraitItem(tm)); - } - TypeTraitItem(ref typ) => { - self.insert(typ.ty_param.id, NodeTraitItem(tm)); - } - } + for ti in trait_items { + self.insert(ti.id, NodeTraitItem(ti)); } } _ => {} @@ -800,6 +720,20 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.parent = parent; } + fn visit_trait_item(&mut self, ti: &'ast TraitItem) { + let parent = self.parent; + self.parent = ti.id; + visit::walk_trait_item(self, ti); + self.parent = parent; + } + + fn visit_impl_item(&mut self, ii: &'ast ImplItem) { + let parent = self.parent; + self.parent = ii.id; + visit::walk_impl_item(self, ii); + self.parent = parent; + } + fn visit_pat(&mut self, pat: &'ast Pat) { self.insert(pat.id, match pat.node { // Note: this is at least *potentially* a pattern... @@ -819,29 +753,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { visit::walk_stmt(self, stmt); } - fn visit_ty_method(&mut self, m: &'ast TypeMethod) { - let parent = self.parent; - self.parent = m.id; - self.visit_fn_decl(&*m.decl); - visit::walk_ty_method(self, m); - self.parent = parent; - } - fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl, - b: &'ast Block, s: Span, id: NodeId) { - match fk { - visit::FkMethod(..) => { - let parent = self.parent; - self.parent = id; - self.visit_fn_decl(fd); - visit::walk_fn(self, fk, fd, b, s); - self.parent = parent; - } - _ => { - self.visit_fn_decl(fd); - visit::walk_fn(self, fk, fd, b, s); - } - } + b: &'ast Block, s: Span, _: NodeId) { + self.visit_fn_decl(fd); + visit::walk_fn(self, fk, fd, b, s); } fn visit_ty(&mut self, ty: &'ast Ty) { @@ -923,33 +838,14 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, let mut fld = IdAndSpanUpdater { fold_ops: fold_ops }; let ii = match ii { IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")), - IITraitItem(d, ti) => match ti { - ProvidedMethod(m) => { - IITraitItem(fld.fold_ops.new_def_id(d), - ProvidedMethod(fld.fold_method(m) - .expect_one("expected one method"))) - } - RequiredMethod(ty_m) => { - IITraitItem(fld.fold_ops.new_def_id(d), - RequiredMethod(fld.fold_type_method(ty_m))) - } - TypeTraitItem(at) => { - IITraitItem( - fld.fold_ops.new_def_id(d), - TypeTraitItem(P(fld.fold_associated_type((*at).clone())))) - } - }, - IIImplItem(d, m) => match m { - MethodImplItem(m) => { - IIImplItem(fld.fold_ops.new_def_id(d), - MethodImplItem(fld.fold_method(m) - .expect_one("expected one method"))) - } - TypeImplItem(t) => { - IIImplItem(fld.fold_ops.new_def_id(d), - TypeImplItem(P(fld.fold_typedef((*t).clone())))) - } - }, + IITraitItem(d, ti) => { + IITraitItem(fld.fold_ops.new_def_id(d), + fld.fold_trait_item(ti).expect_one("expected one trait item")) + } + IIImplItem(d, ii) => { + IIImplItem(fld.fold_ops.new_def_id(d), + fld.fold_impl_item(ii).expect_one("expected one impl item")) + } IIForeign(i) => IIForeign(fld.fold_foreign_item(i)) }; @@ -971,25 +867,14 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, // add it to the table now. Likewise with foreign items. match ii_parent.ii { IIItem(_) => {} - IITraitItem(_, ref trait_item) => { - let trait_item_id = match *trait_item { - ProvidedMethod(ref m) => m.id, - RequiredMethod(ref m) => m.id, - TypeTraitItem(ref ty) => ty.ty_param.id, - }; - - collector.insert(trait_item_id, NodeTraitItem(trait_item)); + IITraitItem(_, ref ti) => { + collector.insert(ti.id, NodeTraitItem(ti)); } - IIImplItem(_, ref impl_item) => { - let impl_item_id = match *impl_item { - MethodImplItem(ref m) => m.id, - TypeImplItem(ref ti) => ti.id, - }; - - collector.insert(impl_item_id, NodeImplItem(impl_item)); + IIImplItem(_, ref ii) => { + collector.insert(ii.id, NodeImplItem(ii)); } IIForeign(ref i) => { - collector.insert(i.id, NodeForeignItem(&**i)); + collector.insert(i.id, NodeForeignItem(i)); } } *map.map.borrow_mut() = collector.map; @@ -997,16 +882,16 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>, } pub trait NodePrinter { - fn print_node(&mut self, node: &Node) -> IoResult<()>; + fn print_node(&mut self, node: &Node) -> io::Result<()>; } impl<'a> NodePrinter for pprust::State<'a> { - fn print_node(&mut self, node: &Node) -> IoResult<()> { + fn print_node(&mut self, node: &Node) -> io::Result<()> { match *node { NodeItem(a) => self.print_item(&*a), NodeForeignItem(a) => self.print_foreign_item(&*a), - NodeTraitItem(a) => self.print_trait_method(&*a), - NodeImplItem(a) => self.print_impl_item(&*a), + NodeTraitItem(a) => self.print_trait_item(a), + NodeImplItem(a) => self.print_impl_item(a), NodeVariant(a) => self.print_variant(&*a), NodeExpr(a) => self.print_expr(&*a), NodeStmt(a) => self.print_stmt(&*a), @@ -1044,6 +929,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { ItemStruct(..) => "struct", ItemTrait(..) => "trait", ItemImpl(..) => "impl", + ItemDefaultImpl(..) => "default impl", ItemMac(..) => "macro" }; format!("{} {}{}", item_str, path_str, id_str) @@ -1052,44 +938,38 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { let path_str = map.path_to_str_with_ident(id, item.ident); format!("foreign item {}{}", path_str, id_str) } - Some(NodeImplItem(ref ii)) => { - match **ii { - MethodImplItem(ref m) => { - match m.node { - MethDecl(ident, _, _, _, _, _, _, _) => - format!("method {} in {}{}", - token::get_ident(ident), - map.path_to_string(id), id_str), - MethMac(ref mac) => - format!("method macro {}{}", - pprust::mac_to_string(mac), id_str) - } - } - TypeImplItem(ref t) => { - format!("typedef {} in {}{}", - token::get_ident(t.ident), - map.path_to_string(id), - id_str) - } - } - } - Some(NodeTraitItem(ref tm)) => { - match **tm { - RequiredMethod(_) | ProvidedMethod(_) => { - let m = ast_util::trait_item_to_ty_method(&**tm); + Some(NodeImplItem(ii)) => { + match ii.node { + MethodImplItem(..) => { format!("method {} in {}{}", - token::get_ident(m.ident), - map.path_to_string(id), - id_str) + token::get_ident(ii.ident), + map.path_to_string(id), id_str) } - TypeTraitItem(ref t) => { - format!("type item {} in {}{}", - token::get_ident(t.ty_param.ident), + TypeImplItem(_) => { + format!("assoc type {} in {}{}", + token::get_ident(ii.ident), map.path_to_string(id), id_str) } + MacImplItem(ref mac) => { + format!("method macro {}{}", + pprust::mac_to_string(mac), id_str) + } } } + Some(NodeTraitItem(ti)) => { + let kind = match ti.node { + MethodTraitItem(..) => "trait method", + TypeTraitItem(..) => "assoc type", +// ConstTraitItem(..) => "assoc constant" + }; + + format!("{} {} in {}{}", + kind, + token::get_ident(ti.ident), + map.path_to_string(id), + id_str) + } Some(NodeVariant(ref variant)) => { format!("variant {} in {}{}", token::get_ident(variant.node.name), diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index f660296fcd..c4c2249d02 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use abi::Abi; use ast::*; use ast; use ast_util; @@ -87,33 +86,17 @@ pub fn is_shift_binop(b: BinOp_) -> bool { pub fn is_comparison_binop(b: BinOp_) -> bool { match b { - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, - _ => false + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => + true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => + false, } } /// Returns `true` if the binary operator takes its arguments by value pub fn is_by_value_binop(b: BinOp_) -> bool { - match b { - BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => { - true - } - _ => false - } -} - -/// Returns `true` if the binary operator is symmetric in the sense that LHS -/// and RHS must have the same type. So the type of LHS can serve as an hint -/// for the type of RHS and vice versa. -pub fn is_symmetric_binop(b: BinOp_) -> bool { - match b { - BiAdd | BiSub | BiMul | BiDiv | BiRem | - BiBitXor | BiBitAnd | BiBitOr | - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => { - true - } - _ => false - } + !is_comparison_binop(b) } /// Returns `true` if the unary operator takes its argument by value @@ -134,14 +117,14 @@ pub fn unop_to_string(op: UnOp) -> &'static str { } pub fn is_path(e: P) -> bool { - return match e.node { ExprPath(_) => true, _ => false }; + match e.node { ExprPath(..) => true, _ => false } } /// Get a string representation of a signed int type, with its value. /// We want to avoid "45int" and "-3int" in favor of "45" and "-3" pub fn int_ty_to_string(t: IntTy, val: Option) -> String { let s = match t { - TyIs(_) => "isize", + TyIs => "isize", TyI8 => "i8", TyI16 => "i16", TyI32 => "i32", @@ -159,10 +142,10 @@ pub fn int_ty_to_string(t: IntTy, val: Option) -> String { pub fn int_ty_max(t: IntTy) -> u64 { match t { - TyI8 => 0x80u64, - TyI16 => 0x8000u64, - TyIs(_) | TyI32 => 0x80000000u64, // actually ni about TyIs - TyI64 => 0x8000000000000000u64 + TyI8 => 0x80, + TyI16 => 0x8000, + TyIs | TyI32 => 0x80000000, // actually ni about TyIs + TyI64 => 0x8000000000000000 } } @@ -170,7 +153,7 @@ pub fn int_ty_max(t: IntTy) -> u64 { /// We want to avoid "42u" in favor of "42us". "42uint" is right out. pub fn uint_ty_to_string(t: UintTy, val: Option) -> String { let s = match t { - TyUs(_) => "usize", + TyUs => "usize", TyU8 => "u8", TyU16 => "u16", TyU32 => "u32", @@ -185,10 +168,10 @@ pub fn uint_ty_to_string(t: UintTy, val: Option) -> String { pub fn uint_ty_max(t: UintTy) -> u64 { match t { - TyU8 => 0xffu64, - TyU16 => 0xffffu64, - TyUs(_) | TyU32 => 0xffffffffu64, // actually ni about TyUs - TyU64 => 0xffffffffffffffffu64 + TyU8 => 0xff, + TyU16 => 0xffff, + TyUs | TyU32 => 0xffffffff, // actually ni about TyUs + TyU64 => 0xffffffffffffffff } } @@ -252,8 +235,12 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime { /// hint of where they came from, (previously they would all just be /// listed as `__extensions__::method_name::hash`, with no indication /// of the type). -pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { - let mut pretty = pprust::ty_to_string(ty); +pub fn impl_pretty_name(trait_ref: &Option, ty: Option<&Ty>) -> Ident { + let mut pretty = match ty { + Some(t) => pprust::ty_to_string(t), + None => String::from_str("..") + }; + match *trait_ref { Some(ref trait_ref) => { pretty.push('.'); @@ -264,62 +251,6 @@ pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { token::gensym_ident(&pretty[..]) } -pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod { - match method.node { - MethDecl(ident, - ref generics, - abi, - ref explicit_self, - unsafety, - ref decl, - _, - vis) => { - TypeMethod { - ident: ident, - attrs: method.attrs.clone(), - unsafety: unsafety, - decl: (*decl).clone(), - generics: generics.clone(), - explicit_self: (*explicit_self).clone(), - id: method.id, - span: method.span, - vis: vis, - abi: abi, - } - }, - MethMac(_) => panic!("expected non-macro method declaration") - } -} - -/// extract a TypeMethod from a TraitItem. if the TraitItem is -/// a default, pull out the useful fields to make a TypeMethod -// -// NB: to be used only after expansion is complete, and macros are gone. -pub fn trait_item_to_ty_method(method: &TraitItem) -> TypeMethod { - match *method { - RequiredMethod(ref m) => (*m).clone(), - ProvidedMethod(ref m) => trait_method_to_ty_method(&**m), - TypeTraitItem(_) => { - panic!("trait_method_to_ty_method(): expected method but found \ - typedef") - } - } -} - -pub fn split_trait_methods(trait_methods: &[TraitItem]) - -> (Vec, Vec> ) { - let mut reqd = Vec::new(); - let mut provd = Vec::new(); - for trt_method in trait_methods { - match *trt_method { - RequiredMethod(ref tm) => reqd.push((*tm).clone()), - ProvidedMethod(ref m) => provd.push((*m).clone()), - TypeTraitItem(_) => {} - } - }; - (reqd, provd) -} - pub fn struct_field_visibility(field: ast::StructField) -> Visibility { match field.node.kind { ast::NamedField(_, v) | ast::UnnamedField(v) => v @@ -360,7 +291,7 @@ pub fn empty_generics() -> Generics { // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -#[derive(RustcEncodable, RustcDecodable, Debug, Copy)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub struct IdRange { pub min: NodeId, pub max: NodeId, @@ -484,9 +415,6 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { fn visit_ty(&mut self, typ: &Ty) { self.operation.visit_id(typ.id); - if let TyPath(_, id) = typ.node { - self.operation.visit_id(id); - } visit::walk_ty(self, typ) } @@ -512,10 +440,12 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { self.operation.visit_id(node_id); match function_kind { - visit::FkItemFn(_, generics, _, _) | - visit::FkMethod(_, generics, _) => { + visit::FkItemFn(_, generics, _, _) => { self.visit_generics_helper(generics) } + visit::FkMethod(_, sig) => { + self.visit_generics_helper(&sig.generics) + } visit::FkFnBlock => {} } @@ -551,22 +481,28 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { visit::walk_struct_def(self, struct_def); } - fn visit_trait_item(&mut self, tm: &ast::TraitItem) { - match *tm { - ast::RequiredMethod(ref m) => self.operation.visit_id(m.id), - ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id), - ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.ty_param.id), - } - visit::walk_trait_item(self, tm); + fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + self.operation.visit_id(ti.id); + visit::walk_trait_item(self, ti); } - fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { + fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + self.operation.visit_id(ii.id); + visit::walk_impl_item(self, ii); + } + + fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) { self.operation.visit_id(lifetime.id); } - fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) { + fn visit_lifetime_def(&mut self, def: &LifetimeDef) { self.visit_lifetime_ref(&def.lifetime); } + + fn visit_trait_ref(&mut self, trait_ref: &TraitRef) { + self.operation.visit_id(trait_ref.ref_id); + visit::walk_trait_ref(self, trait_ref); + } } pub fn visit_ids_for_inlined_item(item: &InlinedItem, @@ -695,52 +631,6 @@ pub fn lit_is_str(lit: &Lit) -> bool { } } -/// Macro invocations are guaranteed not to occur after expansion is complete. -/// Extracting fields of a method requires a dynamic check to make sure that it's -/// not a macro invocation. This check is guaranteed to succeed, assuming -/// that the invocations are indeed gone. -pub trait PostExpansionMethod { - fn pe_ident(&self) -> ast::Ident; - fn pe_generics<'a>(&'a self) -> &'a ast::Generics; - fn pe_abi(&self) -> Abi; - fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf; - fn pe_unsafety(&self) -> ast::Unsafety; - fn pe_fn_decl<'a>(&'a self) -> &'a ast::FnDecl; - fn pe_body<'a>(&'a self) -> &'a ast::Block; - fn pe_vis(&self) -> ast::Visibility; -} - -macro_rules! mf_method{ - ($meth_name:ident, $field_ty:ty, $field_pat:pat, $result:expr) => { - fn $meth_name<'a>(&'a self) -> $field_ty { - match self.node { - $field_pat => $result, - MethMac(_) => { - panic!("expected an AST without macro invocations"); - } - } - } - } -} - - -impl PostExpansionMethod for Method { - mf_method! { pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident } - mf_method! { - pe_generics,&'a ast::Generics, - MethDecl(_,ref generics,_,_,_,_,_,_),generics - } - mf_method! { pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi } - mf_method! { - pe_explicit_self,&'a ast::ExplicitSelf, - MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self - } - mf_method! { pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety } - mf_method! { pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl } - mf_method! { pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body } - mf_method! { pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis } -} - #[cfg(test)] mod test { use ast::*; @@ -754,13 +644,13 @@ mod test { #[test] fn idents_name_eq_test() { assert!(segments_name_eq( &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] - .iter().map(ident_to_segment).collect::>()[], + .iter().map(ident_to_segment).collect::>(), &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}] - .iter().map(ident_to_segment).collect::>()[])); + .iter().map(ident_to_segment).collect::>())); assert!(!segments_name_eq( &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] - .iter().map(ident_to_segment).collect::>()[], + .iter().map(ident_to_segment).collect::>(), &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}] - .iter().map(ident_to_segment).collect::>()[])); + .iter().map(ident_to_segment).collect::>())); } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 62e676891a..06e447bb12 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -10,7 +10,6 @@ // Functions dealing with attributes and meta items -pub use self::InlineAttr::*; pub use self::StabilityLevel::*; pub use self::ReprAttr::*; pub use self::IntType::*; @@ -283,31 +282,35 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option { first_attr_value_str_by_name(attrs, "crate_name") } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum InlineAttr { - InlineNone, - InlineHint, - InlineAlways, - InlineNever, + None, + Hint, + Always, + Never, } /// Determine what `#[inline]` attribute is present in `attrs`, if any. -pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { +pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr { // FIXME (#2809)---validate the usage of #[inline] and #[inline] - attrs.iter().fold(InlineNone, |ia,attr| { + attrs.iter().fold(InlineAttr::None, |ia,attr| { match attr.node.value.node { MetaWord(ref n) if *n == "inline" => { mark_used(attr); - InlineHint + InlineAttr::Hint } MetaList(ref n, ref items) if *n == "inline" => { mark_used(attr); - if contains_name(&items[..], "always") { - InlineAlways + if items.len() != 1 { + diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); }); + InlineAttr::None + } else if contains_name(&items[..], "always") { + InlineAttr::Always } else if contains_name(&items[..], "never") { - InlineNever + InlineAttr::Never } else { - InlineHint + diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); }); + InlineAttr::None } } _ => ia @@ -317,9 +320,9 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { /// True if `#[inline]` or `#[inline(always)]` is present in `attrs`. pub fn requests_inline(attrs: &[Attribute]) -> bool { - match find_inline_attr(attrs) { - InlineHint | InlineAlways => true, - InlineNone | InlineNever => false, + match find_inline_attr(None, attrs) { + InlineAttr::Hint | InlineAttr::Always => true, + InlineAttr::None | InlineAttr::Never => false, } } @@ -562,15 +565,13 @@ fn int_type_of_word(s: &str) -> Option { "u32" => Some(UnsignedInt(ast::TyU32)), "i64" => Some(SignedInt(ast::TyI64)), "u64" => Some(UnsignedInt(ast::TyU64)), - "int" => Some(SignedInt(ast::TyIs(true))), - "uint" => Some(UnsignedInt(ast::TyUs(true))), - "isize" => Some(SignedInt(ast::TyIs(false))), - "usize" => Some(UnsignedInt(ast::TyUs(false))), + "isize" => Some(SignedInt(ast::TyIs)), + "usize" => Some(UnsignedInt(ast::TyUs)), _ => None } } -#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy)] +#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum ReprAttr { ReprAny, ReprInt(Span, IntType), @@ -589,7 +590,7 @@ impl ReprAttr { } } -#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy)] +#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum IntType { SignedInt(ast::IntTy), UnsignedInt(ast::UintTy) @@ -609,7 +610,7 @@ impl IntType { SignedInt(ast::TyI16) | UnsignedInt(ast::TyU16) | SignedInt(ast::TyI32) | UnsignedInt(ast::TyU32) | SignedInt(ast::TyI64) | UnsignedInt(ast::TyU64) => true, - SignedInt(ast::TyIs(_)) | UnsignedInt(ast::TyUs(_)) => false + SignedInt(ast::TyIs) | UnsignedInt(ast::TyUs) => false } } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 099f646294..b563a5e7d6 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -29,6 +29,11 @@ use std::rc::Rc; use libc::c_uint; use serialize::{Encodable, Decodable, Encoder, Decoder}; + +// _____________________________________________________________________________ +// Pos, BytePos, CharPos +// + pub trait Pos { fn from_usize(n: usize) -> Self; fn to_usize(&self) -> usize; @@ -42,7 +47,7 @@ pub struct BytePos(pub u32); /// A character offset. Because of multibyte utf8 characters, a byte offset /// is not equivalent to a character offset. The CodeMap will convert BytePos /// values to CharPos values as necessary. -#[derive(Copy, PartialEq, Hash, PartialOrd, Debug)] +#[derive(Copy, Clone, PartialEq, Hash, PartialOrd, Debug)] pub struct CharPos(pub usize); // FIXME: Lots of boilerplate in these impls, but so far my attempts to fix @@ -69,6 +74,18 @@ impl Sub for BytePos { } } +impl Encodable for BytePos { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_u32(self.0) + } +} + +impl Decodable for BytePos { + fn decode(d: &mut D) -> Result { + Ok(BytePos(try!{ d.read_u32() })) + } +} + impl Pos for CharPos { fn from_usize(n: usize) -> CharPos { CharPos(n) } fn to_usize(&self) -> usize { let CharPos(n) = *self; n } @@ -90,6 +107,10 @@ impl Sub for CharPos { } } +// _____________________________________________________________________________ +// Span, Spanned +// + /// Spans represent a region of code, used for error reporting. Positions in spans /// are *absolute* positions from the beginning of the codemap, not positions /// relative to FileMaps. Methods on the CodeMap can be used to relate spans back @@ -126,15 +147,20 @@ impl PartialEq for Span { impl Eq for Span {} impl Encodable for Span { - /* Note #1972 -- spans are encoded but not decoded */ fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_nil() + // Encode spans as a single u64 in order to cut down on tagging overhead + // added by the RBML metadata encoding. The should be solved differently + // altogether some time (FIXME #21482) + s.emit_u64( (self.lo.0 as u64) | ((self.hi.0 as u64) << 32) ) } } impl Decodable for Span { - fn decode(_d: &mut D) -> Result { - Ok(DUMMY_SP) + fn decode(d: &mut D) -> Result { + let lo_hi: u64 = try! { d.read_u64() }; + let lo = BytePos(lo_hi as u32); + let hi = BytePos((lo_hi >> 32) as u32); + Ok(mk_sp(lo, hi)) } } @@ -168,6 +194,10 @@ pub fn original_sp(cm: &CodeMap, sp: Span, enclosing_sp: Span) -> Span { } } +// _____________________________________________________________________________ +// Loc, LocWithOpt, FileMapAndLine, FileMapAndBytePos +// + /// A source code location used for error reporting pub struct Loc { /// Information about the original source @@ -192,6 +222,11 @@ pub struct LocWithOpt { pub struct FileMapAndLine { pub fm: Rc, pub line: usize } pub struct FileMapAndBytePos { pub fm: Rc, pub pos: BytePos } + +// _____________________________________________________________________________ +// MacroFormat, NameAndSpan, ExpnInfo, ExpnId +// + /// The syntax with which a macro was invoked. #[derive(Clone, Copy, Hash, Debug)] pub enum MacroFormat { @@ -208,6 +243,10 @@ pub struct NameAndSpan { pub name: String, /// The format with which the macro was invoked. pub format: MacroFormat, + /// Whether the macro is allowed to use #[unstable]/feature-gated + /// features internally without forcing the whole crate to opt-in + /// to them. + pub allow_internal_unstable: bool, /// The span of the macro definition itself. The macro may not /// have a sensible definition span (e.g. something defined /// completely inside libsyntax) in which case this is None. @@ -239,13 +278,13 @@ pub struct ExpnInfo { #[derive(PartialEq, Eq, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Copy)] pub struct ExpnId(u32); -pub const NO_EXPANSION: ExpnId = ExpnId(-1); +pub const NO_EXPANSION: ExpnId = ExpnId(!0); // For code appearing from the command line -pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(-2); +pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1); impl ExpnId { pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId { - ExpnId(cookie as u32) + ExpnId(cookie) } pub fn to_llvm_cookie(self) -> i32 { @@ -254,6 +293,10 @@ impl ExpnId { } } +// _____________________________________________________________________________ +// FileMap, MultiByteChar, FileName, FileLines +// + pub type FileName = String; pub struct FileLines { @@ -262,7 +305,7 @@ pub struct FileLines { } /// Identifies an offset of a multi-byte character in a FileMap -#[derive(Copy)] +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq)] pub struct MultiByteChar { /// The absolute offset of the character in the CodeMap pub pos: BytePos, @@ -277,13 +320,133 @@ pub struct FileMap { /// e.g. `` pub name: FileName, /// The complete source code - pub src: String, + pub src: Option>, /// The start position of this source in the CodeMap pub start_pos: BytePos, + /// The end position of this source in the CodeMap + pub end_pos: BytePos, /// Locations of lines beginnings in the source code - pub lines: RefCell >, + pub lines: RefCell>, /// Locations of multi-byte characters in the source code - pub multibyte_chars: RefCell >, + pub multibyte_chars: RefCell>, +} + +impl Encodable for FileMap { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_struct("FileMap", 5, |s| { + try! { s.emit_struct_field("name", 0, |s| self.name.encode(s)) }; + try! { s.emit_struct_field("start_pos", 1, |s| self.start_pos.encode(s)) }; + try! { s.emit_struct_field("end_pos", 2, |s| self.end_pos.encode(s)) }; + try! { s.emit_struct_field("lines", 3, |s| { + let lines = self.lines.borrow(); + // store the length + try! { s.emit_u32(lines.len() as u32) }; + + if lines.len() > 0 { + // In order to preserve some space, we exploit the fact that + // the lines list is sorted and individual lines are + // probably not that long. Because of that we can store lines + // as a difference list, using as little space as possible + // for the differences. + let max_line_length = if lines.len() == 1 { + 0 + } else { + lines.windows(2) + .map(|w| w[1] - w[0]) + .map(|bp| bp.to_usize()) + .max() + .unwrap() + }; + + let bytes_per_diff: u8 = match max_line_length { + 0 ... 0xFF => 1, + 0x100 ... 0xFFFF => 2, + _ => 4 + }; + + // Encode the number of bytes used per diff. + try! { bytes_per_diff.encode(s) }; + + // Encode the first element. + try! { lines[0].encode(s) }; + + let diff_iter = (&lines[..]).windows(2) + .map(|w| (w[1] - w[0])); + + match bytes_per_diff { + 1 => for diff in diff_iter { try! { (diff.0 as u8).encode(s) } }, + 2 => for diff in diff_iter { try! { (diff.0 as u16).encode(s) } }, + 4 => for diff in diff_iter { try! { diff.0.encode(s) } }, + _ => unreachable!() + } + } + + Ok(()) + }) + }; + s.emit_struct_field("multibyte_chars", 4, |s| { + (*self.multibyte_chars.borrow()).encode(s) + }) + }) + } +} + +impl Decodable for FileMap { + fn decode(d: &mut D) -> Result { + + d.read_struct("FileMap", 5, |d| { + let name: String = try! { + d.read_struct_field("name", 0, |d| Decodable::decode(d)) + }; + let start_pos: BytePos = try! { + d.read_struct_field("start_pos", 1, |d| Decodable::decode(d)) + }; + let end_pos: BytePos = try! { + d.read_struct_field("end_pos", 2, |d| Decodable::decode(d)) + }; + let lines: Vec = try! { + d.read_struct_field("lines", 3, |d| { + let num_lines: u32 = try! { Decodable::decode(d) }; + let mut lines = Vec::with_capacity(num_lines as usize); + + if num_lines > 0 { + // Read the number of bytes used per diff. + let bytes_per_diff: u8 = try! { Decodable::decode(d) }; + + // Read the first element. + let mut line_start: BytePos = try! { Decodable::decode(d) }; + lines.push(line_start); + + for _ in 1..num_lines { + let diff = match bytes_per_diff { + 1 => try! { d.read_u8() } as u32, + 2 => try! { d.read_u16() } as u32, + 4 => try! { d.read_u32() }, + _ => unreachable!() + }; + + line_start = line_start + BytePos(diff); + + lines.push(line_start); + } + } + + Ok(lines) + }) + }; + let multibyte_chars: Vec = try! { + d.read_struct_field("multibyte_chars", 4, |d| Decodable::decode(d)) + }; + Ok(FileMap { + name: name, + start_pos: start_pos, + end_pos: end_pos, + src: None, + lines: RefCell::new(lines), + multibyte_chars: RefCell::new(multibyte_chars) + }) + }) + } } impl FileMap { @@ -307,16 +470,21 @@ impl FileMap { /// get a line from the list of pre-computed line-beginnings /// pub fn get_line(&self, line_number: usize) -> Option { - let lines = self.lines.borrow(); - lines.get(line_number).map(|&line| { - let begin: BytePos = line - self.start_pos; - let begin = begin.to_usize(); - let slice = &self.src[begin..]; - match slice.find('\n') { - Some(e) => &slice[..e], - None => slice - }.to_string() - }) + match self.src { + Some(ref src) => { + let lines = self.lines.borrow(); + lines.get(line_number).map(|&line| { + let begin: BytePos = line - self.start_pos; + let begin = begin.to_usize(); + let slice = &src[begin..]; + match slice.find('\n') { + Some(e) => &slice[..e], + None => slice + }.to_string() + }) + } + None => None + } } pub fn record_multibyte_char(&self, pos: BytePos, bytes: usize) { @@ -332,8 +500,17 @@ impl FileMap { !(self.name.starts_with("<") && self.name.ends_with(">")) } + + pub fn is_imported(&self) -> bool { + self.src.is_none() + } } + +// _____________________________________________________________________________ +// CodeMap +// + pub struct CodeMap { pub files: RefCell>>, expansions: RefCell> @@ -351,7 +528,7 @@ impl CodeMap { let mut files = self.files.borrow_mut(); let start_pos = match files.last() { None => 0, - Some(last) => last.start_pos.to_usize() + last.src.len(), + Some(last) => last.end_pos.to_usize(), }; // Remove utf-8 BOM if any. @@ -372,10 +549,13 @@ impl CodeMap { src.push('\n'); } + let end_pos = start_pos + src.len(); + let filemap = Rc::new(FileMap { name: filename, - src: src.to_string(), + src: Some(Rc::new(src)), start_pos: Pos::from_usize(start_pos), + end_pos: Pos::from_usize(end_pos), lines: RefCell::new(Vec::new()), multibyte_chars: RefCell::new(Vec::new()), }); @@ -385,6 +565,45 @@ impl CodeMap { filemap } + /// Allocates a new FileMap representing a source file from an external + /// crate. The source code of such an "imported filemap" is not available, + /// but we still know enough to generate accurate debuginfo location + /// information for things inlined from other crates. + pub fn new_imported_filemap(&self, + filename: FileName, + source_len: usize, + file_local_lines: Vec, + file_local_multibyte_chars: Vec) + -> Rc { + let mut files = self.files.borrow_mut(); + let start_pos = match files.last() { + None => 0, + Some(last) => last.end_pos.to_usize(), + }; + + let end_pos = Pos::from_usize(start_pos + source_len); + let start_pos = Pos::from_usize(start_pos); + + let lines = file_local_lines.map_in_place(|pos| pos + start_pos); + let multibyte_chars = file_local_multibyte_chars.map_in_place(|mbc| MultiByteChar { + pos: mbc.pos + start_pos, + bytes: mbc.bytes + }); + + let filemap = Rc::new(FileMap { + name: filename, + src: None, + start_pos: start_pos, + end_pos: end_pos, + lines: RefCell::new(lines), + multibyte_chars: RefCell::new(multibyte_chars), + }); + + files.push(filemap.clone()); + + filemap + } + pub fn mk_substr_filename(&self, sp: Span) -> String { let pos = self.lookup_char_pos(sp.lo); (format!("<{}:{}:{}>", @@ -431,7 +650,7 @@ impl CodeMap { let lo = self.lookup_char_pos(sp.lo); let hi = self.lookup_char_pos(sp.hi); let mut lines = Vec::new(); - for i in lo.line - 1..hi.line as usize { + for i in lo.line - 1..hi.line { lines.push(i); }; FileLines {file: lo.file, lines: lines} @@ -442,30 +661,42 @@ impl CodeMap { return Err(SpanSnippetError::IllFormedSpan(sp)); } - let begin = self.lookup_byte_offset(sp.lo); - let end = self.lookup_byte_offset(sp.hi); + let local_begin = self.lookup_byte_offset(sp.lo); + let local_end = self.lookup_byte_offset(sp.hi); - if begin.fm.start_pos != end.fm.start_pos { + if local_begin.fm.start_pos != local_end.fm.start_pos { return Err(SpanSnippetError::DistinctSources(DistinctSources { - begin: (begin.fm.name.clone(), - begin.fm.start_pos), - end: (end.fm.name.clone(), - end.fm.start_pos) + begin: (local_begin.fm.name.clone(), + local_begin.fm.start_pos), + end: (local_end.fm.name.clone(), + local_end.fm.start_pos) })); } else { - let start = begin.pos.to_usize(); - let limit = end.pos.to_usize(); - if start > limit || limit > begin.fm.src.len() { - return Err(SpanSnippetError::MalformedForCodemap( - MalformedCodemapPositions { - name: begin.fm.name.clone(), - source_len: begin.fm.src.len(), - begin_pos: begin.pos, - end_pos: end.pos, - })); - } + match local_begin.fm.src { + Some(ref src) => { + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let source_len = (local_begin.fm.end_pos - + local_begin.fm.start_pos).to_usize(); + + if start_index > end_index || end_index > source_len { + return Err(SpanSnippetError::MalformedForCodemap( + MalformedCodemapPositions { + name: local_begin.fm.name.clone(), + source_len: source_len, + begin_pos: local_begin.pos, + end_pos: local_end.pos, + })); + } - return Ok((&begin.fm.src[start..limit]).to_string()) + return Ok((&src[start_index..end_index]).to_string()) + } + None => { + return Err(SpanSnippetError::SourceNotAvailable { + filename: local_begin.fm.name.clone() + }); + } + } } } @@ -478,6 +709,7 @@ impl CodeMap { panic!("asking for {} which we don't know about", filename); } + /// For a global BytePos compute the local offset within the containing FileMap pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos { let idx = self.lookup_filemap_idx(bpos); let fm = (*self.files.borrow())[idx].clone(); @@ -601,49 +833,56 @@ impl CodeMap { } } - /// Check if a span is "internal" to a macro. This means that it is entirely generated by a - /// macro expansion and contains no code that was passed in as an argument. - pub fn span_is_internal(&self, span: Span) -> bool { - // first, check if the given expression was generated by a macro or not - // we need to go back the expn_info tree to check only the arguments - // of the initial macro call, not the nested ones. - let mut is_internal = false; - let mut expnid = span.expn_id; - while self.with_expn_info(expnid, |expninfo| { - match expninfo { - Some(ref info) => { - // save the parent expn_id for next loop iteration - expnid = info.call_site.expn_id; - if info.callee.name == "format_args" { - // This is a hack because the format_args builtin calls unstable APIs. - // I spent like 6 hours trying to solve this more generally but am stupid. - is_internal = true; - false - } else if info.callee.span.is_none() { - // it's a compiler built-in, we *really* don't want to mess with it - // so we skip it, unless it was called by a regular macro, in which case - // we will handle the caller macro next turn - is_internal = true; - true // continue looping + /// Check if a span is "internal" to a macro in which #[unstable] + /// items can be used (that is, a macro marked with + /// `#[allow_internal_unstable]`). + pub fn span_allows_unstable(&self, span: Span) -> bool { + debug!("span_allows_unstable(span = {:?})", span); + let mut allows_unstable = false; + let mut expn_id = span.expn_id; + loop { + let quit = self.with_expn_info(expn_id, |expninfo| { + debug!("span_allows_unstable: expninfo = {:?}", expninfo); + expninfo.map_or(/* hit the top level */ true, |info| { + + let span_comes_from_this_expansion = + info.callee.span.map_or(span == info.call_site, |mac_span| { + mac_span.lo <= span.lo && span.hi <= mac_span.hi + }); + + debug!("span_allows_unstable: from this expansion? {}, allows unstable? {}", + span_comes_from_this_expansion, + info.callee.allow_internal_unstable); + if span_comes_from_this_expansion { + allows_unstable = info.callee.allow_internal_unstable; + // we've found the right place, stop looking + true } else { - // was this expression from the current macro arguments ? - is_internal = !( span.lo > info.call_site.lo && - span.hi < info.call_site.hi ); - true // continue looping + // not the right place, keep looking + expn_id = info.call_site.expn_id; + false } - }, - _ => false // stop looping + }) + }); + if quit { + break } - }) { /* empty while loop body */ } - return is_internal; + } + debug!("span_allows_unstable? {}", allows_unstable); + allows_unstable } } +// _____________________________________________________________________________ +// SpanSnippetError, DistinctSources, MalformedCodemapPositions +// + #[derive(Clone, PartialEq, Eq, Debug)] pub enum SpanSnippetError { IllFormedSpan(Span), DistinctSources(DistinctSources), MalformedForCodemap(MalformedCodemapPositions), + SourceNotAvailable { filename: String } } #[derive(Clone, PartialEq, Eq, Debug)] @@ -660,6 +899,11 @@ pub struct MalformedCodemapPositions { end_pos: BytePos } + +// _____________________________________________________________________________ +// Tests +// + #[cfg(test)] mod test { use super::*; @@ -677,7 +921,7 @@ mod test { } #[test] - #[should_fail] + #[should_panic] fn t2 () { let cm = CodeMap::new(); let fm = cm.new_filemap("blork.rs".to_string(), diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index dfe3477bdd..489a7721d7 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -118,13 +118,13 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ let item = match item { ast::ItemImpl(u, o, a, b, c, impl_items) => { let impl_items = impl_items.into_iter() - .filter(|ii| impl_item_in_cfg(cx, ii)) + .filter(|ii| (cx.in_cfg)(&ii.attrs)) .collect(); ast::ItemImpl(u, o, a, b, c, impl_items) } ast::ItemTrait(u, a, b, methods) => { let methods = methods.into_iter() - .filter(|m| trait_method_in_cfg(cx, m)) + .filter(|ti| (cx.in_cfg)(&ti.attrs)) .collect(); ast::ItemTrait(u, a, b, methods) } @@ -246,25 +246,6 @@ fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool return (cx.in_cfg)(&item.attrs); } -fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - match *meth { - ast::RequiredMethod(ref meth) => (cx.in_cfg)(&meth.attrs), - ast::ProvidedMethod(ref meth) => (cx.in_cfg)(&meth.attrs), - ast::TypeTraitItem(ref typ) => (cx.in_cfg)(&typ.attrs), - } -} - -fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool where - F: FnMut(&[ast::Attribute]) -> bool -{ - match *impl_item { - ast::MethodImplItem(ref meth) => (cx.in_cfg)(&meth.attrs), - ast::TypeImplItem(ref typ) => (cx.in_cfg)(&typ.attrs), - } -} - // Determine if an item should be translated in the current crate // configuration based on the item's attributes fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attribute]) -> bool { diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 27219774cf..f35cc8c8d2 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -19,13 +19,14 @@ use diagnostics; use std::cell::{RefCell, Cell}; use std::fmt; -use std::old_io; -use std::string::String; +use std::io::prelude::*; +use std::io; use term::WriterWrapper; use term; +use libc; /// maximum number of lines we will print for each error; arbitrary. -static MAX_LINES: usize = 6; +const MAX_LINES: usize = 6; #[derive(Clone, Copy)] pub enum RenderSpan { @@ -70,12 +71,12 @@ pub trait Emitter { /// This structure is used to signify that a task has panicked with a fatal error /// from the diagnostics. You can use this with the `Any` trait to figure out /// how a rustc task died (if so desired). -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct FatalError; /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct ExplicitBug; /// A span-handler is like a handler but also @@ -223,7 +224,7 @@ pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler { pub fn default_handler(color_config: ColorConfig, registry: Option, can_emit_warnings: bool) -> Handler { - mk_handler(can_emit_warnings, box EmitterWriter::stderr(color_config, registry)) + mk_handler(can_emit_warnings, Box::new(EmitterWriter::stderr(color_config, registry))) } pub fn mk_handler(can_emit_warnings: bool, e: Box) -> Handler { @@ -271,7 +272,7 @@ impl Level { fn print_maybe_styled(w: &mut EmitterWriter, msg: &str, - color: term::attr::Attr) -> old_io::IoResult<()> { + color: term::attr::Attr) -> io::Result<()> { match w.dst { Terminal(ref mut t) => { try!(t.attr(color)); @@ -289,23 +290,21 @@ fn print_maybe_styled(w: &mut EmitterWriter, // to be miscolored. We assume this is rare enough that we don't // have to worry about it. if msg.ends_with("\n") { - try!(t.write_str(&msg[..msg.len()-1])); + try!(t.write_all(msg[..msg.len()-1].as_bytes())); try!(t.reset()); - try!(t.write_str("\n")); + try!(t.write_all(b"\n")); } else { - try!(t.write_str(msg)); + try!(t.write_all(msg.as_bytes())); try!(t.reset()); } Ok(()) } - Raw(ref mut w) => { - w.write_str(msg) - } + Raw(ref mut w) => w.write_all(msg.as_bytes()), } } fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, - msg: &str, code: Option<&str>) -> old_io::IoResult<()> { + msg: &str, code: Option<&str>) -> io::Result<()> { if !topic.is_empty() { try!(write!(&mut dst.dst, "{} ", topic)); } @@ -324,7 +323,7 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, } None => () } - try!(dst.dst.write_char('\n')); + try!(write!(&mut dst.dst, "\n")); Ok(()) } @@ -335,42 +334,67 @@ pub struct EmitterWriter { enum Destination { Terminal(Box + Send>), - Raw(Box), + Raw(Box), } impl EmitterWriter { pub fn stderr(color_config: ColorConfig, registry: Option) -> EmitterWriter { - let stderr = old_io::stderr(); + let stderr = io::stderr(); let use_color = match color_config { Always => true, Never => false, - Auto => stderr.get_ref().isatty() + Auto => stderr_isatty(), }; if use_color { let dst = match term::stderr() { Some(t) => Terminal(t), - None => Raw(box stderr), + None => Raw(Box::new(stderr)), }; EmitterWriter { dst: dst, registry: registry } } else { - EmitterWriter { dst: Raw(box stderr), registry: registry } + EmitterWriter { dst: Raw(Box::new(stderr)), registry: registry } } } - pub fn new(dst: Box, + pub fn new(dst: Box, registry: Option) -> EmitterWriter { EmitterWriter { dst: Raw(dst), registry: registry } } } -impl Writer for Destination { - fn write_all(&mut self, bytes: &[u8]) -> old_io::IoResult<()> { +#[cfg(unix)] +fn stderr_isatty() -> bool { + unsafe { libc::isatty(libc::STDERR_FILENO) != 0 } +} +#[cfg(windows)] +fn stderr_isatty() -> bool { + const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD; + extern "system" { + fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + fn GetConsoleMode(hConsoleHandle: libc::HANDLE, + lpMode: libc::LPDWORD) -> libc::BOOL; + } + unsafe { + let handle = GetStdHandle(STD_ERROR_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + +impl Write for Destination { + fn write(&mut self, bytes: &[u8]) -> io::Result { + match *self { + Terminal(ref mut t) => t.write(bytes), + Raw(ref mut w) => w.write(bytes), + } + } + fn flush(&mut self) -> io::Result<()> { match *self { - Terminal(ref mut t) => t.write_all(bytes), - Raw(ref mut w) => w.write_all(bytes), + Terminal(ref mut t) => t.flush(), + Raw(ref mut w) => w.flush(), } } } @@ -403,7 +427,7 @@ impl Emitter for EmitterWriter { } fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, - msg: &str, code: Option<&str>, lvl: Level, custom: bool) -> old_io::IoResult<()> { + msg: &str, code: Option<&str>, lvl: Level, custom: bool) -> io::Result<()> { let sp = rsp.span(); // We cannot check equality directly with COMMAND_LINE_SP @@ -451,7 +475,7 @@ fn highlight_lines(err: &mut EmitterWriter, cm: &codemap::CodeMap, sp: Span, lvl: Level, - lines: codemap::FileLines) -> old_io::IoResult<()> { + lines: codemap::FileLines) -> io::Result<()> { let fm = &*lines.file; let mut elided = false; @@ -560,7 +584,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, sp: Span, lvl: Level, lines: codemap::FileLines) - -> old_io::IoResult<()> { + -> io::Result<()> { let fm = &*lines.file; let lines = &lines.lines[..]; @@ -617,8 +641,8 @@ fn custom_highlight_lines(w: &mut EmitterWriter, fn print_macro_backtrace(w: &mut EmitterWriter, cm: &codemap::CodeMap, sp: Span) - -> old_io::IoResult<()> { - let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> old_io::IoResult<_> { + -> io::Result<()> { + let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { match expn_info { Some(ei) => { let ss = ei.callee.span.map_or(String::new(), diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index 54689a1f77..055ade46a3 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -52,6 +52,13 @@ macro_rules! span_help { }) } +#[macro_export] +macro_rules! fileline_help { + ($session:expr, $span:expr, $($message:tt)*) => ({ + ($session).fileline_help($span, &format!($($message)*)) + }) +} + #[macro_export] macro_rules! register_diagnostics { ($($code:tt),*) => ( diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index b3afc3fc4d..59fe365843 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -14,10 +14,11 @@ use std::collections::BTreeMap; use ast; use ast::{Ident, Name, TokenTree}; use codemap::Span; -use ext::base::{ExtCtxt, MacExpr, MacResult, MacItems}; +use ext::base::{ExtCtxt, MacEager, MacResult}; use ext::build::AstBuilder; use parse::token; use ptr::P; +use util::small_vector::SmallVector; thread_local! { static REGISTERED_DIAGNOSTICS: RefCell>> = { @@ -73,7 +74,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, )); } }); - MacExpr::new(quote_expr!(ecx, ())) + MacEager::expr(quote_expr!(ecx, ())) } pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, @@ -101,7 +102,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, let sym = Ident::new(token::gensym(&( "__register_diagnostic_".to_string() + &token::get_ident(*code) ))); - MacItems::new(vec![quote_item!(ecx, mod $sym {}).unwrap()].into_iter()) + MacEager::items(SmallVector::many(vec![quote_item!(ecx, mod $sym {}).unwrap()])) } pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, @@ -126,7 +127,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, (descriptions.len(), ecx.expr_vec(span, descriptions)) }); - MacItems::new(vec![quote_item!(ecx, + MacEager::items(SmallVector::many(vec![quote_item!(ecx, pub static $name: [(&'static str, &'static str); $count] = $expr; - ).unwrap()].into_iter()) + ).unwrap()])) } diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index d8cba139fb..d256698b88 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -45,7 +45,7 @@ impl State { } } -static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"]; +const OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"]; pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { @@ -113,7 +113,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Some(('=', _)) => None, Some(('+', operand)) => { Some(token::intern_and_get_ident(&format!( - "={}", operand)[])) + "={}", operand))) } _ => { cx.span_err(span, "output operand constraint lacks '=' or '+'"); @@ -214,10 +214,11 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) name: "asm".to_string(), format: codemap::MacroBang, span: None, + allow_internal_unstable: false, }, }); - MacExpr::new(P(ast::Expr { + MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprInlineAsm(ast::InlineAsm { asm: token::intern_and_get_ident(&asm), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d4ccabbd63..71fba789ff 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -28,6 +28,7 @@ use fold::Folder; use std::collections::HashMap; use std::rc::Rc; +use std::default::Default; pub trait ItemDecorator { fn expand(&self, @@ -76,51 +77,31 @@ impl ItemModifier for F #[derive(Debug,Clone)] pub enum Annotatable { Item(P), - TraitItem(ast::TraitItem), - ImplItem(ast::ImplItem), + TraitItem(P), + ImplItem(P), } impl Annotatable { pub fn attrs(&self) -> &[ast::Attribute] { match *self { - Annotatable::Item(ref i) => &i.attrs[], - Annotatable::TraitItem(ref i) => match *i { - ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs[], - ast::TraitItem::ProvidedMethod(ref m) => &m.attrs[], - ast::TraitItem::TypeTraitItem(ref at) => &at.attrs[], - }, - Annotatable::ImplItem(ref i) => match *i { - ast::ImplItem::MethodImplItem(ref m) => &m.attrs[], - ast::ImplItem::TypeImplItem(ref t) => &t.attrs[], - } + Annotatable::Item(ref i) => &i.attrs, + Annotatable::TraitItem(ref ti) => &ti.attrs, + Annotatable::ImplItem(ref ii) => &ii.attrs, } } pub fn fold_attrs(self, attrs: Vec) -> Annotatable { match self { - Annotatable::Item(i) => Annotatable::Item(P(ast::Item { + Annotatable::Item(i) => Annotatable::Item(i.map(|i| ast::Item { attrs: attrs, - ..(*i).clone() + ..i + })), + Annotatable::TraitItem(i) => Annotatable::TraitItem(i.map(|ti| { + ast::TraitItem { attrs: attrs, ..ti } + })), + Annotatable::ImplItem(i) => Annotatable::ImplItem(i.map(|ii| { + ast::ImplItem { attrs: attrs, ..ii } })), - Annotatable::TraitItem(i) => match i { - ast::TraitItem::RequiredMethod(tm) => Annotatable::TraitItem( - ast::TraitItem::RequiredMethod( - ast::TypeMethod { attrs: attrs, ..tm })), - ast::TraitItem::ProvidedMethod(m) => Annotatable::TraitItem( - ast::TraitItem::ProvidedMethod(P( - ast::Method { attrs: attrs, ..(*m).clone() }))), - ast::TraitItem::TypeTraitItem(at) => Annotatable::TraitItem( - ast::TraitItem::TypeTraitItem(P( - ast::AssociatedType { attrs: attrs, ..(*at).clone() }))), - }, - Annotatable::ImplItem(i) => match i { - ast::ImplItem::MethodImplItem(m) => Annotatable::ImplItem( - ast::ImplItem::MethodImplItem(P( - ast::Method { attrs: attrs, ..(*m).clone() }))), - ast::ImplItem::TypeImplItem(t) => Annotatable::ImplItem( - ast::ImplItem::TypeImplItem(P( - ast::Typedef { attrs: attrs, ..(*t).clone() }))), - } } } @@ -131,14 +112,14 @@ impl Annotatable { } } - pub fn expect_trait_item(self) -> ast::TraitItem { + pub fn expect_trait_item(self) -> P { match self { Annotatable::TraitItem(i) => i, _ => panic!("expected Item") } } - pub fn expect_impl_item(self) -> ast::ImplItem { + pub fn expect_impl_item(self) -> P { match self { Annotatable::ImplItem(i) => i, _ => panic!("expected Item") @@ -226,9 +207,17 @@ impl IdentMacroExpander for F } } +// Use a macro because forwarding to a simple function has type system issues +macro_rules! make_stmt_default { + ($me:expr) => { + $me.make_expr().map(|e| { + P(codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID))) + }) + } +} + /// The result of a macro expansion. The return values of the various -/// methods are spliced into the AST at the callsite of the macro (or -/// just into the compiler's internal macro table, for `make_def`). +/// methods are spliced into the AST at the callsite of the macro. pub trait MacResult { /// Create an expression. fn make_expr(self: Box) -> Option> { @@ -239,8 +228,8 @@ pub trait MacResult { None } - /// Create zero or more methods. - fn make_methods(self: Box) -> Option>> { + /// Create zero or more impl items. + fn make_impl_items(self: Box) -> Option>> { None } @@ -254,69 +243,82 @@ pub trait MacResult { /// By default this attempts to create an expression statement, /// returning None if that fails. fn make_stmt(self: Box) -> Option> { - self.make_expr() - .map(|e| P(codemap::respan(e.span, ast::StmtExpr(e, ast::DUMMY_NODE_ID)))) + make_stmt_default!(self) } } -/// A convenience type for macros that return a single expression. -pub struct MacExpr { - e: P -} -impl MacExpr { - pub fn new(e: P) -> Box { - box MacExpr { e: e } as Box - } -} -impl MacResult for MacExpr { - fn make_expr(self: Box) -> Option> { - Some(self.e) - } - fn make_pat(self: Box) -> Option> { - match self.e.node { - ast::ExprLit(_) => Some(P(ast::Pat { - id: ast::DUMMY_NODE_ID, - span: self.e.span, - node: ast::PatLit(self.e) - })), - _ => None +macro_rules! make_MacEager { + ( $( $fld:ident: $t:ty, )* ) => { + /// `MacResult` implementation for the common case where you've already + /// built each form of AST that you might return. + #[derive(Default)] + pub struct MacEager { + $( + pub $fld: Option<$t>, + )* + } + + impl MacEager { + $( + pub fn $fld(v: $t) -> Box { + box MacEager { + $fld: Some(v), + ..Default::default() + } + } + )* } } } -/// A convenience type for macros that return a single pattern. -pub struct MacPat { - p: P + +make_MacEager! { + expr: P, + pat: P, + items: SmallVector>, + impl_items: SmallVector>, + stmt: P, } -impl MacPat { - pub fn new(p: P) -> Box { - box MacPat { p: p } as Box + +impl MacResult for MacEager { + fn make_expr(self: Box) -> Option> { + self.expr } -} -impl MacResult for MacPat { - fn make_pat(self: Box) -> Option> { - Some(self.p) + + fn make_items(self: Box) -> Option>> { + self.items } -} -/// A type for macros that return multiple items. -pub struct MacItems { - items: SmallVector> -} -impl MacItems { - pub fn new>>(it: I) -> Box { - box MacItems { items: it.collect() } as Box + fn make_impl_items(self: Box) -> Option>> { + self.impl_items } -} -impl MacResult for MacItems { - fn make_items(self: Box) -> Option>> { - Some(self.items) + fn make_stmt(self: Box) -> Option> { + match self.stmt { + None => make_stmt_default!(self), + s => s, + } + } + + fn make_pat(self: Box) -> Option> { + if let Some(p) = self.pat { + return Some(p); + } + if let Some(e) = self.expr { + if let ast::ExprLit(_) = e.node { + return Some(P(ast::Pat { + id: ast::DUMMY_NODE_ID, + span: e.span, + node: ast::PatLit(e), + })); + } + } + None } } /// Fill-in macro expansion result, to allow compilation to continue /// after hitting errors. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct DummyResult { expr_only: bool, span: Span @@ -328,7 +330,7 @@ impl DummyResult { /// Use this as a return value after hitting any errors and /// calling `span_err`. pub fn any(sp: Span) -> Box { - box DummyResult { expr_only: false, span: sp } as Box + box DummyResult { expr_only: false, span: sp } } /// Create a default MacResult that can only be an expression. @@ -337,7 +339,7 @@ impl DummyResult { /// if an error is encountered internally, the user will receive /// an error that they also used it in the wrong place. pub fn expr(sp: Span) -> Box { - box DummyResult { expr_only: true, span: sp } as Box + box DummyResult { expr_only: true, span: sp } } /// A plain dummy expression. @@ -375,7 +377,7 @@ impl MacResult for DummyResult { Some(SmallVector::zero()) } } - fn make_methods(self: Box) -> Option>> { + fn make_impl_items(self: Box) -> Option>> { if self.expr_only { None } else { @@ -408,12 +410,15 @@ pub enum SyntaxExtension { /// A normal, function-like syntax extension. /// /// `bytes!` is a `NormalTT`. - NormalTT(Box, Option), + /// + /// The `bool` dictates whether the contents of the macro can + /// directly use `#[unstable]` things (true == yes). + NormalTT(Box, Option, bool), /// A function-like syntax extension that has an extra ident before /// the block. /// - IdentTT(Box, Option), + IdentTT(Box, Option, bool), /// Represents `macro_rules!` itself. MacroRulesTT, @@ -443,14 +448,14 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) -> SyntaxEnv { // utility function to simplify creating NormalTT syntax extensions fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension { - NormalTT(box f, None) + NormalTT(Box::new(f), None, false) } let mut syntax_expanders = SyntaxEnv::new(); syntax_expanders.insert(intern("macro_rules"), MacroRulesTT); syntax_expanders.insert(intern("format_args"), - builtin_normal_expander( - ext::format::expand_format_args)); + // format_args uses `unstable` things internally. + NormalTT(Box::new(ext::format::expand_format_args), None, true)); syntax_expanders.insert(intern("env"), builtin_normal_expander( ext::env::expand_env)); @@ -466,10 +471,8 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) syntax_expanders.insert(intern("log_syntax"), builtin_normal_expander( ext::log_syntax::expand_syntax_ext)); - syntax_expanders.insert(intern("derive"), - Decorator(box ext::deriving::expand_meta_derive)); - syntax_expanders.insert(intern("deriving"), - Decorator(box ext::deriving::expand_deprecated_deriving)); + + ext::deriving::register_all(&mut syntax_expanders); if ecfg.enable_quotes() { // Quasi-quoting expanders @@ -482,9 +485,6 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) syntax_expanders.insert(intern("quote_ty"), builtin_normal_expander( ext::quote::expand_quote_ty)); - syntax_expanders.insert(intern("quote_method"), - builtin_normal_expander( - ext::quote::expand_quote_method)); syntax_expanders.insert(intern("quote_item"), builtin_normal_expander( ext::quote::expand_quote_item)); @@ -497,6 +497,12 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>) syntax_expanders.insert(intern("quote_stmt"), builtin_normal_expander( ext::quote::expand_quote_stmt)); + syntax_expanders.insert(intern("quote_matcher"), + builtin_normal_expander( + ext::quote::expand_quote_matcher)); + syntax_expanders.insert(intern("quote_attr"), + builtin_normal_expander( + ext::quote::expand_quote_attr)); } syntax_expanders.insert(intern("line"), @@ -639,7 +645,7 @@ impl<'a> ExtCtxt<'a> { pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); } pub fn mod_path(&self) -> Vec { let mut v = Vec::new(); - v.push(token::str_to_ident(&self.ecfg.crate_name[])); + v.push(token::str_to_ident(&self.ecfg.crate_name)); v.extend(self.mod_path.iter().cloned()); return v; } @@ -648,7 +654,7 @@ impl<'a> ExtCtxt<'a> { if self.recursion_count > self.ecfg.recursion_limit { self.span_fatal(ei.call_site, &format!("recursion limit reached while expanding the macro `{}`", - ei.callee.name)[]); + ei.callee.name)); } let mut call_site = ei.call_site; @@ -725,6 +731,10 @@ impl<'a> ExtCtxt<'a> { self.print_backtrace(); self.parse_sess.span_diagnostic.span_help(sp, msg); } + pub fn fileline_help(&self, sp: Span, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.fileline_help(sp, msg); + } pub fn bug(&self, msg: &str) -> ! { self.print_backtrace(); self.parse_sess.span_diagnostic.handler().bug(msg); @@ -773,7 +783,7 @@ pub fn check_zero_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], name: &str) { if tts.len() != 0 { - cx.span_err(sp, &format!("{} takes no arguments", name)[]); + cx.span_err(sp, &format!("{} takes no arguments", name)); } } @@ -786,12 +796,12 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt, -> Option { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { - cx.span_err(sp, &format!("{} takes 1 argument", name)[]); + cx.span_err(sp, &format!("{} takes 1 argument", name)); return None } let ret = cx.expander().fold_expr(p.parse_expr()); if p.token != token::Eof { - cx.span_err(sp, &format!("{} takes 1 argument", name)[]); + cx.span_err(sp, &format!("{} takes 1 argument", name)); } expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| { s.to_string() diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 5bfd4a9f61..5d0853761e 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -41,16 +41,16 @@ pub trait AstBuilder { -> ast::Path; fn qpath(&self, self_type: P, - trait_ref: P, - ident: ast::Ident ) - -> P; + trait_path: ast::Path, + ident: ast::Ident) + -> (ast::QSelf, ast::Path); fn qpath_all(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, - bindings: Vec> ) - -> P; + bindings: Vec>) + -> (ast::QSelf, ast::Path); // types fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; @@ -114,7 +114,7 @@ pub trait AstBuilder { // expressions fn expr(&self, span: Span, node: ast::Expr_) -> P; fn expr_path(&self, path: ast::Path) -> P; - fn expr_qpath(&self, span: Span, qpath: P) -> P; + fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P; fn expr_ident(&self, span: Span, id: ast::Ident) -> P; fn expr_self(&self, span: Span) -> P; @@ -148,6 +148,7 @@ pub trait AstBuilder { fn expr_usize(&self, span: Span, i: usize) -> P; fn expr_int(&self, sp: Span, i: isize) -> P; fn expr_u8(&self, sp: Span, u: u8) -> P; + fn expr_u32(&self, sp: Span, u: u32) -> P; fn expr_bool(&self, sp: Span, value: bool) -> P; fn expr_vec(&self, sp: Span, exprs: Vec>) -> P; @@ -345,40 +346,40 @@ impl<'a> AstBuilder for ExtCtxt<'a> { /// Constructs a qualified path. /// - /// Constructs a path like `::ident`. + /// Constructs a path like `::ident`. fn qpath(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident) - -> P { - self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new()) + -> (ast::QSelf, ast::Path) { + self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) } /// Constructs a qualified path. /// - /// Constructs a path like `::ident`. + /// Constructs a path like `::ident<'a, T, A=Bar>`. fn qpath_all(&self, self_type: P, - trait_ref: P, + trait_path: ast::Path, ident: ast::Ident, lifetimes: Vec, types: Vec>, - bindings: Vec> ) - -> P { - let segment = ast::PathSegment { + bindings: Vec>) + -> (ast::QSelf, ast::Path) { + let mut path = trait_path; + path.segments.push(ast::PathSegment { identifier: ident, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), bindings: OwnedSlice::from_vec(bindings), }) - }; + }); - P(ast::QPath { - self_type: self_type, - trait_ref: trait_ref, - item_path: segment, - }) + (ast::QSelf { + ty: self_type, + position: path.segments.len() - 1 + }, path) } fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy { @@ -397,7 +398,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_path(&self, path: ast::Path) -> P { - self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID)) + self.ty(path.span, ast::TyPath(None, path)) } fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { @@ -602,12 +603,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_path(&self, path: ast::Path) -> P { - self.expr(path.span, ast::ExprPath(path)) + self.expr(path.span, ast::ExprPath(None, path)) } /// Constructs a QPath expression. - fn expr_qpath(&self, span: Span, qpath: P) -> P { - self.expr(span, ast::ExprQPath(qpath)) + fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P { + self.expr(span, ast::ExprPath(Some(qself), path)) } fn expr_ident(&self, span: Span, id: ast::Ident) -> P { @@ -695,12 +696,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(sp, ast::ExprLit(P(respan(sp, lit)))) } fn expr_usize(&self, span: Span, i: usize) -> P { - self.expr_lit(span, ast::LitInt(i as u64, ast::UnsignedIntLit(ast::TyUs(false)))) + self.expr_lit(span, ast::LitInt(i as u64, ast::UnsignedIntLit(ast::TyUs))) } fn expr_int(&self, sp: Span, i: isize) -> P { - self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs(false), + self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs, ast::Sign::new(i)))) } + fn expr_u32(&self, sp: Span, u: u32) -> P { + self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU32))) + } fn expr_u8(&self, sp: Span, u: u8) -> P { self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8))) } @@ -762,7 +766,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_fail(&self, span: Span, msg: InternedString) -> P { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, - token::intern_and_get_ident(&loc.file.name[])); + token::intern_and_get_ident(&loc.file.name)); let expr_line = self.expr_usize(span, loc.line); let expr_file_line_tuple = self.expr_tuple(span, vec!(expr_file, expr_line)); let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs index 7216602071..6a2209bf0a 100644 --- a/src/libsyntax/ext/cfg.rs +++ b/src/libsyntax/ext/cfg.rs @@ -35,5 +35,5 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt, } let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &*cfg); - MacExpr::new(cx.expr_bool(sp, matches_cfg)) + MacEager::expr(cx.expr_bool(sp, matches_cfg)) } diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index 38098e50de..754c73a9d7 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -40,14 +40,14 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, ast::LitInt(i, ast::UnsignedIntLit(_)) | ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) | ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => { - accumulator.push_str(&format!("{}", i)[]); + accumulator.push_str(&format!("{}", i)); } ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) | ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => { - accumulator.push_str(&format!("-{}", i)[]); + accumulator.push_str(&format!("-{}", i)); } ast::LitBool(b) => { - accumulator.push_str(&format!("{}", b)[]); + accumulator.push_str(&format!("{}", b)); } ast::LitByte(..) | ast::LitBinary(..) => { @@ -60,7 +60,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, } } } - base::MacExpr::new(cx.expr_str( + base::MacEager::expr(cx.expr_str( sp, token::intern_and_get_ident(&accumulator[..]))) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 9410a51e7a..5d07c36c92 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -14,7 +14,7 @@ use ext::base::*; use ext::base; use feature_gate; use parse::token; -use parse::token::{str_to_ident}; +use parse::token::str_to_ident; use ptr::P; pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) @@ -53,7 +53,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] let e = P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path { span: sp, global: false, @@ -67,5 +67,5 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] ), span: sp, }); - MacExpr::new(e) + MacEager::expr(e) } diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 93098484ae..e408c99935 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -8,47 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{MetaItem, MetaWord, Item}; +use ast::{MetaItem, Item}; use codemap::Span; use ext::base::ExtCtxt; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_bound(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: F) where +pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt, + span: Span, + _: &MetaItem, + _: &Item, + _: F) where F: FnOnce(P), { - let name = match mitem.node { - MetaWord(ref tname) => { - match &tname[..] { - "Copy" => "Copy", - "Send" | "Sync" => { - return cx.span_err(span, - &format!("{} is an unsafe trait and it \ - should be implemented explicitly", - *tname)) - } - ref tname => { - cx.span_bug(span, - &format!("expected built-in trait name but \ - found {}", *tname)) - } - } - }, - _ => { - return cx.span_err(span, "unexpected value in deriving, expected \ - a trait") - } - }; + cx.span_err(span, "this unsafe trait should be implemented explicitly"); +} +pub fn expand_deriving_copy(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P), +{ let path = Path::new(vec![ if cx.use_std { "std" } else { "core" }, "marker", - name + "Copy", ]); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 518fbcc80e..f89f3ab55f 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -40,9 +40,9 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, args: Vec::new(), ret_ty: Self_, attributes: attrs, - combine_substructure: combine_substructure(box |c, s, sub| { + combine_substructure: combine_substructure(Box::new(|c, s, sub| { cs_clone("Clone", c, s, sub) - }), + })), } ), associated_types: Vec::new(), @@ -81,11 +81,11 @@ fn cs_clone( EnumNonMatchingCollapsed (..) => { cx.span_bug(trait_span, &format!("non-matching enum variants in \ - `derive({})`", name)[]) + `derive({})`", name)) } StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, - &format!("static method in `derive({})`", name)[]) + &format!("static method in `derive({})`", name)) } } @@ -102,7 +102,7 @@ fn cs_clone( None => { cx.span_bug(trait_span, &format!("unnamed field in normal struct in \ - `derive({})`", name)[]) + `derive({})`", name)) } }; cx.field_imm(field.span, ident, subcall(field)) diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 91212a8695..c02af437b1 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -40,7 +40,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, cx.expr_binary(span, ast::BiAnd, subexpr, eq) }, cx.expr_bool(span, true), - box |cx, span, _, _| cx.expr_bool(span, false), + Box::new(|cx, span, _, _| cx.expr_bool(span, false)), cx, span, substr) } fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { @@ -57,7 +57,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, cx.expr_binary(span, ast::BiOr, subexpr, eq) }, cx.expr_bool(span, false), - box |cx, span, _, _| cx.expr_bool(span, true), + Box::new(|cx, span, _, _| cx.expr_bool(span, true)), cx, span, substr) } @@ -70,11 +70,11 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(bool)), + ret_ty: Literal(path_local!(bool)), attributes: attrs, - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { $f(a, b, c) - }) + })) } } } } diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index b109850a6b..8ecd172b2f 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -36,11 +36,11 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec!(borrowed_self()), - ret_ty: Literal(path!(bool)), + ret_ty: Literal(path_local!(bool)), attributes: attrs, - combine_substructure: combine_substructure(box |cx, span, substr| { + combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_op($op, $equal, cx, span, substr) - }) + })) } } } } @@ -61,9 +61,9 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, args: vec![borrowed_self()], ret_ty: ret_ty, attributes: attrs, - combine_substructure: combine_substructure(box |cx, span, substr| { + combine_substructure: combine_substructure(Box::new(|cx, span, substr| { cs_partial_cmp(cx, span, substr) - }) + })) }; let trait_def = TraitDef { @@ -84,7 +84,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum OrderingOp { PartialCmpOp, LtOp, LeOp, GtOp, GeOp, } @@ -175,13 +175,13 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, cx.expr_block(cx.block(span, vec!(assign), Some(if_))) }, equals_expr.clone(), - box |cx, span, (self_args, tag_tuple), _non_self_args| { + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") } else { some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple) } - }, + }), cx, span, substr) } @@ -223,7 +223,7 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, cx.expr_binary(span, ast::BiOr, cmp, and) }, cx.expr_bool(span, equal), - box |cx, span, (self_args, tag_tuple), _non_self_args| { + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`") } else { @@ -233,6 +233,6 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, }; some_ordering_collapsed(cx, span, op, tag_tuple) } - }, + }), cx, span, substr) } diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 31a754a125..83164d242e 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -32,7 +32,8 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, let block = cx.block(span, stmts, None); cx.expr_block(block) }, - box |cx, sp, _, _| cx.span_bug(sp, "non matching enums in derive(Eq)?"), + Box::new(|cx, sp, _, _| { + cx.span_bug(sp, "non matching enums in derive(Eq)?") }), cx, span, substr) @@ -57,9 +58,9 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, args: vec!(), ret_ty: nil_ty(), attributes: attrs, - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { cs_total_eq_assert(a, b, c) - }) + })) } ), associated_types: Vec::new(), diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 2f6f99bc1e..1de955856e 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -41,9 +41,9 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt, args: vec!(borrowed_self()), ret_ty: Literal(path_std!(cx, core::cmp::Ordering)), attributes: attrs, - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { cs_cmp(a, b, c) - }), + })), } ), associated_types: Vec::new(), @@ -131,12 +131,12 @@ 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()), - box |cx, span, (self_args, tag_tuple), _non_self_args| { + Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { cx.span_bug(span, "not exactly 2 arguments in `derives(Ord)`") } else { ordering_collapsed(cx, span, tag_tuple) } - }, + }), cx, span, substr) } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index ab0f64e823..6ce68948e4 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -82,9 +82,9 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, true )), attributes: Vec::new(), - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { decodable_substructure(a, b, c, krate) - }), + })), } ), associated_types: Vec::new(), @@ -204,7 +204,7 @@ fn decode_static_fields(cx: &mut ExtCtxt, } else { let fields = fields.iter().enumerate().map(|(i, &span)| { getarg(cx, span, - token::intern_and_get_ident(&format!("_field{}", i)[]), + token::intern_and_get_ident(&format!("_field{}", i)), i) }).collect(); diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index c10975a2d3..f9991a2335 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -40,9 +40,9 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, args: Vec::new(), ret_ty: Self_, attributes: attrs, - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { default_substructure(a, b, c) - }) + })) } ), associated_types: Vec::new(), diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index dd60947059..06255f4677 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -64,7 +64,7 @@ //! fn encode(&self, s: &mut S) -> Result<(), E> { //! s.emit_struct("Spanned", 2, |this| { //! this.emit_struct_field("node", 0, |this| self.node.encode(this)) -//! .ok().unwrap(); +//! .unwrap(); //! this.emit_struct_field("span", 1, |this| self.span.encode(this)) //! }) //! } @@ -79,9 +79,9 @@ //! d.read_struct("Spanned", 2, |this| { //! Ok(Spanned { //! node: this.read_struct_field("node", 0, |this| Decodable::decode(this)) -//! .ok().unwrap(), +//! .unwrap(), //! span: this.read_struct_field("span", 1, |this| Decodable::decode(this)) -//! .ok().unwrap(), +//! .unwrap(), //! }) //! }) //! } @@ -158,9 +158,9 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, true )), attributes: Vec::new(), - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { encodable_substructure(a, b, c) - }), + })), } ), associated_types: Vec::new(), @@ -181,7 +181,6 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, Struct(ref fields) => { let emit_struct_field = cx.ident_of("emit_struct_field"); let mut stmts = Vec::new(); - let last = fields.len() - 1; for (i, &FieldInfo { name, ref self_, @@ -191,7 +190,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let name = match name { Some(id) => token::get_ident(id), None => { - token::intern_and_get_ident(&format!("_field{}", i)[]) + token::intern_and_get_ident(&format!("_field{}", i)) } }; let enc = cx.expr_method_call(span, self_.clone(), @@ -204,6 +203,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, lambda)); // last call doesn't need a try! + let last = fields.len() - 1; let call = if i != last { cx.expr_try(span, call) } else { @@ -240,25 +240,24 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let encoder = cx.expr_ident(trait_span, blkarg); let emit_variant_arg = cx.ident_of("emit_enum_variant_arg"); let mut stmts = Vec::new(); - let last = fields.len() - 1; - for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() { - let enc = cx.expr_method_call(span, self_.clone(), - encode, vec!(blkencoder.clone())); - let lambda = cx.lambda_expr_1(span, enc, blkarg); - let call = cx.expr_method_call(span, blkencoder.clone(), - emit_variant_arg, - vec!(cx.expr_usize(span, i), - lambda)); - let call = if i != last { - cx.expr_try(span, call) - } else { - cx.expr(span, ExprRet(Some(call))) - }; - stmts.push(cx.stmt_expr(call)); - } - - // enums with no fields need to return Ok() - if stmts.len() == 0 { + if fields.len() > 0 { + let last = fields.len() - 1; + for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() { + let enc = cx.expr_method_call(span, self_.clone(), + encode, vec!(blkencoder.clone())); + let lambda = cx.lambda_expr_1(span, enc, blkarg); + let call = cx.expr_method_call(span, blkencoder.clone(), + emit_variant_arg, + vec!(cx.expr_usize(span, i), + lambda)); + let call = if i != last { + cx.expr_try(span, call) + } else { + cx.expr(span, ExprRet(Some(call))) + }; + stmts.push(cx.stmt_expr(call)); + } + } else { let ret_ok = cx.expr(trait_span, ExprRet(Some(cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![]))))); diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b912ed34ae..397775fdbf 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -332,6 +332,46 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) RefCell::new(f) } +/// This method helps to extract all the type parameters referenced from a +/// type. For a type parameter ``, it looks for either a `TyPath` that +/// is not global and starts with `T`, or a `TyQPath`. +fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec> { + use visit; + + struct Visitor<'a> { + ty_param_names: &'a [ast::Name], + types: Vec>, + } + + impl<'a> visit::Visitor<'a> for Visitor<'a> { + fn visit_ty(&mut self, ty: &'a ast::Ty) { + match ty.node { + ast::TyPath(_, ref path) if !path.global => { + match path.segments.first() { + Some(segment) => { + if self.ty_param_names.contains(&segment.identifier.name) { + self.types.push(P(ty.clone())); + } + } + None => {} + } + } + _ => {} + } + + visit::walk_ty(self, ty) + } + } + + let mut visitor = Visitor { + ty_param_names: ty_param_names, + types: Vec::new(), + }; + + visit::Visitor::visit_ty(&mut visitor, ty); + + visitor.types +} impl<'a> TraitDef<'a> { pub fn expand(&self, @@ -363,7 +403,7 @@ impl<'a> TraitDef<'a> { // generated implementations are linted let mut attrs = newitem.attrs.clone(); attrs.extend(item.attrs.iter().filter(|a| { - match &a.name()[] { + match &a.name()[..] { "allow" | "warn" | "deny" | "forbid" => true, _ => false, } @@ -374,34 +414,58 @@ impl<'a> TraitDef<'a> { })) } - /// Given that we are deriving a trait `Tr` for a type `T<'a, ..., - /// 'z, A, ..., Z>`, creates an impl like: + /// Given that we are deriving a trait `DerivedTrait` for a type like: /// /// ```ignore - /// impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T { ... } + /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait { + /// a: A, + /// b: B::Item, + /// b1: ::Item, + /// c1: ::Item, + /// c2: Option<::Item>, + /// ... + /// } /// ``` /// - /// where B1, B2, ... are the bounds given by `bounds_paths`.' + /// create an impl like: + /// + /// ```ignore + /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where + /// C: WhereTrait, + /// A: DerivedTrait + B1 + ... + BN, + /// B: DerivedTrait + B1 + ... + BN, + /// C: DerivedTrait + B1 + ... + BN, + /// B::Item: DerivedTrait + B1 + ... + BN, + /// ::Item: DerivedTrait + B1 + ... + BN, + /// ... + /// { + /// ... + /// } + /// ``` + /// + /// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and + /// therefore does not get bound by the derived trait. fn create_derived_impl(&self, cx: &mut ExtCtxt, type_ident: Ident, generics: &Generics, - methods: Vec>) -> P { + field_tys: Vec>, + methods: Vec>) -> P { let trait_path = self.path.to_path(cx, self.span, type_ident, generics); - // Transform associated types from `deriving::ty::Ty` into `ast::Typedef` + // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem` let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { - P(ast::Typedef { + P(ast::ImplItem { id: ast::DUMMY_NODE_ID, span: self.span, ident: ident, vis: ast::Inherited, attrs: Vec::new(), - typ: type_def.to_ty(cx, + node: ast::TypeImplItem(type_def.to_ty(cx, self.span, type_ident, generics - ), + )), }) }); @@ -466,6 +530,35 @@ impl<'a> TraitDef<'a> { } })); + if !ty_params.is_empty() { + let ty_param_names: Vec = ty_params.iter() + .map(|ty_param| ty_param.ident.name) + .collect(); + + for field_ty in field_tys.into_iter() { + let tys = find_type_parameters(&*field_ty, &ty_param_names); + + for ty in tys.into_iter() { + let mut bounds: Vec<_> = self.additional_bounds.iter().map(|p| { + cx.typarambound(p.to_path(cx, self.span, type_ident, generics)) + }).collect(); + + // require the current trait + bounds.push(cx.typarambound(trait_path.clone())); + + let predicate = ast::WhereBoundPredicate { + span: self.span, + bound_lifetimes: vec![], + bounded_ty: ty, + bounds: OwnedSlice::from_vec(bounds), + }; + + let predicate = ast::WherePredicate::BoundPredicate(predicate); + where_clause.predicates.push(predicate); + } + } + } + let trait_generics = Generics { lifetimes: lifetimes, ty_params: OwnedSlice::from_vec(ty_params), @@ -498,7 +591,7 @@ impl<'a> TraitDef<'a> { // Just mark it now since we know that it'll end up used downstream attr::mark_used(&attr); let opt_trait_ref = Some(trait_ref); - let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type); + let ident = ast_util::impl_pretty_name(&opt_trait_ref, Some(&*self_type)); let mut a = vec![attr]; a.extend(self.attributes.iter().cloned()); cx.item( @@ -510,14 +603,7 @@ impl<'a> TraitDef<'a> { trait_generics, opt_trait_ref, self_type, - methods.into_iter() - .map(|method| { - ast::MethodImplItem(method) - }).chain( - associated_types.map(|type_| { - ast::TypeImplItem(type_) - }) - ).collect())) + methods.into_iter().chain(associated_types).collect())) } fn expand_struct_def(&self, @@ -525,6 +611,10 @@ impl<'a> TraitDef<'a> { struct_def: &StructDef, type_ident: Ident, generics: &Generics) -> P { + let field_tys: Vec> = struct_def.fields.iter() + .map(|field| field.node.ty.clone()) + .collect(); + let methods = self.methods.iter().map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = method_def.split_self_nonself_args( @@ -557,7 +647,7 @@ impl<'a> TraitDef<'a> { body) }).collect(); - self.create_derived_impl(cx, type_ident, generics, methods) + self.create_derived_impl(cx, type_ident, generics, field_tys, methods) } fn expand_enum_def(&self, @@ -565,6 +655,21 @@ impl<'a> TraitDef<'a> { enum_def: &EnumDef, type_ident: Ident, generics: &Generics) -> P { + let mut field_tys = Vec::new(); + + for variant in enum_def.variants.iter() { + match variant.node.kind { + ast::VariantKind::TupleVariantKind(ref args) => { + field_tys.extend(args.iter() + .map(|arg| arg.ty.clone())); + } + ast::VariantKind::StructVariantKind(ref args) => { + field_tys.extend(args.fields.iter() + .map(|field| field.node.ty.clone())); + } + } + } + let methods = self.methods.iter().map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = method_def.split_self_nonself_args(cx, self, @@ -597,7 +702,7 @@ impl<'a> TraitDef<'a> { body) }).collect(); - self.create_derived_impl(cx, type_ident, generics, methods) + self.create_derived_impl(cx, type_ident, generics, field_tys, methods) } } @@ -671,7 +776,7 @@ impl<'a> MethodDef<'a> { for (i, ty) in self.args.iter().enumerate() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(&format!("__arg_{}", i)[]); + let ident = cx.ident_of(&format!("__arg_{}", i)); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -702,7 +807,7 @@ impl<'a> MethodDef<'a> { abi: Abi, explicit_self: ast::ExplicitSelf, arg_types: Vec<(Ident, P)> , - body: P) -> P { + body: P) -> P { // create the generics that aren't for Self let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); @@ -725,18 +830,19 @@ impl<'a> MethodDef<'a> { let body_block = cx.block_expr(body); // Create the method. - P(ast::Method { - attrs: self.attributes.clone(), + P(ast::ImplItem { id: ast::DUMMY_NODE_ID, + attrs: self.attributes.clone(), span: trait_.span, - node: ast::MethDecl(method_ident, - fn_generics, - abi, - explicit_self, - ast::Unsafety::Normal, - fn_decl, - body_block, - ast::Inherited) + vis: ast::Inherited, + ident: method_ident, + node: ast::MethodImplItem(ast::MethodSig { + generics: fn_generics, + abi: abi, + explicit_self: explicit_self, + unsafety: ast::Unsafety::Normal, + decl: fn_decl + }, body_block) }) } @@ -778,7 +884,7 @@ impl<'a> MethodDef<'a> { struct_path, struct_def, &format!("__self_{}", - i)[], + i), ast::MutImmutable); patterns.push(pat); raw_fields.push(ident_expr); @@ -971,7 +1077,7 @@ impl<'a> MethodDef<'a> { let mut subpats = Vec::with_capacity(self_arg_names.len()); let mut self_pats_idents = Vec::with_capacity(self_arg_names.len() - 1); let first_self_pat_idents = { - let (p, idents) = mk_self_pat(cx, &self_arg_names[0][]); + let (p, idents) = mk_self_pat(cx, &self_arg_names[0]); subpats.push(p); idents }; @@ -1057,7 +1163,7 @@ impl<'a> MethodDef<'a> { let arms: Vec = variants.iter().enumerate() .map(|(index, variant)| { let pat = variant_to_pat(cx, sp, type_ident, &**variant); - let lit = ast::LitInt(index as u64, ast::UnsignedIntLit(ast::TyUs(false))); + let lit = ast::LitInt(index as u64, ast::UnsignedIntLit(ast::TyUs)); cx.arm(sp, vec![pat], cx.expr_lit(sp, lit)) }).collect(); @@ -1216,7 +1322,8 @@ impl<'a> TraitDef<'a> { callee: codemap::NameAndSpan { name: format!("derive({})", trait_name), format: codemap::MacroAttribute, - span: Some(self.span) + span: Some(self.span), + allow_internal_unstable: false, } }); to_set @@ -1289,7 +1396,7 @@ impl<'a> TraitDef<'a> { cx.span_bug(sp, "a struct with named and unnamed fields in `derive`"); } }; - let ident = cx.ident_of(&format!("{}_{}", prefix, i)[]); + let ident = cx.ident_of(&format!("{}_{}", prefix, i)); paths.push(codemap::Spanned{span: sp, node: ident}); let val = cx.expr( sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident))))); @@ -1335,7 +1442,7 @@ impl<'a> TraitDef<'a> { let mut ident_expr = Vec::new(); for (i, va) in variant_args.iter().enumerate() { let sp = self.set_expn_info(cx, va.ty.span); - let ident = cx.ident_of(&format!("{}_{}", prefix, i)[]); + let ident = cx.ident_of(&format!("{}_{}", prefix, i)); let path1 = codemap::Spanned{span: sp, node: ident}; paths.push(path1); let expr_path = cx.expr_path(cx.path_ident(sp, ident)); @@ -1378,7 +1485,7 @@ pub fn cs_fold(use_foldl: bool, field.span, old, field.self_.clone(), - &field.other[]) + &field.other) }) } else { all_fields.iter().rev().fold(base, |old, field| { @@ -1386,7 +1493,7 @@ pub fn cs_fold(use_foldl: bool, field.span, old, field.self_.clone(), - &field.other[]) + &field.other) }) } }, diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 2149c7a7f7..da80c7a0e6 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -45,9 +45,9 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, args: vec!(Ptr(box Literal(arg), Borrowed(None, MutMutable))), ret_ty: nil_ty(), attributes: vec![], - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { hash_substructure(a, b, c) - }) + })) } ), associated_types: Vec::new(), diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index f8bc331bfc..d8c50b5a09 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -13,9 +13,13 @@ //! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is //! the standard library, and "std" is the core library. -use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord}; -use ext::base::ExtCtxt; +use ast::{Item, MetaItem, MetaWord}; +use attr::AttrMetaMethods; +use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier}; +use ext::build::AstBuilder; +use feature_gate; use codemap::Span; +use parse::token::{intern, intern_and_get_ident}; use ptr::P; macro_rules! pathvec { @@ -30,6 +34,12 @@ macro_rules! path { ) } +macro_rules! path_local { + ($x:ident) => ( + ::ext::deriving::generic::ty::Path::new_local(stringify!($x)) + ) +} + macro_rules! pathvec_std { ($cx:expr, $first:ident :: $($rest:ident)::+) => ( if $cx.use_std { @@ -68,101 +78,123 @@ pub mod totalord; pub mod generic; -pub fn expand_deprecated_deriving(cx: &mut ExtCtxt, - span: Span, - _: &MetaItem, - _: &Item, - _: &mut FnMut(P)) { - cx.span_err(span, "`deriving` has been renamed to `derive`"); -} - -pub fn expand_meta_derive(cx: &mut ExtCtxt, - _span: Span, - mitem: &MetaItem, - item: &Item, - push: &mut FnMut(P)) { - match mitem.node { - MetaNameValue(_, ref l) => { - cx.span_err(l.span, "unexpected value in `derive`"); +fn expand_derive(cx: &mut ExtCtxt, + _: Span, + mitem: &MetaItem, + item: P) -> P { + item.map(|mut item| { + if mitem.value_str().is_some() { + cx.span_err(mitem.span, "unexpected value in `derive`"); } - MetaWord(_) => { + + let traits = mitem.meta_item_list().unwrap_or(&[]); + if traits.is_empty() { cx.span_warn(mitem.span, "empty trait list in `derive`"); } - MetaList(_, ref titems) if titems.len() == 0 => { - cx.span_warn(mitem.span, "empty trait list in `derive`"); + + for titem in traits.iter().rev() { + let tname = match titem.node { + MetaWord(ref tname) => tname, + _ => { + cx.span_err(titem.span, "malformed `derive` entry"); + continue; + } + }; + + if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) { + feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic, + "custom_derive", + titem.span, + feature_gate::EXPLAIN_CUSTOM_DERIVE); + continue; + } + + // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar] + item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span, + intern_and_get_ident(&format!("derive_{}", tname))))); } - MetaList(_, ref titems) => { - for titem in titems.iter().rev() { - match titem.node { - MetaNameValue(ref tname, _) | - MetaList(ref tname, _) | - MetaWord(ref tname) => { - macro_rules! expand { - ($func:path) => ($func(cx, titem.span, &**titem, item, - |i| push(i))) - } - - match &tname[..] { - "Clone" => expand!(clone::expand_deriving_clone), - - "Hash" => expand!(hash::expand_deriving_hash), - - "RustcEncodable" => { - expand!(encodable::expand_deriving_rustc_encodable) - } - "RustcDecodable" => { - expand!(decodable::expand_deriving_rustc_decodable) - } - "Encodable" => { - cx.span_warn(titem.span, - "derive(Encodable) is deprecated \ - in favor of derive(RustcEncodable)"); - - expand!(encodable::expand_deriving_encodable) - } - "Decodable" => { - cx.span_warn(titem.span, - "derive(Decodable) is deprecated \ - in favor of derive(RustcDecodable)"); - - expand!(decodable::expand_deriving_decodable) - } - - "PartialEq" => expand!(eq::expand_deriving_eq), - "Eq" => expand!(totaleq::expand_deriving_totaleq), - "PartialOrd" => expand!(ord::expand_deriving_ord), - "Ord" => expand!(totalord::expand_deriving_totalord), - - "Rand" => expand!(rand::expand_deriving_rand), - - "Show" => { - cx.span_warn(titem.span, - "derive(Show) is deprecated \ - in favor of derive(Debug)"); - - expand!(show::expand_deriving_show) - }, - - "Debug" => expand!(show::expand_deriving_show), - - "Default" => expand!(default::expand_deriving_default), - - "FromPrimitive" => expand!(primitive::expand_deriving_from_primitive), - - "Send" => expand!(bounds::expand_deriving_bound), - "Sync" => expand!(bounds::expand_deriving_bound), - "Copy" => expand!(bounds::expand_deriving_bound), - - ref tname => { - cx.span_err(titem.span, - &format!("unknown `derive` \ - trait: `{}`", - *tname)[]); - } - }; + + item + }) +} + +macro_rules! derive_traits { + ($( $name:expr => $func:path, )*) => { + pub fn register_all(env: &mut SyntaxEnv) { + // Define the #[derive_*] extensions. + $({ + struct DeriveExtension; + + impl ItemDecorator for DeriveExtension { + fn expand(&self, + ecx: &mut ExtCtxt, + sp: Span, + mitem: &MetaItem, + item: &Item, + push: &mut FnMut(P)) { + warn_if_deprecated(ecx, sp, $name); + $func(ecx, sp, mitem, item, |i| push(i)); } } + + env.insert(intern(concat!("derive_", $name)), + Decorator(Box::new(DeriveExtension))); + })* + + env.insert(intern("derive"), + Modifier(Box::new(expand_derive))); + } + + fn is_builtin_trait(name: &str) -> bool { + match name { + $( $name )|* => true, + _ => false, } } } } + +derive_traits! { + "Clone" => clone::expand_deriving_clone, + + "Hash" => hash::expand_deriving_hash, + + "RustcEncodable" => encodable::expand_deriving_rustc_encodable, + + "RustcDecodable" => decodable::expand_deriving_rustc_decodable, + + "PartialEq" => eq::expand_deriving_eq, + "Eq" => totaleq::expand_deriving_totaleq, + "PartialOrd" => ord::expand_deriving_ord, + "Ord" => totalord::expand_deriving_totalord, + + "Rand" => rand::expand_deriving_rand, + + "Debug" => show::expand_deriving_show, + + "Default" => default::expand_deriving_default, + + "FromPrimitive" => primitive::expand_deriving_from_primitive, + + "Send" => bounds::expand_deriving_unsafe_bound, + "Sync" => bounds::expand_deriving_unsafe_bound, + "Copy" => bounds::expand_deriving_copy, + + // deprecated + "Show" => show::expand_deriving_show, + "Encodable" => encodable::expand_deriving_encodable, + "Decodable" => decodable::expand_deriving_decodable, +} + +#[inline] // because `name` is a compile-time constant +fn warn_if_deprecated(ecx: &mut ExtCtxt, sp: Span, name: &str) { + if let Some(replacement) = match name { + "Show" => Some("Debug"), + "Encodable" => Some("RustcEncodable"), + "Decodable" => Some("RustcDecodable"), + _ => None, + } { + ecx.span_warn(sp, &format!("derive({}) is deprecated in favor of derive({})", + name, replacement)); + } +} diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index 22c87d978c..b2d0a9f6b5 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -38,31 +38,31 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, name: "from_i64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!(Literal(path!(i64))), + args: vec!(Literal(path_local!(i64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self_), true)), // #[inline] liable to cause code-bloat attributes: attrs.clone(), - combine_substructure: combine_substructure(box |c, s, sub| { + combine_substructure: combine_substructure(Box::new(|c, s, sub| { cs_from("i64", c, s, sub) - }), + })), }, MethodDef { name: "from_u64", generics: LifetimeBounds::empty(), explicit_self: None, - args: vec!(Literal(path!(u64))), + args: vec!(Literal(path_local!(u64))), ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option), None, vec!(box Self_), true)), // #[inline] liable to cause code-bloat attributes: attrs, - combine_substructure: combine_substructure(box |c, s, sub| { + combine_substructure: combine_substructure(Box::new(|c, s, sub| { cs_from("u64", c, s, sub) - }), + })), } ), associated_types: Vec::new(), diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 029b653510..631e5f979d 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -12,7 +12,7 @@ use ast; use ast::{MetaItem, Item, Expr}; use codemap::Span; use ext::base::ExtCtxt; -use ext::build::{AstBuilder}; +use ext::build::AstBuilder; use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; @@ -55,9 +55,9 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt, ), ret_ty: Self_, attributes: Vec::new(), - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { rand_substructure(a, b, c) - }) + })) } ), associated_types: Vec::new(), diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 281f23f9e6..ae9a402006 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -11,7 +11,6 @@ use ast; use ast::{MetaItem, Item, Expr,}; use codemap::Span; -use ext::format; use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::deriving::generic::*; @@ -19,8 +18,6 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -use std::collections::HashMap; - pub fn expand_deriving_show(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, @@ -46,9 +43,9 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, args: vec!(fmtr), ret_ty: Literal(path_std!(cx, core::fmt::Result)), attributes: Vec::new(), - combine_substructure: combine_substructure(box |a, b, c| { + combine_substructure: combine_substructure(Box::new(|a, b, c| { show_substructure(a, b, c) - }) + })) } ], associated_types: Vec::new(), @@ -56,14 +53,12 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } -/// We construct a format string and then defer to std::fmt, since that -/// knows what's up with formatting and so on. +/// We use the debug builders to do the heavy lifting here fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P { - // build ``, `({}, {}, ...)` or ` { : {}, - // : {}, ... }` based on the "shape". - // - // Easy start: they all start with the name. + // build fmt.debug_struct().field(, &)....build() + // or fmt.debug_tuple().field(&)....build() + // based on the "shape". let name = match *substr.fields { Struct(_) => substr.type_ident, EnumMatching(_, v, _) => v.node.name, @@ -72,70 +67,53 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, } }; - let mut format_string = String::from_str(&token::get_ident(name)); - // the internal fields we're actually formatting - let mut exprs = Vec::new(); + // We want to make sure we have the expn_id set so that we can use unstable methods + let span = Span { expn_id: cx.backtrace(), .. span }; + let name = cx.expr_lit(span, ast::Lit_::LitStr(token::get_ident(name), + ast::StrStyle::CookedStr)); + let mut expr = substr.nonself_args[0].clone(); - // Getting harder... making the format string: match *substr.fields { - // unit struct/nullary variant: no work necessary! - Struct(ref fields) if fields.len() == 0 => {} - EnumMatching(_, _, ref fields) if fields.len() == 0 => {} - Struct(ref fields) | EnumMatching(_, _, ref fields) => { - if fields[0].name.is_none() { + if fields.is_empty() || fields[0].name.is_none() { // tuple struct/"normal" variant - - format_string.push_str("("); - - for (i, field) in fields.iter().enumerate() { - if i != 0 { format_string.push_str(", "); } - - format_string.push_str("{:?}"); - - exprs.push(field.self_.clone()); + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("debug_tuple"), + vec![name]); + + for field in fields { + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("field"), + vec![cx.expr_addr_of(field.span, + field.self_.clone())]); } - - format_string.push_str(")"); } else { // normal struct/struct variant - - format_string.push_str(" {{"); - - for (i, field) in fields.iter().enumerate() { - if i != 0 { format_string.push_str(","); } - - let name = token::get_ident(field.name.unwrap()); - format_string.push_str(" "); - format_string.push_str(&name); - format_string.push_str(": {:?}"); - - exprs.push(field.self_.clone()); + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("debug_struct"), + vec![name]); + + for field in fields { + let name = cx.expr_lit(field.span, ast::Lit_::LitStr( + token::get_ident(field.name.clone().unwrap()), + ast::StrStyle::CookedStr)); + expr = cx.expr_method_call(span, + expr, + token::str_to_ident("field"), + vec![name, + cx.expr_addr_of(field.span, + field.self_.clone())]); } - - format_string.push_str(" }}"); } } _ => unreachable!() } - // AST construction! - // we're basically calling - // - // format_arg_method!(fmt, write_fmt, "", exprs...) - // - // but doing it directly via ext::format. - let formatter = substr.nonself_args[0].clone(); - - let meth = cx.ident_of("write_fmt"); - let s = token::intern_and_get_ident(&format_string[..]); - let format_string = cx.expr_str(span, s); - - // phew, not our responsibility any more! - - let args = vec![ - format::expand_preparsed_format_args(cx, span, format_string, - exprs, vec![], HashMap::new()) - ]; - cx.expr_method_call(span, formatter, meth, args) + cx.expr_method_call(span, + expr, + token::str_to_ident("finish"), + vec![]) } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 9c04d1e928..f72303985e 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -59,7 +59,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT &s[..])))) } }; - MacExpr::new(e) + MacEager::expr(e) } pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) @@ -83,7 +83,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) None => { token::intern_and_get_ident(&format!("environment variable `{}` \ not defined", - var)[]) + var)) } Some(second) => { match expr_to_string(cx, second, "expected string literal") { @@ -108,5 +108,5 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s)) }; - MacExpr::new(e) + MacEager::expr(e) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d4dda7390a..ee2cf9017b 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -22,7 +22,7 @@ use attr::AttrMetaMethods; use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use ext::base::*; -use feature_gate::{Features}; +use feature_gate::{self, Features}; use fold; use fold::*; use parse; @@ -41,7 +41,7 @@ pub fn expand_type(t: P, debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty); let t = match (t.node.clone(), impl_ty) { // Expand uses of `Self` in impls to the concrete type. - (ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => { + (ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => { let path_as_ident = path_to_ident(path); // Note unhygenic comparison here. I think this is correct, since // even though `Self` is almost just a type parameter, the treatment @@ -389,19 +389,20 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, &format!("macro undefined: '{}!'", - &extnamestr)[]); + &extnamestr)); // let compilation continue None } Some(rc) => match *rc { - NormalTT(ref expandfun, exp_span) => { + NormalTT(ref expandfun, exp_span, allow_internal_unstable) => { fld.cx.bt_push(ExpnInfo { call_site: span, callee: NameAndSpan { name: extnamestr.to_string(), format: MacroBang, span: exp_span, + allow_internal_unstable: allow_internal_unstable, }, }); let fm = fresh_mark(); @@ -426,7 +427,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, pth.span, &format!("non-expression macro in expression position: {}", &extnamestr[..] - )[]); + )); return None; } }; @@ -436,7 +437,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, &format!("'{}' is not a tt-style macro", - &extnamestr)[]); + &extnamestr)); None } } @@ -530,6 +531,9 @@ fn expand_item_modifiers(mut it: P, fld: &mut MacroExpander) name: mname.to_string(), format: MacroAttribute, span: None, + // attributes can do whatever they like, + // for now + allow_internal_unstable: true, } }); it = mac.expand(fld.cx, attr.span, &*attr.node.value, it); @@ -571,7 +575,7 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use"); is_use = true; if let ast::AttrInner = attr.node.style { - fld.cx.span_help(attr.span, "consider an outer attribute, \ + fld.cx.fileline_help(attr.span, "consider an outer attribute, \ #[macro_use] mod ..."); } }; @@ -608,20 +612,19 @@ pub fn expand_item_mac(it: P, None => { fld.cx.span_err(path_span, &format!("macro undefined: '{}!'", - extnamestr)[]); + extnamestr)); // let compilation continue return SmallVector::zero(); } Some(rc) => match *rc { - NormalTT(ref expander, span) => { + NormalTT(ref expander, span, allow_internal_unstable) => { if it.ident.name != parse::token::special_idents::invalid.name { fld.cx .span_err(path_span, - &format!("macro {}! expects no ident argument, \ - given '{}'", - extnamestr, - token::get_ident(it.ident))[]); + &format!("macro {}! expects no ident argument, given '{}'", + extnamestr, + token::get_ident(it.ident))); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -629,18 +632,19 @@ pub fn expand_item_mac(it: P, callee: NameAndSpan { name: extnamestr.to_string(), format: MacroBang, - span: span + span: span, + allow_internal_unstable: allow_internal_unstable, } }); // mark before expansion: let marked_before = mark_tts(&tts[..], fm); expander.expand(fld.cx, it.span, &marked_before[..]) } - IdentTT(ref expander, span) => { + IdentTT(ref expander, span, allow_internal_unstable) => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, &format!("macro {}! expects an ident argument", - &extnamestr)[]); + &extnamestr)); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -648,7 +652,8 @@ pub fn expand_item_mac(it: P, callee: NameAndSpan { name: extnamestr.to_string(), format: MacroBang, - span: span + span: span, + allow_internal_unstable: allow_internal_unstable, } }); // mark before expansion: @@ -659,19 +664,38 @@ pub fn expand_item_mac(it: P, if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, &format!("macro_rules! expects an ident argument") - []); + ); return SmallVector::zero(); } + fld.cx.bt_push(ExpnInfo { call_site: it.span, callee: NameAndSpan { name: extnamestr.to_string(), format: MacroBang, span: None, + // `macro_rules!` doesn't directly allow + // unstable (this is orthogonal to whether + // the macro it creates allows it) + allow_internal_unstable: false, } }); // DON'T mark before expansion. + let allow_internal_unstable = attr::contains_name(&it.attrs, + "allow_internal_unstable"); + + // ensure any #[allow_internal_unstable]s are + // detected (including nested macro definitions + // etc.) + if allow_internal_unstable && !fld.cx.ecfg.enable_allow_internal_unstable() { + feature_gate::emit_feature_err( + &fld.cx.parse_sess.span_diagnostic, + "allow_internal_unstable", + it.span, + feature_gate::EXPLAIN_ALLOW_INTERNAL_UNSTABLE) + } + let def = ast::MacroDef { ident: it.ident, attrs: it.attrs.clone(), @@ -680,6 +704,7 @@ pub fn expand_item_mac(it: P, imported_from: None, export: attr::contains_name(&it.attrs, "macro_export"), use_locally: true, + allow_internal_unstable: allow_internal_unstable, body: tts, }; fld.cx.insert_macro(def); @@ -691,7 +716,7 @@ pub fn expand_item_mac(it: P, _ => { fld.cx.span_err(it.span, &format!("{}! is not legal in item position", - &extnamestr)[]); + &extnamestr)); return SmallVector::zero(); } } @@ -710,7 +735,7 @@ pub fn expand_item_mac(it: P, None => { fld.cx.span_err(path_span, &format!("non-item macro in item position: {}", - &extnamestr)[]); + &extnamestr)); return SmallVector::zero(); } }; @@ -954,19 +979,20 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { None => { fld.cx.span_err(pth.span, &format!("macro undefined: '{}!'", - extnamestr)[]); + extnamestr)); // let compilation continue return DummyResult::raw_pat(span); } Some(rc) => match *rc { - NormalTT(ref expander, tt_span) => { + NormalTT(ref expander, tt_span, allow_internal_unstable) => { fld.cx.bt_push(ExpnInfo { call_site: span, callee: NameAndSpan { name: extnamestr.to_string(), format: MacroBang, - span: tt_span + span: tt_span, + allow_internal_unstable: allow_internal_unstable, } }); @@ -983,7 +1009,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { &format!( "non-pattern macro in pattern position: {}", &extnamestr - )[] + ) ); return DummyResult::raw_pat(span); } @@ -995,7 +1021,7 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { _ => { fld.cx.span_err(span, &format!("{}! is not legal in pattern position", - &extnamestr)[]); + &extnamestr)); return DummyResult::raw_pat(span); } } @@ -1095,7 +1121,10 @@ fn expand_annotatable(a: Annotatable, callee: NameAndSpan { name: mname.to_string(), format: MacroAttribute, - span: None + span: Some(attr.span), + // attributes can do whatever they like, + // for now. + allow_internal_unstable: true, } }); @@ -1145,29 +1174,26 @@ fn expand_annotatable(a: Annotatable, noop_fold_item(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect() } }, - Annotatable::TraitItem(it) => match it { - ast::TraitItem::ProvidedMethod(m) => { - expand_method(m, fld).into_iter().map(|m| - Annotatable::TraitItem(ast::TraitItem::ProvidedMethod(m))).collect() - } - ast::TraitItem::RequiredMethod(m) => { - SmallVector::one(Annotatable::TraitItem( - ast::TraitItem::RequiredMethod(fld.fold_type_method(m)))) - } - ast::TraitItem::TypeTraitItem(t) => { - SmallVector::one(Annotatable::TraitItem( - ast::TraitItem::TypeTraitItem(P(fld.fold_associated_type((*t).clone()))))) - } - }, - Annotatable::ImplItem(it) => match it { - ast::ImplItem::MethodImplItem(m) => { - expand_method(m, fld).into_iter().map(|m| - Annotatable::ImplItem(ast::ImplItem::MethodImplItem(m))).collect() - } - ast::ImplItem::TypeImplItem(t) => { - SmallVector::one(Annotatable::ImplItem( - ast::ImplItem::TypeImplItem(P(fld.fold_typedef((*t).clone()))))) - } + + Annotatable::TraitItem(it) => match it.node { + ast::MethodTraitItem(_, Some(_)) => SmallVector::one(it.map(|ti| ast::TraitItem { + id: ti.id, + ident: ti.ident, + attrs: ti.attrs, + node: match ti.node { + ast::MethodTraitItem(sig, Some(body)) => { + let (sig, body) = expand_and_rename_method(sig, body, fld); + ast::MethodTraitItem(sig, Some(body)) + } + _ => unreachable!() + }, + span: fld.new_span(ti.span) + })), + _ => fold::noop_fold_trait_item(it, fld) + }.into_iter().map(Annotatable::TraitItem).collect(), + + Annotatable::ImplItem(ii) => { + expand_impl_item(ii, fld).into_iter().map(Annotatable::ImplItem).collect() } }; @@ -1175,21 +1201,6 @@ fn expand_annotatable(a: Annotatable, new_items } -fn expand_trait_item(i: ast::TraitItem, - fld: &mut MacroExpander) - -> SmallVector { - expand_annotatable(Annotatable::TraitItem(i), fld) - .into_iter().map(|i| i.expect_trait_item()).collect() - -} - -fn expand_impl_item(i: ast::ImplItem, - fld: &mut MacroExpander) - -> SmallVector { - expand_annotatable(Annotatable::ImplItem(i), fld) - .into_iter().map(|i| i.expect_impl_item()).collect() -} - // partition the attributes into ItemModifiers and others fn modifiers(attrs: &Vec, fld: &MacroExpander) @@ -1245,6 +1256,9 @@ fn expand_item_multi_modifier(mut it: Annotatable, name: mname.to_string(), format: MacroAttribute, span: None, + // attributes can do whatever they like, + // for now + allow_internal_unstable: true, } }); it = mac.expand(fld.cx, attr.span, &*attr.node.value, it); @@ -1260,54 +1274,48 @@ fn expand_item_multi_modifier(mut it: Annotatable, expand_item_multi_modifier(it, fld) } -// expand a method -fn expand_method(m: P, fld: &mut MacroExpander) -> SmallVector> { - m.and_then(|m| match m.node { - ast::MethDecl(ident, - generics, - abi, - explicit_self, - fn_style, - decl, - body, - vis) => { - let id = fld.new_id(m.id); - let (rewritten_fn_decl, rewritten_body) - = expand_and_rename_fn_decl_and_block(decl, body, fld); - SmallVector::one(P(ast::Method { - attrs: fold::fold_attrs(m.attrs, fld), - id: id, - span: fld.new_span(m.span), - node: ast::MethDecl(fld.fold_ident(ident), - noop_fold_generics(generics, fld), - abi, - fld.fold_explicit_self(explicit_self), - fn_style, - rewritten_fn_decl, - rewritten_body, - vis) - })) - }, - ast::MethMac(mac) => { - let maybe_new_methods = - expand_mac_invoc(mac, m.span, - |r| r.make_methods(), - |meths, mark| meths.move_map(|m| mark_method(m, mark)), +fn expand_impl_item(ii: P, fld: &mut MacroExpander) + -> SmallVector> { + match ii.node { + ast::MethodImplItem(..) => SmallVector::one(ii.map(|ii| ast::ImplItem { + id: ii.id, + ident: ii.ident, + attrs: ii.attrs, + vis: ii.vis, + node: match ii.node { + ast::MethodImplItem(sig, body) => { + let (sig, body) = expand_and_rename_method(sig, body, fld); + ast::MethodImplItem(sig, body) + } + _ => unreachable!() + }, + span: fld.new_span(ii.span) + })), + ast::MacImplItem(_) => { + let (span, mac) = ii.and_then(|ii| match ii.node { + ast::MacImplItem(mac) => (ii.span, mac), + _ => unreachable!() + }); + let maybe_new_items = + expand_mac_invoc(mac, span, + |r| r.make_impl_items(), + |meths, mark| meths.move_map(|m| mark_impl_item(m, mark)), fld); - match maybe_new_methods { - Some(methods) => { + match maybe_new_items { + Some(impl_items) => { // expand again if necessary - let new_methods = methods.into_iter() - .flat_map(|m| fld.fold_method(m).into_iter()) - .collect(); + let new_items = impl_items.into_iter().flat_map(|ii| { + expand_impl_item(ii, fld).into_iter() + }).collect(); fld.cx.bt_pop(); - new_methods + new_items } None => SmallVector::zero() } } - }) + _ => fold::noop_fold_impl_item(ii, fld) + } } /// Given a fn_decl and a block and a MacroExpander, expand the fn_decl, then use the @@ -1315,7 +1323,7 @@ fn expand_method(m: P, fld: &mut MacroExpander) -> SmallVector, block: P, fld: &mut MacroExpander) - -> (P, P) { + -> (P, P) { let expanded_decl = fld.fold_fn_decl(fn_decl); let idents = fn_decl_arg_bindings(&*expanded_decl); let renames = @@ -1329,6 +1337,20 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: P, block: P, + fld: &mut MacroExpander) + -> (ast::MethodSig, P) { + let (rewritten_fn_decl, rewritten_body) + = expand_and_rename_fn_decl_and_block(sig.decl, body, fld); + (ast::MethodSig { + generics: fld.fold_generics(sig.generics), + abi: sig.abi, + explicit_self: fld.fold_explicit_self(sig.explicit_self), + unsafety: sig.unsafety, + decl: rewritten_fn_decl + }, rewritten_body) +} + /// A tree-folder that performs macro expansion pub struct MacroExpander<'a, 'b:'a> { pub cx: &'a mut ExtCtxt<'b>, @@ -1378,16 +1400,14 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { expand_arm(arm, self) } - fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector { - expand_trait_item(i, self) - } - - fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector { - expand_impl_item(i, self) + fn fold_trait_item(&mut self, i: P) -> SmallVector> { + expand_annotatable(Annotatable::TraitItem(i), self) + .into_iter().map(|i| i.expect_trait_item()).collect() } - fn fold_method(&mut self, method: P) -> SmallVector> { - expand_method(method, self) + fn fold_impl_item(&mut self, i: P) -> SmallVector> { + expand_annotatable(Annotatable::ImplItem(i), self) + .into_iter().map(|i| i.expect_impl_item()).collect() } fn fold_ty(&mut self, t: P) -> P { @@ -1415,6 +1435,19 @@ pub struct ExpansionConfig<'feat> { pub recursion_limit: usize, } +macro_rules! feature_tests { + ($( fn $getter:ident = $field:ident, )*) => { + $( + pub fn $getter(&self) -> bool { + match self.features { + Some(&Features { $field: true, .. }) => true, + _ => false, + } + } + )* + } +} + impl<'feat> ExpansionConfig<'feat> { pub fn default(crate_name: String) -> ExpansionConfig<'static> { ExpansionConfig { @@ -1424,39 +1457,14 @@ impl<'feat> ExpansionConfig<'feat> { } } - pub fn enable_quotes(&self) -> bool { - match self.features { - Some(&Features { allow_quote: true, .. }) => true, - _ => false, - } - } - - pub fn enable_asm(&self) -> bool { - match self.features { - Some(&Features { allow_asm: true, .. }) => true, - _ => false, - } - } - - pub fn enable_log_syntax(&self) -> bool { - match self.features { - Some(&Features { allow_log_syntax: true, .. }) => true, - _ => false, - } - } - - pub fn enable_concat_idents(&self) -> bool { - match self.features { - Some(&Features { allow_concat_idents: true, .. }) => true, - _ => false, - } - } - - pub fn enable_trace_macros(&self) -> bool { - match self.features { - Some(&Features { allow_trace_macros: true, .. }) => true, - _ => false, - } + feature_tests! { + fn enable_quotes = allow_quote, + fn enable_asm = allow_asm, + fn enable_log_syntax = allow_log_syntax, + fn enable_concat_idents = allow_concat_idents, + fn enable_trace_macros = allow_trace_macros, + fn enable_allow_internal_unstable = allow_internal_unstable, + fn enable_custom_derive = allow_custom_derive, } } @@ -1545,9 +1553,9 @@ fn mark_item(expr: P, m: Mrk) -> P { } // apply a given mark to the given item. Used following the expansion of a macro. -fn mark_method(expr: P, m: Mrk) -> P { - Marker{mark:m}.fold_method(expr) - .expect_one("marking an item didn't return exactly one method") +fn mark_impl_item(ii: P, m: Mrk) -> P { + Marker{mark:m}.fold_impl_item(ii) + .expect_one("marking an impl item didn't return exactly one impl item") } /// Check that there are no macro invocations left in the AST: @@ -1595,13 +1603,10 @@ mod test { impl<'v> Visitor<'v> for PathExprFinderContext { fn visit_expr(&mut self, expr: &ast::Expr) { - match expr.node { - ast::ExprPath(ref p) => { - self.path_accumulator.push(p.clone()); - // not calling visit_path, but it should be fine. - } - _ => visit::walk_expr(self, expr) + if let ast::ExprPath(None, ref p) = expr.node { + self.path_accumulator.push(p.clone()); } + visit::walk_expr(self, expr); } } @@ -1639,7 +1644,7 @@ mod test { } // make sure that macros can't escape fns - #[should_fail] + #[should_panic] #[test] fn macros_cant_escape_fns_test () { let src = "fn bogus() {macro_rules! z (() => (3+4));}\ fn inty() -> i32 { z!() }".to_string(); @@ -1653,7 +1658,7 @@ mod test { } // make sure that macros can't escape modules - #[should_fail] + #[should_panic] #[test] fn macros_cant_escape_mods_test () { let src = "mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> i32 { z!() }".to_string(); @@ -1981,7 +1986,7 @@ foo_module!(); // the xx binding should bind all of the xx varrefs: for (idx,v) in varrefs.iter().filter(|p| { p.segments.len() == 1 - && "xx" == &token::get_ident(p.segments[0].identifier)[] + && "xx" == &*token::get_ident(p.segments[0].identifier) }).enumerate() { if mtwt::resolve(v.segments[0].identifier) != resolved_binding { println!("uh oh, xx binding didn't match xx varref:"); @@ -2029,7 +2034,7 @@ foo_module!(); let renamed_crate = renamer.fold_crate(the_crate); let idents = crate_idents(&renamed_crate); let resolved : Vec = idents.iter().map(|id| mtwt::resolve(*id)).collect(); - assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16))); + assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16)]); } // test the PatIdentRenamer; only PatIdents get renamed @@ -2045,8 +2050,6 @@ foo_module!(); let idents = crate_idents(&renamed_crate); let resolved : Vec = idents.iter().map(|id| mtwt::resolve(*id)).collect(); let x_name = x_ident.name; - assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name)); + assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name]); } - - } diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index e17329d7d3..2fe77bf7a5 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -113,7 +113,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) _ => { ecx.span_err(p.span, &format!("expected ident for named argument, found `{}`", - p.this_token_to_string())[]); + p.this_token_to_string())); return None; } }; @@ -127,7 +127,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Some(prev) => { ecx.span_err(e.span, &format!("duplicate argument named `{}`", - name)[]); + name)); ecx.parse_sess.span_diagnostic.span_note(prev.span, "previously here"); continue } @@ -281,19 +281,19 @@ impl<'a, 'b> Context<'a, 'b> { &format!("argument redeclared with type `{}` when \ it was previously `{}`", *ty, - *cur)[]); + *cur)); } (&Known(ref cur), _) => { self.ecx.span_err(sp, &format!("argument used to format with `{}` was \ attempted to not be used for formatting", - *cur)[]); + *cur)); } (_, &Known(ref ty)) => { self.ecx.span_err(sp, &format!("argument previously used as a format \ argument attempted to be used as `{}`", - *ty)[]); + *ty)); } (_, _) => { self.ecx.span_err(sp, "argument declared with multiple formats"); @@ -337,7 +337,7 @@ impl<'a, 'b> Context<'a, 'b> { /// Translate the accumulated string literals to a literal expression fn trans_literal_string(&mut self) -> P { let sp = self.fmtsp; - let s = token::intern_and_get_ident(&self.literal[]); + let s = token::intern_and_get_ident(&self.literal); self.literal.clear(); self.ecx.expr_str(sp, s) } @@ -417,7 +417,7 @@ impl<'a, 'b> Context<'a, 'b> { parse::AlignUnknown => align("Unknown"), }; let align = self.ecx.expr_path(align); - let flags = self.ecx.expr_usize(sp, arg.format.flags); + let flags = self.ecx.expr_u32(sp, arg.format.flags); let prec = self.trans_count(arg.format.precision); let width = self.trans_count(arg.format.width); let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec")); @@ -494,7 +494,7 @@ impl<'a, 'b> Context<'a, 'b> { None => continue // error already generated }; - let name = self.ecx.ident_of(&format!("__arg{}", i)[]); + let name = self.ecx.ident_of(&format!("__arg{}", i)); pats.push(self.ecx.pat_ident(e.span, name)); locals.push(Context::format_arg(self.ecx, e.span, arg_ty, self.ecx.expr_ident(e.span, name))); @@ -511,9 +511,9 @@ impl<'a, 'b> Context<'a, 'b> { }; let lname = self.ecx.ident_of(&format!("__arg{}", - *name)[]); + *name)); pats.push(self.ecx.pat_ident(e.span, lname)); - names[self.name_positions[*name]] = + names[*self.name_positions.get(name).unwrap()] = Some(Context::format_arg(self.ecx, e.span, arg_ty, self.ecx.expr_ident(e.span, lname))); heads.push(self.ecx.expr_addr_of(e.span, e)); @@ -600,7 +600,7 @@ impl<'a, 'b> Context<'a, 'b> { _ => { ecx.span_err(sp, &format!("unknown format trait `{}`", - *tyname)[]); + *tyname)); "Dummy" } } @@ -610,7 +610,7 @@ impl<'a, 'b> Context<'a, 'b> { ecx.ident_of_std("core"), ecx.ident_of("fmt"), ecx.ident_of("ArgumentV1"), - ecx.ident_of("from_uint")], vec![arg]) + ecx.ident_of("from_usize")], vec![arg]) } }; @@ -633,7 +633,7 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, sp: Span, match parse_args(ecx, sp, tts) { Some((efmt, args, order, names)) => { - MacExpr::new(expand_preparsed_format_args(ecx, sp, efmt, + MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, order, names)) } None => DummyResult::expr(sp) @@ -694,7 +694,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, } if !parser.errors.is_empty() { cx.ecx.span_err(cx.fmtsp, &format!("invalid format string: {}", - parser.errors.remove(0))[]); + parser.errors.remove(0))); return DummyResult::raw_expr(sp); } if !cx.literal.is_empty() { diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index b6563d77b8..f514f72d56 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -38,7 +38,7 @@ pub struct SCTable { rename_memo: RefCell>, } -#[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, Clone)] pub enum SyntaxContext_ { EmptyCtxt, Mark (Mrk,SyntaxContext), @@ -66,9 +66,8 @@ pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext { /// Extend a syntax context with a given mark and sctable (explicit memoization) fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext { let key = (ctxt, m); - * table.mark_memo.borrow_mut().entry(key).get().unwrap_or_else( - |vacant_entry| - vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt)))) + * table.mark_memo.borrow_mut().entry(key) + .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt))) } /// Extend a syntax context with a given rename @@ -84,9 +83,8 @@ fn apply_rename_internal(id: Ident, table: &SCTable) -> SyntaxContext { let key = (ctxt, id, to); - * 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)))) + * table.rename_memo.borrow_mut().entry(key) + .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt))) } /// Apply a list of renamings to a context @@ -288,19 +286,19 @@ mod tests { fn xorpush_test () { let mut s = Vec::new(); xor_push(&mut s, 14); - assert_eq!(s.clone(), vec!(14)); + assert_eq!(s.clone(), [14]); xor_push(&mut s, 14); - assert_eq!(s.clone(), Vec::new()); + assert_eq!(s.clone(), []); xor_push(&mut s, 14); - assert_eq!(s.clone(), vec!(14)); + assert_eq!(s.clone(), [14]); xor_push(&mut s, 15); - assert_eq!(s.clone(), vec!(14, 15)); + assert_eq!(s.clone(), [14, 15]); xor_push(&mut s, 16); - assert_eq!(s.clone(), vec!(14, 15, 16)); + assert_eq!(s.clone(), [14, 15, 16]); xor_push(&mut s, 16); - assert_eq!(s.clone(), vec!(14, 15)); + assert_eq!(s.clone(), [14, 15]); xor_push(&mut s, 15); - assert_eq!(s.clone(), vec!(14)); + assert_eq!(s.clone(), [14]); } fn id(n: u32, s: SyntaxContext) -> Ident { @@ -389,13 +387,13 @@ mod tests { assert_eq!(marksof_internal (EMPTY_CTXT,stopname,&t),Vec::new()); // FIXME #5074: ANF'd to dodge nested calls { let ans = unfold_marks(vec!(4,98),EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans,stopname,&t),vec!(4,98));} + assert_eq! (marksof_internal (ans,stopname,&t), [4, 98]);} // does xoring work? { let ans = unfold_marks(vec!(5,5,16),EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans,stopname,&t), vec!(16));} + assert_eq! (marksof_internal (ans,stopname,&t), [16]);} // does nested xoring work? { let ans = unfold_marks(vec!(5,10,10,5,16),EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans, stopname,&t), vec!(16));} + assert_eq! (marksof_internal (ans, stopname,&t), [16]);} // rename where stop doesn't match: { let chain = vec!(M(9), R(id(name1.usize() as u32, @@ -403,7 +401,7 @@ mod tests { Name(100101102)), M(14)); let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans, stopname, &t), vec!(9,14));} + assert_eq! (marksof_internal (ans, stopname, &t), [9, 14]);} // rename where stop does match { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t); let chain = vec!(M(9), @@ -411,7 +409,7 @@ mod tests { stopname), M(14)); let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t); - assert_eq! (marksof_internal (ans, stopname, &t), vec!(9)); } + assert_eq! (marksof_internal (ans, stopname, &t), [9]); } } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 2c7bf713aa..87299721fb 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -171,12 +171,15 @@ pub mod rt { } } + impl_to_source! { ast::Path, path_to_string } impl_to_source! { ast::Ty, ty_to_string } impl_to_source! { ast::Block, block_to_string } impl_to_source! { ast::Arg, arg_to_string } impl_to_source! { Generics, generics_to_string } + impl_to_source! { ast::WhereClause, where_clause_to_string } impl_to_source! { P, item_to_string } - impl_to_source! { P, method_to_string } + impl_to_source! { P, impl_item_to_string } + impl_to_source! { P, trait_item_to_string } impl_to_source! { P, stmt_to_string } impl_to_source! { P, expr_to_string } impl_to_source! { P, pat_to_string } @@ -273,13 +276,13 @@ pub mod rt { ); } - impl_to_source_int! { signed, int, ast::TyIs(false) } + impl_to_source_int! { signed, isize, ast::TyIs } impl_to_source_int! { signed, i8, ast::TyI8 } impl_to_source_int! { signed, i16, ast::TyI16 } impl_to_source_int! { signed, i32, ast::TyI32 } impl_to_source_int! { signed, i64, ast::TyI64 } - impl_to_source_int! { unsigned, uint, ast::TyUs(false) } + impl_to_source_int! { unsigned, usize, ast::TyUs } impl_to_source_int! { unsigned, u8, ast::TyU8 } impl_to_source_int! { unsigned, u16, ast::TyU16 } impl_to_source_int! { unsigned, u32, ast::TyU32 } @@ -308,14 +311,17 @@ pub mod rt { } impl_to_tokens! { ast::Ident } + impl_to_tokens! { ast::Path } impl_to_tokens! { P } + impl_to_tokens! { P } + impl_to_tokens! { P } impl_to_tokens! { P } impl_to_tokens! { ast::Arm } - impl_to_tokens! { P } impl_to_tokens_lifetime! { &'a [P] } impl_to_tokens! { ast::Ty } impl_to_tokens_lifetime! { &'a [ast::Ty] } impl_to_tokens! { Generics } + impl_to_tokens! { ast::WhereClause } impl_to_tokens! { P } impl_to_tokens! { P } impl_to_tokens! { ast::Block } @@ -325,12 +331,12 @@ pub mod rt { impl_to_tokens! { () } impl_to_tokens! { char } impl_to_tokens! { bool } - impl_to_tokens! { int } + impl_to_tokens! { isize } impl_to_tokens! { i8 } impl_to_tokens! { i16 } impl_to_tokens! { i32 } impl_to_tokens! { i64 } - impl_to_tokens! { uint } + impl_to_tokens! { usize } impl_to_tokens! { u8 } impl_to_tokens! { u16 } impl_to_tokens! { u32 } @@ -363,8 +369,7 @@ pub mod rt { parse::parse_stmt_from_source_str("".to_string(), s, self.cfg(), - Vec::new(), - self.parse_sess()) + self.parse_sess()).expect("parse error") } fn parse_expr(&self, s: String) -> P { @@ -401,25 +406,24 @@ pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt, tts: &[ast::TokenTree]) -> Box { let (cx_expr, expr) = expand_tts(cx, sp, tts); - let expanded = expand_wrapper(cx, sp, cx_expr, expr); - base::MacExpr::new(expanded) + let expanded = expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"]]); + base::MacEager::expr(expanded) } pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { - let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts); - base::MacExpr::new(expanded) + let expanded = expand_parse_call(cx, sp, "parse_expr", vec!(), tts); + base::MacEager::expr(expanded) } pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { - let expanded = expand_parse_call(cx, sp, "parse_item_with_outer_attributes", - vec!(), tts); - base::MacExpr::new(expanded) + let expanded = expand_parse_call(cx, sp, "parse_item", vec!(), tts); + base::MacEager::expr(expanded) } pub fn expand_quote_pat<'cx>(cx: &'cx mut ExtCtxt, @@ -427,7 +431,7 @@ pub fn expand_quote_pat<'cx>(cx: &'cx mut ExtCtxt, tts: &[ast::TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_pat", vec!(), tts); - base::MacExpr::new(expanded) + base::MacEager::expr(expanded) } pub fn expand_quote_arm(cx: &mut ExtCtxt, @@ -435,7 +439,7 @@ pub fn expand_quote_arm(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_arm", vec!(), tts); - base::MacExpr::new(expanded) + base::MacEager::expr(expanded) } pub fn expand_quote_ty(cx: &mut ExtCtxt, @@ -443,30 +447,45 @@ pub fn expand_quote_ty(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Box { let expanded = expand_parse_call(cx, sp, "parse_ty", vec!(), tts); - base::MacExpr::new(expanded) + base::MacEager::expr(expanded) } -pub fn expand_quote_method(cx: &mut ExtCtxt, - sp: Span, - tts: &[ast::TokenTree]) - -> Box { - let expanded = expand_parse_call(cx, sp, "parse_method_with_outer_attributes", - vec!(), tts); - base::MacExpr::new(expanded) +pub fn expand_quote_stmt(cx: &mut ExtCtxt, + sp: Span, + tts: &[ast::TokenTree]) + -> Box { + let expanded = expand_parse_call(cx, sp, "parse_stmt", vec!(), tts); + base::MacEager::expr(expanded) } -pub fn expand_quote_stmt(cx: &mut ExtCtxt, +pub fn expand_quote_attr(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { - let e_attrs = cx.expr_vec_ng(sp); - let expanded = expand_parse_call(cx, sp, "parse_stmt", - vec!(e_attrs), tts); - base::MacExpr::new(expanded) + let expanded = expand_parse_call(cx, sp, "parse_attribute", + vec!(cx.expr_bool(sp, true)), tts); + + base::MacEager::expr(expanded) +} + +pub fn expand_quote_matcher(cx: &mut ExtCtxt, + sp: Span, + tts: &[ast::TokenTree]) + -> Box { + let (cx_expr, tts) = parse_arguments_to_quote(cx, tts); + let mut vector = mk_stmts_let(cx, sp); + vector.extend(statements_mk_tts(cx, &tts[..], true).into_iter()); + let block = cx.expr_block( + cx.block_all(sp, + vector, + Some(cx.expr_ident(sp, id_ext("tt"))))); + + let expanded = expand_wrapper(cx, sp, cx_expr, block, &[&["syntax", "ext", "quote", "rt"]]); + base::MacEager::expr(expanded) } fn ids_ext(strs: Vec ) -> Vec { - strs.iter().map(|str| str_to_ident(&(*str)[])).collect() + strs.iter().map(|str| str_to_ident(&(*str))).collect() } fn id_ext(str: &str) -> ast::Ident { @@ -527,7 +546,7 @@ fn mk_delim(cx: &ExtCtxt, sp: Span, delim: token::DelimToken) -> P { } #[allow(non_upper_case_globals)] -fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { +fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { macro_rules! mk_lit { ($name: expr, $suffix: expr, $($args: expr),*) => {{ let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![$($args),*]); @@ -606,6 +625,21 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { vec!(mk_name(cx, sp, ident.ident()))); } + token::MatchNt(name, kind, namep, kindp) => { + return cx.expr_call(sp, + mk_token_path(cx, sp, "MatchNt"), + vec!(mk_ident(cx, sp, name), + mk_ident(cx, sp, kind), + match namep { + ModName => mk_token_path(cx, sp, "ModName"), + Plain => mk_token_path(cx, sp, "Plain"), + }, + match kindp { + ModName => mk_token_path(cx, sp, "ModName"), + Plain => mk_token_path(cx, sp, "Plain"), + })); + } + token::Interpolated(_) => panic!("quote! with interpolated token"), _ => () @@ -635,14 +669,15 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P { token::FatArrow => "FatArrow", token::Pound => "Pound", token::Dollar => "Dollar", + token::Question => "Question", token::Underscore => "Underscore", token::Eof => "Eof", - _ => panic!(), + _ => panic!("unhandled token in quote!"), }; mk_token_path(cx, sp, name) } -fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec> { +fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec> { match *tt { ast::TtToken(sp, SubstNt(ident, _)) => { // tt.extend($ident.to_tokens(ext_cx).into_iter()) @@ -663,18 +698,18 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec> { vec!(cx.stmt_expr(e_push)) } - ref tt @ ast::TtToken(_, MatchNt(..)) => { + ref tt @ ast::TtToken(_, MatchNt(..)) if !matcher => { let mut seq = vec![]; for i in 0..tt.len() { seq.push(tt.get_tt(i)); } - mk_tts(cx, &seq[..]) + statements_mk_tts(cx, &seq[..], matcher) } ast::TtToken(sp, ref tok) => { let e_sp = cx.expr_ident(sp, id_ext("_sp")); let e_tok = cx.expr_call(sp, mk_ast_path(cx, sp, "TtToken"), - vec!(e_sp, mk_token(cx, sp, tok))); + vec!(e_sp, expr_mk_token(cx, sp, tok))); let e_push = cx.expr_method_call(sp, cx.expr_ident(sp, id_ext("tt")), @@ -683,27 +718,61 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec> { vec!(cx.stmt_expr(e_push)) }, ast::TtDelimited(_, ref delimed) => { - mk_tt(cx, &delimed.open_tt()).into_iter() - .chain(delimed.tts.iter().flat_map(|tt| mk_tt(cx, tt).into_iter())) - .chain(mk_tt(cx, &delimed.close_tt()).into_iter()) + statements_mk_tt(cx, &delimed.open_tt(), matcher).into_iter() + .chain(delimed.tts.iter() + .flat_map(|tt| statements_mk_tt(cx, tt, matcher).into_iter())) + .chain(statements_mk_tt(cx, &delimed.close_tt(), matcher).into_iter()) .collect() }, - ast::TtSequence(..) => panic!("TtSequence in quote!"), - } -} + ast::TtSequence(sp, ref seq) => { + if !matcher { + panic!("TtSequence in quote!"); + } -fn mk_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> Vec> { - let mut ss = Vec::new(); - for tt in tts { - ss.extend(mk_tt(cx, tt).into_iter()); + let e_sp = cx.expr_ident(sp, id_ext("_sp")); + + let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp)); + let mut tts_stmts = vec![stmt_let_tt]; + tts_stmts.extend(statements_mk_tts(cx, &seq.tts[..], matcher).into_iter()); + let e_tts = cx.expr_block(cx.block(sp, tts_stmts, + Some(cx.expr_ident(sp, id_ext("tt"))))); + let e_separator = match seq.separator { + Some(ref sep) => cx.expr_some(sp, expr_mk_token(cx, sp, sep)), + None => cx.expr_none(sp), + }; + let e_op = match seq.op { + ast::ZeroOrMore => mk_ast_path(cx, sp, "ZeroOrMore"), + ast::OneOrMore => mk_ast_path(cx, sp, "OneOrMore"), + }; + let fields = vec![cx.field_imm(sp, id_ext("tts"), e_tts), + cx.field_imm(sp, id_ext("separator"), e_separator), + cx.field_imm(sp, id_ext("op"), e_op), + cx.field_imm(sp, id_ext("num_captures"), + cx.expr_usize(sp, seq.num_captures))]; + let seq_path = vec![id_ext("syntax"), id_ext("ast"), id_ext("SequenceRepetition")]; + let e_seq_struct = cx.expr_struct(sp, cx.path_global(sp, seq_path), fields); + let e_rc_new = cx.expr_call_global(sp, vec![id_ext("std"), + id_ext("rc"), + id_ext("Rc"), + id_ext("new")], + vec![e_seq_struct]); + let e_tok = cx.expr_call(sp, + mk_ast_path(cx, sp, "TtSequence"), + vec!(e_sp, e_rc_new)); + let e_push = + cx.expr_method_call(sp, + cx.expr_ident(sp, id_ext("tt")), + id_ext("push"), + vec!(e_tok)); + vec!(cx.stmt_expr(e_push)) + } } - ss } -fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) - -> (P, P) { +fn parse_arguments_to_quote(cx: &ExtCtxt, tts: &[ast::TokenTree]) + -> (P, Vec) { // NB: It appears that the main parser loses its mind if we consider - // $foo as a TtNonterminal during the main parse, so we have to re-parse + // $foo as a SubstNt during the main parse, so we have to re-parse // under quote_depth > 0. This is silly and should go away; the _guess_ is // it has to do with transition away from supporting old-style macros, so // try removing it when enough of them are gone. @@ -719,6 +788,10 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let tts = p.parse_all_token_trees(); p.abort_if_errors(); + (cx_expr, tts) +} + +fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec> { // We also bind a single value, sp, to ext_cx.call_site() // // This causes every span in a token-tree quote to be attributed to the @@ -756,8 +829,23 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp)); - let mut vector = vec!(stmt_let_sp, stmt_let_tt); - vector.extend(mk_tts(cx, &tts[..]).into_iter()); + vec!(stmt_let_sp, stmt_let_tt) +} + +fn statements_mk_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], matcher: bool) -> Vec> { + let mut ss = Vec::new(); + for tt in tts { + ss.extend(statements_mk_tt(cx, tt, matcher).into_iter()); + } + ss +} + +fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) + -> (P, P) { + let (cx_expr, tts) = parse_arguments_to_quote(cx, tts); + + let mut vector = mk_stmts_let(cx, sp); + vector.extend(statements_mk_tts(cx, &tts[..], false).into_iter()); let block = cx.expr_block( cx.block_all(sp, vector, @@ -769,14 +857,14 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) fn expand_wrapper(cx: &ExtCtxt, sp: Span, cx_expr: P, - expr: P) -> P { + expr: P, + imports: &[&[&str]]) -> P { // Explicitly borrow to avoid moving from the invoker (#16992) let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr)); let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow); - let stmts = [ - &["syntax", "ext", "quote", "rt"], - ].iter().map(|path| { + let stmts = imports.iter().map(|path| { + // make item: `use ...;` let path = path.iter().map(|s| s.to_string()).collect(); cx.stmt_item(sp, cx.item_use_glob(sp, ast::Inherited, ids_ext(path))) }).chain(Some(stmt_let_ext_cx).into_iter()).collect(); @@ -807,5 +895,10 @@ fn expand_parse_call(cx: &ExtCtxt, let expr = cx.expr_method_call(sp, new_parser_call, id_ext(parse_method), arg_exprs); - expand_wrapper(cx, sp, cx_expr, expr) + if parse_method == "parse_attribute" { + expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"], + &["syntax", "parse", "attr"]]) + } else { + expand_wrapper(cx, sp, cx_expr, expr, &[&["syntax", "ext", "quote", "rt"]]) + } } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index c8d48750c7..31d8b207bb 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -20,7 +20,9 @@ use print::pprust; use ptr::P; use util::small_vector::SmallVector; -use std::old_io::File; +use std::fs::File; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; use std::rc::Rc; // These macros all relate to the file system; they either return @@ -35,7 +37,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - base::MacExpr::new(cx.expr_usize(topmost, loc.line)) + base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32)) } /* column!(): expands to the current column number */ @@ -45,7 +47,8 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - base::MacExpr::new(cx.expr_usize(topmost, loc.col.to_usize())) + + base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32)) } /// file!(): expands to the current filename */ @@ -57,14 +60,14 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - let filename = token::intern_and_get_ident(&loc.file.name[]); - base::MacExpr::new(cx.expr_str(topmost, filename)) + let filename = token::intern_and_get_ident(&loc.file.name); + base::MacEager::expr(cx.expr_str(topmost, filename)) } pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { let s = pprust::tts_to_string(tts); - base::MacExpr::new(cx.expr_str(sp, + base::MacEager::expr(cx.expr_str(sp, token::intern_and_get_ident(&s[..]))) } @@ -76,7 +79,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) .map(|x| token::get_ident(*x).to_string()) .collect::>() .connect("::"); - base::MacExpr::new(cx.expr_str( + base::MacEager::expr(cx.expr_str( sp, token::intern_and_get_ident(&string[..]))) } @@ -96,7 +99,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree cx.cfg(), &res_rel_file(cx, sp, - &Path::new(file)), + Path::new(&file)), true, None, sp); @@ -112,7 +115,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree -> Option>> { let mut ret = SmallVector::zero(); while self.p.token != token::Eof { - match self.p.parse_item_with_outer_attributes() { + match self.p.parse_item() { Some(item) => ret.push(item), None => self.p.span_fatal( self.p.span, @@ -135,8 +138,10 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Some(f) => f, None => return DummyResult::expr(sp) }; - let file = res_rel_file(cx, sp, &Path::new(file)); - let bytes = match File::open(&file).read_to_end() { + let file = res_rel_file(cx, sp, Path::new(&file)); + let mut bytes = Vec::new(); + match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { + Ok(..) => {} Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", @@ -144,7 +149,6 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) e)); return DummyResult::expr(sp); } - Ok(bytes) => bytes, }; match String::from_utf8(bytes) { Ok(src) => { @@ -154,7 +158,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let interned = token::intern_and_get_ident(&src[..]); cx.codemap().new_filemap(filename, src); - base::MacExpr::new(cx.expr_str(sp, interned)) + base::MacEager::expr(cx.expr_str(sp, interned)) } Err(_) => { cx.span_err(sp, @@ -171,30 +175,30 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Some(f) => f, None => return DummyResult::expr(sp) }; - let file = res_rel_file(cx, sp, &Path::new(file)); - match File::open(&file).read_to_end() { + let file = res_rel_file(cx, sp, Path::new(&file)); + let mut bytes = Vec::new(); + match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) { Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); return DummyResult::expr(sp); } - Ok(bytes) => { - let bytes = bytes.iter().cloned().collect(); - base::MacExpr::new(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes)))) + Ok(..) => { + base::MacEager::expr(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes)))) } } } // resolve a file-system path to an absolute file-system path (if it // isn't already) -fn res_rel_file(cx: &mut ExtCtxt, sp: codemap::Span, arg: &Path) -> Path { +fn res_rel_file(cx: &mut ExtCtxt, sp: codemap::Span, arg: &Path) -> PathBuf { // NB: relative paths are resolved relative to the compilation unit if !arg.is_absolute() { - let mut cu = Path::new(cx.codemap().span_to_filename(sp)); + let mut cu = PathBuf::from(&cx.codemap().span_to_filename(sp)); cu.pop(); cu.push(arg); cu } else { - arg.clone() + arg.to_path_buf() } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 664f7b3e08..b7d40a46f3 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -153,7 +153,7 @@ pub fn count_names(ms: &[TokenTree]) -> usize { seq.num_captures } &TtDelimited(_, ref delim) => { - count_names(&delim.tts[]) + count_names(&delim.tts) } &TtToken(_, MatchNt(..)) => { 1 @@ -243,12 +243,15 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) ret_val } -pub enum ParseResult { - Success(HashMap>), +pub enum ParseResult { + Success(T), Failure(codemap::Span, String), Error(codemap::Span, String) } +pub type NamedParseResult = ParseResult>>; +pub type PositionalParseResult = ParseResult>>; + pub fn parse_or_else(sess: &ParseSess, cfg: ast::CrateConfig, rdr: TtReader, @@ -280,7 +283,7 @@ pub fn parse(sess: &ParseSess, cfg: ast::CrateConfig, mut rdr: TtReader, ms: &[TokenTree]) - -> ParseResult { + -> NamedParseResult { let mut cur_eis = Vec::new(); cur_eis.push(initial_matcher_pos(Rc::new(ms.iter() .cloned() @@ -479,7 +482,7 @@ pub fn parse(sess: &ParseSess, } rdr.next_token(); } else /* bb_eis.len() == 1 */ { - let mut rust_parser = Parser::new(sess, cfg.clone(), box rdr.clone()); + let mut rust_parser = Parser::new(sess, cfg.clone(), Box::new(rdr.clone())); let mut ei = bb_eis.pop().unwrap(); match ei.top_elts.get_tt(ei.idx) { @@ -518,12 +521,15 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { // check at the beginning and the parser checks after each bump p.check_unknown_macro_variable(); match name { - "item" => match p.parse_item(Vec::new()) { + "item" => match p.parse_item() { Some(i) => token::NtItem(i), None => p.fatal("expected an item keyword") }, "block" => token::NtBlock(p.parse_block()), - "stmt" => token::NtStmt(p.parse_stmt(Vec::new())), + "stmt" => match p.parse_stmt() { + Some(s) => token::NtStmt(s), + None => p.fatal("expected a statement") + }, "pat" => token::NtPat(p.parse_pat()), "expr" => token::NtExpr(p.parse_expr()), "ty" => token::NtTy(p.parse_ty()), diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index fa6d934a45..1e53db6030 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -15,9 +15,8 @@ use ext::base::{NormalTT, TTMacroExpander}; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::{parse, parse_or_else}; -use parse::lexer::{new_tt_reader, new_tt_reader_with_doc_flag}; +use parse::lexer::new_tt_reader; use parse::parser::Parser; -use parse::attr::ParserAttr; use parse::token::{self, special_idents, gensym_ident, NtTT, Token}; use parse::token::Token::*; use print; @@ -68,29 +67,21 @@ impl<'a> MacResult for ParserAnyMacro<'a> { } fn make_items(self: Box>) -> Option>> { let mut ret = SmallVector::zero(); - loop { - let mut parser = self.parser.borrow_mut(); - // so... do outer attributes attached to the macro invocation - // just disappear? This question applies to make_methods, as - // well. - match parser.parse_item_with_outer_attributes() { - Some(item) => ret.push(item), - None => break - } + while let Some(item) = self.parser.borrow_mut().parse_item() { + ret.push(item); } self.ensure_complete_parse(false); Some(ret) } - fn make_methods(self: Box>) -> Option>> { + fn make_impl_items(self: Box>) + -> Option>> { let mut ret = SmallVector::zero(); loop { let mut parser = self.parser.borrow_mut(); match parser.token { token::Eof => break, - _ => { - ret.push(parser.parse_method_with_outer_attributes()); - } + _ => ret.push(parser.parse_impl_item()) } } self.ensure_complete_parse(false); @@ -98,10 +89,9 @@ impl<'a> MacResult for ParserAnyMacro<'a> { } fn make_stmt(self: Box>) -> Option> { - let attrs = self.parser.borrow_mut().parse_outer_attributes(); - let ret = self.parser.borrow_mut().parse_stmt(attrs); + let ret = self.parser.borrow_mut().parse_stmt(); self.ensure_complete_parse(true); - Some(ret) + ret } } @@ -154,15 +144,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, TtDelimited(_, ref delim) => &delim.tts[..], _ => cx.span_fatal(sp, "malformed macro lhs") }; - // `None` is because we're not interpolating - let arg_rdr = new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic, - None, - None, - arg.iter() - .cloned() - .collect(), - true); - match parse(cx.parse_sess(), cx.cfg(), arg_rdr, lhs_tt) { + + match TokenTree::parse(cx, lhs_tt, arg) { Success(named_matches) => { let rhs = match *rhses[i] { // okay, what's your transcriber? @@ -180,13 +163,13 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, Some(named_matches), imported_from, rhs); - let mut p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr); + let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr)); p.check_unknown_macro_variable(); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. return box ParserAnyMacro { parser: RefCell::new(p), - } as Box + } } Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; @@ -253,7 +236,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, argument_gram); // Extract the arguments: - let lhses = match *argument_map[lhs_nm] { + let lhses = match **argument_map.get(&lhs_nm).unwrap() { MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), _ => cx.span_bug(def.span, "wrong-structured lhs") }; @@ -262,19 +245,19 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, check_lhs_nt_follows(cx, &**lhs, def.span); } - let rhses = match *argument_map[rhs_nm] { + let rhses = match **argument_map.get(&rhs_nm).unwrap() { MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(), _ => cx.span_bug(def.span, "wrong-structured rhs") }; - let exp = box MacroRulesMacroExpander { + let exp: Box<_> = box MacroRulesMacroExpander { name: def.ident, imported_from: def.imported_from, lhses: lhses, rhses: rhses, }; - NormalTT(exp, Some(def.span)) + NormalTT(exp, Some(def.span), def.allow_internal_unstable) } fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &NamedMatch, sp: Span) { @@ -334,6 +317,10 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() }; // If T' is in the set FOLLOW(NT), continue. Else, reject. match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) { + (_, Err(msg)) => { + cx.span_err(sp, &msg); + continue + } (&Eof, _) => return Some((sp, tok.clone())), (_, Ok(true)) => continue, (next, Ok(false)) => { @@ -343,10 +330,6 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token) token_to_string(next))); continue }, - (_, Err(msg)) => { - cx.span_err(sp, &msg); - continue - } } }, TtSequence(sp, ref seq) => { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 071158fceb..dbddd9dd44 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -25,7 +25,7 @@ use self::Status::*; use self::AttributeType::*; -use abi::RustIntrinsic; +use abi::Abi; use ast::NodeId; use ast; use attr; @@ -45,7 +45,7 @@ use std::ascii::AsciiExt; // stable (active). // NB: The featureck.py script parses this information directly out of the source // so take care when modifying it. -static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ +const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("globs", "1.0.0", Accepted), ("macro_rules", "1.0.0", Accepted), ("struct_variant", "1.0.0", Accepted), @@ -54,12 +54,10 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("non_ascii_idents", "1.0.0", Active), ("thread_local", "1.0.0", Active), ("link_args", "1.0.0", Active), - ("phase", "1.0.0", Removed), ("plugin_registrar", "1.0.0", Active), ("log_syntax", "1.0.0", Active), ("trace_macros", "1.0.0", Active), ("concat_idents", "1.0.0", Active), - ("unsafe_destructor", "1.0.0", Active), ("intrinsics", "1.0.0", Active), ("lang_items", "1.0.0", Active), @@ -74,6 +72,7 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("rustc_diagnostic_macros", "1.0.0", Active), ("unboxed_closures", "1.0.0", Active), + ("reflect", "1.0.0", Active), ("import_shadowing", "1.0.0", Removed), ("advanced_slice_patterns", "1.0.0", Active), ("tuple_indexing", "1.0.0", Accepted), @@ -83,6 +82,7 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("box_syntax", "1.0.0", Active), ("on_unimplemented", "1.0.0", Active), ("simd_ffi", "1.0.0", Active), + ("allocator", "1.0.0", Active), ("if_let", "1.0.0", Accepted), ("while_let", "1.0.0", Accepted), @@ -91,6 +91,12 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ ("start", "1.0.0", Active), ("main", "1.0.0", Active), + ("fundamental", "1.0.0", Active), + + // Deprecate after snapshot + // SNAP 5520801 + ("unsafe_destructor", "1.0.0", Active), + // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. ("issue_5723_bootstrap", "1.0.0", Accepted), @@ -98,18 +104,9 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // A way to temporarily opt out of opt in copy. This will *never* be accepted. ("opt_out_copy", "1.0.0", Removed), - // A way to temporarily opt out of the new orphan rules. This will *never* be accepted. - ("old_orphan_check", "1.0.0", Deprecated), - - // A way to temporarily opt out of the new impl rules. This will *never* be accepted. - ("old_impl_check", "1.0.0", Deprecated), - // OIBIT specific features ("optin_builtin_traits", "1.0.0", Active), - // int and uint are now deprecated - ("int_uint", "1.0.0", Active), - // macro reexport needs more discussion and stabilization ("macro_reexport", "1.0.0", Active), @@ -137,8 +134,27 @@ static KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // Allows the use of custom attributes; RFC 572 ("custom_attribute", "1.0.0", Active), + // Allows the use of #[derive(Anything)] as sugar for + // #[derive_Anything]. + ("custom_derive", "1.0.0", Active), + // Allows the use of rustc_* attributes; RFC 572 ("rustc_attrs", "1.0.0", Active), + + // Allows the use of `static_assert` + ("static_assert", "1.0.0", Active), + + // Allows the use of #[allow_internal_unstable]. This is an + // attribute on macro_rules! and can't use the attribute handling + // below (it has to be checked before expansion possibly makes + // macros disappear). + ("allow_internal_unstable", "1.0.0", Active), + + // #23121. Array patterns have some hazards yet. + ("slice_patterns", "1.0.0", Active), + + // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 + ("negate_unsigned", "1.0.0", Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -147,10 +163,6 @@ enum Status { /// currently being considered for addition/removal. Active, - /// Represents a feature gate that is temporarily enabling deprecated behavior. - /// This gate will never be accepted. - Deprecated, - /// Represents a feature which has since been removed (it was once Active) Removed, @@ -159,7 +171,7 @@ enum Status { } // Attributes that have a special meaning to rustc or rustdoc -pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ +pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ // Normal attributes ("warn", Normal), @@ -173,6 +185,7 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("plugin_registrar", Normal), ("cfg", Normal), + ("cfg_attr", Normal), ("main", Normal), ("start", Normal), ("test", Normal), @@ -181,19 +194,19 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("repr", Normal), ("path", Normal), ("abi", Normal), - ("unsafe_destructor", Normal), ("automatically_derived", Normal), ("no_mangle", Normal), ("no_link", Normal), ("derive", Normal), - ("should_fail", Normal), + ("should_panic", Normal), ("ignore", Normal), ("no_implicit_prelude", Normal), ("reexport_test_harness_main", Normal), ("link_args", Normal), ("macro_escape", Normal), - + ("unsafe_destructor", Gated("unsafe_destructor", + "`#[unsafe_destructor]` does nothing anymore")), ("staged_api", Gated("staged_api", "staged_api is for use by rustc only")), ("plugin", Gated("plugin", @@ -214,6 +227,8 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("rustc_on_unimplemented", Gated("on_unimplemented", "the `#[rustc_on_unimplemented]` attribute \ is an experimental feature")), + ("allocator", Gated("allocator", + "the `#[allocator]` attribute is an experimental feature")), ("rustc_variance", Gated("rustc_attrs", "the `#[rustc_variance]` attribute \ is an experimental feature")), @@ -224,6 +239,13 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ "the `#[rustc_move_fragments]` attribute \ is an experimental feature")), + ("allow_internal_unstable", Gated("allow_internal_unstable", + EXPLAIN_ALLOW_INTERNAL_UNSTABLE)), + + ("fundamental", Gated("fundamental", + "the `#[fundamental]` attribute \ + is an experimental feature")), + // FIXME: #14408 whitelist docs since rustdoc looks at them ("doc", Whitelisted), @@ -237,13 +259,15 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("link_section", Whitelisted), ("no_builtins", Whitelisted), ("no_mangle", Whitelisted), - ("no_split_stack", Whitelisted), ("no_stack_check", Whitelisted), ("packed", Whitelisted), - ("static_assert", Whitelisted), + ("static_assert", Gated("static_assert", + "`#[static_assert]` is an experimental feature, and has a poor API")), ("no_debug", Whitelisted), ("omit_gdb_pretty_printer_section", Whitelisted), - ("unsafe_no_drop_flag", Whitelisted), + ("unsafe_no_drop_flag", Gated("unsafe_no_drop_flag", + "unsafe_no_drop_flag has unstable semantics \ + and may be removed in the future")), // used in resolve ("prelude_import", Whitelisted), @@ -255,10 +279,10 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("stable", Whitelisted), ("unstable", Whitelisted), - // FIXME: #19470 this shouldn't be needed forever - ("old_orphan_check", Whitelisted), - ("old_impl_check", Whitelisted), - ("rustc_paren_sugar", Whitelisted), // FIXME: #18101 temporary unboxed closure hack + ("rustc_paren_sugar", Gated("unboxed_closures", + "unboxed_closures are still evolving")), + ("rustc_reflect_like", Gated("reflect", + "defining reflective traits is still evolving")), // Crate level attributes ("crate_name", CrateLevel), @@ -271,7 +295,7 @@ pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("recursion_limit", CrateLevel), ]; -#[derive(PartialEq, Copy)] +#[derive(PartialEq, Copy, Clone, Debug)] pub enum AttributeType { /// Normal, builtin attribute that is consumed /// by the compiler before the unused_attribute check @@ -300,9 +324,11 @@ pub struct Features { pub allow_log_syntax: bool, pub allow_concat_idents: bool, pub allow_trace_macros: bool, - pub old_orphan_check: bool, + pub allow_internal_unstable: bool, + pub allow_custom_derive: bool, pub simd_ffi: bool, pub unmarked_api: bool, + pub negate_unsigned: bool, /// spans of #![feature] attrs for stable language features. for error reporting pub declared_stable_lang_features: Vec, /// #![feature] attrs for non-language (library) features @@ -320,9 +346,11 @@ impl Features { allow_log_syntax: false, allow_concat_idents: false, allow_trace_macros: false, - old_orphan_check: false, + allow_internal_unstable: false, + allow_custom_derive: false, simd_ffi: false, unmarked_api: false, + negate_unsigned: false, declared_stable_lang_features: Vec::new(), declared_lib_features: Vec::new() } @@ -337,24 +365,51 @@ struct Context<'a> { impl<'a> Context<'a> { fn gate_feature(&self, feature: &str, span: Span, explain: &str) { - if !self.has_feature(feature) { + let has_feature = self.has_feature(feature); + debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_feature); + if !has_feature { emit_feature_err(self.span_handler, feature, span, explain); } } - - fn warn_feature(&self, feature: &str, span: Span, explain: &str) { - if !self.has_feature(feature) { - emit_feature_warn(self.span_handler, feature, span, explain); - } - } fn has_feature(&self, feature: &str) -> bool { self.features.iter().any(|&n| n == feature) } + + fn check_attribute(&self, attr: &ast::Attribute) { + debug!("check_attribute(attr = {:?})", attr); + let name = &*attr.name(); + for &(n, ty) in KNOWN_ATTRIBUTES { + if n == name { + if let Gated(gate, desc) = ty { + self.gate_feature(gate, attr.span, desc); + } + debug!("check_attribute: {:?} is known, {:?}", name, ty); + return; + } + } + if name.starts_with("rustc_") { + self.gate_feature("rustc_attrs", attr.span, + "unless otherwise specified, attributes \ + with the prefix `rustc_` \ + are reserved for internal compiler diagnostics"); + } else if name.starts_with("derive_") { + self.gate_feature("custom_derive", attr.span, + "attributes of the form `#[derive_*]` are reserved + for the compiler"); + } else { + self.gate_feature("custom_attribute", attr.span, + &format!("The attribute `{}` is currently \ + unknown to the the compiler and \ + may have meaning \ + added to it in the future", + name)); + } + } } pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) { diag.span_err(span, explain); - diag.span_help(span, &format!("add #![feature({})] to the \ + diag.fileline_help(span, &format!("add #![feature({})] to the \ crate attributes to enable", feature)); } @@ -362,7 +417,7 @@ pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: &str) { diag.span_warn(span, explain); if diag.handler.can_emit_warnings { - diag.span_help(span, &format!("add #![feature({})] to the \ + diag.fileline_help(span, &format!("add #![feature({})] to the \ crate attributes to silence this warning", feature)); } @@ -379,6 +434,11 @@ pub const EXPLAIN_CONCAT_IDENTS: &'static str = pub const EXPLAIN_TRACE_MACROS: &'static str = "`trace_macros` is not stable enough for use and is subject to change"; +pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str = + "allow_internal_unstable side-steps feature gating and stability checks"; + +pub const EXPLAIN_CUSTOM_DERIVE: &'static str = + "`#[derive]` for custom traits is not stable enough for use and is subject to change"; struct MacroVisitor<'a> { context: &'a Context<'a> @@ -413,6 +473,10 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> { self.context.gate_feature("concat_idents", path.span, EXPLAIN_CONCAT_IDENTS); } } + + fn visit_attribute(&mut self, attr: &'v ast::Attribute) { + self.context.check_attribute(attr); + } } struct PostExpansionVisitor<'a> { @@ -421,13 +485,19 @@ struct PostExpansionVisitor<'a> { impl<'a> PostExpansionVisitor<'a> { fn gate_feature(&self, feature: &str, span: Span, explain: &str) { - if !self.context.cm.span_is_internal(span) { + if !self.context.cm.span_allows_unstable(span) { self.context.gate_feature(feature, span, explain) } } } impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { + fn visit_attribute(&mut self, attr: &ast::Attribute) { + if !self.context.cm.span_allows_unstable(attr.span) { + self.context.check_attribute(attr); + } + } + fn visit_name(&mut self, sp: Span, name: ast::Name) { if !token::get_name(name).is_ascii() { self.gate_feature("non_ascii_idents", sp, @@ -452,7 +522,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { across platforms, it is recommended to \ use `#[link(name = \"foo\")]` instead") } - if foreign_module.abi == RustIntrinsic { + if foreign_module.abi == Abi::RustIntrinsic { self.gate_feature("intrinsics", i.span, "intrinsics are subject to change") @@ -485,6 +555,13 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } + ast::ItemDefaultImpl(..) => { + self.gate_feature("optin_builtin_traits", + i.span, + "default trait implementations are experimental \ + and possibly buggy"); + } + ast::ItemImpl(_, polarity, _, _, _, _) => { match polarity { ast::ImplPolarity::Negative => { @@ -495,30 +572,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { }, _ => {} } - - if attr::contains_name(&i.attrs, - "unsafe_destructor") { - self.gate_feature("unsafe_destructor", - i.span, - "`#[unsafe_destructor]` allows too \ - many unsafe patterns and may be \ - removed in the future"); - } - - if attr::contains_name(&i.attrs[..], - "old_orphan_check") { - self.gate_feature( - "old_orphan_check", - i.span, - "the new orphan check rules will eventually be strictly enforced"); - } - - if attr::contains_name(&i.attrs[..], - "old_impl_check") { - self.gate_feature("old_impl_check", - i.span, - "`#[old_impl_check]` will be removed in the future"); - } } _ => {} @@ -528,12 +581,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { - if attr::contains_name(&i.attrs, "linkage") { - self.gate_feature("linkage", i.span, - "the `linkage` attribute is experimental \ - and not portable across platforms") - } - let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") { Some(val) => val.starts_with("llvm."), @@ -547,35 +594,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { visit::walk_foreign_item(self, i) } - fn visit_ty(&mut self, t: &ast::Ty) { - match t.node { - ast::TyPath(ref p, _) => { - match &*p.segments { - - [ast::PathSegment { identifier, .. }] => { - let name = token::get_ident(identifier); - let msg = if name == "int" { - Some("the `int` type is deprecated; \ - use `isize` or a fixed-sized integer") - } else if name == "uint" { - Some("the `uint` type is deprecated; \ - use `usize` or a fixed-sized integer") - } else { - None - }; - - if let Some(msg) = msg { - self.context.warn_feature("int_uint", t.span, msg) - } - } - _ => {} - } - } - _ => {} - } - visit::walk_ty(self, t); - } - fn visit_expr(&mut self, e: &ast::Expr) { match e.node { ast::ExprBox(..) | ast::ExprUnary(ast::UnOp::UnUniq, _) => { @@ -584,55 +602,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { "box expression syntax is experimental; \ you can call `Box::new` instead."); } - ast::ExprLit(ref lit) => { - match lit.node { - ast::LitInt(_, ty) => { - let msg = if let ast::SignedIntLit(ast::TyIs(true), _) = ty { - Some("the `i` and `is` suffixes on integers are deprecated; \ - use `isize` or one of the fixed-sized suffixes") - } else if let ast::UnsignedIntLit(ast::TyUs(true)) = ty { - Some("the `u` and `us` suffixes on integers are deprecated; \ - use `usize` or one of the fixed-sized suffixes") - } else { - None - }; - if let Some(msg) = msg { - self.context.warn_feature("int_uint", e.span, msg); - } - } - _ => {} - } - } _ => {} } visit::walk_expr(self, e); } - fn visit_attribute(&mut self, attr: &ast::Attribute) { - let name = &*attr.name(); - for &(n, ty) in KNOWN_ATTRIBUTES { - if n == name { - if let Gated(gate, desc) = ty { - self.gate_feature(gate, attr.span, desc); - } - return; - } - } - if name.starts_with("rustc_") { - self.gate_feature("rustc_attrs", attr.span, - "unless otherwise specified, attributes \ - with the prefix `rustc_` \ - are reserved for internal compiler diagnostics"); - } else { - self.gate_feature("custom_attribute", attr.span, - format!("The attribute `{}` is currently \ - unknown to the the compiler and \ - may have meaning \ - added to it in the future", - name).as_slice()); - } - } - fn visit_pat(&mut self, pattern: &ast::Pat) { match pattern.node { ast::PatVec(_, Some(_), ref last) if !last.is_empty() => { @@ -642,6 +616,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { but at the end of a slice (e.g. \ `[0, ..xs, 0]` are experimental") } + ast::PatVec(..) => { + self.gate_feature("slice_patterns", + pattern.span, + "slice pattern syntax is experimental"); + } ast::PatBox(..) => { self.gate_feature("box_patterns", pattern.span, @@ -659,18 +638,25 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { span: Span, _node_id: NodeId) { match fn_kind { - visit::FkItemFn(_, _, _, abi) if abi == RustIntrinsic => { + visit::FkItemFn(_, _, _, abi) if abi == Abi::RustIntrinsic => { self.gate_feature("intrinsics", span, "intrinsics are subject to change") } + visit::FkItemFn(_, _, _, abi) | + visit::FkMethod(_, &ast::MethodSig { abi, .. }) if abi == Abi::RustCall => { + self.gate_feature("unboxed_closures", + span, + "rust-call ABI is subject to change") + } _ => {} } visit::walk_fn(self, fn_kind, fn_decl, block, span); } } -fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate, +fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, + krate: &ast::Crate, check: F) -> Features where F: FnOnce(&mut Context, &ast::Crate) @@ -710,13 +696,6 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C Some(&(name, _, Active)) => { cx.features.push(name); } - Some(&(name, _, Deprecated)) => { - cx.features.push(name); - span_handler.span_warn( - mi.span, - "feature is deprecated and will only be available \ - for a limited time, please rewrite code that relies on it"); - } Some(&(_, _, Removed)) => { span_handler.span_err(mi.span, "feature has been removed"); } @@ -746,9 +725,11 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C allow_log_syntax: cx.has_feature("log_syntax"), allow_concat_idents: cx.has_feature("concat_idents"), allow_trace_macros: cx.has_feature("trace_macros"), - old_orphan_check: cx.has_feature("old_orphan_check"), + allow_internal_unstable: cx.has_feature("allow_internal_unstable"), + allow_custom_derive: cx.has_feature("custom_derive"), simd_ffi: cx.has_feature("simd_ffi"), unmarked_api: cx.has_feature("unmarked_api"), + negate_unsigned: cx.has_feature("negate_unsigned"), declared_stable_lang_features: accepted_features, declared_lib_features: unknown_features } @@ -761,9 +742,9 @@ pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast: } pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate) --> Features { + -> Features +{ check_crate_inner(cm, span_handler, krate, |ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx }, krate)) } - diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1fb0642d24..d4451cc7b7 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -40,7 +40,7 @@ impl MoveMap for Vec { for p in &mut self { unsafe { // FIXME(#5016) this shouldn't need to zero to be safe. - ptr::write(p, f(ptr::read_and_zero(p))); + ptr::write(p, f(ptr::read_and_drop(p))); } } self @@ -98,11 +98,11 @@ pub trait Folder : Sized { noop_fold_item_underscore(i, self) } - fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector { + fn fold_trait_item(&mut self, i: P) -> SmallVector> { noop_fold_trait_item(i, self) } - fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector { + fn fold_impl_item(&mut self, i: P) -> SmallVector> { noop_fold_impl_item(i, self) } @@ -110,14 +110,6 @@ pub trait Folder : Sized { noop_fold_fn_decl(d, self) } - fn fold_type_method(&mut self, m: TypeMethod) -> TypeMethod { - noop_fold_type_method(m, self) - } - - fn fold_method(&mut self, m: P) -> SmallVector> { - noop_fold_method(m, self) - } - fn fold_block(&mut self, b: P) -> P { noop_fold_block(b, self) } @@ -146,10 +138,6 @@ pub trait Folder : Sized { noop_fold_ty(t, self) } - fn fold_qpath(&mut self, t: P) -> P { - noop_fold_qpath(t, self) - } - fn fold_ty_binding(&mut self, t: P) -> P { noop_fold_ty_binding(t, self) } @@ -319,15 +307,6 @@ pub trait Folder : Sized { noop_fold_where_predicate(where_predicate, self) } - fn fold_typedef(&mut self, typedef: Typedef) -> Typedef { - noop_fold_typedef(typedef, self) - } - - fn fold_associated_type(&mut self, associated_type: AssociatedType) - -> AssociatedType { - noop_fold_associated_type(associated_type, self) - } - fn new_id(&mut self, i: NodeId) -> NodeId { i } @@ -428,17 +407,19 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), - TyPath(path, id) => { - let id = fld.new_id(id); - TyPath(fld.fold_path(path), id) + TyPath(qself, path) => { + let qself = qself.map(|QSelf { ty, position }| { + QSelf { + ty: fld.fold_ty(ty), + position: position + } + }); + TyPath(qself, fld.fold_path(path)) } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds)) } - TyQPath(qpath) => { - TyQPath(fld.fold_qpath(qpath)) - } TyFixedLengthVec(ty, e) => { TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e)) } @@ -453,19 +434,6 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { }) } -pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { - qpath.map(|qpath| { - QPath { - self_type: fld.fold_ty(qpath.self_type), - trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)), - item_path: PathSegment { - identifier: fld.fold_ident(qpath.item_path.identifier), - parameters: fld.fold_path_parameters(qpath.item_path.parameters), - } - } - }) -} - pub fn noop_fold_foreign_mod(ForeignMod {abi, items}: ForeignMod, fld: &mut T) -> ForeignMod { ForeignMod { @@ -844,41 +812,6 @@ pub fn noop_fold_where_predicate( } } -pub fn noop_fold_typedef(t: Typedef, folder: &mut T) - -> Typedef - where T: Folder { - let new_id = folder.new_id(t.id); - let new_span = folder.new_span(t.span); - let new_attrs = t.attrs.iter().flat_map(|attr| { - folder.fold_attribute((*attr).clone()).into_iter() - }).collect(); - let new_ident = folder.fold_ident(t.ident); - let new_type = folder.fold_ty(t.typ); - ast::Typedef { - ident: new_ident, - typ: new_type, - id: new_id, - span: new_span, - vis: t.vis, - attrs: new_attrs, - } -} - -pub fn noop_fold_associated_type(at: AssociatedType, folder: &mut T) - -> AssociatedType - where T: Folder -{ - let new_attrs = at.attrs - .iter() - .flat_map(|attr| folder.fold_attribute((*attr).clone()).into_iter()) - .collect(); - let new_param = folder.fold_ty_param(at.ty_param); - ast::AssociatedType { - attrs: new_attrs, - ty_param: new_param, - } -} - pub fn noop_fold_struct_def(struct_def: P, fld: &mut T) -> P { struct_def.map(|StructDef { fields, ctor_id }| StructDef { fields: fields.move_map(|f| fld.fold_struct_field(f)), @@ -999,6 +932,9 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { let struct_def = folder.fold_struct_def(struct_def); ItemStruct(struct_def, folder.fold_generics(generics)) } + ItemDefaultImpl(unsafety, ref trait_ref) => { + ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone())) + } ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => { let new_impl_items = impl_items.into_iter().flat_map(|item| { folder.fold_impl_item(item).into_iter() @@ -1030,61 +966,43 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ { } } -pub fn noop_fold_trait_item(i: TraitItem, folder: &mut T) -> SmallVector { - match i { - RequiredMethod(m) => { - SmallVector::one(RequiredMethod( - folder.fold_type_method(m))) - } - ProvidedMethod(method) => { - folder.fold_method(method).into_iter() - .map(|m| ProvidedMethod(m)).collect() - } - TypeTraitItem(at) => { - SmallVector::one(TypeTraitItem(P( - folder.fold_associated_type( - (*at).clone())))) - } - } -} - -pub fn noop_fold_impl_item(i: ImplItem, folder: &mut T) -> SmallVector { - match i { - MethodImplItem(ref x) => { - folder.fold_method((*x).clone()).into_iter().map(|m| MethodImplItem(m)).collect() - } - TypeImplItem(ref t) => { - SmallVector::one(TypeImplItem( - P(folder.fold_typedef((**t).clone())))) - } - } +pub fn noop_fold_trait_item(i: P, folder: &mut T) + -> SmallVector> { + SmallVector::one(i.map(|TraitItem {id, ident, attrs, node, span}| TraitItem { + id: folder.new_id(id), + ident: folder.fold_ident(ident), + attrs: fold_attrs(attrs, folder), + node: match node { + MethodTraitItem(sig, body) => { + MethodTraitItem(noop_fold_method_sig(sig, folder), + body.map(|x| folder.fold_block(x))) + } + TypeTraitItem(bounds, default) => { + TypeTraitItem(folder.fold_bounds(bounds), + default.map(|x| folder.fold_ty(x))) + } + }, + span: folder.new_span(span) + })) } -pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMethod { - let TypeMethod { - id, - ident, - attrs, - unsafety, - abi, - decl, - generics, - explicit_self, - vis, - span - } = m; - TypeMethod { - id: fld.new_id(id), - ident: fld.fold_ident(ident), - attrs: fold_attrs(attrs, fld), - unsafety: unsafety, - abi: abi, - decl: fld.fold_fn_decl(decl), - generics: fld.fold_generics(generics), - explicit_self: fld.fold_explicit_self(explicit_self), +pub fn noop_fold_impl_item(i: P, folder: &mut T) + -> SmallVector> { + SmallVector::one(i.map(|ImplItem {id, ident, attrs, node, vis, span}| ImplItem { + id: folder.new_id(id), + ident: folder.fold_ident(ident), + attrs: fold_attrs(attrs, folder), vis: vis, - span: fld.new_span(span) - } + node: match node { + MethodImplItem(sig, body) => { + MethodImplItem(noop_fold_method_sig(sig, folder), + folder.fold_block(body)) + } + TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty)), + MacImplItem(mac) => MacImplItem(folder.fold_mac(mac)) + }, + span: folder.new_span(span) + })) } pub fn noop_fold_mod(Mod {inner, items}: Mod, folder: &mut T) -> Mod { @@ -1150,7 +1068,7 @@ pub fn noop_fold_item_simple(Item {id, ident, attrs, node, vis, span} let ident = match node { // The node may have changed, recompute the "pretty" impl name. ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => { - ast_util::impl_pretty_name(maybe_trait, &**ty) + ast_util::impl_pretty_name(maybe_trait, Some(&**ty)) } _ => ident }; @@ -1183,34 +1101,14 @@ pub fn noop_fold_foreign_item(ni: P, folder: &mut T) -> }) } -// Default fold over a method. -// Invariant: produces exactly one method. -pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector> { - SmallVector::one(m.map(|Method {id, attrs, node, span}| Method { - id: folder.new_id(id), - attrs: fold_attrs(attrs, folder), - node: match node { - MethDecl(ident, - generics, - abi, - explicit_self, - unsafety, - decl, - body, - vis) => { - MethDecl(folder.fold_ident(ident), - folder.fold_generics(generics), - abi, - folder.fold_explicit_self(explicit_self), - unsafety, - folder.fold_fn_decl(decl), - folder.fold_block(body), - vis) - }, - MethMac(mac) => MethMac(folder.fold_mac(mac)), - }, - span: folder.new_span(span) - })) +pub fn noop_fold_method_sig(sig: MethodSig, folder: &mut T) -> MethodSig { + MethodSig { + generics: folder.fold_generics(sig.generics), + abi: sig.abi, + explicit_self: folder.fold_explicit_self(sig.explicit_self), + unsafety: sig.unsafety, + decl: folder.fold_fn_decl(sig.decl) + } } pub fn noop_fold_pat(p: P, folder: &mut T) -> P { @@ -1361,8 +1259,15 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> ExprRange(e1.map(|x| folder.fold_expr(x)), e2.map(|x| folder.fold_expr(x))) } - ExprPath(pth) => ExprPath(folder.fold_path(pth)), - ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)), + ExprPath(qself, path) => { + let qself = qself.map(|QSelf { ty, position }| { + QSelf { + ty: folder.fold_ty(ty), + position: position + } + }); + ExprPath(qself, folder.fold_path(path)) + } ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))), @@ -1437,7 +1342,7 @@ pub fn noop_fold_stmt(Spanned {node, span}: Stmt, folder: &mut T) #[cfg(test)] mod test { - use std::old_io; + use std::io; use ast; use util::parser_testing::{string_to_crate, matches_codepattern}; use parse::token; @@ -1447,7 +1352,7 @@ mod test { // this version doesn't care about getting comments or docstrings in. fn fake_print_crate(s: &mut pprust::State, - krate: &ast::Crate) -> old_io::IoResult<()> { + krate: &ast::Crate) -> io::Result<()> { s.print_mod(&krate.module, &krate.attrs) } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 3a7fa54edb..0980acd343 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -14,6 +14,8 @@ //! //! This API is completely unstable and subject to change. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "syntax"] #![unstable(feature = "rustc_private")] #![staged_api] @@ -27,16 +29,16 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(env)] -#![feature(int_uint)] -#![feature(old_io)] #![feature(libc)] #![feature(old_path)] #![feature(quote, unsafe_destructor)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(std_misc)] #![feature(unicode)] +#![feature(path_ext)] +#![feature(str_char)] +#![feature(into_cow)] +#![feature(slice_patterns)] extern crate arena; extern crate fmt_macros; @@ -46,7 +48,7 @@ extern crate libc; #[macro_use] extern crate log; #[macro_use] #[no_link] extern crate rustc_bitflags; -extern crate "serialize" as rustc_serialize; // used by deriving +extern crate serialize as rustc_serialize; // used by deriving pub mod util { pub mod interner; diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index f5201d4a8b..25f1f9b848 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -30,7 +30,7 @@ impl fmt::Debug for OwnedSlice { impl OwnedSlice { pub fn empty() -> OwnedSlice { - OwnedSlice { data: box [] } + OwnedSlice { data: Box::new([]) } } #[inline(never)] diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 06e8728d23..a5dd4f2222 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -19,9 +19,8 @@ use ptr::P; /// A parser that can parse attributes. pub trait ParserAttr { fn parse_outer_attributes(&mut self) -> Vec; + fn parse_inner_attributes(&mut self) -> Vec; fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute; - fn parse_inner_attrs_and_next(&mut self) - -> (Vec, Vec); fn parse_meta_item(&mut self) -> P; fn parse_meta_seq(&mut self) -> Vec>; fn parse_optional_meta(&mut self) -> Vec>; @@ -77,7 +76,7 @@ impl<'a> ParserAttr for Parser<'a> { self.span_err(span, "an inner attribute is not permitted in \ this context"); - self.span_help(span, + self.fileline_help(span, "place inner attribute at the top of the module or block"); } ast::AttrInner @@ -94,7 +93,7 @@ impl<'a> ParserAttr for Parser<'a> { } _ => { let token_str = self.this_token_to_string(); - self.fatal(&format!("expected `#`, found `{}`", token_str)[]); + self.fatal(&format!("expected `#`, found `{}`", token_str)); } }; @@ -118,45 +117,40 @@ impl<'a> ParserAttr for Parser<'a> { /// Parse attributes that appear after the opening of an item. These should /// be preceded by an exclamation mark, but we accept and warn about one - /// terminated by a semicolon. In addition to a vector of inner attributes, - /// this function also returns a vector that may contain the first outer - /// attribute of the next item (since we can't know whether the attribute - /// is an inner attribute of the containing item or an outer attribute of - /// the first contained item until we see the semi). - - /// matches inner_attrs* outer_attr? - /// you can make the 'next' field an Option, but the result is going to be - /// more useful as a vector. - fn parse_inner_attrs_and_next(&mut self) - -> (Vec , Vec ) { - let mut inner_attrs: Vec = Vec::new(); - let mut next_outer_attrs: Vec = Vec::new(); + /// terminated by a semicolon. + + /// matches inner_attrs* + fn parse_inner_attributes(&mut self) -> Vec { + let mut attrs: Vec = vec![]; loop { - let attr = match self.token { + match self.token { token::Pound => { - self.parse_attribute(true) + // Don't even try to parse if it's not an inner attribute. + if !self.look_ahead(1, |t| t == &token::Not) { + break; + } + + let attr = self.parse_attribute(true); + assert!(attr.node.style == ast::AttrInner); + attrs.push(attr); } token::DocComment(s) => { // we need to get the position of this token before we bump. let Span { lo, hi, .. } = self.span; - self.bump(); - attr::mk_sugared_doc_attr(attr::mk_attr_id(), - self.id_to_interned_str(s.ident()), - lo, - hi) - } - _ => { - break; + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), + self.id_to_interned_str(s.ident()), + lo, hi); + if attr.node.style == ast::AttrInner { + attrs.push(attr); + self.bump(); + } else { + break; + } } - }; - if attr.node.style == ast::AttrInner { - inner_attrs.push(attr); - } else { - next_outer_attrs.push(attr); - break; + _ => break } } - (inner_attrs, next_outer_attrs) + attrs } /// matches meta_item = IDENT diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 1f06db6002..277f5365db 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -19,9 +19,7 @@ use parse::lexer::is_block_doc_comment; use parse::lexer; use print::pprust; -use std::old_io; -use std::str; -use std::string::String; +use std::io::Read; use std::usize; #[derive(Clone, Copy, PartialEq)] @@ -92,7 +90,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { let mut first = true; for line in &lines { for (j, c) in line.chars().enumerate() { - if j > i || !"* \t".contains_char(c) { + if j > i || !"* \t".contains(c) { can_trim = false; break; } @@ -124,8 +122,8 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { } // one-line comments lose their prefix - static ONLINERS: &'static [&'static str] = &["///!", "///", "//!", "//"]; - for prefix in ONLINERS { + const ONELINERS: &'static [&'static str] = &["///!", "///", "//!", "//"]; + for prefix in ONELINERS { if comment.starts_with(*prefix) { return (&comment[prefix.len()..]).to_string(); } @@ -211,11 +209,11 @@ fn all_whitespace(s: &str, col: CharPos) -> Option { let mut col = col.to_usize(); let mut cursor: usize = 0; while col > 0 && cursor < len { - let r: str::CharRange = s.char_range_at(cursor); - if !r.ch.is_whitespace() { + let ch = s.char_at(cursor); + if !ch.is_whitespace() { return None; } - cursor = r.next; + cursor += ch.len_utf8(); col -= 1; } return Some(cursor); @@ -264,7 +262,7 @@ fn read_block_comment(rdr: &mut StringReader, if is_block_doc_comment(&curr_line[..]) { return } - assert!(!curr_line.contains_char('\n')); + assert!(!curr_line.contains('\n')); lines.push(curr_line); } else { let mut level: isize = 1; @@ -337,9 +335,10 @@ pub struct Literal { // probably not a good thing. pub fn gather_comments_and_literals(span_diagnostic: &diagnostic::SpanHandler, path: String, - srdr: &mut old_io::Reader) + srdr: &mut Read) -> (Vec, Vec) { - let src = srdr.read_to_end().unwrap(); + let mut src = Vec::new(); + srdr.read_to_end(&mut src).unwrap(); let src = String::from_utf8(src).unwrap(); let cm = CodeMap::new(); let filemap = cm.new_filemap(path, src); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index fd08cbd161..78470f0020 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -14,15 +14,13 @@ use codemap; use diagnostic::SpanHandler; use ext::tt::transcribe::tt_next_token; use parse::token; -use parse::token::{str_to_ident}; +use parse::token::str_to_ident; use std::borrow::{IntoCow, Cow}; use std::char; use std::fmt; use std::mem::replace; -use std::num; use std::rc::Rc; -use std::str; pub use ext::tt::transcribe::{TtReader, new_tt_reader, new_tt_reader_with_doc_flag}; @@ -76,6 +74,10 @@ pub struct StringReader<'a> { // are revised to go directly to token-trees. /// Is \x00,\x00 is interpreted as encoded ast::Ident? read_embedded_ident: bool, + + // cache a direct reference to the source text, so that we don't have to + // retrieve it via `self.filemap.src.as_ref().unwrap()` all the time. + source_text: Rc } impl<'a> Reader for StringReader<'a> { @@ -141,7 +143,14 @@ pub fn make_reader_with_embedded_idents<'b>(span_diagnostic: &'b SpanHandler, impl<'a> StringReader<'a> { /// For comments.rs, which hackily pokes into pos and curr pub fn new_raw<'b>(span_diagnostic: &'b SpanHandler, - filemap: Rc) -> StringReader<'b> { + filemap: Rc) -> StringReader<'b> { + if filemap.src.is_none() { + span_diagnostic.handler.bug(&format!("Cannot lex filemap without source: {}", + filemap.name)[..]); + } + + let source_text = (*filemap.src.as_ref().unwrap()).clone(); + let mut sr = StringReader { span_diagnostic: span_diagnostic, pos: filemap.start_pos, @@ -153,6 +162,7 @@ impl<'a> StringReader<'a> { peek_tok: token::Eof, peek_span: codemap::DUMMY_SP, read_embedded_ident: false, + source_text: source_text }; sr.bump(); sr @@ -213,7 +223,7 @@ impl<'a> StringReader<'a> { m.push_str(": "); let from = self.byte_offset(from_pos).to_usize(); let to = self.byte_offset(to_pos).to_usize(); - m.push_str(&self.filemap.src[from..to]); + m.push_str(&self.source_text[from..to]); self.fatal_span_(from_pos, to_pos, &m[..]); } @@ -270,9 +280,8 @@ impl<'a> StringReader<'a> { fn with_str_from_to(&self, start: BytePos, end: BytePos, f: F) -> T where F: FnOnce(&str) -> T, { - f(&self.filemap.src[ - self.byte_offset(start).to_usize().. - self.byte_offset(end).to_usize()]) + f(&self.source_text[self.byte_offset(start).to_usize().. + self.byte_offset(end).to_usize()]) } /// Converts CRLF to LF in the given string, raising an error on bare CR. @@ -280,7 +289,8 @@ impl<'a> StringReader<'a> { s: &'b str, errmsg: &'b str) -> Cow<'b, str> { let mut i = 0; while i < s.len() { - let str::CharRange { ch, next } = s.char_range_at(i); + let ch = s.char_at(i); + let next = i + ch.len_utf8(); if ch == '\r' { if next < s.len() && s.char_at(next) == '\n' { return translate_crlf_(self, start, s, errmsg, i).into_cow(); @@ -298,7 +308,8 @@ impl<'a> StringReader<'a> { let mut buf = String::with_capacity(s.len()); let mut j = 0; while i < s.len() { - let str::CharRange { ch, next } = s.char_range_at(i); + let ch = s.char_at(i); + let next = i + ch.len_utf8(); if ch == '\r' { if j < i { buf.push_str(&s[j..i]); } j = next; @@ -321,15 +332,14 @@ impl<'a> StringReader<'a> { pub fn bump(&mut self) { self.last_pos = self.pos; let current_byte_offset = self.byte_offset(self.pos).to_usize(); - if current_byte_offset < self.filemap.src.len() { + if current_byte_offset < self.source_text.len() { assert!(self.curr.is_some()); let last_char = self.curr.unwrap(); - let next = self.filemap - .src - .char_range_at(current_byte_offset); - let byte_offset_diff = next.next - current_byte_offset; + let ch = self.source_text.char_at(current_byte_offset); + let next = current_byte_offset + ch.len_utf8(); + let byte_offset_diff = next - current_byte_offset; self.pos = self.pos + Pos::from_usize(byte_offset_diff); - self.curr = Some(next.ch); + self.curr = Some(ch); self.col = self.col + CharPos(1); if last_char == '\n' { self.filemap.next_line(self.last_pos); @@ -346,8 +356,8 @@ impl<'a> StringReader<'a> { pub fn nextch(&self) -> Option { let offset = self.byte_offset(self.pos).to_usize(); - if offset < self.filemap.src.len() { - Some(self.filemap.src.char_at(offset)) + if offset < self.source_text.len() { + Some(self.source_text.char_at(offset)) } else { None } @@ -359,9 +369,9 @@ impl<'a> StringReader<'a> { pub fn nextnextch(&self) -> Option { let offset = self.byte_offset(self.pos).to_usize(); - let s = &*self.filemap.src; + let s = &self.source_text[..]; if offset >= s.len() { return None } - let str::CharRange { next, .. } = s.char_range_at(offset); + let next = offset + s.char_at(offset).len_utf8(); if next < s.len() { Some(s.char_at(next)) } else { @@ -610,9 +620,9 @@ impl<'a> StringReader<'a> { let base = 10; // find the integer representing the name - self.scan_digits(base); + self.scan_digits(base, base); let encoded_name : u32 = self.with_str_from(start_bpos, |s| { - num::from_str_radix(s, 10).ok().unwrap_or_else(|| { + u32::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]", s, whence, start_bpos, self.last_pos); }) @@ -628,9 +638,9 @@ impl<'a> StringReader<'a> { // find the integer representing the ctxt let start_bpos = self.last_pos; - self.scan_digits(base); + self.scan_digits(base, base); let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| { - num::from_str_radix(s, 10).ok().unwrap_or_else(|| { + u32::from_str_radix(s, 10).unwrap_or_else(|_| { panic!("expected digits representing a ctxt, got {:?}, {}", s, whence); }) }); @@ -642,16 +652,28 @@ impl<'a> StringReader<'a> { ctxt: encoded_ctxt, } } - /// Scan through any digits (base `radix`) or underscores, and return how - /// many digits there were. - fn scan_digits(&mut self, radix: u32) -> usize { + /// Scan through any digits (base `scan_radix`) or underscores, + /// and return how many digits there were. + /// + /// `real_radix` represents the true radix of the number we're + /// interested in, and errors will be emitted for any digits + /// between `real_radix` and `scan_radix`. + fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize { + assert!(real_radix <= scan_radix); let mut len = 0; loop { let c = self.curr; if c == Some('_') { debug!("skipping a _"); self.bump(); continue; } - match c.and_then(|cc| cc.to_digit(radix)) { + match c.and_then(|cc| cc.to_digit(scan_radix)) { Some(_) => { debug!("{:?} in scan_digits", c); + // check that the hypothetical digit is actually + // in range for the true radix + if c.unwrap().to_digit(real_radix).is_none() { + self.err_span_(self.last_pos, self.pos, + &format!("invalid digit for a base {} literal", + real_radix)); + } len += 1; self.bump(); } @@ -670,11 +692,11 @@ impl<'a> StringReader<'a> { if c == '0' { match self.curr.unwrap_or('\0') { - 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2); } - 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8); } - 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16); } + 'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2, 10); } + 'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8, 10); } + 'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16, 16); } '0'...'9' | '_' | '.' => { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } _ => { // just a 0 @@ -682,7 +704,7 @@ impl<'a> StringReader<'a> { } } } else if c.is_digit(10) { - num_digits = self.scan_digits(10) + 1; + num_digits = self.scan_digits(10, 10) + 1; } else { num_digits = 0; } @@ -701,7 +723,7 @@ impl<'a> StringReader<'a> { // with a number self.bump(); if self.curr.unwrap_or('\0').is_digit(10) { - self.scan_digits(10); + self.scan_digits(10, 10); self.scan_float_exponent(); } let last_pos = self.last_pos; @@ -731,6 +753,7 @@ impl<'a> StringReader<'a> { let start_bpos = self.last_pos; let mut accum_int = 0; + let mut valid = true; for _ in 0..n_digits { if self.is_eof() { let last_bpos = self.last_pos; @@ -739,6 +762,7 @@ impl<'a> StringReader<'a> { if self.curr_is(delim) { let last_bpos = self.last_pos; self.err_span_(start_bpos, last_bpos, "numeric character escape is too short"); + valid = false; break; } let c = self.curr.unwrap_or('\x00'); @@ -746,8 +770,10 @@ impl<'a> StringReader<'a> { accum_int += c.to_digit(16).unwrap_or_else(|| { self.err_span_char(self.last_pos, self.pos, "illegal character in numeric character escape", c); + + valid = false; 0 - }) as u32; + }); self.bump(); } @@ -756,10 +782,11 @@ impl<'a> StringReader<'a> { self.last_pos, "this form of character escape may only be used \ with characters in the range [\\x00-\\x7f]"); + valid = false; } match char::from_u32(accum_int) { - Some(_) => true, + Some(_) => valid, None => { let last_bpos = self.last_pos; self.err_span_(start_bpos, last_bpos, "illegal numeric character escape"); @@ -768,13 +795,6 @@ impl<'a> StringReader<'a> { } } - fn old_escape_warning(&mut self, sp: Span) { - self.span_diagnostic - .span_warn(sp, "\\U00ABCD12 and \\uABCD escapes are deprecated"); - self.span_diagnostic - .span_help(sp, "use \\u{ABCD12} escapes instead"); - } - /// Scan for a single (possibly escaped) byte or char /// in a byte, (non-raw) byte string, char, or (non-raw) string literal. /// `start` is the position of `first_source_char`, which is already consumed. @@ -794,21 +814,19 @@ impl<'a> StringReader<'a> { return match e { 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0' => true, 'x' => self.scan_byte_escape(delim, !ascii_only), - 'u' if !ascii_only => { - if self.curr == Some('{') { - self.scan_unicode_escape(delim) - } else { - let res = self.scan_hex_digits(4, delim, false); - let sp = codemap::mk_sp(escaped_pos, self.last_pos); - self.old_escape_warning(sp); - res - } + 'u' if self.curr_is('{') => { + let valid = self.scan_unicode_escape(delim); + if valid && ascii_only { + self.err_span_( + escaped_pos, + self.last_pos, + "unicode escape sequences cannot be used as a byte or in \ + a byte string" + ); + false + } else { + valid } - 'U' if !ascii_only => { - let res = self.scan_hex_digits(8, delim, false); - let sp = codemap::mk_sp(escaped_pos, self.last_pos); - self.old_escape_warning(sp); - res } '\n' if delim == '"' => { self.consume_whitespace(); @@ -878,6 +896,7 @@ impl<'a> StringReader<'a> { let start_bpos = self.last_pos; let mut count = 0; let mut accum_int = 0; + let mut valid = true; while !self.curr_is('}') && count <= 6 { let c = match self.curr { @@ -893,29 +912,30 @@ impl<'a> StringReader<'a> { self.fatal_span_(self.last_pos, self.pos, "unterminated unicode escape (needed a `}`)"); } else { - self.fatal_span_char(self.last_pos, self.pos, + self.err_span_char(self.last_pos, self.pos, "illegal character in unicode escape", c); } - }) as u32; + valid = false; + 0 + }); self.bump(); count += 1; } if count > 6 { - self.fatal_span_(start_bpos, self.last_pos, + self.err_span_(start_bpos, self.last_pos, "overlong unicode escape (can have at most 6 hex digits)"); + valid = false; } self.bump(); // past the ending } - let mut valid = count >= 1 && count <= 6; - if char::from_u32(accum_int).is_none() { - valid = false; + if valid && (char::from_u32(accum_int).is_none() || count == 0) { + self.err_span_(start_bpos, self.last_pos, "illegal unicode character escape"); + valid= false; } - if !valid { - self.fatal_span_(start_bpos, self.last_pos, "illegal unicode character escape"); - } + valid } @@ -926,7 +946,7 @@ impl<'a> StringReader<'a> { if self.curr_is('-') || self.curr_is('+') { self.bump(); } - if self.scan_digits(10) == 0 { + if self.scan_digits(10, 10) == 0 { self.err_span_(self.last_pos, self.pos, "expected at least one digit in exponent") } } @@ -1109,7 +1129,7 @@ impl<'a> StringReader<'a> { // expansion purposes. See #12512 for the gory details of why // this is necessary. let ident = self.with_str_from(start, |lifetime_name| { - str_to_ident(&format!("'{}", lifetime_name)[]) + str_to_ident(&format!("'{}", lifetime_name)) }); // Conjure up a "keyword checking ident" to make sure that @@ -1339,7 +1359,7 @@ impl<'a> StringReader<'a> { "unterminated byte constant".to_string()); } - let id = if valid { self.name_from(start) } else { token::intern("??") }; + let id = if valid { self.name_from(start) } else { token::intern("?") }; self.bump(); // advance curr past token return token::Byte(id); } @@ -1481,11 +1501,12 @@ mod test { use diagnostic; use parse::token; use parse::token::{str_to_ident}; - use std::old_io::util; + use std::io; fn mk_sh() -> diagnostic::SpanHandler { - let emitter = diagnostic::EmitterWriter::new(box util::NullWriter, None); - let handler = diagnostic::mk_handler(true, box emitter); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let emitter = diagnostic::EmitterWriter::new(Box::new(io::sink()), None); + let handler = diagnostic::mk_handler(true, Box::new(emitter)); diagnostic::mk_span_handler(handler, CodeMap::new()) } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 7ed48bdbb9..f59e1d8214 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -18,11 +18,14 @@ use parse::parser::Parser; use ptr::P; use std::cell::{Cell, RefCell}; -use std::old_io::File; -use std::rc::Rc; +use std::fs::File; +use std::io::Read; +use std::iter; +#[allow(deprecated)] // Int use std::num::Int; +use std::path::{Path, PathBuf}; +use std::rc::Rc; use std::str; -use std::iter; #[macro_use] pub mod parser; @@ -39,7 +42,7 @@ pub mod obsolete; pub struct ParseSess { pub span_diagnostic: SpanHandler, // better be the same as the one in the reader! /// Used to determine and report recursive mod inclusions - included_mod_stack: RefCell>, + included_mod_stack: RefCell>, pub node_id: Cell, } @@ -94,9 +97,7 @@ pub fn parse_crate_attrs_from_file( cfg: ast::CrateConfig, sess: &ParseSess ) -> Vec { - let mut parser = new_parser_from_file(sess, cfg, input); - let (inner, _) = parser.parse_inner_attrs_and_next(); - inner + new_parser_from_file(sess, cfg, input).parse_inner_attributes() } pub fn parse_crate_from_source_str(name: String, @@ -120,8 +121,7 @@ pub fn parse_crate_attrs_from_source_str(name: String, cfg, name, source); - let (inner, _) = maybe_aborted(p.parse_inner_attrs_and_next(),p); - inner + maybe_aborted(p.parse_inner_attributes(), p) } pub fn parse_expr_from_source_str(name: String, @@ -139,7 +139,7 @@ pub fn parse_item_from_source_str(name: String, sess: &ParseSess) -> Option> { let mut p = new_parser_from_source_str(sess, cfg, name, source); - maybe_aborted(p.parse_item_with_outer_attributes(),p) + maybe_aborted(p.parse_item(),p) } pub fn parse_meta_from_source_str(name: String, @@ -154,16 +154,15 @@ pub fn parse_meta_from_source_str(name: String, pub fn parse_stmt_from_source_str(name: String, source: String, cfg: ast::CrateConfig, - attrs: Vec , sess: &ParseSess) - -> P { + -> Option> { let mut p = new_parser_from_source_str( sess, cfg, name, source ); - maybe_aborted(p.parse_stmt(attrs),p) + maybe_aborted(p.parse_stmt(), p) } // Note: keep in sync with `with_hygiene::parse_tts_from_source_str` @@ -250,24 +249,24 @@ pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) None => sess.span_diagnostic.handler().fatal(msg), } }; - let bytes = match File::open(path).read_to_end() { - Ok(bytes) => bytes, + let mut bytes = Vec::new(); + match File::open(path).and_then(|mut f| f.read_to_end(&mut bytes)) { + Ok(..) => {} Err(e) => { - err(&format!("couldn't read {:?}: {}", - path.display(), e)[]); - unreachable!() + err(&format!("couldn't read {:?}: {}", path.display(), e)); + unreachable!(); } }; match str::from_utf8(&bytes[..]).ok() { Some(s) => { - return string_to_filemap(sess, s.to_string(), - path.as_str().unwrap().to_string()) + string_to_filemap(sess, s.to_string(), + path.to_str().unwrap().to_string()) } None => { - err(&format!("{:?} is not UTF-8 encoded", path.display())[]) + err(&format!("{:?} is not UTF-8 encoded", path.display())); + unreachable!(); } } - unreachable!() } /// Given a session and a string, add the string to @@ -374,7 +373,7 @@ pub fn maybe_aborted(result: T, p: Parser) -> T { /// well. Can take any slice prefixed by a character escape. Returns the /// character and the number of characters consumed. pub fn char_lit(lit: &str) -> (char, isize) { - use std::{num, char}; + use std::char; let mut chars = lit.chars(); let c = match (chars.next(), chars.next()) { @@ -401,21 +400,22 @@ pub fn char_lit(lit: &str) -> (char, isize) { let msg2 = &msg[..]; fn esc(len: usize, lit: &str) -> Option<(char, isize)> { - num::from_str_radix(&lit[2..len], 16).ok() + u32::from_str_radix(&lit[2..len], 16).ok() .and_then(char::from_u32) .map(|x| (x, len as isize)) } - let unicode_escape = || -> Option<(char, isize)> + let unicode_escape = || -> Option<(char, isize)> { if lit.as_bytes()[2] == b'{' { let idx = lit.find('}').expect(msg2); let subslice = &lit[3..idx]; - num::from_str_radix(subslice, 16).ok() + u32::from_str_radix(subslice, 16).ok() .and_then(char::from_u32) .map(|x| (x, subslice.chars().count() as isize + 4)) } else { esc(6, lit) - }; + } + }; // Unicode escapes return match lit.as_bytes()[1] as char { @@ -583,7 +583,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) { b'\'' => b'\'', b'0' => b'\0', _ => { - match ::std::num::from_str_radix::(&lit[2..4], 16).ok() { + match u64::from_str_radix(&lit[2..4], 16).ok() { Some(c) => if c > 0xFF { panic!(err(2)) @@ -701,18 +701,18 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> if let Some(suf) = suffix { if suf.is_empty() { sd.span_bug(sp, "found empty literal suffix in Some")} ty = match suf { - "isize" => ast::SignedIntLit(ast::TyIs(false), ast::Plus), + "isize" => ast::SignedIntLit(ast::TyIs, ast::Plus), "i8" => ast::SignedIntLit(ast::TyI8, ast::Plus), "i16" => ast::SignedIntLit(ast::TyI16, ast::Plus), "i32" => ast::SignedIntLit(ast::TyI32, ast::Plus), "i64" => ast::SignedIntLit(ast::TyI64, ast::Plus), - "usize" => ast::UnsignedIntLit(ast::TyUs(false)), + "usize" => ast::UnsignedIntLit(ast::TyUs), "u8" => ast::UnsignedIntLit(ast::TyU8), "u16" => ast::UnsignedIntLit(ast::TyU16), "u32" => ast::UnsignedIntLit(ast::TyU32), "u64" => ast::UnsignedIntLit(ast::TyU64), - "i" | "is" => ast::SignedIntLit(ast::TyIs(true), ast::Plus), - "u" | "us" => ast::UnsignedIntLit(ast::TyUs(true)), + "is" => ast::SignedIntLit(ast::TyIs, ast::Plus), + "us" => ast::UnsignedIntLit(ast::TyUs), _ => { // i and u look like widths, so lets // give an error message along those lines @@ -722,7 +722,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> &suf[1..])); } else { sd.span_err(sp, &*format!("illegal suffix `{}` for numeric literal", suf)); - sd.span_help(sp, "the suffix must be one of the integral types \ + sd.fileline_help(sp, "the suffix must be one of the integral types \ (`u32`, `isize`, etc)"); } @@ -734,9 +734,22 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); - let res: u64 = match ::std::num::from_str_radix(s, base).ok() { + let res = match u64::from_str_radix(s, base).ok() { Some(r) => r, - None => { sd.span_err(sp, "int literal is too large"); 0 } + None => { + // small bases are lexed as if they were base 10, e.g, the string + // might be `0b10201`. This will cause the conversion above to fail, + // but these cases have errors in the lexer: we don't want to emit + // two errors, and we especially don't want to emit this error since + // it isn't necessarily true. + let already_errored = base < 10 && + s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); + + if !already_errored { + sd.span_err(sp, "int literal is too large"); + } + 0 + } }; // adjust the sign @@ -751,7 +764,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> #[cfg(test)] mod test { use super::*; - use serialize::json; + use std::rc::Rc; use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION}; use owned_slice::OwnedSlice; use ast; @@ -774,7 +787,7 @@ mod test { assert!(string_to_expr("a".to_string()) == P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 1), global: false, segments: vec!( @@ -792,7 +805,7 @@ mod test { assert!(string_to_expr("::a::b".to_string()) == P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span: sp(0, 6), global: true, segments: vec!( @@ -810,7 +823,7 @@ mod test { })) } - #[should_fail] + #[should_panic] #[test] fn bad_path_expr_1() { string_to_expr("::abc::def::return".to_string()); } @@ -827,19 +840,19 @@ mod test { ast::TtDelimited(_, ref macro_delimed)] if name_macro_rules.as_str() == "macro_rules" && name_zip.as_str() == "zip" => { - match ¯o_delimed.tts[] { + match ¯o_delimed.tts[..] { [ast::TtDelimited(_, ref first_delimed), ast::TtToken(_, token::FatArrow), ast::TtDelimited(_, ref second_delimed)] if macro_delimed.delim == token::Paren => { - match &first_delimed.tts[] { + match &first_delimed.tts[..] { [ast::TtToken(_, token::Dollar), ast::TtToken(_, token::Ident(name, token::Plain))] if first_delimed.delim == token::Paren && name.as_str() == "a" => {}, _ => panic!("value 3: {:?}", **first_delimed), } - match &second_delimed.tts[] { + match &second_delimed.tts[..] { [ast::TtToken(_, token::Dollar), ast::TtToken(_, token::Ident(name, token::Plain))] if second_delimed.delim == token::Paren @@ -855,117 +868,50 @@ mod test { } #[test] - fn string_to_tts_1 () { + fn string_to_tts_1() { let tts = string_to_tts("fn a (b : i32) { b; }".to_string()); - assert_eq!(json::encode(&tts).unwrap(), - "[\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - {\ - \"variant\":\"Ident\",\ - \"fields\":[\ - \"fn\",\ - \"Plain\"\ - ]\ - }\ - ]\ - },\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - {\ - \"variant\":\"Ident\",\ - \"fields\":[\ - \"a\",\ - \"Plain\"\ - ]\ - }\ - ]\ - },\ - {\ - \"variant\":\"TtDelimited\",\ - \"fields\":[\ - null,\ - {\ - \"delim\":\"Paren\",\ - \"open_span\":null,\ - \"tts\":[\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - {\ - \"variant\":\"Ident\",\ - \"fields\":[\ - \"b\",\ - \"Plain\"\ - ]\ - }\ - ]\ - },\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - \"Colon\"\ - ]\ - },\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - {\ - \"variant\":\"Ident\",\ - \"fields\":[\ - \"i32\",\ - \"Plain\"\ - ]\ - }\ - ]\ - }\ - ],\ - \"close_span\":null\ - }\ - ]\ - },\ - {\ - \"variant\":\"TtDelimited\",\ - \"fields\":[\ - null,\ - {\ - \"delim\":\"Brace\",\ - \"open_span\":null,\ - \"tts\":[\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - {\ - \"variant\":\"Ident\",\ - \"fields\":[\ - \"b\",\ - \"Plain\"\ - ]\ - }\ - ]\ - },\ - {\ - \"variant\":\"TtToken\",\ - \"fields\":[\ - null,\ - \"Semi\"\ - ]\ - }\ - ],\ - \"close_span\":null\ - }\ - ]\ - }\ -]" - ); + + let expected = vec![ + ast::TtToken(sp(0, 2), + token::Ident(str_to_ident("fn"), + token::IdentStyle::Plain)), + ast::TtToken(sp(3, 4), + token::Ident(str_to_ident("a"), + token::IdentStyle::Plain)), + ast::TtDelimited( + sp(5, 14), + Rc::new(ast::Delimited { + delim: token::DelimToken::Paren, + open_span: sp(5, 6), + tts: vec![ + ast::TtToken(sp(6, 7), + token::Ident(str_to_ident("b"), + token::IdentStyle::Plain)), + ast::TtToken(sp(8, 9), + token::Colon), + ast::TtToken(sp(10, 13), + token::Ident(str_to_ident("i32"), + token::IdentStyle::Plain)), + ], + close_span: sp(13, 14), + })), + ast::TtDelimited( + sp(15, 21), + Rc::new(ast::Delimited { + delim: token::DelimToken::Brace, + open_span: sp(15, 16), + tts: vec![ + ast::TtToken(sp(17, 18), + token::Ident(str_to_ident("b"), + token::IdentStyle::Plain)), + ast::TtToken(sp(18, 19), + token::Semi) + ], + close_span: sp(20, 21), + })) + ]; + + assert_eq!(tts, expected); } #[test] fn ret_expr() { @@ -974,7 +920,7 @@ mod test { id: ast::DUMMY_NODE_ID, node:ast::ExprRet(Some(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node:ast::ExprPath(ast::Path{ + node:ast::ExprPath(None, ast::Path{ span: sp(7, 8), global: false, segments: vec!( @@ -995,7 +941,7 @@ mod test { P(Spanned{ node: ast::StmtExpr(P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprPath(ast::Path { + node: ast::ExprPath(None, ast::Path { span:sp(0,1), global:false, segments: vec!( @@ -1041,7 +987,7 @@ mod test { node: ast::ItemFn(P(ast::FnDecl { inputs: vec!(ast::Arg{ ty: P(ast::Ty{id: ast::DUMMY_NODE_ID, - node: ast::TyPath(ast::Path{ + node: ast::TyPath(None, ast::Path{ span:sp(10,13), global:false, segments: vec!( @@ -1051,7 +997,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, ast::DUMMY_NODE_ID), + }), span:sp(10,13) }), pat: P(ast::Pat { @@ -1084,7 +1030,7 @@ mod test { stmts: vec!(P(Spanned{ node: ast::StmtSemi(P(ast::Expr{ id: ast::DUMMY_NODE_ID, - node: ast::ExprPath( + node: ast::ExprPath(None, ast::Path{ span:sp(17,18), global:false, @@ -1128,7 +1074,7 @@ mod test { let vitem_s = item_to_string(&*vitem); assert_eq!(&vitem_s[..], ex_s); - let ex_s = "extern crate \"foo\" as bar;"; + let ex_s = "extern crate foo as bar;"; let vitem = string_to_item(ex_s.to_string()).unwrap(); let vitem_s = item_to_string(&*vitem); assert_eq!(&vitem_s[..], ex_s); @@ -1207,7 +1153,7 @@ mod test { let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap(); - let docs = item.attrs.iter().filter(|a| &a.name()[] == "doc") + let docs = item.attrs.iter().filter(|a| &*a.name() == "doc") .map(|a| a.value_str().unwrap().to_string()).collect::>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; assert_eq!(&docs[..], b); diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 8480772ce6..f120dde8e1 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -20,15 +20,10 @@ use parse::token; use ptr::P; /// The specific types of unsupported syntax -#[derive(Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { - Sized, - ForSized, - ProcType, - ProcExpr, - ClosureType, ClosureKind, - EmptyIndex, + ExternCrateString, } pub trait ParserObsoleteMethods { @@ -51,40 +46,14 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { let (kind_str, desc, error) = match kind { - ObsoleteSyntax::ForSized => ( - "for Sized?", - "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \ - by default", - true, - ), - ObsoleteSyntax::ProcType => ( - "the `proc` type", - "use unboxed closures instead", - true, - ), - ObsoleteSyntax::ProcExpr => ( - "`proc` expression", - "use a `move ||` expression instead", - true, - ), - ObsoleteSyntax::ClosureType => ( - "`|usize| -> bool` closure type", - "use unboxed closures instead, no type annotation needed", - true, - ), ObsoleteSyntax::ClosureKind => ( "`:`, `&mut:`, or `&:`", "rely on inference instead", true, ), - ObsoleteSyntax::Sized => ( - "`Sized? T` for removing the `Sized` bound", - "write `T: ?Sized` instead", - true, - ), - ObsoleteSyntax::EmptyIndex => ( - "[]", - "write `[..]` instead", + ObsoleteSyntax::ExternCrateString => ( + "\"crate-name\"", + "use an identifier not in quotes instead", false, // warning for now ), }; @@ -106,16 +75,16 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { desc: &str, error: bool) { if error { - self.span_err(sp, &format!("obsolete syntax: {}", kind_str)[]); + self.span_err(sp, &format!("obsolete syntax: {}", kind_str)); } else { - self.span_warn(sp, &format!("obsolete syntax: {}", kind_str)[]); + self.span_warn(sp, &format!("obsolete syntax: {}", kind_str)); } if !self.obsolete_set.contains(&kind) { self.sess .span_diagnostic .handler() - .note(&format!("{}", desc)[]); + .note(&format!("{}", desc)); self.obsolete_set.insert(kind); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 370201e538..c721624323 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -11,9 +11,9 @@ pub use self::PathParsingMode::*; use abi; -use ast::{AssociatedType, BareFnTy}; +use ast::BareFnTy; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; -use ast::{ProvidedMethod, Public, Unsafety}; +use ast::{Public, Unsafety}; use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue}; use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, BiGt, Block}; use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause}; @@ -25,25 +25,24 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex}; use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath}; +use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; -use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; +use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefaultImpl}; use ast::{ItemExternCrate, ItemUse}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitStr, LitInt, Local, LocalLet}; use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource}; -use ast::{Method, MutTy, BiMul, Mutability}; -use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; +use ast::{MutTy, BiMul, Mutability}; +use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; -use ast::{PolyTraitRef}; -use ast::{QPath, RequiredMethod}; +use ast::{PolyTraitRef, QSelf}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; use ast::{StructVariantKind, BiSub, StrStyle}; @@ -51,11 +50,10 @@ use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; -use ast::{TyFixedLengthVec, TyBareFn}; -use ast::{TyTypeof, TyInfer, TypeMethod}; -use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; +use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer}; +use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; -use ast::{TypeImplItem, TypeTraitItem, Typedef,}; +use ast::{TypeImplItem, TypeTraitItem}; use ast::{UnnamedField, UnsafeBlock}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; @@ -78,10 +76,9 @@ use ptr::P; use owned_slice::OwnedSlice; use std::collections::HashSet; -use std::old_io::fs::PathExtensions; -use std::iter; +use std::io::prelude::*; use std::mem; -use std::num::Float; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::slice; @@ -99,7 +96,7 @@ type ItemInfo = (Ident, Item_, Option >); /// How to parse a path. There are four different kinds of paths, all of which /// are parsed somewhat differently. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum PathParsingMode { /// A path with no type parameters; e.g. `foo::bar::Baz` NoTypesAllowed, @@ -112,17 +109,12 @@ pub enum PathParsingMode { } /// How to parse a bound, whether to allow bound modifiers such as `?`. -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum BoundParsingMode { Bare, Modified, } -/// The `Err` case indicates a failure to parse any kind of item. -/// The attributes are returned. -type MaybeItem = Result, Vec>; - - /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression /// dropped into the token stream, which happens while parsing the result of /// macro expansion). Placement of these is not as complex as I feared it would @@ -143,7 +135,7 @@ macro_rules! maybe_whole_expr { _ => unreachable!() }; let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprPath(pt))) + Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt))) } token::Interpolated(token::NtBlock(_)) => { // FIXME: The following avoids an issue with lexical borrowck scopes, @@ -209,7 +201,7 @@ macro_rules! maybe_whole { } } ); - (Some $p:expr, $constructor:ident) => ( + (Some deref $p:expr, $constructor:ident) => ( { let found = match ($p).token { token::Interpolated(token::$constructor(_)) => { @@ -218,7 +210,7 @@ macro_rules! maybe_whole { _ => None }; if let Some(token::Interpolated(token::$constructor(x))) = found { - return Some(x.clone()); + return Some((*x).clone()); } } ); @@ -524,11 +516,7 @@ impl<'a> Parser<'a> { pub fn parse_path_list_item(&mut self) -> ast::PathListItem { let lo = self.span.lo; - let node = if self.eat_keyword_noexpect(keywords::Mod) { - let span = self.last_span; - self.span_warn(span, "deprecated syntax; use the `self` keyword now"); - ast::PathListMod { id: ast::DUMMY_NODE_ID } - } else if self.eat_keyword(keywords::SelfValue) { + let node = if self.eat_keyword(keywords::SelfValue) { ast::PathListMod { id: ast::DUMMY_NODE_ID } } else { let ident = self.parse_ident(); @@ -627,23 +615,6 @@ impl<'a> Parser<'a> { } } - /// Expect and consume a `|`. If `||` is seen, replace it with a single - /// `|` and continue. If a `|` is not seen, signal an error. - fn expect_or(&mut self) { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or))); - match self.token { - token::BinOp(token::Or) => self.bump(), - token::OrOr => { - let span = self.span; - let lo = span.lo + BytePos(1); - self.replace_token(token::BinOp(token::Or), lo, span.hi) - } - _ => { - self.expect_one_of(&[], &[]); - } - } - } - pub fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { match suffix { None => {/* everything ok */} @@ -683,28 +654,6 @@ impl<'a> Parser<'a> { } } - /// Parse a sequence bracketed by `|` and `|`, stopping before the `|`. - fn parse_seq_to_before_or(&mut self, - sep: &token::Token, - mut f: F) - -> Vec where - F: FnMut(&mut Parser) -> T, - { - let mut first = true; - let mut vector = Vec::new(); - while self.token != token::BinOp(token::Or) && - self.token != token::OrOr { - if first { - first = false - } else { - self.expect(sep) - } - - vector.push(f(self)) - } - vector - } - /// Expect and consume a GT. if a >> is seen, replace it /// with a single > and continue. If a GT is not seen, /// signal an error. @@ -750,7 +699,7 @@ impl<'a> Parser<'a> { // would encounter a `>` and stop. This lets the parser handle trailing // commas in generic parameters, because it can stop either after // parsing a type or after parsing a comma. - for i in iter::count(0, 1) { + for i in 0.. { if self.check(&token::Gt) || self.token == token::BinOp(token::Shr) || self.token == token::Ge @@ -916,7 +865,7 @@ impl<'a> Parser<'a> { } else { // Avoid token copies with `replace`. let buffer_start = self.buffer_start as usize; - let next_index = (buffer_start + 1) & 3 as usize; + let next_index = (buffer_start + 1) & 3; self.buffer_start = next_index as isize; let placeholder = TokenAndSpan { @@ -973,7 +922,7 @@ impl<'a> Parser<'a> { } pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> ! { self.span_err(sp, m); - self.span_help(sp, help); + self.fileline_help(sp, help); panic!(diagnostic::FatalError); } pub fn span_note(&self, sp: Span, m: &str) { @@ -982,6 +931,9 @@ impl<'a> Parser<'a> { pub fn span_help(&self, sp: Span, m: &str) { self.sess.span_diagnostic.span_help(sp, m) } + pub fn fileline_help(&self, sp: Span, m: &str) { + self.sess.span_diagnostic.fileline_help(sp, m) + } pub fn bug(&self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.span, m) } @@ -1013,11 +965,6 @@ impl<'a> Parser<'a> { self.check_keyword(keywords::Extern) } - /// Is the current token one of the keywords that signals a closure type? - pub fn token_is_closure_keyword(&mut self) -> bool { - self.check_keyword(keywords::Unsafe) - } - pub fn get_lifetime(&mut self) -> ast::Ident { match self.token { token::Lifetime(ref ident) => *ident, @@ -1047,14 +994,9 @@ impl<'a> Parser<'a> { let lifetime_defs = self.parse_late_bound_lifetime_defs(); // examine next token to decide to do - if self.eat_keyword_noexpect(keywords::Proc) { - self.parse_proc_type(lifetime_defs) - } else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() { - self.parse_ty_bare_fn_or_ty_closure(lifetime_defs) - } else if self.check(&token::ModSep) || - self.token.is_ident() || - self.token.is_path() - { + if self.token_is_bare_fn_keyword() { + self.parse_ty_bare_fn(lifetime_defs) + } else { let hi = self.span.hi; let trait_ref = self.parse_trait_ref(); let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs, @@ -1070,14 +1012,11 @@ impl<'a> Parser<'a> { .chain(other_bounds.into_vec().into_iter()) .collect(); ast::TyPolyTraitRef(all_bounds) - } else { - self.parse_ty_closure(lifetime_defs) } } pub fn parse_ty_path(&mut self) -> Ty_ { - let path = self.parse_path(LifetimeAndTypesWithoutColons); - TyPath(path, ast::DUMMY_NODE_ID) + TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons)) } /// parse a TyBareFn type: @@ -1102,7 +1041,6 @@ impl<'a> Parser<'a> { }; self.expect_keyword(keywords::Fn); - let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs); let (inputs, variadic) = self.parse_fn_args(false, true); let ret_ty = self.parse_ret_ty(); let decl = P(FnDecl { @@ -1118,35 +1056,6 @@ impl<'a> Parser<'a> { })) } - /// Parses a procedure type (`proc`). The initial `proc` keyword must - /// already have been parsed. - pub fn parse_proc_type(&mut self, lifetime_defs: Vec) -> Ty_ { - /* - - proc <'lt> (S) [:Bounds] -> T - ^~~^ ^~~~^ ^ ^~~~~~~~^ ^ - | | | | | - | | | | Return type - | | | Bounds - | | Argument types - | Legacy lifetimes - the `proc` keyword (already consumed) - - */ - - let proc_span = self.last_span; - - // To be helpful, parse the proc as ever - let _ = self.parse_legacy_lifetime_defs(lifetime_defs); - let _ = self.parse_fn_args(false, false); - let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); - let _ = self.parse_ret_ty(); - - self.obsolete(proc_span, ObsoleteSyntax::ProcType); - - TyInfer - } - /// Parses an obsolete closure kind (`&:`, `&mut:`, or `:`). pub fn parse_obsolete_closure_kind(&mut self) { let lo = self.span.lo; @@ -1164,7 +1073,6 @@ impl<'a> Parser<'a> { { self.bump(); self.bump(); - return; } else if self.eat(&token::Colon) { @@ -1177,71 +1085,6 @@ impl<'a> Parser<'a> { self.obsolete(span, ObsoleteSyntax::ClosureKind); } - pub fn parse_ty_bare_fn_or_ty_closure(&mut self, lifetime_defs: Vec) -> Ty_ { - // Both bare fns and closures can begin with stuff like unsafe - // and extern. So we just scan ahead a few tokens to see if we see - // a `fn`. - // - // Closure: [unsafe] <'lt> |S| [:Bounds] -> T - // Fn: [unsafe] [extern "ABI"] fn <'lt> (S) -> T - - if self.check_keyword(keywords::Fn) { - self.parse_ty_bare_fn(lifetime_defs) - } else if self.check_keyword(keywords::Extern) { - self.parse_ty_bare_fn(lifetime_defs) - } else if self.check_keyword(keywords::Unsafe) { - if self.look_ahead(1, |t| t.is_keyword(keywords::Fn) || - t.is_keyword(keywords::Extern)) { - self.parse_ty_bare_fn(lifetime_defs) - } else { - self.parse_ty_closure(lifetime_defs) - } - } else { - self.parse_ty_closure(lifetime_defs) - } - } - - /// Parse a TyClosure type - pub fn parse_ty_closure(&mut self, lifetime_defs: Vec) -> Ty_ { - /* - - [unsafe] <'lt> |S| [:Bounds] -> T - ^~~~~~~^ ^~~~^ ^ ^~~~~~~~^ ^ - | | | | | - | | | | Return type - | | | Closure bounds - | | Argument types - | Deprecated lifetime defs - | - Function Style - - */ - - let ty_closure_span = self.last_span; - - // To be helpful, parse the closure type as ever - let _ = self.parse_unsafety(); - - let _ = self.parse_legacy_lifetime_defs(lifetime_defs); - - if !self.eat(&token::OrOr) { - self.expect_or(); - - let _ = self.parse_seq_to_before_or( - &token::Comma, - |p| p.parse_arg_general(false)); - self.expect_or(); - } - - let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); - - let _ = self.parse_ret_ty(); - - self.obsolete(ty_closure_span, ObsoleteSyntax::ClosureType); - - TyInfer - } - pub fn parse_unsafety(&mut self) -> Unsafety { if self.eat_keyword(keywords::Unsafe) { return Unsafety::Unsafe; @@ -1250,75 +1093,21 @@ impl<'a> Parser<'a> { } } - /// Parses `[ 'for' '<' lifetime_defs '>' ]' - fn parse_legacy_lifetime_defs(&mut self, - lifetime_defs: Vec) - -> Vec - { - if self.token == token::Lt { - self.bump(); - if lifetime_defs.is_empty() { - self.warn("deprecated syntax; use the `for` keyword now \ - (e.g. change `fn<'a>` to `for<'a> fn`)"); - let lifetime_defs = self.parse_lifetime_defs(); - self.expect_gt(); - lifetime_defs - } else { - self.fatal("cannot use new `for` keyword and older syntax together"); - } - } else { - lifetime_defs - } - } - - /// Parses `type Foo;` in a trait declaration only. The `type` keyword has - /// already been parsed. - fn parse_associated_type(&mut self, attrs: Vec) - -> AssociatedType - { - let ty_param = self.parse_ty_param(); - self.expect(&token::Semi); - AssociatedType { - attrs: attrs, - ty_param: ty_param, - } - } - - /// Parses `type Foo = TYPE;` in an implementation declaration only. The - /// `type` keyword has already been parsed. - fn parse_typedef(&mut self, attrs: Vec, vis: Visibility) - -> Typedef { - let lo = self.span.lo; - let ident = self.parse_ident(); - self.expect(&token::Eq); - let typ = self.parse_ty_sum(); - let hi = self.span.hi; - self.expect(&token::Semi); - Typedef { - id: ast::DUMMY_NODE_ID, - span: mk_sp(lo, hi), - ident: ident, - vis: vis, - attrs: attrs, - typ: typ, - } - } - /// Parse the items in a trait declaration - pub fn parse_trait_items(&mut self) -> Vec { + pub fn parse_trait_items(&mut self) -> Vec> { self.parse_unspanned_seq( &token::OpenDelim(token::Brace), &token::CloseDelim(token::Brace), seq_sep_none(), |p| { - let attrs = p.parse_outer_attributes(); + let lo = p.span.lo; + let mut attrs = p.parse_outer_attributes(); - if p.eat_keyword(keywords::Type) { - TypeTraitItem(P(p.parse_associated_type(attrs))) + let (name, node) = if p.eat_keyword(keywords::Type) { + let TyParam {ident, bounds, default, ..} = p.parse_ty_param(); + p.expect(&token::Semi); + (ident, TypeTraitItem(bounds, default)) } else { - let lo = p.span.lo; - - let vis = p.parse_visibility(); let style = p.parse_unsafety(); let abi = if p.eat_keyword(keywords::Extern) { p.parse_opt_abi().unwrap_or(abi::C) @@ -1337,45 +1126,27 @@ impl<'a> Parser<'a> { p.parse_arg_general(false) }); - p.parse_where_clause(&mut generics); + generics.where_clause = p.parse_where_clause(); + let sig = ast::MethodSig { + unsafety: style, + decl: d, + generics: generics, + abi: abi, + explicit_self: explicit_self, + }; - let hi = p.last_span.hi; - match p.token { + let body = match p.token { token::Semi => { p.bump(); debug!("parse_trait_methods(): parsing required method"); - RequiredMethod(TypeMethod { - ident: ident, - attrs: attrs, - unsafety: style, - decl: d, - generics: generics, - abi: abi, - explicit_self: explicit_self, - id: ast::DUMMY_NODE_ID, - span: mk_sp(lo, hi), - vis: vis, - }) + None } token::OpenDelim(token::Brace) => { debug!("parse_trait_methods(): parsing provided method"); let (inner_attrs, body) = p.parse_inner_attrs_and_block(); - let mut attrs = attrs; attrs.push_all(&inner_attrs[..]); - ProvidedMethod(P(ast::Method { - attrs: attrs, - id: ast::DUMMY_NODE_ID, - span: mk_sp(lo, hi), - node: ast::MethDecl(ident, - generics, - abi, - explicit_self, - style, - d, - body, - vis) - })) + Some(body) } _ => { @@ -1383,8 +1154,17 @@ impl<'a> Parser<'a> { p.fatal(&format!("expected `;` or `{{`, found `{}`", token_str)[..]) } - } - } + }; + (ident, ast::MethodTraitItem(sig, body)) + }; + + P(TraitItem { + id: ast::DUMMY_NODE_ID, + ident: name, + attrs: attrs, + node: node, + span: mk_sp(lo, p.last_span.hi), + }) }) } @@ -1401,19 +1181,7 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { NoReturn(self.span) } else { - let t = self.parse_ty(); - - // We used to allow `fn foo() -> &T + U`, but don't - // anymore. If we see it, report a useful error. This - // only makes sense because `parse_ret_ty` is only - // used in fn *declarations*, not fn types or where - // clauses (i.e., not when parsing something like - // `FnMut() -> T + Send`, where the `+` is legal). - if self.token == token::BinOp(token::Plus) { - self.warn("deprecated syntax: `()` are required, see RFC 438 for details"); - } - - Return(t) + Return(self.parse_ty()) } } else { let pos = self.span.lo; @@ -1501,18 +1269,9 @@ impl<'a> Parser<'a> { self.parse_borrowed_pointee() } else if self.check_keyword(keywords::For) { self.parse_for_in_type() - } else if self.token_is_bare_fn_keyword() || - self.token_is_closure_keyword() { - // BARE FUNCTION OR CLOSURE - self.parse_ty_bare_fn_or_ty_closure(Vec::new()) - } else if self.check(&token::BinOp(token::Or)) || - self.token == token::OrOr || - (self.token == token::Lt && - self.look_ahead(1, |t| { - *t == token::Gt || t.is_lifetime() - })) { - // CLOSURE - self.parse_ty_closure(Vec::new()) + } else if self.token_is_bare_fn_keyword() { + // BARE FUNCTION + self.parse_ty_bare_fn(Vec::new()) } else if self.eat_keyword_noexpect(keywords::Typeof) { // TYPEOF // In order to not be ambiguous, the type must be surrounded by parens. @@ -1520,24 +1279,39 @@ impl<'a> Parser<'a> { let e = self.parse_expr(); self.expect(&token::CloseDelim(token::Paren)); TyTypeof(e) - } else if self.eat_keyword_noexpect(keywords::Proc) { - self.parse_proc_type(Vec::new()) } else if self.eat_lt() { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; + self.expect(&token::Gt); self.expect(&token::ModSep); - let item_name = self.parse_ident(); - TyQPath(P(QPath { - self_type: self_type, - trait_ref: P(trait_ref), - item_path: ast::PathSegment { - identifier: item_name, - parameters: ast::PathParameters::none() - } - })) + + path.segments.push(ast::PathSegment { + identifier: self.parse_ident(), + parameters: ast::PathParameters::none() + }); + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + + TyPath(Some(qself), path) } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -2164,10 +1938,7 @@ impl<'a> Parser<'a> { } }, token::OpenDelim(token::Brace) => { - self.bump(); - let blk = self.parse_block_tail(lo, DefaultBlock); - return self.mk_expr(blk.span.lo, blk.span.hi, - ExprBlock(blk)); + return self.parse_block_expr(lo, DefaultBlock); }, token::BinOp(token::Or) | token::OrOr => { return self.parse_lambda_expr(CaptureByRef); @@ -2178,7 +1949,7 @@ impl<'a> Parser<'a> { }, token::Plain) => { self.bump(); let path = ast_util::ident_to_path(mk_sp(lo, hi), id); - ex = ExprPath(path); + ex = ExprPath(None, path); hi = self.last_span.hi; } token::OpenDelim(token::Bracket) => { @@ -2220,10 +1991,22 @@ impl<'a> Parser<'a> { if self.eat_lt() { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); - self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + let mut path = if self.eat_keyword(keywords::As) { + self.parse_path(LifetimeAndTypesWithoutColons) + } else { + ast::Path { + span: self.span, + global: false, + segments: vec![] + } + }; + let qself = QSelf { + ty: self_type, + position: path.segments.len() + }; self.expect(&token::Gt); self.expect(&token::ModSep); + let item_name = self.parse_ident(); let parameters = if self.eat(&token::ModSep) { self.expect_lt(); @@ -2238,25 +2021,22 @@ impl<'a> Parser<'a> { } else { ast::PathParameters::none() }; + path.segments.push(ast::PathSegment { + identifier: item_name, + parameters: parameters + }); + + if path.segments.len() == 1 { + path.span.lo = self.last_span.lo; + } + path.span.hi = self.last_span.hi; + let hi = self.span.hi; - return self.mk_expr(lo, hi, ExprQPath(P(QPath { - self_type: self_type, - trait_ref: P(trait_ref), - item_path: ast::PathSegment { - identifier: item_name, - parameters: parameters - } - }))); + return self.mk_expr(lo, hi, ExprPath(Some(qself), path)); } if self.eat_keyword(keywords::Move) { return self.parse_lambda_expr(CaptureByValue); } - if self.eat_keyword_noexpect(keywords::Proc) { - let span = self.last_span; - let _ = self.parse_proc_decl(); - let _ = self.parse_expr(); - return self.obsolete_expr(span, ObsoleteSyntax::ProcExpr); - } if self.eat_keyword(keywords::If) { return self.parse_if_expr(); } @@ -2386,7 +2166,7 @@ impl<'a> Parser<'a> { } hi = pth.span.hi; - ex = ExprPath(pth); + ex = ExprPath(None, pth); } else { // other literal expression let lit = self.parse_lit(); @@ -2496,12 +2276,12 @@ impl<'a> Parser<'a> { let fstr = n.as_str(); self.span_err(last_span, &format!("unexpected token: `{}`", n.as_str())); - if fstr.chars().all(|x| "0123456789.".contains_char(x)) { + if fstr.chars().all(|x| "0123456789.".contains(x)) { let float = match fstr.parse::().ok() { Some(f) => f, None => continue, }; - self.span_help(last_span, + self.fileline_help(last_span, &format!("try parenthesizing the first index; e.g., `(foo.{}){}`", float.trunc() as usize, &float.fract().to_string()[1..])); @@ -2532,45 +2312,13 @@ impl<'a> Parser<'a> { // expr[...] // Could be either an index expression or a slicing expression. token::OpenDelim(token::Bracket) => { - let bracket_pos = self.span.lo; self.bump(); - if self.eat(&token::CloseDelim(token::Bracket)) { - // No expression, expand to a RangeFull - // FIXME(#20516) It would be better to use a lang item or - // something for RangeFull. - hi = self.last_span.hi; - - let idents = vec![token::str_to_ident("std"), - token::str_to_ident("ops"), - token::str_to_ident("RangeFull")]; - let segments = idents.into_iter().map(|ident| { - ast::PathSegment { - identifier: ident, - parameters: ast::PathParameters::none(), - } - }).collect(); - let span = mk_sp(lo, hi); - let path = ast::Path { - span: span, - global: true, - segments: segments, - }; - - let range = ExprStruct(path, vec![], None); - let ix = self.mk_expr(bracket_pos, hi, range); - let index = self.mk_index(e, ix); - e = self.mk_expr(lo, hi, index); - - self.obsolete(span, ObsoleteSyntax::EmptyIndex); - } else { - let ix = self.parse_expr(); - hi = self.span.hi; - self.commit_expr_expecting(&*ix, token::CloseDelim(token::Bracket)); - let index = self.mk_index(e, ix); - e = self.mk_expr(lo, hi, index) - } - + let ix = self.parse_expr(); + hi = self.span.hi; + self.commit_expr_expecting(&*ix, token::CloseDelim(token::Bracket)); + let index = self.mk_index(e, ix); + e = self.mk_expr(lo, hi, index) } _ => return e } @@ -2911,7 +2659,7 @@ impl<'a> Parser<'a> { self.span_err(op_span, "chained comparison operators require parentheses"); if op.node == BiLt && outer_op == BiGt { - self.span_help(op_span, + self.fileline_help(op_span, "use `::<...>` instead of `<...>` if you meant to specify type arguments"); } } @@ -3053,19 +2801,30 @@ impl<'a> Parser<'a> { { let lo = self.span.lo; let decl = self.parse_fn_block_decl(); - let body = self.parse_expr(); - let fakeblock = P(ast::Block { - id: ast::DUMMY_NODE_ID, - stmts: vec![], - span: body.span, - expr: Some(body), - rules: DefaultBlock, - }); + let body = match decl.output { + DefaultReturn(_) => { + // If no explicit return type is given, parse any + // expr and wrap it up in a dummy block: + let body_expr = self.parse_expr(); + P(ast::Block { + id: ast::DUMMY_NODE_ID, + stmts: vec![], + span: body_expr.span, + expr: Some(body_expr), + rules: DefaultBlock, + }) + } + _ => { + // If an explicit return type is given, require a + // block to appear (RFC 968). + self.parse_block() + } + }; self.mk_expr( lo, - fakeblock.span.hi, - ExprClosure(capture_clause, decl, fakeblock)) + body.span.hi, + ExprClosure(capture_clause, decl, body)) } pub fn parse_else_expr(&mut self) -> P { @@ -3427,7 +3186,7 @@ impl<'a> Parser<'a> { let end = if self.token.is_ident() || self.token.is_path() { let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; - self.mk_expr(lo, hi, ExprPath(path)) + self.mk_expr(lo, hi, ExprPath(None, path)) } else { self.parse_literal_maybe_minus() }; @@ -3493,6 +3252,9 @@ impl<'a> Parser<'a> { }; pat = PatIdent(BindByValue(MutImmutable), pth1, sub); } + } else if self.look_ahead(1, |t| *t == token::Lt) { + self.bump(); + self.unexpected() } else { // parse an enum pat let enum_path = self.parse_path(LifetimeAndTypesWithColons); @@ -3504,6 +3266,19 @@ impl<'a> Parser<'a> { self.bump(); pat = PatStruct(enum_path, fields, etc); } + token::DotDotDot => { + let hi = self.last_span.hi; + let start = self.mk_expr(lo, hi, ExprPath(None, enum_path)); + self.eat(&token::DotDotDot); + let end = if self.token.is_ident() || self.token.is_path() { + let path = self.parse_path(LifetimeAndTypesWithColons); + let hi = self.span.hi; + self.mk_expr(lo, hi, ExprPath(None, path)) + } else { + self.parse_literal_maybe_minus() + }; + pat = PatRange(start, end); + } _ => { let mut args: Vec> = Vec::new(); match self.token { @@ -3645,41 +3420,47 @@ impl<'a> Parser<'a> { }) } - /// Get an expected item after attributes error message. - fn expected_item_err(attrs: &[Attribute]) -> &'static str { - match attrs.last() { + /// Emit an expected item after attributes error. + fn expected_item_err(&self, attrs: &[Attribute]) { + let message = match attrs.last() { Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => { "expected item after doc comment" } _ => "expected item after attributes", - } + }; + + self.span_err(self.last_span, message); } /// Parse a statement. may include decl. - /// Precondition: any attributes are parsed already - pub fn parse_stmt(&mut self, item_attrs: Vec) -> P { - maybe_whole!(self, NtStmt); + pub fn parse_stmt(&mut self) -> Option> { + self.parse_stmt_().map(P) + } + + fn parse_stmt_(&mut self) -> Option { + maybe_whole!(Some deref self, NtStmt); fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) { // If we have attributes then we should have an item if !attrs.is_empty() { - let last_span = p.last_span; - p.span_err(last_span, Parser::expected_item_err(attrs)); + p.expected_item_err(attrs); } } let lo = self.span.lo; - if self.check_keyword(keywords::Let) { - check_expected_item(self, &item_attrs[..]); + let attrs = self.parse_outer_attributes(); + + Some(if self.check_keyword(keywords::Let) { + check_expected_item(self, &attrs); self.expect_keyword(keywords::Let); let decl = self.parse_let(); - P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) + spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)) } else if self.token.is_ident() && !self.token.is_any_keyword() && self.look_ahead(1, |t| *t == token::Not) { // it's a macro invocation: - check_expected_item(self, &item_attrs[..]); + check_expected_item(self, &attrs); // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... @@ -3726,12 +3507,11 @@ impl<'a> Parser<'a> { }; if id.name == token::special_idents::invalid.name { - P(spanned(lo, - hi, - StmtMac(P(spanned(lo, + spanned(lo, hi, + StmtMac(P(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))), - style))) + style)) } else { // if it has a special ident, it's definitely an item // @@ -3745,35 +3525,38 @@ impl<'a> Parser<'a> { followed by a semicolon"); } } - P(spanned(lo, hi, StmtDecl( + spanned(lo, hi, StmtDecl( P(spanned(lo, hi, DeclItem( self.mk_item( lo, hi, id /*id is good here*/, ItemMac(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))), Inherited, Vec::new(/*no attrs*/))))), - ast::DUMMY_NODE_ID))) + ast::DUMMY_NODE_ID)) } } else { - let found_attrs = !item_attrs.is_empty(); - let item_err = Parser::expected_item_err(&item_attrs[..]); - match self.parse_item_(item_attrs, false) { - Ok(i) => { + match self.parse_item_(attrs, false) { + Some(i) => { let hi = i.span.hi; let decl = P(spanned(lo, hi, DeclItem(i))); - P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) + spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)) } - Err(_) => { - if found_attrs { - let last_span = self.last_span; - self.span_err(last_span, item_err); + None => { + // Do not attempt to parse an expression if we're done here. + if self.token == token::Semi { + self.bump(); + return None; + } + + if self.token == token::CloseDelim(token::Brace) { + return None; } // Remainder are line-expr stmts. let e = self.parse_expr_res(RESTRICTION_STMT_EXPR); - P(spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID))) + spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID)) } } - } + }) } /// Is this expression a successfully-parsed statement? @@ -3796,153 +3579,110 @@ impl<'a> Parser<'a> { "place this code inside a block"); } - return self.parse_block_tail_(lo, DefaultBlock, Vec::new()); + self.parse_block_tail(lo, DefaultBlock) } /// Parse a block. Inner attrs are allowed. - fn parse_inner_attrs_and_block(&mut self) - -> (Vec , P) { - + fn parse_inner_attrs_and_block(&mut self) -> (Vec, P) { maybe_whole!(pair_empty self, NtBlock); let lo = self.span.lo; self.expect(&token::OpenDelim(token::Brace)); - let (inner, next) = self.parse_inner_attrs_and_next(); - - (inner, self.parse_block_tail_(lo, DefaultBlock, next)) + (self.parse_inner_attributes(), + self.parse_block_tail(lo, DefaultBlock)) } + /// Parse the rest of a block expression or function body /// Precondition: already parsed the '{'. fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P { - self.parse_block_tail_(lo, s, Vec::new()) - } - - /// Parse the rest of a block expression or function body - fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, - first_item_attrs: Vec) -> P { let mut stmts = vec![]; let mut expr = None; - let mut attributes_box = first_item_attrs; - while self.token != token::CloseDelim(token::Brace) { - // parsing items even when they're not allowed lets us give - // better error messages and recover more gracefully. - attributes_box.push_all(&self.parse_outer_attributes()); - match self.token { - token::Semi => { - if !attributes_box.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attributes_box[..])); - attributes_box = Vec::new(); - } - self.bump(); // empty - } - token::CloseDelim(token::Brace) => { - // fall through and out. + while !self.eat(&token::CloseDelim(token::Brace)) { + let Spanned {node, span} = if let Some(s) = self.parse_stmt_() { + s + } else { + // Found only `;` or `}`. + continue; + }; + match node { + StmtExpr(e, _) => { + self.handle_expression_like_statement(e, span, &mut stmts, &mut expr); } - _ => { - let stmt = self.parse_stmt(attributes_box); - attributes_box = Vec::new(); - stmt.and_then(|Spanned {node, span}| match node { - StmtExpr(e, stmt_id) => { - self.handle_expression_like_statement(e, - stmt_id, - span, - &mut stmts, - &mut expr); + StmtMac(mac, MacStmtWithoutBraces) => { + // statement macro without braces; might be an + // expr depending on whether a semicolon follows + match self.token { + token::Semi => { + stmts.push(P(Spanned { + node: StmtMac(mac, MacStmtWithSemicolon), + span: span, + })); + self.bump(); } - StmtMac(mac, MacStmtWithoutBraces) => { - // statement macro without braces; might be an - // expr depending on whether a semicolon follows - match self.token { - token::Semi => { - stmts.push(P(Spanned { - node: StmtMac(mac, - MacStmtWithSemicolon), - span: span, - })); - self.bump(); - } - _ => { - let e = self.mk_mac_expr(span.lo, - span.hi, - mac.and_then(|m| m.node)); - 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, - span, - &mut stmts, - &mut expr); - } - } + _ => { + let e = self.mk_mac_expr(span.lo, span.hi, + mac.and_then(|m| m.node)); + 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, + span, + &mut stmts, + &mut expr); } - StmtMac(m, style) => { - // statement macro; might be an expr - match self.token { - token::Semi => { - stmts.push(P(Spanned { - node: StmtMac(m, - MacStmtWithSemicolon), - span: span, - })); - self.bump(); - } - token::CloseDelim(token::Brace) => { - // if a block ends in `m!(arg)` without - // a `;`, it must be an expr - expr = Some( - self.mk_mac_expr(span.lo, - span.hi, + } + } + StmtMac(m, style) => { + // statement macro; might be an expr + match self.token { + token::Semi => { + stmts.push(P(Spanned { + node: StmtMac(m, MacStmtWithSemicolon), + span: span, + })); + self.bump(); + } + token::CloseDelim(token::Brace) => { + // if a block ends in `m!(arg)` without + // a `;`, it must be an expr + expr = Some(self.mk_mac_expr(span.lo, span.hi, m.and_then(|x| x.node))); - } - _ => { - stmts.push(P(Spanned { - node: StmtMac(m, style), - span: span - })); - } - } } - _ => { // all other kinds of statements: - if classify::stmt_ends_with_semi(&node) { - self.commit_stmt_expecting(token::Semi); - } - + _ => { stmts.push(P(Spanned { - node: node, + node: StmtMac(m, style), span: span })); } - }) + } } - } - } + _ => { // all other kinds of statements: + if classify::stmt_ends_with_semi(&node) { + self.commit_stmt_expecting(token::Semi); + } - if !attributes_box.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attributes_box[..])); + stmts.push(P(Spanned { + node: node, + span: span + })); + } + } } - let hi = self.span.hi; - self.bump(); P(ast::Block { stmts: stmts, expr: expr, id: ast::DUMMY_NODE_ID, rules: s, - span: mk_sp(lo, hi), + span: mk_sp(lo, self.last_span.hi), }) } fn handle_expression_like_statement( &mut self, e: P, - stmt_id: NodeId, span: Span, stmts: &mut Vec>, last_block_expr: &mut Option>) { @@ -3962,14 +3702,14 @@ impl<'a> Parser<'a> { expn_id: span.expn_id, }; stmts.push(P(Spanned { - node: StmtSemi(e, stmt_id), + node: StmtSemi(e, ast::DUMMY_NODE_ID), span: span_with_semi, })); } token::CloseDelim(token::Brace) => *last_block_expr = Some(e), _ => { stmts.push(P(Spanned { - node: StmtExpr(e, stmt_id), + node: StmtExpr(e, ast::DUMMY_NODE_ID), span: span })); } @@ -4040,56 +3780,19 @@ impl<'a> Parser<'a> { return OwnedSlice::from_vec(result); } - fn trait_ref_from_ident(ident: Ident, span: Span) -> TraitRef { - let segment = ast::PathSegment { - identifier: ident, - parameters: ast::PathParameters::none() - }; - let path = ast::Path { - span: span, - global: false, - segments: vec![segment], - }; - ast::TraitRef { - path: path, - ref_id: ast::DUMMY_NODE_ID, - } - } - - /// Matches typaram = (unbound `?`)? IDENT (`?` unbound)? optbounds ( EQ ty )? + /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )? fn parse_ty_param(&mut self) -> TyParam { - // This is a bit hacky. Currently we are only interested in a single - // unbound, and it may only be `Sized`. To avoid backtracking and other - // complications, we parse an ident, then check for `?`. If we find it, - // we use the ident as the unbound, otherwise, we use it as the name of - // type param. Even worse, we need to check for `?` before or after the - // bound. - let mut span = self.span; - let mut ident = self.parse_ident(); - let mut unbound = None; - if self.eat(&token::Question) { - let tref = Parser::trait_ref_from_ident(ident, span); - unbound = Some(tref); - span = self.span; - ident = self.parse_ident(); - self.obsolete(span, ObsoleteSyntax::Sized); - } + let span = self.span; + let ident = self.parse_ident(); - let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified); - if let Some(unbound) = unbound { - let mut bounds_as_vec = bounds.into_vec(); - bounds_as_vec.push(TraitTyParamBound(PolyTraitRef { bound_lifetimes: vec![], - trait_ref: unbound, - span: span }, - TraitBoundModifier::Maybe)); - bounds = OwnedSlice::from_vec(bounds_as_vec); - }; + let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified); let default = if self.check(&token::Eq) { self.bump(); Some(self.parse_ty_sum()) - } - else { None }; + } else { + None + }; TyParam { ident: ident, @@ -4196,9 +3899,14 @@ impl<'a> Parser<'a> { /// ``` /// where T : Trait + 'b, 'a : 'b /// ``` - fn parse_where_clause(&mut self, generics: &mut ast::Generics) { + fn parse_where_clause(&mut self) -> ast::WhereClause { + let mut where_clause = WhereClause { + id: ast::DUMMY_NODE_ID, + predicates: Vec::new(), + }; + if !self.eat_keyword(keywords::Where) { - return + return where_clause; } let mut parsed_something = false; @@ -4221,7 +3929,7 @@ impl<'a> Parser<'a> { let hi = self.span.hi; let span = mk_sp(lo, hi); - generics.where_clause.predicates.push(ast::WherePredicate::RegionPredicate( + where_clause.predicates.push(ast::WherePredicate::RegionPredicate( ast::WhereRegionPredicate { span: span, lifetime: bounded_lifetime, @@ -4256,7 +3964,7 @@ impl<'a> Parser<'a> { at least one bound in it"); } - generics.where_clause.predicates.push(ast::WherePredicate::BoundPredicate( + where_clause.predicates.push(ast::WherePredicate::BoundPredicate( ast::WhereBoundPredicate { span: span, bound_lifetimes: bound_lifetimes, @@ -4269,7 +3977,7 @@ impl<'a> Parser<'a> { // let ty = self.parse_ty(); let hi = self.span.hi; let span = mk_sp(lo, hi); - // generics.where_clause.predicates.push( + // where_clause.predicates.push( // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { // id: ast::DUMMY_NODE_ID, // span: span, @@ -4300,6 +4008,8 @@ impl<'a> Parser<'a> { "a `where` clause must have at least one predicate \ in it"); } + + where_clause } fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) @@ -4594,23 +4304,6 @@ impl<'a> Parser<'a> { }) } - /// Parses the `(arg, arg) -> return_type` header on a procedure. - fn parse_proc_decl(&mut self) -> P { - let inputs = - self.parse_unspanned_seq(&token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - seq_sep_trailing_allowed(token::Comma), - |p| p.parse_fn_block_arg()); - - let output = self.parse_ret_ty(); - - P(FnDecl { - inputs: inputs, - output: output, - variadic: false - }) - } - /// Parse the name and optional generic types of a function header. fn parse_fn_header(&mut self) -> (Ident, ast::Generics) { let id = self.parse_ident(); @@ -4635,98 +4328,101 @@ impl<'a> Parser<'a> { fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> ItemInfo { let (ident, mut generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(false); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); let (inner_attrs, body) = self.parse_inner_attrs_and_block(); (ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs)) } - /// Parse a method in a trait impl - pub fn parse_method_with_outer_attributes(&mut self) -> P { - let attrs = self.parse_outer_attributes(); - let visa = self.parse_visibility(); - self.parse_method(attrs, visa) + /// Parse an impl item. + pub fn parse_impl_item(&mut self) -> P { + let lo = self.span.lo; + let mut attrs = self.parse_outer_attributes(); + let vis = self.parse_visibility(); + let (name, node) = if self.eat_keyword(keywords::Type) { + let name = self.parse_ident(); + self.expect(&token::Eq); + let typ = self.parse_ty_sum(); + self.expect(&token::Semi); + (name, TypeImplItem(typ)) + } else { + let (name, inner_attrs, node) = self.parse_impl_method(vis); + attrs.extend(inner_attrs.into_iter()); + (name, node) + }; + + P(ImplItem { + id: ast::DUMMY_NODE_ID, + span: mk_sp(lo, self.last_span.hi), + ident: name, + vis: vis, + attrs: attrs, + node: node + }) } fn complain_if_pub_macro(&mut self, visa: Visibility, span: Span) { match visa { Public => { self.span_err(span, "can't qualify macro invocation with `pub`"); - self.span_help(span, "try adjusting the macro to put `pub` inside \ + self.fileline_help(span, "try adjusting the macro to put `pub` inside \ the invocation"); } Inherited => (), } } - /// Parse a method in a trait impl, starting with `attrs` attributes. - pub fn parse_method(&mut self, - attrs: Vec, - visa: Visibility) - -> P { - let lo = self.span.lo; - + /// Parse a method or a macro invocation in a trait impl. + fn parse_impl_method(&mut self, vis: Visibility) + -> (Ident, Vec, ast::ImplItem_) { // code copied from parse_macro_use_or_failure... abstraction! - let (method_, hi, new_attrs) = { - if !self.token.is_any_keyword() - && self.look_ahead(1, |t| *t == token::Not) - && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) - || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { - // method macro. + if !self.token.is_any_keyword() + && self.look_ahead(1, |t| *t == token::Not) + && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) + || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { + // method macro. - let last_span = self.last_span; - self.complain_if_pub_macro(visa, last_span); - - let pth = self.parse_path(NoTypesAllowed); - self.expect(&token::Not); - - // eat a matched-delimiter token tree: - let delim = self.expect_open_delim(); - let tts = self.parse_seq_to_end(&token::CloseDelim(delim), - seq_sep_none(), - |p| p.parse_token_tree()); - let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT); - let m: ast::Mac = codemap::Spanned { node: m_, - span: mk_sp(self.span.lo, - self.span.hi) }; - if delim != token::Brace { - self.expect(&token::Semi) - } - (ast::MethMac(m), self.span.hi, attrs) - } else { - let unsafety = self.parse_unsafety(); - let abi = if self.eat_keyword(keywords::Extern) { - self.parse_opt_abi().unwrap_or(abi::C) - } else { - abi::Rust - }; - self.expect_keyword(keywords::Fn); - let ident = self.parse_ident(); - let mut generics = self.parse_generics(); - let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { - p.parse_arg() - }); - self.parse_where_clause(&mut generics); - let (inner_attrs, body) = self.parse_inner_attrs_and_block(); - let body_span = body.span; - let mut new_attrs = attrs; - new_attrs.push_all(&inner_attrs[..]); - (ast::MethDecl(ident, - generics, - abi, - explicit_self, - unsafety, - decl, - body, - visa), - body_span.hi, new_attrs) + let last_span = self.last_span; + self.complain_if_pub_macro(vis, last_span); + + let pth = self.parse_path(NoTypesAllowed); + self.expect(&token::Not); + + // eat a matched-delimiter token tree: + let delim = self.expect_open_delim(); + let tts = self.parse_seq_to_end(&token::CloseDelim(delim), + seq_sep_none(), + |p| p.parse_token_tree()); + let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT); + let m: ast::Mac = codemap::Spanned { node: m_, + span: mk_sp(self.span.lo, + self.span.hi) }; + if delim != token::Brace { + self.expect(&token::Semi) } - }; - P(ast::Method { - attrs: new_attrs, - id: ast::DUMMY_NODE_ID, - span: mk_sp(lo, hi), - node: method_, - }) + (token::special_idents::invalid, vec![], ast::MacImplItem(m)) + } else { + let unsafety = self.parse_unsafety(); + let abi = if self.eat_keyword(keywords::Extern) { + self.parse_opt_abi().unwrap_or(abi::C) + } else { + abi::Rust + }; + self.expect_keyword(keywords::Fn); + let ident = self.parse_ident(); + let mut generics = self.parse_generics(); + let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { + p.parse_arg() + }); + generics.where_clause = self.parse_where_clause(); + let (inner_attrs, body) = self.parse_inner_attrs_and_block(); + (ident, inner_attrs, MethodImplItem(ast::MethodSig { + generics: generics, + abi: abi, + explicit_self: explicit_self, + unsafety: unsafety, + decl: decl + }, body)) + } } /// Parse trait Foo { ... } @@ -4734,59 +4430,23 @@ impl<'a> Parser<'a> { let ident = self.parse_ident(); let mut tps = self.parse_generics(); - // This is not very accurate, but since unbound only exists to catch - // obsolete syntax, the span is unlikely to ever be used. - let unbound_span = self.span; - let unbound = self.parse_for_sized(); // Parse supertrait bounds. - let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); - - if let Some(unbound) = unbound { - let mut bounds_as_vec = bounds.into_vec(); - bounds_as_vec.push(TraitTyParamBound(PolyTraitRef { bound_lifetimes: vec![], - trait_ref: unbound, - span: unbound_span }, - TraitBoundModifier::Maybe)); - bounds = OwnedSlice::from_vec(bounds_as_vec); - }; + let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare); - self.parse_where_clause(&mut tps); + tps.where_clause = self.parse_where_clause(); let meths = self.parse_trait_items(); (ident, ItemTrait(unsafety, tps, bounds, meths), None) } - fn parse_impl_items(&mut self) -> (Vec, Vec) { - let mut impl_items = Vec::new(); - self.expect(&token::OpenDelim(token::Brace)); - let (inner_attrs, mut method_attrs) = - self.parse_inner_attrs_and_next(); - loop { - method_attrs.extend(self.parse_outer_attributes().into_iter()); - if method_attrs.is_empty() && self.eat(&token::CloseDelim(token::Brace)) { - break; - } - - let vis = self.parse_visibility(); - if self.eat_keyword(keywords::Type) { - impl_items.push(TypeImplItem(P(self.parse_typedef( - method_attrs, - vis)))) - } else { - impl_items.push(MethodImplItem(self.parse_method( - method_attrs, - vis))); - } - method_attrs = vec![]; - } - (impl_items, inner_attrs) - } - - /// Parses two variants (with the region/type params always optional): + /// Parses items implementations variants /// impl Foo { ... } - /// impl ToString for ~[T] { ... } + /// impl ToString for &'static T { ... } + /// impl Send for .. {} fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { + let impl_span = self.span; + // First, parse type parameters if necessary. let mut generics = self.parse_generics(); @@ -4807,21 +4467,18 @@ impl<'a> Parser<'a> { // Parse traits, if necessary. let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. - let opt_trait_ref = match ty.node { - TyPath(ref path, node_id) => { + match ty.node { + TyPath(None, ref path) => { Some(TraitRef { path: (*path).clone(), - ref_id: node_id, + ref_id: ty.id, }) } _ => { self.span_err(ty.span, "not a trait"); None } - }; - - ty = self.parse_ty_sum(); - opt_trait_ref + } } else { match polarity { ast::ImplPolarity::Negative => { @@ -4834,14 +4491,34 @@ impl<'a> Parser<'a> { None }; - self.parse_where_clause(&mut generics); - let (impl_items, attrs) = self.parse_impl_items(); + if self.eat(&token::DotDot) { + if generics.is_parameterized() { + self.span_err(impl_span, "default trait implementations are not \ + allowed to have genercis"); + } - let ident = ast_util::impl_pretty_name(&opt_trait, &*ty); + self.expect(&token::OpenDelim(token::Brace)); + self.expect(&token::CloseDelim(token::Brace)); + (ast_util::impl_pretty_name(&opt_trait, None), + ItemDefaultImpl(unsafety, opt_trait.unwrap()), None) + } else { + if opt_trait.is_some() { + ty = self.parse_ty_sum(); + } + generics.where_clause = self.parse_where_clause(); - (ident, - ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), - Some(attrs)) + self.expect(&token::OpenDelim(token::Brace)); + let attrs = self.parse_inner_attributes(); + + let mut impl_items = vec![]; + while !self.eat(&token::CloseDelim(token::Brace)) { + impl_items.push(self.parse_impl_item()); + } + + (ast_util::impl_pretty_name(&opt_trait, Some(&*ty)), + ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items), + Some(attrs)) + } } /// Parse a::B @@ -4900,7 +4577,7 @@ impl<'a> Parser<'a> { // struct. let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) { - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); if self.eat(&token::Semi) { // If we see a: `struct Foo where T: Copy;` style decl. (Vec::new(), Some(ast::DUMMY_NODE_ID)) @@ -4981,12 +4658,12 @@ impl<'a> Parser<'a> { token::get_ident(class_name.clone()))); } - self.parse_where_clause(generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::Semi); fields // This is the case where we just see struct Foo where T: Copy; } else if self.token.is_keyword(keywords::Where) { - self.parse_where_clause(generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::Semi); Vec::new() // This case is where we see: `struct Foo;` @@ -5042,86 +4719,16 @@ impl<'a> Parser<'a> { else { Inherited } } - fn parse_for_sized(&mut self) -> Option { - // FIXME, this should really use TraitBoundModifier, but it will get - // re-jigged shortly in any case, so leaving the hacky version for now. - if self.eat_keyword(keywords::For) { - let span = self.span; - - let mut ate_question = false; - if self.eat(&token::Question) { - ate_question = true; - } - let ident = self.parse_ident(); - if self.eat(&token::Question) { - if ate_question { - self.span_err(span, - "unexpected `?`"); - } - ate_question = true; - } - if !ate_question { - self.span_err(span, - "expected `?Sized` after `for` in trait item"); - return None; - } - let _tref = Parser::trait_ref_from_ident(ident, span); - - self.obsolete(span, ObsoleteSyntax::ForSized); - - None - } else { - None - } - } - - /// Given a termination token and a vector of already-parsed - /// attributes (of length 0 or 1), parse all of the items in a module - fn parse_mod_items(&mut self, - term: token::Token, - first_item_attrs: Vec, - inner_lo: BytePos) - -> Mod { - // Parse all of the items up to closing or an attribute. - - let mut attrs = first_item_attrs; - attrs.push_all(&self.parse_outer_attributes()); + /// Given a termination token, parse all of the items in a module + fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> Mod { let mut items = vec![]; - - loop { - match self.parse_item_(attrs, true) { - Err(returned_attrs) => { - attrs = returned_attrs; - break - } - Ok(item) => { - attrs = self.parse_outer_attributes(); - items.push(item) - } - } + while let Some(item) = self.parse_item() { + items.push(item); } - // don't think this other loop is even necessary.... - - while self.token != term { - let mut attrs = mem::replace(&mut attrs, vec![]); - attrs.push_all(&self.parse_outer_attributes()); - debug!("parse_mod_items: parse_item_(attrs={:?})", attrs); - match self.parse_item_(attrs, true /* macros allowed */) { - Ok(item) => items.push(item), - Err(_) => { - let token_str = self.this_token_to_string(); - self.fatal(&format!("expected item, found `{}`", - token_str)) - } - } - } - - if !attrs.is_empty() { - // We parsed attributes for the first item but didn't find it - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attrs[..])); + if !self.eat(term) { + let token_str = self.this_token_to_string(); + self.fatal(&format!("expected item, found `{}`", token_str)) } ast::Mod { @@ -5159,12 +4766,11 @@ impl<'a> Parser<'a> { let mod_inner_lo = self.span.lo; let old_owns_directory = self.owns_directory; self.owns_directory = true; - let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_mod_items(token::CloseDelim(token::Brace), next, mod_inner_lo); - self.expect(&token::CloseDelim(token::Brace)); + let attrs = self.parse_inner_attributes(); + let m = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo); self.owns_directory = old_owns_directory; self.pop_mod_path(); - (id, ItemMod(m), Some(inner)) + (id, ItemMod(m), Some(attrs)) } } @@ -5188,14 +4794,17 @@ impl<'a> Parser<'a> { outer_attrs: &[ast::Attribute], id_sp: Span) -> (ast::Item_, Vec ) { - let mut prefix = Path::new(self.sess.span_diagnostic.cm.span_to_filename(self.span)); + let mut prefix = PathBuf::from(&self.sess.span_diagnostic.cm + .span_to_filename(self.span)); prefix.pop(); - let mod_path = Path::new(".").join_many(&self.mod_path_stack[]); - let dir_path = prefix.join(&mod_path); + let mut dir_path = prefix; + for part in &self.mod_path_stack { + dir_path.push(&**part); + } let mod_string = token::get_ident(id); let (file_path, owns_directory) = match ::attr::first_attr_value_str_by_name( outer_attrs, "path") { - Some(d) => (dir_path.join(d), true), + Some(d) => (dir_path.join(&*d), true), None => { let mod_name = mod_string.to_string(); let default_path_str = format!("{}.rs", mod_name); @@ -5259,7 +4868,7 @@ impl<'a> Parser<'a> { } fn eval_src_mod_from_path(&mut self, - path: Path, + path: PathBuf, owns_directory: bool, name: String, id_sp: Span) -> (ast::Item_, Vec ) { @@ -5269,10 +4878,10 @@ impl<'a> Parser<'a> { let mut err = String::from_str("circular modules: "); let len = included_mod_stack.len(); for p in &included_mod_stack[i.. len] { - err.push_str(&p.display().as_cow()); + err.push_str(&p.to_string_lossy()); err.push_str(" -> "); } - err.push_str(&path.display().as_cow()); + err.push_str(&path.to_string_lossy()); self.span_fatal(id_sp, &err[..]); } None => () @@ -5288,11 +4897,10 @@ impl<'a> Parser<'a> { Some(name), id_sp); let mod_inner_lo = p0.span.lo; - let (mod_attrs, next) = p0.parse_inner_attrs_and_next(); - let first_item_outer_attrs = next; - let m0 = p0.parse_mod_items(token::Eof, first_item_outer_attrs, mod_inner_lo); + let mod_attrs = p0.parse_inner_attributes(); + let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo); self.sess.included_mod_stack.borrow_mut().pop(); - return (ast::ItemMod(m0), mod_attrs); + (ast::ItemMod(m0), mod_attrs) } /// Parse a function declaration from a foreign module @@ -5303,7 +4911,7 @@ impl<'a> Parser<'a> { let (ident, mut generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(true); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); let hi = self.span.hi; self.expect(&token::Semi); P(ast::ForeignItem { @@ -5339,74 +4947,25 @@ impl<'a> Parser<'a> { }) } - /// At this point, this is essentially a wrapper for - /// parse_foreign_items. - fn parse_foreign_mod_items(&mut self, - abi: abi::Abi, - first_item_attrs: Vec) - -> ForeignMod { - let foreign_items = self.parse_foreign_items(first_item_attrs); - assert!(self.token == token::CloseDelim(token::Brace)); - ast::ForeignMod { - abi: abi, - items: foreign_items - } - } - /// Parse extern crate links /// - /// # Example + /// # Examples /// - /// extern crate url; - /// extern crate foo = "bar"; //deprecated - /// extern crate "bar" as foo; + /// extern crate foo; + /// extern crate bar as foo; fn parse_item_extern_crate(&mut self, - lo: BytePos, - visibility: Visibility, - attrs: Vec) + lo: BytePos, + visibility: Visibility, + attrs: Vec) -> P { - let span = self.span; - let (maybe_path, ident) = match self.token { - token::Ident(..) => { - let the_ident = self.parse_ident(); - let path = if self.eat_keyword_noexpect(keywords::As) { - // skip the ident if there is one - if self.token.is_ident() { self.bump(); } - - self.span_err(span, "expected `;`, found `as`"); - self.span_help(span, - &format!("perhaps you meant to enclose the crate name `{}` in \ - a string?", - the_ident.as_str())); - None - } else { - None - }; - self.expect(&token::Semi); - (path, the_ident) - }, - token::Literal(token::Str_(..), suf) | token::Literal(token::StrRaw(..), suf) => { - let sp = self.span; - self.expect_no_suffix(sp, "extern crate name", suf); - // forgo the internal suffix check of `parse_str` to - // avoid repeats (this unwrap will always succeed due - // to the restriction of the `match`) - let (s, style, _) = self.parse_optional_str().unwrap(); - self.expect_keyword(keywords::As); - let the_ident = self.parse_ident(); - self.expect(&token::Semi); - (Some((s, style)), the_ident) - }, - _ => { - let span = self.span; - let token_str = self.this_token_to_string(); - self.span_fatal(span, - &format!("expected extern crate name but \ - found `{}`", - token_str)); - } + let crate_name = self.parse_ident(); + let (maybe_path, ident) = if self.eat_keyword(keywords::As) { + (Some(crate_name.name), self.parse_ident()) + } else { + (None, crate_name) }; + self.expect(&token::Semi); let last_span = self.last_span; self.mk_item(lo, @@ -5431,31 +4990,38 @@ impl<'a> Parser<'a> { lo: BytePos, opt_abi: Option, visibility: Visibility, - attrs: Vec) + mut attrs: Vec) -> P { - self.expect(&token::OpenDelim(token::Brace)); let abi = opt_abi.unwrap_or(abi::C); - let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(abi, next); + attrs.extend(self.parse_inner_attributes().into_iter()); + + let mut foreign_items = vec![]; + while let Some(item) = self.parse_foreign_item() { + foreign_items.push(item); + } self.expect(&token::CloseDelim(token::Brace)); let last_span = self.last_span; + let m = ast::ForeignMod { + abi: abi, + items: foreign_items + }; self.mk_item(lo, last_span.hi, special_idents::invalid, ItemForeignMod(m), visibility, - maybe_append(attrs, Some(inner))) + attrs) } /// Parse type Foo = Bar; fn parse_item_type(&mut self) -> ItemInfo { let ident = self.parse_ident(); let mut tps = self.parse_generics(); - self.parse_where_clause(&mut tps); + tps.where_clause = self.parse_where_clause(); self.expect(&token::Eq); let ty = self.parse_ty_sum(); self.expect(&token::Semi); @@ -5555,7 +5121,7 @@ impl<'a> Parser<'a> { fn parse_item_enum(&mut self) -> ItemInfo { let id = self.parse_ident(); let mut generics = self.parse_generics(); - self.parse_where_clause(&mut generics); + generics.where_clause = self.parse_where_clause(); self.expect(&token::OpenDelim(token::Brace)); let enum_definition = self.parse_enum_def(&generics); @@ -5590,12 +5156,11 @@ impl<'a> Parser<'a> { } } - /// Parse one of the items allowed by the flags; on failure, - /// return `Err(remaining_attrs)`. + /// Parse one of the items allowed by the flags. /// NB: this function no longer parses the items inside an /// extern crate. fn parse_item_(&mut self, attrs: Vec, - macros_allowed: bool) -> MaybeItem { + macros_allowed: bool) -> Option> { let nt_item = match self.token { token::Interpolated(token::NtItem(ref item)) => { Some((**item).clone()) @@ -5608,7 +5173,7 @@ impl<'a> Parser<'a> { let mut attrs = attrs; mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs.into_iter()); - return Ok(P(item)); + return Some(P(item)); } None => {} } @@ -5629,12 +5194,12 @@ impl<'a> Parser<'a> { item_, visibility, attrs); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Extern) { if self.eat_keyword(keywords::Crate) { - return Ok(self.parse_item_extern_crate(lo, visibility, attrs)); + return Some(self.parse_item_extern_crate(lo, visibility, attrs)); } let opt_abi = self.parse_opt_abi(); @@ -5651,9 +5216,9 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } else if self.check(&token::OpenDelim(token::Brace)) { - return Ok(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)); + return Some(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)); } let span = self.span; @@ -5679,14 +5244,14 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Const) { // CONST ITEM if self.eat_keyword(keywords::Mut) { let last_span = self.last_span; self.span_err(last_span, "const globals cannot be mutable"); - self.span_help(last_span, "did you mean to declare a static?"); + self.fileline_help(last_span, "did you mean to declare a static?"); } let (ident, item_, extra_attrs) = self.parse_item_const(None); let last_span = self.last_span; @@ -5696,7 +5261,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Unsafe) && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) @@ -5713,7 +5278,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Unsafe) && self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) @@ -5729,7 +5294,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Fn) { // FUNCTION ITEM @@ -5743,7 +5308,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.check_keyword(keywords::Unsafe) && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { @@ -5764,7 +5329,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Mod) { // MODULE ITEM @@ -5777,7 +5342,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Type) { // TYPE ITEM @@ -5789,7 +5354,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Enum) { // ENUM ITEM @@ -5801,7 +5366,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Trait) { // TRAIT ITEM @@ -5814,7 +5379,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Impl) { // IMPL ITEM @@ -5826,7 +5391,7 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } if self.eat_keyword(keywords::Struct) { // STRUCT ITEM @@ -5838,30 +5403,34 @@ impl<'a> Parser<'a> { item_, visibility, maybe_append(attrs, extra_attrs)); - return Ok(item); + return Some(item); } self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) } - /// Parse a foreign item; on failure, return `Err(remaining_attrs)`. - fn parse_foreign_item(&mut self, attrs: Vec) - -> Result, Vec> { + /// Parse a foreign item. + fn parse_foreign_item(&mut self) -> Option> { let lo = self.span.lo; + let attrs = self.parse_outer_attributes(); let visibility = self.parse_visibility(); if self.check_keyword(keywords::Static) { // FOREIGN STATIC ITEM - return Ok(self.parse_item_foreign_static(visibility, attrs)); + return Some(self.parse_item_foreign_static(visibility, attrs)); } if self.check_keyword(keywords::Fn) || self.check_keyword(keywords::Unsafe) { // FOREIGN FUNCTION ITEM - return Ok(self.parse_item_foreign_fn(visibility, attrs)); + return Some(self.parse_item_foreign_fn(visibility, attrs)); } // FIXME #5668: this will occur for a macro invocation: - let item = try!(self.parse_macro_use_or_failure(attrs, true, lo, visibility)); - self.span_fatal(item.span, "macros cannot expand to foreign items"); + match self.parse_macro_use_or_failure(attrs, true, lo, visibility) { + Some(item) => { + self.span_fatal(item.span, "macros cannot expand to foreign items"); + } + None => None + } } /// This is the fall-through for parsing items. @@ -5871,7 +5440,7 @@ impl<'a> Parser<'a> { macros_allowed: bool, lo: BytePos, visibility: Visibility - ) -> MaybeItem { + ) -> Option> { if macros_allowed && !self.token.is_any_keyword() && self.look_ahead(1, |t| *t == token::Not) && (self.look_ahead(2, |t| t.is_plain_ident()) @@ -5923,7 +5492,7 @@ impl<'a> Parser<'a> { item_, visibility, attrs); - return Ok(item); + return Some(item); } // FAILURE TO PARSE ITEM @@ -5934,16 +5503,16 @@ impl<'a> Parser<'a> { self.span_fatal(last_span, "unmatched visibility `pub`"); } } - Err(attrs) - } - pub fn parse_item_with_outer_attributes(&mut self) -> Option> { - let attrs = self.parse_outer_attributes(); - self.parse_item(attrs) + if !attrs.is_empty() { + self.expected_item_err(&attrs); + } + None } - pub fn parse_item(&mut self, attrs: Vec) -> Option> { - self.parse_item_(attrs, true).ok() + pub fn parse_item(&mut self) -> Option> { + let attrs = self.parse_outer_attributes(); + self.parse_item_(attrs, true) } /// Matches view_path : MOD? non_global_path as IDENT @@ -6049,52 +5618,13 @@ impl<'a> Parser<'a> { P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))) } - /// Parses a sequence of foreign items. Stops when it finds program - /// text that can't be parsed as an item - fn parse_foreign_items(&mut self, first_item_attrs: Vec) - -> Vec> { - let mut attrs = first_item_attrs; - attrs.push_all(&self.parse_outer_attributes()); - let mut foreign_items = Vec::new(); - loop { - match self.parse_foreign_item(attrs) { - Ok(foreign_item) => { - foreign_items.push(foreign_item); - } - Err(returned_attrs) => { - if self.check(&token::CloseDelim(token::Brace)) { - attrs = returned_attrs; - break - } - self.unexpected(); - } - } - attrs = self.parse_outer_attributes(); - } - - if !attrs.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - Parser::expected_item_err(&attrs[..])); - } - - foreign_items - } - /// Parses a source module as a crate. This is the main /// entry point for the parser. pub fn parse_crate_mod(&mut self) -> Crate { let lo = self.span.lo; - // parse the crate's inner attrs, maybe (oops) one - // of the attrs of an item: - let (inner, next) = self.parse_inner_attrs_and_next(); - let first_item_outer_attrs = next; - // parse the items inside the crate: - let m = self.parse_mod_items(token::Eof, first_item_outer_attrs, lo); - ast::Crate { - module: m, - attrs: inner, + attrs: self.parse_inner_attributes(), + module: self.parse_mod_items(&token::Eof, lo), config: self.cfg.clone(), span: mk_sp(lo, self.span.lo), exported_macros: Vec::new(), diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 433c013591..4db85eeea4 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -25,6 +25,7 @@ use serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fmt; use std::mem; use std::ops::Deref; +#[allow(deprecated)] use std::old_path::BytesContainer; use std::rc::Rc; @@ -425,10 +426,10 @@ macro_rules! declare_special_idents_and_keywords {( $( ($rk_name:expr, $rk_variant:ident, $rk_str:expr); )* } ) => { - static STRICT_KEYWORD_START: ast::Name = first!($( ast::Name($sk_name), )*); - static STRICT_KEYWORD_FINAL: ast::Name = last!($( ast::Name($sk_name), )*); - static RESERVED_KEYWORD_START: ast::Name = first!($( ast::Name($rk_name), )*); - static RESERVED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($rk_name), )*); + const STRICT_KEYWORD_START: ast::Name = first!($( ast::Name($sk_name), )*); + const STRICT_KEYWORD_FINAL: ast::Name = last!($( ast::Name($sk_name), )*); + const RESERVED_KEYWORD_START: ast::Name = first!($( ast::Name($rk_name), )*); + const RESERVED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($rk_name), )*); pub mod special_idents { use ast; @@ -561,11 +562,11 @@ declare_special_idents_and_keywords! { (39, Virtual, "virtual"); (40, While, "while"); (41, Continue, "continue"); - (42, Proc, "proc"); - (43, Box, "box"); - (44, Const, "const"); - (45, Where, "where"); + (42, Box, "box"); + (43, Const, "const"); + (44, Where, "where"); 'reserved: + (45, Proc, "proc"); (46, Alignof, "alignof"); (47, Become, "become"); (48, Offsetof, "offsetof"); @@ -638,6 +639,7 @@ impl Deref for InternedString { fn deref(&self) -> &str { &*self.string } } +#[allow(deprecated)] impl BytesContainer for InternedString { fn container_as_bytes<'a>(&'a self) -> &'a [u8] { // FIXME #12938: This is a workaround for the incorrect signature @@ -652,47 +654,47 @@ impl BytesContainer for InternedString { impl fmt::Debug for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.string[], f) + fmt::Debug::fmt(&self.string, f) } } impl fmt::Display for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.string[], f) + fmt::Display::fmt(&self.string, f) } } impl<'a> PartialEq<&'a str> for InternedString { #[inline(always)] fn eq(&self, other: & &'a str) -> bool { - PartialEq::eq(&self.string[], *other) + PartialEq::eq(&self.string[..], *other) } #[inline(always)] fn ne(&self, other: & &'a str) -> bool { - PartialEq::ne(&self.string[], *other) + PartialEq::ne(&self.string[..], *other) } } impl<'a> PartialEq for &'a str { #[inline(always)] fn eq(&self, other: &InternedString) -> bool { - PartialEq::eq(*self, &other.string[]) + PartialEq::eq(*self, &other.string[..]) } #[inline(always)] fn ne(&self, other: &InternedString) -> bool { - PartialEq::ne(*self, &other.string[]) + PartialEq::ne(*self, &other.string[..]) } } impl Decodable for InternedString { fn decode(d: &mut D) -> Result { - Ok(get_name(get_ident_interner().intern(&try!(d.read_str())[]))) + Ok(get_name(get_ident_interner().intern(&try!(d.read_str())[..]))) } } impl Encodable for InternedString { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.string[]) + s.emit_str(&self.string) } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 1593bfb97f..ebfd970f3d 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -59,7 +59,7 @@ //! line (which it can't) and so naturally place the content on its own line to //! avoid combining it with other lines and making matters even worse. -use std::old_io; +use std::io; use std::string; use std::iter::repeat; @@ -139,7 +139,7 @@ pub fn buf_str(toks: &[Token], } s.push_str(&format!("{}={}", szs[i], - tok_str(&toks[i]))[]); + tok_str(&toks[i]))); i += 1; i %= n; } @@ -147,21 +147,21 @@ pub fn buf_str(toks: &[Token], s } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum PrintStackBreak { Fits, Broken(Breaks), } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct PrintStackElem { offset: isize, pbreak: PrintStackBreak } -static SIZE_INFINITY: isize = 0xffff; +const SIZE_INFINITY: isize = 0xffff; -pub fn mk_printer(out: Box, linewidth: usize) -> Printer { +pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { // Yes 3, it makes the ring buffers big enough to never // fall behind. let n: usize = 3 * linewidth; @@ -265,8 +265,8 @@ pub fn mk_printer(out: Box, linewidth: usize) -> Printer /// In this implementation (following the paper, again) the SCAN process is /// the method called 'pretty_print', and the 'PRINT' process is the method /// called 'print'. -pub struct Printer { - pub out: Box, +pub struct Printer<'a> { + pub out: Box, buf_len: usize, /// Width of lines we're constrained to margin: isize, @@ -303,7 +303,7 @@ pub struct Printer { pending_indentation: isize, } -impl Printer { +impl<'a> Printer<'a> { pub fn last_token(&mut self) -> Token { self.token[self.right].clone() } @@ -311,7 +311,7 @@ impl Printer { pub fn replace_last_token(&mut self, t: Token) { self.token[self.right] = t; } - pub fn pretty_print(&mut self, token: Token) -> old_io::IoResult<()> { + pub fn pretty_print(&mut self, token: Token) -> io::Result<()> { debug!("pp ~[{},{}]", self.left, self.right); match token { Token::Eof => { @@ -385,7 +385,7 @@ impl Printer { } } } - pub fn check_stream(&mut self) -> old_io::IoResult<()> { + pub fn check_stream(&mut self) -> io::Result<()> { debug!("check_stream ~[{}, {}] with left_total={}, right_total={}", self.left, self.right, self.left_total, self.right_total); if self.right_total - self.left_total > self.space { @@ -445,7 +445,7 @@ impl Printer { self.right %= self.buf_len; assert!((self.right != self.left)); } - pub fn advance_left(&mut self) -> old_io::IoResult<()> { + pub fn advance_left(&mut self) -> io::Result<()> { debug!("advance_left ~[{},{}], sizeof({})={}", self.left, self.right, self.left, self.size[self.left]); @@ -506,7 +506,7 @@ impl Printer { } } } - pub fn print_newline(&mut self, amount: isize) -> old_io::IoResult<()> { + pub fn print_newline(&mut self, amount: isize) -> io::Result<()> { debug!("NEWLINE {}", amount); let ret = write!(self.out, "\n"); self.pending_indentation = 0; @@ -529,14 +529,14 @@ impl Printer { } } } - pub fn print_str(&mut self, s: &str) -> old_io::IoResult<()> { + pub fn print_str(&mut self, s: &str) -> io::Result<()> { while self.pending_indentation > 0 { try!(write!(self.out, " ")); self.pending_indentation -= 1; } write!(self.out, "{}", s) } - pub fn print(&mut self, token: Token, l: isize) -> old_io::IoResult<()> { + pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { debug!("print {} {} (remaining line space={})", tok_str(&token), l, self.space); debug!("{}", buf_str(&self.token, @@ -620,61 +620,61 @@ impl Printer { // Convenience functions to talk to the printer. // // "raw box" -pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> old_io::IoResult<()> { +pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> { p.pretty_print(Token::Begin(BeginToken { offset: indent as isize, breaks: b })) } -pub fn ibox(p: &mut Printer, indent: usize) -> old_io::IoResult<()> { +pub fn ibox(p: &mut Printer, indent: usize) -> io::Result<()> { rbox(p, indent, Breaks::Inconsistent) } -pub fn cbox(p: &mut Printer, indent: usize) -> old_io::IoResult<()> { +pub fn cbox(p: &mut Printer, indent: usize) -> io::Result<()> { rbox(p, indent, Breaks::Consistent) } -pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> old_io::IoResult<()> { +pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> io::Result<()> { p.pretty_print(Token::Break(BreakToken { offset: off, blank_space: n as isize })) } -pub fn end(p: &mut Printer) -> old_io::IoResult<()> { +pub fn end(p: &mut Printer) -> io::Result<()> { p.pretty_print(Token::End) } -pub fn eof(p: &mut Printer) -> old_io::IoResult<()> { +pub fn eof(p: &mut Printer) -> io::Result<()> { p.pretty_print(Token::Eof) } -pub fn word(p: &mut Printer, wrd: &str) -> old_io::IoResult<()> { +pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> { p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as isize)) } -pub fn huge_word(p: &mut Printer, wrd: &str) -> old_io::IoResult<()> { +pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> { p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY)) } -pub fn zero_word(p: &mut Printer, wrd: &str) -> old_io::IoResult<()> { +pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> { p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0)) } -pub fn spaces(p: &mut Printer, n: usize) -> old_io::IoResult<()> { +pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> { break_offset(p, n, 0) } -pub fn zerobreak(p: &mut Printer) -> old_io::IoResult<()> { +pub fn zerobreak(p: &mut Printer) -> io::Result<()> { spaces(p, 0) } -pub fn space(p: &mut Printer) -> old_io::IoResult<()> { +pub fn space(p: &mut Printer) -> io::Result<()> { spaces(p, 1) } -pub fn hardbreak(p: &mut Printer) -> old_io::IoResult<()> { +pub fn hardbreak(p: &mut Printer) -> io::Result<()> { spaces(p, SIZE_INFINITY as usize) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f26578e740..46d196d13f 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -12,8 +12,7 @@ pub use self::AnnNode::*; use abi; use ast; -use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; -use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem}; +use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast_util; use attr; use owned_slice::OwnedSlice; @@ -30,7 +29,7 @@ use ptr::P; use std_inject; use std::{ascii, mem}; -use std::old_io::{self, IoResult}; +use std::io::{self, Write, Read}; use std::iter; pub enum AnnNode<'a> { @@ -38,28 +37,29 @@ pub enum AnnNode<'a> { NodeName(&'a ast::Name), NodeBlock(&'a ast::Block), NodeItem(&'a ast::Item), + NodeSubItem(ast::NodeId), NodeExpr(&'a ast::Expr), NodePat(&'a ast::Pat), } pub trait PpAnn { - fn pre(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) } - fn post(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) } + fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) } + fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) } } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct NoAnn; impl PpAnn for NoAnn {} -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct CurrentCommentAndLiteral { cur_cmnt: usize, cur_lit: usize, } pub struct State<'a> { - pub s: pp::Printer, + pub s: pp::Printer<'a>, cm: Option<&'a CodeMap>, comments: Option >, literals: Option >, @@ -69,12 +69,12 @@ pub struct State<'a> { encode_idents_with_hygiene: bool, } -pub fn rust_printer(writer: Box) -> State<'static> { +pub fn rust_printer<'a>(writer: Box) -> State<'a> { static NO_ANN: NoAnn = NoAnn; rust_printer_annotated(writer, &NO_ANN) } -pub fn rust_printer_annotated<'a>(writer: Box, +pub fn rust_printer_annotated<'a>(writer: Box, ann: &'a PpAnn) -> State<'a> { State { s: pp::mk_printer(writer, default_columns), @@ -104,10 +104,10 @@ pub fn print_crate<'a>(cm: &'a CodeMap, span_diagnostic: &diagnostic::SpanHandler, krate: &ast::Crate, filename: String, - input: &mut old_io::Reader, - out: Box, + input: &mut Read, + out: Box, ann: &'a PpAnn, - is_expanded: bool) -> IoResult<()> { + is_expanded: bool) -> io::Result<()> { let mut s = State::new_from_input(cm, span_diagnostic, filename, @@ -143,8 +143,8 @@ impl<'a> State<'a> { pub fn new_from_input(cm: &'a CodeMap, span_diagnostic: &diagnostic::SpanHandler, filename: String, - input: &mut old_io::Reader, - out: Box, + input: &mut Read, + out: Box, ann: &'a PpAnn, is_expanded: bool) -> State<'a> { let (cmnts, lits) = comments::gather_comments_and_literals( @@ -164,7 +164,7 @@ impl<'a> State<'a> { } pub fn new(cm: &'a CodeMap, - out: Box, + out: Box, ann: &'a PpAnn, comments: Option>, literals: Option>) -> State<'a> { @@ -185,14 +185,14 @@ impl<'a> State<'a> { } pub fn to_string(f: F) -> String where - F: FnOnce(&mut State) -> IoResult<()>, + F: FnOnce(&mut State) -> io::Result<()>, { use std::raw::TraitObject; let mut s = rust_printer(box Vec::new()); f(&mut s).unwrap(); eof(&mut s.s).unwrap(); let wr = unsafe { - // FIXME(pcwalton): A nasty function to extract the string from an `old_io::Writer` + // FIXME(pcwalton): A nasty function to extract the string from an `Write` // that we "know" to be a `Vec` that works around the lack of checked // downcasts. let obj: &TraitObject = mem::transmute(&s.s.out); @@ -356,16 +356,20 @@ pub fn item_to_string(i: &ast::Item) -> String { $to_string(|s| s.print_item(i)) } -pub fn generics_to_string(generics: &ast::Generics) -> String { - $to_string(|s| s.print_generics(generics)) +pub fn impl_item_to_string(i: &ast::ImplItem) -> String { + $to_string(|s| s.print_impl_item(i)) +} + +pub fn trait_item_to_string(i: &ast::TraitItem) -> String { + $to_string(|s| s.print_trait_item(i)) } -pub fn ty_method_to_string(p: &ast::TypeMethod) -> String { - $to_string(|s| s.print_ty_method(p)) +pub fn generics_to_string(generics: &ast::Generics) -> String { + $to_string(|s| s.print_generics(generics)) } -pub fn method_to_string(p: &ast::Method) -> String { - $to_string(|s| s.print_method(p)) +pub fn where_clause_to_string(i: &ast::WhereClause) -> String { + $to_string(|s| s.print_where_clause(i)) } pub fn fn_block_to_string(p: &ast::FnDecl) -> String { @@ -373,7 +377,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String { } pub fn path_to_string(p: &ast::Path) -> String { - $to_string(|s| s.print_path(p, false)) + $to_string(|s| s.print_path(p, false, 0)) } pub fn ident_to_string(id: &ast::Ident) -> String { @@ -384,8 +388,9 @@ pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ide opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics) -> String { $to_string(|s| { - try!(s.print_fn(decl, Some(unsafety), abi::Rust, - name, generics, opt_explicit_self, ast::Inherited)); + try!(s.head("")); + try!(s.print_fn(decl, unsafety, abi::Rust, Some(name), + generics, opt_explicit_self, ast::Inherited)); try!(s.end()); // Close the head box s.end() // Close the outer box }) @@ -440,13 +445,13 @@ thing_to_string_impls! { to_string } pub mod with_hygiene { use abi; use ast; - use std::old_io::IoResult; + use std::io; use super::indent_unit; // This function is the trick that all the rest of the routines // hang on. pub fn to_string_hyg(f: F) -> String where - F: FnOnce(&mut super::State) -> IoResult<()>, + F: FnOnce(&mut super::State) -> io::Result<()>, { super::to_string(move |s| { s.encode_idents_with_hygiene = true; @@ -474,44 +479,44 @@ fn needs_parentheses(expr: &ast::Expr) -> bool { } impl<'a> State<'a> { - pub fn ibox(&mut self, u: usize) -> IoResult<()> { + pub fn ibox(&mut self, u: usize) -> io::Result<()> { self.boxes.push(pp::Breaks::Inconsistent); pp::ibox(&mut self.s, u) } - pub fn end(&mut self) -> IoResult<()> { + pub fn end(&mut self) -> io::Result<()> { self.boxes.pop().unwrap(); pp::end(&mut self.s) } - pub fn cbox(&mut self, u: usize) -> IoResult<()> { + pub fn cbox(&mut self, u: usize) -> io::Result<()> { self.boxes.push(pp::Breaks::Consistent); pp::cbox(&mut self.s, u) } // "raw box" - pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> IoResult<()> { + pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> { self.boxes.push(b); pp::rbox(&mut self.s, u, b) } - pub fn nbsp(&mut self) -> IoResult<()> { word(&mut self.s, " ") } + pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") } - pub fn word_nbsp(&mut self, w: &str) -> IoResult<()> { + pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> { try!(word(&mut self.s, w)); self.nbsp() } - pub fn word_space(&mut self, w: &str) -> IoResult<()> { + pub fn word_space(&mut self, w: &str) -> io::Result<()> { try!(word(&mut self.s, w)); space(&mut self.s) } - pub fn popen(&mut self) -> IoResult<()> { word(&mut self.s, "(") } + pub fn popen(&mut self) -> io::Result<()> { word(&mut self.s, "(") } - pub fn pclose(&mut self) -> IoResult<()> { word(&mut self.s, ")") } + pub fn pclose(&mut self) -> io::Result<()> { word(&mut self.s, ")") } - pub fn head(&mut self, w: &str) -> IoResult<()> { + pub fn head(&mut self, w: &str) -> io::Result<()> { // outer-box is consistent try!(self.cbox(indent_unit)); // head-box is inconsistent @@ -523,17 +528,17 @@ impl<'a> State<'a> { Ok(()) } - pub fn bopen(&mut self) -> IoResult<()> { + pub fn bopen(&mut self) -> io::Result<()> { try!(word(&mut self.s, "{")); self.end() // close the head-box } pub fn bclose_(&mut self, span: codemap::Span, - indented: usize) -> IoResult<()> { + indented: usize) -> io::Result<()> { self.bclose_maybe_open(span, indented, true) } pub fn bclose_maybe_open (&mut self, span: codemap::Span, - indented: usize, close_box: bool) -> IoResult<()> { + indented: usize, close_box: bool) -> io::Result<()> { try!(self.maybe_print_comment(span.hi)); try!(self.break_offset_if_not_bol(1, -(indented as isize))); try!(word(&mut self.s, "}")); @@ -542,7 +547,7 @@ impl<'a> State<'a> { } Ok(()) } - pub fn bclose(&mut self, span: codemap::Span) -> IoResult<()> { + pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> { self.bclose_(span, indent_unit) } @@ -572,18 +577,18 @@ impl<'a> State<'a> { } } - pub fn hardbreak_if_not_bol(&mut self) -> IoResult<()> { + pub fn hardbreak_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { try!(hardbreak(&mut self.s)) } Ok(()) } - pub fn space_if_not_bol(&mut self) -> IoResult<()> { + pub fn space_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { try!(space(&mut self.s)); } Ok(()) } pub fn break_offset_if_not_bol(&mut self, n: usize, - off: isize) -> IoResult<()> { + off: isize) -> io::Result<()> { if !self.is_bol() { break_offset(&mut self.s, n, off) } else { @@ -599,7 +604,7 @@ impl<'a> State<'a> { // Synthesizes a comment that was not textually present in the original source // file. - pub fn synth_comment(&mut self, text: String) -> IoResult<()> { + pub fn synth_comment(&mut self, text: String) -> io::Result<()> { try!(word(&mut self.s, "/*")); try!(space(&mut self.s)); try!(word(&mut self.s, &text[..])); @@ -607,8 +612,8 @@ impl<'a> State<'a> { word(&mut self.s, "*/") } - pub fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> IoResult<()> where - F: FnMut(&mut State, &T) -> IoResult<()>, + pub fn commasep(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> where + F: FnMut(&mut State, &T) -> io::Result<()>, { try!(self.rbox(0, b)); let mut first = true; @@ -624,8 +629,8 @@ impl<'a> State<'a> { b: Breaks, elts: &[T], mut op: F, - mut get_span: G) -> IoResult<()> where - F: FnMut(&mut State, &T) -> IoResult<()>, + mut get_span: G) -> io::Result<()> where + F: FnMut(&mut State, &T) -> io::Result<()>, G: FnMut(&T) -> codemap::Span, { try!(self.rbox(0, b)); @@ -646,12 +651,12 @@ impl<'a> State<'a> { } pub fn commasep_exprs(&mut self, b: Breaks, - exprs: &[P]) -> IoResult<()> { + exprs: &[P]) -> io::Result<()> { self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&**e), |e| e.span) } pub fn print_mod(&mut self, _mod: &ast::Mod, - attrs: &[ast::Attribute]) -> IoResult<()> { + attrs: &[ast::Attribute]) -> io::Result<()> { try!(self.print_inner_attributes(attrs)); for item in &_mod.items { try!(self.print_item(&**item)); @@ -660,7 +665,7 @@ impl<'a> State<'a> { } pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, - attrs: &[ast::Attribute]) -> IoResult<()> { + attrs: &[ast::Attribute]) -> io::Result<()> { try!(self.print_inner_attributes(attrs)); for item in &nmod.items { try!(self.print_foreign_item(&**item)); @@ -669,7 +674,7 @@ impl<'a> State<'a> { } pub fn print_opt_lifetime(&mut self, - lifetime: &Option) -> IoResult<()> { + lifetime: &Option) -> io::Result<()> { if let Some(l) = *lifetime { try!(self.print_lifetime(&l)); try!(self.nbsp()); @@ -677,7 +682,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> { + pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> { try!(self.maybe_print_comment(ty.span.lo)); try!(self.ibox(0)); match ty.node { @@ -729,8 +734,11 @@ impl<'a> State<'a> { &generics, None)); } - ast::TyPath(ref path, _) => { - try!(self.print_path(path, false)); + ast::TyPath(None, ref path) => { + try!(self.print_path(path, false, 0)); + } + ast::TyPath(Some(ref qself), ref path) => { + try!(self.print_qpath(path, qself, false)) } ast::TyObjectSum(ref ty, ref bounds) => { try!(self.print_type(&**ty)); @@ -739,9 +747,6 @@ impl<'a> State<'a> { ast::TyPolyTraitRef(ref bounds) => { try!(self.print_bounds("", &bounds[..])); } - ast::TyQPath(ref qpath) => { - try!(self.print_qpath(&**qpath, false)) - } ast::TyFixedLengthVec(ref ty, ref v) => { try!(word(&mut self.s, "[")); try!(self.print_type(&**ty)); @@ -762,14 +767,16 @@ impl<'a> State<'a> { } pub fn print_foreign_item(&mut self, - item: &ast::ForeignItem) -> IoResult<()> { + item: &ast::ForeignItem) -> io::Result<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); try!(self.print_outer_attributes(&item.attrs)); match item.node { ast::ForeignItemFn(ref decl, ref generics) => { - try!(self.print_fn(&**decl, None, abi::Rust, item.ident, generics, - None, item.vis)); + try!(self.head("")); + try!(self.print_fn(&**decl, ast::Unsafety::Normal, + abi::Rust, Some(item.ident), + generics, None, item.vis)); try!(self.end()); // end head-ibox try!(word(&mut self.s, ";")); self.end() // end the outer fn box @@ -790,26 +797,27 @@ impl<'a> State<'a> { } } - fn print_associated_type(&mut self, typedef: &ast::AssociatedType) - -> IoResult<()> - { - try!(self.print_outer_attributes(&typedef.attrs)); + fn print_associated_type(&mut self, + ident: ast::Ident, + bounds: Option<&ast::TyParamBounds>, + ty: Option<&ast::Ty>) + -> io::Result<()> { try!(self.word_space("type")); - try!(self.print_ty_param(&typedef.ty_param)); + try!(self.print_ident(ident)); + if let Some(bounds) = bounds { + try!(self.print_bounds(":", bounds)); + } + if let Some(ty) = ty { + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(ty)); + } word(&mut self.s, ";") } - fn print_typedef(&mut self, typedef: &ast::Typedef) -> IoResult<()> { - try!(self.word_space("type")); - try!(self.print_ident(typedef.ident)); - try!(space(&mut self.s)); - try!(self.word_space("=")); - try!(self.print_type(&*typedef.typ)); - word(&mut self.s, ";") - } /// Pretty-print an item - pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { + pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); try!(self.print_outer_attributes(&item.attrs)); @@ -818,8 +826,13 @@ impl<'a> State<'a> { ast::ItemExternCrate(ref optional_path) => { try!(self.head(&visibility_qualified(item.vis, "extern crate"))); - if let Some((ref p, style)) = *optional_path { - try!(self.print_string(p, style)); + if let Some(p) = *optional_path { + let val = token::get_name(p); + if val.contains("-") { + try!(self.print_string(&val, ast::CookedStr)); + } else { + try!(self.print_name(p)); + } try!(space(&mut self.s)); try!(word(&mut self.s, "as")); try!(space(&mut self.s)); @@ -869,11 +882,12 @@ impl<'a> State<'a> { try!(self.end()); // end the outer cbox } ast::ItemFn(ref decl, unsafety, abi, ref typarams, ref body) => { + try!(self.head("")); try!(self.print_fn( - &**decl, - Some(unsafety), + decl, + unsafety, abi, - item.ident, + Some(item.ident), typarams, None, item.vis @@ -908,7 +922,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space("=")); try!(self.print_type(&**ty)); - try!(self.print_where_clause(params)); + try!(self.print_where_clause(¶ms.where_clause)); try!(word(&mut self.s, ";")); try!(self.end()); // end the outer ibox } @@ -926,6 +940,18 @@ impl<'a> State<'a> { try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); } + ast::ItemDefaultImpl(unsafety, ref trait_ref) => { + try!(self.head("")); + try!(self.print_visibility(item.vis)); + try!(self.print_unsafety(unsafety)); + try!(self.word_nbsp("impl")); + try!(self.print_trait_ref(trait_ref)); + try!(space(&mut self.s)); + try!(self.word_space("for")); + try!(self.word_space("..")); + try!(self.bopen()); + try!(self.bclose(item.span)); + } ast::ItemImpl(unsafety, polarity, ref generics, @@ -959,24 +985,17 @@ impl<'a> State<'a> { } try!(self.print_type(&**ty)); - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(space(&mut self.s)); try!(self.bopen()); try!(self.print_inner_attributes(&item.attrs)); for impl_item in impl_items { - match *impl_item { - ast::MethodImplItem(ref meth) => { - try!(self.print_method(&**meth)); - } - ast::TypeImplItem(ref typ) => { - try!(self.print_typedef(&**typ)); - } - } + try!(self.print_impl_item(impl_item)); } try!(self.bclose(item.span)); } - ast::ItemTrait(unsafety, ref generics, ref bounds, ref methods) => { + ast::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => { try!(self.head("")); try!(self.print_visibility(item.vis)); try!(self.print_unsafety(unsafety)); @@ -994,11 +1013,11 @@ impl<'a> State<'a> { } } try!(self.print_bounds(":", &real_bounds[..])); - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(word(&mut self.s, " ")); try!(self.bopen()); - for meth in methods { - try!(self.print_trait_method(meth)); + for trait_item in trait_items { + try!(self.print_trait_item(trait_item)); } try!(self.bclose(item.span)); } @@ -1006,7 +1025,7 @@ impl<'a> State<'a> { ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { try!(self.print_visibility(item.vis)); - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "! ")); try!(self.print_ident(item.ident)); try!(self.cbox(indent_unit)); @@ -1020,11 +1039,11 @@ impl<'a> State<'a> { self.ann.post(self, NodeItem(item)) } - fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> { - self.print_path(&t.path, false) + fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> { + self.print_path(&t.path, false, 0) } - fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> { + fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> { if !lifetimes.is_empty() { try!(word(&mut self.s, "for<")); let mut comma = false; @@ -1040,7 +1059,7 @@ impl<'a> State<'a> { Ok(()) } - fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> IoResult<()> { + fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> { try!(self.print_formal_lifetime_list(&t.bound_lifetimes)); self.print_trait_ref(&t.trait_ref) } @@ -1048,18 +1067,18 @@ impl<'a> State<'a> { pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef, generics: &ast::Generics, ident: ast::Ident, span: codemap::Span, - visibility: ast::Visibility) -> IoResult<()> { + visibility: ast::Visibility) -> io::Result<()> { try!(self.head(&visibility_qualified(visibility, "enum"))); try!(self.print_ident(ident)); try!(self.print_generics(generics)); - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(space(&mut self.s)); self.print_variants(&enum_definition.variants, span) } pub fn print_variants(&mut self, variants: &[P], - span: codemap::Span) -> IoResult<()> { + span: codemap::Span) -> io::Result<()> { try!(self.bopen()); for v in variants { try!(self.space_if_not_bol()); @@ -1074,7 +1093,7 @@ impl<'a> State<'a> { self.bclose(span) } - pub fn print_visibility(&mut self, vis: ast::Visibility) -> IoResult<()> { + pub fn print_visibility(&mut self, vis: ast::Visibility) -> io::Result<()> { match vis { ast::Public => self.word_nbsp("pub"), ast::Inherited => Ok(()) @@ -1085,7 +1104,7 @@ impl<'a> State<'a> { struct_def: &ast::StructDef, generics: &ast::Generics, ident: ast::Ident, - span: codemap::Span) -> IoResult<()> { + span: codemap::Span) -> io::Result<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); if ast_util::struct_def_is_tuple_like(struct_def) { @@ -1106,12 +1125,12 @@ impl<'a> State<'a> { )); try!(self.pclose()); } - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(word(&mut self.s, ";")); try!(self.end()); self.end() // close the outer-box } else { - try!(self.print_where_clause(generics)); + try!(self.print_where_clause(&generics.where_clause)); try!(self.nbsp()); try!(self.bopen()); try!(self.hardbreak_if_not_bol()); @@ -1143,7 +1162,7 @@ impl<'a> State<'a> { /// appropriate macro, transcribe back into the grammar we just parsed from, /// and then pretty-print the resulting AST nodes (so, e.g., we print /// expression arguments as expressions). It can be done! I think. - pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> { + pub fn print_tt(&mut self, tt: &ast::TokenTree) -> io::Result<()> { match *tt { ast::TtToken(_, ref tk) => { try!(word(&mut self.s, &token_to_string(tk))); @@ -1181,7 +1200,7 @@ impl<'a> State<'a> { } } - pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> IoResult<()> { + pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> io::Result<()> { try!(self.ibox(0)); let mut suppress_space = false; for (i, tt) in tts.iter().enumerate() { @@ -1201,7 +1220,7 @@ impl<'a> State<'a> { self.end() } - pub fn print_variant(&mut self, v: &ast::Variant) -> IoResult<()> { + pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> { try!(self.print_visibility(v.node.vis)); match v.node.kind { ast::TupleVariantKind(ref args) => { @@ -1230,75 +1249,80 @@ impl<'a> State<'a> { } } - pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> { - try!(self.hardbreak_if_not_bol()); - try!(self.maybe_print_comment(m.span.lo)); - try!(self.print_outer_attributes(&m.attrs)); - try!(self.print_ty_fn(m.abi, - m.unsafety, - &*m.decl, - Some(m.ident), - &m.generics, - Some(&m.explicit_self.node))); - word(&mut self.s, ";") - } - - pub fn print_trait_method(&mut self, - m: &ast::TraitItem) -> IoResult<()> { - match *m { - RequiredMethod(ref ty_m) => self.print_ty_method(ty_m), - ProvidedMethod(ref m) => self.print_method(&**m), - TypeTraitItem(ref t) => self.print_associated_type(&**t), - } + pub fn print_method_sig(&mut self, + ident: ast::Ident, + m: &ast::MethodSig, + vis: ast::Visibility) + -> io::Result<()> { + self.print_fn(&m.decl, + m.unsafety, + m.abi, + Some(ident), + &m.generics, + Some(&m.explicit_self.node), + vis) } - pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> { - match *ii { - MethodImplItem(ref m) => self.print_method(&**m), - TypeImplItem(ref td) => self.print_typedef(&**td), + pub fn print_trait_item(&mut self, ti: &ast::TraitItem) + -> io::Result<()> { + try!(self.ann.pre(self, NodeSubItem(ti.id))); + try!(self.hardbreak_if_not_bol()); + try!(self.maybe_print_comment(ti.span.lo)); + try!(self.print_outer_attributes(&ti.attrs)); + match ti.node { + ast::MethodTraitItem(ref sig, ref body) => { + if body.is_some() { + try!(self.head("")); + } + try!(self.print_method_sig(ti.ident, sig, ast::Inherited)); + if let Some(ref body) = *body { + try!(self.nbsp()); + try!(self.print_block_with_attrs(body, &ti.attrs)); + } else { + try!(word(&mut self.s, ";")); + } + } + ast::TypeTraitItem(ref bounds, ref default) => { + try!(self.print_associated_type(ti.ident, Some(bounds), + default.as_ref().map(|ty| &**ty))); + } } + self.ann.post(self, NodeSubItem(ti.id)) } - pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> { + pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> { + try!(self.ann.pre(self, NodeSubItem(ii.id))); try!(self.hardbreak_if_not_bol()); - try!(self.maybe_print_comment(meth.span.lo)); - try!(self.print_outer_attributes(&meth.attrs)); - match meth.node { - ast::MethDecl(ident, - ref generics, - abi, - ref explicit_self, - unsafety, - ref decl, - ref body, - vis) => { - try!(self.print_fn(&**decl, - Some(unsafety), - abi, - ident, - generics, - Some(&explicit_self.node), - vis)); - try!(word(&mut self.s, " ")); - self.print_block_with_attrs(&**body, &meth.attrs) - }, - ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), - ..}) => { + try!(self.maybe_print_comment(ii.span.lo)); + try!(self.print_outer_attributes(&ii.attrs)); + match ii.node { + ast::MethodImplItem(ref sig, ref body) => { + try!(self.head("")); + try!(self.print_method_sig(ii.ident, sig, ii.vis)); + try!(self.nbsp()); + try!(self.print_block_with_attrs(body, &ii.attrs)); + } + ast::TypeImplItem(ref ty) => { + try!(self.print_associated_type(ii.ident, None, Some(ty))); + } + ast::MacImplItem(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), + ..}) => { // code copied from ItemMac: - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "! ")); try!(self.cbox(indent_unit)); try!(self.popen()); try!(self.print_tts(&tts[..])); try!(self.pclose()); try!(word(&mut self.s, ";")); - self.end() + try!(self.end()) } } + self.ann.post(self, NodeSubItem(ii.id)) } pub fn print_outer_attributes(&mut self, - attrs: &[ast::Attribute]) -> IoResult<()> { + attrs: &[ast::Attribute]) -> io::Result<()> { let mut count = 0; for attr in attrs { match attr.node.style { @@ -1316,7 +1340,7 @@ impl<'a> State<'a> { } pub fn print_inner_attributes(&mut self, - attrs: &[ast::Attribute]) -> IoResult<()> { + attrs: &[ast::Attribute]) -> io::Result<()> { let mut count = 0; for attr in attrs { match attr.node.style { @@ -1333,7 +1357,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_attribute(&mut self, attr: &ast::Attribute) -> IoResult<()> { + pub fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(attr.span.lo)); if attr.node.is_sugared_doc { @@ -1349,7 +1373,7 @@ impl<'a> State<'a> { } - pub fn print_stmt(&mut self, st: &ast::Stmt) -> IoResult<()> { + pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> { try!(self.maybe_print_comment(st.span.lo)); match st.node { ast::StmtDecl(ref decl, _) => { @@ -1383,22 +1407,22 @@ impl<'a> State<'a> { self.maybe_print_trailing_comment(st.span, None) } - pub fn print_block(&mut self, blk: &ast::Block) -> IoResult<()> { + pub fn print_block(&mut self, blk: &ast::Block) -> io::Result<()> { self.print_block_with_attrs(blk, &[]) } - pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> IoResult<()> { + pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> io::Result<()> { self.print_block_unclosed_indent(blk, indent_unit) } pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block, - indented: usize) -> IoResult<()> { + indented: usize) -> io::Result<()> { self.print_block_maybe_unclosed(blk, indented, &[], false) } pub fn print_block_with_attrs(&mut self, blk: &ast::Block, - attrs: &[ast::Attribute]) -> IoResult<()> { + attrs: &[ast::Attribute]) -> io::Result<()> { self.print_block_maybe_unclosed(blk, indent_unit, attrs, true) } @@ -1406,7 +1430,7 @@ impl<'a> State<'a> { blk: &ast::Block, indented: usize, attrs: &[ast::Attribute], - close_box: bool) -> IoResult<()> { + close_box: bool) -> io::Result<()> { match blk.rules { ast::UnsafeBlock(..) => try!(self.word_space("unsafe")), ast::DefaultBlock => () @@ -1432,7 +1456,7 @@ impl<'a> State<'a> { self.ann.post(self, NodeBlock(blk)) } - fn print_else(&mut self, els: Option<&ast::Expr>) -> IoResult<()> { + fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> { match els { Some(_else) => { match _else.node { @@ -1477,7 +1501,7 @@ impl<'a> State<'a> { } pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, - elseopt: Option<&ast::Expr>) -> IoResult<()> { + elseopt: Option<&ast::Expr>) -> io::Result<()> { try!(self.head("if")); try!(self.print_expr(test)); try!(space(&mut self.s)); @@ -1486,7 +1510,7 @@ impl<'a> State<'a> { } pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block, - elseopt: Option<&ast::Expr>) -> IoResult<()> { + elseopt: Option<&ast::Expr>) -> io::Result<()> { try!(self.head("if let")); try!(self.print_pat(pat)); try!(space(&mut self.s)); @@ -1498,11 +1522,11 @@ impl<'a> State<'a> { } pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) - -> IoResult<()> { + -> io::Result<()> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { - try!(self.print_path(pth, false)); + try!(self.print_path(pth, false, 0)); try!(word(&mut self.s, "!")); match delim { token::Paren => try!(self.popen()), @@ -1520,13 +1544,13 @@ impl<'a> State<'a> { } - fn print_call_post(&mut self, args: &[P]) -> IoResult<()> { + fn print_call_post(&mut self, args: &[P]) -> io::Result<()> { try!(self.popen()); try!(self.commasep_exprs(Inconsistent, args)); self.pclose() } - pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> IoResult<()> { + pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> io::Result<()> { let needs_par = needs_parentheses(expr); if needs_par { try!(self.popen()); @@ -1540,7 +1564,7 @@ impl<'a> State<'a> { fn print_expr_box(&mut self, place: &Option>, - expr: &ast::Expr) -> IoResult<()> { + expr: &ast::Expr) -> io::Result<()> { try!(word(&mut self.s, "box")); try!(word(&mut self.s, "(")); try!(place.as_ref().map_or(Ok(()), |e|self.print_expr(&**e))); @@ -1548,7 +1572,7 @@ impl<'a> State<'a> { self.print_expr(expr) } - fn print_expr_vec(&mut self, exprs: &[P]) -> IoResult<()> { + fn print_expr_vec(&mut self, exprs: &[P]) -> io::Result<()> { try!(self.ibox(indent_unit)); try!(word(&mut self.s, "[")); try!(self.commasep_exprs(Inconsistent, &exprs[..])); @@ -1558,7 +1582,7 @@ impl<'a> State<'a> { fn print_expr_repeat(&mut self, element: &ast::Expr, - count: &ast::Expr) -> IoResult<()> { + count: &ast::Expr) -> io::Result<()> { try!(self.ibox(indent_unit)); try!(word(&mut self.s, "[")); try!(self.print_expr(element)); @@ -1571,8 +1595,8 @@ impl<'a> State<'a> { fn print_expr_struct(&mut self, path: &ast::Path, fields: &[ast::Field], - wth: &Option>) -> IoResult<()> { - try!(self.print_path(path, true)); + wth: &Option>) -> io::Result<()> { + try!(self.print_path(path, true, 0)); if !(fields.is_empty() && wth.is_none()) { try!(word(&mut self.s, "{")); try!(self.commasep_cmnt( @@ -1604,7 +1628,7 @@ impl<'a> State<'a> { Ok(()) } - fn print_expr_tup(&mut self, exprs: &[P]) -> IoResult<()> { + fn print_expr_tup(&mut self, exprs: &[P]) -> io::Result<()> { try!(self.popen()); try!(self.commasep_exprs(Inconsistent, &exprs[..])); if exprs.len() == 1 { @@ -1615,7 +1639,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &ast::Expr, - args: &[P]) -> IoResult<()> { + args: &[P]) -> io::Result<()> { try!(self.print_expr_maybe_paren(func)); self.print_call_post(args) } @@ -1623,7 +1647,7 @@ impl<'a> State<'a> { fn print_expr_method_call(&mut self, ident: ast::SpannedIdent, tys: &[P], - args: &[P]) -> IoResult<()> { + args: &[P]) -> io::Result<()> { let base_args = &args[1..]; try!(self.print_expr(&*args[0])); try!(word(&mut self.s, ".")); @@ -1640,7 +1664,7 @@ impl<'a> State<'a> { fn print_expr_binary(&mut self, op: ast::BinOp, lhs: &ast::Expr, - rhs: &ast::Expr) -> IoResult<()> { + rhs: &ast::Expr) -> io::Result<()> { try!(self.print_expr(lhs)); try!(space(&mut self.s)); try!(self.word_space(ast_util::binop_to_string(op.node))); @@ -1649,20 +1673,20 @@ impl<'a> State<'a> { fn print_expr_unary(&mut self, op: ast::UnOp, - expr: &ast::Expr) -> IoResult<()> { + expr: &ast::Expr) -> io::Result<()> { try!(word(&mut self.s, ast_util::unop_to_string(op))); self.print_expr_maybe_paren(expr) } fn print_expr_addr_of(&mut self, mutability: ast::Mutability, - expr: &ast::Expr) -> IoResult<()> { + expr: &ast::Expr) -> io::Result<()> { try!(word(&mut self.s, "&")); try!(self.print_mutability(mutability)); self.print_expr_maybe_paren(expr) } - pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> { + pub fn print_expr(&mut self, expr: &ast::Expr) -> io::Result<()> { try!(self.maybe_print_comment(expr.span.lo)); try!(self.ibox(indent_unit)); try!(self.ann.pre(self, NodeExpr(expr))); @@ -1775,7 +1799,12 @@ impl<'a> State<'a> { try!(self.print_fn_block_args(&**decl)); try!(space(&mut self.s)); - if !body.stmts.is_empty() || !body.expr.is_some() { + let default_return = match decl.output { + ast::DefaultReturn(..) => true, + _ => false + }; + + if !default_return || !body.stmts.is_empty() || body.expr.is_none() { try!(self.print_block_unclosed(&**body)); } else { // we extract the block, so as not to create another set of boxes @@ -1840,8 +1869,12 @@ impl<'a> State<'a> { try!(self.print_expr(&**e)); } } - ast::ExprPath(ref path) => try!(self.print_path(path, true)), - ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)), + ast::ExprPath(None, ref path) => { + try!(self.print_path(path, true, 0)) + } + ast::ExprPath(Some(ref qself), ref path) => { + try!(self.print_qpath(path, qself, true)) + } ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); try!(space(&mut self.s)); @@ -1942,7 +1975,7 @@ impl<'a> State<'a> { self.end() } - pub fn print_local_decl(&mut self, loc: &ast::Local) -> IoResult<()> { + pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> { try!(self.print_pat(&*loc.pat)); if let Some(ref ty) = loc.ty { try!(self.word_space(":")); @@ -1951,7 +1984,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> { + pub fn print_decl(&mut self, decl: &ast::Decl) -> io::Result<()> { try!(self.maybe_print_comment(decl.span.lo)); match decl.node { ast::DeclLocal(ref loc) => { @@ -1973,7 +2006,7 @@ impl<'a> State<'a> { } } - pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> { + pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> { if self.encode_idents_with_hygiene { let encoded = ident.encode_with_hygiene(); try!(word(&mut self.s, &encoded[..])) @@ -1983,17 +2016,17 @@ impl<'a> State<'a> { self.ann.post(self, NodeIdent(&ident)) } - pub fn print_usize(&mut self, i: usize) -> IoResult<()> { + pub fn print_usize(&mut self, i: usize) -> io::Result<()> { word(&mut self.s, &i.to_string()) } - pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> { + pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> { try!(word(&mut self.s, &token::get_name(name))); self.ann.post(self, NodeName(&name)) } pub fn print_for_decl(&mut self, loc: &ast::Local, - coll: &ast::Expr) -> IoResult<()> { + coll: &ast::Expr) -> io::Result<()> { try!(self.print_local_decl(loc)); try!(space(&mut self.s)); try!(self.word_space("in")); @@ -2002,16 +2035,14 @@ impl<'a> State<'a> { fn print_path(&mut self, path: &ast::Path, - colons_before_params: bool) - -> IoResult<()> + colons_before_params: bool, + depth: usize) + -> io::Result<()> { try!(self.maybe_print_comment(path.span.lo)); - if path.global { - try!(word(&mut self.s, "::")); - } - let mut first = true; - for segment in &path.segments { + let mut first = !path.global; + for segment in &path.segments[..path.segments.len()-depth] { if first { first = false } else { @@ -2027,25 +2058,30 @@ impl<'a> State<'a> { } fn print_qpath(&mut self, - qpath: &ast::QPath, + path: &ast::Path, + qself: &ast::QSelf, colons_before_params: bool) - -> IoResult<()> + -> io::Result<()> { try!(word(&mut self.s, "<")); - try!(self.print_type(&*qpath.self_type)); - try!(space(&mut self.s)); - try!(self.word_space("as")); - try!(self.print_trait_ref(&*qpath.trait_ref)); + try!(self.print_type(&qself.ty)); + if qself.position > 0 { + try!(space(&mut self.s)); + try!(self.word_space("as")); + let depth = path.segments.len() - qself.position; + try!(self.print_path(&path, false, depth)); + } try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); - try!(self.print_ident(qpath.item_path.identifier)); - self.print_path_parameters(&qpath.item_path.parameters, colons_before_params) + let item_segment = path.segments.last().unwrap(); + try!(self.print_ident(item_segment.identifier)); + self.print_path_parameters(&item_segment.parameters, colons_before_params) } fn print_path_parameters(&mut self, parameters: &ast::PathParameters, colons_before_params: bool) - -> IoResult<()> + -> io::Result<()> { if parameters.is_empty() { return Ok(()); @@ -2115,7 +2151,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { + pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> { try!(self.maybe_print_comment(pat.span.lo)); try!(self.ann.pre(self, NodePat(pat))); /* Pat isn't normalized, but the beauty of it @@ -2144,7 +2180,7 @@ impl<'a> State<'a> { } } ast::PatEnum(ref path, ref args_) => { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); match *args_ { None => try!(word(&mut self.s, "(..)")), Some(ref args) => { @@ -2158,7 +2194,7 @@ impl<'a> State<'a> { } } ast::PatStruct(ref path, ref fields, etc) => { - try!(self.print_path(path, true)); + try!(self.print_path(path, true, 0)); try!(self.nbsp()); try!(self.word_space("{")); try!(self.commasep_cmnt( @@ -2234,7 +2270,7 @@ impl<'a> State<'a> { self.ann.post(self, NodePat(pat)) } - fn print_arm(&mut self, arm: &ast::Arm) -> IoResult<()> { + fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> { // I have no idea why this check is necessary, but here it // is :( if arm.attrs.is_empty() { @@ -2283,7 +2319,7 @@ impl<'a> State<'a> { // Returns whether it printed anything fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf_, - mutbl: ast::Mutability) -> IoResult { + mutbl: ast::Mutability) -> io::Result { try!(self.print_mutability(mutbl)); match *explicit_self { ast::SelfStatic => { return Ok(false); } @@ -2307,24 +2343,26 @@ impl<'a> State<'a> { pub fn print_fn(&mut self, decl: &ast::FnDecl, - unsafety: Option, + unsafety: ast::Unsafety, abi: abi::Abi, - name: ast::Ident, + name: Option, generics: &ast::Generics, opt_explicit_self: Option<&ast::ExplicitSelf_>, - vis: ast::Visibility) -> IoResult<()> { - try!(self.head("")); + vis: ast::Visibility) -> io::Result<()> { try!(self.print_fn_header_info(unsafety, abi, vis)); - try!(self.nbsp()); - try!(self.print_ident(name)); + + if let Some(name) = name { + try!(self.nbsp()); + try!(self.print_ident(name)); + } try!(self.print_generics(generics)); try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); - self.print_where_clause(generics) + self.print_where_clause(&generics.where_clause) } pub fn print_fn_args(&mut self, decl: &ast::FnDecl, opt_explicit_self: Option<&ast::ExplicitSelf_>) - -> IoResult<()> { + -> io::Result<()> { // It is unfortunate to duplicate the commasep logic, but we want the // self type and the args all in the same box. try!(self.rbox(0, Inconsistent)); @@ -2342,7 +2380,7 @@ impl<'a> State<'a> { // HACK(eddyb) ignore the separately printed self argument. let args = if first { - &decl.inputs[] + &decl.inputs[..] } else { &decl.inputs[1..] }; @@ -2357,7 +2395,7 @@ impl<'a> State<'a> { pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl, opt_explicit_self: Option<&ast::ExplicitSelf_>) - -> IoResult<()> { + -> io::Result<()> { try!(self.popen()); try!(self.print_fn_args(decl, opt_explicit_self)); if decl.variadic { @@ -2371,7 +2409,7 @@ impl<'a> State<'a> { pub fn print_fn_block_args( &mut self, decl: &ast::FnDecl) - -> IoResult<()> { + -> io::Result<()> { try!(word(&mut self.s, "|")); try!(self.print_fn_args(decl, None)); try!(word(&mut self.s, "|")); @@ -2396,7 +2434,7 @@ impl<'a> State<'a> { } pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause) - -> IoResult<()> { + -> io::Result<()> { match capture_clause { ast::CaptureByValue => self.word_space("move"), ast::CaptureByRef => Ok(()), @@ -2406,7 +2444,7 @@ impl<'a> State<'a> { pub fn print_bounds(&mut self, prefix: &str, bounds: &[ast::TyParamBound]) - -> IoResult<()> { + -> io::Result<()> { if !bounds.is_empty() { try!(word(&mut self.s, prefix)); let mut first = true; @@ -2439,14 +2477,14 @@ impl<'a> State<'a> { pub fn print_lifetime(&mut self, lifetime: &ast::Lifetime) - -> IoResult<()> + -> io::Result<()> { self.print_name(lifetime.name) } pub fn print_lifetime_def(&mut self, lifetime: &ast::LifetimeDef) - -> IoResult<()> + -> io::Result<()> { try!(self.print_lifetime(&lifetime.lifetime)); let mut sep = ":"; @@ -2460,7 +2498,7 @@ impl<'a> State<'a> { pub fn print_generics(&mut self, generics: &ast::Generics) - -> IoResult<()> + -> io::Result<()> { let total = generics.lifetimes.len() + generics.ty_params.len(); if total == 0 { @@ -2489,7 +2527,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> { + pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> { try!(self.print_ident(param.ident)); try!(self.print_bounds(":", ¶m.bounds)); match param.default { @@ -2502,19 +2540,16 @@ impl<'a> State<'a> { } } - pub fn print_where_clause(&mut self, generics: &ast::Generics) - -> IoResult<()> { - if generics.where_clause.predicates.len() == 0 { + pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause) + -> io::Result<()> { + if where_clause.predicates.len() == 0 { return Ok(()) } try!(space(&mut self.s)); try!(self.word_space("where")); - for (i, predicate) in generics.where_clause - .predicates - .iter() - .enumerate() { + for (i, predicate) in where_clause.predicates.iter().enumerate() { if i != 0 { try!(self.word_space(",")); } @@ -2543,7 +2578,7 @@ impl<'a> State<'a> { } } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); try!(space(&mut self.s)); try!(self.word_space("=")); try!(self.print_type(&**ty)); @@ -2554,7 +2589,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> { + pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> { try!(self.ibox(indent_unit)); match item.node { ast::MetaWord(ref name) => { @@ -2577,10 +2612,10 @@ impl<'a> State<'a> { self.end() } - pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> { + pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> { match vp.node { ast::ViewPathSimple(ident, ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); // FIXME(#6993) can't compare identifiers directly here if path.segments.last().unwrap().identifier.name != @@ -2594,7 +2629,7 @@ impl<'a> State<'a> { } ast::ViewPathGlob(ref path) => { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); word(&mut self.s, "::*") } @@ -2602,7 +2637,7 @@ impl<'a> State<'a> { if path.segments.is_empty() { try!(word(&mut self.s, "{")); } else { - try!(self.print_path(path, false)); + try!(self.print_path(path, false, 0)); try!(word(&mut self.s, "::{")); } try!(self.commasep(Inconsistent, &idents[..], |s, w| { @@ -2621,19 +2656,19 @@ impl<'a> State<'a> { } pub fn print_mutability(&mut self, - mutbl: ast::Mutability) -> IoResult<()> { + mutbl: ast::Mutability) -> io::Result<()> { match mutbl { ast::MutMutable => self.word_nbsp("mut"), ast::MutImmutable => Ok(()), } } - pub fn print_mt(&mut self, mt: &ast::MutTy) -> IoResult<()> { + pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> { try!(self.print_mutability(mt.mutbl)); self.print_type(&*mt.ty) } - pub fn print_arg(&mut self, input: &ast::Arg) -> IoResult<()> { + pub fn print_arg(&mut self, input: &ast::Arg) -> io::Result<()> { try!(self.ibox(indent_unit)); match input.ty.node { ast::TyInfer => try!(self.print_pat(&*input.pat)), @@ -2656,7 +2691,7 @@ impl<'a> State<'a> { self.end() } - pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> IoResult<()> { + pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> io::Result<()> { if let ast::DefaultReturn(..) = decl.output { return Ok(()); } @@ -2683,31 +2718,32 @@ impl<'a> State<'a> { abi: abi::Abi, unsafety: ast::Unsafety, decl: &ast::FnDecl, - id: Option, + name: Option, generics: &ast::Generics, opt_explicit_self: Option<&ast::ExplicitSelf_>) - -> IoResult<()> { + -> io::Result<()> { try!(self.ibox(indent_unit)); - try!(self.print_fn_header_info(Some(unsafety), abi, ast::Inherited)); - - match id { - Some(id) => { - try!(word(&mut self.s, " ")); - try!(self.print_ident(id)); - } - _ => () - } - - try!(self.print_generics(generics)); - try!(zerobreak(&mut self.s)); - try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); - try!(self.print_where_clause(generics)); + if generics.lifetimes.len() > 0 || generics.ty_params.len() > 0 { + try!(word(&mut self.s, "for")); + try!(self.print_generics(generics)); + } + let generics = ast::Generics { + lifetimes: Vec::new(), + ty_params: OwnedSlice::empty(), + where_clause: ast::WhereClause { + id: ast::DUMMY_NODE_ID, + predicates: Vec::new(), + }, + }; + try!(self.print_fn(decl, unsafety, abi, name, + &generics, opt_explicit_self, + ast::Inherited)); self.end() } pub fn maybe_print_trailing_comment(&mut self, span: codemap::Span, next_pos: Option) - -> IoResult<()> { + -> io::Result<()> { let cm = match self.cm { Some(cm) => cm, _ => return Ok(()) @@ -2730,7 +2766,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_remaining_comments(&mut self) -> IoResult<()> { + pub fn print_remaining_comments(&mut self) -> io::Result<()> { // If there aren't any remaining comments, then we need to manually // make sure there is a line break at the end. if self.next_comment().is_none() { @@ -2748,7 +2784,7 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { + pub fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> { try!(self.maybe_print_comment(lit.span.lo)); match self.next_lit(lit.span.lo) { Some(ref ltrl) => { @@ -2806,7 +2842,7 @@ impl<'a> State<'a> { ast::LitBinary(ref v) => { let mut escaped: String = String::new(); for &ch in &**v { - escaped.extend(ascii::escape_default(ch as u8) + escaped.extend(ascii::escape_default(ch) .map(|c| c as char)); } word(&mut self.s, &format!("b\"{}\"", escaped)) @@ -2829,7 +2865,7 @@ impl<'a> State<'a> { } } - pub fn maybe_print_comment(&mut self, pos: BytePos) -> IoResult<()> { + pub fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> { loop { match self.next_comment() { Some(ref cmnt) => { @@ -2845,7 +2881,7 @@ impl<'a> State<'a> { } pub fn print_comment(&mut self, - cmnt: &comments::Comment) -> IoResult<()> { + cmnt: &comments::Comment) -> io::Result<()> { match cmnt.style { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1); @@ -2896,7 +2932,7 @@ impl<'a> State<'a> { } pub fn print_string(&mut self, st: &str, - style: ast::StrStyle) -> IoResult<()> { + style: ast::StrStyle) -> io::Result<()> { let st = match style { ast::CookedStr => { (format!("\"{}\"", st.escape_default())) @@ -2923,17 +2959,9 @@ impl<'a> State<'a> { } } - pub fn print_opt_unsafety(&mut self, - opt_unsafety: Option) -> IoResult<()> { - match opt_unsafety { - Some(unsafety) => self.print_unsafety(unsafety), - None => Ok(()) - } - } - pub fn print_opt_abi_and_extern_if_nondefault(&mut self, opt_abi: Option) - -> IoResult<()> { + -> io::Result<()> { match opt_abi { Some(abi::Rust) => Ok(()), Some(abi) => { @@ -2945,7 +2973,7 @@ impl<'a> State<'a> { } pub fn print_extern_opt_abi(&mut self, - opt_abi: Option) -> IoResult<()> { + opt_abi: Option) -> io::Result<()> { match opt_abi { Some(abi) => { try!(self.word_nbsp("extern")); @@ -2956,11 +2984,11 @@ impl<'a> State<'a> { } pub fn print_fn_header_info(&mut self, - opt_unsafety: Option, + unsafety: ast::Unsafety, abi: abi::Abi, - vis: ast::Visibility) -> IoResult<()> { + vis: ast::Visibility) -> io::Result<()> { try!(word(&mut self.s, &visibility_qualified(vis, ""))); - try!(self.print_opt_unsafety(opt_unsafety)); + try!(self.print_unsafety(unsafety)); if abi != abi::Rust { try!(self.word_nbsp("extern")); @@ -2970,7 +2998,7 @@ impl<'a> State<'a> { word(&mut self.s, "fn") } - pub fn print_unsafety(&mut self, s: ast::Unsafety) -> IoResult<()> { + pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> { match s { ast::Unsafety::Normal => Ok(()), ast::Unsafety::Unsafe => self.word_nbsp("unsafe"), @@ -3025,7 +3053,7 @@ mod test { #[test] fn test_signed_int_to_string() { let pos_int = ast::LitInt(42, ast::SignedIntLit(ast::TyI32, ast::Plus)); - let neg_int = ast::LitInt((-42) as u64, ast::SignedIntLit(ast::TyI32, ast::Minus)); + let neg_int = ast::LitInt((!42 + 1) as u64, ast::SignedIntLit(ast::TyI32, ast::Minus)); assert_eq!(format!("-{}", lit_to_string(&codemap::dummy_spanned(pos_int))), lit_to_string(&codemap::dummy_spanned(neg_int))); } diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index adb5383a8f..7e0bcd3e1d 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -71,8 +71,8 @@ impl P { { unsafe { let p = &mut *self.ptr; - // FIXME(#5016) this shouldn't need to zero to be safe. - ptr::write(p, f(ptr::read_and_zero(p))); + // FIXME(#5016) this shouldn't need to drop-fill to be safe. + ptr::write(p, f(ptr::read_and_drop(p))); } self } @@ -111,13 +111,6 @@ impl Display for P { } } -#[cfg(stage0)] -impl> Hash for P { - fn hash(&self, state: &mut S) { - (**self).hash(state); - } -} -#[cfg(not(stage0))] impl Hash for P { fn hash(&self, state: &mut H) { (**self).hash(state); diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 4e4a571ede..021ec4738e 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -38,7 +38,7 @@ pub fn maybe_inject_prelude(krate: ast::Crate) -> ast::Crate { } pub fn use_std(krate: &ast::Crate) -> bool { - !attr::contains_name(&krate.attrs[], "no_std") + !attr::contains_name(&krate.attrs, "no_std") } fn no_prelude(attrs: &[ast::Attribute]) -> bool { @@ -52,10 +52,10 @@ struct StandardLibraryInjector { impl fold::Folder for StandardLibraryInjector { fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { - // The name to use in `extern crate "name" as std;` + // The name to use in `extern crate name as std;` let actual_crate_name = match self.alt_std_name { - Some(ref s) => token::intern_and_get_ident(&s[..]), - None => token::intern_and_get_ident("std"), + Some(ref s) => token::intern(&s), + None => token::intern("std"), }; krate.module.items.insert(0, P(ast::Item { @@ -64,7 +64,7 @@ impl fold::Folder for StandardLibraryInjector { attrs: vec!( attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item( InternedString::new("macro_use")))), - node: ast::ItemExternCrate(Some((actual_crate_name, ast::CookedStr))), + node: ast::ItemExternCrate(Some(actual_crate_name)), vis: ast::Inherited, span: DUMMY_SP })); @@ -88,14 +88,14 @@ impl fold::Folder for PreludeInjector { // only add `use std::prelude::*;` if there wasn't a // `#![no_implicit_prelude]` at the crate level. // fold_mod() will insert glob path. - if !no_prelude(&krate.attrs[]) { + if !no_prelude(&krate.attrs) { krate.module = self.fold_mod(krate.module); } krate } fn fold_item(&mut self, item: P) -> SmallVector> { - if !no_prelude(&item.attrs[]) { + if !no_prelude(&item.attrs) { // only recur if there wasn't `#![no_implicit_prelude]` // on this item, i.e. this means that the prelude is not // implicitly imported though the whole subtree diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 7b1fc91e45..fbee11ee65 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -37,7 +37,7 @@ use {ast, ast_util}; use ptr::P; use util::small_vector::SmallVector; -enum ShouldFail { +enum ShouldPanic { No, Yes(Option), } @@ -47,7 +47,7 @@ struct Test { path: Vec , bench: bool, ignore: bool, - should_fail: ShouldFail + should_panic: ShouldPanic } struct TestCtxt<'a> { @@ -73,14 +73,14 @@ pub fn modify_for_testing(sess: &ParseSess, // We generate the test harness when building in the 'test' // configuration, either with the '--test' or '--cfg test' // command line options. - let should_test = attr::contains_name(&krate.config[], "test"); + let should_test = attr::contains_name(&krate.config, "test"); // Check for #[reexport_test_harness_main = "some_name"] which // creates a `use some_name = __test::main;`. This needs to be // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = - attr::first_attr_value_str_by_name(&krate.attrs[], + attr::first_attr_value_str_by_name(&krate.attrs, "reexport_test_harness_main"); if should_test { @@ -121,13 +121,11 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { debug!("current path: {}", ast_util::path_name_i(&self.cx.path)); - if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { + let i = if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { match i.node { ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => { let diag = self.cx.span_diagnostic; - diag.span_fatal(i.span, - "unsafe functions cannot be used for \ - tests"); + diag.span_fatal(i.span, "unsafe functions cannot be used for tests"); } _ => { debug!("this is a test function"); @@ -136,15 +134,25 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { path: self.cx.path.clone(), bench: is_bench_fn(&self.cx, &*i), ignore: is_ignored(&*i), - should_fail: should_fail(&*i) + should_panic: should_panic(&*i) }; self.cx.testfns.push(test); self.tests.push(i.ident); // debug!("have {} test/bench functions", // cx.testfns.len()); + + // Make all tests public so we can call them from outside + // the module (note that the tests are re-exported and must + // be made public themselves to avoid privacy errors). + i.map(|mut i| { + i.vis = ast::Public; + i + }) } } - } + } else { + i + }; // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things @@ -256,7 +264,8 @@ fn generate_test_harness(sess: &ParseSess, callee: NameAndSpan { name: "test".to_string(), format: MacroAttribute, - span: None + span: None, + allow_internal_unstable: false, } }); @@ -288,7 +297,8 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span { callee: NameAndSpan { name: "test".to_string(), format: MacroAttribute, - span: None + span: None, + allow_internal_unstable: true, } }; let expn_id = cx.sess.span_diagnostic.cm.record_expansion(info); @@ -306,7 +316,7 @@ enum HasTestSignature { fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { - let has_test_attr = attr::contains_name(&i.attrs[], "test"); + let has_test_attr = attr::contains_name(&i.attrs, "test"); fn has_test_signature(i: &ast::Item) -> HasTestSignature { match &i.node { @@ -342,7 +352,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { } fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { - let has_bench_attr = attr::contains_name(&i.attrs[], "bench"); + let has_bench_attr = attr::contains_name(&i.attrs, "bench"); fn has_test_signature(i: &ast::Item) -> bool { match i.node { @@ -376,15 +386,15 @@ fn is_ignored(i: &ast::Item) -> bool { i.attrs.iter().any(|attr| attr.check_name("ignore")) } -fn should_fail(i: &ast::Item) -> ShouldFail { - match i.attrs.iter().find(|attr| attr.check_name("should_fail")) { +fn should_panic(i: &ast::Item) -> ShouldPanic { + match i.attrs.iter().find(|attr| attr.check_name("should_panic")) { Some(attr) => { let msg = attr.meta_item_list() .and_then(|list| list.iter().find(|mi| mi.check_name("expected"))) .and_then(|mi| mi.value_str()); - ShouldFail::Yes(msg) + ShouldPanic::Yes(msg) } - None => ShouldFail::No, + None => ShouldPanic::No, } } @@ -562,7 +572,7 @@ fn mk_tests(cx: &TestCtxt) -> P { } fn is_test_crate(krate: &ast::Crate) -> bool { - match attr::find_crate_name(&krate.attrs[]) { + match attr::find_crate_name(&krate.attrs) { Some(ref s) if "test" == &s[..] => true, _ => false } @@ -615,13 +625,13 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { vec![name_expr]); let ignore_expr = ecx.expr_bool(span, test.ignore); - let should_fail_path = |name| { - ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldFail"), ecx.ident_of(name)]) + let should_panic_path = |name| { + ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldPanic"), ecx.ident_of(name)]) }; - let fail_expr = match test.should_fail { - ShouldFail::No => ecx.expr_path(should_fail_path("No")), - ShouldFail::Yes(ref msg) => { - let path = should_fail_path("Yes"); + let fail_expr = match test.should_panic { + ShouldPanic::No => ecx.expr_path(should_panic_path("No")), + ShouldPanic::Yes(ref msg) => { + let path = should_panic_path("Yes"); let arg = match *msg { Some(ref msg) => ecx.expr_some(span, ecx.expr_str(span, msg.clone())), None => ecx.expr_none(span), @@ -636,7 +646,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { test_path("TestDesc"), vec![field("name", name_expr), field("ignore", ignore_expr), - field("should_fail", fail_expr)]); + field("should_panic", fail_expr)]); let mut visible_path = match cx.toplevel_reexport { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index dffeac6f3f..7ae9e4646e 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -18,7 +18,6 @@ use std::borrow::Borrow; use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashMap; -#[cfg(stage0)] use std::collections::hash_map::Hasher; use std::fmt; use std::hash::Hash; use std::ops::Deref; @@ -30,71 +29,6 @@ pub struct Interner { } // when traits can extend traits, we should extend index to get [] -#[cfg(stage0)] -impl + Clone + 'static> Interner { - pub fn new() -> Interner { - Interner { - map: RefCell::new(HashMap::new()), - vect: RefCell::new(Vec::new()), - } - } - - pub fn prefill(init: &[T]) -> Interner { - let rv = Interner::new(); - for v in init { - rv.intern((*v).clone()); - } - rv - } - - pub fn intern(&self, val: T) -> Name { - let mut map = self.map.borrow_mut(); - match (*map).get(&val) { - Some(&idx) => return idx, - None => (), - } - - let mut vect = self.vect.borrow_mut(); - let new_idx = Name((*vect).len() as u32); - (*map).insert(val.clone(), new_idx); - (*vect).push(val); - new_idx - } - - pub fn gensym(&self, val: T) -> Name { - let mut vect = self.vect.borrow_mut(); - let new_idx = Name((*vect).len() as u32); - // leave out of .map to avoid colliding - (*vect).push(val); - new_idx - } - - pub fn get(&self, idx: Name) -> T { - let vect = self.vect.borrow(); - (*vect)[idx.usize()].clone() - } - - pub fn len(&self) -> usize { - let vect = self.vect.borrow(); - (*vect).len() - } - - pub fn find(&self, val: &Q) -> Option - where T: Borrow, Q: Eq + Hash { - let map = self.map.borrow(); - match (*map).get(val) { - Some(v) => Some(*v), - None => None, - } - } - - pub fn clear(&self) { - *self.map.borrow_mut() = HashMap::new(); - *self.vect.borrow_mut() = Vec::new(); - } -} -// when traits can extend traits, we should extend index to get [] -#[cfg(not(stage0))] impl Interner { pub fn new() -> Interner { Interner { @@ -275,15 +209,6 @@ impl StrInterner { self.vect.borrow().len() } - #[cfg(stage0)] - pub fn find(&self, val: &Q) -> Option - where RcStr: Borrow, Q: Eq + Hash { - match (*self.map.borrow()).get(val) { - Some(v) => Some(*v), - None => None, - } - } - #[cfg(not(stage0))] pub fn find(&self, val: &Q) -> Option where RcStr: Borrow, Q: Eq + Hash { match (*self.map.borrow()).get(val) { @@ -309,7 +234,7 @@ mod tests { use ast::Name; #[test] - #[should_fail] + #[should_panic] fn i1 () { let i : Interner = Interner::new(); i.get(Name(13)); diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 89854f5d97..ec60864632 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -9,9 +9,9 @@ // except according to those terms. use ast; -use parse::{new_parse_sess}; +use parse::new_parse_sess; use parse::{ParseSess,string_to_filemap,filemap_to_tts}; -use parse::{new_parser_from_source_str}; +use parse::new_parser_from_source_str; use parse::parser::Parser; use parse::token; use ptr::P; @@ -58,14 +58,14 @@ pub fn string_to_expr (source_str : String) -> P { /// Parse a string, return an item pub fn string_to_item (source_str : String) -> Option> { with_error_checking_parse(source_str, |p| { - p.parse_item(Vec::new()) + p.parse_item() }) } /// Parse a string, return a stmt pub fn string_to_stmt(source_str : String) -> P { with_error_checking_parse(source_str, |p| { - p.parse_stmt(Vec::new()) + p.parse_stmt().unwrap() }) } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 0a39d38090..1649934f4b 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -226,23 +226,23 @@ mod test { fn test_move_iter() { let v = SmallVector::zero(); let v: Vec = v.into_iter().collect(); - assert_eq!(Vec::new(), v); + assert_eq!(v, Vec::new()); let v = SmallVector::one(1); - assert_eq!(vec![1], v.into_iter().collect::>()); + assert_eq!(v.into_iter().collect::>(), [1]); let v = SmallVector::many(vec![1, 2, 3]); - assert_eq!(vec!(1, 2, 3), v.into_iter().collect::>()); + assert_eq!(v.into_iter().collect::>(), [1, 2, 3]); } #[test] - #[should_fail] + #[should_panic] fn test_expect_one_zero() { let _: isize = SmallVector::zero().expect_one(""); } #[test] - #[should_fail] + #[should_panic] fn test_expect_one_many() { SmallVector::many(vec!(1, 2)).expect_one(""); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 21cb62b0a0..5c345c7564 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -32,13 +32,13 @@ use codemap::Span; use ptr::P; use owned_slice::OwnedSlice; -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() FkItemFn(Ident, &'a Generics, Unsafety, Abi), /// fn foo(&self) - FkMethod(Ident, &'a Generics, &'a Method), + FkMethod(Ident, &'a MethodSig), /// |x, y| ... /// proc(x, y) ... @@ -77,8 +77,8 @@ pub trait Visitor<'v> : Sized { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) { walk_fn(self, fk, fd, b, s) } - fn visit_ty_method(&mut self, t: &'v TypeMethod) { walk_ty_method(self, t) } - fn visit_trait_item(&mut self, t: &'v TraitItem) { walk_trait_item(self, t) } + fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) } + fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) } fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) } fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { walk_ty_param_bound(self, bounds) @@ -125,9 +125,6 @@ pub trait Visitor<'v> : Sized { fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) } - fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) { - walk_qpath(self, qpath_span, qpath) - } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) } @@ -146,13 +143,7 @@ pub fn walk_inlined_item<'v,V>(visitor: &mut V, item: &'v InlinedItem) IIItem(ref i) => visitor.visit_item(&**i), IIForeign(ref i) => visitor.visit_foreign_item(&**i), IITraitItem(_, ref ti) => visitor.visit_trait_item(ti), - IIImplItem(_, MethodImplItem(ref m)) => { - walk_method_helper(visitor, &**m) - } - IIImplItem(_, TypeImplItem(ref typedef)) => { - visitor.visit_ident(typedef.span, typedef.ident); - visitor.visit_ty(&*typedef.typ); - } + IIImplItem(_, ref ii) => visitor.visit_impl_item(ii), } } @@ -205,8 +196,6 @@ pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, } } -/// Like with walk_method_helper this doesn't correspond to a method -/// in Visitor, and so it gets a _helper suffix. pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v PolyTraitRef, _modifier: &'v TraitBoundModifier) @@ -216,8 +205,6 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, visitor.visit_trait_ref(&trait_ref.trait_ref); } -/// Like with walk_method_helper this doesn't correspond to a method -/// in Visitor, and so it gets a _helper suffix. pub fn walk_trait_ref<'v,V>(visitor: &mut V, trait_ref: &'v TraitRef) where V: Visitor<'v> @@ -282,6 +269,9 @@ 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) } + ItemDefaultImpl(_, ref trait_ref) => { + visitor.visit_trait_ref(trait_ref) + } ItemImpl(_, _, ref type_parameters, ref trait_reference, @@ -294,15 +284,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } visitor.visit_ty(&**typ); for impl_item in impl_items { - match *impl_item { - MethodImplItem(ref method) => { - walk_method_helper(visitor, &**method) - } - TypeImplItem(ref typedef) => { - visitor.visit_ident(typedef.span, typedef.ident); - visitor.visit_ty(&*typedef.typ); - } - } + visitor.visit_impl_item(impl_item); } } ItemStruct(ref struct_definition, ref generics) => { @@ -396,16 +378,16 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_ret_ty(visitor, &function_declaration.decl.output); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyPath(ref path, id) => { - visitor.visit_path(path, id); + TyPath(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(&qself.ty); + } + visitor.visit_path(path, typ.id); } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); walk_ty_param_bounds_helper(visitor, bounds); } - TyQPath(ref qpath) => { - visitor.visit_qpath(typ.span, &**qpath); - } TyFixedLengthVec(ref ty, ref expression) => { visitor.visit_ty(&**ty); visitor.visit_expr(&**expression) @@ -433,14 +415,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, - qpath_span: Span, - qpath: &'v QPath) { - visitor.visit_ty(&*qpath.self_type); - visitor.visit_trait_ref(&*qpath.trait_ref); - visitor.visit_path_segment(qpath_span, &qpath.item_path); -} - pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { @@ -569,15 +543,11 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, } } -pub fn walk_ty_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v TyParam) { - visitor.visit_ident(param.span, param.ident); - walk_ty_param_bounds_helper(visitor, ¶m.bounds); - walk_ty_opt(visitor, ¶m.default); -} - pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { - for type_parameter in &*generics.ty_params { - walk_ty_param(visitor, type_parameter); + for param in &*generics.ty_params { + visitor.visit_ident(param.span, param.ident); + walk_ty_param_bounds_helper(visitor, ¶m.bounds); + walk_ty_opt(visitor, ¶m.default); } walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in &generics.where_clause.predicates { @@ -622,28 +592,6 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: & walk_fn_ret_ty(visitor, &function_declaration.output) } -// Note: there is no visit_method() method in the visitor, instead override -// visit_fn() and check for FkMethod(). I named this visit_method_helper() -// because it is not a default impl of any method, though I doubt that really -// clarifies anything. - Niko -pub fn walk_method_helper<'v, V: Visitor<'v>>(visitor: &mut V, method: &'v Method) { - match method.node { - MethDecl(ident, ref generics, _, _, _, ref decl, ref body, _) => { - visitor.visit_ident(method.span, ident); - visitor.visit_fn(FkMethod(ident, generics, method), - &**decl, - &**body, - method.span, - method.id); - for attr in &method.attrs { - visitor.visit_attribute(attr); - } - - }, - MethMac(ref mac) => visitor.visit_mac(mac) - } -} - pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>, function_declaration: &'v FnDecl, @@ -655,14 +603,9 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, FkItemFn(_, generics, _, _) => { visitor.visit_generics(generics); } - FkMethod(_, generics, method) => { - visitor.visit_generics(generics); - match method.node { - MethDecl(_, _, _, ref explicit_self, _, _, _, _) => - visitor.visit_explicit_self(explicit_self), - MethMac(ref mac) => - visitor.visit_mac(mac) - } + FkMethod(_, sig) => { + visitor.visit_generics(&sig.generics); + visitor.visit_explicit_self(&sig.explicit_self); } FkFnBlock(..) => {} } @@ -670,25 +613,43 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, visitor.visit_block(function_body) } -pub fn walk_ty_method<'v, V: Visitor<'v>>(visitor: &mut V, method_type: &'v TypeMethod) { - visitor.visit_ident(method_type.span, method_type.ident); - visitor.visit_explicit_self(&method_type.explicit_self); - for argument_type in &method_type.decl.inputs { - visitor.visit_ty(&*argument_type.ty) - } - visitor.visit_generics(&method_type.generics); - walk_fn_ret_ty(visitor, &method_type.decl.output); - for attr in &method_type.attrs { +pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { + visitor.visit_ident(trait_item.span, trait_item.ident); + for attr in &trait_item.attrs { visitor.visit_attribute(attr); } + match trait_item.node { + MethodTraitItem(ref sig, None) => { + visitor.visit_explicit_self(&sig.explicit_self); + visitor.visit_generics(&sig.generics); + walk_fn_decl(visitor, &sig.decl); + } + MethodTraitItem(ref sig, Some(ref body)) => { + visitor.visit_fn(FkMethod(trait_item.ident, sig), &sig.decl, + body, trait_item.span, trait_item.id); + } + TypeTraitItem(ref bounds, ref default) => { + walk_ty_param_bounds_helper(visitor, bounds); + walk_ty_opt(visitor, default); + } + } } -pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v TraitItem) { - match *trait_method { - RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type), - ProvidedMethod(ref method) => walk_method_helper(visitor, &**method), - TypeTraitItem(ref associated_type) => { - walk_ty_param(visitor, &associated_type.ty_param); +pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { + visitor.visit_ident(impl_item.span, impl_item.ident); + for attr in &impl_item.attrs { + visitor.visit_attribute(attr); + } + match impl_item.node { + MethodImplItem(ref sig, ref body) => { + visitor.visit_fn(FkMethod(impl_item.ident, sig), &sig.decl, + body, impl_item.span, impl_item.id); + } + TypeImplItem(ref ty) => { + visitor.visit_ty(ty); + } + MacImplItem(ref mac) => { + visitor.visit_mac(mac); } } } @@ -866,12 +827,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } - ExprPath(ref path) => { + ExprPath(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(&qself.ty); + } visitor.visit_path(path, expression.id) } - ExprQPath(ref qpath) => { - visitor.visit_qpath(expression.span, &**qpath) - } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 5418533aff..74ec3406f7 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -19,8 +19,11 @@ //! # Examples //! //! ```no_run +//! # #![feature(rustc_private)] //! extern crate term; //! +//! use std::io::prelude::*; +//! //! fn main() { //! let mut t = term::stdout().unwrap(); //! @@ -38,6 +41,8 @@ //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx //! [ti]: https://en.wikipedia.org/wiki/Terminfo +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "term"] #![unstable(feature = "rustc_private", reason = "use the crates.io `term` library instead")] @@ -52,14 +57,11 @@ #![feature(box_syntax)] #![feature(collections)] -#![feature(int_uint)] -#![feature(old_io)] -#![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] -#![feature(unicode)] #![feature(std_misc)] -#![feature(env)] +#![feature(str_char)] +#![feature(path_ext)] #![cfg_attr(windows, feature(libc))] #[macro_use] extern crate log; @@ -68,27 +70,28 @@ pub use terminfo::TerminfoTerminal; #[cfg(windows)] pub use win::WinConsole; -use std::old_io::IoResult; +use std::io::prelude::*; +use std::io; pub mod terminfo; #[cfg(windows)] mod win; -/// A hack to work around the fact that `Box` does not -/// currently implement `Writer`. +/// A hack to work around the fact that `Box` does not +/// currently implement `Write`. pub struct WriterWrapper { - wrapped: Box, + wrapped: Box, } -impl Writer for WriterWrapper { +impl Write for WriterWrapper { #[inline] - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - self.wrapped.write_all(buf) + fn write(&mut self, buf: &[u8]) -> io::Result { + self.wrapped.write(buf) } #[inline] - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { self.wrapped.flush() } } @@ -98,7 +101,7 @@ impl Writer for WriterWrapper { /// opened. pub fn stdout() -> Option + Send>> { TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stdout() as Box, + wrapped: box std::io::stdout(), }) } @@ -107,14 +110,14 @@ pub fn stdout() -> Option + Send>> { /// opened. pub fn stdout() -> Option + Send>> { let ti = TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stdout() as Box, + wrapped: box std::io::stdout(), }); match ti { Some(t) => Some(t), None => { WinConsole::new(WriterWrapper { - wrapped: box std::old_io::stdout() as Box, + wrapped: box std::io::stdout(), }) } } @@ -125,7 +128,7 @@ pub fn stdout() -> Option + Send>> { /// opened. pub fn stderr() -> Option + Send>> { TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stderr() as Box, + wrapped: box std::io::stderr(), }) } @@ -134,14 +137,14 @@ pub fn stderr() -> Option + Send>> { /// opened. pub fn stderr() -> Option + Send>> { let ti = TerminfoTerminal::new(WriterWrapper { - wrapped: box std::old_io::stderr() as Box, + wrapped: box std::io::stderr(), }); match ti { Some(t) => Some(t), None => { WinConsole::new(WriterWrapper { - wrapped: box std::old_io::stderr() as Box, + wrapped: box std::io::stderr(), }) } } @@ -153,23 +156,23 @@ pub mod color { /// Number for a terminal color pub type Color = u16; - pub const BLACK: Color = 0u16; - pub const RED: Color = 1u16; - pub const GREEN: Color = 2u16; - pub const YELLOW: Color = 3u16; - pub const BLUE: Color = 4u16; - pub const MAGENTA: Color = 5u16; - pub const CYAN: Color = 6u16; - pub const WHITE: Color = 7u16; - - pub const BRIGHT_BLACK: Color = 8u16; - pub const BRIGHT_RED: Color = 9u16; - pub const BRIGHT_GREEN: Color = 10u16; - pub const BRIGHT_YELLOW: Color = 11u16; - pub const BRIGHT_BLUE: Color = 12u16; - pub const BRIGHT_MAGENTA: Color = 13u16; - pub const BRIGHT_CYAN: Color = 14u16; - pub const BRIGHT_WHITE: Color = 15u16; + pub const BLACK: Color = 0; + pub const RED: Color = 1; + pub const GREEN: Color = 2; + pub const YELLOW: Color = 3; + pub const BLUE: Color = 4; + pub const MAGENTA: Color = 5; + pub const CYAN: Color = 6; + pub const WHITE: Color = 7; + + pub const BRIGHT_BLACK: Color = 8; + pub const BRIGHT_RED: Color = 9; + pub const BRIGHT_GREEN: Color = 10; + pub const BRIGHT_YELLOW: Color = 11; + pub const BRIGHT_BLUE: Color = 12; + pub const BRIGHT_MAGENTA: Color = 13; + pub const BRIGHT_CYAN: Color = 14; + pub const BRIGHT_WHITE: Color = 15; } /// Terminal attributes @@ -181,7 +184,7 @@ pub mod attr { /// Most attributes can only be turned on and must be turned off with term.reset(). /// The ones that can be turned off explicitly take a boolean value. /// Color is also represented as an attribute for convenience. - #[derive(Copy)] + #[derive(Copy, Clone)] pub enum Attr { /// Bold (or possibly bright) mode Bold, @@ -208,7 +211,7 @@ pub mod attr { /// A terminal with similar capabilities to an ANSI Terminal /// (foreground/background colors etc). -pub trait Terminal: Writer { +pub trait Terminal: Write { /// Sets the foreground color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, @@ -216,7 +219,7 @@ pub trait Terminal: Writer { /// /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` /// if there was an I/O error. - fn fg(&mut self, color: color::Color) -> IoResult; + fn fg(&mut self, color: color::Color) -> io::Result; /// Sets the background color to the given color. /// @@ -225,19 +228,19 @@ pub trait Terminal: Writer { /// /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` /// if there was an I/O error. - fn bg(&mut self, color: color::Color) -> IoResult; + fn bg(&mut self, color: color::Color) -> io::Result; /// Sets the given terminal attribute, if supported. Returns `Ok(true)` /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if /// there was an I/O error. - fn attr(&mut self, attr: attr::Attr) -> IoResult; + fn attr(&mut self, attr: attr::Attr) -> io::Result; /// Returns whether the given terminal attribute is supported. fn supports_attr(&self, attr: attr::Attr) -> bool; /// Resets all terminal attributes and color to the default. /// Returns `Ok()`. - fn reset(&mut self) -> IoResult<()>; + fn reset(&mut self) -> io::Result<()>; /// Gets an immutable reference to the stream inside fn get_ref<'a>(&'a self) -> &'a T; @@ -247,7 +250,7 @@ pub trait Terminal: Writer { } /// A terminal which can be unwrapped. -pub trait UnwrappableTerminal: Terminal { +pub trait UnwrappableTerminal: Terminal { /// Returns the contained stream, destroying the `Terminal` fn unwrap(self) -> T; } diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index be1c623c85..4840cd1fdd 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -11,8 +11,9 @@ //! Terminfo database interface. use std::collections::HashMap; -use std::old_io::IoResult; use std::env; +use std::io::prelude::*; +use std::io; use attr; use color; @@ -72,8 +73,8 @@ pub struct TerminfoTerminal { ti: Box } -impl Terminal for TerminfoTerminal { - fn fg(&mut self, color: color::Color) -> IoResult { +impl Terminal for TerminfoTerminal { + fn fg(&mut self, color: color::Color) -> io::Result { let color = self.dim_if_necessary(color); if self.num_colors > color { let s = expand(self.ti @@ -81,7 +82,7 @@ impl Terminal for TerminfoTerminal { .get("setaf") .unwrap() , - &[Number(color as int)], &mut Variables::new()); + &[Number(color as isize)], &mut Variables::new()); if s.is_ok() { try!(self.out.write_all(&s.unwrap())); return Ok(true) @@ -90,7 +91,7 @@ impl Terminal for TerminfoTerminal { Ok(false) } - fn bg(&mut self, color: color::Color) -> IoResult { + fn bg(&mut self, color: color::Color) -> io::Result { let color = self.dim_if_necessary(color); if self.num_colors > color { let s = expand(self.ti @@ -98,7 +99,7 @@ impl Terminal for TerminfoTerminal { .get("setab") .unwrap() , - &[Number(color as int)], &mut Variables::new()); + &[Number(color as isize)], &mut Variables::new()); if s.is_ok() { try!(self.out.write_all(&s.unwrap())); return Ok(true) @@ -107,7 +108,7 @@ impl Terminal for TerminfoTerminal { Ok(false) } - fn attr(&mut self, attr: attr::Attr) -> IoResult { + fn attr(&mut self, attr: attr::Attr) -> io::Result { match attr { attr::ForegroundColor(c) => self.fg(c), attr::BackgroundColor(c) => self.bg(c), @@ -140,7 +141,7 @@ impl Terminal for TerminfoTerminal { } } - fn reset(&mut self) -> IoResult<()> { + fn reset(&mut self) -> io::Result<()> { let mut cap = self.ti.strings.get("sgr0"); if cap.is_none() { // are there any terminals that have color/attrs and not sgr0? @@ -164,11 +165,11 @@ impl Terminal for TerminfoTerminal { fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out } } -impl UnwrappableTerminal for TerminfoTerminal { +impl UnwrappableTerminal for TerminfoTerminal { fn unwrap(self) -> T { self.out } } -impl TerminfoTerminal { +impl TerminfoTerminal { /// Returns `None` whenever the terminal cannot be created for some /// reason. pub fn new(out: T) -> Option+Send+'static>> { @@ -180,21 +181,24 @@ impl TerminfoTerminal { } }; - let entry = open(&term[..]); - if entry.is_err() { - if env::var("MSYSCON").ok().map_or(false, |s| { - "mintty.exe" == s - }) { - // msys terminal - return Some(box TerminfoTerminal {out: out, - ti: msys_terminfo(), - num_colors: 8} as Box+Send>); - } - debug!("error finding terminfo entry: {:?}", entry.err().unwrap()); - return None; - } + let mut file = match open(&term[..]) { + Ok(f) => f, + Err(err) => return match env::var("MSYSCON") { + Ok(ref val) if &val[..] == "mintty.exe" => { + // msys terminal + Some(box TerminfoTerminal{ + out: out, + ti: msys_terminfo(), + num_colors: 8, + }) + }, + _ => { + debug!("error finding terminfo entry: {:?}", err); + None + }, + }, + }; - let mut file = entry.unwrap(); let ti = parse(&mut file, false); if ti.is_err() { debug!("error parsing terminfo entry: {:?}", ti.err().unwrap()); @@ -209,7 +213,7 @@ impl TerminfoTerminal { return Some(box TerminfoTerminal {out: out, ti: inf, - num_colors: nc} as Box+Send>); + num_colors: nc}); } fn dim_if_necessary(&self, color: color::Color) -> color::Color { @@ -220,12 +224,12 @@ impl TerminfoTerminal { } -impl Writer for TerminfoTerminal { - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - self.out.write_all(buf) +impl Write for TerminfoTerminal { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.out.write(buf) } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { self.out.flush() } } diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index 0b577f8de7..01586b8f36 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -18,7 +18,7 @@ use std::ascii::OwnedAsciiExt; use std::mem::replace; use std::iter::repeat; -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum States { Nothing, Percent, @@ -27,15 +27,15 @@ enum States { PushParam, CharConstant, CharClose, - IntConstant(int), + IntConstant(isize), FormatPattern(Flags, FormatState), - SeekIfElse(int), - SeekIfElsePercent(int), - SeekIfEnd(int), - SeekIfEndPercent(int) + SeekIfElse(isize), + SeekIfElsePercent(isize), + SeekIfEnd(isize), + SeekIfEndPercent(isize) } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] enum FormatState { FormatStateFlags, FormatStateWidth, @@ -47,7 +47,7 @@ enum FormatState { #[derive(Clone)] pub enum Param { Words(String), - Number(int) + Number(isize) } /// Container for static and dynamic variable arrays @@ -128,7 +128,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) // if c is 0, use 0200 (128) for ncurses compatibility Number(c) => { output.push(if c == 0 { - 128u8 + 128 } else { c as u8 }) @@ -143,7 +143,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) '{' => state = IntConstant(0), 'l' => if stack.len() > 0 { match stack.pop().unwrap() { - Words(s) => stack.push(Number(s.len() as int)), + Words(s) => stack.push(Number(s.len() as isize)), _ => return Err("a non-str was used with %l".to_string()) } } else { return Err("stack is empty".to_string()) }, @@ -268,7 +268,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) ' ' => flags.space = true, '.' => fstate = FormatStatePrecision, '0'...'9' => { - flags.width = cur as uint - '0' as uint; + flags.width = cur as usize - '0' as usize; fstate = FormatStateWidth; } _ => unreachable!() @@ -305,12 +305,12 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) if cur >= 'A' && cur <= 'Z' { if stack.len() > 0 { let idx = (cur as u8) - b'A'; - vars.sta[idx as uint] = stack.pop().unwrap(); + vars.sta[idx as usize] = stack.pop().unwrap(); } else { return Err("stack is empty".to_string()) } } else if cur >= 'a' && cur <= 'z' { if stack.len() > 0 { let idx = (cur as u8) - b'a'; - vars.dyn[idx as uint] = stack.pop().unwrap(); + vars.dyn[idx as usize] = stack.pop().unwrap(); } else { return Err("stack is empty".to_string()) } } else { return Err("bad variable name in %P".to_string()); @@ -319,16 +319,16 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) GetVar => { if cur >= 'A' && cur <= 'Z' { let idx = (cur as u8) - b'A'; - stack.push(vars.sta[idx as uint].clone()); + stack.push(vars.sta[idx as usize].clone()); } else if cur >= 'a' && cur <= 'z' { let idx = (cur as u8) - b'a'; - stack.push(vars.dyn[idx as uint].clone()); + stack.push(vars.dyn[idx as usize].clone()); } else { return Err("bad variable name in %g".to_string()); } }, CharConstant => { - stack.push(Number(c as int)); + stack.push(Number(c as isize)); state = CharClose; }, CharClose => { @@ -343,10 +343,10 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) state = Nothing; } '0'...'9' => { - state = IntConstant(i*10 + (cur as int - '0' as int)); + state = IntConstant(i*10 + (cur as isize - '0' as isize)); old_state = Nothing; } - _ => return Err("bad int constant".to_string()) + _ => return Err("bad isize constant".to_string()) } } FormatPattern(ref mut flags, ref mut fstate) => { @@ -372,7 +372,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) flags.space = true; } (FormatStateFlags,'0'...'9') => { - flags.width = cur as uint - '0' as uint; + flags.width = cur as usize - '0' as usize; *fstate = FormatStateWidth; } (FormatStateFlags,'.') => { @@ -380,7 +380,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) } (FormatStateWidth,'0'...'9') => { let old = flags.width; - flags.width = flags.width * 10 + (cur as uint - '0' as uint); + flags.width = flags.width * 10 + (cur as usize - '0' as usize); if flags.width < old { return Err("format width overflow".to_string()) } } (FormatStateWidth,'.') => { @@ -388,7 +388,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) } (FormatStatePrecision,'0'...'9') => { let old = flags.precision; - flags.precision = flags.precision * 10 + (cur as uint - '0' as uint); + flags.precision = flags.precision * 10 + (cur as usize - '0' as usize); if flags.precision < old { return Err("format precision overflow".to_string()) } @@ -444,10 +444,10 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) Ok(output) } -#[derive(Copy, PartialEq)] +#[derive(Copy, Clone, PartialEq)] struct Flags { - width: uint, - precision: uint, + width: usize, + precision: usize, alternate: bool, left: bool, sign: bool, @@ -461,7 +461,7 @@ impl Flags { } } -#[derive(Copy)] +#[derive(Copy, Clone)] enum FormatOp { FormatDigit, FormatOctal, @@ -647,20 +647,20 @@ mod test { #[test] fn test_comparison_ops() { - let v = [('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8])]; + let v = [('<', [1, 0, 0]), ('=', [0, 1, 0]), ('>', [0, 0, 1])]; for &(op, bs) in &v { let s = format!("%{{1}}%{{2}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); - assert_eq!(res.unwrap(), vec!(b'0' + bs[0])); + assert_eq!(res.unwrap(), [b'0' + bs[0]]); let s = format!("%{{1}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); - assert_eq!(res.unwrap(), vec!(b'0' + bs[1])); + assert_eq!(res.unwrap(), [b'0' + bs[1]]); let s = format!("%{{2}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); - assert_eq!(res.unwrap(), vec!(b'0' + bs[2])); + assert_eq!(res.unwrap(), [b'0' + bs[2]]); } } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index c147e6aa05..01d191f301 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -13,7 +13,8 @@ //! ncurses-compatible compiled terminfo format parsing (term(5)) use std::collections::HashMap; -use std::old_io; +use std::io::prelude::*; +use std::io; use super::super::TermInfo; // These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable. @@ -158,7 +159,7 @@ pub static stringnames: &'static[&'static str] = &[ "cbt", "_", "cr", "csr", "tb "box1"]; /// Parse a compiled terminfo entry, using long capability names if `longnames` is true -pub fn parse(file: &mut old_io::Reader, longnames: bool) +pub fn parse(file: &mut Read, longnames: bool) -> Result, String> { macro_rules! try { ($e:expr) => ( match $e { @@ -182,37 +183,37 @@ pub fn parse(file: &mut old_io::Reader, longnames: bool) } // Check magic number - let magic = try!(file.read_le_u16()); + let magic = try!(read_le_u16(file)); if magic != 0x011A { return Err(format!("invalid magic number: expected {:x}, found {:x}", - 0x011A as usize, magic as usize)); + 0x011A_usize, magic as usize)); } - let names_bytes = try!(file.read_le_i16()) as int; - let bools_bytes = try!(file.read_le_i16()) as int; - let numbers_count = try!(file.read_le_i16()) as int; - let string_offsets_count = try!(file.read_le_i16()) as int; - let string_table_bytes = try!(file.read_le_i16()) as int; + let names_bytes = try!(read_le_u16(file)) as isize; + let bools_bytes = try!(read_le_u16(file)) as isize; + let numbers_count = try!(read_le_u16(file)) as isize; + let string_offsets_count = try!(read_le_u16(file)) as isize; + let string_table_bytes = try!(read_le_u16(file)) as isize; assert!(names_bytes > 0); - if (bools_bytes as uint) > boolnames.len() { + if (bools_bytes as usize) > boolnames.len() { return Err("incompatible file: more booleans than \ expected".to_string()); } - if (numbers_count as uint) > numnames.len() { + if (numbers_count as usize) > numnames.len() { return Err("incompatible file: more numbers than \ expected".to_string()); } - if (string_offsets_count as uint) > stringnames.len() { + if (string_offsets_count as usize) > stringnames.len() { return Err("incompatible file: more string offsets than \ expected".to_string()); } // don't read NUL - let bytes = try!(file.read_exact(names_bytes as uint - 1)); + let bytes = try!(read_exact(file, names_bytes as usize - 1)); let names_str = match String::from_utf8(bytes) { Ok(s) => s, Err(_) => return Err("input not utf-8".to_string()), @@ -222,28 +223,28 @@ pub fn parse(file: &mut old_io::Reader, longnames: bool) .map(|s| s.to_string()) .collect(); - try!(file.read_byte()); // consume NUL + try!(read_byte(file)); // consume NUL let mut bools_map = HashMap::new(); if bools_bytes != 0 { for i in 0..bools_bytes { - let b = try!(file.read_byte()); + let b = try!(read_byte(file)); if b == 1 { - bools_map.insert(bnames[i as uint].to_string(), true); + bools_map.insert(bnames[i as usize].to_string(), true); } } } if (bools_bytes + names_bytes) % 2 == 1 { - try!(file.read_byte()); // compensate for padding + try!(read_byte(file)); // compensate for padding } let mut numbers_map = HashMap::new(); if numbers_count != 0 { for i in 0..numbers_count { - let n = try!(file.read_le_u16()); + let n = try!(read_le_u16(file)); if n != 0xFFFF { - numbers_map.insert(nnames[i as uint].to_string(), n); + numbers_map.insert(nnames[i as usize].to_string(), n); } } } @@ -253,12 +254,12 @@ pub fn parse(file: &mut old_io::Reader, longnames: bool) if string_offsets_count != 0 { let mut string_offsets = Vec::with_capacity(10); for _ in 0..string_offsets_count { - string_offsets.push(try!(file.read_le_u16())); + string_offsets.push(try!(read_le_u16(file))); } - let string_table = try!(file.read_exact(string_table_bytes as uint)); + let string_table = try!(read_exact(file, string_table_bytes as usize)); - if string_table.len() != string_table_bytes as uint { + if string_table.len() != string_table_bytes as usize { return Err("error: hit EOF before end of string \ table".to_string()); } @@ -284,13 +285,13 @@ pub fn parse(file: &mut old_io::Reader, longnames: bool) // Find the offset of the NUL we want to go to - let nulpos = string_table[offset as uint .. string_table_bytes as uint] + let nulpos = string_table[offset as usize .. string_table_bytes as usize] .iter().position(|&b| b == 0); match nulpos { Some(len) => { string_map.insert(name.to_string(), - string_table[offset as uint .. - (offset as uint + len)].to_vec()) + string_table[offset as usize .. + (offset as usize + len)].to_vec()) }, None => { return Err("invalid file: missing NUL in \ @@ -309,6 +310,25 @@ pub fn parse(file: &mut old_io::Reader, longnames: bool) }) } +fn read_le_u16(r: &mut R) -> io::Result { + let mut b = [0; 2]; + assert_eq!(try!(r.read(&mut b)), 2); + Ok((b[0] as u16) | ((b[1] as u16) << 8)) +} + +fn read_byte(r: &mut R) -> io::Result { + let mut b = [0; 1]; + assert_eq!(try!(r.read(&mut b)), 1); + Ok(b[0]) +} + +fn read_exact(r: &mut R, sz: usize) -> io::Result> { + let mut v = Vec::with_capacity(sz); + try!(r.take(sz as u64).read_to_end(&mut v)); + assert_eq!(v.len(), sz); + Ok(v) +} + /// Create a dummy TermInfo struct for msys terminals pub fn msys_terminfo() -> Box { let mut strings = HashMap::new(); diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index c40a5534ef..3083f8e892 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -12,12 +12,14 @@ //! //! Does not support hashed database, only filesystem! -use std::old_io::File; -use std::old_io::fs::PathExtensions; use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::path::PathBuf; /// Return path to database entry for `term` -pub fn get_dbpath_for_term(term: &str) -> Option> { +#[allow(deprecated)] +pub fn get_dbpath_for_term(term: &str) -> Option> { if term.len() == 0 { return None; } @@ -28,9 +30,9 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { let first_char = term.char_at(0); // Find search directory - match env::var("TERMINFO") { - Ok(dir) => dirs_to_search.push(Path::new(dir)), - Err(..) => { + match env::var_os("TERMINFO") { + Some(dir) => dirs_to_search.push(PathBuf::from(dir)), + None => { if homedir.is_some() { // ncurses compatibility; dirs_to_search.push(homedir.unwrap().join(".terminfo")) @@ -38,9 +40,9 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { match env::var("TERMINFO_DIRS") { Ok(dirs) => for i in dirs.split(':') { if i == "" { - dirs_to_search.push(Path::new("/usr/share/terminfo")); + dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); } else { - dirs_to_search.push(Path::new(i)); + dirs_to_search.push(PathBuf::from(i)); } }, // Found nothing in TERMINFO_DIRS, use the default paths: @@ -48,9 +50,9 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { // ~/.terminfo, ncurses will search /etc/terminfo, then // /lib/terminfo, and eventually /usr/share/terminfo. Err(..) => { - dirs_to_search.push(Path::new("/etc/terminfo")); - dirs_to_search.push(Path::new("/lib/terminfo")); - dirs_to_search.push(Path::new("/usr/share/terminfo")); + dirs_to_search.push(PathBuf::from("/etc/terminfo")); + dirs_to_search.push(PathBuf::from("/lib/terminfo")); + dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); } } } @@ -60,13 +62,13 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { for p in &dirs_to_search { if p.exists() { let f = first_char.to_string(); - let newp = p.join_many(&[&f[..], term]); + let newp = p.join(&f).join(term); if newp.exists() { return Some(box newp); } // on some installations the dir is named after the hex of the char (e.g. OS X) - let f = format!("{:x}", first_char as uint); - let newp = p.join_many(&[&f[..], term]); + let f = format!("{:x}", first_char as usize); + let newp = p.join(&f).join(term); if newp.exists() { return Some(box newp); } @@ -95,17 +97,17 @@ pub fn open(term: &str) -> Result { fn test_get_dbpath_for_term() { // woefully inadequate test coverage // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's) - use std::os::{setenv, unsetenv}; + use std::env; // FIXME (#9639): This needs to handle non-utf8 paths fn x(t: &str) -> String { let p = get_dbpath_for_term(t).expect("no terminfo entry found"); - p.as_str().unwrap().to_string() + p.to_str().unwrap().to_string() }; assert!(x("screen") == "/usr/share/terminfo/s/screen"); assert!(get_dbpath_for_term("") == None); - setenv("TERMINFO_DIRS", ":"); + env::set_var("TERMINFO_DIRS", ":"); assert!(x("screen") == "/usr/share/terminfo/s/screen"); - unsetenv("TERMINFO_DIRS"); + env::remove_var("TERMINFO_DIRS"); } #[test] diff --git a/src/libterm/win.rs b/src/libterm/win.rs index e93b956dc7..66ef5e8661 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -14,7 +14,8 @@ extern crate libc; -use std::old_io::IoResult; +use std::io; +use std::io::prelude::*; use attr; use color; @@ -86,7 +87,7 @@ fn bits_to_color(bits: u16) -> color::Color { color | (bits & 0x8) // copy the hi-intensity bit } -impl WinConsole { +impl WinConsole { fn apply(&mut self) { let _unused = self.buf.flush(); let mut accum: libc::WORD = 0; @@ -103,7 +104,7 @@ impl WinConsole { // terminal! Admittedly, this is fragile, since stderr could be // redirected to a different console. This is good enough for // rustc though. See #13400. - let out = GetStdHandle(-11); + let out = GetStdHandle(-11i32 as libc::DWORD); SetConsoleTextAttribute(out, accum); } } @@ -115,7 +116,8 @@ impl WinConsole { let bg; unsafe { let mut buffer_info = ::std::mem::uninitialized(); - if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 { + if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as libc::DWORD), + &mut buffer_info) != 0 { fg = bits_to_color(buffer_info.wAttributes); bg = bits_to_color(buffer_info.wAttributes >> 4); } else { @@ -125,36 +127,36 @@ impl WinConsole { } Some(box WinConsole { buf: out, def_foreground: fg, def_background: bg, - foreground: fg, background: bg } as Box+Send>) + foreground: fg, background: bg }) } } -impl Writer for WinConsole { - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { - self.buf.write_all(buf) +impl Write for WinConsole { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.buf.write(buf) } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { self.buf.flush() } } -impl Terminal for WinConsole { - fn fg(&mut self, color: color::Color) -> IoResult { +impl Terminal for WinConsole { + fn fg(&mut self, color: color::Color) -> io::Result { self.foreground = color; self.apply(); Ok(true) } - fn bg(&mut self, color: color::Color) -> IoResult { + fn bg(&mut self, color: color::Color) -> io::Result { self.background = color; self.apply(); Ok(true) } - fn attr(&mut self, attr: attr::Attr) -> IoResult { + fn attr(&mut self, attr: attr::Attr) -> io::Result { match attr { attr::ForegroundColor(f) => { self.foreground = f; @@ -179,7 +181,7 @@ impl Terminal for WinConsole { } } - fn reset(&mut self) -> IoResult<()> { + fn reset(&mut self) -> io::Result<()> { self.foreground = self.def_foreground; self.background = self.def_background; self.apply(); @@ -192,6 +194,6 @@ impl Terminal for WinConsole { fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf } } -impl UnwrappableTerminal for WinConsole { +impl UnwrappableTerminal for WinConsole { fn unwrap(self) -> T { self.buf } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 82c1a4b119..c84703b93e 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -23,6 +23,8 @@ // running tests while providing a base that other test frameworks may // build off of. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "test"] #![unstable(feature = "test")] #![staged_api] @@ -36,18 +38,18 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(env)] -#![feature(int_uint)] -#![feature(old_io)] -#![feature(old_path)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] +#![feature(libc)] +#![feature(set_stdio)] +#![cfg_attr(test, feature(old_io))] extern crate getopts; extern crate serialize; -extern crate "serialize" as rustc_serialize; +extern crate serialize as rustc_serialize; extern crate term; +extern crate libc; pub use self::TestFn::*; pub use self::ColorConfig::*; @@ -60,22 +62,25 @@ use self::OutputLocation::*; use stats::Stats; use getopts::{OptGroup, optflag, optopt}; use serialize::Encodable; +use std::boxed::FnBox; use term::Terminal; use term::color::{Color, RED, YELLOW, GREEN, CYAN}; use std::any::Any; use std::cmp; use std::collections::BTreeMap; +use std::env; use std::fmt; -use std::old_io::stdio::StdWriter; -use std::old_io::{File, ChanReader, ChanWriter}; -use std::old_io; +use std::fs::File; +use std::io::prelude::*; +use std::io; use std::iter::repeat; use std::num::{Float, Int}; -use std::env; +use std::path::PathBuf; use std::sync::mpsc::{channel, Sender}; +use std::sync::{Arc, Mutex}; use std::thread; -use std::thunk::{Thunk, Invoke}; +use std::thunk::Thunk; use std::time::Duration; // to be used by rustc to compile tests in libtest @@ -85,7 +90,7 @@ pub mod test { Metric, MetricMap, StaticTestFn, StaticTestName, DynTestName, DynTestFn, run_test, test_main, test_main_static, filter_tests, - parse_opts, StaticBenchFn, ShouldFail}; + parse_opts, StaticBenchFn, ShouldPanic}; } pub mod stats; @@ -122,7 +127,7 @@ enum NamePadding { } impl TestDesc { - fn padded_name(&self, column_count: uint, align: NamePadding) -> String { + fn padded_name(&self, column_count: usize, align: NamePadding) -> String { let mut name = String::from_str(self.name.as_slice()); let fill = column_count.saturating_sub(name.len()); let mut pad = repeat(" ").take(fill).collect::(); @@ -154,7 +159,7 @@ pub enum TestFn { StaticBenchFn(fn(&mut Bencher)), StaticMetricFn(fn(&mut MetricMap)), DynTestFn(Thunk<'static>), - DynMetricFn(Box Invoke<&'a mut MetricMap>+'static>), + DynMetricFn(Box), DynBenchFn(Box) } @@ -189,7 +194,7 @@ impl fmt::Debug for TestFn { /// This is fed into functions marked with `#[bench]` to allow for /// set-up & tear-down before running a piece of code repeatedly via a /// call to `iter`. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Bencher { iterations: u64, dur: Duration, @@ -197,7 +202,7 @@ pub struct Bencher { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum ShouldFail { +pub enum ShouldPanic { No, Yes(Option<&'static str>) } @@ -208,7 +213,7 @@ pub enum ShouldFail { pub struct TestDesc { pub name: TestName, pub ignore: bool, - pub should_fail: ShouldFail, + pub should_panic: ShouldPanic, } unsafe impl Send for TestDesc {} @@ -276,7 +281,7 @@ pub fn test_main_static(args: env::Args, tests: &[TestDescAndFn]) { test_main(&args, owned_tests) } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum ColorConfig { AutoColor, AlwaysColor, @@ -288,7 +293,7 @@ pub struct TestOpts { pub run_ignored: bool, pub run_tests: bool, pub run_benchmarks: bool, - pub logfile: Option, + pub logfile: Option, pub nocapture: bool, pub color: ColorConfig, } @@ -334,7 +339,7 @@ The FILTER regex is tested against the name of all tests to run, and only those tests that match are run. By default, all tests are run in parallel. This can be altered with the -RUST_TEST_TASKS environment variable when running tests (set it to 1). +RUST_TEST_THREADS environment variable when running tests (set it to 1). All tests have their standard output and standard error captured by default. This can be overridden with the --nocapture flag or the RUST_TEST_NOCAPTURE=1 @@ -346,10 +351,10 @@ Test Attributes: takes no arguments. #[bench] - Indicates a function is a benchmark to be run. This function takes one argument (test::Bencher). - #[should_fail] - This function (also labeled with #[test]) will only pass if - the code causes a failure (an assertion failure or panic!) + #[should_panic] - This function (also labeled with #[test]) will only pass if + the code causes a panic (an assertion failure or panic!) A message may be provided, which the failure string must - contain: #[should_fail(expected = "foo")]. + contain: #[should_panic(expected = "foo")]. #[ignore] - When applied to a function which is already attributed as a test, then the test runner will ignore these tests during normal test runs. Running with --ignored will run these @@ -377,7 +382,7 @@ pub fn parse_opts(args: &[String]) -> Option { let run_ignored = matches.opt_present("ignored"); let logfile = matches.opt_str("logfile"); - let logfile = logfile.map(|s| Path::new(s)); + let logfile = logfile.map(|s| PathBuf::from(&s)); let run_benchmarks = matches.opt_present("bench"); let run_tests = ! run_benchmarks || @@ -414,7 +419,7 @@ pub fn parse_opts(args: &[String]) -> Option { #[derive(Clone, PartialEq)] pub struct BenchSamples { ns_iter_summ: stats::Summary, - mb_s: uint, + mb_s: usize, } #[derive(Clone, PartialEq)] @@ -437,25 +442,25 @@ struct ConsoleTestState { log_out: Option, out: OutputLocation, use_color: bool, - total: uint, - passed: uint, - failed: uint, - ignored: uint, - measured: uint, + total: usize, + passed: usize, + failed: usize, + ignored: usize, + measured: usize, metrics: MetricMap, failures: Vec<(TestDesc, Vec )> , - max_name_len: uint, // number of columns to fill when aligning names + max_name_len: usize, // number of columns to fill when aligning names } -impl ConsoleTestState { +impl ConsoleTestState { pub fn new(opts: &TestOpts, - _: Option) -> old_io::IoResult> { + _: Option) -> io::Result> { let log_out = match opts.logfile { Some(ref path) => Some(try!(File::create(path))), None => None }; let out = match term::stdout() { - None => Raw(old_io::stdio::stdout_raw()), + None => Raw(io::stdout()), Some(t) => Pretty(t) }; @@ -474,29 +479,29 @@ impl ConsoleTestState { }) } - pub fn write_ok(&mut self) -> old_io::IoResult<()> { + pub fn write_ok(&mut self) -> io::Result<()> { self.write_pretty("ok", term::color::GREEN) } - pub fn write_failed(&mut self) -> old_io::IoResult<()> { + pub fn write_failed(&mut self) -> io::Result<()> { self.write_pretty("FAILED", term::color::RED) } - pub fn write_ignored(&mut self) -> old_io::IoResult<()> { + pub fn write_ignored(&mut self) -> io::Result<()> { self.write_pretty("ignored", term::color::YELLOW) } - pub fn write_metric(&mut self) -> old_io::IoResult<()> { + pub fn write_metric(&mut self) -> io::Result<()> { self.write_pretty("metric", term::color::CYAN) } - pub fn write_bench(&mut self) -> old_io::IoResult<()> { + pub fn write_bench(&mut self) -> io::Result<()> { self.write_pretty("bench", term::color::CYAN) } pub fn write_pretty(&mut self, word: &str, - color: term::color::Color) -> old_io::IoResult<()> { + color: term::color::Color) -> io::Result<()> { match self.out { Pretty(ref mut term) => { if self.use_color { @@ -506,32 +511,41 @@ impl ConsoleTestState { if self.use_color { try!(term.reset()); } - Ok(()) + term.flush() + } + Raw(ref mut stdout) => { + try!(stdout.write_all(word.as_bytes())); + stdout.flush() } - Raw(ref mut stdout) => stdout.write_all(word.as_bytes()) } } - pub fn write_plain(&mut self, s: &str) -> old_io::IoResult<()> { + pub fn write_plain(&mut self, s: &str) -> io::Result<()> { match self.out { - Pretty(ref mut term) => term.write_all(s.as_bytes()), - Raw(ref mut stdout) => stdout.write_all(s.as_bytes()) + Pretty(ref mut term) => { + try!(term.write_all(s.as_bytes())); + term.flush() + }, + Raw(ref mut stdout) => { + try!(stdout.write_all(s.as_bytes())); + stdout.flush() + }, } } - pub fn write_run_start(&mut self, len: uint) -> old_io::IoResult<()> { + pub fn write_run_start(&mut self, len: usize) -> io::Result<()> { self.total = len; let noun = if len != 1 { "tests" } else { "test" }; self.write_plain(&format!("\nrunning {} {}\n", len, noun)) } pub fn write_test_start(&mut self, test: &TestDesc, - align: NamePadding) -> old_io::IoResult<()> { + align: NamePadding) -> io::Result<()> { let name = test.padded_name(self.max_name_len, align); self.write_plain(&format!("test {} ... ", name)) } - pub fn write_result(&mut self, result: &TestResult) -> old_io::IoResult<()> { + pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> { try!(match *result { TrOk => self.write_ok(), TrFailed => self.write_failed(), @@ -552,7 +566,7 @@ impl ConsoleTestState { } pub fn write_log(&mut self, test: &TestDesc, - result: &TestResult) -> old_io::IoResult<()> { + result: &TestResult) -> io::Result<()> { match self.log_out { None => Ok(()), Some(ref mut o) => { @@ -568,7 +582,7 @@ impl ConsoleTestState { } } - pub fn write_failures(&mut self) -> old_io::IoResult<()> { + pub fn write_failures(&mut self) -> io::Result<()> { try!(self.write_plain("\nfailures:\n")); let mut failures = Vec::new(); let mut fail_out = String::new(); @@ -594,7 +608,7 @@ impl ConsoleTestState { Ok(()) } - pub fn write_run_finish(&mut self) -> old_io::IoResult { + pub fn write_run_finish(&mut self) -> io::Result { assert!(self.passed + self.failed + self.ignored + self.measured == self.total); let success = self.failed == 0; @@ -619,21 +633,21 @@ impl ConsoleTestState { pub fn fmt_bench_samples(bs: &BenchSamples) -> String { if bs.mb_s != 0 { format!("{:>9} ns/iter (+/- {}) = {} MB/s", - bs.ns_iter_summ.median as uint, - (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as uint, + bs.ns_iter_summ.median as usize, + (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize, bs.mb_s) } else { format!("{:>9} ns/iter (+/- {})", - bs.ns_iter_summ.median as uint, - (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as uint) + bs.ns_iter_summ.median as usize, + (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize) } } // A simple console test runner -pub fn run_tests_console(opts: &TestOpts, tests: Vec ) -> old_io::IoResult { +pub fn run_tests_console(opts: &TestOpts, tests: Vec ) -> io::Result { - fn callback(event: &TestEvent, - st: &mut ConsoleTestState) -> old_io::IoResult<()> { + fn callback(event: &TestEvent, + st: &mut ConsoleTestState) -> io::Result<()> { match (*event).clone() { TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()), TeWait(ref test, padding) => st.write_test_start(test, padding), @@ -672,8 +686,8 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec ) -> old_io: } } - let mut st = try!(ConsoleTestState::new(opts, None::)); - fn len_if_padded(t: &TestDescAndFn) -> uint { + let mut st = try!(ConsoleTestState::new(opts, None::)); + fn len_if_padded(t: &TestDescAndFn) -> usize { match t.testfn.padding() { PadNone => 0, PadOnLeft | PadOnRight => t.desc.name.as_slice().len(), @@ -682,7 +696,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec ) -> old_io: match tests.iter().max_by(|t|len_if_padded(*t)) { Some(t) => { let n = t.desc.name.as_slice(); - st.max_name_len = n.as_slice().len(); + st.max_name_len = n.len(); }, None => {} } @@ -695,13 +709,13 @@ fn should_sort_failures_before_printing_them() { let test_a = TestDesc { name: StaticTestName("a"), ignore: false, - should_fail: ShouldFail::No + should_panic: ShouldPanic::No }; let test_b = TestDesc { name: StaticTestName("b"), ignore: false, - should_fail: ShouldFail::No + should_panic: ShouldPanic::No }; let mut st = ConsoleTestState { @@ -724,19 +738,38 @@ fn should_sort_failures_before_printing_them() { Pretty(_) => unreachable!() }; - let apos = s.find_str("a").unwrap(); - let bpos = s.find_str("b").unwrap(); + let apos = s.find("a").unwrap(); + let bpos = s.find("b").unwrap(); assert!(apos < bpos); } fn use_color(opts: &TestOpts) -> bool { match opts.color { - AutoColor => get_concurrency() == 1 && old_io::stdout().get_ref().isatty(), + AutoColor => get_concurrency() == 1 && stdout_isatty(), AlwaysColor => true, NeverColor => false, } } +#[cfg(unix)] +fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +fn stdout_isatty() -> bool { + const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD; + extern "system" { + fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; + fn GetConsoleMode(hConsoleHandle: libc::HANDLE, + lpMode: libc::LPDWORD) -> libc::BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + #[derive(Clone)] enum TestEvent { TeFiltered(Vec ), @@ -749,8 +782,8 @@ pub type MonitorMsg = (TestDesc, TestResult, Vec ); fn run_tests(opts: &TestOpts, tests: Vec , - mut callback: F) -> old_io::IoResult<()> where - F: FnMut(TestEvent) -> old_io::IoResult<()>, + mut callback: F) -> io::Result<()> where + F: FnMut(TestEvent) -> io::Result<()>, { let filtered_tests = filter_tests(opts, tests); let filtered_descs = filtered_tests.iter() @@ -809,18 +842,23 @@ fn run_tests(opts: &TestOpts, Ok(()) } -fn get_concurrency() -> uint { - use std::rt; - match env::var("RUST_TEST_TASKS") { +#[allow(deprecated)] +fn get_concurrency() -> usize { + match env::var("RUST_TEST_THREADS") { Ok(s) => { - let opt_n: Option = s.parse().ok(); + let opt_n: Option = s.parse().ok(); match opt_n { Some(n) if n > 0 => n, - _ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s) + _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", s) } } Err(..) => { - rt::default_sched_threads() + if std::rt::util::limit_thread_creation_due_to_osx_and_valgrind() { + 1 + } else { + extern { fn rust_get_num_cpus() -> libc::uintptr_t; } + unsafe { rust_get_num_cpus() as usize } + } } } } @@ -878,25 +916,31 @@ pub fn run_test(opts: &TestOpts, monitor_ch: Sender, nocapture: bool, testfn: Thunk<'static>) { + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + thread::spawn(move || { - let (tx, rx) = channel(); - let mut reader = ChanReader::new(rx); - let stdout = ChanWriter::new(tx.clone()); - let stderr = ChanWriter::new(tx); - let mut cfg = thread::Builder::new().name(match desc.name { + let data = Arc::new(Mutex::new(Vec::new())); + let data2 = data.clone(); + let cfg = thread::Builder::new().name(match desc.name { DynTestName(ref name) => name.clone().to_string(), StaticTestName(name) => name.to_string(), }); - if nocapture { - drop((stdout, stderr)); - } else { - cfg = cfg.stdout(box stdout as Box); - cfg = cfg.stderr(box stderr as Box); - } - let result_guard = cfg.spawn(move || { testfn.invoke(()) }).unwrap(); - let stdout = reader.read_to_end().unwrap().into_iter().collect(); + let result_guard = cfg.spawn(move || { + if !nocapture { + io::set_print(box Sink(data2.clone())); + io::set_panic(box Sink(data2)); + } + testfn() + }).unwrap(); let test_result = calc_result(&desc, result_guard.join()); + let stdout = data.lock().unwrap().to_vec(); monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); }); } @@ -914,7 +958,7 @@ pub fn run_test(opts: &TestOpts, } DynMetricFn(f) => { let mut mm = MetricMap::new(); - f.invoke(&mut mm); + f.call_box((&mut mm,)); monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap(); return; } @@ -926,15 +970,15 @@ pub fn run_test(opts: &TestOpts, } DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f), StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, - Thunk::new(move|| f())) + Box::new(move|| f())) } } fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { - match (&desc.should_fail, task_result) { - (&ShouldFail::No, Ok(())) | - (&ShouldFail::Yes(None), Err(_)) => TrOk, - (&ShouldFail::Yes(Some(msg)), Err(ref err)) + match (&desc.should_panic, task_result) { + (&ShouldPanic::No, Ok(())) | + (&ShouldPanic::Yes(None), Err(_)) => TrOk, + (&ShouldPanic::Yes(Some(msg)), Err(ref err)) if err.downcast_ref::() .map(|e| &**e) .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e)) @@ -976,7 +1020,7 @@ impl MetricMap { let MetricMap(ref mm) = *self; let v : Vec = mm.iter() .map(|(k,v)| format!("{}: {} (+/- {})", *k, - v.value as f64, v.noise as f64)) + v.value, v.noise)) .collect(); v.connect(", ") } @@ -1003,7 +1047,7 @@ impl Bencher { pub fn iter(&mut self, mut inner: F) where F: FnMut() -> T { self.dur = Duration::span(|| { let k = self.iterations; - for _ in 0u64..k { + for _ in 0..k { black_box(inner()); } }); @@ -1029,7 +1073,7 @@ impl Bencher { // This is a more statistics-driven benchmark algorithm pub fn auto_bench(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut Bencher) { // Initial bench run to get ballpark figure. - let mut n = 1_u64; + let mut n = 1; self.bench_n(n, |x| f(x)); // Try to estimate iter count for 1ms falling back to 1m @@ -1087,7 +1131,14 @@ impl Bencher { return summ5; } - n *= 2; + // If we overflow here just return the results so far. We check a + // multiplier of 10 because we're about to multiply by 2 and the + // next iteration of the loop will also multiply by 5 (to calculate + // the summ5 result) + n = match n.checked_mul(10) { + Some(_) => n * 2, + None => return summ5, + }; } } } @@ -1112,7 +1163,7 @@ pub mod bench { BenchSamples { ns_iter_summ: ns_iter_summ, - mb_s: mb_s as uint + mb_s: mb_s as usize } } } @@ -1122,7 +1173,7 @@ mod tests { use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc, TestDescAndFn, TestOpts, run_test, MetricMap, - StaticTestName, DynTestName, DynTestFn, ShouldFail}; + StaticTestName, DynTestName, DynTestFn, ShouldPanic}; use std::thunk::Thunk; use std::sync::mpsc::channel; @@ -1133,9 +1184,9 @@ mod tests { desc: TestDesc { name: StaticTestName("whatever"), ignore: true, - should_fail: ShouldFail::No, + should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1150,9 +1201,9 @@ mod tests { desc: TestDesc { name: StaticTestName("whatever"), ignore: true, - should_fail: ShouldFail::No, + should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1161,15 +1212,15 @@ mod tests { } #[test] - fn test_should_fail() { + fn test_should_panic() { fn f() { panic!(); } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - should_fail: ShouldFail::Yes(None) + should_panic: ShouldPanic::Yes(None) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1178,15 +1229,15 @@ mod tests { } #[test] - fn test_should_fail_good_message() { + fn test_should_panic_good_message() { fn f() { panic!("an error message"); } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - should_fail: ShouldFail::Yes(Some("error message")) + should_panic: ShouldPanic::Yes(Some("error message")) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1195,15 +1246,15 @@ mod tests { } #[test] - fn test_should_fail_bad_message() { + fn test_should_panic_bad_message() { fn f() { panic!("an error message"); } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - should_fail: ShouldFail::Yes(Some("foobar")) + should_panic: ShouldPanic::Yes(Some("foobar")) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1212,15 +1263,15 @@ mod tests { } #[test] - fn test_should_fail_but_succeeds() { + fn test_should_panic_but_succeeds() { fn f() { } let desc = TestDescAndFn { desc: TestDesc { name: StaticTestName("whatever"), ignore: false, - should_fail: ShouldFail::Yes(None) + should_panic: ShouldPanic::Yes(None) }, - testfn: DynTestFn(Thunk::new(move|| f())), + testfn: DynTestFn(Box::new(move|| f())), }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx); @@ -1254,17 +1305,17 @@ mod tests { desc: TestDesc { name: StaticTestName("1"), ignore: true, - should_fail: ShouldFail::No, + should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| {})), + testfn: DynTestFn(Box::new(move|| {})), }, TestDescAndFn { desc: TestDesc { name: StaticTestName("2"), ignore: false, - should_fail: ShouldFail::No, + should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(move|| {})), + testfn: DynTestFn(Box::new(move|| {})), }); let filtered = filter_tests(&opts, tests); @@ -1281,8 +1332,8 @@ mod tests { let names = vec!("sha1::test".to_string(), - "int::test_to_str".to_string(), - "int::test_pow".to_string(), + "isize::test_to_str".to_string(), + "isize::test_pow".to_string(), "test::do_not_run_ignored_tests".to_string(), "test::ignored_tests_result_in_ignored".to_string(), "test::first_free_arg_should_be_a_filter".to_string(), @@ -1298,9 +1349,9 @@ mod tests { desc: TestDesc { name: DynTestName((*name).clone()), ignore: false, - should_fail: ShouldFail::No, + should_panic: ShouldPanic::No, }, - testfn: DynTestFn(Thunk::new(testfn)), + testfn: DynTestFn(Box::new(testfn)), }; tests.push(test); } @@ -1309,8 +1360,8 @@ mod tests { let filtered = filter_tests(&opts, tests); let expected = - vec!("int::test_pow".to_string(), - "int::test_to_str".to_string(), + vec!("isize::test_pow".to_string(), + "isize::test_to_str".to_string(), "sha1::test".to_string(), "test::do_not_run_ignored_tests".to_string(), "test::filter_for_ignored_option".to_string(), diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 4e94be59ad..94dee5ccc3 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -9,11 +9,9 @@ // except according to those terms. #![allow(missing_docs)] +#![allow(deprecated)] // Float use std::cmp::Ordering::{self, Less, Greater, Equal}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::collections::hash_map; -use std::hash::Hash; use std::mem; use std::num::{Float, FromPrimitive}; @@ -210,11 +208,11 @@ impl Stats for [T] { fn mean(&self) -> T { assert!(self.len() != 0); - self.sum() / FromPrimitive::from_uint(self.len()).unwrap() + self.sum() / FromPrimitive::from_usize(self.len()).unwrap() } fn median(&self) -> T { - self.percentile(FromPrimitive::from_uint(50).unwrap()) + self.percentile(FromPrimitive::from_usize(50).unwrap()) } fn var(&self) -> T { @@ -230,7 +228,7 @@ impl Stats for [T] { // NB: this is _supposed to be_ len-1, not len. If you // change it back to len, you will be calculating a // population variance, not a sample variance. - let denom = FromPrimitive::from_uint(self.len()-1).unwrap(); + let denom = FromPrimitive::from_usize(self.len()-1).unwrap(); v/denom } } @@ -240,7 +238,7 @@ impl Stats for [T] { } fn std_dev_pct(&self) -> T { - let hundred = FromPrimitive::from_uint(100).unwrap(); + let hundred = FromPrimitive::from_usize(100).unwrap(); (self.std_dev() / self.mean()) * hundred } @@ -254,7 +252,7 @@ impl Stats for [T] { } fn median_abs_dev_pct(&self) -> T { - let hundred = FromPrimitive::from_uint(100).unwrap(); + let hundred = FromPrimitive::from_usize(100).unwrap(); (self.median_abs_dev() / self.median()) * hundred } @@ -267,11 +265,11 @@ impl Stats for [T] { fn quartiles(&self) -> (T,T,T) { let mut tmp = self.to_vec(); local_sort(&mut tmp); - let first = FromPrimitive::from_uint(25).unwrap(); + let first = FromPrimitive::from_usize(25).unwrap(); let a = percentile_of_sorted(&tmp, first); - let secound = FromPrimitive::from_uint(50).unwrap(); + let secound = FromPrimitive::from_usize(50).unwrap(); let b = percentile_of_sorted(&tmp, secound); - let third = FromPrimitive::from_uint(75).unwrap(); + let third = FromPrimitive::from_usize(75).unwrap(); let c = percentile_of_sorted(&tmp, third); (a,b,c) } @@ -293,16 +291,16 @@ fn percentile_of_sorted(sorted_samples: &[T], } let zero: T = Float::zero(); assert!(zero <= pct); - let hundred = FromPrimitive::from_uint(100).unwrap(); + let hundred = FromPrimitive::from_usize(100).unwrap(); assert!(pct <= hundred); if pct == hundred { return sorted_samples[sorted_samples.len() - 1]; } - let length = FromPrimitive::from_uint(sorted_samples.len() - 1).unwrap(); + let length = FromPrimitive::from_usize(sorted_samples.len() - 1).unwrap(); let rank = (pct / hundred) * length; let lrank = rank.floor(); let d = rank - lrank; - let n = lrank.to_uint().unwrap(); + let n = lrank.to_usize().unwrap(); let lo = sorted_samples[n]; let hi = sorted_samples[n+1]; lo + (hi - lo) * d @@ -319,7 +317,7 @@ pub fn winsorize(samples: &mut [T], pct: T) { let mut tmp = samples.to_vec(); local_sort(&mut tmp); let lo = percentile_of_sorted(&tmp, pct); - let hundred: T = FromPrimitive::from_uint(100).unwrap(); + let hundred: T = FromPrimitive::from_usize(100).unwrap(); let hi = percentile_of_sorted(&tmp, hundred-pct); for samp in samples { if *samp > hi { @@ -330,28 +328,13 @@ pub fn winsorize(samples: &mut [T], pct: T) { } } -/// Returns a HashMap with the number of occurrences of every element in the -/// sequence that the iterator exposes. -pub fn freq_count(iter: T) -> hash_map::HashMap - where T: Iterator, U: Eq + Clone + Hash -{ - let mut map: hash_map::HashMap = hash_map::HashMap::new(); - for elem in iter { - match map.entry(elem) { - Occupied(mut entry) => { *entry.get_mut() += 1; }, - Vacant(entry) => { entry.insert(1); }, - } - } - map -} - // Test vectors generated from R, using the script src/etc/stat-test-vectors.r. #[cfg(test)] mod tests { use stats::Stats; use stats::Summary; - use std::old_io; + use std::old_io::{self, Writer}; use std::f64; macro_rules! assert_approx_eq { diff --git a/src/libunicode/u_char.rs b/src/libunicode/char.rs similarity index 51% rename from src/libunicode/u_char.rs rename to src/libunicode/char.rs index c0f45ca4d7..2aeade5066 100644 --- a/src/libunicode/u_char.rs +++ b/src/libunicode/char.rs @@ -8,19 +8,66 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Unicode-intensive `char` methods along with the `core` methods. +//! Character manipulation (`char` type, Unicode Scalar Value) //! -//! These methods implement functionality for `char` that requires knowledge of -//! Unicode definitions, including normalization, categorization, and display information. +//! 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)*, as it can +//! contain any Unicode code point except high-surrogate and low-surrogate code +//! points. +//! +//! As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\] +//! (inclusive) are allowed. A `char` can always be safely cast to a `u32`; +//! however the converse is not always true due to the above range limits +//! and, as such, should be performed via the `from_u32` function. + +#![stable(feature = "rust1", since = "1.0.0")] +#![doc(primitive = "char")] -use core::char; use core::char::CharExt as C; -use core::option::Option; +use core::option::Option::{self, Some}; +use core::iter::Iterator; use tables::{derived_property, property, general_category, conversions, charwidth}; -/// Functionality for manipulating `char`. +// stable reexports +pub use core::char::{MAX, from_u32, from_digit, EscapeUnicode, EscapeDefault}; + +// unstable reexports +pub use normalize::{decompose_canonical, decompose_compatible, compose}; +pub use tables::normalization::canonical_combining_class; +pub use tables::UNICODE_VERSION; + +/// An iterator over the lowercase mapping of a given character, returned from +/// the [`to_lowercase` method](../primitive.char.html#method.to_lowercase) on +/// characters. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct ToLowercase(Option); + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for ToLowercase { + type Item = char; + fn next(&mut self) -> Option { self.0.take() } +} + +/// An iterator over the uppercase mapping of a given character, returned from +/// the [`to_uppercase` method](../primitive.char.html#method.to_uppercase) on +/// characters. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct ToUppercase(Option); + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for ToUppercase { + type Item = char; + fn next(&mut self) -> Option { self.0.take() } +} + #[stable(feature = "rust1", since = "1.0.0")] -pub trait CharExt { +#[lang = "char"] +impl char { /// Checks if a `char` parses as a numeric digit in the given radix. /// /// Compared to `is_numeric()`, this function only recognizes the characters @@ -34,9 +81,19 @@ pub trait CharExt { /// # Panics /// /// Panics if given a radix > 36. - #[unstable(feature = "unicode", - reason = "pending integer conventions")] - fn is_digit(self, radix: u32) -> bool; + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert!(c.is_digit(10)); + /// + /// assert!('f'.is_digit(16)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) } /// Converts a character to the corresponding digit. /// @@ -49,18 +106,56 @@ pub trait CharExt { /// # Panics /// /// Panics if given a radix outside the range [0..36]. - #[unstable(feature = "unicode", - reason = "pending integer conventions")] - fn to_digit(self, radix: u32) -> Option; + /// + /// # Examples + /// + /// ``` + /// let c = '1'; + /// + /// assert_eq!(c.to_digit(10), Some(1)); + /// + /// assert_eq!('f'.to_digit(16), Some(15)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_digit(self, radix: u32) -> Option { C::to_digit(self, radix) } - /// Returns an iterator that yields the hexadecimal Unicode escape - /// of a character, as `char`s. + /// 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. + /// + /// # Examples + /// + /// ``` + /// for i in '❤'.escape_unicode() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// u + /// { + /// 2 + /// 7 + /// 6 + /// 4 + /// } + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let heart: String = '❤'.escape_unicode().collect(); + /// + /// assert_eq!(heart, r"\u{2764}"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn escape_unicode(self) -> char::EscapeUnicode; + pub fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) } /// Returns an iterator that yields the 'default' ASCII and /// C++11-like literal escape of a character, as `char`s. @@ -74,41 +169,137 @@ pub trait CharExt { /// escaped. /// * Any other chars in the range [0x20,0x7e] are not escaped. /// * Any other chars are given hex Unicode escapes; see `escape_unicode`. + /// + /// # Examples + /// + /// ``` + /// for i in '"'.escape_default() { + /// println!("{}", i); + /// } + /// ``` + /// + /// This prints: + /// + /// ```text + /// \ + /// " + /// ``` + /// + /// Collecting into a `String`: + /// + /// ``` + /// let quote: String = '"'.escape_default().collect(); + /// + /// assert_eq!(quote, "\\\""); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn escape_default(self) -> char::EscapeDefault; + pub fn escape_default(self) -> EscapeDefault { C::escape_default(self) } - /// Returns the amount of bytes this character would need if encoded in + /// Returns the number of bytes this character would need if encoded in /// UTF-8. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf8(); + /// + /// assert_eq!(n, 2); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn len_utf8(self) -> usize; + pub fn len_utf8(self) -> usize { C::len_utf8(self) } - /// Returns the amount of bytes this character would need if encoded in - /// UTF-16. + /// Returns the number of 16-bit code units this character would need if + /// encoded in UTF-16. + /// + /// # Examples + /// + /// ``` + /// let n = 'ß'.len_utf16(); + /// + /// assert_eq!(n, 1); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn len_utf16(self) -> usize; + pub fn len_utf16(self) -> usize { C::len_utf16(self) } - /// Encodes this character as UTF-8 into the provided byte buffer, - /// and then returns the number of bytes written. + /// 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. A buffer of length four is large enough to + /// encode any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes two bytes to encode. + /// + /// ``` + /// # #![feature(unicode)] + /// let mut b = [0; 2]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, Some(2)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// # #![feature(unicode)] + /// let mut b = [0; 1]; /// - /// If the buffer is not large enough, nothing will be written into it - /// and a `None` will be returned. + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` #[unstable(feature = "unicode", reason = "pending decision about Iterator/Writer/Reader")] - fn encode_utf8(self, dst: &mut [u8]) -> Option; + pub fn encode_utf8(self, dst: &mut [u8]) -> Option { C::encode_utf8(self, dst) } - /// Encodes this character as UTF-16 into the provided `u16` buffer, - /// and then returns the number of `u16`s written. + /// 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. A buffer of length 2 is large enough to encode + /// any `char`. + /// + /// # Examples + /// + /// In both of these examples, 'ß' takes one `u16` to encode. + /// + /// ``` + /// # #![feature(unicode)] + /// let mut b = [0; 1]; + /// + /// let result = 'ß'.encode_utf16(&mut b); /// - /// If the buffer is not large enough, nothing will be written into it - /// and a `None` will be returned. + /// assert_eq!(result, Some(1)); + /// ``` + /// + /// A buffer that's too small: + /// + /// ``` + /// # #![feature(unicode)] + /// let mut b = [0; 0]; + /// + /// let result = 'ß'.encode_utf8(&mut b); + /// + /// assert_eq!(result, None); + /// ``` #[unstable(feature = "unicode", reason = "pending decision about Iterator/Writer/Reader")] - fn encode_utf16(self, dst: &mut [u16]) -> Option; + pub fn encode_utf16(self, dst: &mut [u16]) -> Option { C::encode_utf16(self, dst) } /// Returns whether the specified character is considered a Unicode /// alphabetic code point. #[stable(feature = "rust1", since = "1.0.0")] - fn is_alphabetic(self) -> bool; + #[inline] + pub fn is_alphabetic(self) -> bool { + match self { + 'a' ... 'z' | 'A' ... 'Z' => true, + c if c > '\x7f' => derived_property::Alphabetic(c), + _ => false + } + } /// Returns whether the specified character satisfies the 'XID_Start' /// Unicode property. @@ -118,7 +309,8 @@ pub trait CharExt { /// mostly similar to ID_Start but modified for closure under NFKx. #[unstable(feature = "unicode", reason = "mainly needed for compiler internals")] - fn is_xid_start(self) -> bool; + #[inline] + pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } /// Returns whether the specified `char` satisfies the 'XID_Continue' /// Unicode property. @@ -128,45 +320,78 @@ pub trait CharExt { /// mostly similar to 'ID_Continue' but modified for closure under NFKx. #[unstable(feature = "unicode", reason = "mainly needed for compiler internals")] - fn is_xid_continue(self) -> bool; + #[inline] + pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) } /// Indicates whether a character is in lowercase. /// /// This is defined according to the terms of the Unicode Derived Core /// Property `Lowercase`. #[stable(feature = "rust1", since = "1.0.0")] - fn is_lowercase(self) -> bool; + #[inline] + pub fn is_lowercase(self) -> bool { + match self { + 'a' ... 'z' => true, + c if c > '\x7f' => derived_property::Lowercase(c), + _ => false + } + } /// Indicates whether a character is in uppercase. /// /// This is defined according to the terms of the Unicode Derived Core /// Property `Uppercase`. #[stable(feature = "rust1", since = "1.0.0")] - fn is_uppercase(self) -> bool; + #[inline] + pub fn is_uppercase(self) -> bool { + match self { + 'A' ... 'Z' => true, + c if c > '\x7f' => derived_property::Uppercase(c), + _ => false + } + } /// Indicates whether a character is whitespace. /// /// Whitespace is defined in terms of the Unicode Property `White_Space`. #[stable(feature = "rust1", since = "1.0.0")] - fn is_whitespace(self) -> bool; + #[inline] + pub fn is_whitespace(self) -> bool { + match self { + ' ' | '\x09' ... '\x0d' => true, + c if c > '\x7f' => property::White_Space(c), + _ => false + } + } /// 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(feature = "rust1", since = "1.0.0")] - fn is_alphanumeric(self) -> bool; + #[inline] + pub fn is_alphanumeric(self) -> bool { + self.is_alphabetic() || self.is_numeric() + } /// Indicates whether a character is a control code point. /// /// Control code points are defined in terms of the Unicode General /// Category `Cc`. #[stable(feature = "rust1", since = "1.0.0")] - fn is_control(self) -> bool; + #[inline] + pub fn is_control(self) -> bool { general_category::Cc(self) } /// Indicates whether the character is numeric (Nd, Nl, or No). #[stable(feature = "rust1", since = "1.0.0")] - fn is_numeric(self) -> bool; + #[inline] + pub fn is_numeric(self) -> bool { + match self { + '0' ... '9' => true, + c if c > '\x7f' => general_category::N(c), + _ => false + } + } /// Converts a character to its lowercase equivalent. /// @@ -175,35 +400,41 @@ pub trait CharExt { /// /// # Return value /// - /// Returns the lowercase equivalent of the character, or the character - /// itself if no conversion is possible. - #[unstable(feature = "unicode", - reason = "pending case transformation decisions")] - fn to_lowercase(self) -> char; + /// Returns an iterator which yields the characters corresponding to the + /// lowercase equivalent of the character. If no conversion is possible then + /// the input character is returned. + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_lowercase(self) -> ToLowercase { + ToLowercase(Some(conversions::to_lower(self))) + } /// Converts a character to its uppercase equivalent. /// /// The case-folding performed is the common or simple mapping: it maps - /// one Unicode codepoint (one character in Rust) to its uppercase - /// equivalent according to the Unicode database [1]. The additional - /// [`SpecialCasing.txt`] is not considered here, as it expands to multiple - /// codepoints in some cases. + /// one Unicode codepoint to its uppercase equivalent according to the + /// Unicode database [1]. The additional [`SpecialCasing.txt`] is not yet + /// considered here, but the iterator returned will soon support this form + /// of case folding. /// /// A full reference can be found here [2]. /// /// # Return value /// - /// Returns the uppercase equivalent of the character, or the character - /// itself if no conversion was made. + /// Returns an iterator which yields the characters corresponding to the + /// uppercase equivalent of the character. If no conversion is possible then + /// the input character is returned. /// /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt /// /// [`SpecialCasing`.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt /// /// [2]: http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf#G33992 - #[unstable(feature = "unicode", - reason = "pending case transformation decisions")] - fn to_uppercase(self) -> char; + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn to_uppercase(self) -> ToUppercase { + ToUppercase(Some(conversions::to_upper(self))) + } /// Returns this character's displayed width in columns, or `None` if it is a /// control character other than `'\x00'`. @@ -216,102 +447,5 @@ pub trait CharExt { /// `is_cjk` = `false`) if the context cannot be reliably determined. #[unstable(feature = "unicode", reason = "needs expert opinion. is_cjk flag stands out as ugly")] - fn width(self, is_cjk: bool) -> Option; -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl CharExt for char { - #[unstable(feature = "unicode", - reason = "pending integer conventions")] - fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) } - #[unstable(feature = "unicode", - reason = "pending integer conventions")] - fn to_digit(self, radix: u32) -> Option { C::to_digit(self, radix) } - #[stable(feature = "rust1", since = "1.0.0")] - fn escape_unicode(self) -> char::EscapeUnicode { C::escape_unicode(self) } - #[stable(feature = "rust1", since = "1.0.0")] - fn escape_default(self) -> char::EscapeDefault { C::escape_default(self) } - #[stable(feature = "rust1", since = "1.0.0")] - fn len_utf8(self) -> usize { C::len_utf8(self) } - #[stable(feature = "rust1", since = "1.0.0")] - fn len_utf16(self) -> usize { C::len_utf16(self) } - #[unstable(feature = "unicode", - reason = "pending decision about Iterator/Writer/Reader")] - fn encode_utf8(self, dst: &mut [u8]) -> Option { C::encode_utf8(self, dst) } - #[unstable(feature = "unicode", - reason = "pending decision about Iterator/Writer/Reader")] - fn encode_utf16(self, dst: &mut [u16]) -> Option { C::encode_utf16(self, dst) } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_alphabetic(self) -> bool { - match self { - 'a' ... 'z' | 'A' ... 'Z' => true, - c if c > '\x7f' => derived_property::Alphabetic(c), - _ => false - } - } - - #[unstable(feature = "unicode", - reason = "mainly needed for compiler internals")] - fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } - - #[unstable(feature = "unicode", - reason = "mainly needed for compiler internals")] - fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_lowercase(self) -> bool { - match self { - 'a' ... 'z' => true, - c if c > '\x7f' => derived_property::Lowercase(c), - _ => false - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_uppercase(self) -> bool { - match self { - 'A' ... 'Z' => true, - c if c > '\x7f' => derived_property::Uppercase(c), - _ => false - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_whitespace(self) -> bool { - match self { - ' ' | '\x09' ... '\x0d' => true, - c if c > '\x7f' => property::White_Space(c), - _ => false - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_alphanumeric(self) -> bool { - self.is_alphabetic() || self.is_numeric() - } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_control(self) -> bool { general_category::Cc(self) } - - #[stable(feature = "rust1", since = "1.0.0")] - fn is_numeric(self) -> bool { - match self { - '0' ... '9' => true, - c if c > '\x7f' => general_category::N(c), - _ => false - } - } - - #[unstable(feature = "unicode", - reason = "pending case transformation decisions")] - fn to_lowercase(self) -> char { conversions::to_lower(self) } - - #[unstable(feature = "unicode", - reason = "pending case transformation decisions")] - fn to_uppercase(self) -> char { conversions::to_upper(self) } - - #[unstable(feature = "unicode", - reason = "needs expert opinion. is_cjk flag stands out as ugly")] - fn width(self, is_cjk: bool) -> Option { charwidth::width(self, is_cjk) } + pub fn width(self, is_cjk: bool) -> Option { charwidth::width(self, is_cjk) } } diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs index 791886be1c..6879fa7b3b 100644 --- a/src/libunicode/lib.rs +++ b/src/libunicode/lib.rs @@ -20,8 +20,11 @@ //! provide for basic string-related manipulations. This crate does not //! (yet) aim to provide a full set of Unicode tables. +// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) +#![cfg_attr(stage0, feature(custom_attribute))] #![crate_name = "unicode"] #![unstable(feature = "unicode")] +#![feature(lang_items)] #![feature(staged_api)] #![staged_api] #![crate_type = "rlib"] @@ -32,6 +35,7 @@ #![feature(no_std)] #![no_std] #![feature(core)] +#![doc(test(no_crate_inject))] extern crate core; @@ -40,37 +44,8 @@ pub use tables::regex; mod normalize; mod tables; -mod u_char; mod u_str; - -// re-export char so that std et al see it correctly -/// Character manipulation (`char` type, Unicode Scalar Value) -/// -/// 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)*, -/// as it can contain any Unicode code point except high-surrogate and -/// low-surrogate code points. -/// -/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\] -/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`; -/// however the converse is not always true due to the above range limits -/// and, as such, should be performed via the `from_u32` function. -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(primitive = "char")] -pub mod 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::CharExt; -} +pub mod char; pub mod str { pub use u_str::{UnicodeStr, Words, Graphemes, GraphemeIndices}; diff --git a/src/libunicode/tables.rs b/src/libunicode/tables.rs index 61f447a3dd..1fb6ee7bc7 100644 --- a/src/libunicode/tables.rs +++ b/src/libunicode/tables.rs @@ -27,7 +27,7 @@ fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { } pub mod general_category { - pub static C_table: &'static [(char, char)] = &[ + pub const C_table: &'static [(char, char)] = &[ ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}'), ('\u{ad}', '\u{ad}'), ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'), ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'), ('\u{557}', '\u{558}'), ('\u{560}', '\u{560}'), @@ -115,27 +115,26 @@ pub mod general_category { '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}', '\u{2fff}'), ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'), ('\u{3100}', '\u{3104}'), ('\u{312e}', '\u{3130}'), ('\u{318f}', '\u{318f}'), ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', '\u{31ef}'), ('\u{321f}', '\u{321f}'), - ('\u{32ff}', '\u{32ff}'), ('\u{3401}', '\u{4db4}'), ('\u{4db6}', '\u{4dbf}'), ('\u{4e01}', - '\u{9fcb}'), ('\u{9fcd}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'), ('\u{a4c7}', '\u{a4cf}'), - ('\u{a62c}', '\u{a63f}'), ('\u{a69e}', '\u{a69e}'), ('\u{a6f8}', '\u{a6ff}'), ('\u{a78f}', - '\u{a78f}'), ('\u{a7ae}', '\u{a7af}'), ('\u{a7b2}', '\u{a7f6}'), ('\u{a82c}', '\u{a82f}'), - ('\u{a83a}', '\u{a83f}'), ('\u{a878}', '\u{a87f}'), ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', - '\u{a8df}'), ('\u{a8fc}', '\u{a8ff}'), ('\u{a954}', '\u{a95e}'), ('\u{a97d}', '\u{a97f}'), - ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'), ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', - '\u{aa3f}'), ('\u{aa4e}', '\u{aa4f}'), ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'), - ('\u{aaf7}', '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}', '\u{ab10}'), ('\u{ab17}', - '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}', '\u{ab2f}'), ('\u{ab60}', '\u{ab63}'), - ('\u{ab66}', '\u{abbf}'), ('\u{abee}', '\u{abef}'), ('\u{abfa}', '\u{abff}'), ('\u{ac01}', - '\u{d7a2}'), ('\u{d7a4}', '\u{d7af}'), ('\u{d7c7}', '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), - ('\u{e000}', '\u{f8ff}'), ('\u{fa6e}', '\u{fa6f}'), ('\u{fada}', '\u{faff}'), ('\u{fb07}', - '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}', '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'), - ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'), ('\u{fb45}', '\u{fb45}'), ('\u{fbc2}', - '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', '\u{fd91}'), ('\u{fdc8}', '\u{fdef}'), - ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'), ('\u{fe2e}', '\u{fe2f}'), ('\u{fe53}', - '\u{fe53}'), ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}', '\u{fe75}'), - ('\u{fefd}', '\u{ff00}'), ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'), ('\u{ffd0}', - '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), ('\u{ffdd}', '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'), - ('\u{ffef}', '\u{fffb}'), ('\u{fffe}', '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), + ('\u{32ff}', '\u{32ff}'), ('\u{4db6}', '\u{4dbf}'), ('\u{9fcd}', '\u{9fff}'), ('\u{a48d}', + '\u{a48f}'), ('\u{a4c7}', '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'), ('\u{a69e}', '\u{a69e}'), + ('\u{a6f8}', '\u{a6ff}'), ('\u{a78f}', '\u{a78f}'), ('\u{a7ae}', '\u{a7af}'), ('\u{a7b2}', + '\u{a7f6}'), ('\u{a82c}', '\u{a82f}'), ('\u{a83a}', '\u{a83f}'), ('\u{a878}', '\u{a87f}'), + ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'), ('\u{a8fc}', '\u{a8ff}'), ('\u{a954}', + '\u{a95e}'), ('\u{a97d}', '\u{a97f}'), ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'), + ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}', '\u{aa4f}'), ('\u{aa5a}', + '\u{aa5b}'), ('\u{aac3}', '\u{aada}'), ('\u{aaf7}', '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), + ('\u{ab0f}', '\u{ab10}'), ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}', + '\u{ab2f}'), ('\u{ab60}', '\u{ab63}'), ('\u{ab66}', '\u{abbf}'), ('\u{abee}', '\u{abef}'), + ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'), ('\u{d7c7}', '\u{d7ca}'), ('\u{d7fc}', + '\u{d7ff}'), ('\u{e000}', '\u{f8ff}'), ('\u{fa6e}', '\u{fa6f}'), ('\u{fada}', '\u{faff}'), + ('\u{fb07}', '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}', '\u{fb37}'), ('\u{fb3d}', + '\u{fb3d}'), ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'), ('\u{fb45}', '\u{fb45}'), + ('\u{fbc2}', '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', '\u{fd91}'), ('\u{fdc8}', + '\u{fdef}'), ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'), ('\u{fe2e}', '\u{fe2f}'), + ('\u{fe53}', '\u{fe53}'), ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', '\u{fe6f}'), ('\u{fe75}', + '\u{fe75}'), ('\u{fefd}', '\u{ff00}'), ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'), + ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), ('\u{ffdd}', '\u{ffdf}'), ('\u{ffe7}', + '\u{ffe7}'), ('\u{ffef}', '\u{fffb}'), ('\u{fffe}', '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'), ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'), ('\u{1004e}', '\u{1004f}'), ('\u{1005e}', '\u{1007f}'), ('\u{100fb}', '\u{100ff}'), ('\u{10103}', '\u{10106}'), ('\u{10134}', '\u{10136}'), ('\u{1018d}', '\u{1018f}'), @@ -210,13 +209,12 @@ pub mod general_category { ('\u{1f643}', '\u{1f644}'), ('\u{1f6d0}', '\u{1f6df}'), ('\u{1f6ed}', '\u{1f6ef}'), ('\u{1f6f4}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'), ('\u{1f7d5}', '\u{1f7ff}'), ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}', '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), - ('\u{1f888}', '\u{1f88f}'), ('\u{1f8ae}', '\u{1ffff}'), ('\u{20001}', '\u{2a6d5}'), - ('\u{2a6d7}', '\u{2a6ff}'), ('\u{2a701}', '\u{2b733}'), ('\u{2b735}', '\u{2b73f}'), - ('\u{2b741}', '\u{2b81c}'), ('\u{2b81e}', '\u{2f7ff}'), ('\u{2fa1e}', '\u{e00ff}'), + ('\u{1f888}', '\u{1f88f}'), ('\u{1f8ae}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'), + ('\u{2b735}', '\u{2b73f}'), ('\u{2b81e}', '\u{2f7ff}'), ('\u{2fa1e}', '\u{e00ff}'), ('\u{e01f0}', '\u{10ffff}') ]; - pub static Cc_table: &'static [(char, char)] = &[ + pub const Cc_table: &'static [(char, char)] = &[ ('\u{0}', '\u{1f}'), ('\u{7f}', '\u{9f}') ]; @@ -224,7 +222,7 @@ pub mod general_category { super::bsearch_range_table(c, Cc_table) } - pub static Cf_table: &'static [(char, char)] = &[ + pub const Cf_table: &'static [(char, char)] = &[ ('\u{ad}', '\u{ad}'), ('\u{600}', '\u{605}'), ('\u{61c}', '\u{61c}'), ('\u{6dd}', '\u{6dd}'), ('\u{70f}', '\u{70f}'), ('\u{180e}', '\u{180e}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{2064}'), ('\u{2066}', '\u{206f}'), ('\u{feff}', @@ -233,7 +231,7 @@ pub mod general_category { '\u{e007f}') ]; - pub static Cn_table: &'static [(char, char)] = &[ + pub const Cn_table: &'static [(char, char)] = &[ ('\u{378}', '\u{379}'), ('\u{380}', '\u{383}'), ('\u{38b}', '\u{38b}'), ('\u{38d}', '\u{38d}'), ('\u{3a2}', '\u{3a2}'), ('\u{530}', '\u{530}'), ('\u{557}', '\u{558}'), ('\u{560}', '\u{560}'), ('\u{588}', '\u{588}'), ('\u{58b}', '\u{58c}'), ('\u{590}', @@ -319,115 +317,111 @@ pub mod general_category { ('\u{2e9a}', '\u{2e9a}'), ('\u{2ef4}', '\u{2eff}'), ('\u{2fd6}', '\u{2fef}'), ('\u{2ffc}', '\u{2fff}'), ('\u{3040}', '\u{3040}'), ('\u{3097}', '\u{3098}'), ('\u{3100}', '\u{3104}'), ('\u{312e}', '\u{3130}'), ('\u{318f}', '\u{318f}'), ('\u{31bb}', '\u{31bf}'), ('\u{31e4}', - '\u{31ef}'), ('\u{321f}', '\u{321f}'), ('\u{32ff}', '\u{32ff}'), ('\u{3401}', '\u{4db4}'), - ('\u{4db6}', '\u{4dbf}'), ('\u{4e01}', '\u{9fcb}'), ('\u{9fcd}', '\u{9fff}'), ('\u{a48d}', - '\u{a48f}'), ('\u{a4c7}', '\u{a4cf}'), ('\u{a62c}', '\u{a63f}'), ('\u{a69e}', '\u{a69e}'), - ('\u{a6f8}', '\u{a6ff}'), ('\u{a78f}', '\u{a78f}'), ('\u{a7ae}', '\u{a7af}'), ('\u{a7b2}', - '\u{a7f6}'), ('\u{a82c}', '\u{a82f}'), ('\u{a83a}', '\u{a83f}'), ('\u{a878}', '\u{a87f}'), - ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'), ('\u{a8fc}', '\u{a8ff}'), ('\u{a954}', - '\u{a95e}'), ('\u{a97d}', '\u{a97f}'), ('\u{a9ce}', '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'), - ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), ('\u{aa4e}', '\u{aa4f}'), ('\u{aa5a}', - '\u{aa5b}'), ('\u{aac3}', '\u{aada}'), ('\u{aaf7}', '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), - ('\u{ab0f}', '\u{ab10}'), ('\u{ab17}', '\u{ab1f}'), ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}', - '\u{ab2f}'), ('\u{ab60}', '\u{ab63}'), ('\u{ab66}', '\u{abbf}'), ('\u{abee}', '\u{abef}'), - ('\u{abfa}', '\u{abff}'), ('\u{ac01}', '\u{d7a2}'), ('\u{d7a4}', '\u{d7af}'), ('\u{d7c7}', - '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), ('\u{e001}', '\u{f8fe}'), ('\u{fa6e}', '\u{fa6f}'), - ('\u{fada}', '\u{faff}'), ('\u{fb07}', '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}', - '\u{fb37}'), ('\u{fb3d}', '\u{fb3d}'), ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'), - ('\u{fb45}', '\u{fb45}'), ('\u{fbc2}', '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', - '\u{fd91}'), ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'), - ('\u{fe2e}', '\u{fe2f}'), ('\u{fe53}', '\u{fe53}'), ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', - '\u{fe6f}'), ('\u{fe75}', '\u{fe75}'), ('\u{fefd}', '\u{fefe}'), ('\u{ff00}', '\u{ff00}'), - ('\u{ffbf}', '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'), ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', - '\u{ffd9}'), ('\u{ffdd}', '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'), ('\u{ffef}', '\u{fff8}'), - ('\u{fffe}', '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'), - ('\u{1003b}', '\u{1003b}'), ('\u{1003e}', '\u{1003e}'), ('\u{1004e}', '\u{1004f}'), - ('\u{1005e}', '\u{1007f}'), ('\u{100fb}', '\u{100ff}'), ('\u{10103}', '\u{10106}'), - ('\u{10134}', '\u{10136}'), ('\u{1018d}', '\u{1018f}'), ('\u{1019c}', '\u{1019f}'), - ('\u{101a1}', '\u{101cf}'), ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'), - ('\u{102d1}', '\u{102df}'), ('\u{102fc}', '\u{102ff}'), ('\u{10324}', '\u{1032f}'), - ('\u{1034b}', '\u{1034f}'), ('\u{1037b}', '\u{1037f}'), ('\u{1039e}', '\u{1039e}'), - ('\u{103c4}', '\u{103c7}'), ('\u{103d6}', '\u{103ff}'), ('\u{1049e}', '\u{1049f}'), - ('\u{104aa}', '\u{104ff}'), ('\u{10528}', '\u{1052f}'), ('\u{10564}', '\u{1056e}'), - ('\u{10570}', '\u{105ff}'), ('\u{10737}', '\u{1073f}'), ('\u{10756}', '\u{1075f}'), - ('\u{10768}', '\u{107ff}'), ('\u{10806}', '\u{10807}'), ('\u{10809}', '\u{10809}'), - ('\u{10836}', '\u{10836}'), ('\u{10839}', '\u{1083b}'), ('\u{1083d}', '\u{1083e}'), - ('\u{10856}', '\u{10856}'), ('\u{1089f}', '\u{108a6}'), ('\u{108b0}', '\u{108ff}'), - ('\u{1091c}', '\u{1091e}'), ('\u{1093a}', '\u{1093e}'), ('\u{10940}', '\u{1097f}'), - ('\u{109b8}', '\u{109bd}'), ('\u{109c0}', '\u{109ff}'), ('\u{10a04}', '\u{10a04}'), - ('\u{10a07}', '\u{10a0b}'), ('\u{10a14}', '\u{10a14}'), ('\u{10a18}', '\u{10a18}'), - ('\u{10a34}', '\u{10a37}'), ('\u{10a3b}', '\u{10a3e}'), ('\u{10a48}', '\u{10a4f}'), - ('\u{10a59}', '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'), ('\u{10ae7}', '\u{10aea}'), - ('\u{10af7}', '\u{10aff}'), ('\u{10b36}', '\u{10b38}'), ('\u{10b56}', '\u{10b57}'), - ('\u{10b73}', '\u{10b77}'), ('\u{10b92}', '\u{10b98}'), ('\u{10b9d}', '\u{10ba8}'), - ('\u{10bb0}', '\u{10bff}'), ('\u{10c49}', '\u{10e5f}'), ('\u{10e7f}', '\u{10fff}'), - ('\u{1104e}', '\u{11051}'), ('\u{11070}', '\u{1107e}'), ('\u{110c2}', '\u{110cf}'), - ('\u{110e9}', '\u{110ef}'), ('\u{110fa}', '\u{110ff}'), ('\u{11135}', '\u{11135}'), - ('\u{11144}', '\u{1114f}'), ('\u{11177}', '\u{1117f}'), ('\u{111c9}', '\u{111cc}'), - ('\u{111ce}', '\u{111cf}'), ('\u{111db}', '\u{111e0}'), ('\u{111f5}', '\u{111ff}'), - ('\u{11212}', '\u{11212}'), ('\u{1123e}', '\u{112af}'), ('\u{112eb}', '\u{112ef}'), - ('\u{112fa}', '\u{11300}'), ('\u{11304}', '\u{11304}'), ('\u{1130d}', '\u{1130e}'), - ('\u{11311}', '\u{11312}'), ('\u{11329}', '\u{11329}'), ('\u{11331}', '\u{11331}'), - ('\u{11334}', '\u{11334}'), ('\u{1133a}', '\u{1133b}'), ('\u{11345}', '\u{11346}'), - ('\u{11349}', '\u{1134a}'), ('\u{1134e}', '\u{11356}'), ('\u{11358}', '\u{1135c}'), - ('\u{11364}', '\u{11365}'), ('\u{1136d}', '\u{1136f}'), ('\u{11375}', '\u{1147f}'), - ('\u{114c8}', '\u{114cf}'), ('\u{114da}', '\u{1157f}'), ('\u{115b6}', '\u{115b7}'), - ('\u{115ca}', '\u{115ff}'), ('\u{11645}', '\u{1164f}'), ('\u{1165a}', '\u{1167f}'), - ('\u{116b8}', '\u{116bf}'), ('\u{116ca}', '\u{1189f}'), ('\u{118f3}', '\u{118fe}'), - ('\u{11900}', '\u{11abf}'), ('\u{11af9}', '\u{11fff}'), ('\u{12399}', '\u{123ff}'), - ('\u{1246f}', '\u{1246f}'), ('\u{12475}', '\u{12fff}'), ('\u{1342f}', '\u{167ff}'), - ('\u{16a39}', '\u{16a3f}'), ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}', '\u{16a6d}'), - ('\u{16a70}', '\u{16acf}'), ('\u{16aee}', '\u{16aef}'), ('\u{16af6}', '\u{16aff}'), - ('\u{16b46}', '\u{16b4f}'), ('\u{16b5a}', '\u{16b5a}'), ('\u{16b62}', '\u{16b62}'), - ('\u{16b78}', '\u{16b7c}'), ('\u{16b90}', '\u{16eff}'), ('\u{16f45}', '\u{16f4f}'), - ('\u{16f7f}', '\u{16f8e}'), ('\u{16fa0}', '\u{1afff}'), ('\u{1b002}', '\u{1bbff}'), - ('\u{1bc6b}', '\u{1bc6f}'), ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}', '\u{1bc8f}'), - ('\u{1bc9a}', '\u{1bc9b}'), ('\u{1bca4}', '\u{1cfff}'), ('\u{1d0f6}', '\u{1d0ff}'), - ('\u{1d127}', '\u{1d128}'), ('\u{1d1de}', '\u{1d1ff}'), ('\u{1d246}', '\u{1d2ff}'), - ('\u{1d357}', '\u{1d35f}'), ('\u{1d372}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'), - ('\u{1d49d}', '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'), - ('\u{1d4a7}', '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}', '\u{1d4ba}'), - ('\u{1d4bc}', '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'), ('\u{1d506}', '\u{1d506}'), - ('\u{1d50b}', '\u{1d50c}'), ('\u{1d515}', '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'), - ('\u{1d53a}', '\u{1d53a}'), ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'), - ('\u{1d547}', '\u{1d549}'), ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'), - ('\u{1d7cc}', '\u{1d7cd}'), ('\u{1d800}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'), - ('\u{1e8d7}', '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}', '\u{1ee20}'), - ('\u{1ee23}', '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'), ('\u{1ee28}', '\u{1ee28}'), - ('\u{1ee33}', '\u{1ee33}'), ('\u{1ee38}', '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'), - ('\u{1ee3c}', '\u{1ee41}'), ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'), - ('\u{1ee4a}', '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'), - ('\u{1ee53}', '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}', '\u{1ee58}'), - ('\u{1ee5a}', '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'), ('\u{1ee5e}', '\u{1ee5e}'), - ('\u{1ee60}', '\u{1ee60}'), ('\u{1ee63}', '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'), - ('\u{1ee6b}', '\u{1ee6b}'), ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'), - ('\u{1ee7d}', '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'), - ('\u{1ee9c}', '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}', '\u{1eeaa}'), - ('\u{1eebc}', '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'), ('\u{1f02c}', '\u{1f02f}'), - ('\u{1f094}', '\u{1f09f}'), ('\u{1f0af}', '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'), - ('\u{1f0d0}', '\u{1f0d0}'), ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'), - ('\u{1f12f}', '\u{1f12f}'), ('\u{1f16c}', '\u{1f16f}'), ('\u{1f19b}', '\u{1f1e5}'), - ('\u{1f203}', '\u{1f20f}'), ('\u{1f23b}', '\u{1f23f}'), ('\u{1f249}', '\u{1f24f}'), - ('\u{1f252}', '\u{1f2ff}'), ('\u{1f32d}', '\u{1f32f}'), ('\u{1f37e}', '\u{1f37f}'), - ('\u{1f3cf}', '\u{1f3d3}'), ('\u{1f3f8}', '\u{1f3ff}'), ('\u{1f4ff}', '\u{1f4ff}'), - ('\u{1f54b}', '\u{1f54f}'), ('\u{1f57a}', '\u{1f57a}'), ('\u{1f5a4}', '\u{1f5a4}'), - ('\u{1f643}', '\u{1f644}'), ('\u{1f6d0}', '\u{1f6df}'), ('\u{1f6ed}', '\u{1f6ef}'), - ('\u{1f6f4}', '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'), ('\u{1f7d5}', '\u{1f7ff}'), - ('\u{1f80c}', '\u{1f80f}'), ('\u{1f848}', '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), - ('\u{1f888}', '\u{1f88f}'), ('\u{1f8ae}', '\u{1ffff}'), ('\u{20001}', '\u{2a6d5}'), - ('\u{2a6d7}', '\u{2a6ff}'), ('\u{2a701}', '\u{2b733}'), ('\u{2b735}', '\u{2b73f}'), - ('\u{2b741}', '\u{2b81c}'), ('\u{2b81e}', '\u{2f7ff}'), ('\u{2fa1e}', '\u{e0000}'), - ('\u{e0002}', '\u{e001f}'), ('\u{e0080}', '\u{e00ff}'), ('\u{e01f0}', '\u{effff}'), - ('\u{f0001}', '\u{ffffc}'), ('\u{ffffe}', '\u{fffff}'), ('\u{100001}', '\u{10fffc}'), - ('\u{10fffe}', '\u{10ffff}') - ]; - - pub static Co_table: &'static [(char, char)] = &[ - ('\u{e000}', '\u{e000}'), ('\u{f8ff}', '\u{f8ff}'), ('\u{f0000}', '\u{f0000}'), - ('\u{ffffd}', '\u{ffffd}'), ('\u{100000}', '\u{100000}'), ('\u{10fffd}', '\u{10fffd}') - ]; - - pub static L_table: &'static [(char, char)] = &[ + '\u{31ef}'), ('\u{321f}', '\u{321f}'), ('\u{32ff}', '\u{32ff}'), ('\u{4db6}', '\u{4dbf}'), + ('\u{9fcd}', '\u{9fff}'), ('\u{a48d}', '\u{a48f}'), ('\u{a4c7}', '\u{a4cf}'), ('\u{a62c}', + '\u{a63f}'), ('\u{a69e}', '\u{a69e}'), ('\u{a6f8}', '\u{a6ff}'), ('\u{a78f}', '\u{a78f}'), + ('\u{a7ae}', '\u{a7af}'), ('\u{a7b2}', '\u{a7f6}'), ('\u{a82c}', '\u{a82f}'), ('\u{a83a}', + '\u{a83f}'), ('\u{a878}', '\u{a87f}'), ('\u{a8c5}', '\u{a8cd}'), ('\u{a8da}', '\u{a8df}'), + ('\u{a8fc}', '\u{a8ff}'), ('\u{a954}', '\u{a95e}'), ('\u{a97d}', '\u{a97f}'), ('\u{a9ce}', + '\u{a9ce}'), ('\u{a9da}', '\u{a9dd}'), ('\u{a9ff}', '\u{a9ff}'), ('\u{aa37}', '\u{aa3f}'), + ('\u{aa4e}', '\u{aa4f}'), ('\u{aa5a}', '\u{aa5b}'), ('\u{aac3}', '\u{aada}'), ('\u{aaf7}', + '\u{ab00}'), ('\u{ab07}', '\u{ab08}'), ('\u{ab0f}', '\u{ab10}'), ('\u{ab17}', '\u{ab1f}'), + ('\u{ab27}', '\u{ab27}'), ('\u{ab2f}', '\u{ab2f}'), ('\u{ab60}', '\u{ab63}'), ('\u{ab66}', + '\u{abbf}'), ('\u{abee}', '\u{abef}'), ('\u{abfa}', '\u{abff}'), ('\u{d7a4}', '\u{d7af}'), + ('\u{d7c7}', '\u{d7ca}'), ('\u{d7fc}', '\u{d7ff}'), ('\u{fa6e}', '\u{fa6f}'), ('\u{fada}', + '\u{faff}'), ('\u{fb07}', '\u{fb12}'), ('\u{fb18}', '\u{fb1c}'), ('\u{fb37}', '\u{fb37}'), + ('\u{fb3d}', '\u{fb3d}'), ('\u{fb3f}', '\u{fb3f}'), ('\u{fb42}', '\u{fb42}'), ('\u{fb45}', + '\u{fb45}'), ('\u{fbc2}', '\u{fbd2}'), ('\u{fd40}', '\u{fd4f}'), ('\u{fd90}', '\u{fd91}'), + ('\u{fdc8}', '\u{fdef}'), ('\u{fdfe}', '\u{fdff}'), ('\u{fe1a}', '\u{fe1f}'), ('\u{fe2e}', + '\u{fe2f}'), ('\u{fe53}', '\u{fe53}'), ('\u{fe67}', '\u{fe67}'), ('\u{fe6c}', '\u{fe6f}'), + ('\u{fe75}', '\u{fe75}'), ('\u{fefd}', '\u{fefe}'), ('\u{ff00}', '\u{ff00}'), ('\u{ffbf}', + '\u{ffc1}'), ('\u{ffc8}', '\u{ffc9}'), ('\u{ffd0}', '\u{ffd1}'), ('\u{ffd8}', '\u{ffd9}'), + ('\u{ffdd}', '\u{ffdf}'), ('\u{ffe7}', '\u{ffe7}'), ('\u{ffef}', '\u{fff8}'), ('\u{fffe}', + '\u{ffff}'), ('\u{1000c}', '\u{1000c}'), ('\u{10027}', '\u{10027}'), ('\u{1003b}', + '\u{1003b}'), ('\u{1003e}', '\u{1003e}'), ('\u{1004e}', '\u{1004f}'), ('\u{1005e}', + '\u{1007f}'), ('\u{100fb}', '\u{100ff}'), ('\u{10103}', '\u{10106}'), ('\u{10134}', + '\u{10136}'), ('\u{1018d}', '\u{1018f}'), ('\u{1019c}', '\u{1019f}'), ('\u{101a1}', + '\u{101cf}'), ('\u{101fe}', '\u{1027f}'), ('\u{1029d}', '\u{1029f}'), ('\u{102d1}', + '\u{102df}'), ('\u{102fc}', '\u{102ff}'), ('\u{10324}', '\u{1032f}'), ('\u{1034b}', + '\u{1034f}'), ('\u{1037b}', '\u{1037f}'), ('\u{1039e}', '\u{1039e}'), ('\u{103c4}', + '\u{103c7}'), ('\u{103d6}', '\u{103ff}'), ('\u{1049e}', '\u{1049f}'), ('\u{104aa}', + '\u{104ff}'), ('\u{10528}', '\u{1052f}'), ('\u{10564}', '\u{1056e}'), ('\u{10570}', + '\u{105ff}'), ('\u{10737}', '\u{1073f}'), ('\u{10756}', '\u{1075f}'), ('\u{10768}', + '\u{107ff}'), ('\u{10806}', '\u{10807}'), ('\u{10809}', '\u{10809}'), ('\u{10836}', + '\u{10836}'), ('\u{10839}', '\u{1083b}'), ('\u{1083d}', '\u{1083e}'), ('\u{10856}', + '\u{10856}'), ('\u{1089f}', '\u{108a6}'), ('\u{108b0}', '\u{108ff}'), ('\u{1091c}', + '\u{1091e}'), ('\u{1093a}', '\u{1093e}'), ('\u{10940}', '\u{1097f}'), ('\u{109b8}', + '\u{109bd}'), ('\u{109c0}', '\u{109ff}'), ('\u{10a04}', '\u{10a04}'), ('\u{10a07}', + '\u{10a0b}'), ('\u{10a14}', '\u{10a14}'), ('\u{10a18}', '\u{10a18}'), ('\u{10a34}', + '\u{10a37}'), ('\u{10a3b}', '\u{10a3e}'), ('\u{10a48}', '\u{10a4f}'), ('\u{10a59}', + '\u{10a5f}'), ('\u{10aa0}', '\u{10abf}'), ('\u{10ae7}', '\u{10aea}'), ('\u{10af7}', + '\u{10aff}'), ('\u{10b36}', '\u{10b38}'), ('\u{10b56}', '\u{10b57}'), ('\u{10b73}', + '\u{10b77}'), ('\u{10b92}', '\u{10b98}'), ('\u{10b9d}', '\u{10ba8}'), ('\u{10bb0}', + '\u{10bff}'), ('\u{10c49}', '\u{10e5f}'), ('\u{10e7f}', '\u{10fff}'), ('\u{1104e}', + '\u{11051}'), ('\u{11070}', '\u{1107e}'), ('\u{110c2}', '\u{110cf}'), ('\u{110e9}', + '\u{110ef}'), ('\u{110fa}', '\u{110ff}'), ('\u{11135}', '\u{11135}'), ('\u{11144}', + '\u{1114f}'), ('\u{11177}', '\u{1117f}'), ('\u{111c9}', '\u{111cc}'), ('\u{111ce}', + '\u{111cf}'), ('\u{111db}', '\u{111e0}'), ('\u{111f5}', '\u{111ff}'), ('\u{11212}', + '\u{11212}'), ('\u{1123e}', '\u{112af}'), ('\u{112eb}', '\u{112ef}'), ('\u{112fa}', + '\u{11300}'), ('\u{11304}', '\u{11304}'), ('\u{1130d}', '\u{1130e}'), ('\u{11311}', + '\u{11312}'), ('\u{11329}', '\u{11329}'), ('\u{11331}', '\u{11331}'), ('\u{11334}', + '\u{11334}'), ('\u{1133a}', '\u{1133b}'), ('\u{11345}', '\u{11346}'), ('\u{11349}', + '\u{1134a}'), ('\u{1134e}', '\u{11356}'), ('\u{11358}', '\u{1135c}'), ('\u{11364}', + '\u{11365}'), ('\u{1136d}', '\u{1136f}'), ('\u{11375}', '\u{1147f}'), ('\u{114c8}', + '\u{114cf}'), ('\u{114da}', '\u{1157f}'), ('\u{115b6}', '\u{115b7}'), ('\u{115ca}', + '\u{115ff}'), ('\u{11645}', '\u{1164f}'), ('\u{1165a}', '\u{1167f}'), ('\u{116b8}', + '\u{116bf}'), ('\u{116ca}', '\u{1189f}'), ('\u{118f3}', '\u{118fe}'), ('\u{11900}', + '\u{11abf}'), ('\u{11af9}', '\u{11fff}'), ('\u{12399}', '\u{123ff}'), ('\u{1246f}', + '\u{1246f}'), ('\u{12475}', '\u{12fff}'), ('\u{1342f}', '\u{167ff}'), ('\u{16a39}', + '\u{16a3f}'), ('\u{16a5f}', '\u{16a5f}'), ('\u{16a6a}', '\u{16a6d}'), ('\u{16a70}', + '\u{16acf}'), ('\u{16aee}', '\u{16aef}'), ('\u{16af6}', '\u{16aff}'), ('\u{16b46}', + '\u{16b4f}'), ('\u{16b5a}', '\u{16b5a}'), ('\u{16b62}', '\u{16b62}'), ('\u{16b78}', + '\u{16b7c}'), ('\u{16b90}', '\u{16eff}'), ('\u{16f45}', '\u{16f4f}'), ('\u{16f7f}', + '\u{16f8e}'), ('\u{16fa0}', '\u{1afff}'), ('\u{1b002}', '\u{1bbff}'), ('\u{1bc6b}', + '\u{1bc6f}'), ('\u{1bc7d}', '\u{1bc7f}'), ('\u{1bc89}', '\u{1bc8f}'), ('\u{1bc9a}', + '\u{1bc9b}'), ('\u{1bca4}', '\u{1cfff}'), ('\u{1d0f6}', '\u{1d0ff}'), ('\u{1d127}', + '\u{1d128}'), ('\u{1d1de}', '\u{1d1ff}'), ('\u{1d246}', '\u{1d2ff}'), ('\u{1d357}', + '\u{1d35f}'), ('\u{1d372}', '\u{1d3ff}'), ('\u{1d455}', '\u{1d455}'), ('\u{1d49d}', + '\u{1d49d}'), ('\u{1d4a0}', '\u{1d4a1}'), ('\u{1d4a3}', '\u{1d4a4}'), ('\u{1d4a7}', + '\u{1d4a8}'), ('\u{1d4ad}', '\u{1d4ad}'), ('\u{1d4ba}', '\u{1d4ba}'), ('\u{1d4bc}', + '\u{1d4bc}'), ('\u{1d4c4}', '\u{1d4c4}'), ('\u{1d506}', '\u{1d506}'), ('\u{1d50b}', + '\u{1d50c}'), ('\u{1d515}', '\u{1d515}'), ('\u{1d51d}', '\u{1d51d}'), ('\u{1d53a}', + '\u{1d53a}'), ('\u{1d53f}', '\u{1d53f}'), ('\u{1d545}', '\u{1d545}'), ('\u{1d547}', + '\u{1d549}'), ('\u{1d551}', '\u{1d551}'), ('\u{1d6a6}', '\u{1d6a7}'), ('\u{1d7cc}', + '\u{1d7cd}'), ('\u{1d800}', '\u{1e7ff}'), ('\u{1e8c5}', '\u{1e8c6}'), ('\u{1e8d7}', + '\u{1edff}'), ('\u{1ee04}', '\u{1ee04}'), ('\u{1ee20}', '\u{1ee20}'), ('\u{1ee23}', + '\u{1ee23}'), ('\u{1ee25}', '\u{1ee26}'), ('\u{1ee28}', '\u{1ee28}'), ('\u{1ee33}', + '\u{1ee33}'), ('\u{1ee38}', '\u{1ee38}'), ('\u{1ee3a}', '\u{1ee3a}'), ('\u{1ee3c}', + '\u{1ee41}'), ('\u{1ee43}', '\u{1ee46}'), ('\u{1ee48}', '\u{1ee48}'), ('\u{1ee4a}', + '\u{1ee4a}'), ('\u{1ee4c}', '\u{1ee4c}'), ('\u{1ee50}', '\u{1ee50}'), ('\u{1ee53}', + '\u{1ee53}'), ('\u{1ee55}', '\u{1ee56}'), ('\u{1ee58}', '\u{1ee58}'), ('\u{1ee5a}', + '\u{1ee5a}'), ('\u{1ee5c}', '\u{1ee5c}'), ('\u{1ee5e}', '\u{1ee5e}'), ('\u{1ee60}', + '\u{1ee60}'), ('\u{1ee63}', '\u{1ee63}'), ('\u{1ee65}', '\u{1ee66}'), ('\u{1ee6b}', + '\u{1ee6b}'), ('\u{1ee73}', '\u{1ee73}'), ('\u{1ee78}', '\u{1ee78}'), ('\u{1ee7d}', + '\u{1ee7d}'), ('\u{1ee7f}', '\u{1ee7f}'), ('\u{1ee8a}', '\u{1ee8a}'), ('\u{1ee9c}', + '\u{1eea0}'), ('\u{1eea4}', '\u{1eea4}'), ('\u{1eeaa}', '\u{1eeaa}'), ('\u{1eebc}', + '\u{1eeef}'), ('\u{1eef2}', '\u{1efff}'), ('\u{1f02c}', '\u{1f02f}'), ('\u{1f094}', + '\u{1f09f}'), ('\u{1f0af}', '\u{1f0b0}'), ('\u{1f0c0}', '\u{1f0c0}'), ('\u{1f0d0}', + '\u{1f0d0}'), ('\u{1f0f6}', '\u{1f0ff}'), ('\u{1f10d}', '\u{1f10f}'), ('\u{1f12f}', + '\u{1f12f}'), ('\u{1f16c}', '\u{1f16f}'), ('\u{1f19b}', '\u{1f1e5}'), ('\u{1f203}', + '\u{1f20f}'), ('\u{1f23b}', '\u{1f23f}'), ('\u{1f249}', '\u{1f24f}'), ('\u{1f252}', + '\u{1f2ff}'), ('\u{1f32d}', '\u{1f32f}'), ('\u{1f37e}', '\u{1f37f}'), ('\u{1f3cf}', + '\u{1f3d3}'), ('\u{1f3f8}', '\u{1f3ff}'), ('\u{1f4ff}', '\u{1f4ff}'), ('\u{1f54b}', + '\u{1f54f}'), ('\u{1f57a}', '\u{1f57a}'), ('\u{1f5a4}', '\u{1f5a4}'), ('\u{1f643}', + '\u{1f644}'), ('\u{1f6d0}', '\u{1f6df}'), ('\u{1f6ed}', '\u{1f6ef}'), ('\u{1f6f4}', + '\u{1f6ff}'), ('\u{1f774}', '\u{1f77f}'), ('\u{1f7d5}', '\u{1f7ff}'), ('\u{1f80c}', + '\u{1f80f}'), ('\u{1f848}', '\u{1f84f}'), ('\u{1f85a}', '\u{1f85f}'), ('\u{1f888}', + '\u{1f88f}'), ('\u{1f8ae}', '\u{1ffff}'), ('\u{2a6d7}', '\u{2a6ff}'), ('\u{2b735}', + '\u{2b73f}'), ('\u{2b81e}', '\u{2f7ff}'), ('\u{2fa1e}', '\u{e0000}'), ('\u{e0002}', + '\u{e001f}'), ('\u{e0080}', '\u{e00ff}'), ('\u{e01f0}', '\u{effff}'), ('\u{ffffe}', + '\u{fffff}'), ('\u{10fffe}', '\u{10ffff}') + ]; + + pub const Co_table: &'static [(char, char)] = &[ + ('\u{e000}', '\u{f8ff}'), ('\u{f0000}', '\u{ffffd}'), ('\u{100000}', '\u{10fffd}') + ]; + + pub const L_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', @@ -511,89 +505,87 @@ pub mod general_category { ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}', '\u{3006}'), ('\u{3031}', '\u{3035}'), ('\u{303b}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}', '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', - '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{3400}'), ('\u{4db5}', '\u{4db5}'), - ('\u{4e00}', '\u{4e00}'), ('\u{9fcc}', '\u{9fcc}'), ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', - '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), - ('\u{a640}', '\u{a66e}'), ('\u{a67f}', '\u{a69d}'), ('\u{a6a0}', '\u{a6e5}'), ('\u{a717}', - '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a78e}'), ('\u{a790}', '\u{a7ad}'), - ('\u{a7b0}', '\u{a7b1}'), ('\u{a7f7}', '\u{a801}'), ('\u{a803}', '\u{a805}'), ('\u{a807}', - '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}', '\u{a873}'), ('\u{a882}', '\u{a8b3}'), - ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a90a}', '\u{a925}'), ('\u{a930}', - '\u{a946}'), ('\u{a960}', '\u{a97c}'), ('\u{a984}', '\u{a9b2}'), ('\u{a9cf}', '\u{a9cf}'), - ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', - '\u{aa28}'), ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}', '\u{aa76}'), - ('\u{aa7a}', '\u{aa7a}'), ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', - '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), - ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}', '\u{aaf4}'), ('\u{ab01}', - '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), - ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab5f}'), ('\u{ab64}', - '\u{ab65}'), ('\u{abc0}', '\u{abe2}'), ('\u{ac00}', '\u{ac00}'), ('\u{d7a3}', '\u{d7a3}'), - ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', - '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb1d}'), - ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', - '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), - ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', - '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), - ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', - '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), - ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), - ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), - ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{10300}', '\u{1031f}'), - ('\u{10330}', '\u{10340}'), ('\u{10342}', '\u{10349}'), ('\u{10350}', '\u{10375}'), - ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), - ('\u{10400}', '\u{1049d}'), ('\u{10500}', '\u{10527}'), ('\u{10530}', '\u{10563}'), - ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}'), - ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), - ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'), - ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{10900}', '\u{10915}'), - ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', '\u{109bf}'), - ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), - ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), - ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), - ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), - ('\u{10c00}', '\u{10c48}'), ('\u{11003}', '\u{11037}'), ('\u{11083}', '\u{110af}'), - ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}', '\u{11172}'), - ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'), ('\u{111c1}', '\u{111c4}'), - ('\u{111da}', '\u{111da}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1122b}'), - ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'), - ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), - ('\u{11335}', '\u{11339}'), ('\u{1133d}', '\u{1133d}'), ('\u{1135d}', '\u{11361}'), - ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), - ('\u{11580}', '\u{115ae}'), ('\u{11600}', '\u{1162f}'), ('\u{11644}', '\u{11644}'), - ('\u{11680}', '\u{116aa}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', '\u{118ff}'), - ('\u{11ac0}', '\u{11af8}'), ('\u{12000}', '\u{12398}'), ('\u{13000}', '\u{1342e}'), - ('\u{16800}', '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), - ('\u{16b00}', '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'), - ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'), - ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), - ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), - ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), - ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), - ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), - ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), - ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), - ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), - ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), - ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), - ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), - ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), - ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), - ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), - ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), - ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), - ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), - ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), - ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), - ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), - ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), - ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), - ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), - ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{20000}'), ('\u{2a6d6}', '\u{2a6d6}'), - ('\u{2a700}', '\u{2a700}'), ('\u{2b734}', '\u{2b734}'), ('\u{2b740}', '\u{2b740}'), - ('\u{2b81d}', '\u{2b81d}'), ('\u{2f800}', '\u{2fa1d}') + '\u{31ba}'), ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fcc}'), + ('\u{a000}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', + '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'), ('\u{a67f}', '\u{a69d}'), + ('\u{a6a0}', '\u{a6e5}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', + '\u{a78e}'), ('\u{a790}', '\u{a7ad}'), ('\u{a7b0}', '\u{a7b1}'), ('\u{a7f7}', '\u{a801}'), + ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}', + '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), + ('\u{a90a}', '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', '\u{a97c}'), ('\u{a984}', + '\u{a9b2}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e6}', '\u{a9ef}'), + ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'), ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', + '\u{aa4b}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'), ('\u{aa7e}', '\u{aaaf}'), + ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', + '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), ('\u{aae0}', '\u{aaea}'), + ('\u{aaf2}', '\u{aaf4}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', + '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), + ('\u{ab5c}', '\u{ab5f}'), ('\u{ab64}', '\u{ab65}'), ('\u{abc0}', '\u{abe2}'), ('\u{ac00}', + '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), + ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', + '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), + ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', + '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), + ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', + '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), + ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', + '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', + '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', + '\u{100fa}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{10300}', + '\u{1031f}'), ('\u{10330}', '\u{10340}'), ('\u{10342}', '\u{10349}'), ('\u{10350}', + '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', + '\u{103cf}'), ('\u{10400}', '\u{1049d}'), ('\u{10500}', '\u{10527}'), ('\u{10530}', + '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}', + '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', + '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', + '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), ('\u{10900}', + '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}', + '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}', + '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', + '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', + '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', + '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{11003}', '\u{11037}'), ('\u{11083}', + '\u{110af}'), ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'), ('\u{11150}', + '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'), ('\u{111c1}', + '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{11200}', '\u{11211}'), ('\u{11213}', + '\u{1122b}'), ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', + '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', + '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}', '\u{1133d}'), ('\u{1135d}', + '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', + '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{11600}', '\u{1162f}'), ('\u{11644}', + '\u{11644}'), ('\u{11680}', '\u{116aa}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}', + '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), ('\u{12000}', '\u{12398}'), ('\u{13000}', + '\u{1342e}'), ('\u{16800}', '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', + '\u{16aed}'), ('\u{16b00}', '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', + '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', + '\u{16f50}'), ('\u{16f93}', '\u{16f9f}'), ('\u{1b000}', '\u{1b001}'), ('\u{1bc00}', + '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', + '\u{1bc99}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', + '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', + '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', + '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', + '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', + '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', + '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', + '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', + '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', + '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', + '\u{1d7cb}'), ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', + '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', + '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', + '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', + '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', + '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', + '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', + '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', + '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', + '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', + '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', + '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{2a6d6}'), ('\u{2a700}', + '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2f800}', '\u{2fa1d}') ]; - pub static LC_table: &'static [(char, char)] = &[ + pub const LC_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{b5}', '\u{b5}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'), ('\u{1bc}', '\u{1bf}'), ('\u{1c4}', '\u{293}'), ('\u{295}', '\u{2af}'), ('\u{370}', '\u{373}'), ('\u{376}', '\u{377}'), ('\u{37b}', @@ -631,7 +623,7 @@ pub mod general_category { ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}') ]; - pub static Ll_table: &'static [(char, char)] = &[ + pub const Ll_table: &'static [(char, char)] = &[ ('\u{61}', '\u{7a}'), ('\u{b5}', '\u{b5}'), ('\u{df}', '\u{f6}'), ('\u{f8}', '\u{ff}'), ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'), ('\u{105}', '\u{105}'), ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'), ('\u{10b}', '\u{10b}'), ('\u{10d}', '\u{10d}'), @@ -814,7 +806,7 @@ pub mod general_category { '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7c9}'), ('\u{1d7cb}', '\u{1d7cb}') ]; - pub static Lm_table: &'static [(char, char)] = &[ + pub const Lm_table: &'static [(char, char)] = &[ ('\u{2b0}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'), ('\u{2ec}', '\u{2ec}'), ('\u{2ee}', '\u{2ee}'), ('\u{374}', '\u{374}'), ('\u{37a}', '\u{37a}'), ('\u{559}', '\u{559}'), ('\u{640}', '\u{640}'), ('\u{6e5}', '\u{6e6}'), ('\u{7f4}', @@ -834,7 +826,7 @@ pub mod general_category { '\u{16f9f}') ]; - pub static Lo_table: &'static [(char, char)] = &[ + pub const Lo_table: &'static [(char, char)] = &[ ('\u{aa}', '\u{aa}'), ('\u{ba}', '\u{ba}'), ('\u{1bb}', '\u{1bb}'), ('\u{1c0}', '\u{1c3}'), ('\u{294}', '\u{294}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', '\u{5f2}'), ('\u{620}', '\u{63f}'), ('\u{641}', '\u{64a}'), ('\u{66e}', '\u{66f}'), ('\u{671}', '\u{6d3}'), @@ -896,81 +888,80 @@ pub mod general_category { '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{3006}', '\u{3006}'), ('\u{303c}', '\u{303c}'), ('\u{3041}', '\u{3096}'), ('\u{309f}', '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30ff}', '\u{30ff}'), ('\u{3105}', '\u{312d}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31ba}'), - ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{3400}'), ('\u{4db5}', '\u{4db5}'), ('\u{4e00}', - '\u{4e00}'), ('\u{9fcc}', '\u{9fcc}'), ('\u{a000}', '\u{a014}'), ('\u{a016}', '\u{a48c}'), - ('\u{a4d0}', '\u{a4f7}'), ('\u{a500}', '\u{a60b}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', - '\u{a62b}'), ('\u{a66e}', '\u{a66e}'), ('\u{a6a0}', '\u{a6e5}'), ('\u{a7f7}', '\u{a7f7}'), - ('\u{a7fb}', '\u{a801}'), ('\u{a803}', '\u{a805}'), ('\u{a807}', '\u{a80a}'), ('\u{a80c}', - '\u{a822}'), ('\u{a840}', '\u{a873}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), - ('\u{a8fb}', '\u{a8fb}'), ('\u{a90a}', '\u{a925}'), ('\u{a930}', '\u{a946}'), ('\u{a960}', - '\u{a97c}'), ('\u{a984}', '\u{a9b2}'), ('\u{a9e0}', '\u{a9e4}'), ('\u{a9e7}', '\u{a9ef}'), - ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'), ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', - '\u{aa4b}'), ('\u{aa60}', '\u{aa6f}'), ('\u{aa71}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'), - ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab9}', - '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadc}'), - ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}', '\u{aaf2}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', - '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), - ('\u{abc0}', '\u{abe2}'), ('\u{ac00}', '\u{ac00}'), ('\u{d7a3}', '\u{d7a3}'), ('\u{d7b0}', - '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), - ('\u{fb1d}', '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', - '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), - ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', - '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), - ('\u{ff66}', '\u{ff6f}'), ('\u{ff71}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}', - '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), - ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), - ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), - ('\u{10080}', '\u{100fa}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), - ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{10340}'), ('\u{10342}', '\u{10349}'), - ('\u{10350}', '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), - ('\u{103c8}', '\u{103cf}'), ('\u{10450}', '\u{1049d}'), ('\u{10500}', '\u{10527}'), - ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), - ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), - ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), - ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', '\u{1089e}'), - ('\u{10900}', '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), - ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', '\u{10a13}'), - ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', '\u{10a7c}'), - ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', '\u{10ae4}'), - ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', '\u{10b72}'), - ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{11003}', '\u{11037}'), - ('\u{11083}', '\u{110af}'), ('\u{110d0}', '\u{110e8}'), ('\u{11103}', '\u{11126}'), - ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}', '\u{111b2}'), - ('\u{111c1}', '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{11200}', '\u{11211}'), - ('\u{11213}', '\u{1122b}'), ('\u{112b0}', '\u{112de}'), ('\u{11305}', '\u{1130c}'), - ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), - ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}', '\u{1133d}'), - ('\u{1135d}', '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', '\u{114c5}'), - ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{11600}', '\u{1162f}'), - ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116aa}'), ('\u{118ff}', '\u{118ff}'), - ('\u{11ac0}', '\u{11af8}'), ('\u{12000}', '\u{12398}'), ('\u{13000}', '\u{1342e}'), - ('\u{16800}', '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', '\u{16aed}'), - ('\u{16b00}', '\u{16b2f}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), - ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'), ('\u{1b000}', '\u{1b001}'), - ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), - ('\u{1bc90}', '\u{1bc99}'), ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', '\u{1ee03}'), - ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), - ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), - ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), - ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), - ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), - ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), - ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), - ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), - ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), - ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), - ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', '\u{20000}'), - ('\u{2a6d6}', '\u{2a6d6}'), ('\u{2a700}', '\u{2a700}'), ('\u{2b734}', '\u{2b734}'), - ('\u{2b740}', '\u{2b740}'), ('\u{2b81d}', '\u{2b81d}'), ('\u{2f800}', '\u{2fa1d}') + ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fcc}'), ('\u{a000}', + '\u{a014}'), ('\u{a016}', '\u{a48c}'), ('\u{a4d0}', '\u{a4f7}'), ('\u{a500}', '\u{a60b}'), + ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a66e}', '\u{a66e}'), ('\u{a6a0}', + '\u{a6e5}'), ('\u{a7f7}', '\u{a7f7}'), ('\u{a7fb}', '\u{a801}'), ('\u{a803}', '\u{a805}'), + ('\u{a807}', '\u{a80a}'), ('\u{a80c}', '\u{a822}'), ('\u{a840}', '\u{a873}'), ('\u{a882}', + '\u{a8b3}'), ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a90a}', '\u{a925}'), + ('\u{a930}', '\u{a946}'), ('\u{a960}', '\u{a97c}'), ('\u{a984}', '\u{a9b2}'), ('\u{a9e0}', + '\u{a9e4}'), ('\u{a9e7}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}', '\u{aa28}'), + ('\u{aa40}', '\u{aa42}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa60}', '\u{aa6f}'), ('\u{aa71}', + '\u{aa76}'), ('\u{aa7a}', '\u{aa7a}'), ('\u{aa7e}', '\u{aaaf}'), ('\u{aab1}', '\u{aab1}'), + ('\u{aab5}', '\u{aab6}'), ('\u{aab9}', '\u{aabd}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', + '\u{aac2}'), ('\u{aadb}', '\u{aadc}'), ('\u{aae0}', '\u{aaea}'), ('\u{aaf2}', '\u{aaf2}'), + ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', + '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{abc0}', '\u{abe2}'), ('\u{ac00}', '\u{d7a3}'), + ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}', + '\u{fad9}'), ('\u{fb1d}', '\u{fb1d}'), ('\u{fb1f}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), + ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', + '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), + ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', + '\u{fefc}'), ('\u{ff66}', '\u{ff6f}'), ('\u{ff71}', '\u{ff9d}'), ('\u{ffa0}', '\u{ffbe}'), + ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', + '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', + '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', + '\u{1005d}'), ('\u{10080}', '\u{100fa}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', + '\u{102d0}'), ('\u{10300}', '\u{1031f}'), ('\u{10330}', '\u{10340}'), ('\u{10342}', + '\u{10349}'), ('\u{10350}', '\u{10375}'), ('\u{10380}', '\u{1039d}'), ('\u{103a0}', + '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{10450}', '\u{1049d}'), ('\u{10500}', + '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10600}', '\u{10736}'), ('\u{10740}', + '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10800}', '\u{10805}'), ('\u{10808}', + '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', + '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}', + '\u{1089e}'), ('\u{10900}', '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', + '\u{109b7}'), ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a00}'), ('\u{10a10}', + '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a60}', + '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}', + '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}', + '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{11003}', + '\u{11037}'), ('\u{11083}', '\u{110af}'), ('\u{110d0}', '\u{110e8}'), ('\u{11103}', + '\u{11126}'), ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11183}', + '\u{111b2}'), ('\u{111c1}', '\u{111c4}'), ('\u{111da}', '\u{111da}'), ('\u{11200}', + '\u{11211}'), ('\u{11213}', '\u{1122b}'), ('\u{112b0}', '\u{112de}'), ('\u{11305}', + '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', + '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133d}', + '\u{1133d}'), ('\u{1135d}', '\u{11361}'), ('\u{11480}', '\u{114af}'), ('\u{114c4}', + '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115ae}'), ('\u{11600}', + '\u{1162f}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116aa}'), ('\u{118ff}', + '\u{118ff}'), ('\u{11ac0}', '\u{11af8}'), ('\u{12000}', '\u{12398}'), ('\u{13000}', + '\u{1342e}'), ('\u{16800}', '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16ad0}', + '\u{16aed}'), ('\u{16b00}', '\u{16b2f}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', + '\u{16b8f}'), ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'), ('\u{1b000}', + '\u{1b001}'), ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', + '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1e800}', '\u{1e8c4}'), ('\u{1ee00}', + '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'), ('\u{1ee24}', + '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'), ('\u{1ee34}', + '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'), ('\u{1ee42}', + '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'), ('\u{1ee4b}', + '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'), ('\u{1ee54}', + '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'), ('\u{1ee5b}', + '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'), ('\u{1ee61}', + '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'), ('\u{1ee6c}', + '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'), ('\u{1ee7e}', + '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'), ('\u{1eea1}', + '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'), ('\u{20000}', + '\u{2a6d6}'), ('\u{2a700}', '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2f800}', + '\u{2fa1d}') ]; - pub static Lt_table: &'static [(char, char)] = &[ + pub const Lt_table: &'static [(char, char)] = &[ ('\u{1c5}', '\u{1c5}'), ('\u{1c8}', '\u{1c8}'), ('\u{1cb}', '\u{1cb}'), ('\u{1f2}', '\u{1f2}'), ('\u{1f88}', '\u{1f8f}'), ('\u{1f98}', '\u{1f9f}'), ('\u{1fa8}', '\u{1faf}'), ('\u{1fbc}', '\u{1fbc}'), ('\u{1fcc}', '\u{1fcc}'), ('\u{1ffc}', '\u{1ffc}') ]; - pub static Lu_table: &'static [(char, char)] = &[ + pub const Lu_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'), ('\u{100}', '\u{100}'), ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'), ('\u{106}', '\u{106}'), ('\u{108}', '\u{108}'), ('\u{10a}', '\u{10a}'), ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), @@ -1153,7 +1144,7 @@ pub mod general_category { '\u{1d7ca}') ]; - pub static M_table: &'static [(char, char)] = &[ + pub const M_table: &'static [(char, char)] = &[ ('\u{300}', '\u{36f}'), ('\u{483}', '\u{489}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'), ('\u{670}', '\u{670}'), ('\u{6d6}', @@ -1224,7 +1215,7 @@ pub mod general_category { ('\u{1e8d0}', '\u{1e8d6}'), ('\u{e0100}', '\u{e01ef}') ]; - pub static Mc_table: &'static [(char, char)] = &[ + pub const Mc_table: &'static [(char, char)] = &[ ('\u{903}', '\u{903}'), ('\u{93b}', '\u{93b}'), ('\u{93e}', '\u{940}'), ('\u{949}', '\u{94c}'), ('\u{94e}', '\u{94f}'), ('\u{982}', '\u{983}'), ('\u{9be}', '\u{9c0}'), ('\u{9c7}', '\u{9c8}'), ('\u{9cb}', '\u{9cc}'), ('\u{9d7}', '\u{9d7}'), ('\u{a03}', @@ -1271,12 +1262,12 @@ pub mod general_category { ('\u{1d165}', '\u{1d166}'), ('\u{1d16d}', '\u{1d172}') ]; - pub static Me_table: &'static [(char, char)] = &[ + pub const Me_table: &'static [(char, char)] = &[ ('\u{488}', '\u{489}'), ('\u{1abe}', '\u{1abe}'), ('\u{20dd}', '\u{20e0}'), ('\u{20e2}', '\u{20e4}'), ('\u{a670}', '\u{a672}') ]; - pub static Mn_table: &'static [(char, char)] = &[ + pub const Mn_table: &'static [(char, char)] = &[ ('\u{300}', '\u{36f}'), ('\u{483}', '\u{487}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'), ('\u{670}', '\u{670}'), ('\u{6d6}', @@ -1355,7 +1346,7 @@ pub mod general_category { '\u{1e8d6}'), ('\u{e0100}', '\u{e01ef}') ]; - pub static N_table: &'static [(char, char)] = &[ + pub const N_table: &'static [(char, char)] = &[ ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'), ('\u{7c0}', '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'), ('\u{a66}', '\u{a6f}'), ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'), ('\u{be6}', '\u{bef}'), ('\u{c66}', @@ -1381,7 +1372,7 @@ pub mod general_category { super::bsearch_range_table(c, N_table) } - pub static Nd_table: &'static [(char, char)] = &[ + pub const Nd_table: &'static [(char, char)] = &[ ('\u{30}', '\u{39}'), ('\u{660}', '\u{669}'), ('\u{6f0}', '\u{6f9}'), ('\u{7c0}', '\u{7c9}'), ('\u{966}', '\u{96f}'), ('\u{9e6}', '\u{9ef}'), ('\u{a66}', '\u{a6f}'), ('\u{ae6}', '\u{aef}'), ('\u{b66}', '\u{b6f}'), ('\u{be6}', '\u{bef}'), ('\u{c66}', @@ -1399,14 +1390,14 @@ pub mod general_category { ('\u{16a60}', '\u{16a69}'), ('\u{16b50}', '\u{16b59}'), ('\u{1d7ce}', '\u{1d7ff}') ]; - pub static Nl_table: &'static [(char, char)] = &[ + pub const Nl_table: &'static [(char, char)] = &[ ('\u{16ee}', '\u{16f0}'), ('\u{2160}', '\u{2182}'), ('\u{2185}', '\u{2188}'), ('\u{3007}', '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303a}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{10140}', '\u{10174}'), ('\u{10341}', '\u{10341}'), ('\u{1034a}', '\u{1034a}'), ('\u{103d1}', '\u{103d5}'), ('\u{12400}', '\u{1246e}') ]; - pub static No_table: &'static [(char, char)] = &[ + pub const No_table: &'static [(char, char)] = &[ ('\u{b2}', '\u{b3}'), ('\u{b9}', '\u{b9}'), ('\u{bc}', '\u{be}'), ('\u{9f4}', '\u{9f9}'), ('\u{b72}', '\u{b77}'), ('\u{bf0}', '\u{bf2}'), ('\u{c78}', '\u{c7e}'), ('\u{d70}', '\u{d75}'), ('\u{f2a}', '\u{f33}'), ('\u{1369}', '\u{137c}'), ('\u{17f0}', '\u{17f9}'), @@ -1425,7 +1416,7 @@ pub mod general_category { '\u{1d371}'), ('\u{1e8c7}', '\u{1e8cf}'), ('\u{1f100}', '\u{1f10c}') ]; - pub static P_table: &'static [(char, char)] = &[ + pub const P_table: &'static [(char, char)] = &[ ('\u{21}', '\u{23}'), ('\u{25}', '\u{2a}'), ('\u{2c}', '\u{2f}'), ('\u{3a}', '\u{3b}'), ('\u{3f}', '\u{40}'), ('\u{5b}', '\u{5d}'), ('\u{5f}', '\u{5f}'), ('\u{7b}', '\u{7b}'), ('\u{7d}', '\u{7d}'), ('\u{a1}', '\u{a1}'), ('\u{a7}', '\u{a7}'), ('\u{ab}', '\u{ab}'), @@ -1474,12 +1465,12 @@ pub mod general_category { '\u{1bc9f}') ]; - pub static Pc_table: &'static [(char, char)] = &[ + pub const Pc_table: &'static [(char, char)] = &[ ('\u{5f}', '\u{5f}'), ('\u{203f}', '\u{2040}'), ('\u{2054}', '\u{2054}'), ('\u{fe33}', '\u{fe34}'), ('\u{fe4d}', '\u{fe4f}'), ('\u{ff3f}', '\u{ff3f}') ]; - pub static Pd_table: &'static [(char, char)] = &[ + pub const Pd_table: &'static [(char, char)] = &[ ('\u{2d}', '\u{2d}'), ('\u{58a}', '\u{58a}'), ('\u{5be}', '\u{5be}'), ('\u{1400}', '\u{1400}'), ('\u{1806}', '\u{1806}'), ('\u{2010}', '\u{2015}'), ('\u{2e17}', '\u{2e17}'), ('\u{2e1a}', '\u{2e1a}'), ('\u{2e3a}', '\u{2e3b}'), ('\u{2e40}', '\u{2e40}'), ('\u{301c}', @@ -1487,7 +1478,7 @@ pub mod general_category { ('\u{fe58}', '\u{fe58}'), ('\u{fe63}', '\u{fe63}'), ('\u{ff0d}', '\u{ff0d}') ]; - pub static Pe_table: &'static [(char, char)] = &[ + pub const Pe_table: &'static [(char, char)] = &[ ('\u{29}', '\u{29}'), ('\u{5d}', '\u{5d}'), ('\u{7d}', '\u{7d}'), ('\u{f3b}', '\u{f3b}'), ('\u{f3d}', '\u{f3d}'), ('\u{169c}', '\u{169c}'), ('\u{2046}', '\u{2046}'), ('\u{207e}', '\u{207e}'), ('\u{208e}', '\u{208e}'), ('\u{2309}', '\u{2309}'), ('\u{230b}', '\u{230b}'), @@ -1511,20 +1502,20 @@ pub mod general_category { '\u{ff60}'), ('\u{ff63}', '\u{ff63}') ]; - pub static Pf_table: &'static [(char, char)] = &[ + pub const Pf_table: &'static [(char, char)] = &[ ('\u{bb}', '\u{bb}'), ('\u{2019}', '\u{2019}'), ('\u{201d}', '\u{201d}'), ('\u{203a}', '\u{203a}'), ('\u{2e03}', '\u{2e03}'), ('\u{2e05}', '\u{2e05}'), ('\u{2e0a}', '\u{2e0a}'), ('\u{2e0d}', '\u{2e0d}'), ('\u{2e1d}', '\u{2e1d}'), ('\u{2e21}', '\u{2e21}') ]; - pub static Pi_table: &'static [(char, char)] = &[ + pub const Pi_table: &'static [(char, char)] = &[ ('\u{ab}', '\u{ab}'), ('\u{2018}', '\u{2018}'), ('\u{201b}', '\u{201c}'), ('\u{201f}', '\u{201f}'), ('\u{2039}', '\u{2039}'), ('\u{2e02}', '\u{2e02}'), ('\u{2e04}', '\u{2e04}'), ('\u{2e09}', '\u{2e09}'), ('\u{2e0c}', '\u{2e0c}'), ('\u{2e1c}', '\u{2e1c}'), ('\u{2e20}', '\u{2e20}') ]; - pub static Po_table: &'static [(char, char)] = &[ + pub const Po_table: &'static [(char, char)] = &[ ('\u{21}', '\u{23}'), ('\u{25}', '\u{27}'), ('\u{2a}', '\u{2a}'), ('\u{2c}', '\u{2c}'), ('\u{2e}', '\u{2f}'), ('\u{3a}', '\u{3b}'), ('\u{3f}', '\u{40}'), ('\u{5c}', '\u{5c}'), ('\u{a1}', '\u{a1}'), ('\u{a7}', '\u{a7}'), ('\u{b6}', '\u{b7}'), ('\u{bf}', '\u{bf}'), @@ -1572,7 +1563,7 @@ pub mod general_category { '\u{1bc9f}') ]; - pub static Ps_table: &'static [(char, char)] = &[ + pub const Ps_table: &'static [(char, char)] = &[ ('\u{28}', '\u{28}'), ('\u{5b}', '\u{5b}'), ('\u{7b}', '\u{7b}'), ('\u{f3a}', '\u{f3a}'), ('\u{f3c}', '\u{f3c}'), ('\u{169b}', '\u{169b}'), ('\u{201a}', '\u{201a}'), ('\u{201e}', '\u{201e}'), ('\u{2045}', '\u{2045}'), ('\u{207d}', '\u{207d}'), ('\u{208d}', '\u{208d}'), @@ -1597,7 +1588,7 @@ pub mod general_category { ('\u{ff62}', '\u{ff62}') ]; - pub static S_table: &'static [(char, char)] = &[ + pub const S_table: &'static [(char, char)] = &[ ('\u{24}', '\u{24}'), ('\u{2b}', '\u{2b}'), ('\u{3c}', '\u{3e}'), ('\u{5e}', '\u{5e}'), ('\u{60}', '\u{60}'), ('\u{7c}', '\u{7c}'), ('\u{7e}', '\u{7e}'), ('\u{a2}', '\u{a6}'), ('\u{a8}', '\u{a9}'), ('\u{ac}', '\u{ac}'), ('\u{ae}', '\u{b1}'), ('\u{b4}', '\u{b4}'), @@ -1663,7 +1654,7 @@ pub mod general_category { '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}') ]; - pub static Sc_table: &'static [(char, char)] = &[ + pub const Sc_table: &'static [(char, char)] = &[ ('\u{24}', '\u{24}'), ('\u{a2}', '\u{a5}'), ('\u{58f}', '\u{58f}'), ('\u{60b}', '\u{60b}'), ('\u{9f2}', '\u{9f3}'), ('\u{9fb}', '\u{9fb}'), ('\u{af1}', '\u{af1}'), ('\u{bf9}', '\u{bf9}'), ('\u{e3f}', '\u{e3f}'), ('\u{17db}', '\u{17db}'), ('\u{20a0}', '\u{20bd}'), @@ -1671,7 +1662,7 @@ pub mod general_category { '\u{ff04}'), ('\u{ffe0}', '\u{ffe1}'), ('\u{ffe5}', '\u{ffe6}') ]; - pub static Sk_table: &'static [(char, char)] = &[ + pub const Sk_table: &'static [(char, char)] = &[ ('\u{5e}', '\u{5e}'), ('\u{60}', '\u{60}'), ('\u{a8}', '\u{a8}'), ('\u{af}', '\u{af}'), ('\u{b4}', '\u{b4}'), ('\u{b8}', '\u{b8}'), ('\u{2c2}', '\u{2c5}'), ('\u{2d2}', '\u{2df}'), ('\u{2e5}', '\u{2eb}'), ('\u{2ed}', '\u{2ed}'), ('\u{2ef}', '\u{2ff}'), ('\u{375}', @@ -1682,7 +1673,7 @@ pub mod general_category { '\u{ff3e}'), ('\u{ff40}', '\u{ff40}'), ('\u{ffe3}', '\u{ffe3}') ]; - pub static Sm_table: &'static [(char, char)] = &[ + pub const Sm_table: &'static [(char, char)] = &[ ('\u{2b}', '\u{2b}'), ('\u{3c}', '\u{3e}'), ('\u{7c}', '\u{7c}'), ('\u{7e}', '\u{7e}'), ('\u{ac}', '\u{ac}'), ('\u{b1}', '\u{b1}'), ('\u{d7}', '\u{d7}'), ('\u{f7}', '\u{f7}'), ('\u{3f6}', '\u{3f6}'), ('\u{606}', '\u{608}'), ('\u{2044}', '\u{2044}'), ('\u{2052}', @@ -1704,7 +1695,7 @@ pub mod general_category { '\u{1d7c3}'), ('\u{1eef0}', '\u{1eef1}') ]; - pub static So_table: &'static [(char, char)] = &[ + pub const So_table: &'static [(char, char)] = &[ ('\u{a6}', '\u{a6}'), ('\u{a9}', '\u{a9}'), ('\u{ae}', '\u{ae}'), ('\u{b0}', '\u{b0}'), ('\u{482}', '\u{482}'), ('\u{58d}', '\u{58e}'), ('\u{60e}', '\u{60f}'), ('\u{6de}', '\u{6de}'), ('\u{6e9}', '\u{6e9}'), ('\u{6fd}', '\u{6fe}'), ('\u{7f6}', '\u{7f6}'), @@ -1757,21 +1748,21 @@ pub mod general_category { '\u{1f887}'), ('\u{1f890}', '\u{1f8ad}') ]; - pub static Z_table: &'static [(char, char)] = &[ + pub const Z_table: &'static [(char, char)] = &[ ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'), ('\u{2028}', '\u{2029}'), ('\u{202f}', '\u{202f}'), ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}') ]; - pub static Zl_table: &'static [(char, char)] = &[ + pub const Zl_table: &'static [(char, char)] = &[ ('\u{2028}', '\u{2028}') ]; - pub static Zp_table: &'static [(char, char)] = &[ + pub const Zp_table: &'static [(char, char)] = &[ ('\u{2029}', '\u{2029}') ]; - pub static Zs_table: &'static [(char, char)] = &[ + pub const Zs_table: &'static [(char, char)] = &[ ('\u{20}', '\u{20}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'), ('\u{202f}', '\u{202f}'), ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}') ]; @@ -1779,7 +1770,7 @@ pub mod general_category { } pub mod derived_property { - pub static Alphabetic_table: &'static [(char, char)] = &[ + pub const Alphabetic_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'), ('\u{1bb}', '\u{1bb}'), ('\u{1bc}', '\u{1bf}'), ('\u{1c0}', '\u{1c3}'), ('\u{1c4}', @@ -2057,7 +2048,7 @@ pub mod derived_property { super::bsearch_range_table(c, Alphabetic_table) } - pub static Default_Ignorable_Code_Point_table: &'static [(char, char)] = &[ + pub const Default_Ignorable_Code_Point_table: &'static [(char, char)] = &[ ('\u{ad}', '\u{ad}'), ('\u{34f}', '\u{34f}'), ('\u{61c}', '\u{61c}'), ('\u{115f}', '\u{1160}'), ('\u{17b4}', '\u{17b5}'), ('\u{180b}', '\u{180d}'), ('\u{180e}', '\u{180e}'), ('\u{200b}', '\u{200f}'), ('\u{202a}', '\u{202e}'), ('\u{2060}', '\u{2064}'), ('\u{2065}', @@ -2068,7 +2059,7 @@ pub mod derived_property { '\u{e00ff}'), ('\u{e0100}', '\u{e01ef}'), ('\u{e01f0}', '\u{e0fff}') ]; - pub static Lowercase_table: &'static [(char, char)] = &[ + pub const Lowercase_table: &'static [(char, char)] = &[ ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{df}', '\u{f6}'), ('\u{f8}', '\u{ff}'), ('\u{101}', '\u{101}'), ('\u{103}', '\u{103}'), ('\u{105}', '\u{105}'), ('\u{107}', '\u{107}'), ('\u{109}', '\u{109}'), ('\u{10b}', @@ -2261,7 +2252,7 @@ pub mod derived_property { super::bsearch_range_table(c, Lowercase_table) } - pub static Uppercase_table: &'static [(char, char)] = &[ + pub const Uppercase_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{de}'), ('\u{100}', '\u{100}'), ('\u{102}', '\u{102}'), ('\u{104}', '\u{104}'), ('\u{106}', '\u{106}'), ('\u{108}', '\u{108}'), ('\u{10a}', '\u{10a}'), ('\u{10c}', '\u{10c}'), ('\u{10e}', '\u{10e}'), @@ -2449,7 +2440,7 @@ pub mod derived_property { super::bsearch_range_table(c, Uppercase_table) } - pub static XID_Continue_table: &'static [(char, char)] = &[ + pub const XID_Continue_table: &'static [(char, char)] = &[ ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{b7}', '\u{b7}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'), ('\u{1bb}', '\u{1bb}'), @@ -2775,7 +2766,7 @@ pub mod derived_property { super::bsearch_range_table(c, XID_Continue_table) } - pub static XID_Start_table: &'static [(char, char)] = &[ + pub const XID_Start_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'), ('\u{1bb}', '\u{1bb}'), ('\u{1bc}', '\u{1bf}'), ('\u{1c0}', '\u{1c3}'), ('\u{1c4}', @@ -2967,7 +2958,7 @@ pub mod derived_property { } pub mod script { - pub static Arabic_table: &'static [(char, char)] = &[ + pub const Arabic_table: &'static [(char, char)] = &[ ('\u{600}', '\u{604}'), ('\u{606}', '\u{608}'), ('\u{609}', '\u{60a}'), ('\u{60b}', '\u{60b}'), ('\u{60d}', '\u{60d}'), ('\u{60e}', '\u{60f}'), ('\u{610}', '\u{61a}'), ('\u{61e}', '\u{61e}'), ('\u{620}', '\u{63f}'), ('\u{641}', '\u{64a}'), ('\u{656}', @@ -2994,17 +2985,17 @@ pub mod script { ('\u{1eef0}', '\u{1eef1}') ]; - pub static Armenian_table: &'static [(char, char)] = &[ + pub const Armenian_table: &'static [(char, char)] = &[ ('\u{531}', '\u{556}'), ('\u{559}', '\u{559}'), ('\u{55a}', '\u{55f}'), ('\u{561}', '\u{587}'), ('\u{58a}', '\u{58a}'), ('\u{58d}', '\u{58e}'), ('\u{58f}', '\u{58f}'), ('\u{fb13}', '\u{fb17}') ]; - pub static Avestan_table: &'static [(char, char)] = &[ + pub const Avestan_table: &'static [(char, char)] = &[ ('\u{10b00}', '\u{10b35}'), ('\u{10b39}', '\u{10b3f}') ]; - pub static Balinese_table: &'static [(char, char)] = &[ + pub const Balinese_table: &'static [(char, char)] = &[ ('\u{1b00}', '\u{1b03}'), ('\u{1b04}', '\u{1b04}'), ('\u{1b05}', '\u{1b33}'), ('\u{1b34}', '\u{1b34}'), ('\u{1b35}', '\u{1b35}'), ('\u{1b36}', '\u{1b3a}'), ('\u{1b3b}', '\u{1b3b}'), ('\u{1b3c}', '\u{1b3c}'), ('\u{1b3d}', '\u{1b41}'), ('\u{1b42}', '\u{1b42}'), ('\u{1b43}', @@ -3012,22 +3003,22 @@ pub mod script { ('\u{1b61}', '\u{1b6a}'), ('\u{1b6b}', '\u{1b73}'), ('\u{1b74}', '\u{1b7c}') ]; - pub static Bamum_table: &'static [(char, char)] = &[ + pub const Bamum_table: &'static [(char, char)] = &[ ('\u{a6a0}', '\u{a6e5}'), ('\u{a6e6}', '\u{a6ef}'), ('\u{a6f0}', '\u{a6f1}'), ('\u{a6f2}', '\u{a6f7}'), ('\u{16800}', '\u{16a38}') ]; - pub static Bassa_Vah_table: &'static [(char, char)] = &[ + pub const Bassa_Vah_table: &'static [(char, char)] = &[ ('\u{16ad0}', '\u{16aed}'), ('\u{16af0}', '\u{16af4}'), ('\u{16af5}', '\u{16af5}') ]; - pub static Batak_table: &'static [(char, char)] = &[ + pub const Batak_table: &'static [(char, char)] = &[ ('\u{1bc0}', '\u{1be5}'), ('\u{1be6}', '\u{1be6}'), ('\u{1be7}', '\u{1be7}'), ('\u{1be8}', '\u{1be9}'), ('\u{1bea}', '\u{1bec}'), ('\u{1bed}', '\u{1bed}'), ('\u{1bee}', '\u{1bee}'), ('\u{1bef}', '\u{1bf1}'), ('\u{1bf2}', '\u{1bf3}'), ('\u{1bfc}', '\u{1bff}') ]; - pub static Bengali_table: &'static [(char, char)] = &[ + pub const Bengali_table: &'static [(char, char)] = &[ ('\u{980}', '\u{980}'), ('\u{981}', '\u{981}'), ('\u{982}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bc}', '\u{9bc}'), ('\u{9bd}', @@ -3038,60 +3029,60 @@ pub mod script { '\u{9f9}'), ('\u{9fa}', '\u{9fa}'), ('\u{9fb}', '\u{9fb}') ]; - pub static Bopomofo_table: &'static [(char, char)] = &[ + pub const Bopomofo_table: &'static [(char, char)] = &[ ('\u{2ea}', '\u{2eb}'), ('\u{3105}', '\u{312d}'), ('\u{31a0}', '\u{31ba}') ]; - pub static Brahmi_table: &'static [(char, char)] = &[ + pub const Brahmi_table: &'static [(char, char)] = &[ ('\u{11000}', '\u{11000}'), ('\u{11001}', '\u{11001}'), ('\u{11002}', '\u{11002}'), ('\u{11003}', '\u{11037}'), ('\u{11038}', '\u{11046}'), ('\u{11047}', '\u{1104d}'), ('\u{11052}', '\u{11065}'), ('\u{11066}', '\u{1106f}'), ('\u{1107f}', '\u{1107f}') ]; - pub static Braille_table: &'static [(char, char)] = &[ + pub const Braille_table: &'static [(char, char)] = &[ ('\u{2800}', '\u{28ff}') ]; - pub static Buginese_table: &'static [(char, char)] = &[ + pub const Buginese_table: &'static [(char, char)] = &[ ('\u{1a00}', '\u{1a16}'), ('\u{1a17}', '\u{1a18}'), ('\u{1a19}', '\u{1a1a}'), ('\u{1a1b}', '\u{1a1b}'), ('\u{1a1e}', '\u{1a1f}') ]; - pub static Buhid_table: &'static [(char, char)] = &[ + pub const Buhid_table: &'static [(char, char)] = &[ ('\u{1740}', '\u{1751}'), ('\u{1752}', '\u{1753}') ]; - pub static Canadian_Aboriginal_table: &'static [(char, char)] = &[ + pub const Canadian_Aboriginal_table: &'static [(char, char)] = &[ ('\u{1400}', '\u{1400}'), ('\u{1401}', '\u{166c}'), ('\u{166d}', '\u{166e}'), ('\u{166f}', '\u{167f}'), ('\u{18b0}', '\u{18f5}') ]; - pub static Carian_table: &'static [(char, char)] = &[ + pub const Carian_table: &'static [(char, char)] = &[ ('\u{102a0}', '\u{102d0}') ]; - pub static Caucasian_Albanian_table: &'static [(char, char)] = &[ + pub const Caucasian_Albanian_table: &'static [(char, char)] = &[ ('\u{10530}', '\u{10563}'), ('\u{1056f}', '\u{1056f}') ]; - pub static Chakma_table: &'static [(char, char)] = &[ + pub const Chakma_table: &'static [(char, char)] = &[ ('\u{11100}', '\u{11102}'), ('\u{11103}', '\u{11126}'), ('\u{11127}', '\u{1112b}'), ('\u{1112c}', '\u{1112c}'), ('\u{1112d}', '\u{11134}'), ('\u{11136}', '\u{1113f}'), ('\u{11140}', '\u{11143}') ]; - pub static Cham_table: &'static [(char, char)] = &[ + pub const Cham_table: &'static [(char, char)] = &[ ('\u{aa00}', '\u{aa28}'), ('\u{aa29}', '\u{aa2e}'), ('\u{aa2f}', '\u{aa30}'), ('\u{aa31}', '\u{aa32}'), ('\u{aa33}', '\u{aa34}'), ('\u{aa35}', '\u{aa36}'), ('\u{aa40}', '\u{aa42}'), ('\u{aa43}', '\u{aa43}'), ('\u{aa44}', '\u{aa4b}'), ('\u{aa4c}', '\u{aa4c}'), ('\u{aa4d}', '\u{aa4d}'), ('\u{aa50}', '\u{aa59}'), ('\u{aa5c}', '\u{aa5f}') ]; - pub static Cherokee_table: &'static [(char, char)] = &[ + pub const Cherokee_table: &'static [(char, char)] = &[ ('\u{13a0}', '\u{13f4}') ]; - pub static Common_table: &'static [(char, char)] = &[ + pub const Common_table: &'static [(char, char)] = &[ ('\u{0}', '\u{1f}'), ('\u{20}', '\u{20}'), ('\u{21}', '\u{23}'), ('\u{24}', '\u{24}'), ('\u{25}', '\u{27}'), ('\u{28}', '\u{28}'), ('\u{29}', '\u{29}'), ('\u{2a}', '\u{2a}'), ('\u{2b}', '\u{2b}'), ('\u{2c}', '\u{2c}'), ('\u{2d}', '\u{2d}'), ('\u{2e}', '\u{2f}'), @@ -3261,22 +3252,22 @@ pub mod script { ('\u{1f890}', '\u{1f8ad}'), ('\u{e0001}', '\u{e0001}'), ('\u{e0020}', '\u{e007f}') ]; - pub static Coptic_table: &'static [(char, char)] = &[ + pub const Coptic_table: &'static [(char, char)] = &[ ('\u{3e2}', '\u{3ef}'), ('\u{2c80}', '\u{2ce4}'), ('\u{2ce5}', '\u{2cea}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cef}', '\u{2cf1}'), ('\u{2cf2}', '\u{2cf3}'), ('\u{2cf9}', '\u{2cfc}'), ('\u{2cfd}', '\u{2cfd}'), ('\u{2cfe}', '\u{2cff}') ]; - pub static Cuneiform_table: &'static [(char, char)] = &[ + pub const Cuneiform_table: &'static [(char, char)] = &[ ('\u{12000}', '\u{12398}'), ('\u{12400}', '\u{1246e}'), ('\u{12470}', '\u{12474}') ]; - pub static Cypriot_table: &'static [(char, char)] = &[ + pub const Cypriot_table: &'static [(char, char)] = &[ ('\u{10800}', '\u{10805}'), ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{1083f}') ]; - pub static Cyrillic_table: &'static [(char, char)] = &[ + pub const Cyrillic_table: &'static [(char, char)] = &[ ('\u{400}', '\u{481}'), ('\u{482}', '\u{482}'), ('\u{483}', '\u{484}'), ('\u{487}', '\u{487}'), ('\u{488}', '\u{489}'), ('\u{48a}', '\u{52f}'), ('\u{1d2b}', '\u{1d2b}'), ('\u{1d78}', '\u{1d78}'), ('\u{2de0}', '\u{2dff}'), ('\u{a640}', '\u{a66d}'), ('\u{a66e}', @@ -3285,11 +3276,11 @@ pub mod script { '\u{a69b}'), ('\u{a69c}', '\u{a69d}'), ('\u{a69f}', '\u{a69f}') ]; - pub static Deseret_table: &'static [(char, char)] = &[ + pub const Deseret_table: &'static [(char, char)] = &[ ('\u{10400}', '\u{1044f}') ]; - pub static Devanagari_table: &'static [(char, char)] = &[ + pub const Devanagari_table: &'static [(char, char)] = &[ ('\u{900}', '\u{902}'), ('\u{903}', '\u{903}'), ('\u{904}', '\u{939}'), ('\u{93a}', '\u{93a}'), ('\u{93b}', '\u{93b}'), ('\u{93c}', '\u{93c}'), ('\u{93d}', '\u{93d}'), ('\u{93e}', '\u{940}'), ('\u{941}', '\u{948}'), ('\u{949}', '\u{94c}'), ('\u{94d}', @@ -3299,21 +3290,21 @@ pub mod script { ('\u{a8f2}', '\u{a8f7}'), ('\u{a8f8}', '\u{a8fa}'), ('\u{a8fb}', '\u{a8fb}') ]; - pub static Duployan_table: &'static [(char, char)] = &[ + pub const Duployan_table: &'static [(char, char)] = &[ ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9c}', '\u{1bc9c}'), ('\u{1bc9d}', '\u{1bc9e}'), ('\u{1bc9f}', '\u{1bc9f}') ]; - pub static Egyptian_Hieroglyphs_table: &'static [(char, char)] = &[ + pub const Egyptian_Hieroglyphs_table: &'static [(char, char)] = &[ ('\u{13000}', '\u{1342e}') ]; - pub static Elbasan_table: &'static [(char, char)] = &[ + pub const Elbasan_table: &'static [(char, char)] = &[ ('\u{10500}', '\u{10527}') ]; - pub static Ethiopic_table: &'static [(char, char)] = &[ + pub const Ethiopic_table: &'static [(char, char)] = &[ ('\u{1200}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', @@ -3326,22 +3317,22 @@ pub mod script { '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}') ]; - pub static Georgian_table: &'static [(char, char)] = &[ + pub const Georgian_table: &'static [(char, char)] = &[ ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}', '\u{10fc}'), ('\u{10fd}', '\u{10ff}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}') ]; - pub static Glagolitic_table: &'static [(char, char)] = &[ + pub const Glagolitic_table: &'static [(char, char)] = &[ ('\u{2c00}', '\u{2c2e}'), ('\u{2c30}', '\u{2c5e}') ]; - pub static Gothic_table: &'static [(char, char)] = &[ + pub const Gothic_table: &'static [(char, char)] = &[ ('\u{10330}', '\u{10340}'), ('\u{10341}', '\u{10341}'), ('\u{10342}', '\u{10349}'), ('\u{1034a}', '\u{1034a}') ]; - pub static Grantha_table: &'static [(char, char)] = &[ + pub const Grantha_table: &'static [(char, char)] = &[ ('\u{11301}', '\u{11301}'), ('\u{11302}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}', '\u{11339}'), ('\u{1133c}', '\u{1133c}'), @@ -3351,7 +3342,7 @@ pub mod script { ('\u{11366}', '\u{1136c}'), ('\u{11370}', '\u{11374}') ]; - pub static Greek_table: &'static [(char, char)] = &[ + pub const Greek_table: &'static [(char, char)] = &[ ('\u{370}', '\u{373}'), ('\u{375}', '\u{375}'), ('\u{376}', '\u{377}'), ('\u{37a}', '\u{37a}'), ('\u{37b}', '\u{37d}'), ('\u{37f}', '\u{37f}'), ('\u{384}', '\u{384}'), ('\u{386}', '\u{386}'), ('\u{388}', '\u{38a}'), ('\u{38c}', '\u{38c}'), ('\u{38e}', @@ -3371,7 +3362,7 @@ pub mod script { '\u{1d245}') ]; - pub static Gujarati_table: &'static [(char, char)] = &[ + pub const Gujarati_table: &'static [(char, char)] = &[ ('\u{a81}', '\u{a82}'), ('\u{a83}', '\u{a83}'), ('\u{a85}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abc}', '\u{abc}'), ('\u{abd}', '\u{abd}'), ('\u{abe}', @@ -3381,7 +3372,7 @@ pub mod script { ('\u{af1}', '\u{af1}') ]; - pub static Gurmukhi_table: &'static [(char, char)] = &[ + pub const Gurmukhi_table: &'static [(char, char)] = &[ ('\u{a01}', '\u{a02}'), ('\u{a03}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a33}'), ('\u{a35}', '\u{a36}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'), ('\u{a3e}', @@ -3390,7 +3381,7 @@ pub mod script { '\u{a6f}'), ('\u{a70}', '\u{a71}'), ('\u{a72}', '\u{a74}'), ('\u{a75}', '\u{a75}') ]; - pub static Han_table: &'static [(char, char)] = &[ + pub const Han_table: &'static [(char, char)] = &[ ('\u{2e80}', '\u{2e99}'), ('\u{2e9b}', '\u{2ef3}'), ('\u{2f00}', '\u{2fd5}'), ('\u{3005}', '\u{3005}'), ('\u{3007}', '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3038}', '\u{303a}'), ('\u{303b}', '\u{303b}'), ('\u{3400}', '\u{4db5}'), ('\u{4e00}', '\u{9fcc}'), ('\u{f900}', @@ -3398,18 +3389,18 @@ pub mod script { '\u{2b734}'), ('\u{2b740}', '\u{2b81d}'), ('\u{2f800}', '\u{2fa1d}') ]; - pub static Hangul_table: &'static [(char, char)] = &[ + pub const Hangul_table: &'static [(char, char)] = &[ ('\u{1100}', '\u{11ff}'), ('\u{302e}', '\u{302f}'), ('\u{3131}', '\u{318e}'), ('\u{3200}', '\u{321e}'), ('\u{3260}', '\u{327e}'), ('\u{a960}', '\u{a97c}'), ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{ffa0}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}') ]; - pub static Hanunoo_table: &'static [(char, char)] = &[ + pub const Hanunoo_table: &'static [(char, char)] = &[ ('\u{1720}', '\u{1731}'), ('\u{1732}', '\u{1734}') ]; - pub static Hebrew_table: &'static [(char, char)] = &[ + pub const Hebrew_table: &'static [(char, char)] = &[ ('\u{591}', '\u{5bd}'), ('\u{5be}', '\u{5be}'), ('\u{5bf}', '\u{5bf}'), ('\u{5c0}', '\u{5c0}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c3}', '\u{5c3}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c6}', '\u{5c6}'), ('\u{5c7}', '\u{5c7}'), ('\u{5d0}', '\u{5ea}'), ('\u{5f0}', @@ -3419,16 +3410,16 @@ pub mod script { ('\u{fb46}', '\u{fb4f}') ]; - pub static Hiragana_table: &'static [(char, char)] = &[ + pub const Hiragana_table: &'static [(char, char)] = &[ ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309e}'), ('\u{309f}', '\u{309f}'), ('\u{1b001}', '\u{1b001}'), ('\u{1f200}', '\u{1f200}') ]; - pub static Imperial_Aramaic_table: &'static [(char, char)] = &[ + pub const Imperial_Aramaic_table: &'static [(char, char)] = &[ ('\u{10840}', '\u{10855}'), ('\u{10857}', '\u{10857}'), ('\u{10858}', '\u{1085f}') ]; - pub static Inherited_table: &'static [(char, char)] = &[ + pub const Inherited_table: &'static [(char, char)] = &[ ('\u{300}', '\u{36f}'), ('\u{485}', '\u{486}'), ('\u{64b}', '\u{655}'), ('\u{670}', '\u{670}'), ('\u{951}', '\u{952}'), ('\u{1ab0}', '\u{1abd}'), ('\u{1abe}', '\u{1abe}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'), ('\u{1ce2}', '\u{1ce8}'), ('\u{1ced}', @@ -3441,29 +3432,29 @@ pub mod script { '\u{1d1ad}'), ('\u{e0100}', '\u{e01ef}') ]; - pub static Inscriptional_Pahlavi_table: &'static [(char, char)] = &[ + pub const Inscriptional_Pahlavi_table: &'static [(char, char)] = &[ ('\u{10b60}', '\u{10b72}'), ('\u{10b78}', '\u{10b7f}') ]; - pub static Inscriptional_Parthian_table: &'static [(char, char)] = &[ + pub const Inscriptional_Parthian_table: &'static [(char, char)] = &[ ('\u{10b40}', '\u{10b55}'), ('\u{10b58}', '\u{10b5f}') ]; - pub static Javanese_table: &'static [(char, char)] = &[ + pub const Javanese_table: &'static [(char, char)] = &[ ('\u{a980}', '\u{a982}'), ('\u{a983}', '\u{a983}'), ('\u{a984}', '\u{a9b2}'), ('\u{a9b3}', '\u{a9b3}'), ('\u{a9b4}', '\u{a9b5}'), ('\u{a9b6}', '\u{a9b9}'), ('\u{a9ba}', '\u{a9bb}'), ('\u{a9bc}', '\u{a9bc}'), ('\u{a9bd}', '\u{a9c0}'), ('\u{a9c1}', '\u{a9cd}'), ('\u{a9d0}', '\u{a9d9}'), ('\u{a9de}', '\u{a9df}') ]; - pub static Kaithi_table: &'static [(char, char)] = &[ + pub const Kaithi_table: &'static [(char, char)] = &[ ('\u{11080}', '\u{11081}'), ('\u{11082}', '\u{11082}'), ('\u{11083}', '\u{110af}'), ('\u{110b0}', '\u{110b2}'), ('\u{110b3}', '\u{110b6}'), ('\u{110b7}', '\u{110b8}'), ('\u{110b9}', '\u{110ba}'), ('\u{110bb}', '\u{110bc}'), ('\u{110bd}', '\u{110bd}'), ('\u{110be}', '\u{110c1}') ]; - pub static Kannada_table: &'static [(char, char)] = &[ + pub const Kannada_table: &'static [(char, char)] = &[ ('\u{c81}', '\u{c81}'), ('\u{c82}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbc}', '\u{cbc}'), ('\u{cbd}', '\u{cbd}'), ('\u{cbe}', '\u{cbe}'), ('\u{cbf}', @@ -3473,25 +3464,25 @@ pub mod script { ('\u{cf1}', '\u{cf2}') ]; - pub static Katakana_table: &'static [(char, char)] = &[ + pub const Katakana_table: &'static [(char, char)] = &[ ('\u{30a1}', '\u{30fa}'), ('\u{30fd}', '\u{30fe}'), ('\u{30ff}', '\u{30ff}'), ('\u{31f0}', '\u{31ff}'), ('\u{32d0}', '\u{32fe}'), ('\u{3300}', '\u{3357}'), ('\u{ff66}', '\u{ff6f}'), ('\u{ff71}', '\u{ff9d}'), ('\u{1b000}', '\u{1b000}') ]; - pub static Kayah_Li_table: &'static [(char, char)] = &[ + pub const Kayah_Li_table: &'static [(char, char)] = &[ ('\u{a900}', '\u{a909}'), ('\u{a90a}', '\u{a925}'), ('\u{a926}', '\u{a92d}'), ('\u{a92f}', '\u{a92f}') ]; - pub static Kharoshthi_table: &'static [(char, char)] = &[ + pub const Kharoshthi_table: &'static [(char, char)] = &[ ('\u{10a00}', '\u{10a00}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}', '\u{10a0f}'), ('\u{10a10}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a33}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10a3f}', '\u{10a3f}'), ('\u{10a40}', '\u{10a47}'), ('\u{10a50}', '\u{10a58}') ]; - pub static Khmer_table: &'static [(char, char)] = &[ + pub const Khmer_table: &'static [(char, char)] = &[ ('\u{1780}', '\u{17b3}'), ('\u{17b4}', '\u{17b5}'), ('\u{17b6}', '\u{17b6}'), ('\u{17b7}', '\u{17bd}'), ('\u{17be}', '\u{17c5}'), ('\u{17c6}', '\u{17c6}'), ('\u{17c7}', '\u{17c8}'), ('\u{17c9}', '\u{17d3}'), ('\u{17d4}', '\u{17d6}'), ('\u{17d7}', '\u{17d7}'), ('\u{17d8}', @@ -3499,18 +3490,18 @@ pub mod script { ('\u{17e0}', '\u{17e9}'), ('\u{17f0}', '\u{17f9}'), ('\u{19e0}', '\u{19ff}') ]; - pub static Khojki_table: &'static [(char, char)] = &[ + pub const Khojki_table: &'static [(char, char)] = &[ ('\u{11200}', '\u{11211}'), ('\u{11213}', '\u{1122b}'), ('\u{1122c}', '\u{1122e}'), ('\u{1122f}', '\u{11231}'), ('\u{11232}', '\u{11233}'), ('\u{11234}', '\u{11234}'), ('\u{11235}', '\u{11235}'), ('\u{11236}', '\u{11237}'), ('\u{11238}', '\u{1123d}') ]; - pub static Khudawadi_table: &'static [(char, char)] = &[ + pub const Khudawadi_table: &'static [(char, char)] = &[ ('\u{112b0}', '\u{112de}'), ('\u{112df}', '\u{112df}'), ('\u{112e0}', '\u{112e2}'), ('\u{112e3}', '\u{112ea}'), ('\u{112f0}', '\u{112f9}') ]; - pub static Lao_table: &'static [(char, char)] = &[ + pub const Lao_table: &'static [(char, char)] = &[ ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e87}', '\u{e88}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8d}', '\u{e8d}'), ('\u{e94}', '\u{e97}'), ('\u{e99}', '\u{e9f}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{eaa}', @@ -3520,7 +3511,7 @@ pub mod script { ('\u{edc}', '\u{edf}') ]; - pub static Latin_table: &'static [(char, char)] = &[ + pub const Latin_table: &'static [(char, char)] = &[ ('\u{41}', '\u{5a}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{1ba}'), ('\u{1bb}', '\u{1bb}'), ('\u{1bc}', '\u{1bf}'), ('\u{1c0}', '\u{1c3}'), ('\u{1c4}', '\u{293}'), ('\u{294}', @@ -3537,47 +3528,47 @@ pub mod script { '\u{ab64}'), ('\u{fb00}', '\u{fb06}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}') ]; - pub static Lepcha_table: &'static [(char, char)] = &[ + pub const Lepcha_table: &'static [(char, char)] = &[ ('\u{1c00}', '\u{1c23}'), ('\u{1c24}', '\u{1c2b}'), ('\u{1c2c}', '\u{1c33}'), ('\u{1c34}', '\u{1c35}'), ('\u{1c36}', '\u{1c37}'), ('\u{1c3b}', '\u{1c3f}'), ('\u{1c40}', '\u{1c49}'), ('\u{1c4d}', '\u{1c4f}') ]; - pub static Limbu_table: &'static [(char, char)] = &[ + pub const Limbu_table: &'static [(char, char)] = &[ ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{1922}'), ('\u{1923}', '\u{1926}'), ('\u{1927}', '\u{1928}'), ('\u{1929}', '\u{192b}'), ('\u{1930}', '\u{1931}'), ('\u{1932}', '\u{1932}'), ('\u{1933}', '\u{1938}'), ('\u{1939}', '\u{193b}'), ('\u{1940}', '\u{1940}'), ('\u{1944}', '\u{1945}'), ('\u{1946}', '\u{194f}') ]; - pub static Linear_A_table: &'static [(char, char)] = &[ + pub const Linear_A_table: &'static [(char, char)] = &[ ('\u{10600}', '\u{10736}'), ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}') ]; - pub static Linear_B_table: &'static [(char, char)] = &[ + pub const Linear_B_table: &'static [(char, char)] = &[ ('\u{10000}', '\u{1000b}'), ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}') ]; - pub static Lisu_table: &'static [(char, char)] = &[ + pub const Lisu_table: &'static [(char, char)] = &[ ('\u{a4d0}', '\u{a4f7}'), ('\u{a4f8}', '\u{a4fd}'), ('\u{a4fe}', '\u{a4ff}') ]; - pub static Lycian_table: &'static [(char, char)] = &[ + pub const Lycian_table: &'static [(char, char)] = &[ ('\u{10280}', '\u{1029c}') ]; - pub static Lydian_table: &'static [(char, char)] = &[ + pub const Lydian_table: &'static [(char, char)] = &[ ('\u{10920}', '\u{10939}'), ('\u{1093f}', '\u{1093f}') ]; - pub static Mahajani_table: &'static [(char, char)] = &[ + pub const Mahajani_table: &'static [(char, char)] = &[ ('\u{11150}', '\u{11172}'), ('\u{11173}', '\u{11173}'), ('\u{11174}', '\u{11175}'), ('\u{11176}', '\u{11176}') ]; - pub static Malayalam_table: &'static [(char, char)] = &[ + pub const Malayalam_table: &'static [(char, char)] = &[ ('\u{d01}', '\u{d01}'), ('\u{d02}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'), ('\u{d3e}', '\u{d40}'), ('\u{d41}', '\u{d44}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4c}'), ('\u{d4d}', @@ -3586,16 +3577,16 @@ pub mod script { '\u{d79}'), ('\u{d7a}', '\u{d7f}') ]; - pub static Mandaic_table: &'static [(char, char)] = &[ + pub const Mandaic_table: &'static [(char, char)] = &[ ('\u{840}', '\u{858}'), ('\u{859}', '\u{85b}'), ('\u{85e}', '\u{85e}') ]; - pub static Manichaean_table: &'static [(char, char)] = &[ + pub const Manichaean_table: &'static [(char, char)] = &[ ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac8}', '\u{10ac8}'), ('\u{10ac9}', '\u{10ae4}'), ('\u{10ae5}', '\u{10ae6}'), ('\u{10aeb}', '\u{10aef}'), ('\u{10af0}', '\u{10af6}') ]; - pub static Meetei_Mayek_table: &'static [(char, char)] = &[ + pub const Meetei_Mayek_table: &'static [(char, char)] = &[ ('\u{aae0}', '\u{aaea}'), ('\u{aaeb}', '\u{aaeb}'), ('\u{aaec}', '\u{aaed}'), ('\u{aaee}', '\u{aaef}'), ('\u{aaf0}', '\u{aaf1}'), ('\u{aaf2}', '\u{aaf2}'), ('\u{aaf3}', '\u{aaf4}'), ('\u{aaf5}', '\u{aaf5}'), ('\u{aaf6}', '\u{aaf6}'), ('\u{abc0}', '\u{abe2}'), ('\u{abe3}', @@ -3604,42 +3595,42 @@ pub mod script { '\u{abed}'), ('\u{abf0}', '\u{abf9}') ]; - pub static Mende_Kikakui_table: &'static [(char, char)] = &[ + pub const Mende_Kikakui_table: &'static [(char, char)] = &[ ('\u{1e800}', '\u{1e8c4}'), ('\u{1e8c7}', '\u{1e8cf}'), ('\u{1e8d0}', '\u{1e8d6}') ]; - pub static Meroitic_Cursive_table: &'static [(char, char)] = &[ + pub const Meroitic_Cursive_table: &'static [(char, char)] = &[ ('\u{109a0}', '\u{109b7}'), ('\u{109be}', '\u{109bf}') ]; - pub static Meroitic_Hieroglyphs_table: &'static [(char, char)] = &[ + pub const Meroitic_Hieroglyphs_table: &'static [(char, char)] = &[ ('\u{10980}', '\u{1099f}') ]; - pub static Miao_table: &'static [(char, char)] = &[ + pub const Miao_table: &'static [(char, char)] = &[ ('\u{16f00}', '\u{16f44}'), ('\u{16f50}', '\u{16f50}'), ('\u{16f51}', '\u{16f7e}'), ('\u{16f8f}', '\u{16f92}'), ('\u{16f93}', '\u{16f9f}') ]; - pub static Modi_table: &'static [(char, char)] = &[ + pub const Modi_table: &'static [(char, char)] = &[ ('\u{11600}', '\u{1162f}'), ('\u{11630}', '\u{11632}'), ('\u{11633}', '\u{1163a}'), ('\u{1163b}', '\u{1163c}'), ('\u{1163d}', '\u{1163d}'), ('\u{1163e}', '\u{1163e}'), ('\u{1163f}', '\u{11640}'), ('\u{11641}', '\u{11643}'), ('\u{11644}', '\u{11644}'), ('\u{11650}', '\u{11659}') ]; - pub static Mongolian_table: &'static [(char, char)] = &[ + pub const Mongolian_table: &'static [(char, char)] = &[ ('\u{1800}', '\u{1801}'), ('\u{1804}', '\u{1804}'), ('\u{1806}', '\u{1806}'), ('\u{1807}', '\u{180a}'), ('\u{180b}', '\u{180d}'), ('\u{180e}', '\u{180e}'), ('\u{1810}', '\u{1819}'), ('\u{1820}', '\u{1842}'), ('\u{1843}', '\u{1843}'), ('\u{1844}', '\u{1877}'), ('\u{1880}', '\u{18a8}'), ('\u{18a9}', '\u{18a9}'), ('\u{18aa}', '\u{18aa}') ]; - pub static Mro_table: &'static [(char, char)] = &[ + pub const Mro_table: &'static [(char, char)] = &[ ('\u{16a40}', '\u{16a5e}'), ('\u{16a60}', '\u{16a69}'), ('\u{16a6e}', '\u{16a6f}') ]; - pub static Myanmar_table: &'static [(char, char)] = &[ + pub const Myanmar_table: &'static [(char, char)] = &[ ('\u{1000}', '\u{102a}'), ('\u{102b}', '\u{102c}'), ('\u{102d}', '\u{1030}'), ('\u{1031}', '\u{1031}'), ('\u{1032}', '\u{1037}'), ('\u{1038}', '\u{1038}'), ('\u{1039}', '\u{103a}'), ('\u{103b}', '\u{103c}'), ('\u{103d}', '\u{103e}'), ('\u{103f}', '\u{103f}'), ('\u{1040}', @@ -3657,56 +3648,56 @@ pub mod script { ('\u{aa7e}', '\u{aa7f}') ]; - pub static Nabataean_table: &'static [(char, char)] = &[ + pub const Nabataean_table: &'static [(char, char)] = &[ ('\u{10880}', '\u{1089e}'), ('\u{108a7}', '\u{108af}') ]; - pub static New_Tai_Lue_table: &'static [(char, char)] = &[ + pub const New_Tai_Lue_table: &'static [(char, char)] = &[ ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c0}'), ('\u{19c1}', '\u{19c7}'), ('\u{19c8}', '\u{19c9}'), ('\u{19d0}', '\u{19d9}'), ('\u{19da}', '\u{19da}'), ('\u{19de}', '\u{19df}') ]; - pub static Nko_table: &'static [(char, char)] = &[ + pub const Nko_table: &'static [(char, char)] = &[ ('\u{7c0}', '\u{7c9}'), ('\u{7ca}', '\u{7ea}'), ('\u{7eb}', '\u{7f3}'), ('\u{7f4}', '\u{7f5}'), ('\u{7f6}', '\u{7f6}'), ('\u{7f7}', '\u{7f9}'), ('\u{7fa}', '\u{7fa}') ]; - pub static Ogham_table: &'static [(char, char)] = &[ + pub const Ogham_table: &'static [(char, char)] = &[ ('\u{1680}', '\u{1680}'), ('\u{1681}', '\u{169a}'), ('\u{169b}', '\u{169b}'), ('\u{169c}', '\u{169c}') ]; - pub static Ol_Chiki_table: &'static [(char, char)] = &[ + pub const Ol_Chiki_table: &'static [(char, char)] = &[ ('\u{1c50}', '\u{1c59}'), ('\u{1c5a}', '\u{1c77}'), ('\u{1c78}', '\u{1c7d}'), ('\u{1c7e}', '\u{1c7f}') ]; - pub static Old_Italic_table: &'static [(char, char)] = &[ + pub const Old_Italic_table: &'static [(char, char)] = &[ ('\u{10300}', '\u{1031f}'), ('\u{10320}', '\u{10323}') ]; - pub static Old_North_Arabian_table: &'static [(char, char)] = &[ + pub const Old_North_Arabian_table: &'static [(char, char)] = &[ ('\u{10a80}', '\u{10a9c}'), ('\u{10a9d}', '\u{10a9f}') ]; - pub static Old_Permic_table: &'static [(char, char)] = &[ + pub const Old_Permic_table: &'static [(char, char)] = &[ ('\u{10350}', '\u{10375}'), ('\u{10376}', '\u{1037a}') ]; - pub static Old_Persian_table: &'static [(char, char)] = &[ + pub const Old_Persian_table: &'static [(char, char)] = &[ ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d0}', '\u{103d0}'), ('\u{103d1}', '\u{103d5}') ]; - pub static Old_South_Arabian_table: &'static [(char, char)] = &[ + pub const Old_South_Arabian_table: &'static [(char, char)] = &[ ('\u{10a60}', '\u{10a7c}'), ('\u{10a7d}', '\u{10a7e}'), ('\u{10a7f}', '\u{10a7f}') ]; - pub static Old_Turkic_table: &'static [(char, char)] = &[ + pub const Old_Turkic_table: &'static [(char, char)] = &[ ('\u{10c00}', '\u{10c48}') ]; - pub static Oriya_table: &'static [(char, char)] = &[ + pub const Oriya_table: &'static [(char, char)] = &[ ('\u{b01}', '\u{b01}'), ('\u{b02}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}', '\u{b39}'), ('\u{b3c}', '\u{b3c}'), ('\u{b3d}', '\u{b3d}'), ('\u{b3e}', @@ -3717,75 +3708,75 @@ pub mod script { '\u{b71}'), ('\u{b72}', '\u{b77}') ]; - pub static Osmanya_table: &'static [(char, char)] = &[ + pub const Osmanya_table: &'static [(char, char)] = &[ ('\u{10480}', '\u{1049d}'), ('\u{104a0}', '\u{104a9}') ]; - pub static Pahawh_Hmong_table: &'static [(char, char)] = &[ + pub const Pahawh_Hmong_table: &'static [(char, char)] = &[ ('\u{16b00}', '\u{16b2f}'), ('\u{16b30}', '\u{16b36}'), ('\u{16b37}', '\u{16b3b}'), ('\u{16b3c}', '\u{16b3f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b44}', '\u{16b44}'), ('\u{16b45}', '\u{16b45}'), ('\u{16b50}', '\u{16b59}'), ('\u{16b5b}', '\u{16b61}'), ('\u{16b63}', '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}') ]; - pub static Palmyrene_table: &'static [(char, char)] = &[ + pub const Palmyrene_table: &'static [(char, char)] = &[ ('\u{10860}', '\u{10876}'), ('\u{10877}', '\u{10878}'), ('\u{10879}', '\u{1087f}') ]; - pub static Pau_Cin_Hau_table: &'static [(char, char)] = &[ + pub const Pau_Cin_Hau_table: &'static [(char, char)] = &[ ('\u{11ac0}', '\u{11af8}') ]; - pub static Phags_Pa_table: &'static [(char, char)] = &[ + pub const Phags_Pa_table: &'static [(char, char)] = &[ ('\u{a840}', '\u{a873}'), ('\u{a874}', '\u{a877}') ]; - pub static Phoenician_table: &'static [(char, char)] = &[ + pub const Phoenician_table: &'static [(char, char)] = &[ ('\u{10900}', '\u{10915}'), ('\u{10916}', '\u{1091b}'), ('\u{1091f}', '\u{1091f}') ]; - pub static Psalter_Pahlavi_table: &'static [(char, char)] = &[ + pub const Psalter_Pahlavi_table: &'static [(char, char)] = &[ ('\u{10b80}', '\u{10b91}'), ('\u{10b99}', '\u{10b9c}'), ('\u{10ba9}', '\u{10baf}') ]; - pub static Rejang_table: &'static [(char, char)] = &[ + pub const Rejang_table: &'static [(char, char)] = &[ ('\u{a930}', '\u{a946}'), ('\u{a947}', '\u{a951}'), ('\u{a952}', '\u{a953}'), ('\u{a95f}', '\u{a95f}') ]; - pub static Runic_table: &'static [(char, char)] = &[ + pub const Runic_table: &'static [(char, char)] = &[ ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f0}'), ('\u{16f1}', '\u{16f8}') ]; - pub static Samaritan_table: &'static [(char, char)] = &[ + pub const Samaritan_table: &'static [(char, char)] = &[ ('\u{800}', '\u{815}'), ('\u{816}', '\u{819}'), ('\u{81a}', '\u{81a}'), ('\u{81b}', '\u{823}'), ('\u{824}', '\u{824}'), ('\u{825}', '\u{827}'), ('\u{828}', '\u{828}'), ('\u{829}', '\u{82d}'), ('\u{830}', '\u{83e}') ]; - pub static Saurashtra_table: &'static [(char, char)] = &[ + pub const Saurashtra_table: &'static [(char, char)] = &[ ('\u{a880}', '\u{a881}'), ('\u{a882}', '\u{a8b3}'), ('\u{a8b4}', '\u{a8c3}'), ('\u{a8c4}', '\u{a8c4}'), ('\u{a8ce}', '\u{a8cf}'), ('\u{a8d0}', '\u{a8d9}') ]; - pub static Sharada_table: &'static [(char, char)] = &[ + pub const Sharada_table: &'static [(char, char)] = &[ ('\u{11180}', '\u{11181}'), ('\u{11182}', '\u{11182}'), ('\u{11183}', '\u{111b2}'), ('\u{111b3}', '\u{111b5}'), ('\u{111b6}', '\u{111be}'), ('\u{111bf}', '\u{111c0}'), ('\u{111c1}', '\u{111c4}'), ('\u{111c5}', '\u{111c8}'), ('\u{111cd}', '\u{111cd}'), ('\u{111d0}', '\u{111d9}'), ('\u{111da}', '\u{111da}') ]; - pub static Shavian_table: &'static [(char, char)] = &[ + pub const Shavian_table: &'static [(char, char)] = &[ ('\u{10450}', '\u{1047f}') ]; - pub static Siddham_table: &'static [(char, char)] = &[ + pub const Siddham_table: &'static [(char, char)] = &[ ('\u{11580}', '\u{115ae}'), ('\u{115af}', '\u{115b1}'), ('\u{115b2}', '\u{115b5}'), ('\u{115b8}', '\u{115bb}'), ('\u{115bc}', '\u{115bd}'), ('\u{115be}', '\u{115be}'), ('\u{115bf}', '\u{115c0}'), ('\u{115c1}', '\u{115c9}') ]; - pub static Sinhala_table: &'static [(char, char)] = &[ + pub const Sinhala_table: &'static [(char, char)] = &[ ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd1}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', @@ -3793,42 +3784,42 @@ pub mod script { ('\u{111e1}', '\u{111f4}') ]; - pub static Sora_Sompeng_table: &'static [(char, char)] = &[ + pub const Sora_Sompeng_table: &'static [(char, char)] = &[ ('\u{110d0}', '\u{110e8}'), ('\u{110f0}', '\u{110f9}') ]; - pub static Sundanese_table: &'static [(char, char)] = &[ + pub const Sundanese_table: &'static [(char, char)] = &[ ('\u{1b80}', '\u{1b81}'), ('\u{1b82}', '\u{1b82}'), ('\u{1b83}', '\u{1ba0}'), ('\u{1ba1}', '\u{1ba1}'), ('\u{1ba2}', '\u{1ba5}'), ('\u{1ba6}', '\u{1ba7}'), ('\u{1ba8}', '\u{1ba9}'), ('\u{1baa}', '\u{1baa}'), ('\u{1bab}', '\u{1bad}'), ('\u{1bae}', '\u{1baf}'), ('\u{1bb0}', '\u{1bb9}'), ('\u{1bba}', '\u{1bbf}'), ('\u{1cc0}', '\u{1cc7}') ]; - pub static Syloti_Nagri_table: &'static [(char, char)] = &[ + pub const Syloti_Nagri_table: &'static [(char, char)] = &[ ('\u{a800}', '\u{a801}'), ('\u{a802}', '\u{a802}'), ('\u{a803}', '\u{a805}'), ('\u{a806}', '\u{a806}'), ('\u{a807}', '\u{a80a}'), ('\u{a80b}', '\u{a80b}'), ('\u{a80c}', '\u{a822}'), ('\u{a823}', '\u{a824}'), ('\u{a825}', '\u{a826}'), ('\u{a827}', '\u{a827}'), ('\u{a828}', '\u{a82b}') ]; - pub static Syriac_table: &'static [(char, char)] = &[ + pub const Syriac_table: &'static [(char, char)] = &[ ('\u{700}', '\u{70d}'), ('\u{70f}', '\u{70f}'), ('\u{710}', '\u{710}'), ('\u{711}', '\u{711}'), ('\u{712}', '\u{72f}'), ('\u{730}', '\u{74a}'), ('\u{74d}', '\u{74f}') ]; - pub static Tagalog_table: &'static [(char, char)] = &[ + pub const Tagalog_table: &'static [(char, char)] = &[ ('\u{1700}', '\u{170c}'), ('\u{170e}', '\u{1711}'), ('\u{1712}', '\u{1714}') ]; - pub static Tagbanwa_table: &'static [(char, char)] = &[ + pub const Tagbanwa_table: &'static [(char, char)] = &[ ('\u{1760}', '\u{176c}'), ('\u{176e}', '\u{1770}'), ('\u{1772}', '\u{1773}') ]; - pub static Tai_Le_table: &'static [(char, char)] = &[ + pub const Tai_Le_table: &'static [(char, char)] = &[ ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}') ]; - pub static Tai_Tham_table: &'static [(char, char)] = &[ + pub const Tai_Tham_table: &'static [(char, char)] = &[ ('\u{1a20}', '\u{1a54}'), ('\u{1a55}', '\u{1a55}'), ('\u{1a56}', '\u{1a56}'), ('\u{1a57}', '\u{1a57}'), ('\u{1a58}', '\u{1a5e}'), ('\u{1a60}', '\u{1a60}'), ('\u{1a61}', '\u{1a61}'), ('\u{1a62}', '\u{1a62}'), ('\u{1a63}', '\u{1a64}'), ('\u{1a65}', '\u{1a6c}'), ('\u{1a6d}', @@ -3837,20 +3828,20 @@ pub mod script { '\u{1aad}') ]; - pub static Tai_Viet_table: &'static [(char, char)] = &[ + pub const Tai_Viet_table: &'static [(char, char)] = &[ ('\u{aa80}', '\u{aaaf}'), ('\u{aab0}', '\u{aab0}'), ('\u{aab1}', '\u{aab1}'), ('\u{aab2}', '\u{aab4}'), ('\u{aab5}', '\u{aab6}'), ('\u{aab7}', '\u{aab8}'), ('\u{aab9}', '\u{aabd}'), ('\u{aabe}', '\u{aabf}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac1}', '\u{aac1}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadc}'), ('\u{aadd}', '\u{aadd}'), ('\u{aade}', '\u{aadf}') ]; - pub static Takri_table: &'static [(char, char)] = &[ + pub const Takri_table: &'static [(char, char)] = &[ ('\u{11680}', '\u{116aa}'), ('\u{116ab}', '\u{116ab}'), ('\u{116ac}', '\u{116ac}'), ('\u{116ad}', '\u{116ad}'), ('\u{116ae}', '\u{116af}'), ('\u{116b0}', '\u{116b5}'), ('\u{116b6}', '\u{116b6}'), ('\u{116b7}', '\u{116b7}'), ('\u{116c0}', '\u{116c9}') ]; - pub static Tamil_table: &'static [(char, char)] = &[ + pub const Tamil_table: &'static [(char, char)] = &[ ('\u{b82}', '\u{b82}'), ('\u{b83}', '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'), ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', @@ -3860,7 +3851,7 @@ pub mod script { ('\u{bf3}', '\u{bf8}'), ('\u{bf9}', '\u{bf9}'), ('\u{bfa}', '\u{bfa}') ]; - pub static Telugu_table: &'static [(char, char)] = &[ + pub const Telugu_table: &'static [(char, char)] = &[ ('\u{c00}', '\u{c00}'), ('\u{c01}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c3d}'), ('\u{c3e}', '\u{c40}'), ('\u{c41}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', @@ -3869,17 +3860,17 @@ pub mod script { '\u{c7f}') ]; - pub static Thaana_table: &'static [(char, char)] = &[ + pub const Thaana_table: &'static [(char, char)] = &[ ('\u{780}', '\u{7a5}'), ('\u{7a6}', '\u{7b0}'), ('\u{7b1}', '\u{7b1}') ]; - pub static Thai_table: &'static [(char, char)] = &[ + pub const Thai_table: &'static [(char, char)] = &[ ('\u{e01}', '\u{e30}'), ('\u{e31}', '\u{e31}'), ('\u{e32}', '\u{e33}'), ('\u{e34}', '\u{e3a}'), ('\u{e40}', '\u{e45}'), ('\u{e46}', '\u{e46}'), ('\u{e47}', '\u{e4e}'), ('\u{e4f}', '\u{e4f}'), ('\u{e50}', '\u{e59}'), ('\u{e5a}', '\u{e5b}') ]; - pub static Tibetan_table: &'static [(char, char)] = &[ + pub const Tibetan_table: &'static [(char, char)] = &[ ('\u{f00}', '\u{f00}'), ('\u{f01}', '\u{f03}'), ('\u{f04}', '\u{f12}'), ('\u{f13}', '\u{f13}'), ('\u{f14}', '\u{f14}'), ('\u{f15}', '\u{f17}'), ('\u{f18}', '\u{f19}'), ('\u{f1a}', '\u{f1f}'), ('\u{f20}', '\u{f29}'), ('\u{f2a}', '\u{f33}'), ('\u{f34}', @@ -3893,12 +3884,12 @@ pub mod script { ('\u{fd0}', '\u{fd4}'), ('\u{fd9}', '\u{fda}') ]; - pub static Tifinagh_table: &'static [(char, char)] = &[ + pub const Tifinagh_table: &'static [(char, char)] = &[ ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d70}', '\u{2d70}'), ('\u{2d7f}', '\u{2d7f}') ]; - pub static Tirhuta_table: &'static [(char, char)] = &[ + pub const Tirhuta_table: &'static [(char, char)] = &[ ('\u{11480}', '\u{114af}'), ('\u{114b0}', '\u{114b2}'), ('\u{114b3}', '\u{114b8}'), ('\u{114b9}', '\u{114b9}'), ('\u{114ba}', '\u{114ba}'), ('\u{114bb}', '\u{114be}'), ('\u{114bf}', '\u{114c0}'), ('\u{114c1}', '\u{114c1}'), ('\u{114c2}', '\u{114c3}'), @@ -3906,21 +3897,21 @@ pub mod script { ('\u{114d0}', '\u{114d9}') ]; - pub static Ugaritic_table: &'static [(char, char)] = &[ + pub const Ugaritic_table: &'static [(char, char)] = &[ ('\u{10380}', '\u{1039d}'), ('\u{1039f}', '\u{1039f}') ]; - pub static Vai_table: &'static [(char, char)] = &[ + pub const Vai_table: &'static [(char, char)] = &[ ('\u{a500}', '\u{a60b}'), ('\u{a60c}', '\u{a60c}'), ('\u{a60d}', '\u{a60f}'), ('\u{a610}', '\u{a61f}'), ('\u{a620}', '\u{a629}'), ('\u{a62a}', '\u{a62b}') ]; - pub static Warang_Citi_table: &'static [(char, char)] = &[ + pub const Warang_Citi_table: &'static [(char, char)] = &[ ('\u{118a0}', '\u{118df}'), ('\u{118e0}', '\u{118e9}'), ('\u{118ea}', '\u{118f2}'), ('\u{118ff}', '\u{118ff}') ]; - pub static Yi_table: &'static [(char, char)] = &[ + pub const Yi_table: &'static [(char, char)] = &[ ('\u{a000}', '\u{a014}'), ('\u{a015}', '\u{a015}'), ('\u{a016}', '\u{a48c}'), ('\u{a490}', '\u{a4c6}') ]; @@ -3928,11 +3919,11 @@ pub mod script { } pub mod property { - pub static Join_Control_table: &'static [(char, char)] = &[ + pub const Join_Control_table: &'static [(char, char)] = &[ ('\u{200c}', '\u{200d}') ]; - pub static Noncharacter_Code_Point_table: &'static [(char, char)] = &[ + pub const Noncharacter_Code_Point_table: &'static [(char, char)] = &[ ('\u{fdd0}', '\u{fdef}'), ('\u{fffe}', '\u{ffff}'), ('\u{1fffe}', '\u{1ffff}'), ('\u{2fffe}', '\u{2ffff}'), ('\u{3fffe}', '\u{3ffff}'), ('\u{4fffe}', '\u{4ffff}'), ('\u{5fffe}', '\u{5ffff}'), ('\u{6fffe}', '\u{6ffff}'), ('\u{7fffe}', '\u{7ffff}'), @@ -3941,7 +3932,7 @@ pub mod property { ('\u{efffe}', '\u{effff}'), ('\u{ffffe}', '\u{fffff}') ]; - pub static White_Space_table: &'static [(char, char)] = &[ + pub const White_Space_table: &'static [(char, char)] = &[ ('\u{9}', '\u{d}'), ('\u{20}', '\u{20}'), ('\u{85}', '\u{85}'), ('\u{a0}', '\u{a0}'), ('\u{1680}', '\u{1680}'), ('\u{2000}', '\u{200a}'), ('\u{2028}', '\u{2028}'), ('\u{2029}', '\u{2029}'), ('\u{202f}', '\u{202f}'), ('\u{205f}', '\u{205f}'), ('\u{3000}', '\u{3000}') @@ -3954,111 +3945,110 @@ pub mod property { } pub mod regex { - pub static UNICODE_CLASSES: &'static [(&'static str, &'static &'static [(char, char)])] = &[ - ("Alphabetic", &super::derived_property::Alphabetic_table), ("Arabic", - &super::script::Arabic_table), ("Armenian", &super::script::Armenian_table), ("Avestan", - &super::script::Avestan_table), ("Balinese", &super::script::Balinese_table), ("Bamum", - &super::script::Bamum_table), ("Bassa_Vah", &super::script::Bassa_Vah_table), ("Batak", - &super::script::Batak_table), ("Bengali", &super::script::Bengali_table), ("Bopomofo", - &super::script::Bopomofo_table), ("Brahmi", &super::script::Brahmi_table), ("Braille", - &super::script::Braille_table), ("Buginese", &super::script::Buginese_table), ("Buhid", - &super::script::Buhid_table), ("C", &super::general_category::C_table), - ("Canadian_Aboriginal", &super::script::Canadian_Aboriginal_table), ("Carian", - &super::script::Carian_table), ("Caucasian_Albanian", - &super::script::Caucasian_Albanian_table), ("Cc", &super::general_category::Cc_table), - ("Cf", &super::general_category::Cf_table), ("Chakma", &super::script::Chakma_table), - ("Cham", &super::script::Cham_table), ("Cherokee", &super::script::Cherokee_table), ("Cn", - &super::general_category::Cn_table), ("Co", &super::general_category::Co_table), ("Common", - &super::script::Common_table), ("Coptic", &super::script::Coptic_table), ("Cuneiform", - &super::script::Cuneiform_table), ("Cypriot", &super::script::Cypriot_table), ("Cyrillic", - &super::script::Cyrillic_table), ("Default_Ignorable_Code_Point", - &super::derived_property::Default_Ignorable_Code_Point_table), ("Deseret", - &super::script::Deseret_table), ("Devanagari", &super::script::Devanagari_table), - ("Duployan", &super::script::Duployan_table), ("Egyptian_Hieroglyphs", - &super::script::Egyptian_Hieroglyphs_table), ("Elbasan", &super::script::Elbasan_table), - ("Ethiopic", &super::script::Ethiopic_table), ("Georgian", &super::script::Georgian_table), - ("Glagolitic", &super::script::Glagolitic_table), ("Gothic", &super::script::Gothic_table), - ("Grantha", &super::script::Grantha_table), ("Greek", &super::script::Greek_table), - ("Gujarati", &super::script::Gujarati_table), ("Gurmukhi", &super::script::Gurmukhi_table), - ("Han", &super::script::Han_table), ("Hangul", &super::script::Hangul_table), ("Hanunoo", - &super::script::Hanunoo_table), ("Hebrew", &super::script::Hebrew_table), ("Hiragana", - &super::script::Hiragana_table), ("Imperial_Aramaic", - &super::script::Imperial_Aramaic_table), ("Inherited", &super::script::Inherited_table), - ("Inscriptional_Pahlavi", &super::script::Inscriptional_Pahlavi_table), - ("Inscriptional_Parthian", &super::script::Inscriptional_Parthian_table), ("Javanese", - &super::script::Javanese_table), ("Join_Control", &super::property::Join_Control_table), - ("Kaithi", &super::script::Kaithi_table), ("Kannada", &super::script::Kannada_table), - ("Katakana", &super::script::Katakana_table), ("Kayah_Li", &super::script::Kayah_Li_table), - ("Kharoshthi", &super::script::Kharoshthi_table), ("Khmer", &super::script::Khmer_table), - ("Khojki", &super::script::Khojki_table), ("Khudawadi", &super::script::Khudawadi_table), - ("L", &super::general_category::L_table), ("LC", &super::general_category::LC_table), - ("Lao", &super::script::Lao_table), ("Latin", &super::script::Latin_table), ("Lepcha", - &super::script::Lepcha_table), ("Limbu", &super::script::Limbu_table), ("Linear_A", - &super::script::Linear_A_table), ("Linear_B", &super::script::Linear_B_table), ("Lisu", - &super::script::Lisu_table), ("Ll", &super::general_category::Ll_table), ("Lm", - &super::general_category::Lm_table), ("Lo", &super::general_category::Lo_table), - ("Lowercase", &super::derived_property::Lowercase_table), ("Lt", - &super::general_category::Lt_table), ("Lu", &super::general_category::Lu_table), ("Lycian", - &super::script::Lycian_table), ("Lydian", &super::script::Lydian_table), ("M", - &super::general_category::M_table), ("Mahajani", &super::script::Mahajani_table), - ("Malayalam", &super::script::Malayalam_table), ("Mandaic", &super::script::Mandaic_table), - ("Manichaean", &super::script::Manichaean_table), ("Mc", - &super::general_category::Mc_table), ("Me", &super::general_category::Me_table), - ("Meetei_Mayek", &super::script::Meetei_Mayek_table), ("Mende_Kikakui", - &super::script::Mende_Kikakui_table), ("Meroitic_Cursive", - &super::script::Meroitic_Cursive_table), ("Meroitic_Hieroglyphs", - &super::script::Meroitic_Hieroglyphs_table), ("Miao", &super::script::Miao_table), ("Mn", - &super::general_category::Mn_table), ("Modi", &super::script::Modi_table), ("Mongolian", - &super::script::Mongolian_table), ("Mro", &super::script::Mro_table), ("Myanmar", - &super::script::Myanmar_table), ("N", &super::general_category::N_table), ("Nabataean", - &super::script::Nabataean_table), ("Nd", &super::general_category::Nd_table), - ("New_Tai_Lue", &super::script::New_Tai_Lue_table), ("Nko", &super::script::Nko_table), - ("Nl", &super::general_category::Nl_table), ("No", &super::general_category::No_table), - ("Noncharacter_Code_Point", &super::property::Noncharacter_Code_Point_table), ("Ogham", - &super::script::Ogham_table), ("Ol_Chiki", &super::script::Ol_Chiki_table), ("Old_Italic", - &super::script::Old_Italic_table), ("Old_North_Arabian", - &super::script::Old_North_Arabian_table), ("Old_Permic", &super::script::Old_Permic_table), - ("Old_Persian", &super::script::Old_Persian_table), ("Old_South_Arabian", - &super::script::Old_South_Arabian_table), ("Old_Turkic", &super::script::Old_Turkic_table), - ("Oriya", &super::script::Oriya_table), ("Osmanya", &super::script::Osmanya_table), ("P", - &super::general_category::P_table), ("Pahawh_Hmong", &super::script::Pahawh_Hmong_table), - ("Palmyrene", &super::script::Palmyrene_table), ("Pau_Cin_Hau", - &super::script::Pau_Cin_Hau_table), ("Pc", &super::general_category::Pc_table), ("Pd", - &super::general_category::Pd_table), ("Pe", &super::general_category::Pe_table), ("Pf", - &super::general_category::Pf_table), ("Phags_Pa", &super::script::Phags_Pa_table), - ("Phoenician", &super::script::Phoenician_table), ("Pi", - &super::general_category::Pi_table), ("Po", &super::general_category::Po_table), ("Ps", - &super::general_category::Ps_table), ("Psalter_Pahlavi", - &super::script::Psalter_Pahlavi_table), ("Rejang", &super::script::Rejang_table), ("Runic", - &super::script::Runic_table), ("S", &super::general_category::S_table), ("Samaritan", - &super::script::Samaritan_table), ("Saurashtra", &super::script::Saurashtra_table), ("Sc", - &super::general_category::Sc_table), ("Sharada", &super::script::Sharada_table), ("Shavian", - &super::script::Shavian_table), ("Siddham", &super::script::Siddham_table), ("Sinhala", - &super::script::Sinhala_table), ("Sk", &super::general_category::Sk_table), ("Sm", - &super::general_category::Sm_table), ("So", &super::general_category::So_table), - ("Sora_Sompeng", &super::script::Sora_Sompeng_table), ("Sundanese", - &super::script::Sundanese_table), ("Syloti_Nagri", &super::script::Syloti_Nagri_table), - ("Syriac", &super::script::Syriac_table), ("Tagalog", &super::script::Tagalog_table), - ("Tagbanwa", &super::script::Tagbanwa_table), ("Tai_Le", &super::script::Tai_Le_table), - ("Tai_Tham", &super::script::Tai_Tham_table), ("Tai_Viet", &super::script::Tai_Viet_table), - ("Takri", &super::script::Takri_table), ("Tamil", &super::script::Tamil_table), ("Telugu", - &super::script::Telugu_table), ("Thaana", &super::script::Thaana_table), ("Thai", - &super::script::Thai_table), ("Tibetan", &super::script::Tibetan_table), ("Tifinagh", - &super::script::Tifinagh_table), ("Tirhuta", &super::script::Tirhuta_table), ("Ugaritic", - &super::script::Ugaritic_table), ("Uppercase", &super::derived_property::Uppercase_table), - ("Vai", &super::script::Vai_table), ("Warang_Citi", &super::script::Warang_Citi_table), - ("White_Space", &super::property::White_Space_table), ("XID_Continue", - &super::derived_property::XID_Continue_table), ("XID_Start", - &super::derived_property::XID_Start_table), ("Yi", &super::script::Yi_table), ("Z", - &super::general_category::Z_table), ("Zl", &super::general_category::Zl_table), ("Zp", - &super::general_category::Zp_table), ("Zs", &super::general_category::Zs_table) - ]; - - pub static PERLD: &'static &'static [(char, char)] = &super::general_category::Nd_table; - - pub static PERLS: &'static &'static [(char, char)] = &super::property::White_Space_table; - - pub static PERLW: &'static [(char, char)] = &[ + pub const UNICODE_CLASSES: &'static [(&'static str, &'static [(char, char)])] = &[ + ("Alphabetic", super::derived_property::Alphabetic_table), ("Arabic", + super::script::Arabic_table), ("Armenian", super::script::Armenian_table), ("Avestan", + super::script::Avestan_table), ("Balinese", super::script::Balinese_table), ("Bamum", + super::script::Bamum_table), ("Bassa_Vah", super::script::Bassa_Vah_table), ("Batak", + super::script::Batak_table), ("Bengali", super::script::Bengali_table), ("Bopomofo", + super::script::Bopomofo_table), ("Brahmi", super::script::Brahmi_table), ("Braille", + super::script::Braille_table), ("Buginese", super::script::Buginese_table), ("Buhid", + super::script::Buhid_table), ("C", super::general_category::C_table), + ("Canadian_Aboriginal", super::script::Canadian_Aboriginal_table), ("Carian", + super::script::Carian_table), ("Caucasian_Albanian", + super::script::Caucasian_Albanian_table), ("Cc", super::general_category::Cc_table), ("Cf", + super::general_category::Cf_table), ("Chakma", super::script::Chakma_table), ("Cham", + super::script::Cham_table), ("Cherokee", super::script::Cherokee_table), ("Cn", + super::general_category::Cn_table), ("Co", super::general_category::Co_table), ("Common", + super::script::Common_table), ("Coptic", super::script::Coptic_table), ("Cuneiform", + super::script::Cuneiform_table), ("Cypriot", super::script::Cypriot_table), ("Cyrillic", + super::script::Cyrillic_table), ("Default_Ignorable_Code_Point", + super::derived_property::Default_Ignorable_Code_Point_table), ("Deseret", + super::script::Deseret_table), ("Devanagari", super::script::Devanagari_table), ("Duployan", + super::script::Duployan_table), ("Egyptian_Hieroglyphs", + super::script::Egyptian_Hieroglyphs_table), ("Elbasan", super::script::Elbasan_table), + ("Ethiopic", super::script::Ethiopic_table), ("Georgian", super::script::Georgian_table), + ("Glagolitic", super::script::Glagolitic_table), ("Gothic", super::script::Gothic_table), + ("Grantha", super::script::Grantha_table), ("Greek", super::script::Greek_table), + ("Gujarati", super::script::Gujarati_table), ("Gurmukhi", super::script::Gurmukhi_table), + ("Han", super::script::Han_table), ("Hangul", super::script::Hangul_table), ("Hanunoo", + super::script::Hanunoo_table), ("Hebrew", super::script::Hebrew_table), ("Hiragana", + super::script::Hiragana_table), ("Imperial_Aramaic", super::script::Imperial_Aramaic_table), + ("Inherited", super::script::Inherited_table), ("Inscriptional_Pahlavi", + super::script::Inscriptional_Pahlavi_table), ("Inscriptional_Parthian", + super::script::Inscriptional_Parthian_table), ("Javanese", super::script::Javanese_table), + ("Join_Control", super::property::Join_Control_table), ("Kaithi", + super::script::Kaithi_table), ("Kannada", super::script::Kannada_table), ("Katakana", + super::script::Katakana_table), ("Kayah_Li", super::script::Kayah_Li_table), ("Kharoshthi", + super::script::Kharoshthi_table), ("Khmer", super::script::Khmer_table), ("Khojki", + super::script::Khojki_table), ("Khudawadi", super::script::Khudawadi_table), ("L", + super::general_category::L_table), ("LC", super::general_category::LC_table), ("Lao", + super::script::Lao_table), ("Latin", super::script::Latin_table), ("Lepcha", + super::script::Lepcha_table), ("Limbu", super::script::Limbu_table), ("Linear_A", + super::script::Linear_A_table), ("Linear_B", super::script::Linear_B_table), ("Lisu", + super::script::Lisu_table), ("Ll", super::general_category::Ll_table), ("Lm", + super::general_category::Lm_table), ("Lo", super::general_category::Lo_table), ("Lowercase", + super::derived_property::Lowercase_table), ("Lt", super::general_category::Lt_table), ("Lu", + super::general_category::Lu_table), ("Lycian", super::script::Lycian_table), ("Lydian", + super::script::Lydian_table), ("M", super::general_category::M_table), ("Mahajani", + super::script::Mahajani_table), ("Malayalam", super::script::Malayalam_table), ("Mandaic", + super::script::Mandaic_table), ("Manichaean", super::script::Manichaean_table), ("Mc", + super::general_category::Mc_table), ("Me", super::general_category::Me_table), + ("Meetei_Mayek", super::script::Meetei_Mayek_table), ("Mende_Kikakui", + super::script::Mende_Kikakui_table), ("Meroitic_Cursive", + super::script::Meroitic_Cursive_table), ("Meroitic_Hieroglyphs", + super::script::Meroitic_Hieroglyphs_table), ("Miao", super::script::Miao_table), ("Mn", + super::general_category::Mn_table), ("Modi", super::script::Modi_table), ("Mongolian", + super::script::Mongolian_table), ("Mro", super::script::Mro_table), ("Myanmar", + super::script::Myanmar_table), ("N", super::general_category::N_table), ("Nabataean", + super::script::Nabataean_table), ("Nd", super::general_category::Nd_table), ("New_Tai_Lue", + super::script::New_Tai_Lue_table), ("Nko", super::script::Nko_table), ("Nl", + super::general_category::Nl_table), ("No", super::general_category::No_table), + ("Noncharacter_Code_Point", super::property::Noncharacter_Code_Point_table), ("Ogham", + super::script::Ogham_table), ("Ol_Chiki", super::script::Ol_Chiki_table), ("Old_Italic", + super::script::Old_Italic_table), ("Old_North_Arabian", + super::script::Old_North_Arabian_table), ("Old_Permic", super::script::Old_Permic_table), + ("Old_Persian", super::script::Old_Persian_table), ("Old_South_Arabian", + super::script::Old_South_Arabian_table), ("Old_Turkic", super::script::Old_Turkic_table), + ("Oriya", super::script::Oriya_table), ("Osmanya", super::script::Osmanya_table), ("P", + super::general_category::P_table), ("Pahawh_Hmong", super::script::Pahawh_Hmong_table), + ("Palmyrene", super::script::Palmyrene_table), ("Pau_Cin_Hau", + super::script::Pau_Cin_Hau_table), ("Pc", super::general_category::Pc_table), ("Pd", + super::general_category::Pd_table), ("Pe", super::general_category::Pe_table), ("Pf", + super::general_category::Pf_table), ("Phags_Pa", super::script::Phags_Pa_table), + ("Phoenician", super::script::Phoenician_table), ("Pi", super::general_category::Pi_table), + ("Po", super::general_category::Po_table), ("Ps", super::general_category::Ps_table), + ("Psalter_Pahlavi", super::script::Psalter_Pahlavi_table), ("Rejang", + super::script::Rejang_table), ("Runic", super::script::Runic_table), ("S", + super::general_category::S_table), ("Samaritan", super::script::Samaritan_table), + ("Saurashtra", super::script::Saurashtra_table), ("Sc", super::general_category::Sc_table), + ("Sharada", super::script::Sharada_table), ("Shavian", super::script::Shavian_table), + ("Siddham", super::script::Siddham_table), ("Sinhala", super::script::Sinhala_table), ("Sk", + super::general_category::Sk_table), ("Sm", super::general_category::Sm_table), ("So", + super::general_category::So_table), ("Sora_Sompeng", super::script::Sora_Sompeng_table), + ("Sundanese", super::script::Sundanese_table), ("Syloti_Nagri", + super::script::Syloti_Nagri_table), ("Syriac", super::script::Syriac_table), ("Tagalog", + super::script::Tagalog_table), ("Tagbanwa", super::script::Tagbanwa_table), ("Tai_Le", + super::script::Tai_Le_table), ("Tai_Tham", super::script::Tai_Tham_table), ("Tai_Viet", + super::script::Tai_Viet_table), ("Takri", super::script::Takri_table), ("Tamil", + super::script::Tamil_table), ("Telugu", super::script::Telugu_table), ("Thaana", + super::script::Thaana_table), ("Thai", super::script::Thai_table), ("Tibetan", + super::script::Tibetan_table), ("Tifinagh", super::script::Tifinagh_table), ("Tirhuta", + super::script::Tirhuta_table), ("Ugaritic", super::script::Ugaritic_table), ("Uppercase", + super::derived_property::Uppercase_table), ("Vai", super::script::Vai_table), + ("Warang_Citi", super::script::Warang_Citi_table), ("White_Space", + super::property::White_Space_table), ("XID_Continue", + super::derived_property::XID_Continue_table), ("XID_Start", + super::derived_property::XID_Start_table), ("Yi", super::script::Yi_table), ("Z", + super::general_category::Z_table), ("Zl", super::general_category::Zl_table), ("Zp", + super::general_category::Zp_table), ("Zs", super::general_category::Zs_table) + ]; + + pub const PERLD: &'static [(char, char)] = super::general_category::Nd_table; + + pub const PERLS: &'static [(char, char)] = super::property::White_Space_table; + + pub const PERLW: &'static [(char, char)] = &[ ('\u{30}', '\u{39}'), ('\u{41}', '\u{5a}'), ('\u{5f}', '\u{5f}'), ('\u{61}', '\u{7a}'), ('\u{aa}', '\u{aa}'), ('\u{b5}', '\u{b5}'), ('\u{ba}', '\u{ba}'), ('\u{c0}', '\u{d6}'), ('\u{d8}', '\u{f6}'), ('\u{f8}', '\u{2c1}'), ('\u{2c6}', '\u{2d1}'), ('\u{2e0}', '\u{2e4}'), @@ -4254,7 +4244,7 @@ pub mod regex { pub mod normalization { // Canonical decompositions - pub static canonical_table: &'static [(char, &'static [char])] = &[ + pub const canonical_table: &'static [(char, &'static [char])] = &[ ('\u{c0}', &['\u{41}', '\u{300}']), ('\u{c1}', &['\u{41}', '\u{301}']), ('\u{c2}', &['\u{41}', '\u{302}']), ('\u{c3}', &['\u{41}', '\u{303}']), ('\u{c4}', &['\u{41}', '\u{308}']), ('\u{c5}', &['\u{41}', '\u{30a}']), ('\u{c7}', &['\u{43}', '\u{327}']), @@ -5056,7 +5046,7 @@ pub mod normalization { ]; // Compatibility decompositions - pub static compatibility_table: &'static [(char, &'static [char])] = &[ + pub const compatibility_table: &'static [(char, &'static [char])] = &[ ('\u{a0}', &['\u{20}']), ('\u{a8}', &['\u{20}', '\u{308}']), ('\u{aa}', &['\u{61}']), ('\u{af}', &['\u{20}', '\u{304}']), ('\u{b2}', &['\u{32}']), ('\u{b3}', &['\u{33}']), ('\u{b4}', &['\u{20}', '\u{301}']), ('\u{b5}', &['\u{3bc}']), ('\u{b8}', &['\u{20}', @@ -6480,7 +6470,7 @@ pub mod normalization { ]; // Canonical compositions - pub static composition_table: &'static [(char, &'static [(char, char)])] = &[ + pub const composition_table: &'static [(char, &'static [(char, char)])] = &[ ('\u{3c}', &[('\u{338}', '\u{226e}')]), ('\u{3d}', &[('\u{338}', '\u{2260}')]), ('\u{3e}', &[('\u{338}', '\u{226f}')]), ('\u{41}', &[('\u{300}', '\u{c0}'), ('\u{301}', '\u{c1}'), ('\u{302}', '\u{c2}'), ('\u{303}', '\u{c3}'), ('\u{304}', '\u{100}'), ('\u{306}', @@ -6840,7 +6830,7 @@ pub mod normalization { } } - static combining_class_table: &'static [(char, char, u8)] = &[ + const combining_class_table: &'static [(char, char, u8)] = &[ ('\u{300}', '\u{314}', 230), ('\u{315}', '\u{315}', 232), ('\u{316}', '\u{319}', 220), ('\u{31a}', '\u{31a}', 232), ('\u{31b}', '\u{31b}', 216), ('\u{31c}', '\u{320}', 220), ('\u{321}', '\u{322}', 202), ('\u{323}', '\u{326}', 220), ('\u{327}', '\u{328}', 202), @@ -6988,7 +6978,7 @@ pub mod conversions { } } - static LuLl_table: &'static [(char, char)] = &[ + const LuLl_table: &'static [(char, char)] = &[ ('\u{41}', '\u{61}'), ('\u{42}', '\u{62}'), ('\u{43}', '\u{63}'), ('\u{44}', '\u{64}'), ('\u{45}', '\u{65}'), ('\u{46}', '\u{66}'), ('\u{47}', '\u{67}'), ('\u{48}', '\u{68}'), ('\u{49}', '\u{69}'), ('\u{4a}', '\u{6a}'), ('\u{4b}', '\u{6b}'), ('\u{4c}', '\u{6c}'), @@ -7284,7 +7274,7 @@ pub mod conversions { ('\u{118be}', '\u{118de}'), ('\u{118bf}', '\u{118df}') ]; - static LlLu_table: &'static [(char, char)] = &[ + const LlLu_table: &'static [(char, char)] = &[ ('\u{61}', '\u{41}'), ('\u{62}', '\u{42}'), ('\u{63}', '\u{43}'), ('\u{64}', '\u{44}'), ('\u{65}', '\u{45}'), ('\u{66}', '\u{46}'), ('\u{67}', '\u{47}'), ('\u{68}', '\u{48}'), ('\u{69}', '\u{49}'), ('\u{6a}', '\u{4a}'), ('\u{6b}', '\u{4b}'), ('\u{6c}', '\u{4c}'), @@ -7625,7 +7615,7 @@ pub mod charwidth { // character width table. Based on Markus Kuhn's free wcwidth() implementation, // http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c - static charwidth_table: &'static [(char, char, u8, u8)] = &[ + const charwidth_table: &'static [(char, char, u8, u8)] = &[ ('\u{a1}', '\u{a1}', 1, 2), ('\u{a4}', '\u{a4}', 1, 2), ('\u{a7}', '\u{a8}', 1, 2), ('\u{aa}', '\u{aa}', 1, 2), ('\u{ae}', '\u{ae}', 1, 2), ('\u{b0}', '\u{b4}', 1, 2), ('\u{b6}', '\u{ba}', 1, 2), ('\u{bc}', '\u{bf}', 1, 2), ('\u{c6}', '\u{c6}', 1, 2), @@ -7839,7 +7829,7 @@ pub mod grapheme { bsearch_range_value_table(c, grapheme_cat_table) } - static grapheme_cat_table: &'static [(char, char, GraphemeCat)] = &[ + const grapheme_cat_table: &'static [(char, char, GraphemeCat)] = &[ ('\u{0}', '\u{1f}', GC_Control), ('\u{7f}', '\u{9f}', GC_Control), ('\u{ad}', '\u{ad}', GC_Control), ('\u{300}', '\u{36f}', GC_Extend), ('\u{483}', '\u{487}', GC_Extend), ('\u{488}', '\u{489}', GC_Extend), ('\u{591}', '\u{5bd}', GC_Extend), ('\u{5bf}', '\u{5bf}', diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 9bd8c5525a..3f9dd8ab63 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -22,11 +22,9 @@ use core::char; use core::cmp; use core::iter::{Filter, AdditiveIterator}; use core::mem; -use core::num::Int; use core::slice; use core::str::Split; -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 @@ -84,7 +82,7 @@ impl UnicodeStr for str { #[inline] fn trim(&self) -> &str { - self.trim_left().trim_right() + self.trim_matches(|c: char| c.is_whitespace()) } #[inline] @@ -243,7 +241,7 @@ impl<'a> Iterator for Graphemes<'a> { } self.cat = if take_curr { - idx = self.string.char_range_at(idx).next; + idx = idx + self.string.char_at(idx).len_utf8(); None } else { Some(cat) @@ -479,22 +477,27 @@ impl<'a> Iterator for Utf16Items<'a> { /// Create an iterator over the UTF-16 encoded codepoints in `v`, /// returning invalid surrogates as `LoneSurrogate`s. /// -/// # Example +/// # Examples +/// +/// ``` +/// # #![feature(unicode)] +/// extern crate unicode; /// -/// ```rust /// use unicode::str::Utf16Item::{ScalarValue, LoneSurrogate}; /// -/// // 𝄞music -/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, -/// 0x0073, 0xDD1E, 0x0069, 0x0063, -/// 0xD834]; +/// fn main() { +/// // 𝄞music +/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, +/// 0x0073, 0xDD1E, 0x0069, 0x0063, +/// 0xD834]; /// -/// assert_eq!(unicode::str::utf16_items(&v).collect::>(), -/// vec![ScalarValue('𝄞'), -/// ScalarValue('m'), ScalarValue('u'), ScalarValue('s'), -/// LoneSurrogate(0xDD1E), -/// ScalarValue('i'), ScalarValue('c'), -/// LoneSurrogate(0xD834)]); +/// assert_eq!(unicode::str::utf16_items(&v).collect::>(), +/// vec![ScalarValue('𝄞'), +/// ScalarValue('m'), ScalarValue('u'), ScalarValue('s'), +/// LoneSurrogate(0xDD1E), +/// ScalarValue('i'), ScalarValue('c'), +/// LoneSurrogate(0xD834)]); +/// } /// ``` pub fn utf16_items<'a>(v: &'a [u16]) -> Utf16Items<'a> { Utf16Items { iter : v.iter() } @@ -525,7 +528,7 @@ impl Iterator for Utf16Encoder where I: Iterator { return Some(tmp); } - let mut buf = [0u16; 2]; + let mut buf = [0; 2]; self.chars.next().map(|ch| { let n = CharExt::encode_utf16(ch, &mut buf).unwrap_or(0); if n == 2 { self.extra = buf[1]; } diff --git a/src/llvm/autoconf/config.sub b/src/llvm/autoconf/config.sub index 673d62bfbf..612bff3de8 100755 --- a/src/llvm/autoconf/config.sub +++ b/src/llvm/autoconf/config.sub @@ -1354,7 +1354,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -bitrig*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) diff --git a/src/llvm/autoconf/configure.ac b/src/llvm/autoconf/configure.ac index 3bd8aa1806..d05575222f 100644 --- a/src/llvm/autoconf/configure.ac +++ b/src/llvm/autoconf/configure.ac @@ -267,6 +267,11 @@ AC_CACHE_CHECK([type of operating system we're going to host on], llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="DragonFly" llvm_cv_platform_type="Unix" ;; + *-*-bitrig*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Bitrig" + llvm_cv_platform_type="Unix" ;; *-*-hpux*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -347,6 +352,8 @@ AC_CACHE_CHECK([type of operating system we're going to target], llvm_cv_target_os_type="NetBSD" ;; *-*-dragonfly*) llvm_cv_target_os_type="DragonFly" ;; + *-*-bitrig*) + llvm_cv_target_os_type="Bitrig" ;; *-*-hpux*) llvm_cv_target_os_type="HP-UX" ;; *-*-interix*) diff --git a/src/llvm/configure b/src/llvm/configure index ba5ecbef33..d22c569a52 100755 --- a/src/llvm/configure +++ b/src/llvm/configure @@ -3966,6 +3966,11 @@ else llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="DragonFly" llvm_cv_platform_type="Unix" ;; + *-*-bitrig*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Bitrig" + llvm_cv_platform_type="Unix" ;; *-*-hpux*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -4052,6 +4057,8 @@ else llvm_cv_target_os_type="NetBSD" ;; *-*-dragonfly*) llvm_cv_target_os_type="DragonFly" ;; + *-*-bitrig*) + llvm_cv_target_os_type="Bitrig" ;; *-*-hpux*) llvm_cv_target_os_type="HP-UX" ;; *-*-interix*) diff --git a/src/llvm/docs/ReleaseNotes.rst b/src/llvm/docs/ReleaseNotes.rst index 107f9d297d..32e8295acd 100644 --- a/src/llvm/docs/ReleaseNotes.rst +++ b/src/llvm/docs/ReleaseNotes.rst @@ -5,11 +5,6 @@ LLVM 3.6 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 3.6 release. You may - prefer the `LLVM 3.5 Release Notes `_. - Introduction ============ @@ -26,10 +21,6 @@ have questions or comments, the `LLVM Developer's Mailing List `_ is a good place to send them. -Note that if you are reading this file from a Subversion checkout or the main -LLVM web page, this document applies to the *next* release, not the current -one. To see the release notes for a specific release, please see the `releases -page `_. Non-comprehensive list of changes in this release ================================================= @@ -507,6 +498,12 @@ Changes to the OCaml bindings * As usual, many more functions have been exposed to OCaml. +Go bindings +----------- + +* A set of Go bindings based on `gollvm `_ + was introduced in this release. + External Open Source Projects Using LLVM 3.6 ============================================ @@ -544,6 +541,33 @@ new LLVM-based code generators "on the fly" for the designed processors and loads them in to the compiler backend as runtime libraries to avoid per-target recompilation of larger parts of the compiler chain. +Likely +------ + +`Likely `_ is an embeddable just-in-time Lisp for +image recognition and heterogenous computing. Algorithms are just-in-time +compiled using LLVM's MCJIT infrastructure to execute on single or +multi-threaded CPUs and potentially OpenCL SPIR or CUDA enabled GPUs. +Likely seeks to explore new optimizations for statistical learning +algorithms by moving them from an offline model generation step to the +compile-time evaluation of a function (the learning algorithm) with constant +arguments (the training data). + +LDC - the LLVM-based D compiler +------------------------------- + +`D `_ is a language with C-like syntax and static typing. It +pragmatically combines efficiency, control, and modeling power, with safety and +programmer productivity. D supports powerful concepts like Compile-Time Function +Execution (CTFE) and Template Meta-Programming, provides an innovative approach +to concurrency and offers many classical paradigms. + +`LDC `_ uses the frontend from the reference compiler +combined with LLVM as backend to produce efficient native code. LDC targets +x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux on +PowerPC (32/64 bit). Ports to other architectures like ARM, AArch64 and MIPS64 +are underway. + Additional Information ====================== diff --git a/src/llvm/docs/index.rst b/src/llvm/docs/index.rst index dd6ea18f09..33bb0834ac 100644 --- a/src/llvm/docs/index.rst +++ b/src/llvm/docs/index.rst @@ -1,11 +1,6 @@ Overview ======== -.. warning:: - - If you are using a released version of LLVM, see `the download page - `_ to find your documentation. - The LLVM compiler infrastructure supports a wide range of projects, from industrial strength compilers to specialized JIT applications to small research projects. diff --git a/src/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/src/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt index 45e92e4b8c..284491a267 100644 --- a/src/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt +++ b/src/llvm/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine InstCombine MC + RuntimeDyld ScalarOpts Support native diff --git a/src/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/src/llvm/include/llvm/CodeGen/MachineModuleInfo.h index f0d0b2dbcd..584ce65c9d 100644 --- a/src/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/src/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -66,7 +66,6 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector BeginLabels; // Labels prior to invoke. SmallVector EndLabels; // Labels after invoke. - SmallVector ClauseLabels; // Labels for each clause. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector TypeIds; // List of type ids (filters negative) @@ -331,11 +330,6 @@ public: /// void addCleanup(MachineBasicBlock *LandingPad); - /// Add a clause for a landing pad. Returns a new label for the clause. This - /// is used by EH schemes that have more than one landing pad. In this case, - /// each clause gets its own basic block. - MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); - /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned getTypeIDFor(const GlobalValue *TI); diff --git a/src/llvm/include/llvm/CodeGen/SelectionDAG.h b/src/llvm/include/llvm/CodeGen/SelectionDAG.h index 4950797bb1..ee4bc08495 100644 --- a/src/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/src/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -867,9 +867,11 @@ public: SDValue Offset, ISD::MemIndexedMode AM); SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, - SDValue Mask, SDValue Src0, MachineMemOperand *MMO); + SDValue Mask, SDValue Src0, EVT MemVT, + MachineMemOperand *MMO, ISD::LoadExtType); SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, - SDValue Ptr, SDValue Mask, MachineMemOperand *MMO); + SDValue Ptr, SDValue Mask, EVT MemVT, + MachineMemOperand *MMO, bool IsTrunc); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); diff --git a/src/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/src/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 8e7fd54762..933ec7fff4 100644 --- a/src/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/src/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1970,13 +1970,17 @@ public: class MaskedLoadSDNode : public MaskedLoadStoreSDNode { public: friend class SelectionDAG; - MaskedLoadSDNode(unsigned Order, DebugLoc dl, - SDValue *Operands, unsigned numOperands, - SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy, + EVT MemVT, MachineMemOperand *MMO) : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, - VTs, MemVT, MMO) - {} + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)ETy; + } + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(SubclassData & 3); + } const SDValue &getSrc0() const { return getOperand(3); } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MLOAD; @@ -1989,14 +1993,19 @@ class MaskedStoreSDNode : public MaskedLoadStoreSDNode { public: friend class SelectionDAG; - MaskedStoreSDNode(unsigned Order, DebugLoc dl, - SDValue *Operands, unsigned numOperands, - SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, - VTs, MemVT, MMO) - {} + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; + } + /// isTruncatingStore - Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return SubclassData & 1; } - const SDValue &getData() const { return getOperand(3); } + const SDValue &getValue() const { return getOperand(3); } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MSTORE; diff --git a/src/llvm/include/llvm/Config/config.h.cmake b/src/llvm/include/llvm/Config/config.h.cmake index d154135e25..27f07d4e39 100644 --- a/src/llvm/include/llvm/Config/config.h.cmake +++ b/src/llvm/include/llvm/Config/config.h.cmake @@ -6,9 +6,6 @@ /* Exported configuration */ #include "llvm/Config/llvm-config.h" -/* Patch version of the LLVM API */ -#cmakedefine LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} - /* Bug report URL. */ #define BUG_REPORT_URL "${BUG_REPORT_URL}" diff --git a/src/llvm/include/llvm/Config/llvm-config.h.cmake b/src/llvm/include/llvm/Config/llvm-config.h.cmake index 77201e6330..d54003d993 100644 --- a/src/llvm/include/llvm/Config/llvm-config.h.cmake +++ b/src/llvm/include/llvm/Config/llvm-config.h.cmake @@ -87,10 +87,13 @@ #cmakedefine LLVM_USE_OPROFILE 1 /* Major version of the LLVM API */ -#cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} +#define LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} /* Minor version of the LLVM API */ -#cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} +#define LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} + +/* Patch version of the LLVM API */ +#define LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} /* LLVM version string */ #define LLVM_VERSION_STRING "${PACKAGE_VERSION}" diff --git a/src/llvm/include/llvm/Config/llvm-config.h.in b/src/llvm/include/llvm/Config/llvm-config.h.in index 2d6add71a4..25a9295448 100644 --- a/src/llvm/include/llvm/Config/llvm-config.h.in +++ b/src/llvm/include/llvm/Config/llvm-config.h.in @@ -92,6 +92,9 @@ /* Minor version of the LLVM API */ #undef LLVM_VERSION_MINOR +/* Patch version of the LLVM API */ +#undef LLVM_VERSION_PATCH + /* LLVM version string */ #undef LLVM_VERSION_STRING diff --git a/src/llvm/include/llvm/IR/Constants.h b/src/llvm/include/llvm/IR/Constants.h index 1b0e1b7e7b..5b098b4f51 100644 --- a/src/llvm/include/llvm/IR/Constants.h +++ b/src/llvm/include/llvm/IR/Constants.h @@ -325,6 +325,9 @@ public: /// index. Constant *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// static bool classof(const Value *V) { @@ -1196,6 +1199,9 @@ public: /// index. UndefValue *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/src/llvm/include/llvm/Target/TargetLibraryInfo.h b/src/llvm/include/llvm/Target/TargetLibraryInfo.h index 46f87b93b0..1863a84b6e 100644 --- a/src/llvm/include/llvm/Target/TargetLibraryInfo.h +++ b/src/llvm/include/llvm/Target/TargetLibraryInfo.h @@ -371,6 +371,10 @@ namespace llvm { isascii, /// int isdigit(int c); isdigit, + /// void *je_mallocx(size_t size, int flags); + je_mallocx, + /// void *je_sdallocx(void *ptr, size_t size, int flags) + je_sdallocx, /// long int labs(long int j); labs, /// int lchown(const char *path, uid_t owner, gid_t group); @@ -688,6 +692,7 @@ namespace llvm { /// ssize_t write(int fildes, const void *buf, size_t nbyte); write, + NumLibFuncs }; } diff --git a/src/llvm/lib/Analysis/IPA/InlineCost.cpp b/src/llvm/lib/Analysis/IPA/InlineCost.cpp index 58ac5d3340..86e7fc21b9 100644 --- a/src/llvm/lib/Analysis/IPA/InlineCost.cpp +++ b/src/llvm/lib/Analysis/IPA/InlineCost.cpp @@ -52,7 +52,7 @@ class CallAnalyzer : public InstVisitor { const TargetTransformInfo &TTI; /// The cache of @llvm.assume intrinsics. - AssumptionCache &AC; + AssumptionCacheTracker *ACT; // The called function. Function &F; @@ -146,8 +146,8 @@ class CallAnalyzer : public InstVisitor { public: CallAnalyzer(const DataLayout *DL, const TargetTransformInfo &TTI, - AssumptionCache &AC, Function &Callee, int Threshold) - : DL(DL), TTI(TTI), AC(AC), F(Callee), Threshold(Threshold), Cost(0), + AssumptionCacheTracker *ACT, Function &Callee, int Threshold) + : DL(DL), TTI(TTI), ACT(ACT), F(Callee), Threshold(Threshold), Cost(0), IsCallerRecursive(false), IsRecursiveCall(false), ExposesReturnsTwice(false), HasDynamicAlloca(false), ContainsNoDuplicateCall(false), HasReturn(false), HasIndirectBr(false), @@ -783,7 +783,7 @@ bool CallAnalyzer::visitCallSite(CallSite CS) { // during devirtualization and so we want to give it a hefty bonus for // inlining, but cap that bonus in the event that inlining wouldn't pan // out. Pretend to inline the function, with a custom threshold. - CallAnalyzer CA(DL, TTI, AC, *F, InlineConstants::IndirectCallThreshold); + CallAnalyzer CA(DL, TTI, ACT, *F, InlineConstants::IndirectCallThreshold); if (CA.analyzeCall(CS)) { // We were able to inline the indirect call! Subtract the cost from the // bonus we want to apply, but don't go below zero. @@ -1110,7 +1110,7 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { // the ephemeral values multiple times (and they're completely determined by // the callee, so this is purely duplicate work). SmallPtrSet EphValues; - CodeMetrics::collectEphemeralValues(&F, &AC, EphValues); + CodeMetrics::collectEphemeralValues(&F, &ACT->getAssumptionCache(F), EphValues); // The worklist of live basic blocks in the callee *after* inlining. We avoid // adding basic blocks of the callee which can be proven to be dead for this @@ -1310,7 +1310,7 @@ InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee, << "...\n"); CallAnalyzer CA(Callee->getDataLayout(), *TTI, - ACT->getAssumptionCache(*Callee), *Callee, Threshold); + ACT, *Callee, Threshold); bool ShouldInline = CA.analyzeCall(CS); DEBUG(CA.dump()); diff --git a/src/llvm/lib/Analysis/MemoryBuiltins.cpp b/src/llvm/lib/Analysis/MemoryBuiltins.cpp index 08b41fee44..72f127fc95 100644 --- a/src/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/src/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -66,7 +66,8 @@ static const AllocFnsTy AllocationFnData[] = { {LibFunc::realloc, ReallocLike, 2, 1, -1}, {LibFunc::reallocf, ReallocLike, 2, 1, -1}, {LibFunc::strdup, StrDupLike, 1, -1, -1}, - {LibFunc::strndup, StrDupLike, 2, 1, -1} + {LibFunc::strndup, StrDupLike, 2, 1, -1}, + {LibFunc::je_mallocx, MallocLike, 2, 0, -1} // TODO: Handle "int posix_memalign(void **, size_t, size_t)" }; @@ -339,6 +340,8 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { TLIFn == LibFunc::ZdaPvm || // delete[](void*, ulong) TLIFn == LibFunc::ZdaPvRKSt9nothrow_t) // delete[](void*, nothrow) ExpectedNumParams = 2; + else if (TLIFn == LibFunc::je_sdallocx) + ExpectedNumParams = 3; else return nullptr; diff --git a/src/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/src/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 409adafc78..3d9546fc2b 100644 --- a/src/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/src/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -538,9 +538,17 @@ Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) { if (Metadata *MD = MDValuePtrs[Idx]) return MD; - // Create and return a placeholder, which will later be RAUW'd. - AnyFwdRefs = true; + // Track forward refs to be resolved later. + if (AnyFwdRefs) { + MinFwdRef = std::min(MinFwdRef, Idx); + MaxFwdRef = std::max(MaxFwdRef, Idx); + } else { + AnyFwdRefs = true; + MinFwdRef = MaxFwdRef = Idx; + } ++NumFwdRefs; + + // Create and return a placeholder, which will later be RAUW'd. Metadata *MD = MDNode::getTemporary(Context, None); MDValuePtrs[Idx].reset(MD); return MD; @@ -556,11 +564,15 @@ void BitcodeReaderMDValueList::tryToResolveCycles() { return; // Resolve any cycles. - for (auto &MD : MDValuePtrs) { + for (unsigned I = MinFwdRef, E = MaxFwdRef + 1; I != E; ++I) { + auto &MD = MDValuePtrs[I]; assert(!(MD && isa(MD)) && "Unexpected forward reference"); if (auto *N = dyn_cast_or_null(MD)) N->resolveCycles(); } + + // Make sure we return early again until there's another forward ref. + AnyFwdRefs = false; } Type *BitcodeReader::getTypeByID(unsigned ID) { diff --git a/src/llvm/lib/Bitcode/Reader/BitcodeReader.h b/src/llvm/lib/Bitcode/Reader/BitcodeReader.h index 7f7eb70bce..5090be4845 100644 --- a/src/llvm/lib/Bitcode/Reader/BitcodeReader.h +++ b/src/llvm/lib/Bitcode/Reader/BitcodeReader.h @@ -99,6 +99,8 @@ public: class BitcodeReaderMDValueList { unsigned NumFwdRefs; bool AnyFwdRefs; + unsigned MinFwdRef; + unsigned MaxFwdRef; std::vector MDValuePtrs; LLVMContext &Context; diff --git a/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp index 1bc86f6c22..f112120c1a 100644 --- a/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -121,8 +121,7 @@ computeActionsTable(const SmallVectorImpl &LandingPads, for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { int TypeID = TypeIds[J]; assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); - int ValueForTypeID = - isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID; + int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; unsigned SizeTypeID = getSLEB128Size(ValueForTypeID); int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; @@ -270,14 +269,14 @@ computeCallSiteTable(SmallVectorImpl &CallSites, CallSiteEntry Site = { BeginLabel, LastLabel, - LandingPad, + LandingPad->LandingPadLabel, FirstActions[P.PadIndex] }; // Try to merge with the previous call-site. SJLJ doesn't do this if (PreviousIsInvoke && !IsSJLJ) { CallSiteEntry &Prev = CallSites.back(); - if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) { + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; continue; @@ -577,15 +576,15 @@ void EHStreamer::emitExceptionTable() { // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - if (!S.LPad) { + if (!S.PadLabel) { if (VerboseAsm) Asm->OutStreamer.AddComment(" has no landing pad"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/); } else { if (VerboseAsm) Asm->OutStreamer.AddComment(Twine(" jumps to ") + - S.LPad->LandingPadLabel->getName()); - Asm->EmitLabelDifference(S.LPad->LandingPadLabel, EHFuncBeginSym, 4); + S.PadLabel->getName()); + Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); } // Offset of the first associated action record, relative to the start of @@ -682,7 +681,7 @@ void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) { unsigned TypeID = *I; if (VerboseAsm) { --Entry; - if (isFilterEHSelector(TypeID)) + if (TypeID != 0) Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry)); } diff --git a/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h b/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h index 9b316ff00e..e93055ce86 100644 --- a/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h +++ b/src/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h @@ -23,8 +23,6 @@ class MachineModuleInfo; class MachineInstr; class MachineFunction; class AsmPrinter; -class MCSymbol; -class MCSymbolRefExpr; template class SmallVectorImpl; @@ -62,11 +60,11 @@ protected: /// Structure describing an entry in the call-site table. struct CallSiteEntry { // The 'try-range' is BeginLabel .. EndLabel. - MCSymbol *BeginLabel; // Null indicates the start of the function. - MCSymbol *EndLabel; // Null indicates the end of the function. + MCSymbol *BeginLabel; // zero indicates the start of the function. + MCSymbol *EndLabel; // zero indicates the end of the function. - // LPad contains the landing pad start labels. - const LandingPadInfo *LPad; // Null indicates that there is no landing pad. + // The landing pad starts at PadLabel. + MCSymbol *PadLabel; // zero indicates that there is no landing pad. unsigned Action; }; @@ -114,13 +112,6 @@ protected: virtual void emitTypeInfos(unsigned TTypeEncoding); - // Helpers for for identifying what kind of clause an EH typeid or selector - // corresponds to. Negative selectors are for filter clauses, the zero - // selector is for cleanups, and positive selectors are for catch clauses. - static bool isFilterEHSelector(int Selector) { return Selector < 0; } - static bool isCleanupEHSelector(int Selector) { return Selector == 0; } - static bool isCatchEHSelector(int Selector) { return Selector > 0; } - public: EHStreamer(AsmPrinter *A); virtual ~EHStreamer(); diff --git a/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 2138cb9514..0f0ad75583 100644 --- a/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -99,156 +99,9 @@ void Win64Exception::endFunction(const MachineFunction *) { if (shouldEmitPersonality) { Asm->OutStreamer.PushSection(); - - // Emit an UNWIND_INFO struct describing the prologue. Asm->OutStreamer.EmitWinEHHandlerData(); - - // Emit either MSVC-compatible tables or the usual Itanium-style LSDA after - // the UNWIND_INFO struct. - if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::MSVC) { - const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()]; - if (Per->getName() == "__C_specific_handler") - emitCSpecificHandlerTable(); - else - report_fatal_error(Twine("unexpected personality function: ") + - Per->getName()); - } else { - emitExceptionTable(); - } - + emitExceptionTable(); Asm->OutStreamer.PopSection(); } Asm->OutStreamer.EmitWinCFIEndProc(); } - -const MCSymbolRefExpr *Win64Exception::createImageRel32(const MCSymbol *Value) { - return MCSymbolRefExpr::Create(Value, MCSymbolRefExpr::VK_COFF_IMGREL32, - Asm->OutContext); -} - -/// Emit the language-specific data that __C_specific_handler expects. This -/// handler lives in the x64 Microsoft C runtime and allows catching or cleaning -/// up after faults with __try, __except, and __finally. The typeinfo values -/// are not really RTTI data, but pointers to filter functions that return an -/// integer (1, 0, or -1) indicating how to handle the exception. For __finally -/// blocks and other cleanups, the landing pad label is zero, and the filter -/// function is actually a cleanup handler with the same prototype. A catch-all -/// entry is modeled with a null filter function field and a non-zero landing -/// pad label. -/// -/// Possible filter function return values: -/// EXCEPTION_EXECUTE_HANDLER (1): -/// Jump to the landing pad label after cleanups. -/// EXCEPTION_CONTINUE_SEARCH (0): -/// Continue searching this table or continue unwinding. -/// EXCEPTION_CONTINUE_EXECUTION (-1): -/// Resume execution at the trapping PC. -/// -/// Inferred table structure: -/// struct Table { -/// int NumEntries; -/// struct Entry { -/// imagerel32 LabelStart; -/// imagerel32 LabelEnd; -/// imagerel32 FilterOrFinally; // Zero means catch-all. -/// imagerel32 LabelLPad; // Zero means __finally. -/// } Entries[NumEntries]; -/// }; -void Win64Exception::emitCSpecificHandlerTable() { - const std::vector &PadInfos = MMI->getLandingPads(); - - // Simplifying assumptions for first implementation: - // - Cleanups are not implemented. - // - Filters are not implemented. - - // The Itanium LSDA table sorts similar landing pads together to simplify the - // actions table, but we don't need that. - SmallVector LandingPads; - LandingPads.reserve(PadInfos.size()); - for (const auto &LP : PadInfos) - LandingPads.push_back(&LP); - - // Compute label ranges for call sites as we would for the Itanium LSDA, but - // use an all zero action table because we aren't using these actions. - SmallVector FirstActions; - FirstActions.resize(LandingPads.size()); - SmallVector CallSites; - computeCallSiteTable(CallSites, LandingPads, FirstActions); - - MCSymbol *EHFuncBeginSym = - Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); - MCSymbol *EHFuncEndSym = - Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); - - // Emit the number of table entries. - unsigned NumEntries = 0; - for (const CallSiteEntry &CSE : CallSites) { - if (!CSE.LPad) - continue; // Ignore gaps. - for (int Selector : CSE.LPad->TypeIds) { - // Ignore C++ filter clauses in SEH. - // FIXME: Implement cleanup clauses. - if (isCatchEHSelector(Selector)) - ++NumEntries; - } - } - Asm->OutStreamer.EmitIntValue(NumEntries, 4); - - // Emit the four-label records for each call site entry. The table has to be - // sorted in layout order, and the call sites should already be sorted. - for (const CallSiteEntry &CSE : CallSites) { - // Ignore gaps. Unlike the Itanium model, unwinding through a frame without - // an EH table entry will propagate the exception rather than terminating - // the program. - if (!CSE.LPad) - continue; - const LandingPadInfo *LPad = CSE.LPad; - - // Compute the label range. We may reuse the function begin and end labels - // rather than forming new ones. - const MCExpr *Begin = - createImageRel32(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym); - const MCExpr *End; - if (CSE.EndLabel) { - // The interval is half-open, so we have to add one to include the return - // address of the last invoke in the range. - End = MCBinaryExpr::CreateAdd(createImageRel32(CSE.EndLabel), - MCConstantExpr::Create(1, Asm->OutContext), - Asm->OutContext); - } else { - End = createImageRel32(EHFuncEndSym); - } - - // These aren't really type info globals, they are actually pointers to - // filter functions ordered by selector. The zero selector is used for - // cleanups, so slot zero corresponds to selector 1. - const std::vector &SelectorToFilter = MMI->getTypeInfos(); - - // Do a parallel iteration across typeids and clause labels, skipping filter - // clauses. - assert(LPad->TypeIds.size() == LPad->ClauseLabels.size()); - for (size_t I = 0, E = LPad->TypeIds.size(); I < E; ++I) { - // AddLandingPadInfo stores the clauses in reverse, but there is a FIXME - // to change that. - int Selector = LPad->TypeIds[E - I - 1]; - MCSymbol *ClauseLabel = LPad->ClauseLabels[I]; - - // Ignore C++ filter clauses in SEH. - // FIXME: Implement cleanup clauses. - if (!isCatchEHSelector(Selector)) - continue; - - Asm->OutStreamer.EmitValue(Begin, 4); - Asm->OutStreamer.EmitValue(End, 4); - if (isCatchEHSelector(Selector)) { - assert(unsigned(Selector - 1) < SelectorToFilter.size()); - const GlobalValue *TI = SelectorToFilter[Selector - 1]; - if (TI) // Emit the filter function pointer. - Asm->OutStreamer.EmitValue(createImageRel32(Asm->getSymbol(TI)), 4); - else // Otherwise, this is a "catch i8* null", or catch all. - Asm->OutStreamer.EmitIntValue(0, 4); - } - Asm->OutStreamer.EmitValue(createImageRel32(ClauseLabel), 4); - } - } -} diff --git a/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.h b/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.h index b2d5d1bce5..538e132815 100644 --- a/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.h +++ b/src/llvm/lib/CodeGen/AsmPrinter/Win64Exception.h @@ -29,10 +29,6 @@ class Win64Exception : public EHStreamer { /// Per-function flag to indicate if frame moves info should be emitted. bool shouldEmitMoves; - void emitCSpecificHandlerTable(); - - const MCSymbolRefExpr *createImageRel32(const MCSymbol *Value); - public: //===--------------------------------------------------------------------===// // Main entry points. diff --git a/src/llvm/lib/CodeGen/MachineModuleInfo.cpp b/src/llvm/lib/CodeGen/MachineModuleInfo.cpp index 32d511285e..baad411e2c 100644 --- a/src/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/src/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -452,14 +452,6 @@ void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) { LP.TypeIds.push_back(0); } -MCSymbol * -MachineModuleInfo::addClauseForLandingPad(MachineBasicBlock *LandingPad) { - MCSymbol *ClauseLabel = Context.CreateTempSymbol(); - LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); - LP.ClauseLabels.push_back(ClauseLabel); - return ClauseLabel; -} - /// TidyLandingPads - Remap landing pad labels and remove any deleted landing /// pads. void MachineModuleInfo::TidyLandingPads(DenseMap *LPMap) { diff --git a/src/llvm/lib/CodeGen/Passes.cpp b/src/llvm/lib/CodeGen/Passes.cpp index 28e9f847a9..e53e874cb1 100644 --- a/src/llvm/lib/CodeGen/Passes.cpp +++ b/src/llvm/lib/CodeGen/Passes.cpp @@ -449,9 +449,9 @@ void TargetPassConfig::addPassesToHandleExceptions() { case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: case ExceptionHandling::ItaniumWinEH: - case ExceptionHandling::MSVC: // FIXME: Needs preparation. addPass(createDwarfEHPass(TM)); break; + case ExceptionHandling::MSVC: // FIXME: Add preparation. case ExceptionHandling::None: addPass(createLowerInvokePass()); diff --git a/src/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/src/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 5145731f62..afb986f1d7 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4842,7 +4842,7 @@ SDValue DAGCombiner::visitMSTORE(SDNode *N) { MaskedStoreSDNode *MST = dyn_cast(N); SDValue Mask = MST->getMask(); - SDValue Data = MST->getData(); + SDValue Data = MST->getValue(); SDLoc DL(N); // If the MSTORE data type requires splitting and the mask is provided by a @@ -4885,7 +4885,8 @@ SDValue DAGCombiner::visitMSTORE(SDNode *N) { MachineMemOperand::MOStore, LoMemVT.getStoreSize(), Alignment, MST->getAAInfo(), MST->getRanges()); - Lo = DAG.getMaskedStore(Chain, DL, DataLo, Ptr, MaskLo, MMO); + Lo = DAG.getMaskedStore(Chain, DL, DataLo, Ptr, MaskLo, LoMemVT, MMO, + MST->isTruncatingStore()); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, @@ -4897,7 +4898,8 @@ SDValue DAGCombiner::visitMSTORE(SDNode *N) { SecondHalfAlignment, MST->getAAInfo(), MST->getRanges()); - Hi = DAG.getMaskedStore(Chain, DL, DataHi, Ptr, MaskHi, MMO); + Hi = DAG.getMaskedStore(Chain, DL, DataHi, Ptr, MaskHi, HiMemVT, MMO, + MST->isTruncatingStore()); AddToWorklist(Lo.getNode()); AddToWorklist(Hi.getNode()); @@ -4958,7 +4960,8 @@ SDValue DAGCombiner::visitMLOAD(SDNode *N) { MachineMemOperand::MOLoad, LoMemVT.getStoreSize(), Alignment, MLD->getAAInfo(), MLD->getRanges()); - Lo = DAG.getMaskedLoad(LoVT, DL, Chain, Ptr, MaskLo, Src0Lo, MMO); + Lo = DAG.getMaskedLoad(LoVT, DL, Chain, Ptr, MaskLo, Src0Lo, LoMemVT, MMO, + ISD::NON_EXTLOAD); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, @@ -4969,7 +4972,8 @@ SDValue DAGCombiner::visitMLOAD(SDNode *N) { MachineMemOperand::MOLoad, HiMemVT.getStoreSize(), SecondHalfAlignment, MLD->getAAInfo(), MLD->getRanges()); - Hi = DAG.getMaskedLoad(HiVT, DL, Chain, Ptr, MaskHi, Src0Hi, MMO); + Hi = DAG.getMaskedLoad(HiVT, DL, Chain, Ptr, MaskHi, Src0Hi, HiMemVT, MMO, + ISD::NON_EXTLOAD); AddToWorklist(Lo.getNode()); AddToWorklist(Hi.getNode()); @@ -6544,19 +6548,15 @@ SDValue DAGCombiner::visitBITCAST(SDNode *N) { // If the input is a constant, let getNode fold it. if (isa(N0) || isa(N0)) { - SDValue Res = DAG.getNode(ISD::BITCAST, SDLoc(N), VT, N0); - if (Res.getNode() != N) { - if (!LegalOperations || - TLI.isOperationLegal(Res.getNode()->getOpcode(), VT)) - return Res; - - // Folding it resulted in an illegal node, and it's too late to - // do that. Clean up the old node and forego the transformation. - // Ideally this won't happen very often, because instcombine - // and the earlier dagcombine runs (where illegal nodes are - // permitted) should have folded most of them already. - deleteAndRecombine(Res.getNode()); - } + // If we can't allow illegal operations, we need to check that this is just + // a fp -> int or int -> conversion and that the resulting operation will + // be legal. + if (!LegalOperations || + (isa(N0) && VT.isFloatingPoint() && !VT.isVector() && + TLI.isOperationLegal(ISD::ConstantFP, VT)) || + (isa(N0) && VT.isInteger() && !VT.isVector() && + TLI.isOperationLegal(ISD::Constant, VT))) + return DAG.getNode(ISD::BITCAST, SDLoc(N), VT, N0); } // (conv (conv x, t1), t2) -> (conv x, t2) @@ -9486,6 +9486,8 @@ SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) { unsigned MSB = BitWidth - Imm.countLeadingZeros() - 1; unsigned NewBW = NextPowerOf2(MSB - ShAmt); EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), NewBW); + // The narrowing should be profitable, the load/store operation should be + // legal (or custom) and the store size should be equal to the NewVT width. while (NewBW < BitWidth && !(TLI.isOperationLegalOrCustom(Opc, NewVT) && TLI.isNarrowingProfitable(VT, NewVT))) { diff --git a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 82b114b80a..a4e44ccbd7 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -458,16 +458,16 @@ SDValue DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { SDValue DAGTypeLegalizer::PromoteIntRes_MLOAD(MaskedLoadSDNode *N) { EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); SDValue ExtSrc0 = GetPromotedInteger(N->getSrc0()); - SDValue ExtMask = PromoteTargetBoolean(N->getMask(), NVT); - SDLoc dl(N); - MachineMemOperand *MMO = DAG.getMachineFunction(). - getMachineMemOperand(N->getPointerInfo(), - MachineMemOperand::MOLoad, NVT.getStoreSize(), - N->getAlignment(), N->getAAInfo(), N->getRanges()); + SDValue Mask = N->getMask(); + EVT NewMaskVT = getSetCCResultType(NVT); + if (NewMaskVT != N->getMask().getValueType()) + Mask = PromoteTargetBoolean(Mask, NewMaskVT); + SDLoc dl(N); SDValue Res = DAG.getMaskedLoad(NVT, dl, N->getChain(), N->getBasePtr(), - ExtMask, ExtSrc0, MMO); + Mask, ExtSrc0, N->getMemoryVT(), + N->getMemOperand(), ISD::SEXTLOAD); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); @@ -1117,16 +1117,18 @@ SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ SDValue DAGTypeLegalizer::PromoteIntOp_MSTORE(MaskedStoreSDNode *N, unsigned OpNo){ assert(OpNo == 2 && "Only know how to promote the mask!"); - SDValue DataOp = N->getData(); + SDValue DataOp = N->getValue(); EVT DataVT = DataOp.getValueType(); SDValue Mask = N->getMask(); EVT MaskVT = Mask.getValueType(); SDLoc dl(N); + bool TruncateStore = false; if (!TLI.isTypeLegal(DataVT)) { if (getTypeAction(DataVT) == TargetLowering::TypePromoteInteger) { DataOp = GetPromotedInteger(DataOp); Mask = PromoteTargetBoolean(Mask, DataOp.getValueType()); + TruncateStore = true; } else { assert(getTypeAction(DataVT) == TargetLowering::TypeWidenVector && @@ -1156,10 +1158,9 @@ SDValue DAGTypeLegalizer::PromoteIntOp_MSTORE(MaskedStoreSDNode *N, unsigned OpN } else Mask = PromoteTargetBoolean(N->getMask(), DataOp.getValueType()); - SmallVector NewOps(N->op_begin(), N->op_end()); - NewOps[2] = Mask; - NewOps[3] = DataOp; - return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0); + return DAG.getMaskedStore(N->getChain(), dl, DataOp, N->getBasePtr(), Mask, + N->getMemoryVT(), N->getMemOperand(), + TruncateStore); } SDValue DAGTypeLegalizer::PromoteIntOp_MLOAD(MaskedLoadSDNode *N, unsigned OpNo){ diff --git a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 1cd9f407bc..cef3fc9908 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -659,6 +659,7 @@ private: SDValue WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N); SDValue WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N); SDValue WidenVecOp_STORE(SDNode* N); + SDValue WidenVecOp_MSTORE(SDNode* N, unsigned OpNo); SDValue WidenVecOp_SETCC(SDNode* N); SDValue WidenVecOp_Convert(SDNode *N); diff --git a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp index 11e6b38f07..3a8c276e26 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -390,7 +390,8 @@ SDValue VectorLegalizer::Promote(SDValue Op) { if (Op.getOperand(j) .getValueType() .getVectorElementType() - .isFloatingPoint()) + .isFloatingPoint() && + NVT.isVector() && NVT.getVectorElementType().isFloatingPoint()) Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Op.getOperand(j)); else Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Op.getOperand(j)); @@ -399,8 +400,9 @@ SDValue VectorLegalizer::Promote(SDValue Op) { } Op = DAG.getNode(Op.getOpcode(), dl, NVT, Operands); - if (VT.isFloatingPoint() || - (VT.isVector() && VT.getVectorElementType().isFloatingPoint())) + if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) || + (VT.isVector() && VT.getVectorElementType().isFloatingPoint() && + NVT.isVector() && NVT.getVectorElementType().isFloatingPoint())) return DAG.getNode(ISD::FP_ROUND, dl, VT, Op, DAG.getIntPtrConstant(0)); else return DAG.getNode(ISD::BITCAST, dl, VT, Op); diff --git a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 96b69eec33..63671f75bf 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -992,6 +992,7 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD, SDValue Ptr = MLD->getBasePtr(); SDValue Mask = MLD->getMask(); unsigned Alignment = MLD->getOriginalAlignment(); + ISD::LoadExtType ExtType = MLD->getExtensionType(); // if Alignment is equal to the vector size, // take the half of it for the second part @@ -1015,7 +1016,8 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD, MachineMemOperand::MOLoad, LoMemVT.getStoreSize(), Alignment, MLD->getAAInfo(), MLD->getRanges()); - Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, MaskLo, Src0Lo, MMO); + Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, MaskLo, Src0Lo, LoMemVT, MMO, + ExtType); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -1026,7 +1028,8 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD, MachineMemOperand::MOLoad, HiMemVT.getStoreSize(), SecondHalfAlignment, MLD->getAAInfo(), MLD->getRanges()); - Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, MaskHi, Src0Hi, MMO); + Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, MaskHi, Src0Hi, HiMemVT, MMO, + ExtType); // Build a factor node to remember that this load is independent of the @@ -1464,7 +1467,7 @@ SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N, SDValue Ch = N->getChain(); SDValue Ptr = N->getBasePtr(); SDValue Mask = N->getMask(); - SDValue Data = N->getData(); + SDValue Data = N->getValue(); EVT MemoryVT = N->getMemoryVT(); unsigned Alignment = N->getOriginalAlignment(); SDLoc DL(N); @@ -1489,7 +1492,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N, MachineMemOperand::MOStore, LoMemVT.getStoreSize(), Alignment, N->getAAInfo(), N->getRanges()); - Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, MaskLo, MMO); + Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, MaskLo, LoMemVT, MMO, + N->isTruncatingStore()); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, @@ -1500,7 +1504,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N, MachineMemOperand::MOStore, HiMemVT.getStoreSize(), SecondHalfAlignment, N->getAAInfo(), N->getRanges()); - Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, MaskHi, MMO); + Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, MaskHi, HiMemVT, MMO, + N->isTruncatingStore()); // Build a factor node to remember that this store is independent of the @@ -2412,6 +2417,7 @@ SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) { SDValue Mask = N->getMask(); EVT MaskVT = Mask.getValueType(); SDValue Src0 = GetWidenedVector(N->getSrc0()); + ISD::LoadExtType ExtType = N->getExtensionType(); SDLoc dl(N); if (getTypeAction(MaskVT) == TargetLowering::TypeWidenVector) @@ -2434,14 +2440,9 @@ SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) { Mask = DAG.getNode(ISD::CONCAT_VECTORS, dl, BoolVT, Ops); } - // Rebuild memory operand because MemoryVT was changed - MachineMemOperand *MMO = DAG.getMachineFunction(). - getMachineMemOperand(N->getPointerInfo(), - MachineMemOperand::MOLoad, WidenVT.getStoreSize(), - N->getAlignment(), N->getAAInfo(), N->getRanges()); - SDValue Res = DAG.getMaskedLoad(WidenVT, dl, N->getChain(), N->getBasePtr(), - Mask, Src0, MMO); + Mask, Src0, N->getMemoryVT(), + N->getMemOperand(), ExtType); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); @@ -2593,6 +2594,7 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) { case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break; case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break; case ISD::STORE: Res = WidenVecOp_STORE(N); break; + case ISD::MSTORE: Res = WidenVecOp_MSTORE(N, OpNo); break; case ISD::SETCC: Res = WidenVecOp_SETCC(N); break; case ISD::ANY_EXTEND: @@ -2791,6 +2793,42 @@ SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) { return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain); } +SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) { + MaskedStoreSDNode *MST = cast(N); + SDValue Mask = MST->getMask(); + EVT MaskVT = Mask.getValueType(); + SDValue StVal = MST->getValue(); + // Widen the value + SDValue WideVal = GetWidenedVector(StVal); + SDLoc dl(N); + + if (OpNo == 2 || getTypeAction(MaskVT) == TargetLowering::TypeWidenVector) + Mask = GetWidenedVector(Mask); + else { + // The mask should be widened as well + EVT BoolVT = getSetCCResultType(WideVal.getValueType()); + // We can't use ModifyToType() because we should fill the mask with + // zeroes + unsigned WidenNumElts = BoolVT.getVectorNumElements(); + unsigned MaskNumElts = MaskVT.getVectorNumElements(); + + unsigned NumConcat = WidenNumElts / MaskNumElts; + SmallVector Ops(NumConcat); + SDValue ZeroVal = DAG.getConstant(0, MaskVT); + Ops[0] = Mask; + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = ZeroVal; + + Mask = DAG.getNode(ISD::CONCAT_VECTORS, dl, BoolVT, Ops); + } + assert(Mask.getValueType().getVectorNumElements() == + WideVal.getValueType().getVectorNumElements() && + "Mask and data vectors should have the same number of elements"); + return DAG.getMaskedStore(MST->getChain(), dl, WideVal, MST->getBasePtr(), + Mask, MST->getMemoryVT(), MST->getMemOperand(), + false); +} + SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) { SDValue InOp0 = GetWidenedVector(N->getOperand(0)); SDValue InOp1 = GetWidenedVector(N->getOperand(1)); diff --git a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index c819516eca..f75d5f4b2b 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4924,15 +4924,15 @@ SelectionDAG::getIndexedStore(SDValue OrigStore, SDLoc dl, SDValue Base, SDValue SelectionDAG::getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, - SDValue Ptr, SDValue Mask, SDValue Src0, - MachineMemOperand *MMO) { + SDValue Ptr, SDValue Mask, SDValue Src0, EVT MemVT, + MachineMemOperand *MMO, ISD::LoadExtType ExtTy) { SDVTList VTs = getVTList(VT, MVT::Other); SDValue Ops[] = { Chain, Ptr, Mask, Src0 }; FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::MLOAD, VTs, Ops); ID.AddInteger(VT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(ISD::NON_EXTLOAD, ISD::UNINDEXED, + ID.AddInteger(encodeMemSDNodeFlags(ExtTy, ISD::UNINDEXED, MMO->isVolatile(), MMO->isNonTemporal(), MMO->isInvariant())); @@ -4944,14 +4944,15 @@ SelectionDAG::getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, } SDNode *N = new (NodeAllocator) MaskedLoadSDNode(dl.getIROrder(), dl.getDebugLoc(), Ops, 4, VTs, - VT, MMO); + ExtTy, MemVT, MMO); CSEMap.InsertNode(N, IP); InsertNode(N); return SDValue(N, 0); } SDValue SelectionDAG::getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, - SDValue Ptr, SDValue Mask, MachineMemOperand *MMO) { + SDValue Ptr, SDValue Mask, EVT MemVT, + MachineMemOperand *MMO, bool isTrunc) { assert(Chain.getValueType() == MVT::Other && "Invalid chain type"); EVT VT = Val.getValueType(); @@ -4970,7 +4971,7 @@ SDValue SelectionDAG::getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, } SDNode *N = new (NodeAllocator) MaskedStoreSDNode(dl.getIROrder(), dl.getDebugLoc(), Ops, 4, - VTs, VT, MMO); + VTs, isTrunc, MemVT, MMO); CSEMap.InsertNode(N, IP); InsertNode(N); return SDValue(N, 0); diff --git a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 86a63eea7c..d1929107fc 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2071,14 +2071,10 @@ void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) { // Get the two live-in registers as SDValues. The physregs have already been // copied into virtual registers. SDValue Ops[2]; - if (FuncInfo.ExceptionPointerVirtReg) { - Ops[0] = DAG.getZExtOrTrunc( - DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), - FuncInfo.ExceptionPointerVirtReg, TLI.getPointerTy()), - getCurSDLoc(), ValueVTs[0]); - } else { - Ops[0] = DAG.getConstant(0, TLI.getPointerTy()); - } + Ops[0] = DAG.getZExtOrTrunc( + DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), + FuncInfo.ExceptionPointerVirtReg, TLI.getPointerTy()), + getCurSDLoc(), ValueVTs[0]); Ops[1] = DAG.getZExtOrTrunc( DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), FuncInfo.ExceptionSelectorVirtReg, TLI.getPointerTy()), @@ -2090,27 +2086,6 @@ void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) { setValue(&LP, Res); } -unsigned -SelectionDAGBuilder::visitLandingPadClauseBB(GlobalValue *ClauseGV, - MachineBasicBlock *LPadBB) { - SDValue Chain = getControlRoot(); - - // Get the typeid that we will dispatch on later. - const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy()); - unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC); - unsigned TypeID = DAG.getMachineFunction().getMMI().getTypeIDFor(ClauseGV); - SDValue Sel = DAG.getConstant(TypeID, TLI.getPointerTy()); - Chain = DAG.getCopyToReg(Chain, getCurSDLoc(), VReg, Sel); - - // Branch to the main landing pad block. - MachineBasicBlock *ClauseMBB = FuncInfo.MBB; - ClauseMBB->addSuccessor(LPadBB); - DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other, Chain, - DAG.getBasicBlock(LPadBB))); - return VReg; -} - /// handleSmallSwitchCaseRange - Emit a series of specific tests (suitable for /// small case ranges). bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, @@ -3692,7 +3667,8 @@ void SelectionDAGBuilder::visitMaskedStore(const CallInst &I) { getMachineMemOperand(MachinePointerInfo(PtrOperand), MachineMemOperand::MOStore, VT.getStoreSize(), Alignment, AAInfo); - SDValue StoreNode = DAG.getMaskedStore(getRoot(), sdl, Src0, Ptr, Mask, MMO); + SDValue StoreNode = DAG.getMaskedStore(getRoot(), sdl, Src0, Ptr, Mask, VT, + MMO, false); DAG.setRoot(StoreNode); setValue(&I, StoreNode); } @@ -3731,7 +3707,8 @@ void SelectionDAGBuilder::visitMaskedLoad(const CallInst &I) { MachineMemOperand::MOLoad, VT.getStoreSize(), Alignment, AAInfo, Ranges); - SDValue Load = DAG.getMaskedLoad(VT, sdl, InChain, Ptr, Mask, Src0, MMO); + SDValue Load = DAG.getMaskedLoad(VT, sdl, InChain, Ptr, Mask, Src0, VT, MMO, + ISD::NON_EXTLOAD); SDValue OutChain = Load.getValue(1); DAG.setRoot(OutChain); setValue(&I, Load); diff --git a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index eba98b8086..9070091d77 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -713,8 +713,6 @@ public: void visitJumpTable(JumpTable &JT); void visitJumpTableHeader(JumpTable &JT, JumpTableHeader &JTH, MachineBasicBlock *SwitchBB); - unsigned visitLandingPadClauseBB(GlobalValue *ClauseGV, - MachineBasicBlock *LPadMBB); private: // These all get lowered before this pass. diff --git a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 4f031d3ff7..ef5452554f 100644 --- a/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/src/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -19,7 +19,6 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/CFG.h" -#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/GCMetadata.h" @@ -41,7 +40,6 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -909,8 +907,6 @@ void SelectionDAGISel::DoInstructionSelection() { void SelectionDAGISel::PrepareEHLandingPad() { MachineBasicBlock *MBB = FuncInfo->MBB; - const TargetRegisterClass *PtrRC = TLI->getRegClassFor(TLI->getPointerTy()); - // Add a label to mark the beginning of the landing pad. Deletion of the // landing pad can thus be detected via the MachineModuleInfo. MCSymbol *Label = MF->getMMI().addLandingPad(MBB); @@ -922,66 +918,8 @@ void SelectionDAGISel::PrepareEHLandingPad() { BuildMI(*MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) .addSym(Label); - if (TM.getMCAsmInfo()->getExceptionHandlingType() == - ExceptionHandling::MSVC) { - // Make virtual registers and a series of labels that fill in values for the - // clauses. - auto &RI = MF->getRegInfo(); - FuncInfo->ExceptionSelectorVirtReg = RI.createVirtualRegister(PtrRC); - - // Get all invoke BBs that will unwind into the clause BBs. - SmallVector InvokeBBs(MBB->pred_begin(), - MBB->pred_end()); - - // Emit separate machine basic blocks with separate labels for each clause - // before the main landing pad block. - const BasicBlock *LLVMBB = MBB->getBasicBlock(); - const LandingPadInst *LPadInst = LLVMBB->getLandingPadInst(); - MachineInstrBuilder SelectorPHI = BuildMI( - *MBB, MBB->begin(), SDB->getCurDebugLoc(), TII->get(TargetOpcode::PHI), - FuncInfo->ExceptionSelectorVirtReg); - for (unsigned I = 0, E = LPadInst->getNumClauses(); I != E; ++I) { - MachineBasicBlock *ClauseBB = MF->CreateMachineBasicBlock(LLVMBB); - MF->insert(MBB, ClauseBB); - - // Add the edge from the invoke to the clause. - for (MachineBasicBlock *InvokeBB : InvokeBBs) - InvokeBB->addSuccessor(ClauseBB); - - // Mark the clause as a landing pad or MI passes will delete it. - ClauseBB->setIsLandingPad(); - - GlobalValue *ClauseGV = ExtractTypeInfo(LPadInst->getClause(I)); - - // Start the BB with a label. - MCSymbol *ClauseLabel = MF->getMMI().addClauseForLandingPad(MBB); - BuildMI(*ClauseBB, ClauseBB->begin(), SDB->getCurDebugLoc(), II) - .addSym(ClauseLabel); - - // Construct a simple BB that defines a register with the typeid constant. - FuncInfo->MBB = ClauseBB; - FuncInfo->InsertPt = ClauseBB->end(); - unsigned VReg = SDB->visitLandingPadClauseBB(ClauseGV, MBB); - CurDAG->setRoot(SDB->getRoot()); - SDB->clear(); - CodeGenAndEmitDAG(); - - // Add the typeid virtual register to the phi in the main landing pad. - SelectorPHI.addReg(VReg).addMBB(ClauseBB); - } - - // Remove the edge from the invoke to the lpad. - for (MachineBasicBlock *InvokeBB : InvokeBBs) - InvokeBB->removeSuccessor(MBB); - - // Restore FuncInfo back to its previous state and select the main landing - // pad block. - FuncInfo->MBB = MBB; - FuncInfo->InsertPt = MBB->end(); - return; - } - // Mark exception register as live in. + const TargetRegisterClass *PtrRC = TLI->getRegClassFor(TLI->getPointerTy()); if (unsigned Reg = TLI->getExceptionPointerRegister()) FuncInfo->ExceptionPointerVirtReg = MBB->addLiveIn(Reg, PtrRC); diff --git a/src/llvm/lib/ExecutionEngine/CMakeLists.txt b/src/llvm/lib/ExecutionEngine/CMakeLists.txt index dc2fe9bf97..83c91eda04 100644 --- a/src/llvm/lib/ExecutionEngine/CMakeLists.txt +++ b/src/llvm/lib/ExecutionEngine/CMakeLists.txt @@ -4,7 +4,6 @@ add_llvm_library(LLVMExecutionEngine ExecutionEngine.cpp ExecutionEngineBindings.cpp GDBRegistrationListener.cpp - RTDyldMemoryManager.cpp TargetSelect.cpp ) diff --git a/src/llvm/lib/ExecutionEngine/LLVMBuild.txt b/src/llvm/lib/ExecutionEngine/LLVMBuild.txt index 7d041cef84..53d62649c5 100644 --- a/src/llvm/lib/ExecutionEngine/LLVMBuild.txt +++ b/src/llvm/lib/ExecutionEngine/LLVMBuild.txt @@ -22,4 +22,4 @@ subdirectories = Interpreter MCJIT RuntimeDyld IntelJITEvents OProfileJIT type = Library name = ExecutionEngine parent = Libraries -required_libraries = Core MC Object Support +required_libraries = Core MC Object Support RuntimeDyld diff --git a/src/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/src/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt index 5790eee9c8..12bbcc61db 100644 --- a/src/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt +++ b/src/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMRuntimeDyld + RTDyldMemoryManager.cpp RuntimeDyld.cpp RuntimeDyldChecker.cpp RuntimeDyldELF.cpp diff --git a/src/llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp b/src/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp similarity index 100% rename from src/llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp rename to src/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp diff --git a/src/llvm/lib/IR/Constants.cpp b/src/llvm/lib/IR/Constants.cpp index 1d2602aef1..44052b2245 100644 --- a/src/llvm/lib/IR/Constants.cpp +++ b/src/llvm/lib/IR/Constants.cpp @@ -257,11 +257,11 @@ Constant *Constant::getAggregateElement(unsigned Elt) const { if (const ConstantVector *CV = dyn_cast(this)) return Elt < CV->getNumOperands() ? CV->getOperand(Elt) : nullptr; - if (const ConstantAggregateZero *CAZ =dyn_cast(this)) - return CAZ->getElementValue(Elt); + if (const ConstantAggregateZero *CAZ = dyn_cast(this)) + return Elt < CAZ->getNumElements() ? CAZ->getElementValue(Elt) : nullptr; if (const UndefValue *UV = dyn_cast(this)) - return UV->getElementValue(Elt); + return Elt < UV->getNumElements() ? UV->getElementValue(Elt) : nullptr; if (const ConstantDataSequential *CDS =dyn_cast(this)) return Elt < CDS->getNumElements() ? CDS->getElementAsConstant(Elt) @@ -764,6 +764,14 @@ Constant *ConstantAggregateZero::getElementValue(unsigned Idx) const { return getStructElement(Idx); } +unsigned ConstantAggregateZero::getNumElements() const { + const Type *Ty = getType(); + if (const auto *AT = dyn_cast(Ty)) + return AT->getNumElements(); + if (const auto *VT = dyn_cast(Ty)) + return VT->getNumElements(); + return Ty->getStructNumElements(); +} //===----------------------------------------------------------------------===// // UndefValue Implementation @@ -797,7 +805,14 @@ UndefValue *UndefValue::getElementValue(unsigned Idx) const { return getStructElement(Idx); } - +unsigned UndefValue::getNumElements() const { + const Type *Ty = getType(); + if (const auto *AT = dyn_cast(Ty)) + return AT->getNumElements(); + if (const auto *VT = dyn_cast(Ty)) + return VT->getNumElements(); + return Ty->getStructNumElements(); +} //===----------------------------------------------------------------------===// // ConstantXXX Classes diff --git a/src/llvm/lib/IR/DebugInfo.cpp b/src/llvm/lib/IR/DebugInfo.cpp index 290dbe29c7..71b43942e8 100644 --- a/src/llvm/lib/IR/DebugInfo.cpp +++ b/src/llvm/lib/IR/DebugInfo.cpp @@ -525,12 +525,15 @@ bool DISubprogram::Verify() const { while ((IA = DL.getInlinedAt())) DL = DebugLoc::getFromDILocation(IA); DL.getScopeAndInlinedAt(Scope, IA); + if (!Scope) + return false; assert(!IA); while (!DIDescriptor(Scope).isSubprogram()) { DILexicalBlockFile D(Scope); Scope = D.isLexicalBlockFile() ? D.getScope() : DebugLoc::getFromDILexicalBlock(Scope).getScope(); + assert(Scope && "lexical block file has no scope"); } if (!DISubprogram(Scope).describes(F)) return false; diff --git a/src/llvm/lib/IR/Type.cpp b/src/llvm/lib/IR/Type.cpp index 889705e95f..65060dc39d 100644 --- a/src/llvm/lib/IR/Type.cpp +++ b/src/llvm/lib/IR/Type.cpp @@ -708,9 +708,10 @@ VectorType::VectorType(Type *ElType, unsigned NumEl) VectorType *VectorType::get(Type *elementType, unsigned NumElements) { Type *ElementType = const_cast(elementType); assert(NumElements > 0 && "#Elements of a VectorType must be greater than 0"); - assert(isValidElementType(ElementType) && - "Elements of a VectorType must be a primitive type"); - + assert(isValidElementType(ElementType) && "Element type of a VectorType must " + "be an integer, floating point, or " + "pointer type."); + LLVMContextImpl *pImpl = ElementType->getContext().pImpl; VectorType *&Entry = ElementType->getContext().pImpl ->VectorTypes[std::make_pair(ElementType, NumElements)]; diff --git a/src/llvm/lib/MC/WinCOFFObjectWriter.cpp b/src/llvm/lib/MC/WinCOFFObjectWriter.cpp index c17f99b9bd..ec0e0f7256 100644 --- a/src/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/src/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -710,17 +710,22 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, CrossSection = &Symbol.getSection() != &B->getSection(); // Offset of the symbol in the section - int64_t a = Layout.getSymbolOffset(&B_SD); + int64_t OffsetOfB = Layout.getSymbolOffset(&B_SD); - // Offset of the relocation in the section - int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); - - FixedValue = b - a; // In the case where we have SymbA and SymB, we just need to store the delta // between the two symbols. Update FixedValue to account for the delta, and // skip recording the relocation. - if (!CrossSection) + if (!CrossSection) { + int64_t OffsetOfA = Layout.getSymbolOffset(&A_SD); + FixedValue = (OffsetOfA - OffsetOfB) + Target.getConstant(); return; + } + + // Offset of the relocation in the section + int64_t OffsetOfRelocation = + Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + + FixedValue = OffsetOfRelocation - OffsetOfB; } else { FixedValue = Target.getConstant(); } diff --git a/src/llvm/lib/Target/TargetLibraryInfo.cpp b/src/llvm/lib/Target/TargetLibraryInfo.cpp index c0abdbd927..4df8092e9b 100644 --- a/src/llvm/lib/Target/TargetLibraryInfo.cpp +++ b/src/llvm/lib/Target/TargetLibraryInfo.cpp @@ -198,6 +198,8 @@ const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] = "iprintf", "isascii", "isdigit", + "je_mallocx", + "je_sdallocx", "labs", "lchown", "ldexp", diff --git a/src/llvm/lib/Target/X86/X86ISelLowering.cpp b/src/llvm/lib/Target/X86/X86ISelLowering.cpp index a1fd34ea80..177299b8af 100644 --- a/src/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/src/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -1679,7 +1679,9 @@ void X86TargetLowering::resetOperationActions() { setTargetDAGCombine(ISD::FMA); setTargetDAGCombine(ISD::SUB); setTargetDAGCombine(ISD::LOAD); + setTargetDAGCombine(ISD::MLOAD); setTargetDAGCombine(ISD::STORE); + setTargetDAGCombine(ISD::MSTORE); setTargetDAGCombine(ISD::ZERO_EXTEND); setTargetDAGCombine(ISD::ANY_EXTEND); setTargetDAGCombine(ISD::SIGN_EXTEND); @@ -5473,6 +5475,8 @@ static bool getTargetShuffleMask(SDNode *N, MVT VT, if (auto *C = dyn_cast(MaskCP->getConstVal())) { DecodePSHUFBMask(C, Mask); + if (Mask.empty()) + return false; break; } @@ -24736,6 +24740,166 @@ static SDValue PerformLOADCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } +/// PerformMLOADCombine - Resolve extending loads +static SDValue PerformMLOADCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const X86Subtarget *Subtarget) { + MaskedLoadSDNode *Mld = cast(N); + if (Mld->getExtensionType() != ISD::SEXTLOAD) + return SDValue(); + + EVT VT = Mld->getValueType(0); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned NumElems = VT.getVectorNumElements(); + EVT LdVT = Mld->getMemoryVT(); + SDLoc dl(Mld); + + assert(LdVT != VT && "Cannot extend to the same type"); + unsigned ToSz = VT.getVectorElementType().getSizeInBits(); + unsigned FromSz = LdVT.getVectorElementType().getSizeInBits(); + // From, To sizes and ElemCount must be pow of two + assert (isPowerOf2_32(NumElems * FromSz * ToSz) && + "Unexpected size for extending masked load"); + + unsigned SizeRatio = ToSz / FromSz; + assert(SizeRatio * NumElems * FromSz == VT.getSizeInBits()); + + // Create a type on which we perform the shuffle + EVT WideVecVT = EVT::getVectorVT(*DAG.getContext(), + LdVT.getScalarType(), NumElems*SizeRatio); + assert(WideVecVT.getSizeInBits() == VT.getSizeInBits()); + + // Convert Src0 value + SDValue WideSrc0 = DAG.getNode(ISD::BITCAST, dl, WideVecVT, Mld->getSrc0()); + if (Mld->getSrc0().getOpcode() != ISD::UNDEF) { + SmallVector ShuffleVec(NumElems * SizeRatio, -1); + for (unsigned i = 0; i != NumElems; ++i) + ShuffleVec[i] = i * SizeRatio; + + // Can't shuffle using an illegal type. + assert (TLI.isTypeLegal(WideVecVT) && "WideVecVT should be legal"); + WideSrc0 = DAG.getVectorShuffle(WideVecVT, dl, WideSrc0, + DAG.getUNDEF(WideVecVT), &ShuffleVec[0]); + } + // Prepare the new mask + SDValue NewMask; + SDValue Mask = Mld->getMask(); + if (Mask.getValueType() == VT) { + // Mask and original value have the same type + NewMask = DAG.getNode(ISD::BITCAST, dl, WideVecVT, Mask); + SmallVector ShuffleVec(NumElems * SizeRatio, -1); + for (unsigned i = 0; i != NumElems; ++i) + ShuffleVec[i] = i * SizeRatio; + for (unsigned i = NumElems; i != NumElems*SizeRatio; ++i) + ShuffleVec[i] = NumElems*SizeRatio; + NewMask = DAG.getVectorShuffle(WideVecVT, dl, NewMask, + DAG.getConstant(0, WideVecVT), + &ShuffleVec[0]); + } + else { + assert(Mask.getValueType().getVectorElementType() == MVT::i1); + unsigned WidenNumElts = NumElems*SizeRatio; + unsigned MaskNumElts = VT.getVectorNumElements(); + EVT NewMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, + WidenNumElts); + + unsigned NumConcat = WidenNumElts / MaskNumElts; + SmallVector Ops(NumConcat); + SDValue ZeroVal = DAG.getConstant(0, Mask.getValueType()); + Ops[0] = Mask; + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = ZeroVal; + + NewMask = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewMaskVT, Ops); + } + + SDValue WideLd = DAG.getMaskedLoad(WideVecVT, dl, Mld->getChain(), + Mld->getBasePtr(), NewMask, WideSrc0, + Mld->getMemoryVT(), Mld->getMemOperand(), + ISD::NON_EXTLOAD); + SDValue NewVec = DAG.getNode(X86ISD::VSEXT, dl, VT, WideLd); + return DCI.CombineTo(N, NewVec, WideLd.getValue(1), true); + +} +/// PerformMSTORECombine - Resolve truncating stores +static SDValue PerformMSTORECombine(SDNode *N, SelectionDAG &DAG, + const X86Subtarget *Subtarget) { + MaskedStoreSDNode *Mst = cast(N); + if (!Mst->isTruncatingStore()) + return SDValue(); + + EVT VT = Mst->getValue().getValueType(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned NumElems = VT.getVectorNumElements(); + EVT StVT = Mst->getMemoryVT(); + SDLoc dl(Mst); + + assert(StVT != VT && "Cannot truncate to the same type"); + unsigned FromSz = VT.getVectorElementType().getSizeInBits(); + unsigned ToSz = StVT.getVectorElementType().getSizeInBits(); + + // From, To sizes and ElemCount must be pow of two + assert (isPowerOf2_32(NumElems * FromSz * ToSz) && + "Unexpected size for truncating masked store"); + // We are going to use the original vector elt for storing. + // Accumulated smaller vector elements must be a multiple of the store size. + assert (((NumElems * FromSz) % ToSz) == 0 && + "Unexpected ratio for truncating masked store"); + + unsigned SizeRatio = FromSz / ToSz; + assert(SizeRatio * NumElems * ToSz == VT.getSizeInBits()); + + // Create a type on which we perform the shuffle + EVT WideVecVT = EVT::getVectorVT(*DAG.getContext(), + StVT.getScalarType(), NumElems*SizeRatio); + + assert(WideVecVT.getSizeInBits() == VT.getSizeInBits()); + + SDValue WideVec = DAG.getNode(ISD::BITCAST, dl, WideVecVT, Mst->getValue()); + SmallVector ShuffleVec(NumElems * SizeRatio, -1); + for (unsigned i = 0; i != NumElems; ++i) + ShuffleVec[i] = i * SizeRatio; + + // Can't shuffle using an illegal type. + assert (TLI.isTypeLegal(WideVecVT) && "WideVecVT should be legal"); + + SDValue TruncatedVal = DAG.getVectorShuffle(WideVecVT, dl, WideVec, + DAG.getUNDEF(WideVecVT), + &ShuffleVec[0]); + + SDValue NewMask; + SDValue Mask = Mst->getMask(); + if (Mask.getValueType() == VT) { + // Mask and original value have the same type + NewMask = DAG.getNode(ISD::BITCAST, dl, WideVecVT, Mask); + for (unsigned i = 0; i != NumElems; ++i) + ShuffleVec[i] = i * SizeRatio; + for (unsigned i = NumElems; i != NumElems*SizeRatio; ++i) + ShuffleVec[i] = NumElems*SizeRatio; + NewMask = DAG.getVectorShuffle(WideVecVT, dl, NewMask, + DAG.getConstant(0, WideVecVT), + &ShuffleVec[0]); + } + else { + assert(Mask.getValueType().getVectorElementType() == MVT::i1); + unsigned WidenNumElts = NumElems*SizeRatio; + unsigned MaskNumElts = VT.getVectorNumElements(); + EVT NewMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, + WidenNumElts); + + unsigned NumConcat = WidenNumElts / MaskNumElts; + SmallVector Ops(NumConcat); + SDValue ZeroVal = DAG.getConstant(0, Mask.getValueType()); + Ops[0] = Mask; + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = ZeroVal; + + NewMask = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewMaskVT, Ops); + } + + return DAG.getMaskedStore(Mst->getChain(), dl, TruncatedVal, Mst->getBasePtr(), + NewMask, StVT, Mst->getMemOperand(), false); +} /// PerformSTORECombine - Do target-specific dag combines on STORE nodes. static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, const X86Subtarget *Subtarget) { @@ -25834,7 +25998,9 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, case ISD::OR: return PerformOrCombine(N, DAG, DCI, Subtarget); case ISD::XOR: return PerformXorCombine(N, DAG, DCI, Subtarget); case ISD::LOAD: return PerformLOADCombine(N, DAG, DCI, Subtarget); + case ISD::MLOAD: return PerformMLOADCombine(N, DAG, DCI, Subtarget); case ISD::STORE: return PerformSTORECombine(N, DAG, Subtarget); + case ISD::MSTORE: return PerformMSTORECombine(N, DAG, Subtarget); case ISD::SINT_TO_FP: return PerformSINT_TO_FPCombine(N, DAG, this); case ISD::FADD: return PerformFADDCombine(N, DAG, Subtarget); case ISD::FSUB: return PerformFSUBCombine(N, DAG, Subtarget); diff --git a/src/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/src/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index af1694d345..6230c000cf 100644 --- a/src/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/src/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -330,11 +330,17 @@ static LoadInst *combineLoadToNewType(InstCombiner &IC, LoadInst &LI, Type *NewT case LLVMContext::MD_noalias: case LLVMContext::MD_nontemporal: case LLVMContext::MD_mem_parallel_loop_access: - case LLVMContext::MD_nonnull: // All of these directly apply. NewLoad->setMetadata(ID, N); break; + case LLVMContext::MD_nonnull: + // FIXME: We should translate this into range metadata for integer types + // and vice versa. + if (NewTy->isPointerTy()) + NewLoad->setMetadata(ID, N); + break; + case LLVMContext::MD_range: // FIXME: It would be nice to propagate this in some way, but the type // conversions make it hard. @@ -548,13 +554,14 @@ static bool combineStoreToValueType(InstCombiner &IC, StoreInst &SI) { case LLVMContext::MD_noalias: case LLVMContext::MD_nontemporal: case LLVMContext::MD_mem_parallel_loop_access: - case LLVMContext::MD_nonnull: // All of these directly apply. NewStore->setMetadata(ID, N); break; case LLVMContext::MD_invariant_load: + case LLVMContext::MD_nonnull: case LLVMContext::MD_range: + // These don't apply for stores. break; } } diff --git a/src/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/src/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index 5f73b89e85..2a3d15421d 100644 --- a/src/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/src/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -71,9 +71,17 @@ private: return isMachO() ? "__DATA,__llvm_prf_data" : "__llvm_prf_data"; } + /// Get the section name for the coverage mapping data. + StringRef getCoverageSection() const { + return isMachO() ? "__DATA,__llvm_covmap" : "__llvm_covmap"; + } + /// Replace instrprof_increment with an increment of the appropriate value. void lowerIncrement(InstrProfIncrementInst *Inc); + /// Set up the section and uses for coverage data and its references. + void lowerCoverageData(GlobalVariable *CoverageData); + /// Get the region counters for an increment, creating them if necessary. /// /// If the counter array doesn't yet exist, the profile data variables @@ -118,6 +126,10 @@ bool InstrProfiling::runOnModule(Module &M) { lowerIncrement(Inc); MadeChange = true; } + if (GlobalVariable *Coverage = M.getNamedGlobal("__llvm_coverage_mapping")) { + lowerCoverageData(Coverage); + MadeChange = true; + } if (!MadeChange) return false; @@ -140,6 +152,35 @@ void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { Inc->eraseFromParent(); } +void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageData) { + CoverageData->setSection(getCoverageSection()); + CoverageData->setAlignment(8); + + Constant *Init = CoverageData->getInitializer(); + // We're expecting { i32, i32, i32, i32, [n x { i8*, i32, i32 }], [m x i8] } + // for some C. If not, the frontend's given us something broken. + assert(Init->getNumOperands() == 6 && "bad number of fields in coverage map"); + assert(isa(Init->getAggregateElement(4)) && + "invalid function list in coverage map"); + ConstantArray *Records = cast(Init->getAggregateElement(4)); + for (unsigned I = 0, E = Records->getNumOperands(); I < E; ++I) { + Constant *Record = Records->getOperand(I); + Value *V = const_cast(Record->getOperand(0))->stripPointerCasts(); + + assert(isa(V) && "Missing reference to function name"); + GlobalVariable *Name = cast(V); + + // If we have region counters for this name, we've already handled it. + auto It = RegionCounters.find(Name); + if (It != RegionCounters.end()) + continue; + + // Move the name variable to the right section. + Name->setSection(getNameSection()); + Name->setAlignment(1); + } +} + /// Get the name of a profiling variable for a particular function. static std::string getVarName(InstrProfIncrementInst *Inc, StringRef VarName) { auto *Arr = cast(Inc->getName()->getInitializer()); diff --git a/src/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/src/llvm/lib/Transforms/Scalar/EarlyCSE.cpp index 394b0d3de7..969b9a8f8d 100644 --- a/src/llvm/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/src/llvm/lib/Transforms/Scalar/EarlyCSE.cpp @@ -480,6 +480,9 @@ bool EarlyCSE::processNode(DomTreeNode *Node) { // Ignore volatile loads. if (!LI->isSimple()) { LastStore = nullptr; + // Don't CSE across synchronization boundaries. + if (Inst->mayWriteToMemory()) + ++CurrentGeneration; continue; } diff --git a/src/llvm/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp b/src/llvm/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp index 8509713b33..1f73cbc4ac 100644 --- a/src/llvm/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp +++ b/src/llvm/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp @@ -403,7 +403,7 @@ bool MergedLoadStoreMotion::isStoreSinkBarrierInRange(const Instruction& Start, const Instruction& End, AliasAnalysis::Location Loc) { - return AA->canInstructionRangeModRef(Start, End, Loc, AliasAnalysis::Ref); + return AA->canInstructionRangeModRef(Start, End, Loc, AliasAnalysis::ModRef); } /// @@ -414,6 +414,7 @@ bool MergedLoadStoreMotion::isStoreSinkBarrierInRange(const Instruction& Start, StoreInst *MergedLoadStoreMotion::canSinkFromBlock(BasicBlock *BB1, StoreInst *Store0) { DEBUG(dbgs() << "can Sink? : "; Store0->dump(); dbgs() << "\n"); + BasicBlock *BB0 = Store0->getParent(); for (BasicBlock::reverse_iterator RBI = BB1->rbegin(), RBE = BB1->rend(); RBI != RBE; ++RBI) { Instruction *Inst = &*RBI; @@ -422,13 +423,14 @@ StoreInst *MergedLoadStoreMotion::canSinkFromBlock(BasicBlock *BB1, continue; StoreInst *Store1 = cast(Inst); - BasicBlock *BB0 = Store0->getParent(); AliasAnalysis::Location Loc0 = AA->getLocation(Store0); AliasAnalysis::Location Loc1 = AA->getLocation(Store1); if (AA->isMustAlias(Loc0, Loc1) && Store0->isSameOperationAs(Store1) && - !isStoreSinkBarrierInRange(*Store1, BB1->back(), Loc1) && - !isStoreSinkBarrierInRange(*Store0, BB0->back(), Loc0)) { + !isStoreSinkBarrierInRange(*(std::next(BasicBlock::iterator(Store1))), + BB1->back(), Loc1) && + !isStoreSinkBarrierInRange(*(std::next(BasicBlock::iterator(Store0))), + BB0->back(), Loc0)) { return Store1; } } diff --git a/src/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/src/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp index f12cd61d46..8a32215a29 100644 --- a/src/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ b/src/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -55,7 +55,7 @@ STATISTIC(NumRuntimeUnrolled, /// - Branch around the original loop if the trip count is less /// than the unroll factor. /// -static void ConnectProlog(Loop *L, Value *TripCount, unsigned Count, +static void ConnectProlog(Loop *L, Value *BECount, unsigned Count, BasicBlock *LastPrologBB, BasicBlock *PrologEnd, BasicBlock *OrigPH, BasicBlock *NewPH, ValueToValueMapTy &VMap, Pass *P) { @@ -105,12 +105,19 @@ static void ConnectProlog(Loop *L, Value *TripCount, unsigned Count, } } - // Create a branch around the orignal loop, which is taken if the - // trip count is less than the unroll factor. + // Create a branch around the orignal loop, which is taken if there are no + // iterations remaining to be executed after running the prologue. Instruction *InsertPt = PrologEnd->getTerminator(); + + assert(Count != 0 && "nonsensical Count!"); + + // If BECount getType(), Count)); + new ICmpInst(InsertPt, ICmpInst::ICMP_ULT, BECount, + ConstantInt::get(BECount->getType(), Count - 1)); BasicBlock *Exit = L->getUniqueExitBlock(); assert(Exit && "Loop must have a single exit block only"); // Split the exit to maintain loop canonicalization guarantees @@ -292,23 +299,28 @@ bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, // Only unroll loops with a computable trip count and the trip count needs // to be an int value (allowing a pointer type is a TODO item) - const SCEV *BECount = SE->getBackedgeTakenCount(L); - if (isa(BECount) || !BECount->getType()->isIntegerTy()) + const SCEV *BECountSC = SE->getBackedgeTakenCount(L); + if (isa(BECountSC) || + !BECountSC->getType()->isIntegerTy()) return false; - // If BECount is INT_MAX, we can't compute trip-count without overflow. - if (BECount->isAllOnesValue()) - return false; + unsigned BEWidth = cast(BECountSC->getType())->getBitWidth(); // Add 1 since the backedge count doesn't include the first loop iteration const SCEV *TripCountSC = - SE->getAddExpr(BECount, SE->getConstant(BECount->getType(), 1)); + SE->getAddExpr(BECountSC, SE->getConstant(BECountSC->getType(), 1)); if (isa(TripCountSC)) return false; // We only handle cases when the unroll factor is a power of 2. // Count is the loop unroll factor, the number of extra copies added + 1. - if ((Count & (Count-1)) != 0) + if (!isPowerOf2_32(Count)) + return false; + + // This constraint lets us deal with an overflowing trip count easily; see the + // comment on ModVal below. This check is equivalent to `Log2(Count) < + // BEWidth`. + if (static_cast(Count) > (1ULL << BEWidth)) return false; // If this loop is nested, then the loop unroller changes the code in @@ -330,16 +342,23 @@ bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, SCEVExpander Expander(*SE, "loop-unroll"); Value *TripCount = Expander.expandCodeFor(TripCountSC, TripCountSC->getType(), PreHeaderBR); + Value *BECount = Expander.expandCodeFor(BECountSC, BECountSC->getType(), + PreHeaderBR); IRBuilder<> B(PreHeaderBR); Value *ModVal = B.CreateAnd(TripCount, Count - 1, "xtraiter"); - // Check if for no extra iterations, then jump to cloned/unrolled loop. - // We have to check that the trip count computation didn't overflow when - // adding one to the backedge taken count. - Value *LCmp = B.CreateIsNotNull(ModVal, "lcmp.mod"); - Value *OverflowCheck = B.CreateIsNull(TripCount, "lcmp.overflow"); - Value *BranchVal = B.CreateOr(OverflowCheck, LCmp, "lcmp.or"); + // If ModVal is zero, we know that either + // 1. there are no iteration to be run in the prologue loop + // OR + // 2. the addition computing TripCount overflowed + // + // If (2) is true, we know that TripCount really is (1 << BEWidth) and so the + // number of iterations that remain to be run in the original loop is a + // multiple Count == (1 << Log2(Count)) because Log2(Count) <= BEWidth (we + // explicitly check this above). + + Value *BranchVal = B.CreateIsNotNull(ModVal, "lcmp.mod"); // Branch to either the extra iterations or the cloned/unrolled loop // We will fix up the true branch label when adding loop body copies @@ -362,10 +381,7 @@ bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, std::vector NewBlocks; ValueToValueMapTy VMap; - // If unroll count is 2 and we can't overflow in tripcount computation (which - // is BECount + 1), then we don't need a loop for prologue, and we can unroll - // it. We can be sure that we don't overflow only if tripcount is a constant. - bool UnrollPrologue = (Count == 2 && isa(TripCount)); + bool UnrollPrologue = Count == 2; // Clone all the basic blocks in the loop. If Count is 2, we don't clone // the loop, otherwise we create a cloned loop to execute the extra @@ -391,7 +407,7 @@ bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, // Connect the prolog code to the original loop and update the // PHI functions. BasicBlock *LastLoopBB = cast(VMap[Latch]); - ConnectProlog(L, TripCount, Count, LastLoopBB, PEnd, PH, NewPH, VMap, + ConnectProlog(L, BECount, Count, LastLoopBB, PEnd, PH, NewPH, VMap, LPM->getAsPass()); NumRuntimeUnrolled++; return true; diff --git a/src/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/src/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 557304ed56..47b92a37cf 100644 --- a/src/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/src/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1874,6 +1874,7 @@ void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr) { // wide store needs to start at the last vector element. PartPtr = Builder.CreateGEP(Ptr, Builder.getInt32(-Part * VF)); PartPtr = Builder.CreateGEP(PartPtr, Builder.getInt32(1 - VF)); + Mask[Part] = reverseVector(Mask[Part]); } Value *VecPtr = Builder.CreateBitCast(PartPtr, @@ -1902,6 +1903,7 @@ void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr) { // wide load needs to start at the last vector element. PartPtr = Builder.CreateGEP(Ptr, Builder.getInt32(-Part * VF)); PartPtr = Builder.CreateGEP(PartPtr, Builder.getInt32(1 - VF)); + Mask[Part] = reverseVector(Mask[Part]); } Instruction* NewLI; diff --git a/src/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/src/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 2213031ecd..bd8a4b3fd3 100644 --- a/src/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/src/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -75,6 +75,18 @@ static const unsigned MinVecRegSize = 128; static const unsigned RecursionMaxDepth = 12; +/// \brief Predicate for the element types that the SLP vectorizer supports. +/// +/// The most important thing to filter here are types which are invalid in LLVM +/// vectors. We also filter target specific types which have absolutely no +/// meaningful vectorization path such as x86_fp80 and ppc_f128. This just +/// avoids spending time checking the cost model and realizing that they will +/// be inevitably scalarized. +static bool isValidElementType(Type *Ty) { + return VectorType::isValidElementType(Ty) && !Ty->isX86_FP80Ty() && + !Ty->isPPC_FP128Ty(); +} + /// \returns the parent basic block if all of the instructions in \p VL /// are in the same block or null otherwise. static BasicBlock *getSameBlock(ArrayRef VL) { @@ -1216,7 +1228,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth) { Type *SrcTy = VL0->getOperand(0)->getType(); for (unsigned i = 0; i < VL.size(); ++i) { Type *Ty = cast(VL[i])->getOperand(0)->getType(); - if (Ty != SrcTy || Ty->isAggregateType() || Ty->isVectorTy()) { + if (Ty != SrcTy || !isValidElementType(Ty)) { BS.cancelScheduling(VL); newTreeEntry(VL, false); DEBUG(dbgs() << "SLP: Gathering casts with different src types.\n"); @@ -3130,7 +3142,7 @@ unsigned SLPVectorizer::collectStores(BasicBlock *BB, BoUpSLP &R) { // Check that the pointer points to scalars. Type *Ty = SI->getValueOperand()->getType(); - if (Ty->isAggregateType() || Ty->isVectorTy()) + if (!isValidElementType(Ty)) continue; // Find the base pointer. @@ -3171,7 +3183,7 @@ bool SLPVectorizer::tryToVectorizeList(ArrayRef VL, BoUpSLP &R, for (int i = 0, e = VL.size(); i < e; ++i) { Type *Ty = VL[i]->getType(); - if (Ty->isAggregateType() || Ty->isVectorTy()) + if (!isValidElementType(Ty)) return false; Instruction *Inst = dyn_cast(VL[i]); if (!Inst || Inst->getOpcode() != Opcode0) @@ -3391,7 +3403,7 @@ public: return false; Type *Ty = B->getType(); - if (Ty->isVectorTy()) + if (!isValidElementType(Ty)) return false; ReductionOpcode = B->getOpcode(); diff --git a/src/llvm/tools/gold/gold-plugin.cpp b/src/llvm/tools/gold/gold-plugin.cpp index 5524bb9922..a9909a721c 100644 --- a/src/llvm/tools/gold/gold-plugin.cpp +++ b/src/llvm/tools/gold/gold-plugin.cpp @@ -559,11 +559,9 @@ static void freeSymName(ld_plugin_symbol &Sym) { } static std::unique_ptr -getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile, +getModuleForFile(LLVMContext &Context, claimed_file &F, + off_t Filesize, raw_fd_ostream *ApiFile, StringSet<> &Internalize, StringSet<> &Maybe) { - ld_plugin_input_file File; - if (get_input_file(F.handle, &File) != LDPS_OK) - message(LDPL_FATAL, "Failed to get file information"); if (get_symbols(F.handle, F.syms.size(), &F.syms[0]) != LDPS_OK) message(LDPL_FATAL, "Failed to get symbol information"); @@ -572,7 +570,7 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile, if (get_view(F.handle, &View) != LDPS_OK) message(LDPL_FATAL, "Failed to get a view of file"); - MemoryBufferRef BufferRef(StringRef((const char *)View, File.filesize), ""); + MemoryBufferRef BufferRef(StringRef((const char *)View, Filesize), ""); ErrorOr> ObjOrErr = object::IRObjectFile::create(BufferRef, Context); @@ -580,9 +578,6 @@ getModuleForFile(LLVMContext &Context, claimed_file &F, raw_fd_ostream *ApiFile, message(LDPL_FATAL, "Could not read bitcode from file : %s", EC.message().c_str()); - if (release_input_file(F.handle) != LDPS_OK) - message(LDPL_FATAL, "Failed to release file information"); - object::IRObjectFile &Obj = **ObjOrErr; Module &M = Obj.getModule(); @@ -798,8 +793,12 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) { StringSet<> Internalize; StringSet<> Maybe; for (claimed_file &F : Modules) { + ld_plugin_input_file File; + if (get_input_file(F.handle, &File) != LDPS_OK) + message(LDPL_FATAL, "Failed to get file information"); std::unique_ptr M = - getModuleForFile(Context, F, ApiFile, Internalize, Maybe); + getModuleForFile(Context, F, File.filesize, ApiFile, + Internalize, Maybe); if (!options::triple.empty()) M->setTargetTriple(options::triple.c_str()); else if (M->getTargetTriple().empty()) { @@ -808,6 +807,8 @@ static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) { if (L.linkInModule(M.get())) message(LDPL_FATAL, "Failed to link module"); + if (release_input_file(F.handle) != LDPS_OK) + message(LDPL_FATAL, "Failed to release file information"); } for (const auto &Name : Internalize) { diff --git a/src/llvm/tools/lli/CMakeLists.txt b/src/llvm/tools/lli/CMakeLists.txt index 3610d76d8f..51f55791ea 100644 --- a/src/llvm/tools/lli/CMakeLists.txt +++ b/src/llvm/tools/lli/CMakeLists.txt @@ -10,6 +10,7 @@ set(LLVM_LINK_COMPONENTS MC MCJIT Object + RuntimeDyld SelectionDAG Support native diff --git a/src/llvm/unittests/ExecutionEngine/CMakeLists.txt b/src/llvm/unittests/ExecutionEngine/CMakeLists.txt index 783c9b5192..05e093e0c0 100644 --- a/src/llvm/unittests/ExecutionEngine/CMakeLists.txt +++ b/src/llvm/unittests/ExecutionEngine/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine Interpreter MC + RuntimeDyld Support ) diff --git a/src/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/src/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index b10cbb4c9e..e29787f8f4 100644 --- a/src/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/src/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS IPO MC MCJIT + RuntimeDyld ScalarOpts Support Target diff --git a/src/llvm/utils/llvm-build/llvmbuild/__init__.pyc b/src/llvm/utils/llvm-build/llvmbuild/__init__.pyc index 1e2975d8ef2e190ec1c225d2455596c116c3e843..2e54cec98e1ea812e1b31a07edd016b7a5c1873d 100644 GIT binary patch delta 16 XcmZo=YGvYJ{>;m@E>AXeBFA3;m@$>CYZM2^1zDUJo^ diff --git a/src/llvm/utils/llvm-build/llvmbuild/componentinfo.pyc b/src/llvm/utils/llvm-build/llvmbuild/componentinfo.pyc index aa38c0bc58dae1deebc7e341143ecce150593e18..ed79c29d915060382c1320b1feba715df9696f33 100644 GIT binary patch delta 19 bcmZ2Fk8$ZdMh@oByj<(@WJ5P{$oc~SMJ5JO delta 19 bcmZ2Fk8$ZdMh@oByj+_co`r1Wko5-uNVNv< diff --git a/src/llvm/utils/llvm-build/llvmbuild/configutil.pyc b/src/llvm/utils/llvm-build/llvmbuild/configutil.pyc index a77c231aed46adeb2a0e26c627e44042bc3a497e..09c8c6722899cbd1d2713fff2718bc81f2d4ea0d 100644 GIT binary patch delta 17 YcmbO&Fk66w`7 +#include +#include +#include + +int rust_get_path(void *p, size_t* sz) +{ + int mib[4]; + char *eq = NULL; + char *key = NULL; + char *val = NULL; + char **menv = NULL; + size_t maxlen, len; + int nenv = 0; + int i; + + if ((p == NULL) && (sz == NULL)) + return -1; + + /* get the argv array */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC_ARGS; + mib[2] = getpid(); + mib[3] = KERN_PROC_ENV; + + /* get the number of bytes needed to get the env */ + maxlen = 0; + if (sysctl(mib, 4, NULL, &maxlen, NULL, 0) == -1) + return -1; + + /* allocate the buffer */ + if ((menv = calloc(maxlen, sizeof(char))) == NULL) + return -1; + + /* get the env array */ + if (sysctl(mib, 4, menv, &maxlen, NULL, 0) == -1) + { + free(menv); + return -1; + } + + mib[3] = KERN_PROC_NENV; + len = sizeof(int); + /* get the length of env array */ + if (sysctl(mib, 4, &nenv, &len, NULL, 0) == -1) + { + free(menv); + return -1; + } + + /* find _ key and resolve the value */ + for (i = 0; i < nenv; i++) + { + if ((eq = strstr(menv[i], "=")) == NULL) + continue; + + key = menv[i]; + val = eq + 1; + *eq = '\0'; + + if (strncmp(key, "PATH", maxlen) != 0) + continue; + + if (p == NULL) + { + /* return the length of the value + NUL */ + *sz = strnlen(val, maxlen) + 1; + free(menv); + return 0; + } + else + { + /* copy *sz bytes to the output buffer */ + memcpy(p, val, *sz); + free(menv); + return 0; + } + } + + free(menv); + return -1; +} + +int rust_get_path_array(void * p, size_t * sz) +{ + char *path, *str; + char **buf; + int i, num; + size_t len; + + if ((p == NULL) && (sz == NULL)) + return -1; + + /* get the length of the PATH value */ + if (rust_get_path(NULL, &len) == -1) + return -1; + + if (len == 0) + return -1; + + /* allocate the buffer */ + if ((path = calloc(len, sizeof(char))) == NULL) + return -1; + + /* get the PATH value */ + if (rust_get_path(path, &len) == -1) + { + free(path); + return -1; + } + + /* count the number of parts in the PATH */ + num = 1; + for(str = path; *str != '\0'; str++) + { + if (*str == ':') + num++; + } + + /* calculate the size of the buffer for the 2D array */ + len = (num * sizeof(char*) + 1) + strlen(path) + 1; + + if (p == NULL) + { + free(path); + *sz = len; + return 0; + } + + /* make sure we have enough buffer space */ + if (*sz < len) + { + free(path); + return -1; + } + + /* zero out the buffer */ + buf = (char**)p; + memset(buf, 0, *sz); + + /* copy the data into the right place */ + str = p + ((num+1) * sizeof(char*)); + memcpy(str, path, strlen(path)); + + /* parse the path into it's parts */ + for (i = 0; i < num && (buf[i] = strsep(&str, ":")) != NULL; i++) {;} + buf[num] = NULL; + + free(path); + return 0; +} + +int rust_get_argv_zero(void* p, size_t* sz) +{ + int mib[4]; + char **argv = NULL; + size_t len; + + if ((p == NULL) && (sz == NULL)) + return -1; + + /* get the argv array */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC_ARGS; + mib[2] = getpid(); + mib[3] = KERN_PROC_ARGV; + + /* request KERN_PROC_ARGV size */ + len = 0; + if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) + return -1; + + /* allocate buffer to receive the values */ + if ((argv = malloc(len)) == NULL) + return -1; + + /* get the argv array */ + if (sysctl(mib, 4, argv, &len, NULL, 0) == -1) + { + free(argv); + return -1; + } + + /* get length of argv[0] */ + len = strnlen(argv[0], len) + 1; + + if (p == NULL) + { + *sz = len; + free(argv); + return 0; + } + + if (*sz < len) + { + free(argv); + return -1; + } + + memset(p, 0, len); + memcpy(p, argv[0], len); + free(argv); + return 0; +} + +const char * rust_current_exe() +{ + static char *self = NULL; + char *argv0; + char **paths; + size_t sz; + int i; + char buf[2*PATH_MAX], exe[2*PATH_MAX]; + + if (self != NULL) + return self; + + if (rust_get_argv_zero(NULL, &sz) == -1) + return NULL; + if ((argv0 = calloc(sz, sizeof(char))) == NULL) + return NULL; + if (rust_get_argv_zero(argv0, &sz) == -1) + { + free(argv0); + return NULL; + } + + /* if argv0 is a relative or absolute path, resolve it with realpath */ + if ((*argv0 == '.') || (*argv0 == '/') || (strstr(argv0, "/") != NULL)) + { + self = realpath(argv0, NULL); + free(argv0); + return self; + } + + /* get the path array */ + if (rust_get_path_array(NULL, &sz) == -1) + { + free(argv0); + return NULL; + } + if ((paths = calloc(sz, sizeof(char))) == NULL) + { + free(argv0); + return NULL; + } + if (rust_get_path_array(paths, &sz) == -1) + { + free(argv0); + free(paths); + return NULL; + } + + for(i = 0; paths[i] != NULL; i++) + { + snprintf(buf, 2*PATH_MAX, "%s/%s", paths[i], argv0); + if (realpath(buf, exe) == NULL) + continue; + + if (access(exe, F_OK | X_OK) == -1) + continue; + + self = strdup(exe); + free(argv0); + free(paths); + return self; + } + + free(argv0); + free(paths); + return NULL; +} + +#elif defined(__OpenBSD__) + #include #include #include @@ -248,6 +523,7 @@ const char * rust_current_exe() { return (self); } + #endif // diff --git a/src/rt/valgrind/memcheck.h b/src/rt/valgrind/memcheck.h index 3af0728f01..ee72707d31 100644 --- a/src/rt/valgrind/memcheck.h +++ b/src/rt/valgrind/memcheck.h @@ -1,4 +1,3 @@ - /* ---------------------------------------------------------------- @@ -284,4 +283,3 @@ typedef (zznbytes), 0, 0 ) #endif - diff --git a/src/rust-installer/.gitmodules b/src/rust-installer/.gitmodules index 145697a130..51ee7b02ea 100644 --- a/src/rust-installer/.gitmodules +++ b/src/rust-installer/.gitmodules @@ -3,4 +3,4 @@ url = https://github.com/rust-lang/rust-installer [submodule "test/rust-installer-v2"] path = test/rust-installer-v2 - url = http://github.com/rust-lang/rust-installer + url = https://github.com/rust-lang/rust-installer diff --git a/src/rust-installer/combine-installers.sh b/src/rust-installer/combine-installers.sh old mode 100644 new mode 100755 diff --git a/src/rust-installer/gen-install-script.sh b/src/rust-installer/gen-install-script.sh index 0dc2fcccb9..289bead89c 100755 --- a/src/rust-installer/gen-install-script.sh +++ b/src/rust-installer/gen-install-script.sh @@ -11,6 +11,12 @@ set -u +if [ -x /bin/echo ]; then + ECHO='/bin/echo' +else + ECHO='echo' +fi + msg() { echo "gen-install-script: ${1-}" } @@ -253,14 +259,14 @@ success_message=`echo "$CFG_SUCCESS_MESSAGE" | sed "s/-/ /g"` script_template=`cat "$src_dir/install-template.sh"` # Using /bin/echo because under sh emulation dash *seems* to escape \n, which screws up the template -script=`/bin/echo "$script_template"` -script=`/bin/echo "$script" | sed "s/%%TEMPLATE_PRODUCT_NAME%%/\"$product_name\"/"` -script=`/bin/echo "$script" | sed "s/%%TEMPLATE_REL_MANIFEST_DIR%%/$CFG_REL_MANIFEST_DIR/"` -script=`/bin/echo "$script" | sed "s/%%TEMPLATE_SUCCESS_MESSAGE%%/\"$success_message\"/"` -script=`/bin/echo "$script" | sed "s/%%TEMPLATE_LEGACY_MANIFEST_DIRS%%/\"$CFG_LEGACY_MANIFEST_DIRS\"/"` -script=`/bin/echo "$script" | sed "s/%%TEMPLATE_RUST_INSTALLER_VERSION%%/\"$rust_installer_version\"/"` - -/bin/echo "$script" > "$CFG_OUTPUT_SCRIPT" +script=`$ECHO "$script_template"` +script=`$ECHO "$script" | sed "s/%%TEMPLATE_PRODUCT_NAME%%/\"$product_name\"/"` +script=`$ECHO "$script" | sed "s/%%TEMPLATE_REL_MANIFEST_DIR%%/$CFG_REL_MANIFEST_DIR/"` +script=`$ECHO "$script" | sed "s/%%TEMPLATE_SUCCESS_MESSAGE%%/\"$success_message\"/"` +script=`$ECHO "$script" | sed "s/%%TEMPLATE_LEGACY_MANIFEST_DIRS%%/\"$CFG_LEGACY_MANIFEST_DIRS\"/"` +script=`$ECHO "$script" | sed "s/%%TEMPLATE_RUST_INSTALLER_VERSION%%/\"$rust_installer_version\"/"` + +$ECHO "$script" > "$CFG_OUTPUT_SCRIPT" need_ok "couldn't write script" chmod u+x "$CFG_OUTPUT_SCRIPT" need_ok "couldn't chmod script" diff --git a/src/rust-installer/gen-installer.sh b/src/rust-installer/gen-installer.sh index 051003ea1a..93e79a9c18 100755 --- a/src/rust-installer/gen-installer.sh +++ b/src/rust-installer/gen-installer.sh @@ -11,6 +11,12 @@ set -u +if [ -x /bin/echo ]; then + ECHO='/bin/echo' +else + ECHO='echo' +fi + msg() { echo "gen-installer: ${1-}" } @@ -283,7 +289,7 @@ done # Add 'file:' installation directives. # The -n prevents adding a blank file: if the manifest is empty -manifest=`/bin/echo -n "$manifest" | sed s/^/file:/` +manifest=`$ECHO -n "$manifest" | sed s/^/file:/` # Add 'dir:' directives for bulk_dir in $bulk_dirs; do diff --git a/src/rust-installer/install-template.sh b/src/rust-installer/install-template.sh index fea699b90a..1e4a17f98b 100644 --- a/src/rust-installer/install-template.sh +++ b/src/rust-installer/install-template.sh @@ -223,7 +223,7 @@ opt() { fi done else - if [ ! -z "$META" ] + if [ ! -z "${META-}" ] then op="$op=<$META>" fi @@ -251,7 +251,7 @@ flag() { fi done else - if [ ! -z "$META" ] + if [ ! -z "${META-}" ] then op="$op=<$META>" fi @@ -327,6 +327,10 @@ get_host_triple() { _ostype=unknown-dragonfly ;; + OpenBSD) + _ostype=unknown-openbsd + ;; + Darwin) _ostype=apple-darwin ;; @@ -753,7 +757,7 @@ need_cmd tr need_cmd sed need_cmd chmod -CFG_ARGS="$@" +CFG_ARGS="${@:-}" HELP=0 if [ "${1-}" = "--help" ] @@ -778,8 +782,9 @@ valopt destdir "" "set installation root" valopt prefix "/usr/local" "set installation prefix" # Avoid prepending an extra / to the prefix path if there's no destdir -if [ -z "$CFG_DESTDIR" ]; then - CFG_DESTDIR_PREFIX="$CFG_PREFIX" +# NB: CFG vars here are undefined when passing --help +if [ -z "${CFG_DESTDIR-}" ]; then + CFG_DESTDIR_PREFIX="${CFG_PREFIX-}" else CFG_DESTDIR_PREFIX="$CFG_DESTDIR/$CFG_PREFIX" fi @@ -831,7 +836,7 @@ src_basename="$(basename "$0")" # then we're doing a full uninstall, as opposed to the --uninstall flag # which just means 'uninstall my components'. if [ "$src_basename" = "uninstall.sh" ]; then - if [ "$*" != "" ]; then + if [ "${*:-}" != "" ]; then # Currently don't know what to do with arguments in this mode err "uninstall.sh does not take any arguments" fi diff --git a/src/rust-installer/test.sh b/src/rust-installer/test.sh index 2843c1b04b..4cab6f6994 100755 --- a/src/rust-installer/test.sh +++ b/src/rust-installer/test.sh @@ -2,6 +2,12 @@ set -e -u +if [ -x /bin/echo ]; then + ECHO='/bin/echo' +else + ECHO='echo' +fi + S="$(cd $(dirname $0) && pwd)" TEST_DIR="$S/test" @@ -57,7 +63,7 @@ try() { if [ $? -ne 0 ]; then echo \$ "$_cmd" # Using /bin/echo to avoid escaping - /bin/echo "$_output" + $ECHO "$_output" echo echo "TEST FAILED!" echo @@ -67,7 +73,7 @@ try() { echo \$ "$_cmd" fi if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - /bin/echo "$_output" + $ECHO "$_output" fi fi set -e @@ -80,7 +86,7 @@ expect_fail() { if [ $? -eq 0 ]; then echo \$ "$_cmd" # Using /bin/echo to avoid escaping - /bin/echo "$_output" + $ECHO "$_output" echo echo "TEST FAILED!" echo @@ -90,7 +96,7 @@ expect_fail() { echo \$ "$_cmd" fi if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - /bin/echo "$_output" + $ECHO "$_output" fi fi set -e @@ -105,14 +111,14 @@ expect_output_ok() { if [ $? -ne 0 ]; then echo \$ "$_cmd" # Using /bin/echo to avoid escaping - /bin/echo "$_output" + $ECHO "$_output" echo echo "TEST FAILED!" echo exit 1 elif ! echo "$_output" | grep -q "$_expected"; then echo \$ "$_cmd" - /bin/echo "$_output" + $ECHO "$_output" echo echo "missing expected output '$_expected'" echo @@ -125,7 +131,7 @@ expect_output_ok() { echo \$ "$_cmd" fi if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - /bin/echo "$_output" + $ECHO "$_output" fi fi set -e @@ -140,14 +146,14 @@ expect_output_fail() { if [ $? -eq 0 ]; then echo \$ "$_cmd" # Using /bin/echo to avoid escaping - /bin/echo "$_output" + $ECHO "$_output" echo echo "TEST FAILED!" echo exit 1 elif ! echo "$_output" | grep -q "$_expected"; then echo \$ "$_cmd" - /bin/echo "$_output" + $ECHO "$_output" echo echo "missing expected output '$_expected'" echo @@ -160,7 +166,7 @@ expect_output_fail() { echo \$ "$_cmd" fi if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - /bin/echo "$_output" + $ECHO "$_output" fi fi set -e @@ -175,14 +181,14 @@ expect_not_output_ok() { if [ $? -ne 0 ]; then echo \$ "$_cmd" # Using /bin/echo to avoid escaping - /bin/echo "$_output" + $ECHO "$_output" echo echo "TEST FAILED!" echo exit 1 elif echo "$_output" | grep -q "$_expected"; then echo \$ "$_cmd" - /bin/echo "$_output" + $ECHO "$_output" echo echo "unexpected output '$_expected'" echo @@ -195,7 +201,7 @@ expect_not_output_ok() { echo \$ "$_cmd" fi if [ -n "${VERBOSE-}" -o -n "${VERBOSE_OUTPUT-}" ]; then - /bin/echo "$_output" + $ECHO "$_output" fi fi set -e @@ -1327,6 +1333,16 @@ leave_log_after_failure() { } runtest leave_log_after_failure +# https://github.com/rust-lang/rust-installer/issues/22 +help() { + try sh "$S/gen-installer.sh" \ + --image-dir="$TEST_DIR/image1" \ + --work-dir="$WORK_DIR" \ + --output-dir="$OUT_DIR" + try "$WORK_DIR/package/install.sh" --help +} +runtest help + # TODO: mandir/libdir/bindir, etc. echo diff --git a/src/rustbook/book.rs b/src/rustbook/book.rs index 21f8a7793d..a08481f8be 100644 --- a/src/rustbook/book.rs +++ b/src/rustbook/book.rs @@ -10,14 +10,16 @@ //! Basic data structures for representing a book. -use std::old_io::BufferedReader; +use std::io::prelude::*; +use std::io::BufReader; use std::iter; use std::iter::AdditiveIterator; +use std::path::{Path, PathBuf}; pub struct BookItem { pub title: String, - pub path: Path, - pub path_to_root: Path, + pub path: PathBuf, + pub path_to_root: PathBuf, pub children: Vec, } @@ -50,14 +52,14 @@ impl<'a> Iterator for BookItems<'a> { let mut section = "".to_string(); for &(_, idx) in &self.stack { - section.push_str(&(idx + 1).to_string()[]); + section.push_str(&(idx + 1).to_string()[..]); section.push('.'); } - section.push_str(&(self.cur_idx + 1).to_string()[]); + section.push_str(&(self.cur_idx + 1).to_string()[..]); section.push('.'); self.stack.push((self.cur_items, self.cur_idx)); - self.cur_items = &cur.children[]; + self.cur_items = &cur.children[..]; self.cur_idx = 0; return Some((section, cur)) } @@ -68,7 +70,7 @@ impl<'a> Iterator for BookItems<'a> { impl Book { pub fn iter(&self) -> BookItems { BookItems { - cur_items: &self.chapters[], + cur_items: &self.chapters[..], cur_idx: 0, stack: Vec::new(), } @@ -76,7 +78,7 @@ impl Book { } /// Construct a book by parsing a summary (markdown table of contents). -pub fn parse_summary(input: R, src: &Path) -> Result> { +pub fn parse_summary(input: &mut Read, src: &Path) -> Result> { fn collapse(stack: &mut Vec, top_items: &mut Vec, to_level: usize) { @@ -100,41 +102,41 @@ pub fn parse_summary(input: R, src: &Path) -> Result line, Err(err) => { - errors.push(err.desc.to_string()); // FIXME: include detail + errors.push(err.to_string()); return Err(errors); } }; - let star_idx = match line.find_str("*") { Some(i) => i, None => continue }; + let star_idx = match line.find("*") { Some(i) => i, None => continue }; - let start_bracket = star_idx + line[star_idx..].find_str("[").unwrap(); - let end_bracket = start_bracket + line[start_bracket..].find_str("](").unwrap(); + let start_bracket = star_idx + line[star_idx..].find("[").unwrap(); + let end_bracket = start_bracket + line[start_bracket..].find("](").unwrap(); let start_paren = end_bracket + 1; - let end_paren = start_paren + line[start_paren..].find_str(")").unwrap(); + let end_paren = start_paren + line[start_paren..].find(")").unwrap(); let given_path = &line[start_paren + 1 .. end_paren]; let title = line[start_bracket + 1..end_bracket].to_string(); let indent = &line[..star_idx]; - let path_from_root = match src.join(given_path).path_relative_from(src) { - Some(p) => p, + let path_from_root = match src.join(given_path).relative_from(src) { + Some(p) => p.to_path_buf(), None => { errors.push(format!("paths in SUMMARY.md must be relative, \ but path '{}' for section '{}' is not.", given_path, title)); - Path::new("") + PathBuf::new() } }; - let path_to_root = Path::new(iter::repeat("../") + let path_to_root = PathBuf::from(&iter::repeat("../") .take(path_from_root.components().count() - 1) .collect::()); let item = BookItem { diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 224f1ef1a8..f06290b27c 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -10,14 +10,16 @@ //! Implementation of the `build` subcommand, used to compile a book. -use std::os; use std::env; -use std::old_io; -use std::old_io::{fs, File, BufferedWriter, TempDir, IoResult}; +use std::fs::{self, File}; +use std::io::prelude::*; +use std::io::{self, BufWriter}; +use std::path::{Path, PathBuf}; +use rustc_back::tempdir::TempDir; use subcommand::Subcommand; use term::Term; -use error::{Error, CliResult, CommandResult}; +use error::{err, CliResult, CommandResult}; use book; use book::{Book, BookItem}; use css; @@ -29,33 +31,33 @@ struct Build; pub fn parse_cmd(name: &str) -> Option> { if name == "build" { - Some(box Build as Box) + Some(Box::new(Build)) } else { None } } -fn write_toc(book: &Book, path_to_root: &Path, out: &mut Writer) -> IoResult<()> { +fn write_toc(book: &Book, path_to_root: &Path, out: &mut Write) -> io::Result<()> { fn walk_items(items: &[BookItem], section: &str, path_to_root: &Path, - out: &mut Writer) -> IoResult<()> { + out: &mut Write) -> io::Result<()> { for (i, item) in items.iter().enumerate() { - try!(walk_item(item, &format!("{}{}.", section, i + 1)[], path_to_root, out)); + try!(walk_item(item, &format!("{}{}.", section, i + 1)[..], path_to_root, out)); } Ok(()) } fn walk_item(item: &BookItem, section: &str, path_to_root: &Path, - out: &mut Writer) -> IoResult<()> { + out: &mut Write) -> io::Result<()> { try!(writeln!(out, "

    ")); } - try!(fs::mkdir_recursive(&out_path, old_io::USER_DIR)); + try!(fs::create_dir_all(&out_path)); let rustdoc_args: &[String] = &[ "".to_string(), @@ -135,7 +142,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> { if output_result != 0 { let message = format!("Could not execute `rustdoc` with {:?}: {}", rustdoc_args, output_result); - return Err(box message as Box); + return Err(err(&message)); } } @@ -150,28 +157,30 @@ impl Subcommand for Build { } fn usage(&self) {} fn execute(&mut self, term: &mut Term) -> CommandResult<()> { - let cwd = os::getcwd().unwrap(); + let cwd = env::current_dir().unwrap(); let src; let tgt; if env::args().len() < 3 { src = cwd.clone(); } else { - src = Path::new(env::args().nth(2).unwrap().clone()); + src = PathBuf::from(&env::args().nth(2).unwrap()); } if env::args().len() < 4 { tgt = cwd.join("_book"); } else { - tgt = Path::new(env::args().nth(3).unwrap().clone()); + tgt = PathBuf::from(&env::args().nth(3).unwrap()); } - try!(fs::mkdir(&tgt, old_io::USER_DIR)); + try!(fs::create_dir(&tgt)); - try!(File::create(&tgt.join("rust-book.css")).write_str(css::STYLE)); + try!(File::create(&tgt.join("rust-book.css")).and_then(|mut f| { + f.write_all(css::STYLE.as_bytes()) + })); - let summary = try!(File::open(&src.join("SUMMARY.md"))); - match book::parse_summary(summary, &src) { + let mut summary = try!(File::open(&src.join("SUMMARY.md"))); + match book::parse_summary(&mut summary, &src) { Ok(book) => { // execute rustdoc on the whole book render(&book, &tgt) @@ -179,10 +188,10 @@ impl Subcommand for Build { Err(errors) => { let n = errors.len(); for err in errors { - term.err(&format!("error: {}", err)[]); + term.err(&format!("error: {}", err)[..]); } - Err(box format!("{} errors occurred", n) as Box) + Err(err(&format!("{} errors occurred", n))) } } } diff --git a/src/rustbook/error.rs b/src/rustbook/error.rs index 43c882c7d5..e896dee279 100644 --- a/src/rustbook/error.rs +++ b/src/rustbook/error.rs @@ -10,10 +10,8 @@ //! Error handling utilities. WIP. +use std::error::Error; use std::fmt; -use std::fmt::{Debug, Formatter}; - -use std::old_io::IoError; pub type CliError = Box; pub type CliResult = Result; @@ -21,63 +19,18 @@ pub type CliResult = Result; pub type CommandError = Box; pub type CommandResult = Result; -pub trait Error { - fn description(&self) -> &str; - - fn detail(&self) -> Option<&str> { None } - fn cause(&self) -> Option<&Error> { None } -} - -pub trait FromError { - fn from_err(err: E) -> Self; -} - -impl Debug for Box { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.description()) - } -} - -impl FromError for Box { - fn from_err(err: E) -> Box { - box err as Box - } -} +pub fn err(s: &str) -> CliError { + #[derive(Debug)] + struct E(String); -impl<'a> Error for &'a str { - fn description<'b>(&'b self) -> &'b str { - *self + impl Error for E { + fn description(&self) -> &str { &self.0 } } -} - -impl Error for String { - fn description<'a>(&'a self) -> &'a str { - &self[..] + impl fmt::Display for E { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } } -} - -impl<'a> Error for Box { - fn description(&self) -> &str { (**self).description() } - fn detail(&self) -> Option<&str> { (**self).detail() } - fn cause(&self) -> Option<&Error> { (**self).cause() } -} - -impl FromError<()> for () { - fn from_err(_: ()) -> () { () } -} -impl FromError for IoError { - fn from_err(error: IoError) -> IoError { error } + Box::new(E(s.to_string())) } - -impl Error for IoError { - fn description(&self) -> &str { - self.desc - } - fn detail(&self) -> Option<&str> { - self.detail.as_ref().map(|s| &s[..]) - } -} - - -//fn iter_map_err>>(iter: I, diff --git a/src/rustbook/help.rs b/src/rustbook/help.rs index 7fd8214f73..995d2f2494 100644 --- a/src/rustbook/help.rs +++ b/src/rustbook/help.rs @@ -19,7 +19,7 @@ struct Help; pub fn parse_cmd(name: &str) -> Option> { match name { - "help" | "--help" | "-h" | "-?" => Some(box Help as Box), + "help" | "--help" | "-h" | "-?" => Some(Box::new(Help)), _ => None } } diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs index ace57f0ac2..09fcd518c1 100644 --- a/src/rustbook/main.rs +++ b/src/rustbook/main.rs @@ -8,31 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] -#![feature(collections)] +#![deny(warnings)] + #![feature(core)] -#![feature(old_io)] -#![feature(os)] -#![feature(env)] -#![feature(old_path)] +#![feature(exit_status)] #![feature(rustdoc)] +#![feature(rustc_private)] +#![feature(path_relative_from)] extern crate rustdoc; +extern crate rustc_back; use std::env; +use std::error::Error; use subcommand::Subcommand; use term::Term; -macro_rules! try ( - ($expr:expr) => ({ - use error; - match $expr { - Ok(val) => val, - Err(err) => return Err(error::FromError::from_err(err)) - } - }) -); - mod term; mod error; mod book; @@ -54,17 +45,14 @@ fn main() { if cmd.len() <= 1 { help::usage() } else { - match subcommand::parse_name(&cmd[1][]) { + match subcommand::parse_name(&cmd[1][..]) { Some(mut subcmd) => { - match subcmd.parse_args(cmd.tail()) { + match subcmd.parse_args(&cmd[..cmd.len()-1]) { Ok(_) => { match subcmd.execute(&mut term) { Ok(_) => (), Err(err) => { - term.err(&format!("error: {}", err.description())[]); - err.detail().map(|detail| { - term.err(&format!("detail: {}", detail)[]); - }); + term.err(&format!("error: {}", err)); } } } diff --git a/src/rustbook/serve.rs b/src/rustbook/serve.rs index 808527dcef..2fa7b7eed7 100644 --- a/src/rustbook/serve.rs +++ b/src/rustbook/serve.rs @@ -19,7 +19,7 @@ struct Serve; pub fn parse_cmd(name: &str) -> Option> { if name == "serve" { - Some(box Serve as Box) + Some(Box::new(Serve)) } else { None } diff --git a/src/rustbook/subcommand.rs b/src/rustbook/subcommand.rs index 473739c919..44af43be78 100644 --- a/src/rustbook/subcommand.rs +++ b/src/rustbook/subcommand.rs @@ -32,11 +32,11 @@ pub trait Subcommand { /// Create a Subcommand object based on its name. pub fn parse_name(name: &str) -> Option> { - for parser in [ - help::parse_cmd as fn(&str) -> Option>, - build::parse_cmd as fn(&str) -> Option>, - serve::parse_cmd as fn(&str) -> Option>, - test::parse_cmd as fn(&str) -> Option>].iter() { + let cmds: [fn(&str) -> Option>; 4] = [help::parse_cmd, + build::parse_cmd, + serve::parse_cmd, + test::parse_cmd]; + for parser in cmds.iter() { let parsed = (*parser)(name); if parsed.is_some() { return parsed } } diff --git a/src/rustbook/term.rs b/src/rustbook/term.rs index 98aa3fca18..060297beb7 100644 --- a/src/rustbook/term.rs +++ b/src/rustbook/term.rs @@ -12,22 +12,23 @@ //! verbosity support. For now, just a wrapper around stdout/stderr. use std::env; -use std::old_io::stdio; +use std::io; +use std::io::prelude::*; pub struct Term { - err: Box + err: Box } impl Term { pub fn new() -> Term { Term { - err: box stdio::stderr() as Box, + err: Box::new(io::stderr()) } } pub fn err(&mut self, msg: &str) { // swallow any errors - let _ = self.err.write_line(msg); + let _ = writeln!(&mut self.err, "{}", msg); env::set_exit_status(101); } } diff --git a/src/rustbook/test.rs b/src/rustbook/test.rs index c5d4875423..72df0768e7 100644 --- a/src/rustbook/test.rs +++ b/src/rustbook/test.rs @@ -11,19 +11,19 @@ //! Implementation of the `test` subcommand. Just a stub for now. use subcommand::Subcommand; -use error::CliResult; -use error::CommandResult; -use error::Error; +use error::{err, CliResult, CommandResult}; use term::Term; use book; -use std::old_io::{Command, File}; -use std::os; + +use std::fs::File; +use std::env; +use std::process::Command; struct Test; pub fn parse_cmd(name: &str) -> Option> { if name == "test" { - Some(box Test as Box) + Some(Box::new(Test)) } else { None } @@ -35,11 +35,11 @@ impl Subcommand for Test { } fn usage(&self) {} fn execute(&mut self, term: &mut Term) -> CommandResult<()> { - let cwd = os::getcwd().unwrap(); + let cwd = env::current_dir().unwrap(); let src = cwd.clone(); - let summary = File::open(&src.join("SUMMARY.md")); - match book::parse_summary(summary, &src) { + let mut summary = try!(File::open(&src.join("SUMMARY.md"))); + match book::parse_summary(&mut summary, &src) { Ok(book) => { for (_, item) in book.iter() { let output_result = Command::new("rustdoc") @@ -50,15 +50,15 @@ impl Subcommand for Test { Ok(output) => { if !output.status.success() { term.err(&format!("{}\n{}", - String::from_utf8_lossy(&output.output[]), - String::from_utf8_lossy(&output.error[]))[]); - return Err(box "Some tests failed." as Box); + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr))); + return Err(err("some tests failed")); } } Err(e) => { - let message = format!("Could not execute `rustdoc`: {}", e); - return Err(box message as Box); + let message = format!("could not execute `rustdoc`: {}", e); + return Err(err(&message)) } } } @@ -67,7 +67,7 @@ impl Subcommand for Test { for err in errors { term.err(&err[..]); } - return Err(box "There was an error." as Box); + return Err(err("there was an error")) } } Ok(()) // lol diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index ce3090390d..b205d87598 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" @@ -83,6 +84,11 @@ LLVMRustCreateTargetMachine(const char *triple, return NULL; } + StringRef real_cpu = cpu; + if (real_cpu == "native") { + real_cpu = sys::getHostCPUName(); + } + TargetOptions Options; Options.PositionIndependentExecutable = PositionIndependentExecutable; Options.NoFramePointerElim = NoFramePointerElim; @@ -96,7 +102,7 @@ LLVMRustCreateTargetMachine(const char *triple, } TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(), - cpu, + real_cpu, feature, Options, RM, diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index aaf6d8df29..9a87c03f1c 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -14,11 +14,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" -#if LLVM_VERSION_MINOR >= 5 #include "llvm/IR/CallSite.h" -#else -#include "llvm/Support/CallSite.h" -#endif //===----------------------------------------------------------------------=== // @@ -33,7 +29,6 @@ using namespace llvm::object; static char *LastError; -#if LLVM_VERSION_MINOR >= 5 extern "C" LLVMMemoryBufferRef LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { ErrorOr> buf_or = MemoryBuffer::getFile(Path, @@ -45,18 +40,6 @@ LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { } return wrap(buf_or.get().release()); } -#else -extern "C" LLVMMemoryBufferRef -LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) { - OwningPtr buf; - error_code err = MemoryBuffer::getFile(Path, buf, -1, false); - if (err) { - LLVMRustSetLastError(err.message().c_str()); - return NULL; - } - return wrap(buf.take()); -} -#endif extern "C" char *LLVMRustGetLastError(void) { char *ret = LastError; @@ -116,7 +99,6 @@ extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uin } -#if LLVM_VERSION_MINOR >= 5 extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned idx, uint64_t b) { CallSite Call = CallSite(unwrap(Instr)); AttrBuilder B; @@ -126,9 +108,6 @@ extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned AttributeSet::get(Call->getContext(), idx, B))); } -#else -extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef, unsigned, uint64_t) {} -#endif extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64_t Val) { Function *A = unwrap(Fn); @@ -137,16 +116,12 @@ extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64 A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } -#if LLVM_VERSION_MINOR >= 5 extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef Fn, unsigned index, uint64_t bytes) { Function *A = unwrap(Fn); AttrBuilder B; B.addDereferenceableAttr(bytes); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } -#else -extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef, unsigned, uint64_t) {} -#endif extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) { Function *F = unwrap(Fn); @@ -199,10 +174,8 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, AtomicOrdering order, AtomicOrdering failure_order) { return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old), - unwrap(source), order -#if LLVM_VERSION_MINOR >= 5 - , failure_order -#endif + unwrap(source), order, + failure_order )); } extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) { @@ -247,11 +220,7 @@ DIT unwrapDI(LLVMMetadataRef ref) { return DIT(ref ? unwrap(ref) : NULL); } -#if LLVM_VERSION_MINOR >= 5 extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION; -#else -extern "C" const uint32_t LLVMRustDebugMetadataVersion = 1; -#endif extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *name, @@ -383,10 +352,8 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType( unwrapDI(DerivedFrom), unwrapDI(Elements), RunTimeLang, - unwrapDI(VTableHolder) -#if LLVM_VERSION_MINOR >= 4 - ,UniqueId -#endif + unwrapDI(VTableHolder), + UniqueId )); } @@ -465,8 +432,8 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable( #if LLVM_VERSION_MINOR < 6 if (AddrOpsCount > 0) { SmallVector addr_ops; - llvm::Type *Int64Ty = Type::getInt64Ty(VMContext); - for (int i = 0; i < AddrOpsCount; ++i) + llvm::Type *Int64Ty = Type::getInt64Ty(unwrap(Scope)->getContext()); + for (unsigned i = 0; i < AddrOpsCount; ++i) addr_ops.push_back(ConstantInt::get(Int64Ty, AddrOps[i])); return wrap(Builder->createComplexVariable( @@ -522,7 +489,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray( LLVMMetadataRef* Ptr, unsigned Count) { return wrap(Builder->getOrCreateArray( +#if LLVM_VERSION_MINOR >= 6 ArrayRef(unwrap(Ptr), Count))); +#else + ArrayRef(reinterpret_cast(Ptr), Count))); +#endif } extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( @@ -627,19 +598,11 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType( AlignInBits, Flags, unwrapDI(Elements), - RunTimeLang -#if LLVM_VERSION_MINOR >= 4 - ,UniqueId -#endif + RunTimeLang, + UniqueId )); } -#if LLVM_VERSION_MINOR < 5 -extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) { - unwrap(Value)->setUnnamedAddr(Unnamed); -} -#endif - extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter( DIBuilderRef Builder, LLVMMetadataRef Scope, @@ -730,7 +693,6 @@ extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) { os << ")"; } -#if LLVM_VERSION_MINOR >= 5 extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { Module *Dst = unwrap(dst); @@ -763,28 +725,7 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { } return true; } -#else -extern "C" bool -LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) { - Module *Dst = unwrap(dst); - MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len)); - std::string Err; - Module *Src = llvm::getLazyBitcodeModule(buf, Dst->getContext(), &Err); - if (!Src) { - LLVMRustSetLastError(Err.c_str()); - delete buf; - return false; - } - - if (Linker::LinkModules(Dst, Src, Linker::DestroySource, &Err)) { - LLVMRustSetLastError(Err.c_str()); - return false; - } - return true; -} -#endif -#if LLVM_VERSION_MINOR >= 5 extern "C" void* LLVMRustOpenArchive(char *path) { ErrorOr> buf_or = MemoryBuffer::getFile(path, @@ -817,23 +758,6 @@ LLVMRustOpenArchive(char *path) { return ret; } -#else -extern "C" void* -LLVMRustOpenArchive(char *path) { - OwningPtr buf; - error_code err = MemoryBuffer::getFile(path, buf, -1, false); - if (err) { - LLVMRustSetLastError(err.message().c_str()); - return NULL; - } - Archive *ret = new Archive(buf.take(), err); - if (err) { - LLVMRustSetLastError(err.message().c_str()); - return NULL; - } - return ret; -} -#endif extern "C" const char* #if LLVM_VERSION_MINOR >= 6 @@ -844,21 +768,12 @@ LLVMRustArchiveReadSection(OwningBinary *ob, char *name, size_t *size) LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) { #endif -#if LLVM_VERSION_MINOR >= 5 Archive::child_iterator child = ar->child_begin(), end = ar->child_end(); for (; child != end; ++child) { ErrorOr name_or_err = child->getName(); if (name_or_err.getError()) continue; StringRef sect_name = name_or_err.get(); -#else - Archive::child_iterator child = ar->begin_children(), - end = ar->end_children(); - for (; child != end; ++child) { - StringRef sect_name; - error_code err = child->getName(sect_name); - if (err) continue; -#endif if (sect_name.trim(" ") == name) { StringRef buf = child->getBuffer(); *size = buf.size(); @@ -877,18 +792,11 @@ LLVMRustDestroyArchive(Archive *ar) { delete ar; } -#if LLVM_VERSION_MINOR >= 5 extern "C" void LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { GlobalValue *V = unwrap(Value); V->setDLLStorageClass(GlobalValue::DLLExportStorageClass); } -#else -extern "C" void -LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) { - LLVMSetLinkage(Value, LLVMDLLExportLinkage); -} -#endif extern "C" int LLVMVersionMinor() { @@ -918,11 +826,7 @@ inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { extern "C" int LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) { StringRef ret; -#if LLVM_VERSION_MINOR >= 5 if (std::error_code ec = (*unwrap(SI))->getName(ret)) -#else - if (error_code ec = (*unwrap(SI))->getName(ret)) -#endif report_fatal_error(ec.message()); *ptr = ret.data(); return ret.size(); diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index 1317343712..1ea40fc46a 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -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-02-13 +2015-03-04 diff --git a/src/snapshots.txt b/src/snapshots.txt index 4759c44259..5d265478b6 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,62 @@ +S 2015-03-27 5520801 + bitrig-x86_64 55a69b0ae5481ccda54c2fcfc54025a0945c4f57 + freebsd-x86_64 0910bbad35e213f679d0433884fd51398eb3bc8d + linux-i386 1ef82402ed16f5a6d2f87a9a62eaa83170e249ec + linux-x86_64 ef2154372e97a3cb687897d027fd51c8f2c5f349 + macos-i386 0310b1a970f2da7e61770fd14dbbbdca3b518234 + macos-x86_64 5f35d9c920b8083a7420ef8cf5b00d5ef3085dfa + winnt-i386 808b7961f85872f04ec15ad0d3e9e23ae9bc0c3b + winnt-x86_64 903a99a58f57a9bd9848cc68a2445dda881f1ee8 + +S 2015-03-25 a923278 + bitrig-x86_64 e56c400a04bca7b52ab54e0780484bb68fa449c2 + freebsd-x86_64 cd02c86a9218da73b2a45aff293787010d33bf3e + linux-i386 da50141558eed6dabab97b79b2c6a7de4f2d2c5e + linux-x86_64 bca03458d28d07506bad4b80e5770b2117286244 + macos-i386 522d59b23dd885a45e2c5b33e80e76240bb2d9af + macos-x86_64 82df09d51d73d119a2f4e4d8041879615cb22081 + winnt-i386 5056e8def5ab4f4283b8f3aab160cc10231bb28d + winnt-x86_64 3f6b35ac12625b4b4b42dfd5eee5f6cbf122794e + +S 2015-03-17 c64d671 + bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163 + freebsd-x86_64 14ced24e1339a4dd8baa9db69995daa52a948d54 + linux-i386 200450ad3cc56bc715ca105b9acae35204bf7351 + linux-x86_64 a54f50fee722ba6bc7281dec3e4d5121af7c15e3 + macos-i386 e33fd692f3808a0265e7b02fbc40e403080cdd4f + macos-x86_64 9a89ed364ae71aeb9d659ad223eae5f5986fc03f + winnt-i386 8911a28581e490d413b56467a6184545633ca04a + winnt-x86_64 38ce4556b19472c23ccce28685e3a2ebefb9bfbc + +S 2015-03-07 270a677 + bitrig-x86_64 4b2f11a96b1b5b3782d74bda707aca33bc179880 + freebsd-x86_64 3c147d8e4cfdcb02c2569f5aca689a1d8920d17b + linux-i386 50a47ef247610fb089d2c4f24e4b641eb0ba4afb + linux-x86_64 ccb20709b3c984f960ddde996451be8ce2268d7c + macos-i386 ad263bdeadcf9bf1889426e0c1391a7cf277364e + macos-x86_64 01c8275828042264206b7acd8e86dc719a2f27aa + winnt-i386 cb73ac7a9bf408e8b5cdb92d595082a537a90794 + winnt-x86_64 b9b47e80101f726ae4f5919373ea20b92d827f3c + +S 2015-02-25 880fb89 + bitrig-x86_64 8cdc4ca0a80103100f46cbf8caa9fe497df048c5 + freebsd-x86_64 f4cbe4227739de986444211f8ee8d74745ab8f7f + linux-i386 3278ebbce8cb269acc0614dac5ddac07eab6a99c + linux-x86_64 72287d0d88de3e5a53bae78ac0d958e1a7637d73 + macos-i386 33b366b5287427a340a0aa6ed886d5ff4edf6a76 + macos-x86_64 914bf9baa32081a9d5633f1d06f4d382cd71504e + winnt-i386 d58b415b9d8629cb6c4952f1f6611a526a38323f + winnt-x86_64 2cb1dcc563d2ac6deada054de15748f5dd599c7e + +S 2015-02-19 522d09d + freebsd-x86_64 7ea14ef85a25bca70a310a2cd660b356cf61abc7 + linux-i386 26e3caa1ce1c482b9941a6bdc64b3e65d036c200 + linux-x86_64 44f514aabb4e4049e4db9a4e1fdeb16f6cee60f2 + macos-i386 157910592224083df56f5f31ced3e6f3dc9b1de0 + macos-x86_64 56c28aa0e14ec6991ad6ca213568f1155561105d + winnt-i386 da0f7a3fbc913fbb177917f2850bb41501affb5c + winnt-x86_64 22bd816ccd2690fc9804b27ca525f603be8aeaa5 + S 2015-02-17 f1bb6c2 freebsd-x86_64 59f3a2c6350c170804fb65838e1b504eeab89105 linux-i386 191ed5ec4f17e32d36abeade55a1c6085e51245c diff --git a/src/test/auxiliary/ambig_impl_2_lib.rs b/src/test/auxiliary/ambig_impl_2_lib.rs index e56df439bc..bd23fb8821 100644 --- a/src/test/auxiliary/ambig_impl_2_lib.rs +++ b/src/test/auxiliary/ambig_impl_2_lib.rs @@ -9,6 +9,6 @@ // except according to those terms. trait me { - fn me(&self) -> uint; + fn me(&self) -> usize; } -impl me for uint { fn me(&self) -> uint { *self } } +impl me for usize { fn me(&self) -> usize { *self } } diff --git a/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs index 12ab62267a..197fb9a6d0 100644 --- a/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -9,6 +9,7 @@ // except according to those terms. #![crate_name="anonexternmod"] +#![feature(libc)] extern crate libc; diff --git a/src/test/auxiliary/anon_trait_static_method_lib.rs b/src/test/auxiliary/anon_trait_static_method_lib.rs index 666d2569c4..9d93d9689e 100644 --- a/src/test/auxiliary/anon_trait_static_method_lib.rs +++ b/src/test/auxiliary/anon_trait_static_method_lib.rs @@ -9,7 +9,7 @@ // except according to those terms. pub struct Foo { - pub x: int + pub x: isize } impl Foo { diff --git a/src/test/auxiliary/associated-types-cc-lib.rs b/src/test/auxiliary/associated-types-cc-lib.rs index 44fbcf2150..b3960c2707 100644 --- a/src/test/auxiliary/associated-types-cc-lib.rs +++ b/src/test/auxiliary/associated-types-cc-lib.rs @@ -19,8 +19,8 @@ pub trait Bar { fn get(x: Option) -> ::T; } -impl Bar for int { - type T = uint; +impl Bar for isize { + type T = usize; - fn get(_: Option) -> uint { 22 } + fn get(_: Option) -> usize { 22 } } diff --git a/src/test/auxiliary/cci_borrow_lib.rs b/src/test/auxiliary/cci_borrow_lib.rs index 96af320306..9c90510a85 100644 --- a/src/test/auxiliary/cci_borrow_lib.rs +++ b/src/test/auxiliary/cci_borrow_lib.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo(x: &uint) -> uint { +pub fn foo(x: &usize) -> usize { *x } diff --git a/src/test/auxiliary/cci_class.rs b/src/test/auxiliary/cci_class.rs index 50116b3973..08a13fd8bc 100644 --- a/src/test/auxiliary/cci_class.rs +++ b/src/test/auxiliary/cci_class.rs @@ -10,12 +10,12 @@ pub mod kitties { pub struct cat { - meows : uint, + meows : usize, - pub how_hungry : int, + pub how_hungry : isize, } - pub fn cat(in_x : uint, in_y : int) -> cat { + pub fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y diff --git a/src/test/auxiliary/cci_class_2.rs b/src/test/auxiliary/cci_class_2.rs index 55fb424205..7d147832f0 100644 --- a/src/test/auxiliary/cci_class_2.rs +++ b/src/test/auxiliary/cci_class_2.rs @@ -10,9 +10,9 @@ pub mod kitties { pub struct cat { - meows : uint, + meows : usize, - pub how_hungry : int, + pub how_hungry : isize, } @@ -20,7 +20,7 @@ pub mod kitties { pub fn speak(&self) {} } - pub fn cat(in_x : uint, in_y : int) -> cat { + pub fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y diff --git a/src/test/auxiliary/cci_class_3.rs b/src/test/auxiliary/cci_class_3.rs index 98881eb09b..ec1bf108dc 100644 --- a/src/test/auxiliary/cci_class_3.rs +++ b/src/test/auxiliary/cci_class_3.rs @@ -10,17 +10,17 @@ pub mod kitties { pub struct cat { - meows : uint, + meows : usize, - pub how_hungry : int, + pub how_hungry : isize, } impl cat { - pub fn speak(&mut self) { self.meows += 1_usize; } - pub fn meow_count(&mut self) -> uint { self.meows } + pub fn speak(&mut self) { self.meows += 1; } + pub fn meow_count(&mut self) -> usize { self.meows } } - pub fn cat(in_x : uint, in_y : int) -> cat { + pub fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y diff --git a/src/test/auxiliary/cci_class_4.rs b/src/test/auxiliary/cci_class_4.rs index 9d7905cdeb..300cc31632 100644 --- a/src/test/auxiliary/cci_class_4.rs +++ b/src/test/auxiliary/cci_class_4.rs @@ -10,9 +10,9 @@ pub mod kitties { pub struct cat { - meows : uint, + meows : usize, - pub how_hungry : int, + pub how_hungry : isize, pub name : String, } @@ -34,14 +34,14 @@ pub mod kitties { impl cat { pub fn meow(&mut self) { println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { + self.meows += 1; + if self.meows % 5 == 0 { self.how_hungry += 1; } } } - pub fn cat(in_x : uint, in_y : int, in_name: String) -> cat { + pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/auxiliary/cci_class_5.rs b/src/test/auxiliary/cci_class_5.rs index d113859a6b..7fe608f163 100644 --- a/src/test/auxiliary/cci_class_5.rs +++ b/src/test/auxiliary/cci_class_5.rs @@ -10,15 +10,15 @@ pub mod kitties { pub struct cat { - meows : uint, - pub how_hungry : int, + meows : usize, + pub how_hungry : isize, } impl cat { fn nap(&self) {} } - pub fn cat(in_x : uint, in_y : int) -> cat { + pub fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y diff --git a/src/test/auxiliary/cci_class_6.rs b/src/test/auxiliary/cci_class_6.rs index 71552f4c97..c902a6c7dc 100644 --- a/src/test/auxiliary/cci_class_6.rs +++ b/src/test/auxiliary/cci_class_6.rs @@ -12,9 +12,9 @@ pub mod kitties { pub struct cat { info : Vec , - meows : uint, + meows : usize, - pub how_hungry : int, + pub how_hungry : isize, } impl cat { @@ -22,10 +22,10 @@ pub mod kitties { self.meows += stuff.len(); } - pub fn meow_count(&mut self) -> uint { self.meows } + pub fn meow_count(&mut self) -> usize { self.meows } } - pub fn cat(in_x : uint, in_y : int, in_info: Vec ) -> cat { + pub fn cat(in_x : usize, in_y : isize, in_info: Vec ) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs index dd272bf639..f54a39d61e 100644 --- a/src/test/auxiliary/cci_class_cast.rs +++ b/src/test/auxiliary/cci_class_cast.rs @@ -12,12 +12,12 @@ pub mod kitty { use std::fmt; pub struct cat { - meows : uint, - pub how_hungry : int, + meows : usize, + pub how_hungry : isize, pub name : String, } - impl fmt::String for cat { + impl fmt::Display for cat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) } @@ -26,8 +26,8 @@ pub mod kitty { impl cat { fn meow(&mut self) { println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { + self.meows += 1; + if self.meows % 5 == 0 { self.how_hungry += 1; } } @@ -50,7 +50,7 @@ pub mod kitty { } } - pub fn cat(in_x : uint, in_y : int, in_name: String) -> cat { + pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/auxiliary/cci_const.rs b/src/test/auxiliary/cci_const.rs index 945004ede6..ee8290050f 100644 --- a/src/test/auxiliary/cci_const.rs +++ b/src/test/auxiliary/cci_const.rs @@ -12,5 +12,5 @@ pub extern fn bar() { } pub const foopy: &'static str = "hi there"; -pub const uint_val: uint = 12; -pub const uint_expr: uint = (1 << uint_val) - 1; +pub const uint_val: usize = 12; +pub const uint_expr: usize = (1 << uint_val) - 1; diff --git a/src/test/auxiliary/cci_const_block.rs b/src/test/auxiliary/cci_const_block.rs index a3bcbd201e..76fe9fe5aa 100644 --- a/src/test/auxiliary/cci_const_block.rs +++ b/src/test/auxiliary/cci_const_block.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub static BLOCK_FN_DEF: fn(uint) -> uint = { - fn foo(a: uint) -> uint { +pub static BLOCK_FN_DEF: fn(usize) -> usize = { + fn foo(a: usize) -> usize { a + 10 } foo diff --git a/src/test/auxiliary/cci_impl_lib.rs b/src/test/auxiliary/cci_impl_lib.rs index 6ee497370e..d8921f4e09 100644 --- a/src/test/auxiliary/cci_impl_lib.rs +++ b/src/test/auxiliary/cci_impl_lib.rs @@ -11,16 +11,16 @@ #![crate_name="cci_impl_lib"] pub trait uint_helpers { - fn to(&self, v: uint, f: F) where F: FnMut(uint); + fn to(&self, v: usize, f: F) where F: FnMut(usize); } -impl uint_helpers for uint { +impl uint_helpers for usize { #[inline] - fn to(&self, v: uint, mut f: F) where F: FnMut(uint) { + fn to(&self, v: usize, mut f: F) where F: FnMut(usize) { let mut i = *self; while i < v { f(i); - i += 1_usize; + i += 1; } } } diff --git a/src/test/auxiliary/cci_intrinsic.rs b/src/test/auxiliary/cci_intrinsic.rs index a3a3dbac2b..b6e69d29f7 100644 --- a/src/test/auxiliary/cci_intrinsic.rs +++ b/src/test/auxiliary/cci_intrinsic.rs @@ -17,7 +17,7 @@ pub mod rusti { } #[inline(always)] -pub fn atomic_xchg(dst: *mut int, src: int) -> int { +pub fn atomic_xchg(dst: *mut isize, src: isize) -> isize { unsafe { rusti::atomic_xchg(dst, src) } diff --git a/src/test/auxiliary/cci_iter_lib.rs b/src/test/auxiliary/cci_iter_lib.rs index 8e00b0dc7b..07d03b4c75 100644 --- a/src/test/auxiliary/cci_iter_lib.rs +++ b/src/test/auxiliary/cci_iter_lib.rs @@ -12,10 +12,10 @@ #[inline] pub fn iter(v: &[T], mut f: F) where F: FnMut(&T) { - let mut i = 0_usize; + let mut i = 0; let n = v.len(); while i < n { f(&v[i]); - i += 1_usize; + i += 1; } } diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs index 587af956c7..8c1a283a72 100644 --- a/src/test/auxiliary/cci_nested_lib.rs +++ b/src/test/auxiliary/cci_nested_lib.rs @@ -44,8 +44,8 @@ pub fn alist_get() -> alist { - fn eq_int(a: int, b: int) -> bool { a == b } +pub fn new_int_alist() -> alist { + fn eq_int(a: isize, b: isize) -> bool { a == b } return alist { eq_fn: eq_int, data: box RefCell::new(Vec::new()), @@ -53,9 +53,9 @@ pub fn new_int_alist() -> alist { } #[inline] -pub fn new_int_alist_2() -> alist { +pub fn new_int_alist_2() -> alist { #[inline] - fn eq_int(a: int, b: int) -> bool { a == b } + fn eq_int(a: isize, b: isize) -> bool { a == b } return alist { eq_fn: eq_int, data: box RefCell::new(Vec::new()), diff --git a/src/test/auxiliary/cci_no_inline_lib.rs b/src/test/auxiliary/cci_no_inline_lib.rs index ce04111890..4c6f808c61 100644 --- a/src/test/auxiliary/cci_no_inline_lib.rs +++ b/src/test/auxiliary/cci_no_inline_lib.rs @@ -12,11 +12,11 @@ // same as cci_iter_lib, more-or-less, but not marked inline -pub fn iter(v: Vec , mut f: F) where F: FnMut(uint) { - let mut i = 0_usize; +pub fn iter(v: Vec , mut f: F) where F: FnMut(usize) { + let mut i = 0; let n = v.len(); while i < n { f(v[i]); - i += 1_usize; + i += 1; } } diff --git a/src/test/auxiliary/cfg_inner_static.rs b/src/test/auxiliary/cfg_inner_static.rs index 4331a1da2a..b5b4390657 100644 --- a/src/test/auxiliary/cfg_inner_static.rs +++ b/src/test/auxiliary/cfg_inner_static.rs @@ -11,7 +11,7 @@ // this used to just ICE on compiling pub fn foo() { if cfg!(foo) { - static a: int = 3; + static a: isize = 3; a } else { 3 }; } diff --git a/src/test/auxiliary/changing-crates-a2.rs b/src/test/auxiliary/changing-crates-a2.rs index a54dcbbbfc..28eae023d6 100644 --- a/src/test/auxiliary/changing-crates-a2.rs +++ b/src/test/auxiliary/changing-crates-a2.rs @@ -11,4 +11,3 @@ #![crate_name = "a"] pub fn foo() { println!("hello!"); } - diff --git a/src/test/auxiliary/changing-crates-b.rs b/src/test/auxiliary/changing-crates-b.rs index 81f924e29d..7b1190fc08 100644 --- a/src/test/auxiliary/changing-crates-b.rs +++ b/src/test/auxiliary/changing-crates-b.rs @@ -12,4 +12,4 @@ extern crate a; -pub fn foo() { a::foo::(); } +pub fn foo() { a::foo::(); } diff --git a/src/test/auxiliary/check_static_recursion_foreign_helper.rs b/src/test/auxiliary/check_static_recursion_foreign_helper.rs index b5c2a4f135..c0d81cd8e1 100644 --- a/src/test/auxiliary/check_static_recursion_foreign_helper.rs +++ b/src/test/auxiliary/check_static_recursion_foreign_helper.rs @@ -10,6 +10,8 @@ // Helper definition for test/run-pass/check-static-recursion-foreign.rs. +#![feature(libc)] + #[crate_id = "check_static_recursion_foreign_helper"] #[crate_type = "lib"] diff --git a/src/test/compile-fail/issue-16465.rs b/src/test/auxiliary/coherence_copy_like_lib.rs similarity index 59% rename from src/test/compile-fail/issue-16465.rs rename to src/test/auxiliary/coherence_copy_like_lib.rs index 825b40cb32..a1e1b48c2c 100644 --- a/src/test/compile-fail/issue-16465.rs +++ b/src/test/auxiliary/coherence_copy_like_lib.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,17 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Used to cause an ICE +#![crate_type = "rlib"] +#![feature(fundamental)] -struct Foo{ - x : T -} +use std::marker::MarkerTrait; -type FooInt = Foo; +pub trait MyCopy : MarkerTrait { } +impl MyCopy for i32 { } -impl Drop for FooInt { -//~^ ERROR cannot implement a destructor on a structure with type parameters - fn drop(&mut self){} -} +pub struct MyStruct(T); -fn main() {} +#[fundamental] +pub struct MyFundamentalStruct(T); diff --git a/src/test/auxiliary/coherence-lib.rs b/src/test/auxiliary/coherence_lib.rs similarity index 100% rename from src/test/auxiliary/coherence-lib.rs rename to src/test/auxiliary/coherence_lib.rs diff --git a/src/test/auxiliary/coherence-orphan-lib.rs b/src/test/auxiliary/coherence_orphan_lib.rs similarity index 99% rename from src/test/auxiliary/coherence-orphan-lib.rs rename to src/test/auxiliary/coherence_orphan_lib.rs index cc42b288e6..93d8fd3da8 100644 --- a/src/test/auxiliary/coherence-orphan-lib.rs +++ b/src/test/auxiliary/coherence_orphan_lib.rs @@ -11,4 +11,3 @@ pub trait TheTrait : ::std::marker::PhantomFn { fn the_fn(&self); } - diff --git a/src/test/auxiliary/crate_with_invalid_spans.rs b/src/test/auxiliary/crate_with_invalid_spans.rs new file mode 100644 index 0000000000..b37533d2da --- /dev/null +++ b/src/test/auxiliary/crate_with_invalid_spans.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +// no-prefer-dynamic + +// compile-flags: -g + +#[macro_use] +mod crate_with_invalid_spans_macros; + +pub fn exported_generic(x: T, y: u32) -> (T, u32) { + // Using the add1 macro will produce an invalid span, because the `y` passed + // to the macro will have a span from this file, but the rest of the code + // generated from the macro will have spans from the macro-defining file. + // The AST node for the (1 + y) expression generated by the macro will then + // take it's `lo` span bound from the `1` literal in the macro-defining file + // and it's `hi` bound from `y` in this file, which should be lower than the + // `lo` and even lower than the lower bound of the FileMap it is supposedly + // contained in because the FileMap for this file was allocated earlier than + // the FileMap of the macro-defining file. + return (x, add1!(y)); +} diff --git a/src/test/auxiliary/crate_with_invalid_spans_macros.rs b/src/test/auxiliary/crate_with_invalid_spans_macros.rs new file mode 100644 index 0000000000..112315af84 --- /dev/null +++ b/src/test/auxiliary/crate_with_invalid_spans_macros.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! add1 { + ($e:expr) => ({ + let a = 1 + $e; + let b = $e + 1; + a + b - 1 + }) +} diff --git a/src/test/auxiliary/crateresolve1-1.rs b/src/test/auxiliary/crateresolve1-1.rs index e26ea7c4fa..050f2fe732 100644 --- a/src/test/auxiliary/crateresolve1-1.rs +++ b/src/test/auxiliary/crateresolve1-1.rs @@ -12,4 +12,4 @@ #![crate_name = "crateresolve1"] #![crate_type = "lib"] -pub fn f() -> int { 10 } +pub fn f() -> isize { 10 } diff --git a/src/test/auxiliary/crateresolve1-2.rs b/src/test/auxiliary/crateresolve1-2.rs index 715171b143..d19b3bafba 100644 --- a/src/test/auxiliary/crateresolve1-2.rs +++ b/src/test/auxiliary/crateresolve1-2.rs @@ -12,4 +12,4 @@ #![crate_name = "crateresolve1"] #![crate_type = "lib"] -pub fn f() -> int { 20 } +pub fn f() -> isize { 20 } diff --git a/src/test/auxiliary/crateresolve1-3.rs b/src/test/auxiliary/crateresolve1-3.rs index f733b5b908..c5096ac49a 100644 --- a/src/test/auxiliary/crateresolve1-3.rs +++ b/src/test/auxiliary/crateresolve1-3.rs @@ -12,4 +12,4 @@ #![crate_name = "crateresolve1"] #![crate_type = "lib"] -pub fn f() -> int { 30 } +pub fn f() -> isize { 30 } diff --git a/src/test/auxiliary/crateresolve3-1.rs b/src/test/auxiliary/crateresolve3-1.rs index 473528c681..0e02a8d96a 100644 --- a/src/test/auxiliary/crateresolve3-1.rs +++ b/src/test/auxiliary/crateresolve3-1.rs @@ -12,4 +12,4 @@ #![crate_type = "lib"] -pub fn f() -> int { 10 } +pub fn f() -> isize { 10 } diff --git a/src/test/auxiliary/crateresolve3-2.rs b/src/test/auxiliary/crateresolve3-2.rs index 1e95fa6b63..6a11465b27 100644 --- a/src/test/auxiliary/crateresolve3-2.rs +++ b/src/test/auxiliary/crateresolve3-2.rs @@ -12,4 +12,4 @@ #![crate_type = "lib"] -pub fn g() -> int { 20 } +pub fn g() -> isize { 20 } diff --git a/src/test/auxiliary/crateresolve4a-1.rs b/src/test/auxiliary/crateresolve4a-1.rs index 68a69f6dc9..579e93aa05 100644 --- a/src/test/auxiliary/crateresolve4a-1.rs +++ b/src/test/auxiliary/crateresolve4a-1.rs @@ -11,4 +11,4 @@ #![crate_name="crateresolve4a#0.1"] #![crate_type = "lib"] -pub fn f() -> int { 10 } +pub fn f() -> isize { 10 } diff --git a/src/test/auxiliary/crateresolve4a-2.rs b/src/test/auxiliary/crateresolve4a-2.rs index 6e23fddbce..7da96e07b3 100644 --- a/src/test/auxiliary/crateresolve4a-2.rs +++ b/src/test/auxiliary/crateresolve4a-2.rs @@ -11,4 +11,4 @@ #![crate_name="crateresolve4a#0.2"] #![crate_type = "lib"] -pub fn g() -> int { 20 } +pub fn g() -> isize { 20 } diff --git a/src/test/auxiliary/crateresolve4b-1.rs b/src/test/auxiliary/crateresolve4b-1.rs index 843fd57ee4..9e4b0d158e 100644 --- a/src/test/auxiliary/crateresolve4b-1.rs +++ b/src/test/auxiliary/crateresolve4b-1.rs @@ -15,4 +15,4 @@ extern crate "crateresolve4a#0.2" as crateresolve4a; -pub fn f() -> int { crateresolve4a::g() } +pub fn f() -> isize { crateresolve4a::g() } diff --git a/src/test/auxiliary/crateresolve4b-2.rs b/src/test/auxiliary/crateresolve4b-2.rs index 28c89c7931..a50b8dbf95 100644 --- a/src/test/auxiliary/crateresolve4b-2.rs +++ b/src/test/auxiliary/crateresolve4b-2.rs @@ -15,4 +15,4 @@ extern crate "crateresolve4a#0.1" as crateresolve4a; -pub fn g() -> int { crateresolve4a::f() } +pub fn g() -> isize { crateresolve4a::f() } diff --git a/src/test/auxiliary/crateresolve5-1.rs b/src/test/auxiliary/crateresolve5-1.rs index 223e4f50ae..eaec37ed41 100644 --- a/src/test/auxiliary/crateresolve5-1.rs +++ b/src/test/auxiliary/crateresolve5-1.rs @@ -12,7 +12,7 @@ #![crate_type = "lib"] -pub struct NameVal { pub name: String, pub val: int } +pub struct NameVal { pub name: String, pub val: isize } pub fn struct_nameval() -> NameVal { NameVal { name: "crateresolve5".to_string(), val: 10 } @@ -31,4 +31,4 @@ impl PartialEq for e { fn ne(&self, other: &e) -> bool { !nominal_eq(*self, *other) } } -pub fn f() -> int { 10 } +pub fn f() -> isize { 10 } diff --git a/src/test/auxiliary/crateresolve5-2.rs b/src/test/auxiliary/crateresolve5-2.rs index 38740886b3..14d28c709c 100644 --- a/src/test/auxiliary/crateresolve5-2.rs +++ b/src/test/auxiliary/crateresolve5-2.rs @@ -12,7 +12,7 @@ #![crate_type = "lib"] -pub struct NameVal { pub name: String, pub val: int } +pub struct NameVal { pub name: String, pub val: isize } pub fn struct_nameval() -> NameVal { NameVal { name: "crateresolve5".to_string(), val: 10 } } @@ -30,4 +30,4 @@ pub fn nominal() -> e { e_val } pub fn nominal_neq(_e1: e, _e2: e) -> bool { false } -pub fn f() -> int { 20 } +pub fn f() -> isize { 20 } diff --git a/src/test/auxiliary/crateresolve7x.rs b/src/test/auxiliary/crateresolve7x.rs index 801ace7d80..c05d292eae 100644 --- a/src/test/auxiliary/crateresolve7x.rs +++ b/src/test/auxiliary/crateresolve7x.rs @@ -14,10 +14,10 @@ // These both have the same version but differ in other metadata pub mod a { extern crate cr_1 (name = "crateresolve_calories", vers = "0.1", calories="100"); - pub fn f() -> int { cr_1::f() } + pub fn f() -> isize { cr_1::f() } } pub mod b { extern crate cr_2 (name = "crateresolve_calories", vers = "0.1", calories="200"); - pub fn f() -> int { cr_2::f() } + pub fn f() -> isize { cr_2::f() } } diff --git a/src/test/auxiliary/crateresolve8-1.rs b/src/test/auxiliary/crateresolve8-1.rs index 5262d66297..bc2a2d83bf 100644 --- a/src/test/auxiliary/crateresolve8-1.rs +++ b/src/test/auxiliary/crateresolve8-1.rs @@ -13,4 +13,4 @@ #![crate_type = "lib"] -pub fn f() -> int { 20 } +pub fn f() -> isize { 20 } diff --git a/src/test/auxiliary/crateresolve_calories-1.rs b/src/test/auxiliary/crateresolve_calories-1.rs index 4dba722971..c1705d687a 100644 --- a/src/test/auxiliary/crateresolve_calories-1.rs +++ b/src/test/auxiliary/crateresolve_calories-1.rs @@ -11,4 +11,4 @@ #![crate_name="crateresolve_calories#0.1"] #![crate_type = "lib"] -pub fn f() -> int { 100 } +pub fn f() -> isize { 100 } diff --git a/src/test/auxiliary/crateresolve_calories-2.rs b/src/test/auxiliary/crateresolve_calories-2.rs index c7e26c8f50..2ae87daab4 100644 --- a/src/test/auxiliary/crateresolve_calories-2.rs +++ b/src/test/auxiliary/crateresolve_calories-2.rs @@ -11,4 +11,4 @@ #![crate_name="crateresolve_calories#0.1"] #![crate_type = "lib"] -pub fn f() -> int { 200 } +pub fn f() -> isize { 200 } diff --git a/src/libcore/num/uint.rs b/src/test/auxiliary/cross_crate_spans.rs similarity index 50% rename from src/libcore/num/uint.rs rename to src/test/auxiliary/cross_crate_spans.rs index f66a0eed97..91a480ac86 100644 --- a/src/libcore/num/uint.rs +++ b/src/test/auxiliary/cross_crate_spans.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,13 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Deprecated: replaced by `usize`. -//! -//! The rollout of the new type will gradually take place over the -//! alpha cycle along with the development of clearer conventions -//! around integer types. +#![crate_type = "rlib"] +#![omit_gdb_pretty_printer_section] -#![unstable(feature = "core")] -#![deprecated(since = "1.0.0", reason = "replaced by usize")] +// no-prefer-dynamic +// compile-flags:-g -uint_module! { uint, int, ::int::BITS } +pub fn generic_function(val: T) -> (T, T) { + let result = (val.clone(), val.clone()); + let a_variable: u32 = 123456789; + let another_variable: f64 = 123456789.5; + zzz(); + result +} + +#[inline(never)] +fn zzz() {()} diff --git a/src/test/auxiliary/custom_derive_plugin.rs b/src/test/auxiliary/custom_derive_plugin.rs new file mode 100644 index 0000000000..e268896480 --- /dev/null +++ b/src/test/auxiliary/custom_derive_plugin.rs @@ -0,0 +1,74 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host + +#![feature(plugin_registrar)] +#![feature(box_syntax)] +#![feature(rustc_private)] + +extern crate syntax; +extern crate rustc; + +use syntax::ast; +use syntax::codemap::Span; +use syntax::ext::base::{Decorator, ExtCtxt}; +use syntax::ext::build::AstBuilder; +use syntax::ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure}; +use syntax::ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self}; +use syntax::parse::token; +use syntax::ptr::P; +use rustc::plugin::Registry; + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_syntax_extension( + token::intern("derive_TotalSum"), + Decorator(box expand)); +} + +fn expand(cx: &mut ExtCtxt, + span: Span, + mitem: &ast::MetaItem, + item: &ast::Item, + push: &mut FnMut(P)) { + let trait_def = TraitDef { + span: span, + attributes: vec![], + path: Path::new(vec!["TotalSum"]), + additional_bounds: vec![], + generics: LifetimeBounds::empty(), + associated_types: vec![], + methods: vec![ + MethodDef { + name: "total_sum", + generics: LifetimeBounds::empty(), + explicit_self: borrowed_explicit_self(), + args: vec![], + ret_ty: Literal(Path::new_local("isize")), + attributes: vec![], + combine_substructure: combine_substructure(box |cx, span, substr| { + let zero = cx.expr_int(span, 0); + cs_fold(false, + |cx, span, subexpr, field, _| { + cx.expr_binary(span, ast::BiAdd, subexpr, + cx.expr_method_call(span, field, + token::str_to_ident("total_sum"), vec![])) + }, + zero, + box |cx, span, _, _| { cx.span_bug(span, "wtf??"); }, + cx, span, substr) + }), + }, + ], + }; + + trait_def.expand(cx, mitem, item, |i| push(i)) +} diff --git a/src/test/auxiliary/default_type_params_xc.rs b/src/test/auxiliary/default_type_params_xc.rs index 0a65174911..fe852e5d8e 100644 --- a/src/test/auxiliary/default_type_params_xc.rs +++ b/src/test/auxiliary/default_type_params_xc.rs @@ -13,4 +13,3 @@ pub struct Heap; pub struct FakeHeap; pub struct FakeVec { pub f: Option<(T,A)> } - diff --git a/src/test/auxiliary/extern-crosscrate-source.rs b/src/test/auxiliary/extern-crosscrate-source.rs index 0e3b531e45..fc2e328f68 100644 --- a/src/test/auxiliary/extern-crosscrate-source.rs +++ b/src/test/auxiliary/extern-crosscrate-source.rs @@ -10,6 +10,7 @@ #![crate_name="externcallback"] #![crate_type = "lib"] +#![feature(libc)] extern crate libc; diff --git a/src/test/auxiliary/extern_calling_convention.rs b/src/test/auxiliary/extern_calling_convention.rs index d7e84a474e..91a404bbba 100644 --- a/src/test/auxiliary/extern_calling_convention.rs +++ b/src/test/auxiliary/extern_calling_convention.rs @@ -13,7 +13,7 @@ #[inline(never)] #[cfg(target_arch = "x86_64")] -pub extern "win64" fn foo(a: int, b: int, c: int, d: int) { +pub extern "win64" fn foo(a: isize, b: isize, c: isize, d: isize) { assert!(a == 1); assert!(b == 2); assert!(c == 3); @@ -25,7 +25,7 @@ pub extern "win64" fn foo(a: int, b: int, c: int, d: int) { #[inline(never)] #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))] -pub extern fn foo(a: int, b: int, c: int, d: int) { +pub extern fn foo(a: isize, b: isize, c: isize, d: isize) { assert!(a == 1); assert!(b == 2); assert!(c == 3); diff --git a/src/test/auxiliary/foreign_lib.rs b/src/test/auxiliary/foreign_lib.rs index a5d672e3c0..92239ce559 100644 --- a/src/test/auxiliary/foreign_lib.rs +++ b/src/test/auxiliary/foreign_lib.rs @@ -9,6 +9,7 @@ // except according to those terms. #![crate_name="foreign_lib"] +#![feature(libc)] pub mod rustrt { extern crate libc; diff --git a/src/test/auxiliary/go_trait.rs b/src/test/auxiliary/go_trait.rs index 4902766534..0a921c8f5b 100644 --- a/src/test/auxiliary/go_trait.rs +++ b/src/test/auxiliary/go_trait.rs @@ -11,33 +11,33 @@ // Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. pub trait Go { - fn go(&self, arg: int); + fn go(&self, arg: isize); } -pub fn go(this: &G, arg: int) { +pub fn go(this: &G, arg: isize) { this.go(arg) } pub trait GoMut { - fn go_mut(&mut self, arg: int); + fn go_mut(&mut self, arg: isize); } -pub fn go_mut(this: &mut G, arg: int) { +pub fn go_mut(this: &mut G, arg: isize) { this.go_mut(arg) } pub trait GoOnce { - fn go_once(self, arg: int); + fn go_once(self, arg: isize); } -pub fn go_once(this: G, arg: int) { +pub fn go_once(this: G, arg: isize) { this.go_once(arg) } impl GoMut for G where G : Go { - fn go_mut(&mut self, arg: int) { + fn go_mut(&mut self, arg: isize) { go(&*self, arg) } } @@ -45,7 +45,7 @@ impl GoMut for G impl GoOnce for G where G : GoMut { - fn go_once(mut self, arg: int) { + fn go_once(mut self, arg: isize) { go_mut(&mut self, arg) } } diff --git a/src/test/auxiliary/impl_privacy_xc_1.rs b/src/test/auxiliary/impl_privacy_xc_1.rs index df4e0658cb..ad3cdedf7e 100644 --- a/src/test/auxiliary/impl_privacy_xc_1.rs +++ b/src/test/auxiliary/impl_privacy_xc_1.rs @@ -11,7 +11,7 @@ #![crate_type = "lib"] pub struct Fish { - pub x: int + pub x: isize } impl Fish { diff --git a/src/test/auxiliary/impl_privacy_xc_2.rs b/src/test/auxiliary/impl_privacy_xc_2.rs index 4d4b1bcc4c..c3212b0fc6 100644 --- a/src/test/auxiliary/impl_privacy_xc_2.rs +++ b/src/test/auxiliary/impl_privacy_xc_2.rs @@ -11,7 +11,7 @@ #![crate_type = "lib"] pub struct Fish { - pub x: int + pub x: isize } mod unexported { diff --git a/src/test/auxiliary/inherit_struct_lib.rs b/src/test/auxiliary/inherit_struct_lib.rs index fd049a25a0..6f5ddfd37a 100644 --- a/src/test/auxiliary/inherit_struct_lib.rs +++ b/src/test/auxiliary/inherit_struct_lib.rs @@ -12,11 +12,11 @@ #![feature(struct_inherit)] pub virtual struct S1 { - pub f1: int, + pub f1: isize, } pub struct S2 : S1 { - pub f2: int, + pub f2: isize, } pub fn test_s2(s2: S2) { diff --git a/src/test/auxiliary/inherited_stability.rs b/src/test/auxiliary/inherited_stability.rs index 77eb82f802..c09cc53466 100644 --- a/src/test/auxiliary/inherited_stability.rs +++ b/src/test/auxiliary/inherited_stability.rs @@ -43,7 +43,7 @@ pub trait Stable { fn stable(&self); } -impl Stable for uint { +impl Stable for usize { fn unstable(&self) {} fn stable(&self) {} } diff --git a/src/test/auxiliary/inner_static.rs b/src/test/auxiliary/inner_static.rs index ca5c6072cb..0d15c13a4e 100644 --- a/src/test/auxiliary/inner_static.rs +++ b/src/test/auxiliary/inner_static.rs @@ -15,43 +15,43 @@ pub mod test { pub struct A { pub v: T } impl A { - pub fn foo(&self) -> int { - static a: int = 5; + pub fn foo(&self) -> isize { + static a: isize = 5; return a } - pub fn bar(&self) -> int { - static a: int = 6; + pub fn bar(&self) -> isize { + static a: isize = 6; return a; } } } impl A { - pub fn foo(&self) -> int { - static a: int = 1; + pub fn foo(&self) -> isize { + static a: isize = 1; return a } - pub fn bar(&self) -> int { - static a: int = 2; + pub fn bar(&self) -> isize { + static a: isize = 2; return a; } } impl B { - pub fn foo(&self) -> int { - static a: int = 3; + pub fn foo(&self) -> isize { + static a: isize = 3; return a } - pub fn bar(&self) -> int { - static a: int = 4; + pub fn bar(&self) -> isize { + static a: isize = 4; return a; } } -pub fn foo() -> int { +pub fn foo() -> isize { let a = A { v: () }; let b = B { v: () }; let c = test::A { v: () }; diff --git a/src/test/auxiliary/internal_unstable.rs b/src/test/auxiliary/internal_unstable.rs new file mode 100644 index 0000000000..3d59b8e900 --- /dev/null +++ b/src/test/auxiliary/internal_unstable.rs @@ -0,0 +1,60 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(staged_api, allow_internal_unstable)] +#![staged_api] +#![stable(feature = "stable", since = "1.0.0")] + +#[unstable(feature = "function")] +pub fn unstable() {} + + +#[stable(feature = "stable", since = "1.0.0")] +pub struct Foo { + #[unstable(feature = "struct_field")] + pub x: u8 +} + +#[allow_internal_unstable] +#[macro_export] +macro_rules! call_unstable_allow { + () => { $crate::unstable() } +} + +#[allow_internal_unstable] +#[macro_export] +macro_rules! construct_unstable_allow { + ($e: expr) => { + $crate::Foo { x: $e } + } +} + +#[allow_internal_unstable] +#[macro_export] +macro_rules! pass_through_allow { + ($e: expr) => { $e } +} + +#[macro_export] +macro_rules! call_unstable_noallow { + () => { $crate::unstable() } +} + +#[macro_export] +macro_rules! construct_unstable_noallow { + ($e: expr) => { + $crate::Foo { x: $e } + } +} + +#[macro_export] +macro_rules! pass_through_noallow { + ($e: expr) => { $e } +} diff --git a/src/test/auxiliary/iss.rs b/src/test/auxiliary/iss.rs index 690d5783c4..b231efa0fe 100644 --- a/src/test/auxiliary/iss.rs +++ b/src/test/auxiliary/iss.rs @@ -20,4 +20,3 @@ fn no_op() { } pub const D : C = C { k: no_op as fn() }; - diff --git a/src/test/auxiliary/issue-11224.rs b/src/test/auxiliary/issue-11224.rs index 560844332a..21935b6b9a 100644 --- a/src/test/auxiliary/issue-11224.rs +++ b/src/test/auxiliary/issue-11224.rs @@ -15,12 +15,12 @@ mod inner { fn f(&self) { f(); } } - impl Trait for int {} + impl Trait for isize {} fn f() {} } pub fn foo() { - let a = &1 as &inner::Trait; + let a = &1is as &inner::Trait; a.f(); } diff --git a/src/test/auxiliary/issue-11225-1.rs b/src/test/auxiliary/issue-11225-1.rs index 88277af4a5..37543ea1d3 100644 --- a/src/test/auxiliary/issue-11225-1.rs +++ b/src/test/auxiliary/issue-11225-1.rs @@ -13,7 +13,7 @@ mod inner { fn f(&self) { f(); } } - impl Trait for int {} + impl Trait for isize {} fn f() {} } diff --git a/src/test/auxiliary/issue-11225-2.rs b/src/test/auxiliary/issue-11225-2.rs index 848574a61f..f12e4c9b6e 100644 --- a/src/test/auxiliary/issue-11225-2.rs +++ b/src/test/auxiliary/issue-11225-2.rs @@ -25,7 +25,7 @@ pub trait Outer { fn foo(&self, t: T) { t.f(); } } -impl Outer for int {} +impl Outer for isize {} pub fn foo(t: T) { t.foo(inner::Foo); diff --git a/src/test/auxiliary/issue-11529.rs b/src/test/auxiliary/issue-11529.rs index a8a4c438e6..21ef99e3c3 100644 --- a/src/test/auxiliary/issue-11529.rs +++ b/src/test/auxiliary/issue-11529.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct A<'a>(pub &'a int); +pub struct A<'a>(pub &'a isize); diff --git a/src/test/auxiliary/issue-12133-dylib2.rs b/src/test/auxiliary/issue-12133-dylib2.rs index ee2b11da8f..fa5722ae6a 100644 --- a/src/test/auxiliary/issue-12133-dylib2.rs +++ b/src/test/auxiliary/issue-12133-dylib2.rs @@ -12,6 +12,5 @@ #![crate_type = "dylib"] -extern crate "issue-12133-rlib" as a; -extern crate "issue-12133-dylib" as b; - +extern crate issue_12133_rlib as a; +extern crate issue_12133_dylib as b; diff --git a/src/test/auxiliary/issue-13560-3.rs b/src/test/auxiliary/issue-13560-3.rs index 5510d3e2e0..c0539aa1b6 100644 --- a/src/test/auxiliary/issue-13560-3.rs +++ b/src/test/auxiliary/issue-13560-3.rs @@ -12,6 +12,5 @@ #![crate_type = "rlib"] -#[macro_use] #[no_link] extern crate "issue-13560-1" as t1; -#[macro_use] extern crate "issue-13560-2" as t2; - +#[macro_use] #[no_link] extern crate issue_13560_1 as t1; +#[macro_use] extern crate issue_13560_2 as t2; diff --git a/src/test/auxiliary/issue-13620-2.rs b/src/test/auxiliary/issue-13620-2.rs index da47115e2b..554170bc13 100644 --- a/src/test/auxiliary/issue-13620-2.rs +++ b/src/test/auxiliary/issue-13620-2.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate "issue-13620-1" as crate1; +extern crate issue_13620_1 as crate1; pub static FOO2: crate1::Foo = crate1::FOO; diff --git a/src/test/auxiliary/issue-13872-2.rs b/src/test/auxiliary/issue-13872-2.rs index 8294d2b459..bb51417528 100644 --- a/src/test/auxiliary/issue-13872-2.rs +++ b/src/test/auxiliary/issue-13872-2.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate "issue-13872-1" as foo; +extern crate issue_13872_1 as foo; pub use foo::A::B; diff --git a/src/test/auxiliary/issue-13872-3.rs b/src/test/auxiliary/issue-13872-3.rs index 827a9f18f4..e20618f1ec 100644 --- a/src/test/auxiliary/issue-13872-3.rs +++ b/src/test/auxiliary/issue-13872-3.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate "issue-13872-2" as bar; +extern crate issue_13872_2 as bar; use bar::B; diff --git a/src/test/auxiliary/issue-14422.rs b/src/test/auxiliary/issue-14422.rs index 3e23698397..32af6d9255 100644 --- a/src/test/auxiliary/issue-14422.rs +++ b/src/test/auxiliary/issue-14422.rs @@ -23,7 +23,7 @@ mod src { pub mod hidden_core { use super::aliases::B; - #[derive(Copy)] + #[derive(Copy, Clone)] pub struct A; pub fn make() -> B { A } diff --git a/src/test/auxiliary/issue-17718.rs b/src/test/auxiliary/issue-17718.rs index cbe56b00c1..67474e7902 100644 --- a/src/test/auxiliary/issue-17718.rs +++ b/src/test/auxiliary/issue-17718.rs @@ -10,13 +10,13 @@ use std::sync::atomic; -pub const C1: uint = 1; +pub const C1: usize = 1; pub const C2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; pub const C3: fn() = foo; -pub const C4: uint = C1 * C1 + C1 / C1; -pub const C5: &'static uint = &C4; +pub const C4: usize = C1 * C1 + C1 / C1; +pub const C5: &'static usize = &C4; -pub static S1: uint = 3; +pub static S1: usize = 3; pub static S2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; fn foo() {} diff --git a/src/test/auxiliary/issue-2414-a.rs b/src/test/auxiliary/issue-2414-a.rs index fe1ef549d0..8c414193bd 100644 --- a/src/test/auxiliary/issue-2414-a.rs +++ b/src/test/auxiliary/issue-2414-a.rs @@ -11,7 +11,7 @@ #![crate_name="a"] #![crate_type = "lib"] -type t1 = uint; +type t1 = usize; trait foo { fn foo(&self); diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index 89b3b56121..e85a0a90af 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -15,8 +15,8 @@ use std::marker; -struct arc_destruct { - _data: int, +struct arc_destruct { + _data: isize, _marker: marker::PhantomData } @@ -25,7 +25,7 @@ impl Drop for arc_destruct { fn drop(&mut self) {} } -fn arc_destruct(data: int) -> arc_destruct { +fn arc_destruct(data: isize) -> arc_destruct { arc_destruct { _data: data, _marker: marker::PhantomData @@ -41,7 +41,7 @@ fn init() -> arc_destruct { } struct context_res { - ctx : int, + ctx : isize, } impl Drop for context_res { diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs index dd1ad413a3..604a3e69a2 100644 --- a/src/test/auxiliary/issue-2631-a.rs +++ b/src/test/auxiliary/issue-2631-a.rs @@ -19,6 +19,6 @@ pub type header_map = HashMap>>>>; // the unused ty param is necessary so this gets monomorphized pub fn request(req: &header_map) { - let data = req["METHOD".to_string()].clone(); + let data = req[&"METHOD".to_string()].clone(); let _x = data.borrow().clone()[0].clone(); } diff --git a/src/test/auxiliary/issue-3012-1.rs b/src/test/auxiliary/issue-3012-1.rs index 25eb67e042..b6199f59eb 100644 --- a/src/test/auxiliary/issue-3012-1.rs +++ b/src/test/auxiliary/issue-3012-1.rs @@ -10,6 +10,7 @@ #![crate_name="socketlib"] #![crate_type = "lib"] +#![feature(libc)] pub mod socket { extern crate libc; diff --git a/src/test/auxiliary/issue-5521.rs b/src/test/auxiliary/issue-5521.rs index d9d393cc74..82bd2b6420 100644 --- a/src/test/auxiliary/issue-5521.rs +++ b/src/test/auxiliary/issue-5521.rs @@ -11,5 +11,4 @@ use std::collections::HashMap; -pub type map = Box>; - +pub type map = Box>; diff --git a/src/test/auxiliary/issue-8044.rs b/src/test/auxiliary/issue-8044.rs index 7bfd2e7964..8f328699ae 100644 --- a/src/test/auxiliary/issue-8044.rs +++ b/src/test/auxiliary/issue-8044.rs @@ -21,5 +21,5 @@ pub fn leaf(value: V) -> TreeItem { } fn main() { - BTree:: { node: leaf(1) }; + BTree:: { node: leaf(1) }; } diff --git a/src/test/auxiliary/issue-9906.rs b/src/test/auxiliary/issue-9906.rs index 1e746bf39d..0da0b9fa47 100644 --- a/src/test/auxiliary/issue-9906.rs +++ b/src/test/auxiliary/issue-9906.rs @@ -14,9 +14,9 @@ pub use other::FooBar; pub use other::foo; mod other { - pub struct FooBar{value: int} + pub struct FooBar{value: isize} impl FooBar{ - pub fn new(val: int) -> FooBar { + pub fn new(val: isize) -> FooBar { FooBar{value: val} } } diff --git a/src/test/auxiliary/issue13213aux.rs b/src/test/auxiliary/issue13213aux.rs index 227fab7304..d0566a1e09 100644 --- a/src/test/auxiliary/issue13213aux.rs +++ b/src/test/auxiliary/issue13213aux.rs @@ -13,13 +13,13 @@ pub use private::P; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct S { p: P, } mod private { - #[derive(Copy)] + #[derive(Copy, Clone)] pub struct P { p: i32, } @@ -27,4 +27,3 @@ mod private { } pub static A: S = S { p: private::THREE }; - diff --git a/src/test/auxiliary/issue13507.rs b/src/test/auxiliary/issue13507.rs index f24721adb5..22ccb3dfac 100644 --- a/src/test/auxiliary/issue13507.rs +++ b/src/test/auxiliary/issue13507.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + pub mod testtypes { use std::any::TypeId; @@ -39,10 +41,10 @@ pub mod testtypes { pub type FooChar = char; // Tests ty_int (does not test all variants of IntTy) - pub type FooInt = int; + pub type FooInt = isize; // Tests ty_uint (does not test all variants of UintTy) - pub type FooUint = uint; + pub type FooUint = usize; // Tests ty_float (does not test all variants of FloatTy) pub type FooFloat = f64; @@ -51,8 +53,8 @@ pub mod testtypes { // Tests ty_enum pub enum FooEnum { - VarA(uint), - VarB(uint, uint) + VarA(usize), + VarB(usize, usize) } // Tests ty_uniq (of u8) @@ -69,14 +71,14 @@ pub mod testtypes { // Tests ty_trait pub trait FooTrait { - fn foo_method(&self) -> uint; - fn foo_static_method() -> uint; + fn foo_method(&self) -> usize; + fn foo_static_method() -> usize; } // Tests ty_struct pub struct FooStruct { - pub pub_foo_field: uint, - foo_field: uint + pub pub_foo_field: usize, + foo_field: usize } // Tests ty_tup diff --git a/src/test/auxiliary/issue-11680.rs b/src/test/auxiliary/issue_11680.rs similarity index 93% rename from src/test/auxiliary/issue-11680.rs rename to src/test/auxiliary/issue_11680.rs index 249a1bab46..18f78750b1 100644 --- a/src/test/auxiliary/issue-11680.rs +++ b/src/test/auxiliary/issue_11680.rs @@ -9,11 +9,11 @@ // except according to those terms. enum Foo { - Bar(int) + Bar(isize) } pub mod test { enum Foo { - Bar(int) + Bar(isize) } } diff --git a/src/test/auxiliary/issue-12612-1.rs b/src/test/auxiliary/issue_12612_1.rs similarity index 100% rename from src/test/auxiliary/issue-12612-1.rs rename to src/test/auxiliary/issue_12612_1.rs diff --git a/src/test/auxiliary/issue-12612-2.rs b/src/test/auxiliary/issue_12612_2.rs similarity index 100% rename from src/test/auxiliary/issue-12612-2.rs rename to src/test/auxiliary/issue_12612_2.rs diff --git a/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs b/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs index bb57b4a98b..58dee1216e 100644 --- a/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs +++ b/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs @@ -11,7 +11,7 @@ // ignore-stage1 // force-host -#![feature(plugin_registrar, quote)] +#![feature(plugin_registrar, quote, rustc_private)] #![crate_type = "dylib"] extern crate syntax; @@ -19,7 +19,8 @@ extern crate rustc; use syntax::ast; use syntax::codemap; -use syntax::ext::base::{ExtCtxt, MacResult, MacItems}; +use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; +use syntax::util::small_vector::SmallVector; use rustc::plugin::Registry; #[plugin_registrar] @@ -28,8 +29,8 @@ pub fn plugin_registrar(reg: &mut Registry) { } fn expand(cx: &mut ExtCtxt, _: codemap::Span, _: &[ast::TokenTree]) -> Box { - MacItems::new(vec![ + MacEager::items(SmallVector::many(vec![ quote_item!(cx, struct Struct1;).unwrap(), quote_item!(cx, struct Struct2;).unwrap() - ].into_iter()) + ])) } diff --git a/src/test/auxiliary/issue-16725.rs b/src/test/auxiliary/issue_16725.rs similarity index 99% rename from src/test/auxiliary/issue-16725.rs rename to src/test/auxiliary/issue_16725.rs index 7f388c13e1..b3b04b4a5a 100644 --- a/src/test/auxiliary/issue-16725.rs +++ b/src/test/auxiliary/issue_16725.rs @@ -11,4 +11,3 @@ extern { fn bar(); } - diff --git a/src/test/auxiliary/issue-17718-const-privacy.rs b/src/test/auxiliary/issue_17718_const_privacy.rs similarity index 86% rename from src/test/auxiliary/issue-17718-const-privacy.rs rename to src/test/auxiliary/issue_17718_const_privacy.rs index 3657d39ff7..3901d73382 100644 --- a/src/test/auxiliary/issue-17718-const-privacy.rs +++ b/src/test/auxiliary/issue_17718_const_privacy.rs @@ -10,9 +10,9 @@ pub use foo::FOO2; -pub const FOO: uint = 3; -const BAR: uint = 3; +pub const FOO: usize = 3; +const BAR: usize = 3; mod foo { - pub const FOO2: uint = 3; + pub const FOO2: usize = 3; } diff --git a/src/test/auxiliary/issue_19293.rs b/src/test/auxiliary/issue_19293.rs index 40c8eb9b23..12894ad72e 100644 --- a/src/test/auxiliary/issue_19293.rs +++ b/src/test/auxiliary/issue_19293.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct Foo (pub int); +pub struct Foo (pub isize); pub enum MyEnum { Foo(Foo), } diff --git a/src/test/auxiliary/issue-21202.rs b/src/test/auxiliary/issue_21202.rs similarity index 100% rename from src/test/auxiliary/issue-21202.rs rename to src/test/auxiliary/issue_21202.rs diff --git a/src/test/auxiliary/issue_2723_a.rs b/src/test/auxiliary/issue_2723_a.rs index bd8857ceef..44bea136a7 100644 --- a/src/test/auxiliary/issue_2723_a.rs +++ b/src/test/auxiliary/issue_2723_a.rs @@ -9,6 +9,6 @@ // except according to those terms. -pub unsafe fn f(xs: Vec ) { +pub unsafe fn f(xs: Vec ) { xs.iter().map(|_x| { unsafe fn q() { panic!(); } }).collect::>(); } diff --git a/src/test/auxiliary/issue_3907.rs b/src/test/auxiliary/issue_3907.rs index 545e15fe16..3d5e52d709 100644 --- a/src/test/auxiliary/issue_3907.rs +++ b/src/test/auxiliary/issue_3907.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + use std::marker::MarkerTrait; pub trait Foo : MarkerTrait { fn bar(); } - diff --git a/src/test/auxiliary/issue_3979_traits.rs b/src/test/auxiliary/issue_3979_traits.rs index 91faace7a3..5c306be69c 100644 --- a/src/test/auxiliary/issue_3979_traits.rs +++ b/src/test/auxiliary/issue_3979_traits.rs @@ -13,12 +13,12 @@ #![crate_type = "lib"] pub trait Positioned { - fn SetX(&mut self, int); - fn X(&self) -> int; + fn SetX(&mut self, isize); + fn X(&self) -> isize; } pub trait Movable: Positioned { - fn translate(&mut self, dx: int) { + fn translate(&mut self, dx: isize) { let x = self.X() + dx; self.SetX(x); } diff --git a/src/test/auxiliary/issue_5844_aux.rs b/src/test/auxiliary/issue_5844_aux.rs index 0f898ae838..5c878b1e66 100644 --- a/src/test/auxiliary/issue_5844_aux.rs +++ b/src/test/auxiliary/issue_5844_aux.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(libc)] + extern crate libc; extern "C" { pub fn rand() -> libc::c_int; } - diff --git a/src/test/auxiliary/issue_8401.rs b/src/test/auxiliary/issue_8401.rs index 9006a5d177..04b56442d0 100644 --- a/src/test/auxiliary/issue_8401.rs +++ b/src/test/auxiliary/issue_8401.rs @@ -24,4 +24,3 @@ fn foo(t: &T) { let b = B; bar(unsafe { mem::transmute(&b as &A) }, t) } - diff --git a/src/test/auxiliary/issue_9123.rs b/src/test/auxiliary/issue_9123.rs index 4f2792aebc..8c2546e76c 100644 --- a/src/test/auxiliary/issue_9123.rs +++ b/src/test/auxiliary/issue_9123.rs @@ -17,4 +17,3 @@ pub trait X { } fn dummy(&self) { } } - diff --git a/src/test/auxiliary/issue_9188.rs b/src/test/auxiliary/issue_9188.rs index 5f5a8f02fd..8ff85cc359 100644 --- a/src/test/auxiliary/issue_9188.rs +++ b/src/test/auxiliary/issue_9188.rs @@ -8,17 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo() -> &'static int { +pub fn foo() -> &'static isize { if false { - static a: int = 4; + static a: isize = 4; return &a; } else { - static a: int = 5; + static a: isize = 5; return &a; } } -pub fn bar() -> &'static int { - foo::() +pub fn bar() -> &'static isize { + foo::() } - diff --git a/src/test/auxiliary/kinds_in_metadata.rs b/src/test/auxiliary/kinds_in_metadata.rs index 7e09052398..82f182c04b 100644 --- a/src/test/auxiliary/kinds_in_metadata.rs +++ b/src/test/auxiliary/kinds_in_metadata.rs @@ -16,4 +16,3 @@ #![crate_type="lib"] pub fn f() {} - diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index b9cc20b63c..72dfc75f41 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -20,7 +20,7 @@ impl PhantomFn for U { } pub trait Sized : PhantomFn {} #[lang="panic"] -fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} } +fn panic(_: &(&'static str, &'static str, usize)) -> ! { loop {} } #[lang = "stack_exhausted"] extern fn stack_exhausted() {} @@ -33,4 +33,21 @@ pub trait Copy : PhantomFn { // Empty. } +#[lang="rem"] +pub trait Rem { + type Output = Self; + fn rem(self, rhs: RHS) -> Self::Output; +} +impl Rem for isize { + type Output = isize; + + #[inline] + fn rem(self, other: isize) -> isize { + // if you use `self % other` here, as one would expect, you + // get back an error because of potential failure/overflow, + // which tries to invoke error fns that don't have the + // appropriate signatures anymore. So...just return 0. + 0 + } +} diff --git a/src/test/auxiliary/linkage-visibility.rs b/src/test/auxiliary/linkage-visibility.rs index 6cd94ee560..d96dfd848f 100644 --- a/src/test/auxiliary/linkage-visibility.rs +++ b/src/test/auxiliary/linkage-visibility.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(std_misc, old_path)] + use std::dynamic_lib::DynamicLibrary; #[no_mangle] @@ -27,11 +29,10 @@ fn bar() { } fn baz() { } pub fn test() { - let none: Option<&Path> = None; // appease the typechecker - let lib = DynamicLibrary::open(none).unwrap(); + let lib = DynamicLibrary::open(None).unwrap(); unsafe { - assert!(lib.symbol::("foo").is_ok()); - assert!(lib.symbol::("baz").is_err()); - assert!(lib.symbol::("bar").is_err()); + assert!(lib.symbol::("foo").is_ok()); + assert!(lib.symbol::("baz").is_err()); + assert!(lib.symbol::("bar").is_err()); } } diff --git a/src/test/auxiliary/linkage1.rs b/src/test/auxiliary/linkage1.rs index a74c8c47cd..ca4046d816 100644 --- a/src/test/auxiliary/linkage1.rs +++ b/src/test/auxiliary/linkage1.rs @@ -9,6 +9,6 @@ // except according to those terms. #[no_mangle] -pub static foo: int = 3; +pub static foo: isize = 3; pub fn bar() {} diff --git a/src/test/auxiliary/lint_for_crate.rs b/src/test/auxiliary/lint_for_crate.rs new file mode 100644 index 0000000000..3b45b0ae70 --- /dev/null +++ b/src/test/auxiliary/lint_for_crate.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host + +#![feature(plugin_registrar, rustc_private)] +#![feature(box_syntax)] + +extern crate syntax; +#[macro_use] extern crate rustc; + +use syntax::{ast, attr}; +use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::plugin::Registry; + +declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]"); + +struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(CRATE_NOT_OKAY) + } + + fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) { + if !attr::contains_name(&krate.attrs, "crate_okay") { + cx.span_lint(CRATE_NOT_OKAY, krate.span, + "crate is not marked with #![crate_okay]"); + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_lint_pass(box Pass as LintPassObject); +} diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index e9d98889ff..ca5a7b75e0 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -11,7 +11,7 @@ // force-host #![feature(plugin_registrar)] -#![feature(box_syntax)] +#![feature(box_syntax, rustc_private)] extern crate syntax; diff --git a/src/test/auxiliary/lint_output_format.rs b/src/test/auxiliary/lint_output_format.rs old mode 100755 new mode 100644 index 1977e2aad2..50a9202a87 --- a/src/test/auxiliary/lint_output_format.rs +++ b/src/test/auxiliary/lint_output_format.rs @@ -16,16 +16,16 @@ #[stable(feature = "test_feature", since = "1.0.0")] #[deprecated(since = "1.0.0")] -pub fn foo() -> uint { +pub fn foo() -> usize { 20 } #[unstable(feature = "test_feature")] -pub fn bar() -> uint { +pub fn bar() -> usize { 40 } #[unstable(feature = "test_feature")] -pub fn baz() -> uint { +pub fn baz() -> usize { 30 } diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index ffb234f70c..20799ce5b4 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -11,7 +11,7 @@ // force-host #![feature(plugin_registrar)] -#![feature(box_syntax)] +#![feature(box_syntax, rustc_private)] extern crate syntax; diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index fb535eb833..bb3b71bc24 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -100,14 +100,22 @@ pub trait UnstableTrait { fn dummy(&self) { } } #[stable(feature = "test_feature", since = "1.0.0")] #[deprecated(since = "1.0.0")] -pub struct DeprecatedStruct { pub i: int } +pub struct DeprecatedStruct { + #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize +} #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] -pub struct DeprecatedUnstableStruct { pub i: int } +pub struct DeprecatedUnstableStruct { + #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize +} #[unstable(feature = "test_feature")] -pub struct UnstableStruct { pub i: int } +pub struct UnstableStruct { + #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize +} #[stable(feature = "rust1", since = "1.0.0")] -pub struct StableStruct { pub i: int } +pub struct StableStruct { + #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize +} #[stable(feature = "test_feature", since = "1.0.0")] #[deprecated(since = "1.0.0")] @@ -137,14 +145,14 @@ pub enum Enum { #[stable(feature = "test_feature", since = "1.0.0")] #[deprecated(since = "1.0.0")] -pub struct DeprecatedTupleStruct(pub int); +pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] -pub struct DeprecatedUnstableTupleStruct(pub int); +pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); #[unstable(feature = "test_feature")] -pub struct UnstableTupleStruct(pub int); +pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); #[stable(feature = "rust1", since = "1.0.0")] -pub struct StableTupleStruct(pub int); +pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); #[macro_export] macro_rules! macro_test { diff --git a/src/test/auxiliary/lint_stability_fields.rs b/src/test/auxiliary/lint_stability_fields.rs new file mode 100644 index 0000000000..66940ee008 --- /dev/null +++ b/src/test/auxiliary/lint_stability_fields.rs @@ -0,0 +1,60 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(staged_api)] +#![staged_api] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable { + #[stable(feature = "rust1", since = "1.0.0")] + pub inherit: u8, // it's a lie (stable doesn't inherit) + #[unstable(feature = "test_feature")] + pub override1: u8, + #[deprecated(since = "1.0.0")] + #[unstable(feature = "test_feature")] + pub override2: u8, +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable2(#[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "test_feature")] pub u8, + #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] pub u8); + +#[unstable(feature = "test_feature")] +pub struct Unstable { + pub inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + pub override1: u8, + #[deprecated(since = "1.0.0")] + #[unstable(feature = "test_feature")] + pub override2: u8, +} + +#[unstable(feature = "test_feature")] +pub struct Unstable2(pub u8, + #[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] pub u8); + +#[unstable(feature = "test_feature")] +#[deprecated(feature = "rust1", since = "1.0.0")] +pub struct Deprecated { + pub inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + pub override1: u8, + #[unstable(feature = "test_feature")] + pub override2: u8, +} + +#[unstable(feature = "test_feature")] +#[deprecated(feature = "rust1", since = "1.0.0")] +pub struct Deprecated2(pub u8, + #[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "test_feature")] pub u8); diff --git a/src/test/auxiliary/lint-unused-extern-crate.rs b/src/test/auxiliary/lint_unused_extern_crate.rs similarity index 100% rename from src/test/auxiliary/lint-unused-extern-crate.rs rename to src/test/auxiliary/lint_unused_extern_crate.rs diff --git a/src/test/auxiliary/logging_right_crate.rs b/src/test/auxiliary/logging_right_crate.rs index bf4ab975ce..db26b10fc6 100644 --- a/src/test/auxiliary/logging_right_crate.rs +++ b/src/test/auxiliary/logging_right_crate.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_private)] + #[macro_use] extern crate log; pub fn foo() { - fn death() -> int { panic!() } + fn death() -> isize { panic!() } debug!("{}", (||{ death() })()); } diff --git a/src/test/auxiliary/macro_crate_MacroRulesTT.rs b/src/test/auxiliary/macro_crate_MacroRulesTT.rs index d50c27a4e7..03cd70d949 100644 --- a/src/test/auxiliary/macro_crate_MacroRulesTT.rs +++ b/src/test/auxiliary/macro_crate_MacroRulesTT.rs @@ -10,7 +10,7 @@ // force-host -#![feature(plugin_registrar)] +#![feature(plugin_registrar, rustc_private)] extern crate syntax; extern crate rustc; diff --git a/src/test/auxiliary/macro_crate_nonterminal.rs b/src/test/auxiliary/macro_crate_nonterminal.rs index 922efc1aec..4f75e2b5d7 100644 --- a/src/test/auxiliary/macro_crate_nonterminal.rs +++ b/src/test/auxiliary/macro_crate_nonterminal.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn increment(x: uint) -> uint { +pub fn increment(x: usize) -> usize { x + 1 } diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index d545a42ae1..5b7e52e916 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -11,12 +11,12 @@ // force-host #![feature(plugin_registrar, quote)] -#![feature(box_syntax)] +#![feature(box_syntax, rustc_private)] extern crate syntax; extern crate rustc; -use syntax::ast::{TokenTree, Item, MetaItem, ImplItem, TraitItem, Method}; +use syntax::ast::{self, TokenTree, Item, MetaItem}; use syntax::codemap::Span; use syntax::ext::base::*; use syntax::parse::token; @@ -36,10 +36,12 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("identity", expand_identity); reg.register_syntax_extension( token::intern("into_foo"), - Modifier(box expand_into_foo)); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Modifier(Box::new(expand_into_foo))); reg.register_syntax_extension( token::intern("into_multi_foo"), - MultiModifier(box expand_into_foo_multi)); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + MultiModifier(Box::new(expand_into_foo_multi))); } fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) @@ -47,7 +49,7 @@ fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) if !tts.is_empty() { cx.span_fatal(sp, "make_a_1 takes no arguments"); } - MacExpr::new(quote_expr!(cx, 1)) + MacEager::expr(quote_expr!(cx, 1)) } // See Issue #15750 @@ -57,7 +59,7 @@ fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree]) let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec()); let expr = parser.parse_expr(); - MacExpr::new(quote_expr!(&mut *cx, $expr)) + MacEager::expr(quote_expr!(&mut *cx, $expr)) } fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: &MetaItem, it: P) @@ -80,14 +82,24 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt, })) } Annotatable::ImplItem(it) => { - Annotatable::ImplItem(ImplItem::MethodImplItem( - quote_method!(cx, fn foo(&self) -> i32 { 42 }) - )) + quote_item!(cx, impl X { fn foo(&self) -> i32 { 42 } }).unwrap().and_then(|i| { + match i.node { + ast::ItemImpl(_, _, _, _, _, mut items) => { + Annotatable::ImplItem(items.pop().expect("impl method not found")) + } + _ => unreachable!("impl parsed to something other than impl") + } + }) } Annotatable::TraitItem(it) => { - Annotatable::TraitItem(TraitItem::ProvidedMethod( - quote_method!(cx, fn foo(&self) -> i32 { 0 }) - )) + quote_item!(cx, trait X { fn foo(&self) -> i32 { 0 } }).unwrap().and_then(|i| { + match i.node { + ast::ItemTrait(_, _, _, mut items) => { + Annotatable::TraitItem(items.pop().expect("trait method not found")) + } + _ => unreachable!("trait parsed to something other than trait") + } + }) } } } @@ -114,7 +126,7 @@ fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box ( 3_usize ) + () => ( 3 ) } diff --git a/src/test/auxiliary/method_self_arg1.rs b/src/test/auxiliary/method_self_arg1.rs index 643442363a..348b71faf0 100644 --- a/src/test/auxiliary/method_self_arg1.rs +++ b/src/test/auxiliary/method_self_arg1.rs @@ -17,7 +17,7 @@ static mut COUNT: u64 = 1; pub fn get_count() -> u64 { unsafe { COUNT } } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Foo; impl Foo { diff --git a/src/test/auxiliary/method_self_arg2.rs b/src/test/auxiliary/method_self_arg2.rs index fd99da87e6..b67ec1b9bf 100644 --- a/src/test/auxiliary/method_self_arg2.rs +++ b/src/test/auxiliary/method_self_arg2.rs @@ -17,7 +17,7 @@ static mut COUNT: u64 = 1; pub fn get_count() -> u64 { unsafe { COUNT } } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Foo; impl Foo { diff --git a/src/test/auxiliary/moves_based_on_type_lib.rs b/src/test/auxiliary/moves_based_on_type_lib.rs index 6ff6da716a..f95be3f4a1 100644 --- a/src/test/auxiliary/moves_based_on_type_lib.rs +++ b/src/test/auxiliary/moves_based_on_type_lib.rs @@ -11,7 +11,7 @@ #![crate_type="lib"] pub struct S { - x: int, + x: isize, } impl Drop for S { diff --git a/src/test/auxiliary/namespaced_enum_emulate_flat.rs b/src/test/auxiliary/namespaced_enum_emulate_flat.rs index 7412c17fd4..b7bde4a74a 100644 --- a/src/test/auxiliary/namespaced_enum_emulate_flat.rs +++ b/src/test/auxiliary/namespaced_enum_emulate_flat.rs @@ -12,8 +12,8 @@ pub use Foo::*; pub enum Foo { A, - B(int), - C { a: int }, + B(isize), + C { a: isize }, } impl Foo { @@ -25,8 +25,8 @@ pub mod nest { pub enum Bar { D, - E(int), - F { a: int }, + E(isize), + F { a: isize }, } impl Bar { diff --git a/src/test/auxiliary/namespaced_enums.rs b/src/test/auxiliary/namespaced_enums.rs index 5b21d130d1..3bf39b788d 100644 --- a/src/test/auxiliary/namespaced_enums.rs +++ b/src/test/auxiliary/namespaced_enums.rs @@ -10,12 +10,11 @@ pub enum Foo { A, - B(int), - C { a: int }, + B(isize), + C { a: isize }, } impl Foo { pub fn foo() {} pub fn bar(&self) {} } - diff --git a/src/test/auxiliary/nested_item.rs b/src/test/auxiliary/nested_item.rs index fc1bea5a9f..63639c4cdb 100644 --- a/src/test/auxiliary/nested_item.rs +++ b/src/test/auxiliary/nested_item.rs @@ -9,9 +9,9 @@ // except according to those terms. // original problem -pub fn foo() -> int { +pub fn foo() -> isize { { - static foo: int = 2; + static foo: isize = 2; foo } } @@ -20,7 +20,7 @@ pub fn foo() -> int { struct Foo; impl Foo { pub fn foo(&self) { - static X: uint = 1; + static X: usize = 1; } } @@ -35,6 +35,6 @@ impl> Parser { struct Bar; impl Foo { pub fn bar(&self) { - static X: uint = 1; + static X: usize = 1; } } diff --git a/src/test/auxiliary/newtype_struct_xc.rs b/src/test/auxiliary/newtype_struct_xc.rs index acd5ef0953..be3414b7ad 100644 --- a/src/test/auxiliary/newtype_struct_xc.rs +++ b/src/test/auxiliary/newtype_struct_xc.rs @@ -10,4 +10,4 @@ #![crate_type="lib"] -pub struct Au(pub int); +pub struct Au(pub isize); diff --git a/src/test/auxiliary/noexporttypelib.rs b/src/test/auxiliary/noexporttypelib.rs index 94b079b1dc..5ae8e0d298 100644 --- a/src/test/auxiliary/noexporttypelib.rs +++ b/src/test/auxiliary/noexporttypelib.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub type oint = Option; +pub type oint = Option; pub fn foo() -> oint { Some(3) } diff --git a/src/test/auxiliary/plugin_args.rs b/src/test/auxiliary/plugin_args.rs index d0ab944813..5a615502a9 100644 --- a/src/test/auxiliary/plugin_args.rs +++ b/src/test/auxiliary/plugin_args.rs @@ -11,7 +11,7 @@ // force-host #![feature(plugin_registrar)] -#![feature(box_syntax)] +#![feature(box_syntax, rustc_private)] extern crate syntax; extern crate rustc; @@ -20,7 +20,7 @@ use std::borrow::ToOwned; use syntax::ast; use syntax::codemap::Span; use syntax::ext::build::AstBuilder; -use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacExpr, NormalTT}; +use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager, NormalTT}; use syntax::parse::token; use syntax::print::pprust; use syntax::ptr::P; @@ -38,7 +38,7 @@ impl TTMacroExpander for Expander { let args = self.args.iter().map(|i| pprust::meta_item_to_string(&*i)) .collect::>().connect(", "); let interned = token::intern_and_get_ident(&args[..]); - MacExpr::new(ecx.expr_str(sp, interned)) + MacEager::expr(ecx.expr_str(sp, interned)) } } @@ -46,5 +46,6 @@ impl TTMacroExpander for Expander { pub fn plugin_registrar(reg: &mut Registry) { let args = reg.args().clone(); reg.register_syntax_extension(token::intern("plugin_args"), - NormalTT(box Expander { args: args, }, None)); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + NormalTT(Box::new(Expander { args: args, }), None, false)); } diff --git a/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs b/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs index c460c60b02..5d93c131ca 100644 --- a/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs +++ b/src/test/auxiliary/plugin_crate_outlive_expansion_phase.rs @@ -11,7 +11,7 @@ // force-host #![feature(plugin_registrar)] -#![feature(box_syntax)] +#![feature(box_syntax, rustc_private)] extern crate rustc; @@ -20,7 +20,7 @@ use std::cell::RefCell; use rustc::plugin::Registry; struct Foo { - foo: int + foo: isize } impl Drop for Foo { @@ -32,4 +32,3 @@ pub fn registrar(_: &mut Registry) { thread_local!(static FOO: RefCell>> = RefCell::new(None)); FOO.with(|s| *s.borrow_mut() = Some(box Foo { foo: 10 } as Box)); } - diff --git a/src/test/auxiliary/plugin_with_plugin_lib.rs b/src/test/auxiliary/plugin_with_plugin_lib.rs index cfc8c01532..75f404c96c 100644 --- a/src/test/auxiliary/plugin_with_plugin_lib.rs +++ b/src/test/auxiliary/plugin_with_plugin_lib.rs @@ -10,7 +10,7 @@ // force-host -#![feature(plugin_registrar)] +#![feature(plugin_registrar, rustc_private)] #![deny(plugin_as_library)] // should have no effect in a plugin crate extern crate macro_crate_test; diff --git a/src/test/auxiliary/priv-impl-prim-ty.rs b/src/test/auxiliary/priv-impl-prim-ty.rs index 8c07dd5b78..19cdede551 100644 --- a/src/test/auxiliary/priv-impl-prim-ty.rs +++ b/src/test/auxiliary/priv-impl-prim-ty.rs @@ -12,7 +12,7 @@ pub trait A { fn frob(&self); } -impl A for int { fn frob(&self) {} } +impl A for isize { fn frob(&self) {} } pub fn frob(t: T) { t.frob(); diff --git a/src/test/auxiliary/privacy_reexport.rs b/src/test/auxiliary/privacy_reexport.rs index 266903169c..e60dbb290b 100644 --- a/src/test/auxiliary/privacy_reexport.rs +++ b/src/test/auxiliary/privacy_reexport.rs @@ -10,6 +10,6 @@ pub use foo as bar; -mod foo { +pub mod foo { pub fn frob() {} } diff --git a/src/test/auxiliary/privacy-tuple-struct.rs b/src/test/auxiliary/privacy_tuple_struct.rs similarity index 86% rename from src/test/auxiliary/privacy-tuple-struct.rs rename to src/test/auxiliary/privacy_tuple_struct.rs index 2fb9d9923c..141b6bdd60 100644 --- a/src/test/auxiliary/privacy-tuple-struct.rs +++ b/src/test/auxiliary/privacy_tuple_struct.rs @@ -9,6 +9,6 @@ // except according to those terms. pub struct A(()); -pub struct B(int); -pub struct C(pub int, int); -pub struct D(pub int); +pub struct B(isize); +pub struct C(pub isize, isize); +pub struct D(pub isize); diff --git a/src/test/auxiliary/private_trait_xc.rs b/src/test/auxiliary/private_trait_xc.rs index 4269157949..dc08033602 100644 --- a/src/test/auxiliary/private_trait_xc.rs +++ b/src/test/auxiliary/private_trait_xc.rs @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + trait Foo : ::std::marker::MarkerTrait {} diff --git a/src/test/auxiliary/procedural_mbe_matching.rs b/src/test/auxiliary/procedural_mbe_matching.rs new file mode 100644 index 0000000000..8c7ad2293e --- /dev/null +++ b/src/test/auxiliary/procedural_mbe_matching.rs @@ -0,0 +1,69 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host + +#![crate_type="dylib"] +#![feature(plugin_registrar, quote, rustc_private)] + +extern crate syntax; +extern crate rustc; + +use syntax::codemap::Span; +use syntax::parse::token::{self, str_to_ident, NtExpr, NtPat}; +use syntax::ast::{TokenTree, TtToken, Pat}; +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax::ext::build::AstBuilder; +use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; +use syntax::ext::tt::macro_parser::{Success, Failure, Error}; +use syntax::ptr::P; +use rustc::plugin::Registry; + +fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) + -> Box { + + let mbe_matcher = quote_matcher!(cx, $matched:expr, $($pat:pat)|+); + + let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) { + Success(map) => { + match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) { + (&MatchedNonterminal(NtExpr(ref matched_expr)), + &MatchedSeq(ref pats, seq_sp)) => { + let pats: Vec> = pats.iter().map(|pat_nt| + if let &MatchedNonterminal(NtPat(ref pat)) = &**pat_nt { + pat.clone() + } else { + unreachable!() + } + ).collect(); + let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true)); + + quote_expr!(cx, + match $matched_expr { + $arm + _ => false + } + ) + } + _ => unreachable!() + } + } + Failure(_, s) | Error(_, s) => { + panic!("expected Success, but got Error/Failure: {}", s); + } + }; + + MacEager::expr(mac_expr) +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_macro("matches", expand_mbe_matches); +} diff --git a/src/test/compile-fail/bad-crate-id.rs b/src/test/auxiliary/pub_static_array.rs similarity index 85% rename from src/test/compile-fail/bad-crate-id.rs rename to src/test/auxiliary/pub_static_array.rs index 71e3ce9a35..4419a5ae83 100644 --- a/src/test/compile-fail/bad-crate-id.rs +++ b/src/test/auxiliary/pub_static_array.rs @@ -8,6 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate "" as foo; //~ ERROR: crate name must not be empty - -fn main() {} +pub static ARRAY: &'static [u8] = &[1]; diff --git a/src/test/auxiliary/pub_use_xcrate1.rs b/src/test/auxiliary/pub_use_xcrate1.rs index 8e1e591d94..41aafd64cb 100644 --- a/src/test/auxiliary/pub_use_xcrate1.rs +++ b/src/test/auxiliary/pub_use_xcrate1.rs @@ -9,5 +9,5 @@ // except according to those terms. pub struct Foo { - pub name: int + pub name: isize } diff --git a/src/test/auxiliary/reexported_static_methods.rs b/src/test/auxiliary/reexported_static_methods.rs index 3bad76f0e7..cc4db1a958 100644 --- a/src/test/auxiliary/reexported_static_methods.rs +++ b/src/test/auxiliary/reexported_static_methods.rs @@ -17,8 +17,8 @@ pub trait Bar { fn bar() -> Self; } -impl Bar for int { - fn bar() -> int { 84 } +impl Bar for isize { + fn bar() -> isize { 84 } } pub mod sub_foo { @@ -26,8 +26,8 @@ pub mod sub_foo { fn foo() -> Self; } - impl Foo for int { - fn foo() -> int { 42 } + impl Foo for isize { + fn foo() -> isize { 42 } } pub struct Boz { @@ -35,7 +35,7 @@ pub mod sub_foo { } impl Boz { - pub fn boz(i: int) -> bool { + pub fn boz(i: isize) -> bool { i > 0 } } diff --git a/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs b/src/test/auxiliary/regions_bounded_method_type_parameters_cross_crate_lib.rs similarity index 95% rename from src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs rename to src/test/auxiliary/regions_bounded_method_type_parameters_cross_crate_lib.rs index 9c0716e2cc..f49ac4fc8e 100644 --- a/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs +++ b/src/test/auxiliary/regions_bounded_method_type_parameters_cross_crate_lib.rs @@ -12,12 +12,12 @@ // scenario work. This is the library portion of the test. pub enum MaybeOwned<'a> { - Owned(int), - Borrowed(&'a int) + Owned(isize), + Borrowed(&'a isize) } pub struct Inv<'a> { // invariant w/r/t 'a - x: &'a mut &'a int + x: &'a mut &'a isize } // I encountered a bug at some point with encoding the IntoMaybeOwned diff --git a/src/test/auxiliary/rlib_crate_test.rs b/src/test/auxiliary/rlib_crate_test.rs index be03a36393..86ce3df9ba 100644 --- a/src/test/auxiliary/rlib_crate_test.rs +++ b/src/test/auxiliary/rlib_crate_test.rs @@ -11,7 +11,7 @@ // no-prefer-dynamic #![crate_type = "rlib"] -#![feature(plugin_registrar)] +#![feature(plugin_registrar, rustc_private)] extern crate rustc; diff --git a/src/test/auxiliary/roman_numerals.rs b/src/test/auxiliary/roman_numerals.rs index e05aa16ba5..855708535f 100644 --- a/src/test/auxiliary/roman_numerals.rs +++ b/src/test/auxiliary/roman_numerals.rs @@ -11,7 +11,8 @@ // force-host #![crate_type="dylib"] -#![feature(plugin_registrar)] +#![feature(plugin_registrar, rustc_private)] +#![feature(slice_patterns)] extern crate syntax; extern crate rustc; @@ -19,7 +20,7 @@ extern crate rustc; use syntax::codemap::Span; use syntax::parse::token; use syntax::ast::{TokenTree, TtToken}; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr}; +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; // trait for expr_usize use rustc::plugin::Registry; @@ -32,7 +33,7 @@ use rustc::plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box { - static NUMERALS: &'static [(&'static str, uint)] = &[ + static NUMERALS: &'static [(&'static str, usize)] = &[ ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), ("C", 100), ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9), ("V", 5), ("IV", 4), @@ -47,7 +48,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) }; let mut text = &*text; - let mut total = 0_usize; + let mut total = 0; while !text.is_empty() { match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) { Some(&(rn, val)) => { @@ -61,7 +62,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } } - MacExpr::new(cx.expr_usize(sp, total)) + MacEager::expr(cx.expr_usize(sp, total)) } #[plugin_registrar] diff --git a/src/test/auxiliary/sepcomp-extern-lib.rs b/src/test/auxiliary/sepcomp-extern-lib.rs index 8f5d3b5768..72f1f73a81 100644 --- a/src/test/auxiliary/sepcomp-extern-lib.rs +++ b/src/test/auxiliary/sepcomp-extern-lib.rs @@ -9,6 +9,6 @@ // except according to those terms. #[no_mangle] -pub extern "C" fn foo() -> uint { +pub extern "C" fn foo() -> usize { 1234 } diff --git a/src/test/auxiliary/sepcomp_cci_lib.rs b/src/test/auxiliary/sepcomp_cci_lib.rs index 1cb7ead2cf..d62b987140 100644 --- a/src/test/auxiliary/sepcomp_cci_lib.rs +++ b/src/test/auxiliary/sepcomp_cci_lib.rs @@ -9,9 +9,9 @@ // except according to those terms. #[inline] -pub fn cci_fn() -> uint { +pub fn cci_fn() -> usize { 1200 } #[inline] -pub static CCI_STATIC: uint = 34; +pub static CCI_STATIC: usize = 34; diff --git a/src/test/auxiliary/sepcomp_lib.rs b/src/test/auxiliary/sepcomp_lib.rs index d1d9e3b8ff..9aa16fb269 100644 --- a/src/test/auxiliary/sepcomp_lib.rs +++ b/src/test/auxiliary/sepcomp_lib.rs @@ -11,13 +11,13 @@ // compile-flags: -C codegen-units=3 --crate-type=rlib,dylib pub mod a { - pub fn one() -> uint { + pub fn one() -> usize { 1 } } pub mod b { - pub fn two() -> uint { + pub fn two() -> usize { 2 } } @@ -25,7 +25,7 @@ pub mod b { pub mod c { use a::one; use b::two; - pub fn three() -> uint { + pub fn three() -> usize { one() + two() } } diff --git a/src/test/auxiliary/static-function-pointer-aux.rs b/src/test/auxiliary/static-function-pointer-aux.rs index 27befee6f0..2ccdb4e086 100644 --- a/src/test/auxiliary/static-function-pointer-aux.rs +++ b/src/test/auxiliary/static-function-pointer-aux.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name="static-function-pointer-aux"] -pub fn f(x: int) -> int { -x } +pub fn f(x: isize) -> isize { -x } -pub static F: fn(int) -> int = f; -pub static mut MutF: fn(int) -> int = f; +pub static F: fn(isize) -> isize = f; +pub static mut MutF: fn(isize) -> isize = f; diff --git a/src/test/auxiliary/static-methods-crate.rs b/src/test/auxiliary/static-methods-crate.rs index d84ded2570..e61fb49add 100644 --- a/src/test/auxiliary/static-methods-crate.rs +++ b/src/test/auxiliary/static-methods-crate.rs @@ -11,14 +11,12 @@ #![crate_name="static_methods_crate"] #![crate_type = "lib"] -use std::int; - pub trait read { fn readMaybe(s: String) -> Option; } -impl read for int { - fn readMaybe(s: String) -> Option { +impl read for isize { + fn readMaybe(s: String) -> Option { s.parse().ok() } } diff --git a/src/test/auxiliary/static_fn_inline_xc_aux.rs b/src/test/auxiliary/static_fn_inline_xc_aux.rs index 0cbd437849..2193e12bce 100644 --- a/src/test/auxiliary/static_fn_inline_xc_aux.rs +++ b/src/test/auxiliary/static_fn_inline_xc_aux.rs @@ -11,13 +11,13 @@ pub mod num { pub trait Num2 { - fn from_int2(n: int) -> Self; + fn from_int2(n: isize) -> Self; } } pub mod f64 { impl ::num::Num2 for f64 { #[inline] - fn from_int2(n: int) -> f64 { return n as f64; } + fn from_int2(n: isize) -> f64 { return n as f64; } } } diff --git a/src/test/auxiliary/static_fn_trait_xc_aux.rs b/src/test/auxiliary/static_fn_trait_xc_aux.rs index 8785a8085d..44e875fbe3 100644 --- a/src/test/auxiliary/static_fn_trait_xc_aux.rs +++ b/src/test/auxiliary/static_fn_trait_xc_aux.rs @@ -10,12 +10,12 @@ pub mod num { pub trait Num2 { - fn from_int2(n: int) -> Self; + fn from_int2(n: isize) -> Self; } } pub mod f64 { impl ::num::Num2 for f64 { - fn from_int2(n: int) -> f64 { return n as f64; } + fn from_int2(n: isize) -> f64 { return n as f64; } } } diff --git a/src/test/auxiliary/static_mut_xc.rs b/src/test/auxiliary/static_mut_xc.rs index 5660fd5b61..9d677e3dc4 100644 --- a/src/test/auxiliary/static_mut_xc.rs +++ b/src/test/auxiliary/static_mut_xc.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub static mut a: int = 3; +pub static mut a: isize = 3; diff --git a/src/test/auxiliary/static_priv_by_default.rs b/src/test/auxiliary/static_priv_by_default.rs index 6951ed729b..859f38e809 100644 --- a/src/test/auxiliary/static_priv_by_default.rs +++ b/src/test/auxiliary/static_priv_by_default.rs @@ -10,8 +10,8 @@ #![crate_type = "lib"] -static private: int = 0; -pub static public: int = 0; +static private: isize = 0; +pub static public: isize = 0; pub struct A(()); @@ -20,11 +20,11 @@ impl A { } mod foo { - pub static a: int = 0; + pub static a: isize = 0; pub fn b() {} pub struct c; pub enum d {} - pub type e = int; + pub type e = isize; pub struct A(()); @@ -33,11 +33,11 @@ mod foo { } // these are public so the parent can reexport them. - pub static reexported_a: int = 0; + pub static reexported_a: isize = 0; pub fn reexported_b() {} pub struct reexported_c; pub enum reexported_d {} - pub type reexported_e = int; + pub type reexported_e = isize; } pub mod bar { @@ -48,14 +48,14 @@ pub mod bar { pub use foo::reexported_e as i; } -pub static a: int = 0; +pub static a: isize = 0; pub fn b() {} pub struct c; pub enum d {} -pub type e = int; +pub type e = isize; -static j: int = 0; +static j: isize = 0; fn k() {} struct l; enum m {} -type n = int; +type n = isize; diff --git a/src/test/auxiliary/struct_destructuring_cross_crate.rs b/src/test/auxiliary/struct_destructuring_cross_crate.rs index 3f386ab55d..26941b726d 100644 --- a/src/test/auxiliary/struct_destructuring_cross_crate.rs +++ b/src/test/auxiliary/struct_destructuring_cross_crate.rs @@ -11,6 +11,6 @@ #![crate_type="lib"] pub struct S { - pub x: int, - pub y: int, + pub x: isize, + pub y: isize, } diff --git a/src/test/auxiliary/struct-field-privacy.rs b/src/test/auxiliary/struct_field_privacy.rs similarity index 88% rename from src/test/auxiliary/struct-field-privacy.rs rename to src/test/auxiliary/struct_field_privacy.rs index e2c16ae8b5..fe1dc9d1c8 100644 --- a/src/test/auxiliary/struct-field-privacy.rs +++ b/src/test/auxiliary/struct_field_privacy.rs @@ -9,11 +9,11 @@ // except according to those terms. struct A { - a: int, - pub b: int, + a: isize, + pub b: isize, } pub struct B { - pub a: int, - b: int, + pub a: isize, + b: isize, } diff --git a/src/test/auxiliary/struct_variant_privacy.rs b/src/test/auxiliary/struct_variant_privacy.rs index 0bdda23508..40868fa3f7 100644 --- a/src/test/auxiliary/struct_variant_privacy.rs +++ b/src/test/auxiliary/struct_variant_privacy.rs @@ -9,6 +9,5 @@ // except according to those terms. enum Bar { - Baz { a: int } + Baz { a: isize } } - diff --git a/src/test/auxiliary/struct_variant_xc_aux.rs b/src/test/auxiliary/struct_variant_xc_aux.rs index 76fd619f68..201f028b6b 100644 --- a/src/test/auxiliary/struct_variant_xc_aux.rs +++ b/src/test/auxiliary/struct_variant_xc_aux.rs @@ -11,6 +11,7 @@ #![crate_name="struct_variant_xc_aux"] #![crate_type = "lib"] +#[derive(Copy, Clone)] pub enum Enum { Variant(u8), StructVariant { arg: u8 } diff --git a/src/test/auxiliary/svh-a-base.rs b/src/test/auxiliary/svh-a-base.rs index 04f1062c16..7e10d2158e 100644 --- a/src/test/auxiliary/svh-a-base.rs +++ b/src/test/auxiliary/svh-a-base.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,12 +27,12 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-change-lit.rs b/src/test/auxiliary/svh-a-change-lit.rs index fabd2289e9..c5f3880551 100644 --- a/src/test/auxiliary/svh-a-change-lit.rs +++ b/src/test/auxiliary/svh-a-change-lit.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,12 +27,12 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 0 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-change-significant-cfg.rs b/src/test/auxiliary/svh-a-change-significant-cfg.rs index 3fdb861bd4..3168e747eb 100644 --- a/src/test/auxiliary/svh-a-change-significant-cfg.rs +++ b/src/test/auxiliary/svh-a-change-significant-cfg.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,14 +27,14 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; #[cfg(some_flag)] -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } #[cfg(not(some_flag))] -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-change-trait-bound.rs b/src/test/auxiliary/svh-a-change-trait-bound.rs index 3116d24673..f86a43494f 100644 --- a/src/test/auxiliary/svh-a-change-trait-bound.rs +++ b/src/test/auxiliary/svh-a-change-trait-bound.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,12 +27,12 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-change-type-arg.rs b/src/test/auxiliary/svh-a-change-type-arg.rs index b49a153362..dc412b7004 100644 --- a/src/test/auxiliary/svh-a-change-type-arg.rs +++ b/src/test/auxiliary/svh-a-change-type-arg.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,12 +27,12 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: i32) -> int { +pub fn foo(_: i32) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-change-type-ret.rs b/src/test/auxiliary/svh-a-change-type-ret.rs index 6562a93135..0cfcbbb055 100644 --- a/src/test/auxiliary/svh-a-change-type-ret.rs +++ b/src/test/auxiliary/svh-a-change-type-ret.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,9 +27,9 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> i64 { +pub fn foo(_: isize) -> i64 { 3 } diff --git a/src/test/auxiliary/svh-a-change-type-static.rs b/src/test/auxiliary/svh-a-change-type-static.rs index c7b392c6ee..e1e32095b5 100644 --- a/src/test/auxiliary/svh-a-change-type-static.rs +++ b/src/test/auxiliary/svh-a-change-type-static.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -28,10 +29,10 @@ impl V for () {} static A_CONSTANT : i32 = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-comment.rs b/src/test/auxiliary/svh-a-comment.rs index 450f610202..9fd97376b6 100644 --- a/src/test/auxiliary/svh-a-comment.rs +++ b/src/test/auxiliary/svh-a-comment.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,13 +27,13 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { // a comment does not affect the svh 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-doc.rs b/src/test/auxiliary/svh-a-doc.rs index c000737c85..e64bde096b 100644 --- a/src/test/auxiliary/svh-a-doc.rs +++ b/src/test/auxiliary/svh-a-doc.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,15 +27,15 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; // Adding some documentation does not affect the svh. /// foo always returns three. -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-macro.rs b/src/test/auxiliary/svh-a-macro.rs index 1e12659dc4..b16338f1e1 100644 --- a/src/test/auxiliary/svh-a-macro.rs +++ b/src/test/auxiliary/svh-a-macro.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,14 +27,14 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { // a macro invocation in a function body does not affect the svh, // as long as it yields the same code. three!() } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-no-change.rs b/src/test/auxiliary/svh-a-no-change.rs index 04f1062c16..7e10d2158e 100644 --- a/src/test/auxiliary/svh-a-no-change.rs +++ b/src/test/auxiliary/svh-a-no-change.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,12 +27,12 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-redundant-cfg.rs b/src/test/auxiliary/svh-a-redundant-cfg.rs index 1e82b74f1e..8cadd7bdf4 100644 --- a/src/test/auxiliary/svh-a-redundant-cfg.rs +++ b/src/test/auxiliary/svh-a-redundant-cfg.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,14 +27,14 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; // cfg attribute does not affect the svh, as long as it yields the same code. #[cfg(not(an_unused_name))] -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-a-whitespace.rs b/src/test/auxiliary/svh-a-whitespace.rs index 3c3dac9cda..fcaf779095 100644 --- a/src/test/auxiliary/svh-a-whitespace.rs +++ b/src/test/auxiliary/svh-a-whitespace.rs @@ -14,6 +14,7 @@ //! (#14132). #![crate_name = "a"] +#![feature(core)] use std::marker::MarkerTrait; @@ -26,14 +27,14 @@ pub trait V : MarkerTrait {} impl U for () {} impl V for () {} -static A_CONSTANT : int = 2; +static A_CONSTANT : isize = 2; -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { 3 } -pub fn an_unused_name() -> int { +pub fn an_unused_name() -> isize { 4 } diff --git a/src/test/auxiliary/svh-uta-base.rs b/src/test/auxiliary/svh-uta-base.rs index 67fdac5df0..6bd3ddab06 100644 --- a/src/test/auxiliary/svh-uta-base.rs +++ b/src/test/auxiliary/svh-uta-base.rs @@ -18,14 +18,14 @@ #![crate_name = "uta"] mod traits { - pub trait TraitA { fn val(&self) -> int { 2 } } - pub trait TraitB { fn val(&self) -> int { 3 } } + pub trait TraitA { fn val(&self) -> isize { 2 } } + pub trait TraitB { fn val(&self) -> isize { 3 } } } impl traits::TraitA for () {} impl traits::TraitB for () {} -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { use traits::TraitA; let v = (); v.val() diff --git a/src/test/auxiliary/svh-uta-change-use-trait.rs b/src/test/auxiliary/svh-uta-change-use-trait.rs index dfcf02c0ff..e863416817 100644 --- a/src/test/auxiliary/svh-uta-change-use-trait.rs +++ b/src/test/auxiliary/svh-uta-change-use-trait.rs @@ -18,14 +18,14 @@ #![crate_name = "uta"] mod traits { - pub trait TraitA { fn val(&self) -> int { 2 } } - pub trait TraitB { fn val(&self) -> int { 3 } } + pub trait TraitA { fn val(&self) -> isize { 2 } } + pub trait TraitB { fn val(&self) -> isize { 3 } } } impl traits::TraitA for () {} impl traits::TraitB for () {} -pub fn foo(_: int) -> int { +pub fn foo(_: isize) -> isize { use traits::TraitB; let v = (); v.val() diff --git a/src/test/auxiliary/syntax_extension_with_dll_deps_1.rs b/src/test/auxiliary/syntax_extension_with_dll_deps_1.rs index 338e04fbb0..fadeb02440 100644 --- a/src/test/auxiliary/syntax_extension_with_dll_deps_1.rs +++ b/src/test/auxiliary/syntax_extension_with_dll_deps_1.rs @@ -12,6 +12,6 @@ #![crate_type = "dylib"] -pub fn the_answer() -> int { +pub fn the_answer() -> isize { 2 } diff --git a/src/test/auxiliary/syntax_extension_with_dll_deps_2.rs b/src/test/auxiliary/syntax_extension_with_dll_deps_2.rs index 7a24dd76f3..4980eb8b91 100644 --- a/src/test/auxiliary/syntax_extension_with_dll_deps_2.rs +++ b/src/test/auxiliary/syntax_extension_with_dll_deps_2.rs @@ -11,9 +11,9 @@ // force-host #![crate_type = "dylib"] -#![feature(plugin_registrar, quote)] +#![feature(plugin_registrar, quote, rustc_private)] -extern crate "syntax_extension_with_dll_deps_1" as other; +extern crate syntax_extension_with_dll_deps_1 as other; extern crate syntax; extern crate rustc; @@ -30,5 +30,5 @@ pub fn plugin_registrar(reg: &mut Registry) { fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box { let answer = other::the_answer(); - MacExpr::new(quote_expr!(cx, $answer)) + MacEager::expr(quote_expr!(cx, $answer)) } diff --git a/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs b/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs index a7c469fcca..29cb0bc176 100644 --- a/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs +++ b/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs @@ -17,8 +17,7 @@ pub struct Foo { } pub enum Bar { - ABar(int), + ABar(isize), BBar(T), - CBar(uint), + CBar(usize), } - diff --git a/src/test/auxiliary/trait_default_method_xc_aux.rs b/src/test/auxiliary/trait_default_method_xc_aux.rs index 7424c21be3..c1168a912d 100644 --- a/src/test/auxiliary/trait_default_method_xc_aux.rs +++ b/src/test/auxiliary/trait_default_method_xc_aux.rs @@ -8,24 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name="trait_default_method_xc_aux"] - -pub struct Something { pub x: int } +pub struct Something { pub x: isize } pub trait A { - fn f(&self) -> int; - fn g(&self) -> int { 10 } - fn h(&self) -> int { 11 } - fn lurr(x: &Self, y: &Self) -> int { x.g() + y.h() } + fn f(&self) -> isize; + fn g(&self) -> isize { 10 } + fn h(&self) -> isize { 11 } + fn lurr(x: &Self, y: &Self) -> isize { x.g() + y.h() } } -impl A for int { - fn f(&self) -> int { 10 } +impl A for isize { + fn f(&self) -> isize { 10 } } impl A for Something { - fn f(&self) -> int { 10 } + fn f(&self) -> isize { 10 } } pub trait B { @@ -33,7 +31,7 @@ pub trait B { fn staticthing(_z: &Self, x: T, y: U) -> (T, U) { (x, y) } } -impl B for int { } +impl B for isize { } impl B for bool { } @@ -45,8 +43,8 @@ pub trait TestEquality { } } -impl TestEquality for int { - fn test_eq(&self, rhs: &int) -> bool { +impl TestEquality for isize { + fn test_eq(&self, rhs: &isize) -> bool { *self == *rhs } } diff --git a/src/test/auxiliary/trait_default_method_xc_aux_2.rs b/src/test/auxiliary/trait_default_method_xc_aux_2.rs index 4239865d57..7443ef9c0f 100644 --- a/src/test/auxiliary/trait_default_method_xc_aux_2.rs +++ b/src/test/auxiliary/trait_default_method_xc_aux_2.rs @@ -10,13 +10,13 @@ // aux-build:trait_default_method_xc_aux.rs -extern crate "trait_default_method_xc_aux" as aux; +extern crate trait_default_method_xc_aux as aux; use aux::A; -pub struct a_struct { pub x: int } +pub struct a_struct { pub x: isize } impl A for a_struct { - fn f(&self) -> int { 10 } + fn f(&self) -> isize { 10 } } // This function will need to get inlined, and badness may result. diff --git a/src/test/auxiliary/trait_impl_conflict.rs b/src/test/auxiliary/trait_impl_conflict.rs index 0982efbdbf..0adedfd4ee 100644 --- a/src/test/auxiliary/trait_impl_conflict.rs +++ b/src/test/auxiliary/trait_impl_conflict.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + pub trait Foo : ::std::marker::MarkerTrait { } -impl Foo for int { +impl Foo for isize { } diff --git a/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs b/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs index 9ef53795a2..af0128d967 100644 --- a/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs +++ b/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Foo { fn f(&self) -> int; } -pub trait Bar { fn g(&self) -> int; } -pub trait Baz { fn h(&self) -> int; } +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } -pub struct A { pub x: int } +pub struct A { pub x: isize } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } diff --git a/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs b/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs index 59fdaed744..6be1f8c45f 100644 --- a/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs +++ b/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait Foo { fn f(&self) -> int; } -pub trait Bar { fn g(&self) -> int; } -pub trait Baz { fn h(&self) -> int; } +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } pub trait Quux: Foo + Bar + Baz { } diff --git a/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs b/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs index 0a84595124..9eeb815c5d 100644 --- a/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs +++ b/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs @@ -10,13 +10,13 @@ pub trait Foo { - fn f(&self) -> int; + fn f(&self) -> isize; } pub struct A { - pub x: int + pub x: isize } impl Foo for A { - fn f(&self) -> int { 10 } + fn f(&self) -> isize { 10 } } diff --git a/src/test/auxiliary/trait_inheritance_overloading_xc.rs b/src/test/auxiliary/trait_inheritance_overloading_xc.rs index 36442ed6c1..1bfada612e 100644 --- a/src/test/auxiliary/trait_inheritance_overloading_xc.rs +++ b/src/test/auxiliary/trait_inheritance_overloading_xc.rs @@ -16,7 +16,7 @@ pub trait MyNum : Add + Sub + Mul + Parti #[derive(Clone, Debug)] pub struct MyInt { - pub val: int + pub val: isize } impl Add for MyInt { @@ -45,4 +45,4 @@ impl PartialEq for MyInt { impl MyNum for MyInt {} -fn mi(v: int) -> MyInt { MyInt { val: v } } +fn mi(v: isize) -> MyInt { MyInt { val: v } } diff --git a/src/test/auxiliary/trait-safety-lib.rs b/src/test/auxiliary/trait_safety_lib.rs similarity index 85% rename from src/test/auxiliary/trait-safety-lib.rs rename to src/test/auxiliary/trait_safety_lib.rs index d5437690ac..585a756fd0 100644 --- a/src/test/auxiliary/trait-safety-lib.rs +++ b/src/test/auxiliary/trait_safety_lib.rs @@ -11,9 +11,9 @@ // Simple smoke test that unsafe traits can be compiled etc. pub unsafe trait Foo { - fn foo(&self) -> int; + fn foo(&self) -> isize; } -unsafe impl Foo for int { - fn foo(&self) -> int { *self } +unsafe impl Foo for isize { + fn foo(&self) -> isize { *self } } diff --git a/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs b/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs new file mode 100644 index 0000000000..5a7a3e7bcc --- /dev/null +++ b/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits, core)] +#![crate_type = "rlib"] + +use std::marker::MarkerTrait; + +pub trait DefaultedTrait : MarkerTrait { } +impl DefaultedTrait for .. { } + +pub struct Something { t: T } diff --git a/src/test/auxiliary/typeid-intrinsic.rs b/src/test/auxiliary/typeid-intrinsic.rs index 82f613ee11..388d3238d4 100644 --- a/src/test/auxiliary/typeid-intrinsic.rs +++ b/src/test/auxiliary/typeid-intrinsic.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::any::TypeId; +#![feature(core)] + +use std::any::{Any, TypeId}; pub struct A; pub struct B(Option); -pub struct C(Option); +pub struct C(Option); pub struct D(Option<&'static str>); -pub struct E(Result<&'static str, int>); +pub struct E(Result<&'static str, isize>); -pub type F = Option; -pub type G = uint; +pub type F = Option; +pub type G = usize; pub type H = &'static str; pub unsafe fn id_A() -> TypeId { TypeId::of::() } @@ -29,4 +31,4 @@ pub unsafe fn id_F() -> TypeId { TypeId::of::() } pub unsafe fn id_G() -> TypeId { TypeId::of::() } pub unsafe fn id_H() -> TypeId { TypeId::of::() } -pub unsafe fn foo() -> TypeId { TypeId::of::() } +pub unsafe fn foo() -> TypeId { TypeId::of::() } diff --git a/src/test/auxiliary/typeid-intrinsic2.rs b/src/test/auxiliary/typeid-intrinsic2.rs index 82f613ee11..3ad307fd3b 100644 --- a/src/test/auxiliary/typeid-intrinsic2.rs +++ b/src/test/auxiliary/typeid-intrinsic2.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::any::TypeId; +#![feature(core)] + +use std::any::{Any, TypeId}; pub struct A; pub struct B(Option); -pub struct C(Option); +pub struct C(Option); pub struct D(Option<&'static str>); -pub struct E(Result<&'static str, int>); +pub struct E(Result<&'static str, isize>); -pub type F = Option; -pub type G = uint; +pub type F = Option; +pub type G = usize; pub type H = &'static str; pub unsafe fn id_A() -> TypeId { TypeId::of::() } @@ -29,4 +31,4 @@ pub unsafe fn id_F() -> TypeId { TypeId::of::() } pub unsafe fn id_G() -> TypeId { TypeId::of::() } pub unsafe fn id_H() -> TypeId { TypeId::of::() } -pub unsafe fn foo() -> TypeId { TypeId::of::() } +pub unsafe fn foo() -> TypeId { TypeId::of::() } diff --git a/src/test/auxiliary/unboxed-closures-cross-crate.rs b/src/test/auxiliary/unboxed-closures-cross-crate.rs index a5178c0344..dac20dd2f7 100644 --- a/src/test/auxiliary/unboxed-closures-cross-crate.rs +++ b/src/test/auxiliary/unboxed-closures-cross-crate.rs @@ -13,10 +13,10 @@ use std::ops::Add; #[inline] -pub fn has_closures() -> uint { - let x = 1_usize; +pub fn has_closures() -> usize { + let x = 1; let mut f = move || x; - let y = 1_usize; + let y = 1; let g = || y; f() + g() } diff --git a/src/test/auxiliary/unreachable-variant.rs b/src/test/auxiliary/unreachable_variant.rs similarity index 100% rename from src/test/auxiliary/unreachable-variant.rs rename to src/test/auxiliary/unreachable_variant.rs diff --git a/src/test/auxiliary/weak-lang-items.rs b/src/test/auxiliary/weak-lang-items.rs index fa254cb91a..ceffae7967 100644 --- a/src/test/auxiliary/weak-lang-items.rs +++ b/src/test/auxiliary/weak-lang-items.rs @@ -13,7 +13,7 @@ // This aux-file will require the eh_personality function to be codegen'd, but // it hasn't been defined just yet. Make sure we don't explode. -#![feature(no_std)] +#![feature(no_std, core)] #![no_std] #![crate_type = "rlib"] @@ -34,4 +34,3 @@ pub fn foo() { mod std { pub use core::{option, fmt}; } - diff --git a/src/test/auxiliary/where_clauses_xc.rs b/src/test/auxiliary/where_clauses_xc.rs index 002b31f099..4549bd719c 100644 --- a/src/test/auxiliary/where_clauses_xc.rs +++ b/src/test/auxiliary/where_clauses_xc.rs @@ -27,4 +27,3 @@ impl Equal for T where T: Eq { pub fn equal(x: &T, y: &T) -> bool where T: Eq { x == y } - diff --git a/src/test/auxiliary/xc_private_method_lib.rs b/src/test/auxiliary/xc_private_method_lib.rs index 07c99ecefb..5e7bc61943 100644 --- a/src/test/auxiliary/xc_private_method_lib.rs +++ b/src/test/auxiliary/xc_private_method_lib.rs @@ -11,7 +11,7 @@ #![crate_type="lib"] pub struct Struct { - pub x: int + pub x: isize } impl Struct { @@ -19,14 +19,14 @@ impl Struct { Struct { x: 1 } } - fn meth_struct(&self) -> int { + fn meth_struct(&self) -> isize { self.x } } pub enum Enum { - Variant1(int), - Variant2(int) + Variant1(isize), + Variant2(isize) } impl Enum { @@ -34,7 +34,7 @@ impl Enum { Enum::Variant2(10) } - fn meth_enum(&self) -> int { + fn meth_enum(&self) -> isize { match *self { Enum::Variant1(x) | Enum::Variant2(x) => x diff --git a/src/test/auxiliary/xcrate_address_insignificant.rs b/src/test/auxiliary/xcrate_address_insignificant.rs index 9e62415a20..5195839c06 100644 --- a/src/test/auxiliary/xcrate_address_insignificant.rs +++ b/src/test/auxiliary/xcrate_address_insignificant.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo() -> int { - static a: int = 3; +pub fn foo() -> isize { + static a: isize = 3; a } -pub fn bar() -> int { - foo::() +pub fn bar() -> isize { + foo::() } diff --git a/src/test/auxiliary/xcrate_static_addresses.rs b/src/test/auxiliary/xcrate_static_addresses.rs index 8065533dd7..652f11a71e 100644 --- a/src/test/auxiliary/xcrate_static_addresses.rs +++ b/src/test/auxiliary/xcrate_static_addresses.rs @@ -9,22 +9,22 @@ // except according to those terms. #[inline(never)] -pub static global: int = 3; +pub static global: isize = 3; #[inline(never)] -static global0: int = 4; +static global0: isize = 4; #[inline(never)] -pub static global2: &'static int = &global0; +pub static global2: &'static isize = &global0; -pub fn verify_same(a: &'static int) { - let a = a as *const int as uint; - let b = &global as *const int as uint; +pub fn verify_same(a: &'static isize) { + let a = a as *const isize as usize; + let b = &global as *const isize as usize; assert_eq!(a, b); } -pub fn verify_same2(a: &'static int) { - let a = a as *const int as uint; - let b = global2 as *const int as uint; +pub fn verify_same2(a: &'static isize) { + let a = a as *const isize as usize; + let b = global2 as *const isize as usize; assert_eq!(a, b); } diff --git a/src/test/auxiliary/xcrate_struct_aliases.rs b/src/test/auxiliary/xcrate_struct_aliases.rs index a0ec727272..334f7829bd 100644 --- a/src/test/auxiliary/xcrate_struct_aliases.rs +++ b/src/test/auxiliary/xcrate_struct_aliases.rs @@ -9,9 +9,8 @@ // except according to those terms. pub struct S { - pub x: int, - pub y: int, + pub x: isize, + pub y: isize, } pub type S2 = S; - diff --git a/src/test/auxiliary/xcrate_unit_struct.rs b/src/test/auxiliary/xcrate_unit_struct.rs index 7ae3655407..7a69be2b06 100644 --- a/src/test/auxiliary/xcrate_unit_struct.rs +++ b/src/test/auxiliary/xcrate_unit_struct.rs @@ -12,28 +12,27 @@ // used by the rpass test -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Struct; -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Unit { UnitVariant, Argument(Struct) } -#[derive(Copy)] -pub struct TupleStruct(pub uint, pub &'static str); +#[derive(Copy, Clone)] +pub struct TupleStruct(pub usize, pub &'static str); // used by the cfail test -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct StructWithFields { - foo: int, + foo: isize, } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum EnumWithVariants { EnumVariant, - EnumVariantArg(int) + EnumVariantArg(isize) } - diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 4909d84a34..0cff90d61e 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +#![feature(unboxed_closures, std_misc, rand)] use std::collections::{BTreeMap, HashMap, HashSet}; use std::env; diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 994c9605fc..aeedaa288f 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -10,7 +10,7 @@ // ignore-pretty very bad with line comments -#![feature(unboxed_closures)] +#![feature(unboxed_closures, rand, std_misc, collections)] extern crate collections; extern crate rand; diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 4c3b3f42ac..0344d6a46e 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -11,9 +11,10 @@ // ignore-lexer-test FIXME #15679 // Microbenchmarks for various functions in std and extra -#![feature(unboxed_closures)] +#![feature(unboxed_closures, rand, old_io, old_path, std_misc, collections)] -use std::old_io::File; +use std::old_io::*; +use std::old_path::{Path, GenericPath}; use std::iter::repeat; use std::mem::swap; use std::env; diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index b8d8f0cc9e..c7748d59c6 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -18,6 +18,8 @@ // different scalability characteristics compared to the select // version. +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender, Receiver}; use std::env; use std::thread; @@ -27,11 +29,11 @@ fn move_out(_x: T) {} enum request { get_count, - bytes(uint), + bytes(usize), stop } -fn server(requests: &Receiver, responses: &Sender) { +fn server(requests: &Receiver, responses: &Sender) { let mut count = 0; let mut done = false; while !done { @@ -53,8 +55,8 @@ fn run(args: &[String]) { let (to_parent, from_child) = channel(); let (to_child, from_parent) = channel(); - let size = args[1].parse::().unwrap(); - let workers = args[2].parse::().unwrap(); + let size = args[1].parse::().unwrap(); + let workers = args[2].parse::().unwrap(); let num_bytes = 100; let mut result = None; let mut p = Some((to_child, to_parent, from_parent)); diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index 3642eb82fd..b6a6e06088 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -14,6 +14,8 @@ // // I *think* it's the same, more or less. +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender, Receiver}; use std::env; use std::thread; @@ -21,12 +23,12 @@ use std::time::Duration; enum request { get_count, - bytes(uint), + bytes(usize), stop } -fn server(requests: &Receiver, responses: &Sender) { - let mut count: uint = 0; +fn server(requests: &Receiver, responses: &Sender) { + let mut count: usize = 0; let mut done = false; while !done { match requests.recv() { @@ -46,8 +48,8 @@ fn server(requests: &Receiver, responses: &Sender) { fn run(args: &[String]) { let (to_parent, from_child) = channel(); - let size = args[1].parse::().unwrap(); - let workers = args[2].parse::().unwrap(); + let size = args[1].parse::().unwrap(); + let workers = args[2].parse::().unwrap(); let num_bytes = 100; let mut result = None; let mut to_parent = Some(to_parent); diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index a980b7ed9e..c87cdb617a 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -18,20 +18,22 @@ // no-pretty-expanded FIXME #15189 // ignore-lexer-test FIXME #15679 +#![feature(std_misc)] + use std::env; use std::sync::{Arc, Future, Mutex, Condvar}; use std::time::Duration; // A poor man's pipe. -type pipe = Arc<(Mutex>, Condvar)>; +type pipe = Arc<(Mutex>, Condvar)>; -fn send(p: &pipe, msg: uint) { +fn send(p: &pipe, msg: usize) { let &(ref lock, ref cond) = &**p; let mut arr = lock.lock().unwrap(); arr.push(msg); cond.notify_one(); } -fn recv(p: &pipe) -> uint { +fn recv(p: &pipe) -> usize { let &(ref lock, ref cond) = &**p; let mut arr = lock.lock().unwrap(); while arr.is_empty() { @@ -46,7 +48,7 @@ fn init() -> (pipe,pipe) { } -fn thread_ring(i: uint, count: uint, num_chan: pipe, num_port: pipe) { +fn thread_ring(i: usize, count: usize, num_chan: pipe, num_port: pipe) { let mut num_chan = Some(num_chan); let mut num_port = Some(num_port); // Send/Receive lots of messages. @@ -72,8 +74,8 @@ fn main() { args.collect() }; - let num_tasks = args[1].parse::().unwrap(); - let msg_per_task = args[2].parse::().unwrap(); + let num_tasks = args[1].parse::().unwrap(); + let msg_per_task = args[2].parse::().unwrap(); let (num_chan, num_port) = init(); diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 53c52ae301..83c39b3f3f 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -12,11 +12,13 @@ // See https://github.com/nsf/pnoise for timings and alternative implementations. // ignore-lexer-test FIXME #15679 +#![feature(rand, core)] + use std::f32::consts::PI; use std::num::Float; use std::rand::{Rng, StdRng}; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Vec2 { x: f32, y: f32, @@ -27,7 +29,7 @@ fn lerp(a: f32, b: f32, v: f32) -> f32 { a * (1.0 - v) + b * v } fn smooth(v: f32) -> f32 { v * v * (3.0 - 2.0 * v) } fn random_gradient(r: &mut R) -> Vec2 { - let v = PI * 2.0 * r.gen(); + let v = PI * 2.0 * r.gen::(); Vec2 { x: v.cos(), y: v.sin() } } @@ -45,11 +47,11 @@ impl Noise2DContext { let mut rng = StdRng::new().unwrap(); let mut rgradients = [Vec2 { x: 0.0, y: 0.0 }; 256]; - for x in &mut rgradients[] { + for x in &mut rgradients[..] { *x = random_gradient(&mut rng); } - let mut permutations = [0i32; 256]; + let mut permutations = [0; 256]; for (i, x) in permutations.iter_mut().enumerate() { *x = i as i32; } @@ -59,9 +61,9 @@ impl Noise2DContext { } fn get_gradient(&self, x: i32, y: i32) -> Vec2 { - let idx = self.permutations[(x & 255) as uint] + - self.permutations[(y & 255) as uint]; - self.rgradients[(idx & 255) as uint] + let idx = self.permutations[(x & 255) as usize] + + self.permutations[(y & 255) as usize]; + self.rgradients[(idx & 255) as usize] } fn get_gradients(&self, x: f32, y: f32) -> ([Vec2; 4], [Vec2; 4]) { @@ -115,7 +117,7 @@ fn main() { for y in 0..256 { for x in 0..256 { - let idx = (pixels[y*256+x] / 0.2) as uint; + let idx = (pixels[y*256+x] / 0.2) as usize; print!("{}", symbols[idx]); } print!("\n"); diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 1e23da3020..ce050cc732 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -38,9 +38,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. +#![feature(rustc_private, core, step_by)] + extern crate arena; -use std::iter::range_step; use std::thread; use arena::TypedArena; @@ -107,9 +108,9 @@ fn main() { let long_lived_arena = TypedArena::new(); let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth); - let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| { + let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| { use std::num::Int; - let iterations = 2.pow((max_depth - depth + min_depth) as usize); + let iterations = 2.pow((max_depth - depth + min_depth) as u32); thread::scoped(move || inner(depth, iterations)) }).collect::>(); diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index 73e7c8eb07..72f3464cdb 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -54,7 +54,7 @@ fn print_complements() { } } -#[derive(Copy)] +#[derive(Copy, Clone)] enum Color { Red, Yellow, @@ -72,9 +72,9 @@ impl fmt::Debug for Color { } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct CreatureInfo { - name: uint, + name: usize, color: Color } @@ -87,7 +87,7 @@ fn show_color_list(set: Vec) -> String { out } -fn show_digit(nn: uint) -> &'static str { +fn show_digit(nn: usize) -> &'static str { match nn { 0 => {" zero"} 1 => {" one"} @@ -103,7 +103,7 @@ fn show_digit(nn: uint) -> &'static str { } } -struct Number(uint); +struct Number(usize); impl fmt::Debug for Number { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut out = vec![]; @@ -139,13 +139,13 @@ fn transform(aa: Color, bb: Color) -> Color { } fn creature( - name: uint, + name: usize, mut color: Color, from_rendezvous: Receiver, to_rendezvous: Sender, to_rendezvous_log: Sender ) { - let mut creatures_met = 0i32; + let mut creatures_met = 0; let mut evil_clones_met = 0; let mut rendezvous = from_rendezvous.iter(); @@ -172,7 +172,7 @@ fn creature( to_rendezvous_log.send(report).unwrap(); } -fn rendezvous(nn: uint, set: Vec) { +fn rendezvous(nn: usize, set: Vec) { // these ports will allow us to hear from the creatures let (to_rendezvous, from_creatures) = channel::(); diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index f7de935d08..4489a124ab 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -38,7 +38,9 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{cmp, iter, mem}; +#![feature(step_by)] + +use std::{cmp, mem}; use std::thread; fn rotate(x: &mut [i32]) { @@ -61,12 +63,12 @@ fn next_permutation(perm: &mut [i32], count: &mut [i32]) { } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct P { p: [i32; 16], } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Perm { cnt: [i32; 16], fact: [u32; 16], @@ -78,7 +80,7 @@ struct Perm { impl Perm { fn new(n: u32) -> Perm { let mut fact = [1; 16]; - for i in 1..n as uint + 1 { + for i in 1..n as usize + 1 { fact[i] = fact[i - 1] * i as u32; } Perm { @@ -91,13 +93,13 @@ impl Perm { } fn get(&mut self, mut idx: i32) -> P { - let mut pp = [0u8; 16]; + let mut pp = [0; 16]; self.permcount = idx as u32; for (i, place) in self.perm.p.iter_mut().enumerate() { *place = i as i32 + 1; } - for i in (1..self.n as uint).rev() { + for i in (1..self.n as usize).rev() { let d = idx / self.fact[i] as i32; self.cnt[i] = d; idx %= self.fact[i] as i32; @@ -105,7 +107,7 @@ impl Perm { *place = (*val) as u8 } - let d = d as uint; + let d = d as usize; for j in 0..i + 1 { self.perm.p[j] = if j + d <= i {pp[j + d]} else {pp[j+d-i-1]} as i32; } @@ -115,7 +117,7 @@ impl Perm { } fn count(&self) -> u32 { self.permcount } - fn max(&self) -> u32 { self.fact[self.n as uint] } + fn max(&self) -> u32 { self.fact[self.n as usize] } fn next(&mut self) -> P { next_permutation(&mut self.perm.p, &mut self.cnt); @@ -126,11 +128,11 @@ impl Perm { } -fn reverse(tperm: &mut [i32], k: uint) { +fn reverse(tperm: &mut [i32], k: usize) { tperm[..k].reverse() } -fn work(mut perm: Perm, n: uint, max: uint) -> (i32, i32) { +fn work(mut perm: Perm, n: usize, max: usize) -> (i32, i32) { let mut checksum = 0; let mut maxflips = 0; @@ -140,7 +142,7 @@ fn work(mut perm: Perm, n: uint, max: uint) -> (i32, i32) { let mut flips = 0; while p.p[0] != 1 { - let k = p.p[0] as uint; + let k = p.p[0] as usize; reverse(&mut p.p, k); flips += 1; } @@ -161,11 +163,11 @@ fn fannkuch(n: i32) -> (i32, i32) { let mut futures = vec![]; let k = perm.max() / N; - for (_, j) in (0..N).zip(iter::count(0, k)) { + for (_, j) in (0..N).zip((0..).step_by(k)) { let max = cmp::min(j+k, perm.max()); futures.push(thread::scoped(move|| { - work(perm, j as uint, max as uint) + work(perm, j as usize, max as usize) })) } @@ -183,7 +185,7 @@ fn main() { let n = std::env::args() .nth(1) .and_then(|arg| arg.parse().ok()) - .unwrap_or(2i32); + .unwrap_or(2); let (checksum, maxflips) = fannkuch(n); println!("{}\nPfannkuchen({}) = {}", checksum, n, maxflips); diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index 277c3ee73d..effdd67027 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -38,8 +38,10 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. +#![feature(core, old_io, io, core)] + use std::cmp::min; -use std::old_io::{stdout, IoResult}; +use std::old_io::*; use std::iter::repeat; use std::env; use std::slice::bytes::copy_memory; @@ -103,7 +105,7 @@ fn sum_and_scale(a: &'static [AminoAcid]) -> Vec { result } -#[derive(Copy)] +#[derive(Copy, Clone)] struct AminoAcid { c: u8, p: f32, @@ -121,13 +123,12 @@ impl<'a, W: Writer> RepeatFasta<'a, W> { fn make(&mut self, n: usize) -> IoResult<()> { let alu_len = self.alu.len(); - let mut buf = repeat(0u8).take(alu_len + LINE_LEN).collect::>(); + let mut buf = repeat(0).take(alu_len + LINE_LEN).collect::>(); let alu: &[u8] = self.alu.as_bytes(); - copy_memory(&mut buf, alu); + copy_memory(alu, &mut buf); let buf_len = buf.len(); - copy_memory(&mut buf[alu_len..buf_len], - &alu[..LINE_LEN]); + copy_memory(&alu[..LINE_LEN], &mut buf[alu_len..buf_len]); let mut pos = 0; let mut bytes; diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 2c640c4b09..78d31faeb5 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -38,9 +38,12 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. +#![feature(old_io, old_path, io, core)] + use std::cmp::min; -use std::old_io::{BufferedWriter, File}; +use std::old_io::*; use std::old_io; +use std::old_path::Path; use std::num::Float; use std::env; @@ -89,7 +92,7 @@ fn make_fasta>( -> std::old_io::IoResult<()> { try!(wr.write(header.as_bytes())); - let mut line = [0u8; LINE_LENGTH + 1]; + let mut line = [0; LINE_LENGTH + 1]; while n > 0 { let nb = min(LINE_LENGTH, n); for i in 0..nb { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 3ea4a10ea8..c190641bfb 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -13,7 +13,7 @@ // multi tasking k-nucleotide -#![feature(box_syntax)] +#![feature(box_syntax, std_misc, old_io, collections, os)] use std::ascii::{AsciiExt, OwnedAsciiExt}; use std::cmp::Ordering::{self, Less, Greater, Equal}; @@ -42,8 +42,8 @@ fn f64_cmp(x: f64, y: f64) -> Ordering { } // given a map, print a sorted version of it -fn sort_and_fmt(mm: &HashMap , uint>, total: uint) -> String { - fn pct(xx: uint, yy: uint) -> f64 { +fn sort_and_fmt(mm: &HashMap , usize>, total: usize) -> String { + fn pct(xx: usize, yy: usize) -> f64 { return (xx as f64) * 100.0 / (yy as f64); } @@ -74,7 +74,7 @@ fn sort_and_fmt(mm: &HashMap , uint>, total: uint) -> String { } // given a map, search for the frequency of a pattern -fn find(mm: &HashMap , uint>, key: String) -> uint { +fn find(mm: &HashMap , usize>, key: String) -> usize { let key = key.into_ascii_lowercase(); match mm.get(key.as_bytes()) { option::Option::None => { return 0; } @@ -83,7 +83,7 @@ fn find(mm: &HashMap , uint>, key: String) -> uint { } // given a map, increment the counter for a key -fn update_freq(mm: &mut HashMap , uint>, key: &[u8]) { +fn update_freq(mm: &mut HashMap , usize>, key: &[u8]) { let key = key.to_vec(); let newval = match mm.remove(&key) { Some(v) => v + 1, @@ -95,7 +95,7 @@ fn update_freq(mm: &mut HashMap , uint>, key: &[u8]) { // given a Vec, 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, mut it: F) -> Vec where +fn windows_with_carry(bb: &[u8], nn: usize, mut it: F) -> Vec where F: FnMut(&[u8]), { let mut ii = 0; @@ -109,12 +109,12 @@ fn windows_with_carry(bb: &[u8], nn: uint, mut it: F) -> Vec where return bb[len - (nn - 1)..len].to_vec(); } -fn make_sequence_processor(sz: uint, +fn make_sequence_processor(sz: usize, from_parent: &Receiver>, to_parent: &Sender) { - let mut freqs: HashMap, uint> = HashMap::new(); + let mut freqs: HashMap, usize> = HashMap::new(); let mut carry = Vec::new(); - let mut total: uint = 0; + let mut total: usize = 0; let mut line: Vec; @@ -147,7 +147,7 @@ fn make_sequence_processor(sz: uint, // given a FASTA file on stdin, process sequence THREE fn main() { - use std::old_io::{stdio, MemReader, BufferedReader}; + use std::old_io::*; let rdr = if env::var_os("RUST_BENCH").is_some() { let foo = include_bytes!("shootout-k-nucleotide.data"); @@ -193,7 +193,7 @@ fn main() { // start processing if this is the one ('>', false) => { - match line[1..].find_str("THREE") { + match line[1..].find("THREE") { Some(_) => { proc_mode = true; } None => { } } diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index fb75c67253..db131bcfdc 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -40,15 +40,19 @@ // ignore-android see #10393 #13206 -#![feature(box_syntax)] +#![feature(box_syntax, std_misc, collections)] use std::ascii::OwnedAsciiExt; +use std::env; +use std::fs::File; +use std::io::prelude::*; +use std::io; use std::slice; use std::sync::Arc; use std::thread; static TABLE: [u8;4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ]; -static TABLE_SIZE: uint = 2 << 16; +static TABLE_SIZE: usize = 2 << 16; static OCCURRENCES: [&'static str;5] = [ "GGT", @@ -60,7 +64,7 @@ static OCCURRENCES: [&'static str;5] = [ // Code implementation -#[derive(Copy, PartialEq, PartialOrd, Ord, Eq)] +#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq)] struct Code(u64); impl Code { @@ -73,15 +77,15 @@ impl Code { Code((self.hash() << 2) + (pack_symbol(c) as u64)) } - fn rotate(&self, c: u8, frame: uint) -> Code { - Code(self.push_char(c).hash() & ((1u64 << (2 * frame)) - 1)) + fn rotate(&self, c: u8, frame: usize) -> Code { + Code(self.push_char(c).hash() & ((1 << (2 * frame)) - 1)) } fn pack(string: &str) -> Code { - string.bytes().fold(Code(0u64), |a, b| a.push_char(b)) + string.bytes().fold(Code(0), |a, b| a.push_char(b)) } - fn unpack(&self, frame: uint) -> String { + fn unpack(&self, frame: usize) -> String { let mut key = self.hash(); let mut result = Vec::new(); for _ in 0..frame { @@ -113,13 +117,13 @@ struct PrintCallback(&'static str); impl TableCallback for PrintCallback { fn f(&self, entry: &mut Entry) { let PrintCallback(s) = *self; - println!("{}\t{}", entry.count as int, s); + println!("{}\t{}", entry.count, s); } } struct Entry { code: Code, - count: uint, + count: usize, next: Option>, } @@ -142,7 +146,7 @@ impl Table { fn search_remainder(item: &mut Entry, key: Code, c: C) { match item.next { None => { - let mut entry = box Entry { + let mut entry: Box<_> = box Entry { code: key, count: 0, next: None, @@ -165,20 +169,20 @@ impl Table { let index = key.hash() % (TABLE_SIZE as u64); { - if self.items[index as uint].is_none() { - let mut entry = box Entry { + if self.items[index as usize].is_none() { + let mut entry: Box<_> = box Entry { code: key, count: 0, next: None, }; c.f(&mut *entry); - self.items[index as uint] = Some(entry); + self.items[index as usize] = Some(entry); return; } } { - let entry = self.items[index as uint].as_mut().unwrap(); + let entry = self.items[index as usize].as_mut().unwrap(); if entry.code == key { c.f(&mut **entry); return; @@ -233,10 +237,10 @@ fn pack_symbol(c: u8) -> u8 { } fn unpack_symbol(c: u8) -> u8 { - TABLE[c as uint] + TABLE[c as usize] } -fn generate_frequencies(mut input: &[u8], frame: uint) -> Table { +fn generate_frequencies(mut input: &[u8], frame: usize) -> Table { let mut frequencies = Table::new(); if input.len() < frame { return frequencies; } let mut code = Code(0); @@ -256,7 +260,7 @@ fn generate_frequencies(mut input: &[u8], frame: uint) -> Table { frequencies } -fn print_frequencies(frequencies: &Table, frame: uint) { +fn print_frequencies(frequencies: &Table, frame: usize) { let mut vector = Vec::new(); for entry in frequencies.iter() { vector.push((entry.count, entry.code)); @@ -280,9 +284,9 @@ fn print_occurrences(frequencies: &mut Table, occurrence: &'static str) { frequencies.lookup(Code::pack(occurrence), PrintCallback(occurrence)) } -fn get_sequence(r: &mut R, key: &str) -> Vec { +fn get_sequence(r: &mut R, key: &str) -> Vec { let mut res = Vec::new(); - for l in r.lines().map(|l| l.ok().unwrap()) + for l in r.lines().map(|l| l.unwrap()) .skip_while(|l| key != &l[..key.len()]).skip(1) { res.push_all(l.trim().as_bytes()); @@ -291,13 +295,13 @@ fn get_sequence(r: &mut R, key: &str) -> Vec { } fn main() { - let input = if std::env::var_os("RUST_BENCH").is_some() { - let fd = std::old_io::File::open(&Path::new("shootout-k-nucleotide.data")); - get_sequence(&mut std::old_io::BufferedReader::new(fd), ">THREE") + let input = if env::var_os("RUST_BENCH").is_some() { + let f = File::open("shootout-k-nucleotide.data").unwrap(); + get_sequence(&mut io::BufReader::new(f), ">THREE") } else { - let mut stdin = std::old_io::stdin(); + let stdin = io::stdin(); let mut stdin = stdin.lock(); - get_sequence(&mut *stdin, ">THREE") + get_sequence(&mut stdin, ">THREE") }; let input = Arc::new(input); diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index bddf615322..d248293103 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -38,11 +38,12 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -#![feature(simd)] +#![feature(simd, old_io, core, io)] // ignore-pretty very bad with line comments use std::old_io; +use std::old_io::*; use std::env; use std::simd::f64x2; use std::sync::Arc; diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs index a94fe0ccd9..150522fd02 100644 --- a/src/test/bench/shootout-meteor.rs +++ b/src/test/bench/shootout-meteor.rs @@ -40,6 +40,8 @@ // no-pretty-expanded FIXME #15189 +#![feature(core)] + use std::iter::repeat; use std::sync::Arc; use std::sync::mpsc::channel; @@ -169,7 +171,7 @@ fn make_masks() -> Vec > > { .map(|(id, p)| transform(p, id != 3)) .collect(); - (0i32..50).map(|yx| { + (0..50).map(|yx| { transforms.iter().enumerate().map(|(id, t)| { t.iter().filter_map(|p| mask(yx / 5, yx % 5, id, p)).collect() }).collect() @@ -211,7 +213,7 @@ fn filter_masks(masks: &mut Vec>>) { // Gets the identifier of a mask. fn get_id(m: u64) -> u8 { - for id in 0u8..10 { + for id in 0..10 { if m & (1 << (id + 50) as usize) != 0 {return id;} } panic!("{:016x} does not have a valid identifier", m); diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index 534dfe9548..669a0e86f1 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -38,12 +38,14 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. +#![feature(core)] + use std::num::Float; const PI: f64 = 3.141592653589793; const SOLAR_MASS: f64 = 4.0 * PI * PI; const YEAR: f64 = 365.24; -const N_BODIES: uint = 5; +const N_BODIES: usize = 5; static BODIES: [Planet;N_BODIES] = [ // Sun @@ -94,14 +96,14 @@ static BODIES: [Planet;N_BODIES] = [ }, ]; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Planet { x: f64, y: f64, z: f64, vx: f64, vy: f64, vz: f64, mass: f64, } -fn advance(bodies: &mut [Planet;N_BODIES], dt: f64, steps: int) { +fn advance(bodies: &mut [Planet;N_BODIES], dt: f64, steps: isize) { for _ in 0..steps { let mut b_slice: &mut [_] = bodies; loop { diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index a542c81f23..ed20f4b636 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -18,6 +18,8 @@ */ +#![feature(std_misc, rustc_private)] + extern crate getopts; use std::sync::mpsc::{channel, Sender}; @@ -75,7 +77,7 @@ fn stress_task(id: isize) { } } -fn stress(num_tasks: int) { +fn stress(num_tasks: isize) { let mut results = Vec::new(); for i in 0..num_tasks { results.push(thread::spawn(move|| { diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index 33d959dfe9..cda90c08f2 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -40,13 +40,13 @@ // ignore-android see #10393 #13206 -#![feature(unboxed_closures)] +#![feature(unboxed_closures, libc, old_io, collections, io, core)] extern crate libc; use std::old_io::stdio::{stdin_raw, stdout_raw}; -use std::old_io::{IoResult, EndOfFile}; -use std::ptr::{copy_memory, Unique}; +use std::old_io::*; +use std::ptr::{copy, Unique}; use std::thread; struct Tables { @@ -92,12 +92,12 @@ impl Tables { /// Retrieves the complement for `i`. fn cpl8(&self, i: u8) -> u8 { - self.table8[i as uint] + self.table8[i as usize] } /// Retrieves the complement for `i`. fn cpl16(&self, i: u16) -> u16 { - self.table16[i as uint] + self.table16[i as usize] } } @@ -107,7 +107,7 @@ fn read_to_end(r: &mut R) -> IoResult> { // Reader::read_to_end() with a fast growing policy to limit // recopies. If MREMAP_RETAIN is implemented in the linux kernel // and jemalloc use it, this trick will become useless. - const CHUNK: uint = 64 * 1024; + const CHUNK: usize = 64 * 1024; let mut vec = Vec::with_capacity(CHUNK); loop { @@ -132,7 +132,7 @@ fn read_to_end(r: &mut R) -> IoResult> { } /// Finds the first position at which `b` occurs in `s`. -fn memchr(h: &[u8], n: u8) -> Option { +fn memchr(h: &[u8], n: u8) -> Option { use libc::{c_void, c_int, size_t}; let res = unsafe { libc::memchr(h.as_ptr() as *const c_void, n as c_int, h.len() as size_t) @@ -140,7 +140,7 @@ fn memchr(h: &[u8], n: u8) -> Option { if res.is_null() { None } else { - Some(res as uint - h.as_ptr() as uint) + Some(res as usize - h.as_ptr() as usize) } } @@ -171,7 +171,7 @@ impl<'a> Iterator for MutDnaSeqs<'a> { } /// Length of a normal line without the terminating \n. -const LINE_LEN: uint = 60; +const LINE_LEN: usize = 60; /// Compute the reverse complement. fn reverse_complement(seq: &mut [u8], tables: &Tables) { @@ -181,8 +181,8 @@ fn reverse_complement(seq: &mut [u8], tables: &Tables) { let mut i = LINE_LEN; while i < len { unsafe { - copy_memory(seq.as_mut_ptr().offset((i - off + 1) as int), - seq.as_ptr().offset((i - off) as int), off); + copy(seq.as_ptr().offset((i - off) as isize), + seq.as_mut_ptr().offset((i - off + 1) as isize), off); *seq.get_unchecked_mut(i - off) = b'\n'; } i += LINE_LEN + 1; @@ -193,8 +193,8 @@ fn reverse_complement(seq: &mut [u8], tables: &Tables) { unsafe { let mut left = seq.as_mut_ptr() as *mut u16; // This is slow if len % 2 != 0 but still faster than bytewise operations. - let mut right = seq.as_mut_ptr().offset(len as int - 2) as *mut u16; - let end = left.offset(div as int); + let mut right = seq.as_mut_ptr().offset(len as isize - 2) as *mut u16; + let end = left.offset(div as isize); while left != end { let tmp = tables.cpl16(*left); *left = tables.cpl16(*right); diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index f7514a3e88..c0268e816c 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -41,7 +41,7 @@ // no-pretty-expanded FIXME #15189 #![allow(non_snake_case)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core, os)] use std::iter::{repeat, AdditiveIterator}; use std::thread; @@ -64,7 +64,7 @@ fn main() { println!("{:.9}", answer); } -fn spectralnorm(n: uint) -> f64 { +fn spectralnorm(n: usize) -> f64 { assert!(n % 2 == 0, "only even lengths are accepted"); let mut u = repeat(1.0).take(n).collect::>(); let mut v = u.clone(); @@ -89,8 +89,8 @@ fn mult_Atv(v: &[f64], out: &mut [f64]) { parallel(out, |start, out| mult(v, out, start, |i, j| A(j, i))); } -fn mult(v: &[f64], out: &mut [f64], start: uint, a: F) - where F: Fn(uint, uint) -> f64 { +fn mult(v: &[f64], out: &mut [f64], start: usize, a: F) + where F: Fn(usize, usize) -> f64 { for (i, slot) in out.iter_mut().enumerate().map(|(i, s)| (i + start, s)) { let mut sum = f64x2(0.0, 0.0); for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) { @@ -103,7 +103,7 @@ fn mult(v: &[f64], out: &mut [f64], start: uint, a: F) } } -fn A(i: uint, j: uint) -> f64 { +fn A(i: usize, j: usize) -> f64 { ((i + j) * (i + j + 1) / 2 + i + 1) as f64 } @@ -117,8 +117,10 @@ fn dot(v: &[f64], u: &[f64]) -> f64 { // sub-slice of `v`. fn parallel<'a,T, F>(v: &mut [T], ref f: F) where T: Send + Sync + 'a, - F: Fn(uint, &mut [T]) + Sync + 'a { - let size = v.len() / os::num_cpus() + 1; + F: Fn(usize, &mut [T]) + Sync + 'a { + // FIXME: pick a more appropriate parallel factor + let parallelism = 4; + let size = v.len() / parallelism + 1; v.chunks_mut(size).enumerate().map(|(i, chunk)| { thread::scoped(move|| { f(i * size, chunk) diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index a54a869412..dd56b18c14 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -10,6 +10,8 @@ // Microbenchmark for the smallintmap library +#![feature(collections, std_misc)] + use std::collections::VecMap; use std::env; use std::time::Duration; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index b45f241e8e..3913de3a3f 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -10,12 +10,11 @@ // ignore-pretty very bad with line comments -#![feature(box_syntax)] +#![feature(box_syntax, core)] #![allow(non_snake_case)] -use std::old_io::BufferedReader; -use std::old_io::stdio::StdReader; -use std::old_io; +use std::io::prelude::*; +use std::io; use std::iter::repeat; use std::num::Int; use std::env; @@ -37,7 +36,7 @@ use std::env; // // internal type of sudoku grids -type grid = Vec > ; +type grid = Vec>; struct Sudoku { grid: grid @@ -55,11 +54,13 @@ impl Sudoku { return Sudoku::new(g) } - pub fn read(mut reader: &mut BufferedReader) -> Sudoku { + pub fn read(reader: &mut BufRead) -> Sudoku { /* assert first line is exactly "9,9" */ - assert!(reader.read_line().unwrap() == "9,9".to_string()); + let mut s = String::new(); + reader.read_line(&mut s).unwrap(); + assert_eq!(s, "9,9\n"); - let mut g = repeat(vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]) + let mut g = repeat(vec![0, 0, 0, 0, 0, 0, 0, 0, 0]) .take(10).collect::>(); for line in reader.lines() { let line = line.unwrap(); @@ -71,7 +72,7 @@ impl Sudoku { if comps.len() == 3 { let row = comps[0].parse::().unwrap(); let col = comps[1].parse::().unwrap(); - g[row as uint][col as uint] = comps[2].parse().unwrap(); + g[row as usize][col as usize] = comps[2].parse().unwrap(); } else { panic!("Invalid sudoku file"); @@ -80,11 +81,11 @@ impl Sudoku { return Sudoku::new(g) } - pub fn write(&self, writer: &mut old_io::Writer) { + pub fn write(&self, writer: &mut Write) { for row in 0u8..9u8 { - write!(writer, "{}", self.grid[row as uint][0]); + write!(writer, "{}", self.grid[row as usize][0]); for col in 1u8..9u8 { - write!(writer, " {}", self.grid[row as uint][col as uint]); + write!(writer, " {}", self.grid[row as usize][col as usize]); } write!(writer, "\n"); } @@ -93,10 +94,10 @@ impl Sudoku { // solve sudoku grid pub fn solve(&mut self) { let mut work: Vec<(u8, u8)> = Vec::new(); /* queue of uncolored fields */ - for row in 0u8..9u8 { - for col in 0u8..9u8 { - let color = self.grid[row as uint][col as uint]; - if color == 0u8 { + for row in 0..9 { + for col in 0..9 { + let color = self.grid[row as usize][col as usize]; + if color == 0 { work.push((row, col)); } } @@ -107,7 +108,7 @@ impl Sudoku { while ptr < end { let (row, col) = work[ptr]; // is there another color to try? - let the_color = self.grid[row as uint][col as uint] + + let the_color = self.grid[row as usize][col as usize] + (1 as u8); if self.next_color(row, col, the_color) { // yes: advance work list @@ -121,37 +122,37 @@ impl Sudoku { } fn next_color(&mut self, row: u8, col: u8, start_color: u8) -> bool { - if start_color < 10u8 { + if start_color < 10 { // colors not yet used - let mut avail = box Colors::new(start_color); + let mut avail: Box<_> = box Colors::new(start_color); // drop colors already in use in neighbourhood self.drop_colors(&mut *avail, row, col); // find first remaining color that is available let next = avail.next(); - self.grid[row as uint][col as uint] = next; - return 0u8 != next; + self.grid[row as usize][col as usize] = next; + return 0 != next; } - self.grid[row as uint][col as uint] = 0u8; + self.grid[row as usize][col as usize] = 0; return false; } // find colors available in neighbourhood of (row, col) fn drop_colors(&mut self, avail: &mut Colors, row: u8, col: u8) { - for idx in 0u8..9u8 { + for idx in 0..9 { /* check same column fields */ - avail.remove(self.grid[idx as uint][col as uint]); + avail.remove(self.grid[idx as usize][col as usize]); /* check same row fields */ - avail.remove(self.grid[row as uint][idx as uint]); + avail.remove(self.grid[row as usize][idx as usize]); } // check same block fields - let row0 = (row / 3u8) * 3u8; - let col0 = (col / 3u8) * 3u8; - for alt_row in row0..row0 + 3u8 { - for alt_col in col0..col0 + 3u8 { - avail.remove(self.grid[alt_row as uint][alt_col as uint]); + let row0 = (row / 3) * 3; + let col0 = (col / 3) * 3; + for alt_row in row0..row0 + 3 { + for alt_col in col0..col0 + 3 { + avail.remove(self.grid[alt_row as usize][alt_col as usize]); } } } @@ -160,29 +161,29 @@ impl Sudoku { // Stores available colors as simple bitfield, bit 0 is always unset struct Colors(u16); -static HEADS: u16 = (1u16 << 10) - 1; /* bits 9..0 */ +static HEADS: u16 = (1 << 10) - 1; /* bits 9..0 */ impl Colors { fn new(start_color: u8) -> Colors { // Sets bits 9..start_color - let tails = !0u16 << start_color as uint; + let tails = !0 << start_color as usize; return Colors(HEADS & tails); } fn next(&self) -> u8 { let Colors(c) = *self; let val = c & HEADS; - if 0u16 == val { - return 0u8; + if 0 == val { + return 0; } else { return val.trailing_zeros() as u8 } } fn remove(&mut self, color: u8) { - if color != 0u8 { + if color != 0 { let Colors(val) = *self; - let mask = !(1u16 << color as uint); + let mask = !(1 << color as usize); *self = Colors(val & mask); } } @@ -190,57 +191,57 @@ impl Colors { static DEFAULT_SUDOKU: [[u8;9];9] = [ /* 0 1 2 3 4 5 6 7 8 */ - /* 0 */ [0u8, 4u8, 0u8, 6u8, 0u8, 0u8, 0u8, 3u8, 2u8], - /* 1 */ [0u8, 0u8, 8u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8], - /* 2 */ [7u8, 0u8, 0u8, 8u8, 0u8, 0u8, 0u8, 0u8, 0u8], - /* 3 */ [0u8, 0u8, 0u8, 5u8, 0u8, 0u8, 0u8, 0u8, 0u8], - /* 4 */ [0u8, 5u8, 0u8, 0u8, 0u8, 3u8, 6u8, 0u8, 0u8], - /* 5 */ [6u8, 8u8, 0u8, 0u8, 0u8, 0u8, 0u8, 9u8, 0u8], - /* 6 */ [0u8, 9u8, 5u8, 0u8, 0u8, 6u8, 0u8, 7u8, 0u8], - /* 7 */ [0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 6u8, 0u8], - /* 8 */ [4u8, 0u8, 0u8, 0u8, 0u8, 7u8, 2u8, 0u8, 3u8] + /* 0 */ [0, 4, 0, 6, 0, 0, 0, 3, 2], + /* 1 */ [0, 0, 8, 0, 2, 0, 0, 0, 0], + /* 2 */ [7, 0, 0, 8, 0, 0, 0, 0, 0], + /* 3 */ [0, 0, 0, 5, 0, 0, 0, 0, 0], + /* 4 */ [0, 5, 0, 0, 0, 3, 6, 0, 0], + /* 5 */ [6, 8, 0, 0, 0, 0, 0, 9, 0], + /* 6 */ [0, 9, 5, 0, 0, 6, 0, 7, 0], + /* 7 */ [0, 0, 0, 0, 4, 0, 0, 6, 0], + /* 8 */ [4, 0, 0, 0, 0, 7, 2, 0, 3] ]; #[cfg(test)] static DEFAULT_SOLUTION: [[u8;9];9] = [ /* 0 1 2 3 4 5 6 7 8 */ - /* 0 */ [1u8, 4u8, 9u8, 6u8, 7u8, 5u8, 8u8, 3u8, 2u8], - /* 1 */ [5u8, 3u8, 8u8, 1u8, 2u8, 9u8, 7u8, 4u8, 6u8], - /* 2 */ [7u8, 2u8, 6u8, 8u8, 3u8, 4u8, 1u8, 5u8, 9u8], - /* 3 */ [9u8, 1u8, 4u8, 5u8, 6u8, 8u8, 3u8, 2u8, 7u8], - /* 4 */ [2u8, 5u8, 7u8, 4u8, 9u8, 3u8, 6u8, 1u8, 8u8], - /* 5 */ [6u8, 8u8, 3u8, 7u8, 1u8, 2u8, 5u8, 9u8, 4u8], - /* 6 */ [3u8, 9u8, 5u8, 2u8, 8u8, 6u8, 4u8, 7u8, 1u8], - /* 7 */ [8u8, 7u8, 2u8, 3u8, 4u8, 1u8, 9u8, 6u8, 5u8], - /* 8 */ [4u8, 6u8, 1u8, 9u8, 5u8, 7u8, 2u8, 8u8, 3u8] + /* 0 */ [1, 4, 9, 6, 7, 5, 8, 3, 2], + /* 1 */ [5, 3, 8, 1, 2, 9, 7, 4, 6], + /* 2 */ [7, 2, 6, 8, 3, 4, 1, 5, 9], + /* 3 */ [9, 1, 4, 5, 6, 8, 3, 2, 7], + /* 4 */ [2, 5, 7, 4, 9, 3, 6, 1, 8], + /* 5 */ [6, 8, 3, 7, 1, 2, 5, 9, 4], + /* 6 */ [3, 9, 5, 2, 8, 6, 4, 7, 1], + /* 7 */ [8, 7, 2, 3, 4, 1, 9, 6, 5], + /* 8 */ [4, 6, 1, 9, 5, 7, 2, 8, 3] ]; #[test] fn colors_new_works() { - assert_eq!(*Colors::new(1), 1022u16); - assert_eq!(*Colors::new(2), 1020u16); - assert_eq!(*Colors::new(3), 1016u16); - assert_eq!(*Colors::new(4), 1008u16); - assert_eq!(*Colors::new(5), 992u16); - assert_eq!(*Colors::new(6), 960u16); - assert_eq!(*Colors::new(7), 896u16); - assert_eq!(*Colors::new(8), 768u16); - assert_eq!(*Colors::new(9), 512u16); + assert_eq!(*Colors::new(1), 1022); + assert_eq!(*Colors::new(2), 1020); + assert_eq!(*Colors::new(3), 1016); + assert_eq!(*Colors::new(4), 1008); + assert_eq!(*Colors::new(5), 992); + assert_eq!(*Colors::new(6), 960); + assert_eq!(*Colors::new(7), 896); + assert_eq!(*Colors::new(8), 768); + assert_eq!(*Colors::new(9), 512); } #[test] fn colors_next_works() { - assert_eq!(Colors(0).next(), 0u8); - assert_eq!(Colors(2).next(), 1u8); - assert_eq!(Colors(4).next(), 2u8); - assert_eq!(Colors(8).next(), 3u8); - assert_eq!(Colors(16).next(), 4u8); - assert_eq!(Colors(32).next(), 5u8); - assert_eq!(Colors(64).next(), 6u8); - assert_eq!(Colors(128).next(), 7u8); - assert_eq!(Colors(256).next(), 8u8); - assert_eq!(Colors(512).next(), 9u8); - assert_eq!(Colors(1024).next(), 0u8); + assert_eq!(Colors(0).next(), 0); + assert_eq!(Colors(2).next(), 1); + assert_eq!(Colors(4).next(), 2); + assert_eq!(Colors(8).next(), 3); + assert_eq!(Colors(16).next(), 4); + assert_eq!(Colors(32).next(), 5); + assert_eq!(Colors(64).next(), 6); + assert_eq!(Colors(128).next(), 7); + assert_eq!(Colors(256).next(), 8); + assert_eq!(Colors(512).next(), 9); + assert_eq!(Colors(1024).next(), 0); } #[test] @@ -252,7 +253,7 @@ fn colors_remove_works() { colors.remove(1); // THEN - assert_eq!(colors.next(), 2u8); + assert_eq!(colors.next(), 2); } #[test] @@ -269,15 +270,16 @@ fn check_DEFAULT_SUDOKU_solution() { } fn main() { - let args = env::args(); + let args = env::args(); let use_default = args.len() == 1; let mut sudoku = if use_default { Sudoku::from_vec(&DEFAULT_SUDOKU) } else { - let mut stdin = old_io::stdin(); - let mut stdin = stdin.lock(); - Sudoku::read(&mut *stdin) + let stdin = io::stdin(); + let mut locked = stdin.lock(); + Sudoku::read(&mut locked) }; sudoku.solve(); - sudoku.write(&mut old_io::stdout()); + let out = io::stdout(); + sudoku.write(&mut out.lock()); } diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs index 6b412c47cd..9eba2c3639 100644 --- a/src/test/bench/task-perf-alloc-unwind.rs +++ b/src/test/bench/task-perf-alloc-unwind.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unsafe_destructor, box_syntax)] +#![feature(unsafe_destructor, box_syntax, std_misc, collections)] use std::env; use std::thread; @@ -29,7 +29,7 @@ fn main() { run(repeat, depth); } -fn run(repeat: int, depth: int) { +fn run(repeat: isize, depth: isize) { for _ in 0..repeat { let dur = Duration::span(|| { let _ = thread::spawn(move|| { @@ -40,9 +40,7 @@ fn run(repeat: int, depth: int) { } } -// FIXME(#21721) used to be `List<()>` but that can cause -// certain LLVM versions to abort during optimizations. -type nillist = List<[u8; 0]>; +type nillist = List<()>; // Filled with things that have to be unwound @@ -67,7 +65,7 @@ fn r(l: Box) -> r { } } -fn recurse_or_panic(depth: int, st: Option) { +fn recurse_or_panic(depth: isize, st: Option) { if depth == 0 { panic!(); } else { @@ -83,11 +81,11 @@ fn recurse_or_panic(depth: int, st: Option) { } Some(st) => { let mut v = st.vec.clone(); - v.push_all(&[box List::Cons([], st.vec.last().unwrap().clone())]); + v.push_all(&[box List::Cons((), st.vec.last().unwrap().clone())]); State { - unique: box List::Cons([], box *st.unique), + unique: box List::Cons((), box *st.unique), vec: v, - res: r(box List::Cons([], st.res._l.clone())), + res: r(box List::Cons((), st.res._l.clone())), } } }; diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs index e36d685d7c..4798e317ac 100644 --- a/src/test/bench/task-perf-jargon-metal-smoke.rs +++ b/src/test/bench/task-perf-jargon-metal-smoke.rs @@ -21,7 +21,7 @@ use std::sync::mpsc::{channel, Sender}; use std::env; use std::thread; -fn child_generation(gens_left: uint, tx: Sender<()>) { +fn child_generation(gens_left: usize, tx: Sender<()>) { // This used to be O(n^2) in the number of generations that ever existed. // With this code, only as many generations are alive at a time as tasks // alive at a time, diff --git a/src/test/codegen/iterate-over-array.rs b/src/test/codegen/iterate-over-array.rs index b2cbd8821e..a5b449285e 100644 --- a/src/test/codegen/iterate-over-array.rs +++ b/src/test/codegen/iterate-over-array.rs @@ -9,7 +9,7 @@ // except according to those terms. #[no_mangle] -pub fn test(x: &[int]) -> int { +pub fn test(x: &[isize]) -> isize { let mut y = 0; let mut i = 0; while (i < x.len()) { diff --git a/src/test/codegen/scalar-function-call.rs b/src/test/codegen/scalar-function-call.rs index b95d6b0328..fe93c864fa 100644 --- a/src/test/codegen/scalar-function-call.rs +++ b/src/test/codegen/scalar-function-call.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(x: int) -> int { +fn foo(x: isize) -> isize { x * x } diff --git a/src/test/codegen/single-return-value.rs b/src/test/codegen/single-return-value.rs index 948809a632..5addba1724 100644 --- a/src/test/codegen/single-return-value.rs +++ b/src/test/codegen/single-return-value.rs @@ -9,6 +9,6 @@ // except according to those terms. #[no_mangle] -pub fn test() -> int { +pub fn test() -> isize { 5 } diff --git a/src/test/codegen/small-dense-int-switch.rs b/src/test/codegen/small-dense-int-switch.rs index d75bc5209f..cf05a2e2f8 100644 --- a/src/test/codegen/small-dense-int-switch.rs +++ b/src/test/codegen/small-dense-int-switch.rs @@ -9,7 +9,7 @@ // except according to those terms. #[no_mangle] -pub fn test(x: int, y: int) -> int { +pub fn test(x: isize, y: isize) -> isize { match x { 1 => y, 2 => y*2, diff --git a/src/test/codegen/static-method-call-multi.rs b/src/test/codegen/static-method-call-multi.rs index 996d220382..025f9b524c 100644 --- a/src/test/codegen/static-method-call-multi.rs +++ b/src/test/codegen/static-method-call-multi.rs @@ -9,11 +9,11 @@ // except according to those terms. pub struct Struct { - field: int + field: isize } impl Struct { - fn method(&self, x: int) -> int { + fn method(&self, x: isize) -> isize { self.field + x } } @@ -23,6 +23,6 @@ pub fn test(a: &Struct, b: &Struct, c: &Struct, d: &Struct, - e: &Struct) -> int { + e: &Struct) -> isize { a.method(b.method(c.method(d.method(e.method(1))))) } diff --git a/src/test/codegen/static-method-call.rs b/src/test/codegen/static-method-call.rs index 9c5894fb97..fca3784d9e 100644 --- a/src/test/codegen/static-method-call.rs +++ b/src/test/codegen/static-method-call.rs @@ -9,16 +9,16 @@ // except according to those terms. pub struct Struct { - field: int + field: isize } impl Struct { - fn method(&self) -> int { + fn method(&self) -> isize { self.field } } #[no_mangle] -pub fn test(s: &Struct) -> int { +pub fn test(s: &Struct) -> isize { s.method() } diff --git a/src/test/codegen/virtual-method-call-struct-return.rs b/src/test/codegen/virtual-method-call-struct-return.rs index ff1a611c4e..ae83409b45 100644 --- a/src/test/codegen/virtual-method-call-struct-return.rs +++ b/src/test/codegen/virtual-method-call-struct-return.rs @@ -9,7 +9,7 @@ // except according to those terms. pub struct Stuff { - a: int, + a: isize, b: f64 } @@ -18,6 +18,6 @@ pub trait Trait { } #[no_mangle] -pub fn test(t: &Trait) -> int { +pub fn test(t: &Trait) -> isize { t.method().a } diff --git a/src/test/codegen/virtual-method-call.rs b/src/test/codegen/virtual-method-call.rs index 036c0957e9..9bfeef1f01 100644 --- a/src/test/codegen/virtual-method-call.rs +++ b/src/test/codegen/virtual-method-call.rs @@ -9,10 +9,10 @@ // except according to those terms. pub trait Trait { - fn method(&self) -> int; + fn method(&self) -> isize; } #[no_mangle] -pub fn test(t: &Trait) -> int { +pub fn test(t: &Trait) -> isize { t.method() } diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs new file mode 100644 index 0000000000..a88445bafc --- /dev/null +++ b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs @@ -0,0 +1,22 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that macro reexports item are gated by `macro_reexport` feature gate. + +// aux-build:macro_reexport_1.rs +// ignore-stage1 + +#![crate_type = "dylib"] + +#[macro_reexport(reexported)] +#[macro_use] #[no_link] +extern crate macro_reexport_1; +//~^ ERROR macros reexports are experimental and possibly buggy +//~| HELP add #![feature(macro_reexport)] to the crate attributes to enable diff --git a/src/test/compile-fail-fulldeps/gated-quote.rs b/src/test/compile-fail-fulldeps/gated-quote.rs new file mode 100644 index 0000000000..6a5cd88a59 --- /dev/null +++ b/src/test/compile-fail-fulldeps/gated-quote.rs @@ -0,0 +1,50 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `quote`-related macro are gated by `quote` feature gate. + +// (To sanity-check the code, uncomment this.) +// #![feature(quote)] + +// FIXME the error message that is current emitted seems pretty bad. + +#![feature(rustc_private)] +#![allow(dead_code, unused_imports, unused_variables)] + +#[macro_use] +extern crate syntax; + +use syntax::ast; +use syntax::codemap::Span; +use syntax::parse; + +struct ParseSess; + +impl ParseSess { + fn cfg(&self) -> ast::CrateConfig { loop { } } + fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { loop { } } + fn call_site(&self) -> Span { loop { } } + fn ident_of(&self, st: &str) -> ast::Ident { loop { } } + fn name_of(&self, st: &str) -> ast::Name { loop { } } +} + +pub fn main() { + let ecx = &ParseSess; + let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: 'quote_tokens!' + let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: 'quote_expr!' + let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: 'quote_ty!' + let x = quote_method!(ecx, 3); //~ ERROR macro undefined: 'quote_method!' + let x = quote_item!(ecx, 3); //~ ERROR macro undefined: 'quote_item!' + let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: 'quote_pat!' + let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: 'quote_arm!' + let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: 'quote_stmt!' + let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: 'quote_matcher!' + let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: 'quote_attr!' +} diff --git a/src/test/compile-fail-fulldeps/issue-15778-fail.rs b/src/test/compile-fail-fulldeps/issue-15778-fail.rs new file mode 100644 index 0000000000..8c6889f715 --- /dev/null +++ b/src/test/compile-fail-fulldeps/issue-15778-fail.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:lint_for_crate.rs +// ignore-stage1 +// compile-flags: -D crate-not-okay + +#![feature(plugin, custom_attribute)] //~ ERROR crate is not marked with #![crate_okay] +#![plugin(lint_for_crate)] + +pub fn main() { } diff --git a/src/test/compile-fail-fulldeps/issue-18986.rs b/src/test/compile-fail-fulldeps/issue-18986.rs index 9b696e05c5..06fc3db58c 100644 --- a/src/test/compile-fail-fulldeps/issue-18986.rs +++ b/src/test/compile-fail-fulldeps/issue-18986.rs @@ -15,6 +15,6 @@ pub use use_from_trait_xc::Trait; fn main() { match () { - Trait { x: 42_usize } => () //~ ERROR use of trait `Trait` in a struct pattern + Trait { x: 42 } => () //~ ERROR use of trait `Trait` in a struct pattern } } diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs index 7111c00d12..6c9b8f81b2 100644 --- a/src/test/compile-fail/array-not-vector.rs +++ b/src/test/compile-fail/array-not-vector.rs @@ -9,14 +9,14 @@ // except according to those terms. fn main() { - let _x: i32 = [1i32, 2, 3]; + let _x: i32 = [1, 2, 3]; //~^ ERROR mismatched types //~| expected `i32` - //~| found `[i32; 3]` + //~| found `[_; 3]` //~| expected i32 //~| found array of 3 elements - let x: &[i32] = &[1i32, 2, 3]; + let x: &[i32] = &[1, 2, 3]; let _y: &i32 = x; //~^ ERROR mismatched types //~| expected `&i32` diff --git a/src/test/compile-fail/asm-in-bad-modifier.rs b/src/test/compile-fail/asm-in-bad-modifier.rs index 01481af817..3cb608a9c5 100644 --- a/src/test/compile-fail/asm-in-bad-modifier.rs +++ b/src/test/compile-fail/asm-in-bad-modifier.rs @@ -20,8 +20,8 @@ pub fn main() { let x: isize; let y: isize; unsafe { - asm!("mov $1, $0" : "=r"(x) : "=r"(5_usize)); //~ ERROR operand constraint contains '=' - asm!("mov $1, $0" : "=r"(y) : "+r"(5_usize)); //~ ERROR operand constraint contains '+' + asm!("mov $1, $0" : "=r"(x) : "=r"(5)); //~ ERROR operand constraint contains '=' + asm!("mov $1, $0" : "=r"(y) : "+r"(5)); //~ ERROR operand constraint contains '+' } foo(x); foo(y); diff --git a/src/test/compile-fail/asm-misplaced-option.rs b/src/test/compile-fail/asm-misplaced-option.rs index 02d06c4e1b..43a0ad6b5f 100644 --- a/src/test/compile-fail/asm-misplaced-option.rs +++ b/src/test/compile-fail/asm-misplaced-option.rs @@ -10,13 +10,14 @@ // ignore-android -#![feature(asm)] +#![feature(asm, rustc_attrs)] #![allow(dead_code, non_upper_case_globals)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -pub fn main() { +#[rustc_error] +pub fn main() { //~ ERROR compilation successful // assignment not dead let mut x: isize = 0; unsafe { @@ -33,7 +34,3 @@ pub fn main() { } assert_eq!(x, 13); } - -// At least one error is needed so that compilation fails -#[static_assert] -static b: bool = false; //~ ERROR static assertion failed diff --git a/src/test/compile-fail/asm-out-assign-imm.rs b/src/test/compile-fail/asm-out-assign-imm.rs index ff56fb14f7..8c8451623d 100644 --- a/src/test/compile-fail/asm-out-assign-imm.rs +++ b/src/test/compile-fail/asm-out-assign-imm.rs @@ -21,7 +21,7 @@ pub fn main() { x = 1; //~ NOTE prior assignment occurs here foo(x); unsafe { - asm!("mov $1, $0" : "=r"(x) : "r"(5_usize)); + asm!("mov $1, $0" : "=r"(x) : "r"(5)); //~^ ERROR re-assignment of immutable variable `x` } foo(x); diff --git a/src/test/compile-fail/asm-out-no-modifier.rs b/src/test/compile-fail/asm-out-no-modifier.rs index 17c19c77ab..9cf43bebe6 100644 --- a/src/test/compile-fail/asm-out-no-modifier.rs +++ b/src/test/compile-fail/asm-out-no-modifier.rs @@ -19,7 +19,7 @@ fn foo(x: isize) { println!("{}", x); } pub fn main() { let x: isize; unsafe { - asm!("mov $1, $0" : "r"(x) : "r"(5_usize)); //~ ERROR output operand constraint lacks '=' + asm!("mov $1, $0" : "r"(x) : "r"(5)); //~ ERROR output operand constraint lacks '=' } foo(x); } diff --git a/src/test/compile-fail/assign-to-method.rs b/src/test/compile-fail/assign-to-method.rs index d32ea327d0..4518ce36b6 100644 --- a/src/test/compile-fail/assign-to-method.rs +++ b/src/test/compile-fail/assign-to-method.rs @@ -15,7 +15,7 @@ struct cat { } impl cat { - pub fn speak(&self) { self.meows += 1_usize; } + pub fn speak(&self) { self.meows += 1; } } fn cat(in_x : usize, in_y : isize) -> cat { @@ -26,6 +26,6 @@ fn cat(in_x : usize, in_y : isize) -> cat { } fn main() { - let nyan : cat = cat(52_usize, 99); + let nyan : cat = cat(52, 99); nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method } diff --git a/src/test/compile-fail/assignment-operator-unimplemented.rs b/src/test/compile-fail/assignment-operator-unimplemented.rs index 5b24c6bd79..fef27af595 100644 --- a/src/test/compile-fail/assignment-operator-unimplemented.rs +++ b/src/test/compile-fail/assignment-operator-unimplemented.rs @@ -13,5 +13,5 @@ struct Foo; fn main() { let mut a = Foo; let ref b = Foo; - a += *b; //~ Error: binary assignment operation `+=` cannot be applied to type `Foo` + a += *b; //~ Error: binary assignment operation `+=` cannot be applied to types `Foo` and `Foo` } diff --git a/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs b/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs new file mode 100644 index 0000000000..ce97019a2b --- /dev/null +++ b/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs @@ -0,0 +1,52 @@ +// 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 or the MIT license +// , 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. + +pub trait Vehicle { + type Color; + + fn go(&self) { } +} + +pub trait Box { + type Color; + + fn mail(&self) { } +} + +fn a(_: C::Color) { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +fn b(_: C::Color) where C : Vehicle+Box { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +fn c(_: C::Color) where C : Vehicle, C : Box { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +struct D; +impl D where X : Vehicle { + fn d(&self, _: X::Color) where X : Box { } + //~^ ERROR ambiguous associated type `Color` in bounds of `X` +} + +trait E { + fn e(&self, _: X::Color) where X : Box; + //~^ ERROR ambiguous associated type `Color` in bounds of `X` + + fn f(&self, _: X::Color) where X : Box { } + //~^ ERROR ambiguous associated type `Color` in bounds of `X` +} + +pub fn main() { } diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index edd1b8255c..04170779ed 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -35,5 +35,6 @@ trait Add { fn ice(a: A) { let r = loop {}; r = r + a; - //~^ ERROR binary operation `+` cannot be applied to type `A` + //~^ ERROR not implemented + //~| ERROR not implemented } diff --git a/src/test/compile-fail/associated-types-coherence-failure.rs b/src/test/compile-fail/associated-types-coherence-failure.rs index b7a16c68a3..915cb07778 100644 --- a/src/test/compile-fail/associated-types-coherence-failure.rs +++ b/src/test/compile-fail/associated-types-coherence-failure.rs @@ -57,4 +57,3 @@ pub trait ToOwned { fn main() {} - diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index c48f9972eb..0d68b960f3 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -22,5 +22,5 @@ impl Foo for isize { pub fn main() { let x: isize = Foo::::bar(); - //~^ERROR unexpected binding of associated item in expression path + //~^ ERROR unexpected binding of associated item in expression path } diff --git a/src/test/compile-fail/associated-types-in-ambiguous-context.rs b/src/test/compile-fail/associated-types-in-ambiguous-context.rs index 3999e9cbe7..becbc27138 100644 --- a/src/test/compile-fail/associated-types-in-ambiguous-context.rs +++ b/src/test/compile-fail/associated-types-in-ambiguous-context.rs @@ -22,5 +22,8 @@ trait Grab { //~^ ERROR ambiguous associated type } +type X = std::ops::Deref::Target; +//~^ ERROR ambiguous associated type + fn main() { } diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs index 625f4cdb8e..5c36e3356a 100644 --- a/src/test/compile-fail/associated-types-issue-17359.rs +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -18,4 +18,3 @@ trait Trait : ::std::marker::MarkerTrait { impl Trait for isize {} //~ ERROR missing: `Type` fn main() {} - diff --git a/src/test/compile-fail/bad-bang-ann-3.rs b/src/test/compile-fail/bad-bang-ann-3.rs index 58a8314af2..de315a4136 100644 --- a/src/test/compile-fail/bad-bang-ann-3.rs +++ b/src/test/compile-fail/bad-bang-ann-3.rs @@ -11,7 +11,7 @@ // Tests that a function with a ! annotation always actually fails fn bad_bang(i: usize) -> ! { - return 7_usize; //~ ERROR `return` in a function declared as diverging [E0166] + return 7; //~ ERROR `return` in a function declared as diverging [E0166] } fn main() { bad_bang(5); } diff --git a/src/test/compile-fail/bad-bang-ann.rs b/src/test/compile-fail/bad-bang-ann.rs index 03c24c2fa3..f0ecf31fd1 100644 --- a/src/test/compile-fail/bad-bang-ann.rs +++ b/src/test/compile-fail/bad-bang-ann.rs @@ -11,7 +11,7 @@ // Tests that a function with a ! annotation always actually fails fn bad_bang(i: usize) -> ! { //~ ERROR computation may converge in a function marked as diverging - if i < 0_usize { } else { panic!(); } + if i < 0 { } else { panic!(); } } fn main() { bad_bang(5); } diff --git a/src/test/compile-fail/bad-const-type.rs b/src/test/compile-fail/bad-const-type.rs index 7e3c356b87..a9e5c957b8 100644 --- a/src/test/compile-fail/bad-const-type.rs +++ b/src/test/compile-fail/bad-const-type.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static i: String = 10i32; +static i: String = 10; //~^ ERROR mismatched types //~| expected `collections::string::String` -//~| found `i32` +//~| found `_` //~| expected struct `collections::string::String` -//~| found i32 +//~| found integral variable fn main() { println!("{}", i); } diff --git a/src/test/compile-fail/bad-method-typaram-kind.rs b/src/test/compile-fail/bad-method-typaram-kind.rs index a97cf5d41e..2129d4fbd5 100644 --- a/src/test/compile-fail/bad-method-typaram-kind.rs +++ b/src/test/compile-fail/bad-method-typaram-kind.rs @@ -9,7 +9,7 @@ // except according to those terms. fn foo() { - 1_usize.bar::(); //~ ERROR `core::marker::Send` is not implemented + 1.bar::(); //~ ERROR `core::marker::Send` is not implemented } trait bar { diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs index 3e02a11c37..7a7406115d 100644 --- a/src/test/compile-fail/bad-mid-path-type-params.rs +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -43,7 +43,7 @@ fn foo<'a>() { //~^ ERROR too many type parameters provided let _ = S::<'a,isize>::new::(1, 1.0); - //~^ ERROR too many lifetime parameters provided + //~^ ERROR wrong number of lifetime parameters let _: S2 = Trait::new::(1, 1.0); //~^ ERROR too many type parameters provided diff --git a/src/test/compile-fail/binop-logic-float.rs b/src/test/compile-fail/binop-logic-float.rs index 923d611ceb..f3fb5a08c8 100644 --- a/src/test/compile-fail/binop-logic-float.rs +++ b/src/test/compile-fail/binop-logic-float.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:`||` cannot be applied to type `f32` - fn main() { let x = 1.0_f32 || 2.0_f32; } +//~^ ERROR mismatched types +//~| ERROR mismatched types + diff --git a/src/test/compile-fail/binop-logic-int.rs b/src/test/compile-fail/binop-logic-int.rs index 2217cf5e4d..f5e53f84c1 100644 --- a/src/test/compile-fail/binop-logic-int.rs +++ b/src/test/compile-fail/binop-logic-int.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:`&&` cannot be applied to type `i32` - -fn main() { let x = 1i32 && 2i32; } +fn main() { let x = 1 && 2; } +//~^ ERROR mismatched types +//~| ERROR mismatched types diff --git a/src/test/compile-fail/borrow-immutable-upvar-mutation.rs b/src/test/compile-fail/borrow-immutable-upvar-mutation.rs index a82aa12dc8..00f51973a4 100644 --- a/src/test/compile-fail/borrow-immutable-upvar-mutation.rs +++ b/src/test/compile-fail/borrow-immutable-upvar-mutation.rs @@ -21,25 +21,25 @@ fn to_fn_mut>(f: F) -> F { f } fn main() { // By-ref captures { - let mut x = 0_usize; + let mut x = 0; let _f = to_fn(|| x = 42); //~ ERROR cannot assign - let mut y = 0_usize; + let mut y = 0; let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow - let mut z = 0_usize; + let mut z = 0; let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); //~ ERROR cannot assign } // By-value captures { - let mut x = 0_usize; + let mut x = 0; let _f = to_fn(move || x = 42); //~ ERROR cannot assign - let mut y = 0_usize; + let mut y = 0; let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow - let mut z = 0_usize; + let mut z = 0; let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign } } diff --git a/src/test/compile-fail/borrow-tuple-fields.rs b/src/test/compile-fail/borrow-tuple-fields.rs index 40e077bd1b..b1abbad525 100644 --- a/src/test/compile-fail/borrow-tuple-fields.rs +++ b/src/test/compile-fail/borrow-tuple-fields.rs @@ -16,7 +16,7 @@ struct Foo(Box, isize); struct Bar(isize, isize); fn main() { - let x = (box 1, 2); + let x: (Box<_>, _) = (box 1, 2); let r = &x.0; let y = x; //~ ERROR cannot move out of `x` because it is borrowed diff --git a/src/test/compile-fail/borrowck-bad-nested-calls-free.rs b/src/test/compile-fail/borrowck-bad-nested-calls-free.rs index 4d1939be5b..7913f9ac90 100644 --- a/src/test/compile-fail/borrowck-bad-nested-calls-free.rs +++ b/src/test/compile-fail/borrowck-bad-nested-calls-free.rs @@ -23,7 +23,7 @@ fn add(v: &usize, w: usize) -> usize { } fn implicit() { - let mut a = box 1; + let mut a: Box<_> = box 1; // Note the danger here: // @@ -36,7 +36,7 @@ fn implicit() { } fn explicit() { - let mut a = box 1; + let mut a: Box<_> = box 1; add( &*a, rewrite(&mut a)); //~ ERROR cannot borrow diff --git a/src/test/compile-fail/borrowck-bad-nested-calls-move.rs b/src/test/compile-fail/borrowck-bad-nested-calls-move.rs index 9eda368933..e24d4e87ad 100644 --- a/src/test/compile-fail/borrowck-bad-nested-calls-move.rs +++ b/src/test/compile-fail/borrowck-bad-nested-calls-move.rs @@ -23,7 +23,7 @@ fn add(v: &usize, w: Box) -> usize { } fn implicit() { - let mut a = box 1; + let mut a: Box<_> = box 1; // Note the danger here: // @@ -36,7 +36,7 @@ fn implicit() { } fn explicit() { - let mut a = box 1; + let mut a: Box<_> = box 1; add( &*a, a); //~ ERROR cannot move diff --git a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs b/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs index 99618c6bf5..e5091a9258 100644 --- a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs +++ b/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs @@ -9,13 +9,13 @@ // except according to those terms. -#[derive(Copy)] +#[derive(Copy, Clone)] struct Foo { bar1: Bar, bar2: Bar } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Bar { int1: isize, int2: isize, diff --git a/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs b/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs index 849c98e122..440be93dfd 100644 --- a/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs +++ b/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +#[derive(Copy, Clone)] struct Foo { bar1: Bar, bar2: Bar } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Bar { int1: isize, int2: isize, diff --git a/src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs b/src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs index 794e0fc6e3..3662e23a41 100644 --- a/src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs +++ b/src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs @@ -18,7 +18,7 @@ impl A { } pub fn main() { - let a = box A; + let a: Box<_> = box A; a.foo(); //~^ ERROR cannot borrow immutable `Box` content `*a` as mutable } diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs index 9126058a4e..d60751eddc 100644 --- a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs +++ b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -11,7 +11,7 @@ // Test that attempt to reborrow an `&mut` pointer in an aliasable // location yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo(t0: & &mut isize) { let t1 = t0; diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs index 9c10f01e02..8bbecfd48c 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs @@ -16,9 +16,10 @@ extern crate collections; use std::collections::HashMap; fn main() { - let tmp; + let tmp: Box<_>; let mut buggy_map: HashMap = HashMap::new(); - buggy_map.insert(42, &*box 1); //~ ERROR borrowed value does not live long enough + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + buggy_map.insert(42, &*Box::new(1)); //~ ERROR borrowed value does not live long enough // but it is ok if we use a temporary tmp = box 2; diff --git a/src/test/compile-fail/borrowck-box-insensitivity.rs b/src/test/compile-fail/borrowck-box-insensitivity.rs index 648d0d81ff..c980e77df6 100644 --- a/src/test/compile-fail/borrowck-box-insensitivity.rs +++ b/src/test/compile-fail/borrowck-box-insensitivity.rs @@ -31,100 +31,100 @@ struct D { } fn copy_after_move() { - let a = box A { x: box 0, y: 1 }; + let a: Box<_> = box A { x: box 0, y: 1 }; let _x = a.x; let _y = a.y; //~ ERROR use of moved //~^^ NOTE `a` moved here (through moving `a.x`) } fn move_after_move() { - let a = box B { x: box 0, y: box 1 }; + let a: Box<_> = box B { x: box 0, y: box 1 }; let _x = a.x; let _y = a.y; //~ ERROR use of moved //~^^ NOTE `a` moved here (through moving `a.x`) } fn borrow_after_move() { - let a = box A { x: box 0, y: 1 }; + let a: Box<_> = box A { x: box 0, y: 1 }; let _x = a.x; let _y = &a.y; //~ ERROR use of moved //~^^ NOTE `a` moved here (through moving `a.x`) } fn move_after_borrow() { - let a = box B { x: box 0, y: box 1 }; + let a: Box<_> = box B { x: box 0, y: box 1 }; let _x = &a.x; let _y = a.y; //~ ERROR cannot move } fn copy_after_mut_borrow() { - let mut a = box A { x: box 0, y: 1 }; + let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &mut a.x; let _y = a.y; //~ ERROR cannot use } fn move_after_mut_borrow() { - let mut a = box B { x: box 0, y: box 1 }; + let mut a: Box<_> = box B { x: box 0, y: box 1 }; let _x = &mut a.x; let _y = a.y; //~ ERROR cannot move } fn borrow_after_mut_borrow() { - let mut a = box A { x: box 0, y: 1 }; + let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &mut a.x; let _y = &a.y; //~ ERROR cannot borrow } fn mut_borrow_after_borrow() { - let mut a = box A { x: box 0, y: 1 }; + let mut a: Box<_> = box A { x: box 0, y: 1 }; let _x = &a.x; let _y = &mut a.y; //~ ERROR cannot borrow } fn copy_after_move_nested() { - let a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = a.x.x; let _y = a.y; //~ ERROR use of collaterally moved } fn move_after_move_nested() { - let a = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = a.x.x; let _y = a.y; //~ ERROR use of collaterally moved } fn borrow_after_move_nested() { - let a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = a.x.x; let _y = &a.y; //~ ERROR use of collaterally moved } fn move_after_borrow_nested() { - let a = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = &a.x.x; let _y = a.y; //~ ERROR cannot move } fn copy_after_mut_borrow_nested() { - let mut a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &mut a.x.x; let _y = a.y; //~ ERROR cannot use } fn move_after_mut_borrow_nested() { - let mut a = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; let _x = &mut a.x.x; let _y = a.y; //~ ERROR cannot move } fn borrow_after_mut_borrow_nested() { - let mut a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &mut a.x.x; let _y = &a.y; //~ ERROR cannot borrow } fn mut_borrow_after_borrow_nested() { - let mut a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; let _x = &a.x.x; let _y = &mut a.y; //~ ERROR cannot borrow } @@ -152,4 +152,3 @@ fn main() { borrow_after_mut_borrow_nested(); mut_borrow_after_borrow_nested(); } - diff --git a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs b/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs index 9ea5fbbdb1..7626f354eb 100644 --- a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs @@ -11,7 +11,6 @@ // Ensure that invoking a closure counts as a unique immutable borrow #![feature(unboxed_closures)] -#![feature(box_syntax)] type Fn<'a> = Box; @@ -19,11 +18,12 @@ struct Test<'a> { f: Box } +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. fn call(mut f: F) where F: FnMut(Fn) { - f(box || { + f(Box::new(|| { //~^ ERROR: cannot borrow `f` as mutable more than once - f(box || {}) - }); + f((Box::new(|| {}))) + })); } fn test1() { @@ -58,11 +58,12 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} let mut f = |g: Box, b: isize| {}; - f(box |a| { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + f(Box::new(|a| { foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed //~| ERROR cannot move out of captured outer variable in an `FnMut` closure - }, 3); + }), 3); } fn main() {} diff --git a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck-closures-mut-and-imm.rs index 851b11fac2..aaa0766121 100644 --- a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs +++ b/src/test/compile-fail/borrowck-closures-mut-and-imm.rs @@ -52,7 +52,7 @@ fn e() { } fn f() { - let mut x = box 3; + let mut x: Box<_> = box 3; let c1 = || get(&*x); *x = 5; //~ ERROR cannot assign } @@ -62,7 +62,7 @@ fn g() { f: Box } - let mut x = box Foo { f: box 3 }; + let mut x: Box<_> = box Foo { f: box 3 }; let c1 = || get(&*x.f); *x.f = 5; //~ ERROR cannot assign to `*x.f` } @@ -72,7 +72,7 @@ fn h() { f: Box } - let mut x = box Foo { f: box 3 }; + let mut x: Box<_> = box Foo { f: box 3 }; let c1 = || get(&*x.f); let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable } diff --git a/src/test/compile-fail/borrowck-closures-two-mut.rs b/src/test/compile-fail/borrowck-closures-two-mut.rs index 8ab4e257b0..29546abe0b 100644 --- a/src/test/compile-fail/borrowck-closures-two-mut.rs +++ b/src/test/compile-fail/borrowck-closures-two-mut.rs @@ -50,7 +50,7 @@ fn g() { f: Box } - let mut x = box Foo { f: box 3 }; + let mut x: Box<_> = box Foo { f: box 3 }; let c1 = to_fn_mut(|| set(&mut *x.f)); let c2 = to_fn_mut(|| set(&mut *x.f)); //~^ ERROR cannot borrow `x` as mutable more than once diff --git a/src/test/compile-fail/borrowck-closures-unique-imm.rs b/src/test/compile-fail/borrowck-closures-unique-imm.rs index dcf43c01e1..247a4fe89a 100644 --- a/src/test/compile-fail/borrowck-closures-unique-imm.rs +++ b/src/test/compile-fail/borrowck-closures-unique-imm.rs @@ -22,4 +22,3 @@ pub fn main() { }; r() } - diff --git a/src/test/compile-fail/borrowck-closures-use-after-free.rs b/src/test/compile-fail/borrowck-closures-use-after-free.rs index 32cd364d1f..bb474342a7 100644 --- a/src/test/compile-fail/borrowck-closures-use-after-free.rs +++ b/src/test/compile-fail/borrowck-closures-use-after-free.rs @@ -25,7 +25,7 @@ impl Drop for Foo { } fn main() { - let mut ptr = box Foo { x: 0 }; + let mut ptr: Box<_> = box Foo { x: 0 }; let mut test = |foo: &Foo| { ptr = box Foo { x: ptr.x + 1 }; }; diff --git a/src/test/compile-fail/borrowck-consume-unsize-vec.rs b/src/test/compile-fail/borrowck-consume-unsize-vec.rs new file mode 100644 index 0000000000..32490e0dc7 --- /dev/null +++ b/src/test/compile-fail/borrowck-consume-unsize-vec.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we report an error if an upcast box is moved twice. + +fn consume(_: Box<[i32]>) { +} + +fn foo(b: Box<[i32;5]>) { + consume(b); + consume(b); //~ ERROR use of moved value +} + +fn main() { +} diff --git a/src/test/compile-fail/borrowck-consume-upcast-box.rs b/src/test/compile-fail/borrowck-consume-upcast-box.rs new file mode 100644 index 0000000000..5bcafa675c --- /dev/null +++ b/src/test/compile-fail/borrowck-consume-upcast-box.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we report an error if an upcast box is moved twice. + +trait Foo { fn dummy(&self); } + +fn consume(_: Box) { +} + +fn foo(b: Box) { + consume(b); + consume(b); //~ ERROR use of moved value +} + +fn main() { +} diff --git a/src/test/compile-fail/borrowck-field-sensitivity.rs b/src/test/compile-fail/borrowck-field-sensitivity.rs index fe5142a773..13fd5fce95 100644 --- a/src/test/compile-fail/borrowck-field-sensitivity.rs +++ b/src/test/compile-fail/borrowck-field-sensitivity.rs @@ -124,4 +124,3 @@ fn main() { borrow_after_field_assign_after_uninit(); move_after_field_assign_after_uninit(); } - diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/borrowck-fn-in-const-a.rs similarity index 69% rename from src/test/compile-fail/issue-5543.rs rename to src/test/compile-fail/borrowck-fn-in-const-a.rs index 4d721ad766..3098807f27 100644 --- a/src/test/compile-fail/issue-5543.rs +++ b/src/test/compile-fail/borrowck-fn-in-const-a.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] +// Check that we check fns appearing in constant declarations. +// Issue #22382. -trait Foo { fn foo(&self) {} } -impl Foo for u8 {} +const MOVE: fn(&String) -> String = { + fn broken(x: &String) -> String { + return *x //~ ERROR cannot move + } + broken +}; fn main() { - let r: Box = box 5; - let _m: Box = r as Box; - //~^ ERROR `core::marker::Sized` is not implemented for the type `Foo` } diff --git a/src/test/compile-fail/borrowck-fn-in-const-b.rs b/src/test/compile-fail/borrowck-fn-in-const-b.rs new file mode 100644 index 0000000000..7e29b2ee0f --- /dev/null +++ b/src/test/compile-fail/borrowck-fn-in-const-b.rs @@ -0,0 +1,24 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we check fns appearing in constant declarations. +// Issue #22382. + +// How about mutating an immutable vector? +const MUTATE: fn(&Vec) = { + fn broken(x: &Vec) { + x.push(format!("this is broken")); + //~^ ERROR cannot borrow + } + broken +}; + +fn main() { +} diff --git a/src/test/compile-fail/borrowck-fn-in-const-c.rs b/src/test/compile-fail/borrowck-fn-in-const-c.rs new file mode 100644 index 0000000000..e607397e92 --- /dev/null +++ b/src/test/compile-fail/borrowck-fn-in-const-c.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that we check fns appearing in constant declarations. +// Issue #22382. + +// Returning local references? +struct DropString { + inner: String +} +impl Drop for DropString { + fn drop(&mut self) { + self.inner.clear(); + self.inner.push_str("dropped"); + } +} +const LOCAL_REF: fn() -> &'static str = { + fn broken() -> &'static str { + let local = DropString { inner: format!("Some local string") }; + return &local.inner; //~ ERROR does not live long enough + } + broken +}; + +fn main() { +} diff --git a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs b/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs index 492fd4a2c8..31ec5aea7f 100644 --- a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs +++ b/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs @@ -28,8 +28,7 @@ fn main() { for &a in &f.a { //~ ERROR cannot move out } - let x = Some(box 1); + let x: Option> = Some(box 1); for &a in x.iter() { //~ ERROR cannot move out } } - diff --git a/src/test/compile-fail/borrowck-for-loop-head-linkage.rs b/src/test/compile-fail/borrowck-for-loop-head-linkage.rs index 01a649ae24..b79fc5b2bf 100644 --- a/src/test/compile-fail/borrowck-for-loop-head-linkage.rs +++ b/src/test/compile-fail/borrowck-for-loop-head-linkage.rs @@ -18,4 +18,3 @@ fn main() { vector[1] = 5; //~ ERROR cannot borrow } } - diff --git a/src/test/compile-fail/borrowck-issue-14498.rs b/src/test/compile-fail/borrowck-issue-14498.rs index cc562afa9f..64033623fe 100644 --- a/src/test/compile-fail/borrowck-issue-14498.rs +++ b/src/test/compile-fail/borrowck-issue-14498.rs @@ -9,26 +9,48 @@ // except according to those terms. // This tests that we can't modify Box<&mut T> contents while they -// are borrowed. +// are borrowed (#14498). +// +// Also includes tests of the errors reported when the Box in question +// is immutable (#14270). #![feature(box_syntax)] struct A { a: isize } struct B<'a> { a: Box<&'a mut isize> } +fn indirect_write_to_imm_box() { + let mut x: isize = 1; + let y: Box<_> = box &mut x; + let p = &y; + ***p = 2; //~ ERROR cannot assign to data in an immutable container + drop(p); +} + fn borrow_in_var_from_var() { let mut x: isize = 1; - let y = box &mut x; + let mut y: Box<_> = box &mut x; + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_var_from_var_via_imm_box() { + let mut x: isize = 1; + let y: Box<_> = box &mut x; let p = &y; let q = &***p; **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + //~^ ERROR cannot assign to data in an immutable container drop(p); drop(q); } fn borrow_in_var_from_field() { let mut x = A { a: 1 }; - let y = box &mut x.a; + let mut y: Box<_> = box &mut x.a; let p = &y; let q = &***p; **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed @@ -36,30 +58,67 @@ fn borrow_in_var_from_field() { drop(q); } +fn borrow_in_var_from_field_via_imm_box() { + let mut x = A { a: 1 }; + let y: Box<_> = box &mut x.a; + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + //~^ ERROR cannot assign to data in an immutable container + drop(p); + drop(q); +} + fn borrow_in_field_from_var() { + let mut x: isize = 1; + let mut y = B { a: box &mut x }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_var_via_imm_box() { let mut x: isize = 1; let y = B { a: box &mut x }; let p = &y.a; let q = &***p; **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + //~^ ERROR cannot assign to data in an immutable container drop(p); drop(q); } fn borrow_in_field_from_field() { + let mut x = A { a: 1 }; + let mut y = B { a: box &mut x.a }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_field_via_imm_box() { let mut x = A { a: 1 }; let y = B { a: box &mut x.a }; let p = &y.a; let q = &***p; **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + //~^ ERROR cannot assign to data in an immutable container drop(p); drop(q); } fn main() { + indirect_write_to_imm_box(); borrow_in_var_from_var(); + borrow_in_var_from_var_via_imm_box(); borrow_in_var_from_field(); + borrow_in_var_from_field_via_imm_box(); borrow_in_field_from_var(); + borrow_in_field_from_var_via_imm_box(); borrow_in_field_from_field(); + borrow_in_field_from_field_via_imm_box(); } - diff --git a/src/test/compile-fail/borrowck-issue-2657-1.rs b/src/test/compile-fail/borrowck-issue-2657-1.rs index 0c717d2ee5..0e1712137d 100644 --- a/src/test/compile-fail/borrowck-issue-2657-1.rs +++ b/src/test/compile-fail/borrowck-issue-2657-1.rs @@ -11,7 +11,7 @@ #![feature(box_syntax)] fn main() { - let x = Some(box 1); + let x: Option> = Some(box 1); match x { Some(ref _y) => { let _a = x; //~ ERROR cannot move diff --git a/src/test/compile-fail/borrowck-issue-2657-2.rs b/src/test/compile-fail/borrowck-issue-2657-2.rs index b4e5ae1c25..a389a4a559 100644 --- a/src/test/compile-fail/borrowck-issue-2657-2.rs +++ b/src/test/compile-fail/borrowck-issue-2657-2.rs @@ -11,7 +11,7 @@ #![feature(box_syntax)] fn main() { - let x = Some(box 1); + let x: Option> = Some(box 1); match x { Some(ref y) => { let _b = *y; //~ ERROR cannot move out diff --git a/src/test/compile-fail/borrowck-lend-flow-if.rs b/src/test/compile-fail/borrowck-lend-flow-if.rs index ca8efb5dc9..0efe862262 100644 --- a/src/test/compile-fail/borrowck-lend-flow-if.rs +++ b/src/test/compile-fail/borrowck-lend-flow-if.rs @@ -30,7 +30,7 @@ fn pre_freeze_cond() { // In this instance, the freeze is conditional and starts before // the mut borrow. - let mut v = box 3; + let mut v: Box<_> = box 3; let _w; if cond() { _w = &v; @@ -42,7 +42,7 @@ fn pre_freeze_else() { // In this instance, the freeze and mut borrow are on separate sides // of the if. - let mut v = box 3; + let mut v: Box<_> = box 3; let _w; if cond() { _w = &v; diff --git a/src/test/compile-fail/borrowck-lend-flow-loop.rs b/src/test/compile-fail/borrowck-lend-flow-loop.rs index 5418a531fe..f841fedf75 100644 --- a/src/test/compile-fail/borrowck-lend-flow-loop.rs +++ b/src/test/compile-fail/borrowck-lend-flow-loop.rs @@ -28,7 +28,7 @@ fn inc(v: &mut Box) { fn loop_overarching_alias_mut() { // In this instance, the borrow encompasses the entire loop. - let mut v = box 3; + let mut v: Box<_> = box 3; let mut x = &mut v; **x += 1; loop { @@ -39,7 +39,7 @@ fn loop_overarching_alias_mut() { fn block_overarching_alias_mut() { // In this instance, the borrow encompasses the entire closure call. - let mut v = box 3; + let mut v: Box<_> = box 3; let mut x = &mut v; for _ in 0..3 { borrow(&*v); //~ ERROR cannot borrow @@ -50,8 +50,8 @@ fn block_overarching_alias_mut() { fn loop_aliased_mut() { // In this instance, the borrow is carried through the loop. - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let mut _x = &w; loop { borrow_mut(&mut *v); //~ ERROR cannot borrow @@ -62,8 +62,8 @@ fn loop_aliased_mut() { fn while_aliased_mut() { // In this instance, the borrow is carried through the loop. - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let mut _x = &w; while cond() { borrow_mut(&mut *v); //~ ERROR cannot borrow @@ -75,8 +75,8 @@ fn while_aliased_mut() { fn loop_aliased_mut_break() { // In this instance, the borrow is carried through the loop. - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let mut _x = &w; loop { borrow_mut(&mut *v); @@ -89,8 +89,8 @@ fn loop_aliased_mut_break() { fn while_aliased_mut_break() { // In this instance, the borrow is carried through the loop. - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let mut _x = &w; while cond() { borrow_mut(&mut *v); @@ -101,8 +101,8 @@ fn while_aliased_mut_break() { } fn while_aliased_mut_cond(cond: bool, cond2: bool) { - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let mut x = &mut w; while cond { **x += 1; diff --git a/src/test/compile-fail/borrowck-lend-flow.rs b/src/test/compile-fail/borrowck-lend-flow.rs index 177976c15f..6da8f088b3 100644 --- a/src/test/compile-fail/borrowck-lend-flow.rs +++ b/src/test/compile-fail/borrowck-lend-flow.rs @@ -29,7 +29,7 @@ fn inc(v: &mut Box) { fn pre_freeze() { // In this instance, the freeze starts before the mut borrow. - let mut v = box 3; + let mut v: Box<_> = box 3; let _w = &v; borrow_mut(&mut *v); //~ ERROR cannot borrow } @@ -37,7 +37,7 @@ fn pre_freeze() { fn post_freeze() { // In this instance, the const alias starts after the borrow. - let mut v = box 3; + let mut v: Box<_> = box 3; borrow_mut(&mut *v); let _w = &v; } diff --git a/src/test/compile-fail/borrowck-let-suggestion.rs b/src/test/compile-fail/borrowck-let-suggestion.rs index 5729f8c561..d760f3db0c 100644 --- a/src/test/compile-fail/borrowck-let-suggestion.rs +++ b/src/test/compile-fail/borrowck-let-suggestion.rs @@ -17,4 +17,3 @@ fn f() { fn main() { f(); } - diff --git a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs b/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs index 7f676f5166..57b584a895 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs @@ -17,7 +17,7 @@ fn borrow(v: &isize, f: F) where F: FnOnce(&isize) { } fn box_imm() { - let v = box 3; + let v: Box<_> = box 3; let _w = &v; thread::spawn(move|| { println!("v={}", *v); @@ -26,7 +26,7 @@ fn box_imm() { } fn box_imm_explicit() { - let v = box 3; + let v: Box<_> = box 3; let _w = &v; thread::spawn(move|| { println!("v={}", *v); diff --git a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs index a52a4484b2..32d8088549 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs @@ -15,7 +15,7 @@ fn borrow(v: &isize, f: F) where F: FnOnce(&isize) { } fn box_imm() { - let mut v = box 3; + let mut v: Box<_> = box 3; borrow(&*v, |w| { //~ ERROR cannot borrow `v` as mutable v = box 4; diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index b1eb06d16b..cce55b6c94 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -10,7 +10,7 @@ use std::ops::Add; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Point { x: isize, y: isize, diff --git a/src/test/compile-fail/borrowck-match-binding-is-assignment.rs b/src/test/compile-fail/borrowck-match-binding-is-assignment.rs index 38593d3184..c219b7c542 100644 --- a/src/test/compile-fail/borrowck-match-binding-is-assignment.rs +++ b/src/test/compile-fail/borrowck-match-binding-is-assignment.rs @@ -10,6 +10,8 @@ // Test that immutable pattern bindings cannot be reassigned. +#![feature(slice_patterns)] + enum E { Foo(isize) } diff --git a/src/test/compile-fail/borrowck-move-by-capture.rs b/src/test/compile-fail/borrowck-move-by-capture.rs index a1708e7f49..bad5212104 100644 --- a/src/test/compile-fail/borrowck-move-by-capture.rs +++ b/src/test/compile-fail/borrowck-move-by-capture.rs @@ -14,7 +14,7 @@ fn to_fn_mut>(f: F) -> F { f } fn to_fn_once>(f: F) -> F { f } pub fn main() { - let bar = box 3; + let bar: Box<_> = box 3; let _g = to_fn_mut(|| { let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of }); diff --git a/src/test/compile-fail/borrowck-move-error-with-note.rs b/src/test/compile-fail/borrowck-move-error-with-note.rs index 2d82c8be51..e4b9fb2671 100644 --- a/src/test/compile-fail/borrowck-move-error-with-note.rs +++ b/src/test/compile-fail/borrowck-move-error-with-note.rs @@ -17,7 +17,7 @@ enum Foo { } fn blah() { - let f = &Foo::Foo1(box 1u32, box 2u32); + let f = &Foo::Foo1(box 1, box 2); match *f { //~ ERROR cannot move out of Foo::Foo1(num1, //~ NOTE attempting to move value to here num2) => (), //~ NOTE and here diff --git a/src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs b/src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs index 3d8d599970..c02c6a7151 100644 --- a/src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs +++ b/src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs @@ -14,7 +14,7 @@ #![feature(box_syntax)] fn main() { - let a = box box 2; + let a: Box> = box box 2; let b = &a; let z = *a; //~ ERROR: cannot move out of `*a` because it is borrowed diff --git a/src/test/compile-fail/borrowck-move-moved-value-into-closure.rs b/src/test/compile-fail/borrowck-move-moved-value-into-closure.rs index 43bf3f25d1..c46bcbb32b 100644 --- a/src/test/compile-fail/borrowck-move-moved-value-into-closure.rs +++ b/src/test/compile-fail/borrowck-move-moved-value-into-closure.rs @@ -15,7 +15,7 @@ fn call_f isize>(f: F) -> isize { } fn main() { - let t = box 3; + let t: Box<_> = box 3; call_f(move|| { *t + 1 }); call_f(move|| { *t + 1 }); //~ ERROR capture of moved value diff --git a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs b/src/test/compile-fail/borrowck-move-mut-base-ptr.rs index 5bdea6a2bd..2fb89e6364 100644 --- a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs +++ b/src/test/compile-fail/borrowck-move-mut-base-ptr.rs @@ -11,7 +11,7 @@ // Test that attempt to move `&mut` pointer while pointee is borrowed // yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo(t0: &mut isize) { let p: &isize = &*t0; // Freezes `*t0` diff --git a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs index f9d24130e4..d9a2f89a9e 100644 --- a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs +++ b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs @@ -10,6 +10,8 @@ // Test that we do not permit moves from &[] matched by a vec pattern. +#![feature(slice_patterns)] + #[derive(Clone, Debug)] struct Foo { string: String diff --git a/src/test/compile-fail/borrowck-multiple-captures.rs b/src/test/compile-fail/borrowck-multiple-captures.rs index 9db05d7628..042b914ce4 100644 --- a/src/test/compile-fail/borrowck-multiple-captures.rs +++ b/src/test/compile-fail/borrowck-multiple-captures.rs @@ -15,9 +15,9 @@ use std::thread; fn borrow(_: &T) { } fn different_vars_after_borrows() { - let x1 = box 1; + let x1: Box<_> = box 1; let p1 = &x1; - let x2 = box 2; + let x2: Box<_> = box 2; let p2 = &x2; thread::spawn(move|| { drop(x1); //~ ERROR cannot move `x1` into closure because it is borrowed @@ -28,9 +28,9 @@ fn different_vars_after_borrows() { } fn different_vars_after_moves() { - let x1 = box 1; + let x1: Box<_> = box 1; drop(x1); - let x2 = box 2; + let x2: Box<_> = box 2; drop(x2); thread::spawn(move|| { drop(x1); //~ ERROR capture of moved value: `x1` @@ -39,7 +39,7 @@ fn different_vars_after_moves() { } fn same_var_after_borrow() { - let x = box 1; + let x: Box<_> = box 1; let p = &x; thread::spawn(move|| { drop(x); //~ ERROR cannot move `x` into closure because it is borrowed @@ -49,7 +49,7 @@ fn same_var_after_borrow() { } fn same_var_after_move() { - let x = box 1; + let x: Box<_> = box 1; drop(x); thread::spawn(move|| { drop(x); //~ ERROR capture of moved value: `x` @@ -63,4 +63,3 @@ fn main() { same_var_after_borrow(); same_var_after_move(); } - diff --git a/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs b/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs index 71dc61abb6..bdeb7ea69b 100644 --- a/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs +++ b/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs @@ -11,7 +11,7 @@ // Test that attempt to mutably borrow `&mut` pointer while pointee is // borrowed yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md fn foo<'a>(mut t0: &'a mut isize, mut t1: &'a mut isize) { diff --git a/src/test/compile-fail/borrowck-mutate-in-guard.rs b/src/test/compile-fail/borrowck-mutate-in-guard.rs index 44353ab5d9..e35edca639 100644 --- a/src/test/compile-fail/borrowck-mutate-in-guard.rs +++ b/src/test/compile-fail/borrowck-mutate-in-guard.rs @@ -30,4 +30,3 @@ fn foo() -> isize { fn main() { foo(); } - diff --git a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs b/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs index 6985d203fb..8cb7423f3c 100644 --- a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs +++ b/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs @@ -19,7 +19,7 @@ enum cycle { empty } fn main() { - let mut x = box cycle::node(node_ {a: box cycle::empty}); + let mut x: Box<_> = box cycle::node(node_ {a: box cycle::empty}); // Create a cycle! match *x { cycle::node(ref mut y) => { diff --git a/src/test/compile-fail/borrowck-object-lifetime.rs b/src/test/compile-fail/borrowck-object-lifetime.rs index bbb58e2119..021b3f38e0 100644 --- a/src/test/compile-fail/borrowck-object-lifetime.rs +++ b/src/test/compile-fail/borrowck-object-lifetime.rs @@ -37,4 +37,3 @@ fn imm_owned_receiver(mut x: Box) { } fn main() {} - diff --git a/src/test/compile-fail/borrowck-object-mutability.rs b/src/test/compile-fail/borrowck-object-mutability.rs index 9b5087bd7e..1bdc32b097 100644 --- a/src/test/compile-fail/borrowck-object-mutability.rs +++ b/src/test/compile-fail/borrowck-object-mutability.rs @@ -35,4 +35,3 @@ fn mut_owned_receiver(mut x: Box) { } fn main() {} - diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs index 04d73cc36f..93c37524bf 100644 --- a/src/test/compile-fail/borrowck-overloaded-call.rs +++ b/src/test/compile-fail/borrowck-overloaded-call.rs @@ -18,26 +18,36 @@ struct SFn { } impl Fn<(isize,)> for SFn { - type Output = isize; - extern "rust-call" fn call(&self, (z,): (isize,)) -> isize { self.x * self.y * z } } +impl FnMut<(isize,)> for SFn { + extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) } +} + +impl FnOnce<(isize,)> for SFn { + type Output = isize; + extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) } +} + struct SFnMut { x: isize, y: isize, } impl FnMut<(isize,)> for SFnMut { - type Output = isize; - extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { self.x * self.y * z } } +impl FnOnce<(isize,)> for SFnMut { + type Output = isize; + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } +} + struct SFnOnce { x: String, } @@ -77,4 +87,3 @@ fn h() { } fn main() {} - diff --git a/src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs b/src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs index 4188cf0014..bee56c9bf3 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs @@ -19,7 +19,7 @@ struct MyVec { x: T } impl Index for MyVec { type Output = T; - fn index(&self, _: &usize) -> &T { + fn index(&self, _: usize) -> &T { &self.x } } @@ -44,4 +44,3 @@ fn main() { } fn read(_: usize) { } - diff --git a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs b/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs index 99f396ef81..b726c46d5d 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs @@ -18,10 +18,10 @@ struct Foo { y: isize, } -impl Index for Foo { +impl<'a> Index<&'a String> for Foo { type Output = isize; - fn index<'a>(&'a self, z: &String) -> &'a isize { + fn index(&self, z: &String) -> &isize { if *z == "x" { &self.x } else { @@ -30,8 +30,8 @@ impl Index for Foo { } } -impl IndexMut for Foo { - fn index_mut<'a>(&'a mut self, z: &String) -> &'a mut isize { +impl<'a> IndexMut<&'a String> for Foo { + fn index_mut(&mut self, z: &String) -> &mut isize { if *z == "x" { &mut self.x } else { @@ -41,13 +41,13 @@ impl IndexMut for Foo { } fn test1(mut f: Box, s: String) { - let _p = &mut f[s]; - let _q = &f[s]; //~ ERROR cannot borrow + let _p = &mut f[&s]; + let _q = &f[&s]; //~ ERROR cannot borrow } fn test2(mut f: Box, s: String) { - let _p = &mut f[s]; - let _q = &mut f[s]; //~ ERROR cannot borrow + let _p = &mut f[&s]; + let _q = &mut f[&s]; //~ ERROR cannot borrow } struct Bar { @@ -55,37 +55,37 @@ struct Bar { } fn test3(mut f: Box, s: String) { - let _p = &mut f.foo[s]; - let _q = &mut f.foo[s]; //~ ERROR cannot borrow + let _p = &mut f.foo[&s]; + let _q = &mut f.foo[&s]; //~ ERROR cannot borrow } fn test4(mut f: Box, s: String) { - let _p = &f.foo[s]; - let _q = &f.foo[s]; + let _p = &f.foo[&s]; + let _q = &f.foo[&s]; } fn test5(mut f: Box, s: String) { - let _p = &f.foo[s]; - let _q = &mut f.foo[s]; //~ ERROR cannot borrow + let _p = &f.foo[&s]; + let _q = &mut f.foo[&s]; //~ ERROR cannot borrow } fn test6(mut f: Box, g: Foo, s: String) { - let _p = &f.foo[s]; + let _p = &f.foo[&s]; f.foo = g; //~ ERROR cannot assign } fn test7(mut f: Box, g: Bar, s: String) { - let _p = &f.foo[s]; + let _p = &f.foo[&s]; *f = g; //~ ERROR cannot assign } fn test8(mut f: Box, g: Foo, s: String) { - let _p = &mut f.foo[s]; + let _p = &mut f.foo[&s]; f.foo = g; //~ ERROR cannot assign } fn test9(mut f: Box, g: Bar, s: String) { - let _p = &mut f.foo[s]; + let _p = &mut f.foo[&s]; *f = g; //~ ERROR cannot assign } diff --git a/src/test/compile-fail/borrowck-overloaded-index-2.rs b/src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs similarity index 88% rename from src/test/compile-fail/borrowck-overloaded-index-2.rs rename to src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs index e9d8544a06..1b62d9c326 100644 --- a/src/test/compile-fail/borrowck-overloaded-index-2.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs @@ -19,13 +19,13 @@ struct MyVec { impl Index for MyVec { type Output = T; - fn index(&self, &i: &usize) -> &T { + fn index(&self, i: usize) -> &T { &self.data[i] } } fn main() { - let v = MyVec { data: vec!(box 1, box 2, box 3) }; + let v = MyVec::> { data: vec!(box 1, box 2, box 3) }; let good = &v[0]; // Shouldn't fail here let bad = v[0]; //~^ ERROR cannot move out of indexed content diff --git a/src/test/compile-fail/borrowck-overloaded-index-move-index.rs b/src/test/compile-fail/borrowck-overloaded-index-move-index.rs new file mode 100644 index 0000000000..d8615d1905 --- /dev/null +++ b/src/test/compile-fail/borrowck-overloaded-index-move-index.rs @@ -0,0 +1,74 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::{Index, IndexMut}; + +struct Foo { + x: isize, + y: isize, +} + +impl Index for Foo { + type Output = isize; + + fn index(&self, z: String) -> &isize { + if z == "x" { + &self.x + } else { + &self.y + } + } +} + +impl IndexMut for Foo { + fn index_mut(&mut self, z: String) -> &mut isize { + if z == "x" { + &mut self.x + } else { + &mut self.y + } + } +} + +struct Bar { + x: isize, +} + +impl Index for Bar { + type Output = isize; + + fn index<'a>(&'a self, z: isize) -> &'a isize { + &self.x + } +} + +fn main() { + let mut f = Foo { + x: 1, + y: 2, + }; + let mut s = "hello".to_string(); + let rs = &mut s; + + println!("{}", f[s]); + //~^ ERROR cannot move out of `s` because it is borrowed + + f[s] = 10; + //~^ ERROR cannot move out of `s` because it is borrowed + //~| ERROR use of moved value: `s` + + let s = Bar { + x: 1, + }; + let i = 2; + let _j = &i; + println!("{}", s[i]); // no error, i is copy + println!("{}", s[i]); +} diff --git a/src/test/compile-fail/borrowck-overloaded-index.rs b/src/test/compile-fail/borrowck-overloaded-index-ref-index.rs similarity index 82% rename from src/test/compile-fail/borrowck-overloaded-index.rs rename to src/test/compile-fail/borrowck-overloaded-index-ref-index.rs index 2d752abe7e..4c50caf497 100644 --- a/src/test/compile-fail/borrowck-overloaded-index.rs +++ b/src/test/compile-fail/borrowck-overloaded-index-ref-index.rs @@ -15,10 +15,10 @@ struct Foo { y: isize, } -impl Index for Foo { +impl<'a> Index<&'a String> for Foo { type Output = isize; - fn index<'a>(&'a self, z: &String) -> &'a isize { + fn index(&self, z: &String) -> &isize { if *z == "x" { &self.x } else { @@ -27,8 +27,8 @@ impl Index for Foo { } } -impl IndexMut for Foo { - fn index_mut<'a>(&'a mut self, z: &String) -> &'a mut isize { +impl<'a> IndexMut<&'a String> for Foo { + fn index_mut(&mut self, z: &String) -> &mut isize { if *z == "x" { &mut self.x } else { @@ -44,7 +44,7 @@ struct Bar { impl Index for Bar { type Output = isize; - fn index<'a>(&'a self, z: &isize) -> &'a isize { + fn index<'a>(&'a self, z: isize) -> &'a isize { &self.x } } @@ -56,9 +56,9 @@ fn main() { }; let mut s = "hello".to_string(); let rs = &mut s; - println!("{}", f[s]); + println!("{}", f[&s]); //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable - f[s] = 10; + f[&s] = 10; //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable let s = Bar { x: 1, diff --git a/src/test/compile-fail/borrowck-partial-reinit-2.rs b/src/test/compile-fail/borrowck-partial-reinit-2.rs index 0926ba6e43..c9cdeff9c7 100644 --- a/src/test/compile-fail/borrowck-partial-reinit-2.rs +++ b/src/test/compile-fail/borrowck-partial-reinit-2.rs @@ -31,4 +31,3 @@ fn main() { stuff(); println!("Hello, world!") } - diff --git a/src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs b/src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs index 2163737072..61bf2c11a1 100644 --- a/src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs +++ b/src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs @@ -11,7 +11,7 @@ #![allow(dead_code)] fn main() { // Original borrow ends at end of function - let mut x = 1_usize; + let mut x = 1; let y = &mut x; let z = &x; //~ ERROR cannot borrow } @@ -21,7 +21,7 @@ fn foo() { match true { true => { // Original borrow ends at end of match arm - let mut x = 1_usize; + let mut x = 1; let y = &x; let z = &mut x; //~ ERROR cannot borrow } @@ -33,7 +33,7 @@ fn foo() { fn bar() { // Original borrow ends at end of closure || { - let mut x = 1_usize; + let mut x = 1; let y = &mut x; let z = &mut x; //~ ERROR cannot borrow }; diff --git a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs b/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs index 0102a90918..552fcec8e2 100644 --- a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs +++ b/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs @@ -11,7 +11,7 @@ // Test that attempt to swap `&mut` pointer while pointee is borrowed // yields an error. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md use std::mem::swap; diff --git a/src/test/compile-fail/borrowck-unboxed-closures.rs b/src/test/compile-fail/borrowck-unboxed-closures.rs index 8e7e2e3e77..3eca850e49 100644 --- a/src/test/compile-fail/borrowck-unboxed-closures.rs +++ b/src/test/compile-fail/borrowck-unboxed-closures.rs @@ -26,4 +26,3 @@ fn c isize>(f: F) { } fn main() {} - diff --git a/src/test/compile-fail/borrowck-uniq-via-lend.rs b/src/test/compile-fail/borrowck-uniq-via-lend.rs index 49a1b782a3..f36dc0ca43 100644 --- a/src/test/compile-fail/borrowck-uniq-via-lend.rs +++ b/src/test/compile-fail/borrowck-uniq-via-lend.rs @@ -13,7 +13,7 @@ fn borrow(_v: &isize) {} fn local() { - let mut v = box 3; + let mut v: Box<_> = box 3; borrow(&*v); } @@ -32,27 +32,27 @@ fn local_recs() { } fn aliased_imm() { - let mut v = box 3; + let mut v: Box<_> = box 3; let _w = &v; borrow(&*v); } fn aliased_mut() { - let mut v = box 3; + let mut v: Box<_> = box 3; let _w = &mut v; borrow(&*v); //~ ERROR cannot borrow `*v` } fn aliased_other() { - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let _x = &mut w; borrow(&*v); } fn aliased_other_reassign() { - let mut v = box 3; - let mut w = box 4; + let mut v: Box<_> = box 3; + let mut w: Box<_> = box 4; let mut _x = &mut w; _x = &mut v; borrow(&*v); //~ ERROR cannot borrow `*v` diff --git a/src/test/compile-fail/borrowck-use-mut-borrow.rs b/src/test/compile-fail/borrowck-use-mut-borrow.rs index 52f89da10b..c11e58651a 100644 --- a/src/test/compile-fail/borrowck-use-mut-borrow.rs +++ b/src/test/compile-fail/borrowck-use-mut-borrow.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -#[derive(Copy)] +#[derive(Copy, Clone)] struct A { a: isize, b: isize } struct B { a: isize, b: Box } @@ -94,4 +94,3 @@ fn main() { field_deref_after_var_borrow(); field_deref_after_field_borrow(); } - diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs index 2d6a4b7d2c..98052ad31a 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] fn a<'a>() -> &'a [isize] { let vec = vec!(1, 2, 3, 4); diff --git a/src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs b/src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs index c1906758a5..db635893c8 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn a() { let mut v = vec!(1, 2, 3); let vb: &mut [isize] = &mut v; diff --git a/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs index 242a384400..97dcaeb0bf 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { let mut a = [1, 2, 3, 4]; let t = match a { diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs index b471439f75..a69ce0cb36 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs @@ -11,6 +11,7 @@ #![feature(advanced_slice_patterns)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(slice_patterns)] fn a() { let mut vec = [box 1, box 2, box 3]; diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs index df0fee437b..82b3490d7d 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn a<'a>() -> &'a isize { let vec = vec!(1, 2, 3, 4); let vec: &[isize] = &vec; //~ ERROR `vec` does not live long enough diff --git a/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs b/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs index e59bd62d17..5ddde6460b 100644 --- a/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs +++ b/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs @@ -10,6 +10,8 @@ #![feature(unboxed_closures)] +use std::io::Read; + fn to_fn_once>(f: F) -> F { f } fn main() { @@ -17,7 +19,7 @@ fn main() { to_fn_once(move|| { x = 2; }); //~^ ERROR: cannot assign to immutable captured outer variable - let s = std::old_io::stdin(); - to_fn_once(move|| { s.read_to_end(); }); + let s = std::io::stdin(); + to_fn_once(move|| { s.read_to_end(&mut Vec::new()); }); //~^ ERROR: cannot borrow immutable captured outer variable } diff --git a/src/test/compile-fail/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/compile-fail/cfg-attr-unknown-attribute-macro-expansion.rs new file mode 100644 index 0000000000..afcb896b43 --- /dev/null +++ b/src/test/compile-fail/cfg-attr-unknown-attribute-macro-expansion.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! foo { + () => { + #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown + fn foo() {} + } +} + +foo!(); + +fn main() {} diff --git a/src/test/compile-fail/class-method-missing.rs b/src/test/compile-fail/class-method-missing.rs index ada45e8c1f..46b100a4d3 100644 --- a/src/test/compile-fail/class-method-missing.rs +++ b/src/test/compile-fail/class-method-missing.rs @@ -27,5 +27,5 @@ fn cat(in_x : usize) -> cat { } fn main() { - let nyan = cat(0_usize); + let nyan = cat(0); } diff --git a/src/test/compile-fail/class-missing-self.rs b/src/test/compile-fail/class-missing-self.rs index f25b2e6538..ab76af1cbe 100644 --- a/src/test/compile-fail/class-missing-self.rs +++ b/src/test/compile-fail/class-missing-self.rs @@ -16,7 +16,7 @@ impl cat { fn sleep(&self) { loop{} } fn meow(&self) { println!("Meow"); - meows += 1_usize; //~ ERROR unresolved name + meows += 1; //~ ERROR unresolved name sleep(); //~ ERROR unresolved name } diff --git a/src/test/compile-fail/closure-reform-bad.rs b/src/test/compile-fail/closure-reform-bad.rs index d2295eba6d..490734d463 100644 --- a/src/test/compile-fail/closure-reform-bad.rs +++ b/src/test/compile-fail/closure-reform-bad.rs @@ -20,4 +20,3 @@ fn main() { let f = |s: &str| println!("{}{}", s, string); call_bare(f) //~ ERROR mismatched types } - diff --git a/src/test/compile-fail/coerce-unsafe-to-closure.rs b/src/test/compile-fail/coerce-unsafe-to-closure.rs index fe7635f065..27b4a04054 100644 --- a/src/test/compile-fail/coerce-unsafe-to-closure.rs +++ b/src/test/compile-fail/coerce-unsafe-to-closure.rs @@ -10,5 +10,6 @@ fn main() { let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); - //~^ ERROR: is not implemented for the type + //~^ ERROR E0277 + //~| ERROR E0277 } diff --git a/src/test/compile-fail/coercion-slice.rs b/src/test/compile-fail/coercion-slice.rs index aac180f9ad..bb4d1693af 100644 --- a/src/test/compile-fail/coercion-slice.rs +++ b/src/test/compile-fail/coercion-slice.rs @@ -11,10 +11,10 @@ // Tests that we forbid coercion from `[T; n]` to `&[T]` fn main() { - let _: &[i32] = [0i32]; + let _: &[i32] = [0]; //~^ ERROR mismatched types //~| expected `&[i32]` - //~| found `[i32; 1]` + //~| found `[_; 1]` //~| expected &-ptr //~| found array of 1 elements } diff --git a/src/test/compile-fail/coherence-all-remote.rs b/src/test/compile-fail/coherence-all-remote.rs index 1e3b7f6dbd..7a5340041c 100644 --- a/src/test/compile-fail/coherence-all-remote.rs +++ b/src/test/compile-fail/coherence-all-remote.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::Remote1; impl Remote1 for isize { } diff --git a/src/test/compile-fail/coherence-bigint-param.rs b/src/test/compile-fail/coherence-bigint-param.rs index b7ca499be7..32c5b66938 100644 --- a/src/test/compile-fail/coherence-bigint-param.rs +++ b/src/test/compile-fail/coherence-bigint-param.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::Remote1; pub struct BigInt; diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs index d4decb7134..98a9c713e8 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; use std::marker::MarkerTrait; diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs index b1ee1762b6..57d25a3bf5 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; // Test that two blanket impls conflict (at least without negative diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs index 1f6bb08871..b3ef79c6cc 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs @@ -13,7 +13,7 @@ extern crate go_trait; use go_trait::{Go,GoMut}; -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; struct MyThingy; diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs index c3563792ce..7b60a5ecbd 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; // Test that a blank impl for all T conflicts with an impl for some diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs index 980e4256d2..d218b64af0 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; // Test that a blank impl for all T conflicts with an impl for some diff --git a/src/test/compile-fail/coherence-cow-1.rs b/src/test/compile-fail/coherence-cow-1.rs new file mode 100644 index 0000000000..530bbf57d9 --- /dev/null +++ b/src/test/compile-fail/coherence-cow-1.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +// Test that the `Pair` type reports an error if it contains type +// parameters, even when they are covered by local types. This test +// was originally intended to test the opposite, but the rules changed +// with RFC 1023 and this became illegal. + +extern crate coherence_lib as lib; +use lib::{Remote,Pair}; + +pub struct Cover(T); + +impl Remote for Pair> { } +//~^ ERROR E0210 + +fn main() { } diff --git a/src/test/compile-fail/coherence-cow-2.rs b/src/test/compile-fail/coherence-cow-2.rs new file mode 100644 index 0000000000..52abceab98 --- /dev/null +++ b/src/test/compile-fail/coherence-cow-2.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:coherence_lib.rs + +// Test that the `Pair` type reports an error if it contains type +// parameters, even when they are covered by local types. This test +// was originally intended to test the opposite, but the rules changed +// with RFC 1023 and this became illegal. + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::{Remote,Pair}; + +pub struct Cover(T); + +impl Remote for Pair,T> { } //~ ERROR E0210 + +fn main() { } diff --git a/src/test/compile-fail/coherence-cow-no-cover.rs b/src/test/compile-fail/coherence-cow-no-cover.rs index 1bec97de53..cd32e797ae 100644 --- a/src/test/compile-fail/coherence-cow-no-cover.rs +++ b/src/test/compile-fail/coherence-cow-no-cover.rs @@ -8,16 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -// Test that it's not ok for U to appear uncovered +// Test that it's not ok for T to appear uncovered -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::{Remote,Pair}; pub struct Cover(T); impl Remote for Pair,U> { } -//~^ ERROR type parameter `U` must be used as the type parameter for some local type +//~^ ERROR type parameter `T` must be used as the type parameter for some local type fn main() { } diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs new file mode 100644 index 0000000000..a5b3173073 --- /dev/null +++ b/src/test/compile-fail/coherence-default-trait-impl.rs @@ -0,0 +1,34 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} + +impl MyTrait for .. {} + +impl MyTrait for .. {} +//~^ ERROR conflicting implementations for trait `MyTrait` + +trait MySafeTrait: MarkerTrait {} + +unsafe impl MySafeTrait for .. {} +//~^ ERROR implementing the trait `MySafeTrait` is not unsafe + +unsafe trait MyUnsafeTrait: MarkerTrait {} + +impl MyUnsafeTrait for .. {} +//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration + +fn main() {} diff --git a/src/test/compile-fail/coherence-impls-copy.rs b/src/test/compile-fail/coherence-impls-copy.rs new file mode 100644 index 0000000000..1be606c354 --- /dev/null +++ b/src/test/compile-fail/coherence-impls-copy.rs @@ -0,0 +1,53 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +use std::marker::Copy; + +enum TestE { + A +} + +struct MyType; + +struct NotSync; +impl !Sync for NotSync {} + +impl Copy for TestE {} +impl Clone for TestE { fn clone(&self) -> Self { *self } } + +impl Copy for MyType {} + +impl Copy for &'static mut MyType {} +//~^ ERROR E0206 +//~| ERROR E0277 +//~| ERROR E0277 +impl Clone for MyType { fn clone(&self) -> Self { *self } } + +impl Copy for (MyType, MyType) {} +//~^ ERROR E0206 +//~| ERROR E0117 + +impl Copy for &'static NotSync {} +//~^ ERROR E0206 + +impl Copy for [MyType] {} +//~^ ERROR E0206 +//~| ERROR E0117 +//~| ERROR E0277 +//~| ERROR E0277 + +impl Copy for &'static [NotSync] {} +//~^ ERROR E0206 +//~| ERROR E0117 + +fn main() { +} diff --git a/src/test/compile-fail/coherence-impls-builtin.rs b/src/test/compile-fail/coherence-impls-send.rs similarity index 69% rename from src/test/compile-fail/coherence-impls-builtin.rs rename to src/test/compile-fail/coherence-impls-send.rs index 38730d241f..f130a93535 100644 --- a/src/test/compile-fail/coherence-impls-builtin.rs +++ b/src/test/compile-fail/coherence-impls-send.rs @@ -10,7 +10,7 @@ #![feature(optin_builtin_traits)] -use std::marker::Send; +use std::marker::Copy; enum TestE { A @@ -24,19 +24,17 @@ impl !Sync for NotSync {} unsafe impl Send for TestE {} unsafe impl Send for MyType {} unsafe impl Send for (MyType, MyType) {} -//~^ ERROR builtin traits can only be implemented on structs or enums +//~^ ERROR E0117 unsafe impl Send for &'static NotSync {} -//~^ ERROR builtin traits can only be implemented on structs or enums +//~^ ERROR E0321 unsafe impl Send for [MyType] {} -//~^ ERROR builtin traits can only be implemented on structs or enums +//~^ ERROR E0117 unsafe impl Send for &'static [NotSync] {} -//~^ ERROR builtin traits can only be implemented on structs or enums - -fn is_send() {} +//~^ ERROR E0117 +//~| ERROR E0119 fn main() { - is_send::<(MyType, TestE)>(); } diff --git a/src/test/compile-fail/coherence-impls-sized.rs b/src/test/compile-fail/coherence-impls-sized.rs new file mode 100644 index 0000000000..2ac4bb0492 --- /dev/null +++ b/src/test/compile-fail/coherence-impls-sized.rs @@ -0,0 +1,38 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +use std::marker::Copy; + +enum TestE { + A +} + +struct MyType; + +struct NotSync; +impl !Sync for NotSync {} + +impl Sized for TestE {} //~ ERROR E0322 + +impl Sized for MyType {} //~ ERROR E0322 + +impl Sized for (MyType, MyType) {} //~ ERROR E0117 + +impl Sized for &'static NotSync {} //~ ERROR E0322 + +impl Sized for [MyType] {} //~ ERROR E0117 +//~^ ERROR E0277 + +impl Sized for &'static [NotSync] {} //~ ERROR E0117 + +fn main() { +} diff --git a/src/test/compile-fail/coherence-lone-type-parameter.rs b/src/test/compile-fail/coherence-lone-type-parameter.rs index 9f7481f12f..e78f392b38 100644 --- a/src/test/compile-fail/coherence-lone-type-parameter.rs +++ b/src/test/compile-fail/coherence-lone-type-parameter.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::Remote; impl Remote for T { } diff --git a/src/test/compile-fail/coherence-orphan.rs b/src/test/compile-fail/coherence-orphan.rs index d7cd68e73c..2243a0507f 100644 --- a/src/test/compile-fail/coherence-orphan.rs +++ b/src/test/compile-fail/coherence-orphan.rs @@ -9,23 +9,25 @@ // except according to those terms. // ignore-tidy-linelength -// aux-build:coherence-orphan-lib.rs +// aux-build:coherence_orphan_lib.rs #![feature(optin_builtin_traits)] -extern crate "coherence-orphan-lib" as lib; +extern crate coherence_orphan_lib as lib; use lib::TheTrait; struct TheType; -impl TheTrait for isize { } //~ ERROR E0117 +impl TheTrait for isize { } +//~^ ERROR E0117 impl TheTrait for isize { } impl TheTrait for TheType { } -impl !Send for Vec { } //~ ERROR E0117 -//~^ ERROR conflicting +impl !Send for Vec { } +//~^ ERROR E0117 +//~| ERROR E0119 fn main() { } diff --git a/src/test/compile-fail/coherence-overlap-issue-23516.rs b/src/test/compile-fail/coherence-overlap-issue-23516.rs new file mode 100644 index 0000000000..d7f060a3bf --- /dev/null +++ b/src/test/compile-fail/coherence-overlap-issue-23516.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that we consider `Box: !Sugar` to be ambiguous, even +// though we see no impl of `Sugar` for `Box`. Therefore, an overlap +// error is reported for the following pair of impls (#23516). + +pub trait Sugar { fn dummy(&self) { } } +pub trait Sweet { fn dummy(&self) { } } +impl Sweet for T { } //~ ERROR E0119 +impl Sweet for Box { } +fn main() { } diff --git a/src/test/compile-fail/coherence-overlapping-pairs.rs b/src/test/compile-fail/coherence-overlapping-pairs.rs index 9878bdec2c..ba9dc53e86 100644 --- a/src/test/compile-fail/coherence-overlapping-pairs.rs +++ b/src/test/compile-fail/coherence-overlapping-pairs.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::Remote; struct Foo; diff --git a/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs b/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs index 2bdcc346f7..f55efef14f 100644 --- a/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs +++ b/src/test/compile-fail/coherence-pair-covered-uncovered-1.rs @@ -11,9 +11,9 @@ // Test that the same coverage rules apply even if the local type appears in the // list of type parameters, not the self type. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::{Remote1, Pair}; pub struct Local(T); diff --git a/src/test/compile-fail/coherence-pair-covered-uncovered.rs b/src/test/compile-fail/coherence-pair-covered-uncovered.rs index 881494f009..0642dff4b2 100644 --- a/src/test/compile-fail/coherence-pair-covered-uncovered.rs +++ b/src/test/compile-fail/coherence-pair-covered-uncovered.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +extern crate coherence_lib as lib; use lib::{Remote, Pair}; struct Local(T); diff --git a/src/test/compile-fail/coherence-tuple-conflict.rs b/src/test/compile-fail/coherence-tuple-conflict.rs index 9673fb6a21..87b007fdd6 100644 --- a/src/test/compile-fail/coherence-tuple-conflict.rs +++ b/src/test/compile-fail/coherence-tuple-conflict.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; use std::default::Default; // Test that a blank impl for all T conflicts with an impl for some diff --git a/src/test/compile-fail/coherence-vec-local-2.rs b/src/test/compile-fail/coherence-vec-local-2.rs new file mode 100644 index 0000000000..5f0b56af2c --- /dev/null +++ b/src/test/compile-fail/coherence-vec-local-2.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that a local, generic type appearing within a +// *non-fundamental* remote type like `Vec` is not considered local. + +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote; + +struct Local(T); + +impl Remote for Vec> { } //~ ERROR E0210 + +fn main() { } diff --git a/src/test/compile-fail/coherence-vec-local.rs b/src/test/compile-fail/coherence-vec-local.rs new file mode 100644 index 0000000000..c354caac2b --- /dev/null +++ b/src/test/compile-fail/coherence-vec-local.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that a local type (with no type parameters) appearing within a +// *non-fundamental* remote type like `Vec` is not considered local. + +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote; + +struct Local; + +impl Remote for Vec { } //~ ERROR E0117 + +fn main() { } diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs new file mode 100644 index 0000000000..f13175ce8e --- /dev/null +++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +use std::marker::MarkerTrait; + +struct MyType { x: i32 } + +trait MyTrait : MarkerTrait { } +impl MyTrait for T { } + +// `MyFundamentalStruct` is declared fundamental, so we can test that +// +// MyFundamentalStruct: !MyTrait +// +// Huzzah. +impl MyTrait for lib::MyFundamentalStruct { } + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs new file mode 100644 index 0000000000..ae3d242af7 --- /dev/null +++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +use std::marker::MarkerTrait; + +struct MyType { x: i32 } + +trait MyTrait : MarkerTrait { } +impl MyTrait for T { } + +// `MyFundamentalStruct` is declared fundamental, so we can test that +// +// MyFundamentalStruct<&MyTrait>: !MyTrait +// +// Huzzah. +impl<'a> MyTrait for lib::MyFundamentalStruct<&'a MyType> { } + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs new file mode 100644 index 0000000000..c4e95e7723 --- /dev/null +++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] + +extern crate coherence_copy_like_lib as lib; + +use std::marker::MarkerTrait; + +struct MyType { x: i32 } + +trait MyTrait : MarkerTrait { } + +impl MyTrait for T { } //~ ERROR E0119 + +// Tuples are not fundamental. +impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/coherence_copy_like_err_struct.rs b/src/test/compile-fail/coherence_copy_like_err_struct.rs new file mode 100644 index 0000000000..f768a475ee --- /dev/null +++ b/src/test/compile-fail/coherence_copy_like_err_struct.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:coherence_copy_like_lib.rs + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +extern crate coherence_copy_like_lib as lib; + +use std::marker::MarkerTrait; + +struct MyType { x: i32 } + +trait MyTrait : MarkerTrait { } +impl MyTrait for T { } //~ ERROR E0119 + +// `MyStruct` is not declared fundamental, therefore this would +// require that +// +// MyStruct: !MyTrait +// +// which we cannot approve. +impl MyTrait for lib::MyStruct { } + +fn main() { } diff --git a/src/test/compile-fail/coherence_copy_like_err_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_tuple.rs new file mode 100644 index 0000000000..0c78fffd2d --- /dev/null +++ b/src/test/compile-fail/coherence_copy_like_err_tuple.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +use std::marker::MarkerTrait; + +struct MyType { x: i32 } + +trait MyTrait : MarkerTrait { } +impl MyTrait for T { } //~ ERROR E0119 + +// Tuples are not fundamental, therefore this would require that +// +// (MyType,): !MyTrait +// +// which we cannot approve. +impl MyTrait for (MyType,) { } + +fn main() { } diff --git a/src/test/compile-fail/coherence_local.rs b/src/test/compile-fail/coherence_local.rs new file mode 100644 index 0000000000..551577b6b4 --- /dev/null +++ b/src/test/compile-fail/coherence_local.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// These are all legal because they are all fundamental types: + +impl lib::MyCopy for MyType { } +impl<'a> lib::MyCopy for &'a MyType { } +impl<'a> lib::MyCopy for &'a Box { } +impl lib::MyCopy for Box { } +impl lib::MyCopy for lib::MyFundamentalStruct { } +impl lib::MyCopy for lib::MyFundamentalStruct> { } + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/coherence_local_err_struct.rs b/src/test/compile-fail/coherence_local_err_struct.rs new file mode 100644 index 0000000000..01f4c1cd8a --- /dev/null +++ b/src/test/compile-fail/coherence_local_err_struct.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// These are all legal because they are all fundamental types: + +// MyStruct is not fundamental. +impl lib::MyCopy for lib::MyStruct { } //~ ERROR E0117 + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/coherence_local_err_tuple.rs b/src/test/compile-fail/coherence_local_err_tuple.rs new file mode 100644 index 0000000000..590f68cee5 --- /dev/null +++ b/src/test/compile-fail/coherence_local_err_tuple.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// These are all legal because they are all fundamental types: + +// Tuples are not fundamental, so this is not a local impl. +impl lib::MyCopy for (MyType,) { } //~ ERROR E0117 + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/coherence_local_ref.rs b/src/test/compile-fail/coherence_local_ref.rs new file mode 100644 index 0000000000..f6e1aab597 --- /dev/null +++ b/src/test/compile-fail/coherence_local_ref.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// naturally, legal +impl lib::MyCopy for MyType { } + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/const-array-oob.rs b/src/test/compile-fail/const-array-oob.rs new file mode 100644 index 0000000000..84d3529260 --- /dev/null +++ b/src/test/compile-fail/const-array-oob.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const FOO: [u32; 3] = [1, 2, 3]; +const BAR: u32 = FOO[5]; //~ ERROR const index-expr is out of bounds + +fn main() { + let _ = BAR; +} diff --git a/src/test/compile-fail/const-block-non-item-statement.rs b/src/test/compile-fail/const-block-non-item-statement.rs index fa63b16afa..5ccfb1ddec 100644 --- a/src/test/compile-fail/const-block-non-item-statement.rs +++ b/src/test/compile-fail/const-block-non-item-statement.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const A: usize = { 1_usize; 2 }; +const A: usize = { 1; 2 }; //~^ ERROR: blocks in constants are limited to items and tail expressions const B: usize = { { } 2 }; @@ -19,7 +19,7 @@ macro_rules! foo { } const C: usize = { foo!(); 2 }; -const D: usize = { let x = 4_usize; 2 }; +const D: usize = { let x = 4; 2 }; //~^ ERROR: blocks in constants are limited to items and tail expressions pub fn main() { diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs new file mode 100644 index 0000000000..be04bc9bd3 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-2.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in refutable patterns goes through +// different compiler control-flow paths. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const NEG_128: i8 = -128; +const NEG_NEG_128: i8 = -NEG_128; +//~^ ERROR constant evaluation error: attempted to negate with overflow +//~| ERROR attempted to negate with overflow + +fn main() { + match -128i8 { + NEG_NEG_128 => println!("A"), + _ => println!("B"), + } +} diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs new file mode 100644 index 0000000000..c2bc5b2648 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-3.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. + +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup; therefore resorting to +// error-pattern for now. + +// error-pattern: expected constant integer for repeat count, but attempted to add with overflow + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1) as usize]; + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-3b.rs b/src/test/compile-fail/const-eval-overflow-3b.rs new file mode 100644 index 0000000000..719b21000f --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-3b.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. +// +// This is a variation of another such test, but in this case the +// types for the left- and right-hand sides of the addition do not +// match (as well as overflow). + +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup; therefore resorting to +// error-pattern for now. + +// error-pattern: mismatched types + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1u8) as usize]; + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-4.rs b/src/test/compile-fail/const-eval-overflow-4.rs new file mode 100644 index 0000000000..f1f125adaa --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-4.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-test this should fail to compile (#23833) + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1i8) as usize] + //~^ ERROR error evaluating count: attempted to add with overflow + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs new file mode 100644 index 0000000000..6322b56a82 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1u8) as usize] + //~^ ERROR mismatched types + //~| the trait `core::ops::Add` is not implemented for the type `i8` + //~| the trait `core::ops::Add` is not implemented for the type `i8` + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} + diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs new file mode 100644 index 0000000000..19b5f9b094 --- /dev/null +++ b/src/test/compile-fail/const-eval-overflow.rs @@ -0,0 +1,132 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(negate_unsigned)] + +#![allow(unused_imports)] +#![feature(negate_unsigned)] + +// Note: the relevant lint pass here runs before some of the constant +// evaluation below (e.g. that performed by trans and llvm), so if you +// change this warn to a deny, then the compiler will exit before +// those errors are detected. +#![warn(unsigned_negation)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const VALS_I8: (i8, i8, i8, i8) = + (-i8::MIN, + //~^ ERROR attempted to negate with overflow + i8::MIN - 1, + //~^ ERROR attempted to sub with overflow + i8::MAX + 1, + //~^ ERROR attempted to add with overflow + i8::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I16: (i16, i16, i16, i16) = + (-i16::MIN, + //~^ ERROR attempted to negate with overflow + i16::MIN - 1, + //~^ ERROR attempted to sub with overflow + i16::MAX + 1, + //~^ ERROR attempted to add with overflow + i16::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I32: (i32, i32, i32, i32) = + (-i32::MIN, + //~^ ERROR attempted to negate with overflow + i32::MIN - 1, + //~^ ERROR attempted to sub with overflow + i32::MAX + 1, + //~^ ERROR attempted to add with overflow + i32::MIN * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_I64: (i64, i64, i64, i64) = + (-i64::MIN, + //~^ ERROR attempted to negate with overflow + i64::MIN - 1, + //~^ ERROR attempted to sub with overflow + i64::MAX + 1, + //~^ ERROR attempted to add with overflow + i64::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U8: (u8, u8, u8, u8) = + (-u8::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u8::MIN - 1, + //~^ ERROR attempted to sub with overflow + u8::MAX + 1, + //~^ ERROR attempted to add with overflow + u8::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U16: (u16, u16, u16, u16) = + (-u16::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u16::MIN - 1, + //~^ ERROR attempted to sub with overflow + u16::MAX + 1, + //~^ ERROR attempted to add with overflow + u16::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U32: (u32, u32, u32, u32) = + (-u32::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u32::MIN - 1, + //~^ ERROR attempted to sub with overflow + u32::MAX + 1, + //~^ ERROR attempted to add with overflow + u32::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +const VALS_U64: (u64, u64, u64, u64) = + (-u64::MIN, + //~^ WARNING negation of unsigned int variable may be unintentional + // (The above is separately linted; unsigned negation is defined to be !x+1.) + u64::MIN - 1, + //~^ ERROR attempted to sub with overflow + u64::MAX + 1, + //~^ ERROR attempted to add with overflow + u64::MAX * 2, + //~^ ERROR attempted to mul with overflow + ); + +fn main() { + foo(VALS_I8); + foo(VALS_I16); + foo(VALS_I32); + foo(VALS_I64); + + foo(VALS_U8); + foo(VALS_U16); + foo(VALS_U32); + foo(VALS_U64); +} + +fn foo(x: T) { + println!("{:?}", x); +} diff --git a/src/test/compile-fail/const-len-underflow-separate-spans.rs b/src/test/compile-fail/const-len-underflow-separate-spans.rs new file mode 100644 index 0000000000..cd021a0d3b --- /dev/null +++ b/src/test/compile-fail/const-len-underflow-separate-spans.rs @@ -0,0 +1,23 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that an constant-evaluation underflow highlights the correct +// spot (where the underflow occurred), while also providing the +// overall context for what caused the evaluation. + +const ONE: usize = 1; +const TWO: usize = 2; +const LEN: usize = ONE - TWO; +//~^ ERROR array length constant evaluation error: attempted to sub with overflow [E0250] + +fn main() { + let a: [i8; LEN] = unimplemented!(); + //~^ NOTE for array length here +} diff --git a/src/test/compile-fail/const-len-underflow-subspans.rs b/src/test/compile-fail/const-len-underflow-subspans.rs new file mode 100644 index 0000000000..a31da11467 --- /dev/null +++ b/src/test/compile-fail/const-len-underflow-subspans.rs @@ -0,0 +1,20 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that an constant-evaluation underflow highlights the correct +// spot (where the underflow occurred). + +const ONE: usize = 1; +const TWO: usize = 2; + +fn main() { + let a: [i8; ONE - TWO] = unimplemented!(); + //~^ ERROR array length constant evaluation error: attempted to sub with overflow [E0250] +} diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs index 6bd21101a6..d60fb1d5d1 100644 --- a/src/test/compile-fail/cross-borrow-trait.rs +++ b/src/test/compile-fail/cross-borrow-trait.rs @@ -11,18 +11,16 @@ // Test that cross-borrowing (implicitly converting from `Box` to `&T`) is // forbidden when `T` is a trait. -#![feature(box_syntax)] - struct Foo; trait Trait { fn foo(&self) {} } impl Trait for Foo {} pub fn main() { - let x: Box = box Foo; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let x: Box = Box::new(Foo); let _y: &Trait = x; //~ ERROR mismatched types //~| expected `&Trait` //~| found `Box` //~| expected &-ptr //~| found box } - diff --git a/src/test/compile-fail/custom_attribute.rs b/src/test/compile-fail/custom_attribute.rs index 193063a98c..4e089a4e59 100644 --- a/src/test/compile-fail/custom_attribute.rs +++ b/src/test/compile-fail/custom_attribute.rs @@ -11,4 +11,4 @@ #[foo] //~ ERROR The attribute `foo` fn main() { -} \ No newline at end of file +} diff --git a/src/test/compile-fail/cycle-projection-based-on-where-clause.rs b/src/test/compile-fail/cycle-projection-based-on-where-clause.rs new file mode 100644 index 0000000000..5ca0700ce6 --- /dev/null +++ b/src/test/compile-fail/cycle-projection-based-on-where-clause.rs @@ -0,0 +1,34 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Example cycle where a bound on `T` uses a shorthand for `T`. This +// creates a cycle because we have to know the bounds on `T` to figure +// out what trait defines `Item`, but we can't know the bounds on `T` +// without knowing how to handle `T::Item`. +// +// Note that in the future cases like this could perhaps become legal, +// if we got more fine-grained about our cycle detection or changed +// how we handle `T::Item` resolution. + +use std::ops::Add; + +// Preamble. +trait Trait { type Item; } + +struct A + where T : Trait, + T : Add + //~^ ERROR unsupported cyclic reference between types/traits detected +{ + data: T +} + +fn main() { +} diff --git a/src/test/compile-fail/cycle-trait-default-type-trait.rs b/src/test/compile-fail/cycle-trait-default-type-trait.rs new file mode 100644 index 0000000000..e6caeb34a8 --- /dev/null +++ b/src/test/compile-fail/cycle-trait-default-type-trait.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a cycle where a type parameter on a trait has a default that +// again references the trait. + +trait Foo> { + //~^ ERROR unsupported cyclic reference +} + +fn main() { } diff --git a/src/test/run-pass/coherence-local-1.rs b/src/test/compile-fail/cycle-trait-supertrait-direct.rs similarity index 67% rename from src/test/run-pass/coherence-local-1.rs rename to src/test/compile-fail/cycle-trait-supertrait-direct.rs index a9bc3dc0e2..ef3fead18f 100644 --- a/src/test/run-pass/coherence-local-1.rs +++ b/src/test/compile-fail/cycle-trait-supertrait-direct.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,13 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// Test a supertrait cycle where a trait extends itself. -extern crate "coherence-lib" as lib; -use lib::Remote; - -struct Local; - -impl Remote for Vec { } +trait Chromosome: Chromosome { + //~^ ERROR unsupported cyclic reference +} fn main() { } diff --git a/src/test/compile-fail/cycle-trait-supertrait-indirect.rs b/src/test/compile-fail/cycle-trait-supertrait-indirect.rs new file mode 100644 index 0000000000..c9bfde3f4e --- /dev/null +++ b/src/test/compile-fail/cycle-trait-supertrait-indirect.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a supertrait cycle where the first trait we find (`A`) is not +// a direct participant in the cycle. + +trait A: B { + //~^ ERROR unsupported cyclic reference +} + +trait B: C { + //~^ ERROR unsupported cyclic reference +} + +trait C: B { } + //~^ ERROR unsupported cyclic reference + +fn main() { } diff --git a/src/test/compile-fail/derive-assoc-type-not-impl.rs b/src/test/compile-fail/derive-assoc-type-not-impl.rs new file mode 100644 index 0000000000..3799f2ffba --- /dev/null +++ b/src/test/compile-fail/derive-assoc-type-not-impl.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + type X; + fn method(&self) {} +} + +#[derive(Clone)] +struct Bar { + x: T::X, +} + +struct NotClone; + +impl Foo for NotClone { + type X = i8; +} + +fn main() { + Bar:: { x: 1 }.clone(); //~ ERROR +} diff --git a/src/test/compile-fail/derive-no-std-not-supported.rs b/src/test/compile-fail/derive-no-std-not-supported.rs index f82e7f3e36..d0cb4f23a8 100644 --- a/src/test/compile-fail/derive-no-std-not-supported.rs +++ b/src/test/compile-fail/derive-no-std-not-supported.rs @@ -13,7 +13,7 @@ extern crate core; extern crate rand; -extern crate "serialize" as rustc_serialize; +extern crate serialize as rustc_serialize; #[derive(Rand)] //~ ERROR this trait cannot be derived //~^ WARNING `#[derive(Rand)]` is deprecated diff --git a/src/test/compile-fail/deriving-bounds.rs b/src/test/compile-fail/deriving-bounds.rs index c0bcbb284a..72d06274de 100644 --- a/src/test/compile-fail/deriving-bounds.rs +++ b/src/test/compile-fail/deriving-bounds.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy(Bad))] -//~^ ERROR unexpected value in deriving, expected a trait +#[derive(Send)] +//~^ ERROR this unsafe trait should be implemented explicitly struct Test; #[derive(Sync)] -//~^ ERROR Sync is an unsafe trait and it should be implemented explicitly +//~^ ERROR this unsafe trait should be implemented explicitly struct Test1; pub fn main() {} diff --git a/src/test/compile-fail/deriving-meta-unknown-trait.rs b/src/test/compile-fail/deriving-meta-unknown-trait.rs index 6b85656bdd..e223499469 100644 --- a/src/test/compile-fail/deriving-meta-unknown-trait.rs +++ b/src/test/compile-fail/deriving-meta-unknown-trait.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Eqr)] //~ ERROR unknown `derive` trait: `Eqr` +#[derive(Eqr)] +//~^ ERROR `#[derive]` for custom traits is not stable enough for use and is subject to change struct Foo; pub fn main() {} diff --git a/src/test/compile-fail/deriving-non-type.rs b/src/test/compile-fail/deriving-non-type.rs index 966e28a789..5b215f3ccd 100644 --- a/src/test/compile-fail/deriving-non-type.rs +++ b/src/test/compile-fail/deriving-non-type.rs @@ -22,10 +22,10 @@ impl S { } impl T for S { } #[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums -static s: usize = 0_usize; +static s: usize = 0; #[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums -const c: usize = 0_usize; +const c: usize = 0; #[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums mod m { } diff --git a/src/test/compile-fail/destructor-restrictions.rs b/src/test/compile-fail/destructor-restrictions.rs index 0836cd1695..22f615cafd 100644 --- a/src/test/compile-fail/destructor-restrictions.rs +++ b/src/test/compile-fail/destructor-restrictions.rs @@ -14,8 +14,8 @@ use std::cell::RefCell; fn main() { let b = { - let a = Box::new(RefCell::new(4i8)); - *a.borrow() + 1i8 //~ ERROR `*a` does not live long enough + let a = Box::new(RefCell::new(4)); + *a.borrow() + 1 //~ ERROR `*a` does not live long enough }; println!("{}", b); } diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs new file mode 100644 index 0000000000..23106c9959 --- /dev/null +++ b/src/test/compile-fail/discrim-ill-typed.rs @@ -0,0 +1,118 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// When explicit discriminant value has +// a type that does not match the representation +// type, rustc should fail gracefully. + +// See also run-pass/discrim-explicit-23030.rs where the input types +// are correct. + +#![allow(dead_code, unused_variables, unused_imports)] + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = 0_u8, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = 0_i8, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = 0_u16, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = 0_i16, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = 0_u32, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = 0_i32, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = 0_u64, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = 0_i64, + //~^ ERROR mismatched types + } + + let x = A::Ok; +} + +fn main() { } diff --git a/src/test/compile-fail/discrim-overflow-2.rs b/src/test/compile-fail/discrim-overflow-2.rs new file mode 100644 index 0000000000..76378d5c80 --- /dev/null +++ b/src/test/compile-fail/discrim-overflow-2.rs @@ -0,0 +1,94 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Issue 23030: Detect overflowing discriminant +// +// Check that we detect the overflow even if enum is not used. + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome + } +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome + } +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } +} + +fn main() { } diff --git a/src/test/compile-fail/discrim-overflow.rs b/src/test/compile-fail/discrim-overflow.rs new file mode 100644 index 0000000000..5d7e61e9d1 --- /dev/null +++ b/src/test/compile-fail/discrim-overflow.rs @@ -0,0 +1,108 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Issue 23030: Detect overflowing discriminant + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +use std::{i8,u8,i16,u16,i32,u32,i64, u64}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed + } + + let x = A::Ok; +} + +fn main() { } diff --git a/src/test/compile-fail/drop-with-active-borrows-1.rs b/src/test/compile-fail/drop-with-active-borrows-1.rs index dc8deb0483..903365fb90 100644 --- a/src/test/compile-fail/drop-with-active-borrows-1.rs +++ b/src/test/compile-fail/drop-with-active-borrows-1.rs @@ -16,4 +16,3 @@ fn main() { println!("{}", *s); } } - diff --git a/src/test/compile-fail/dropck_arr_cycle_checked.rs b/src/test/compile-fail/dropck_arr_cycle_checked.rs index 3aa2fae282..40d992fe21 100644 --- a/src/test/compile-fail/dropck_arr_cycle_checked.rs +++ b/src/test/compile-fail/dropck_arr_cycle_checked.rs @@ -20,9 +20,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs b/src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs new file mode 100644 index 0000000000..f096885381 --- /dev/null +++ b/src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs @@ -0,0 +1,37 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + + +enum FingerTree { + Single(T), + // Bug report said Digit after Box would stack overflow (versus + // Digit before Box; see dropck_no_diverge_on_nonregular_2). + Deep( + Box>>, + Digit, + ) +} + +fn main() { + let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + FingerTree::Single(1); + //~^ ERROR overflow while adding drop-check rules for FingerTree +} diff --git a/src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs b/src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs new file mode 100644 index 0000000000..886bd6bea2 --- /dev/null +++ b/src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + +enum FingerTree { + Single(T), + // Bug report said Digit before Box would infinite loop (versus + // Digit after Box; see dropck_no_diverge_on_nonregular_1). + Deep( + Digit, + Box>>, + ) +} + +fn main() { + let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + FingerTree::Single(1); + //~^ ERROR overflow while adding drop-check rules for FingerTree +} diff --git a/src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs b/src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs new file mode 100644 index 0000000000..f7eb6e10ca --- /dev/null +++ b/src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs @@ -0,0 +1,46 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. +// +// This version is just checking that we still sanely handle a trivial +// wrapper around the non-regular type. (It also demonstrates how the +// error messages will report different types depending on which type +// dropck is analyzing.) + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + +enum FingerTree { + Single(T), + // According to the bug report, Digit before Box would infinite loop. + Deep( + Digit, + Box>>, + ) +} + +enum Wrapper { + Simple, + Other(FingerTree), +} + +fn main() { + let w = //~ ERROR overflow while adding drop-check rules for core::option + Some(Wrapper::Simple::); + //~^ ERROR overflow while adding drop-check rules for core::option::Option + //~| ERROR overflow while adding drop-check rules for Wrapper +} diff --git a/src/test/compile-fail/dropck_tarena_cycle_checked.rs b/src/test/compile-fail/dropck_tarena_cycle_checked.rs index 74e3c724b6..9488882ca9 100644 --- a/src/test/compile-fail/dropck_tarena_cycle_checked.rs +++ b/src/test/compile-fail/dropck_tarena_cycle_checked.rs @@ -27,9 +27,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dropck_vec_cycle_checked.rs b/src/test/compile-fail/dropck_vec_cycle_checked.rs index 3f69c7d1a9..9d92552244 100644 --- a/src/test/compile-fail/dropck_vec_cycle_checked.rs +++ b/src/test/compile-fail/dropck_vec_cycle_checked.rs @@ -19,9 +19,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_count() -> usize { S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 diff --git a/src/test/compile-fail/dst-bad-assign-2.rs b/src/test/compile-fail/dst-bad-assign-2.rs index 7dbb8fc92e..8441f3a99e 100644 --- a/src/test/compile-fail/dst-bad-assign-2.rs +++ b/src/test/compile-fail/dst-bad-assign-2.rs @@ -10,8 +10,6 @@ // Forbid assignment into a dynamically sized type. -#![feature(box_syntax)] - struct Fat { f1: isize, f2: &'static str, @@ -43,7 +41,8 @@ impl ToBar for Bar1 { pub fn main() { // Assignment. let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; - let z: Box = box Bar1 {f: 36}; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let z: Box = Box::new(Bar1 {f: 36}); f5.ptr = *z; //~^ ERROR the trait `core::marker::Sized` is not implemented } diff --git a/src/test/compile-fail/dst-bad-assign.rs b/src/test/compile-fail/dst-bad-assign.rs index 152864b601..d3029bc6a9 100644 --- a/src/test/compile-fail/dst-bad-assign.rs +++ b/src/test/compile-fail/dst-bad-assign.rs @@ -10,8 +10,6 @@ // Forbid assignment into a dynamically sized type. -#![feature(box_syntax)] - struct Fat { f1: isize, f2: &'static str, @@ -43,7 +41,8 @@ impl ToBar for Bar1 { pub fn main() { // Assignment. let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; - let z: Box = box Bar1 {f: 36}; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let z: Box = Box::new(Bar1 {f: 36}); f5.ptr = Bar1 {f: 36}; //~^ ERROR mismatched types //~| expected `ToBar` diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index ddc9290177..2d87345db2 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -23,10 +23,6 @@ pub fn main() { let f2: &Fat<[isize; 3]> = &f1; let f3: &Fat<[usize]> = f2; //~^ ERROR mismatched types - //~| expected `&Fat<[usize]>` - //~| found `&Fat<[isize; 3]>` - //~| expected usize - //~| found isize // With a trait. let f1 = Fat { ptr: Foo }; diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs index 91f3432048..c52458934b 100644 --- a/src/test/compile-fail/dst-index.rs +++ b/src/test/compile-fail/dst-index.rs @@ -14,24 +14,24 @@ use std::ops::Index; use std::fmt::Debug; -#[derive(Copy)] +#[derive(Copy, Clone)] struct S; impl Index for S { type Output = str; - fn index<'a>(&'a self, _: &usize) -> &'a str { + fn index(&self, _: usize) -> &str { "hello" } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct T; impl Index for T { type Output = Debug + 'static; - fn index<'a>(&'a self, idx: &usize) -> &'a (Debug + 'static) { + fn index<'a>(&'a self, idx: usize) -> &'a (Debug + 'static) { static x: usize = 42; &x } diff --git a/src/test/compile-fail/duplicate-parameter.rs b/src/test/compile-fail/duplicate-parameter.rs index 18ec55e10b..7586bc61cd 100644 --- a/src/test/compile-fail/duplicate-parameter.rs +++ b/src/test/compile-fail/duplicate-parameter.rs @@ -13,4 +13,3 @@ fn f(a: isize, a: isize) {} fn main() { } - diff --git a/src/test/compile-fail/duplicate-type-parameter.rs b/src/test/compile-fail/duplicate-type-parameter.rs index d535ce4a69..42b67337c6 100644 --- a/src/test/compile-fail/duplicate-type-parameter.rs +++ b/src/test/compile-fail/duplicate-type-parameter.rs @@ -36,4 +36,3 @@ impl Qux for Option {} fn main() { } - diff --git a/src/test/compile-fail/empty-extern-arg.rs b/src/test/compile-fail/empty-extern-arg.rs index 9b7df81a5d..8791481d9e 100644 --- a/src/test/compile-fail/empty-extern-arg.rs +++ b/src/test/compile-fail/empty-extern-arg.rs @@ -9,6 +9,6 @@ // except according to those terms. // compile-flags: --extern std= -// error-pattern: is not a file +// error-pattern: can't find crate for `std` fn main() {} diff --git a/src/test/compile-fail/enum-discrim-too-small.rs b/src/test/compile-fail/enum-discrim-too-small.rs index 1d7794336a..cdf7d026d5 100644 --- a/src/test/compile-fail/enum-discrim-too-small.rs +++ b/src/test/compile-fail/enum-discrim-too-small.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(negate_unsigned)] + #[repr(u8)] //~ NOTE discriminant type specified here enum Eu8 { Au8 = 23, diff --git a/src/test/compile-fail/estr-subtyping.rs b/src/test/compile-fail/estr-subtyping.rs index 6e64e01d74..b5c6db0cea 100644 --- a/src/test/compile-fail/estr-subtyping.rs +++ b/src/test/compile-fail/estr-subtyping.rs @@ -18,7 +18,7 @@ fn has_uniq(x: String) { fn has_slice(x: &str) { wants_uniq(x); //~ ERROR mismatched types - wants_slice(x.as_slice()); + wants_slice(x); } fn main() { diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs index 92b7b601e4..ed1327f311 100644 --- a/src/test/compile-fail/eval-enum.rs +++ b/src/test/compile-fail/eval-enum.rs @@ -9,8 +9,8 @@ // except according to those terms. enum test { - div_zero = 1/0, //~ERROR expected constant: attempted to divide by zero - rem_zero = 1%0 //~ERROR expected constant: attempted remainder with a divisor of zero + div_zero = 1/0, //~ERROR constant evaluation error: attempted to divide by zero + rem_zero = 1%0 //~ERROR constant evaluation error: attempted remainder with a divisor of zero } fn main() {} diff --git a/src/test/compile-fail/exclusive-drop-and-copy.rs b/src/test/compile-fail/exclusive-drop-and-copy.rs index f47f14d587..460c396750 100644 --- a/src/test/compile-fail/exclusive-drop-and-copy.rs +++ b/src/test/compile-fail/exclusive-drop-and-copy.rs @@ -12,14 +12,14 @@ // issue #20126 -#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented +#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented struct Foo; impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented +#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented struct Bar(::std::marker::PhantomData); #[unsafe_destructor] diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs index 92542ab3bc..922e58698d 100644 --- a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs +++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs @@ -26,4 +26,3 @@ impl<'a,'b> Foo<'a,'b> { } fn main() {} - diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs index ade8b397e0..2553bdcbb2 100644 --- a/src/test/compile-fail/extern-with-type-bounds.rs +++ b/src/test/compile-fail/extern-with-type-bounds.rs @@ -24,8 +24,7 @@ extern "rust-intrinsic" { // Unresolved bounds should still error. fn align_of() -> usize; - //~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait` + //~^ ERROR use of undeclared trait name `NoSuchTrait` } fn main() {} - diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index db3373ea02..d1abed9b26 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -18,5 +18,5 @@ fn main() { let _x: extern "C" fn() = f; // OK is_fn(f); //~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn() - //~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn() + //~| ERROR the trait `core::ops::FnOnce<()>` is not implemented for the type `extern "C" fn() } diff --git a/src/test/compile-fail/feature-gate-advanced-slice-features.rs b/src/test/compile-fail/feature-gate-advanced-slice-features.rs index d5841e1e77..1daca371b3 100644 --- a/src/test/compile-fail/feature-gate-advanced-slice-features.rs +++ b/src/test/compile-fail/feature-gate-advanced-slice-features.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { let x = [ 1, 2, 3, 4, 5 ]; match x { @@ -16,4 +18,3 @@ fn main() { [ 1, 2, xs.. ] => {} // OK without feature gate } } - diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs b/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs new file mode 100644 index 0000000000..c9251c925c --- /dev/null +++ b/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! bar { + () => { + // more layers don't help: + #[allow_internal_unstable] + macro_rules! baz { //~ ERROR allow_internal_unstable side-steps + () => {} + } + } +} + +bar!(); + +fn main() {} diff --git a/src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs b/src/test/compile-fail/feature-gate-allow-internal-unstable.rs similarity index 77% rename from src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs rename to src/test/compile-fail/feature-gate-allow-internal-unstable.rs index ccda5cbdce..8a2d8dddac 100644 --- a/src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs +++ b/src/test/compile-fail/feature-gate-allow-internal-unstable.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[plugin] //~ ERROR #[plugin] on `extern crate` is deprecated -//~^ HELP use a crate attribute instead, i.e. #![plugin(std)] -extern crate std; +#[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps +macro_rules! foo { + () => {} +} fn main() {} diff --git a/src/test/compile-fail/feature-gate-box-expr.rs b/src/test/compile-fail/feature-gate-box-expr.rs index 39f54be456..8f8b035f4a 100644 --- a/src/test/compile-fail/feature-gate-box-expr.rs +++ b/src/test/compile-fail/feature-gate-box-expr.rs @@ -20,4 +20,3 @@ fn main() { let x = box (HEAP) 'c'; //~ ERROR box expression syntax is experimental println!("x: {}", x); } - diff --git a/src/test/compile-fail/feature-gate-int-uint.rs b/src/test/compile-fail/feature-gate-int-uint.rs deleted file mode 100644 index 948e485ccf..0000000000 --- a/src/test/compile-fail/feature-gate-int-uint.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(dead_code, unused_variables)] -#![feature(rustc_attrs)] - -mod u { - type X = uint; //~ WARN the `uint` type is deprecated - struct Foo { - x: uint //~ WARN the `uint` type is deprecated - } - fn bar(x: uint) { //~ WARN the `uint` type is deprecated - 1_u; //~ WARN the `u` and `us` suffixes on integers are deprecated - 1_us; //~ WARN the `u` and `us` suffixes on integers are deprecated - } -} -mod i { - type X = int; //~ WARN the `int` type is deprecated - struct Foo { - x: int //~ WARN the `int` type is deprecated - } - fn bar(x: int) { //~ WARN the `int` type is deprecated - 1_i; //~ WARN the `i` and `is` suffixes on integers are deprecated - 1_is; //~ WARN the `i` and `is` suffixes on integers are deprecated - } -} - -#[rustc_error] -fn main() { //~ ERROR compilation successful -} diff --git a/src/test/compile-fail/feature-gate-intrinsics-and-lang-items.rs b/src/test/compile-fail/feature-gate-intrinsics.rs similarity index 89% rename from src/test/compile-fail/feature-gate-intrinsics-and-lang-items.rs rename to src/test/compile-fail/feature-gate-intrinsics.rs index 986d52b178..a4c09b21c9 100644 --- a/src/test/compile-fail/feature-gate-intrinsics-and-lang-items.rs +++ b/src/test/compile-fail/feature-gate-intrinsics.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[lang="foo"] //~ ERROR language items are subject to change -trait Foo {} - extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change fn bar(); } @@ -20,4 +17,3 @@ extern "rust-intrinsic" fn baz() { //~ ERROR intrinsics are subject to change fn main() { } - diff --git a/src/test/run-pass/deprecated-no-split-stack.rs b/src/test/compile-fail/feature-gate-lang-items.rs similarity index 84% rename from src/test/run-pass/deprecated-no-split-stack.rs rename to src/test/compile-fail/feature-gate-lang-items.rs index 31ba5dde81..0435ff4c33 100644 --- a/src/test/run-pass/deprecated-no-split-stack.rs +++ b/src/test/compile-fail/feature-gate-lang-items.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//~ WARNING no_split_stack is a deprecated synonym for no_stack_check -#[no_split_stack] +#[lang="foo"] //~ ERROR language items are subject to change +trait Foo {} + fn main() { } diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/feature-gate-rust-call.rs similarity index 68% rename from src/test/compile-fail/kindck-destructor-owned.rs rename to src/test/compile-fail/feature-gate-rust-call.rs index 7f3704144b..029a9cad65 100644 --- a/src/test/compile-fail/kindck-destructor-owned.rs +++ b/src/test/compile-fail/feature-gate-rust-call.rs @@ -8,24 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change -struct Bar<'a> { - f: &'a isize, +trait Foo { + extern "rust-call" fn foo(); } -impl<'a> Drop for Bar<'a> { -//~^ ERROR E0141 - fn drop(&mut self) { - } -} - -struct Baz { - f: &'static isize, -} - -impl Drop for Baz { - fn drop(&mut self) { - } +impl Foo for i32 { + extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change } fn main() { } diff --git a/src/test/compile-fail/feature-gate-simd-ffi.rs b/src/test/compile-fail/feature-gate-simd-ffi.rs index 9ee3fcee02..dcd7a0ded8 100644 --- a/src/test/compile-fail/feature-gate-simd-ffi.rs +++ b/src/test/compile-fail/feature-gate-simd-ffi.rs @@ -13,7 +13,7 @@ use std::simd::f32x4; -#[simd] #[derive(Copy)] #[repr(C)] struct LocalSimd(u8, u8); +#[simd] #[derive(Copy, Clone)] #[repr(C)] struct LocalSimd(u8, u8); extern { fn foo() -> f32x4; //~ ERROR use of SIMD type diff --git a/src/test/compile-fail/feature-gate-start.rs b/src/test/compile-fail/feature-gate-start.rs index 6a9acf0429..7a0924d8ad 100644 --- a/src/test/compile-fail/feature-gate-start.rs +++ b/src/test/compile-fail/feature-gate-start.rs @@ -10,4 +10,3 @@ #[start] fn foo() {} //~ ERROR: a #[start] function is an experimental feature - diff --git a/src/test/compile-fail/bad-crate-id2.rs b/src/test/compile-fail/feature-gate-static-assert.rs similarity index 72% rename from src/test/compile-fail/bad-crate-id2.rs rename to src/test/compile-fail/feature-gate-static-assert.rs index 4899252a1a..25740397d7 100644 --- a/src/test/compile-fail/bad-crate-id2.rs +++ b/src/test/compile-fail/feature-gate-static-assert.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate "#a" as bar; //~ ERROR: invalid character `#` in crate name: `#a` +#[static_assert] //~ ERROR `#[static_assert]` is an experimental feature +static X: bool = true; fn main() {} - diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs index e5e5ddadaf..5df309321d 100644 --- a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs +++ b/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs @@ -17,30 +17,23 @@ struct Foo; impl Fn<()> for Foo { - //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits - type Output = (); - - extern "rust-call" fn call(&self, args: ()) -> () {} + extern "rust-call" fn call(self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change } struct Foo1; -impl Fn() for Foo1 { - //~^ ERROR associated type bindings are not allowed here - - extern "rust-call" fn call(&self, args: ()) -> () {} +impl FnOnce() for Foo1 { + extern "rust-call" fn call_once(self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change } struct Bar; impl FnMut<()> for Bar { - //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits - type Output = (); - extern "rust-call" fn call_mut(&self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change } struct Baz; impl FnOnce<()> for Baz { - //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits - type Output = (); - extern "rust-call" fn call_once(&self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change } fn main() {} diff --git a/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs b/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs index 1e15e67876..54bdaf011c 100644 --- a/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs +++ b/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs @@ -21,7 +21,7 @@ // test. Not ideal, but oh well :( fn main() { - let a = &[1i32, 2, 3]; + let a = &[1, 2, 3]; println!("{}", { extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change fn atomic_fence(); diff --git a/src/test/compile-fail/fn-compare-mismatch.rs b/src/test/compile-fail/fn-compare-mismatch.rs index 6178d37a5b..27be1ada44 100644 --- a/src/test/compile-fail/fn-compare-mismatch.rs +++ b/src/test/compile-fail/fn-compare-mismatch.rs @@ -13,4 +13,5 @@ fn main() { fn g() { } let x = f == g; //~^ ERROR binary operation `==` cannot be applied + //~| ERROR mismatched types } diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index 71e1f7091b..6433255bd4 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -15,8 +15,7 @@ fn needs_fn(x: F) where F: Fn(isize) -> isize {} fn main() { let _: () = (box |_: isize| {}) as Box; - //~^ ERROR object-safe - //~| ERROR mismatched types + //~^ ERROR mismatched types //~| expected `()` //~| found `Box` //~| expected () @@ -27,7 +26,7 @@ fn main() { //~| found `Box` //~| expected () //~| found box - let _: () = (box || -> isize unimplemented!()) as Box isize>; + let _: () = (box || -> isize { unimplemented!() }) as Box isize>; //~^ ERROR mismatched types //~| expected `()` //~| found `Box isize>` @@ -36,5 +35,5 @@ fn main() { needs_fn(1); //~^ ERROR `core::ops::Fn<(isize,)>` - //~| ERROR `core::ops::Fn<(isize,)>` + //~| ERROR `core::ops::FnOnce<(isize,)>` } diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs index 838e65e1d0..8e1e88a92e 100644 --- a/src/test/compile-fail/fn-variance-1.rs +++ b/src/test/compile-fail/fn-variance-1.rs @@ -17,9 +17,13 @@ fn apply(t: T, f: F) where F: FnOnce(T) { } fn main() { - apply(&3, takes_mut); //~ ERROR (values differ in mutability) apply(&3, takes_imm); + apply(&3, takes_mut); + //~^ ERROR (values differ in mutability) + //~| ERROR (values differ in mutability) apply(&mut 3, takes_mut); - apply(&mut 3, takes_imm); //~ ERROR (values differ in mutability) + apply(&mut 3, takes_imm); + //~^ ERROR (values differ in mutability) + //~| ERROR (values differ in mutability) } diff --git a/src/test/compile-fail/lint-unnecessary-casts.rs b/src/test/compile-fail/gated-box-patterns.rs similarity index 53% rename from src/test/compile-fail/lint-unnecessary-casts.rs rename to src/test/compile-fail/gated-box-patterns.rs index b3cf8257b8..abaa256d52 100644 --- a/src/test/compile-fail/lint-unnecessary-casts.rs +++ b/src/test/compile-fail/gated-box-patterns.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,17 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![forbid(unused_typecasts)] - -fn foo_i32(_: i32) {} - -fn foo_u64(a: u64) { - let b: i32 = a as i32; - foo_i32(b as i32); //~ ERROR: unnecessary type cast -} +// Test that patterns including the box syntax are gated by `box_patterns` feature gate. fn main() { - let x: u64 = 1; - let y: u64 = x as u64; //~ ERROR: unnecessary type cast - foo_u64(y as u64); //~ ERROR: unnecessary type cast + let x = Box::new(1); + + match x { + box 1 => (), + //~^ box pattern syntax is experimental + //~| add #![feature(box_patterns)] to the crate attributes to enable + _ => () + }; } diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/compile-fail/gated-box-syntax.rs new file mode 100644 index 0000000000..3e08c1f7a7 --- /dev/null +++ b/src/test/compile-fail/gated-box-syntax.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the use of the box syntax is gated by `box_syntax` feature gate. + +fn main() { + let x = box 3; + //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead. + //~| HELP add #![feature(box_syntax)] to the crate attributes to enable +} diff --git a/src/test/compile-fail/gated-link-args.rs b/src/test/compile-fail/gated-link-args.rs new file mode 100644 index 0000000000..c8845ced2f --- /dev/null +++ b/src/test/compile-fail/gated-link-args.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `#[link_args]` attribute is gated by `link_args` +// feature gate. + +#[link_args = "aFdEfSeVEEE"] +extern {} +//~^ ERROR the `link_args` attribute is not portable across platforms +//~| HELP add #![feature(link_args)] to the crate attributes to enable + +fn main() { } diff --git a/src/test/compile-fail/gated-link-llvm-intrinsics.rs b/src/test/compile-fail/gated-link-llvm-intrinsics.rs new file mode 100644 index 0000000000..716ea9f8db --- /dev/null +++ b/src/test/compile-fail/gated-link-llvm-intrinsics.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; + //~^ ERROR linking to LLVM intrinsics is experimental + //~| HELP add #![feature(link_llvm_intrinsics)] to the crate attributes +} + +fn main(){ +} diff --git a/src/test/compile-fail/gated-plugin_registrar.rs b/src/test/compile-fail/gated-plugin_registrar.rs index f6e11ffd9e..d716c53e1d 100644 --- a/src/test/compile-fail/gated-plugin_registrar.rs +++ b/src/test/compile-fail/gated-plugin_registrar.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test that `#[plugin_registrar]` attribute is gated by `plugin_registrar` +// feature gate. + // the registration function isn't typechecked yet #[plugin_registrar] -pub fn registrar() {} //~ ERROR compiler plugins are experimental - +pub fn registrar() {} +//~^ ERROR compiler plugins are experimental +//~| HELP add #![feature(plugin_registrar)] to the crate attributes to enable fn main() {} diff --git a/src/test/compile-fail/gated-simd-ffi.rs b/src/test/compile-fail/gated-simd-ffi.rs new file mode 100644 index 0000000000..883e1be04b --- /dev/null +++ b/src/test/compile-fail/gated-simd-ffi.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the use of smid types in the ffi is gated by `smid_ffi` feature gate. + +#![feature(simd)] + +#[repr(C)] +#[derive(Copy, Clone)] +#[simd] +pub struct f32x4(f32, f32, f32, f32); + +#[allow(dead_code)] +extern { + fn foo(x: f32x4); + //~^ ERROR use of SIMD type `f32x4` in FFI is highly experimental and may result in invalid code + //~| HELP add #![feature(simd_ffi)] to the crate attributes to enable +} + +fn main() {} diff --git a/src/test/compile-fail/gated-thread-local.rs b/src/test/compile-fail/gated-thread-local.rs new file mode 100644 index 0000000000..f355c6562c --- /dev/null +++ b/src/test/compile-fail/gated-thread-local.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `#[thread_local]` attribute is gated by `thread_local` +// feature gate. +// +// (Note that the `thread_local!` macro is explicitly *not* gated; it +// is given permission to expand into this unstable attribute even +// when the surrounding context does not have permission to use it.) + +#[thread_local] //~ ERROR `#[thread_local]` is an experimental feature +static FOO: i32 = 3; + +pub fn main() { + FOO.with(|x| { + println!("x: {}", x); + }); +} diff --git a/src/test/compile-fail/gated-unsafe-destructor.rs b/src/test/compile-fail/gated-unsafe-destructor.rs new file mode 100644 index 0000000000..2aebbf3d54 --- /dev/null +++ b/src/test/compile-fail/gated-unsafe-destructor.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that `#[unsafe_destructor]` attribute is gated by `unsafe_destructor` +// feature gate. +// +// (This test can be removed entirely when we remove the +// `unsafe_destructor` feature itself.) + +struct D<'a>(&'a u32); + +#[unsafe_destructor] +//~^ ERROR `#[unsafe_destructor]` does nothing anymore +//~| HELP: add #![feature(unsafe_destructor)] to the crate attributes to enable +// (but of couse there is no point in doing so) +impl<'a> Drop for D<'a> { + fn drop(&mut self) { } +} + +pub fn main() { } diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs index 9fea5e609d..5fa429445a 100644 --- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs @@ -19,5 +19,5 @@ impl Foo { fn main() { Foo::::new(); - //~^ ERROR too few type parameters provided + //~^ ERROR wrong number of type arguments } diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs index 73c19aa012..d3babb8982 100644 --- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs @@ -21,5 +21,5 @@ impl Vec { fn main() { Vec::::new(); - //~^ ERROR too many type parameters provided + //~^ ERROR wrong number of type arguments } diff --git a/src/test/compile-fail/generic-no-mangle.rs b/src/test/compile-fail/generic-no-mangle.rs index f4ead18ee1..4163d531e8 100644 --- a/src/test/compile-fail/generic-no-mangle.rs +++ b/src/test/compile-fail/generic-no-mangle.rs @@ -15,4 +15,3 @@ fn foo() {} //~ ERROR generic functions must be mangled #[no_mangle] extern fn foo() {} //~ ERROR generic functions must be mangled - diff --git a/src/test/compile-fail/glob-resolve1.rs b/src/test/compile-fail/glob-resolve1.rs index fce8a07d72..181503db81 100644 --- a/src/test/compile-fail/glob-resolve1.rs +++ b/src/test/compile-fail/glob-resolve1.rs @@ -36,9 +36,6 @@ fn main() { import(); //~ ERROR: unresolved foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared foo::(); //~ ERROR: undeclared - //~^ ERROR: undeclared } diff --git a/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs deleted file mode 100644 index db67249bbd..0000000000 --- a/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs +++ /dev/null @@ -1,36 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(unboxed_closures)] - -// Test that we suggest the correct parentheses - -trait Bar { - fn dummy(&self) { } -} - -struct Foo<'a> { - a: &'a Bar+'a, - //~^ ERROR E0178 - //~^^ HELP perhaps you meant `&'a (Bar + 'a)`? - - b: &'a mut Bar+'a, - //~^ ERROR E0178 - //~^^ HELP perhaps you meant `&'a mut (Bar + 'a)`? - - c: Box, // OK, no paren needed in this context - - d: fn() -> Bar+'a, - //~^ ERROR E0178 - //~^^ HELP perhaps you forgot parentheses - //~^^^ WARN deprecated syntax -} - -fn main() { } diff --git a/src/test/compile-fail/huge-array-simple.rs b/src/test/compile-fail/huge-array-simple.rs index 1e04e685e4..54340cf7ac 100644 --- a/src/test/compile-fail/huge-array-simple.rs +++ b/src/test/compile-fail/huge-array-simple.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: too big for the current +// FIXME (#23926): the error output is not consistent between a +// self-hosted and a cross-compiled setup. Skipping for now. + +// ignore-test FIXME(#23926) + +#![allow(exceeding_bitshifts)] fn main() { - let fat : [u8; (1<<61)+(1<<31)] = [0; (1u64<<61) as usize +(1u64<<31) as usize]; + let _fat : [u8; (1<<61)+(1<<31)] = + [0; (1u64<<61) as usize +(1u64<<31) as usize]; } diff --git a/src/test/compile-fail/if-loop.rs b/src/test/compile-fail/if-loop.rs new file mode 100644 index 0000000000..15f04df693 --- /dev/null +++ b/src/test/compile-fail/if-loop.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +// This used to ICE because the "if" being unreachable was not handled correctly +fn err() { + if loop {} {} +} + +#[rustc_error] +fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/impl-duplicate-methods.rs b/src/test/compile-fail/impl-duplicate-methods.rs index c6ce4d04e1..3b4def8c50 100644 --- a/src/test/compile-fail/impl-duplicate-methods.rs +++ b/src/test/compile-fail/impl-duplicate-methods.rs @@ -11,7 +11,7 @@ struct Foo; impl Foo { fn orange(&self){} - fn orange(&self){} //~ ERROR error: duplicate definition of value `orange` + fn orange(&self){} //~ ERROR error: duplicate method } fn main() {} diff --git a/src/test/compile-fail/import-glob-circular.rs b/src/test/compile-fail/import-glob-circular.rs index f38172db44..67834a9996 100644 --- a/src/test/compile-fail/import-glob-circular.rs +++ b/src/test/compile-fail/import-glob-circular.rs @@ -13,13 +13,13 @@ mod circ1 { pub use circ2::f2; pub fn f1() { println!("f1"); } - pub fn common() -> usize { return 0_usize; } + pub fn common() -> usize { return 0; } } mod circ2 { pub use circ1::f1; pub fn f2() { println!("f2"); } - pub fn common() -> usize { return 1_usize; } + pub fn common() -> usize { return 1; } } mod test { diff --git a/src/test/compile-fail/index-bot.rs b/src/test/compile-fail/index-bot.rs index b28f2a746f..70c362303a 100644 --- a/src/test/compile-fail/index-bot.rs +++ b/src/test/compile-fail/index-bot.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - (return)[0_usize]; //~ ERROR the type of this value must be known in this context + (return)[0]; //~ ERROR the type of this value must be known in this context } diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs index 901d8783d0..3ca00fcb66 100644 --- a/src/test/compile-fail/indexing-requires-a-uint.rs +++ b/src/test/compile-fail/indexing-requires-a-uint.rs @@ -23,4 +23,3 @@ fn main() { bar::(i); // i should not be re-coerced back to an isize //~^ ERROR: mismatched types } - diff --git a/src/test/compile-fail/infinite-instantiation.rs b/src/test/compile-fail/infinite-instantiation.rs index 2642ac6204..559e0e9a29 100644 --- a/src/test/compile-fail/infinite-instantiation.rs +++ b/src/test/compile-fail/infinite-instantiation.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,31 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: reached the recursion limit during monomorphization -// issue 2258 +//~^^^^^^^^^^ ERROR overflow +// +// We get an error message at the top of file (dummy span). +// This is not helpful, but also kind of annoying to prevent, +// so for now just live with it. +// This test case was originally for issue #2258. -trait to_opt { +trait ToOpt { fn to_option(&self) -> Option; } -impl to_opt for usize { +impl ToOpt for usize { fn to_option(&self) -> Option { Some(*self) } } -impl to_opt for Option { +impl ToOpt for Option { fn to_option(&self) -> Option> { Some((*self).clone()) } } -fn function(counter: usize, t: T) { - if counter > 0_usize { - function(counter - 1_usize, t.to_option()); +fn function(counter: usize, t: T) { + if counter > 0 { + function(counter - 1, t.to_option()); + // FIXME(#4287) Error message should be here. It should be + // a type error to instantiate `test` at a type other than T. } } fn main() { - function(22_usize, 22_usize); + function(22, 22); } diff --git a/src/test/compile-fail/infinite-macro-expansion.rs b/src/test/compile-fail/infinite-macro-expansion.rs index 74835f4bf2..14d22702db 100644 --- a/src/test/compile-fail/infinite-macro-expansion.rs +++ b/src/test/compile-fail/infinite-macro-expansion.rs @@ -15,4 +15,3 @@ macro_rules! recursive { fn main() { recursive!() } - diff --git a/src/test/compile-fail/infinite-vec-type-recursion.rs b/src/test/compile-fail/infinite-vec-type-recursion.rs index 5bcba350b2..e5120840f7 100644 --- a/src/test/compile-fail/infinite-vec-type-recursion.rs +++ b/src/test/compile-fail/infinite-vec-type-recursion.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: illegal recursive type - - type x = Vec; +//~^ ERROR unsupported cyclic reference fn main() { let b: x = Vec::new(); } diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs index abd7efe0e8..cf2a70deee 100644 --- a/src/test/compile-fail/inner-static-type-parameter.rs +++ b/src/test/compile-fail/inner-static-type-parameter.rs @@ -14,7 +14,8 @@ enum Bar { What } fn foo() { static a: Bar = Bar::What; - //~^ ERROR: cannot use an outer type parameter in this context + //~^ ERROR cannot use an outer type parameter in this context + //~| ERROR use of undeclared type name `T` } fn main() { diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index e8998dd7a9..e2fb0fa4f2 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -24,11 +24,11 @@ pub fn main() { s.as_bytes()[3_usize]; s.as_bytes()[3]; s.as_bytes()[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ERROR the trait `core::ops::Index` is not implemented + //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ERROR the trait `core::ops::Index` is not implemented + //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ERROR the trait `core::ops::Index` is not implemented + //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3i32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ERROR the trait `core::ops::Index` is not implemented + //~^ ERROR the trait `core::ops::Index` is not implemented } diff --git a/src/test/compile-fail/internal-unstable-noallow.rs b/src/test/compile-fail/internal-unstable-noallow.rs new file mode 100644 index 0000000000..2b48d47e94 --- /dev/null +++ b/src/test/compile-fail/internal-unstable-noallow.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// this has to be separate to internal-unstable.rs because these tests +// have error messages pointing deep into the internals of the +// cross-crate macros, and hence need to use error-pattern instead of +// the // ~ form. + +// aux-build:internal_unstable.rs +// error-pattern:use of unstable library feature 'function' +// error-pattern:use of unstable library feature 'struct_field' + +#[macro_use] +extern crate internal_unstable; + +fn main() { + call_unstable_noallow!(); + + construct_unstable_noallow!(0); +} diff --git a/src/test/compile-fail/unsafe-destructor-check-crash.rs b/src/test/compile-fail/internal-unstable-thread-local.rs similarity index 62% rename from src/test/compile-fail/unsafe-destructor-check-crash.rs rename to src/test/compile-fail/internal-unstable-thread-local.rs index af67558772..74526fb3d8 100644 --- a/src/test/compile-fail/unsafe-destructor-check-crash.rs +++ b/src/test/compile-fail/internal-unstable-thread-local.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:internal_unstable.rs +#![allow(dead_code)] -// Regression test for issue #15557 +extern crate internal_unstable; -#![allow(dead_code)] -struct AReg1<'a>(&'a u32); -impl<'a> Drop for AReg1<'a> { -//~^ ERROR: cannot implement a destructor on a structure with type parameters - fn drop(&mut self) {} -} +thread_local!(static FOO: () = ()); +thread_local!(static BAR: () = internal_unstable::unstable()); //~ ERROR use of unstable fn main() {} diff --git a/src/test/compile-fail/internal-unstable.rs b/src/test/compile-fail/internal-unstable.rs new file mode 100755 index 0000000000..accc898b8a --- /dev/null +++ b/src/test/compile-fail/internal-unstable.rs @@ -0,0 +1,50 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:internal_unstable.rs + +#![feature(allow_internal_unstable)] + +#[macro_use] +extern crate internal_unstable; + +macro_rules! foo { + ($e: expr, $f: expr) => {{ + $e; + $f; + internal_unstable::unstable(); //~ ERROR use of unstable + }} +} + +#[allow_internal_unstable] +macro_rules! bar { + ($e: expr) => {{ + foo!($e, + internal_unstable::unstable()); + internal_unstable::unstable(); + }} +} + +fn main() { + // ok, the instability is contained. + call_unstable_allow!(); + construct_unstable_allow!(0); + + // bad. + pass_through_allow!(internal_unstable::unstable()); //~ ERROR use of unstable + + pass_through_noallow!(internal_unstable::unstable()); //~ ERROR use of unstable + + + + println!("{:?}", internal_unstable::unstable()); //~ ERROR use of unstable + + bar!(internal_unstable::unstable()); //~ ERROR use of unstable +} diff --git a/src/test/compile-fail/intrinsic-return-address.rs b/src/test/compile-fail/intrinsic-return-address.rs index a80d393155..b83f0f7343 100644 --- a/src/test/compile-fail/intrinsic-return-address.rs +++ b/src/test/compile-fail/intrinsic-return-address.rs @@ -27,5 +27,3 @@ unsafe fn g() -> isize { } fn main() {} - - diff --git a/src/test/compile-fail/invalid-inline.rs b/src/test/compile-fail/invalid-inline.rs new file mode 100644 index 0000000000..ad89087d66 --- /dev/null +++ b/src/test/compile-fail/invalid-inline.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![allow(dead_code)] + +#[inline(please_no)] //~ ERROR invalid argument +fn a() { +} + +#[inline(please,no)] //~ ERROR expected one argument +fn b() { +} + +#[inline()] //~ ERROR expected one argument +fn c() { +} + +fn main() {} diff --git a/src/test/compile-fail/issue-10291.rs b/src/test/compile-fail/issue-10291.rs index 45f6e55914..9711d760ae 100644 --- a/src/test/compile-fail/issue-10291.rs +++ b/src/test/compile-fail/issue-10291.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - fn test<'x>(x: &'x isize) { - drop:: FnMut(&'z isize) -> &'z isize>>(box |z| { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { x //~^ ERROR cannot infer an appropriate lifetime - }); + })); } fn main() {} diff --git a/src/test/compile-fail/issue-10398.rs b/src/test/compile-fail/issue-10398.rs index 736f963012..08e8effc62 100644 --- a/src/test/compile-fail/issue-10398.rs +++ b/src/test/compile-fail/issue-10398.rs @@ -11,7 +11,7 @@ #![feature(box_syntax)] fn main() { - let x = box 1; + let x: Box<_> = box 1; let f = move|| { let _a = x; drop(x); diff --git a/src/test/compile-fail/issue-10536.rs b/src/test/compile-fail/issue-10536.rs index 370a6228db..3b0ea55cfa 100644 --- a/src/test/compile-fail/issue-10536.rs +++ b/src/test/compile-fail/issue-10536.rs @@ -29,4 +29,3 @@ pub fn main() { // least throw a conventional error. assert!({one! two}); } - diff --git a/src/test/compile-fail/issue-11192.rs b/src/test/compile-fail/issue-11192.rs index a95bcc73a9..7d8a1528ab 100644 --- a/src/test/compile-fail/issue-11192.rs +++ b/src/test/compile-fail/issue-11192.rs @@ -21,7 +21,7 @@ impl Drop for Foo { } fn main() { - let mut ptr = box Foo { x: 0 }; + let mut ptr: Box<_> = box Foo { x: 0 }; let mut test = |foo: &Foo| { println!("access {}", foo.x); ptr = box Foo { x: ptr.x + 1 }; @@ -30,4 +30,3 @@ fn main() { test(&*ptr); //~^ ERROR: cannot borrow `*ptr` as immutable } - diff --git a/src/test/compile-fail/issue-11374.rs b/src/test/compile-fail/issue-11374.rs index 09d7293a3d..f78786a288 100644 --- a/src/test/compile-fail/issue-11374.rs +++ b/src/test/compile-fail/issue-11374.rs @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io; +use std::io::{self, Read}; use std::vec; pub struct Container<'a> { - reader: &'a mut Reader + reader: &'a mut Read } impl<'a> Container<'a> { - pub fn wrap<'s>(reader: &'s mut Reader) -> Container<'s> { + pub fn wrap<'s>(reader: &'s mut io::Read) -> Container<'s> { Container { reader: reader } } @@ -26,8 +26,8 @@ impl<'a> Container<'a> { } pub fn for_stdin<'a>() -> Container<'a> { - let mut r = old_io::stdin(); - Container::wrap(&mut r as &mut Reader) + let mut r = io::stdin(); + Container::wrap(&mut r as &mut io::Read) } fn main() { diff --git a/src/test/compile-fail/issue-11515.rs b/src/test/compile-fail/issue-11515.rs index 4ff574e939..f682d618ab 100644 --- a/src/test/compile-fail/issue-11515.rs +++ b/src/test/compile-fail/issue-11515.rs @@ -15,6 +15,7 @@ struct Test { } fn main() { - let closure: Box = box || (); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let closure: Box = Box::new(|| ()); let test = box Test { func: closure }; //~ ERROR mismatched types } diff --git a/src/test/compile-fail/issue-11593.rs b/src/test/compile-fail/issue-11593.rs index ecc584d81b..2749438433 100644 --- a/src/test/compile-fail/issue-11593.rs +++ b/src/test/compile-fail/issue-11593.rs @@ -18,4 +18,3 @@ impl private_trait_xc::Foo for Bar {} //~^ ERROR: trait `Foo` is private fn main() {} - diff --git a/src/test/compile-fail/issue-11680.rs b/src/test/compile-fail/issue-11680.rs index 0f30243b39..1bd7b0aa1c 100644 --- a/src/test/compile-fail/issue-11680.rs +++ b/src/test/compile-fail/issue-11680.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-11680.rs +// aux-build:issue_11680.rs -extern crate "issue-11680" as other; +extern crate issue_11680 as other; fn main() { let _b = other::Foo::Bar(1); diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/compile-fail/issue-11714.rs index d307352517..998576097a 100644 --- a/src/test/compile-fail/issue-11714.rs +++ b/src/test/compile-fail/issue-11714.rs @@ -9,7 +9,7 @@ // except according to those terms. fn blah() -> i32 { //~ ERROR not all control paths return a value - 1i32 + 1 ; //~ HELP consider removing this semicolon: } diff --git a/src/test/compile-fail/issue-11771.rs b/src/test/compile-fail/issue-11771.rs index 2de86e527e..40fc6b1ed6 100644 --- a/src/test/compile-fail/issue-11771.rs +++ b/src/test/compile-fail/issue-11771.rs @@ -11,19 +11,13 @@ fn main() { let x = (); 1 + - x //~ ERROR mismatched types - //~| expected `_` - //~| found `()` - //~| expected integral variable - //~| found () + x //~^ ERROR E0277 + //~| ERROR E0277 ; let x: () = (); 1 + - x //~ ERROR mismatched types - //~| expected `_` - //~| found `()` - //~| expected integral variable - //~| found () + x //~^ ERROR E0277 + //~| ERROR E0277 ; } diff --git a/src/test/compile-fail/issue-11844.rs b/src/test/compile-fail/issue-11844.rs index 560cbe1b8a..a6dbe954ec 100644 --- a/src/test/compile-fail/issue-11844.rs +++ b/src/test/compile-fail/issue-11844.rs @@ -18,4 +18,3 @@ fn main() { None => panic!() } } - diff --git a/src/test/compile-fail/issue-11925.rs b/src/test/compile-fail/issue-11925.rs index df4dab2552..7bd072c626 100644 --- a/src/test/compile-fail/issue-11925.rs +++ b/src/test/compile-fail/issue-11925.rs @@ -14,7 +14,7 @@ fn to_fn_once>(f: F) -> F { f } fn main() { let r = { - let x = box 42; + let x: Box<_> = box 42; let f = to_fn_once(move|| &x); //~ ERROR: `x` does not live long enough f() }; diff --git a/src/test/compile-fail/issue-12041.rs b/src/test/compile-fail/issue-12041.rs index 735f529277..f0f4bf5ca7 100644 --- a/src/test/compile-fail/issue-12041.rs +++ b/src/test/compile-fail/issue-12041.rs @@ -21,4 +21,3 @@ fn main() { } }); } - diff --git a/src/test/compile-fail/issue-12127.rs b/src/test/compile-fail/issue-12127.rs index 40d446b91a..5565a9a576 100644 --- a/src/test/compile-fail/issue-12127.rs +++ b/src/test/compile-fail/issue-12127.rs @@ -14,7 +14,7 @@ fn to_fn_once>(f: F) -> F { f } fn do_it(x: &isize) { } fn main() { - let x = box 22; + let x: Box<_> = box 22; let f = to_fn_once(move|| do_it(&*x)); to_fn_once(move|| { f(); diff --git a/src/test/compile-fail/issue-12369.rs b/src/test/compile-fail/issue-12369.rs index 9a471a4341..1333bfac64 100644 --- a/src/test/compile-fail/issue-12369.rs +++ b/src/test/compile-fail/issue-12369.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { let sl = vec![1,2,3]; let v: isize = match &*sl { diff --git a/src/test/compile-fail/issue-12567.rs b/src/test/compile-fail/issue-12567.rs index d186a83676..1580ec00f9 100644 --- a/src/test/compile-fail/issue-12567.rs +++ b/src/test/compile-fail/issue-12567.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { match (l1, l2) { ([], []) => println!("both empty"), diff --git a/src/test/compile-fail/issue-12612.rs b/src/test/compile-fail/issue-12612.rs index 0550472dab..f76d12d93f 100644 --- a/src/test/compile-fail/issue-12612.rs +++ b/src/test/compile-fail/issue-12612.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-12612-1.rs +// aux-build:issue_12612_1.rs -extern crate "issue-12612-1" as foo; +extern crate issue_12612_1 as foo; use foo::bar; @@ -20,4 +20,3 @@ mod test { } fn main() {} - diff --git a/src/test/compile-fail/issue-13058.rs b/src/test/compile-fail/issue-13058.rs index 06f14158b9..8886dd80be 100644 --- a/src/test/compile-fail/issue-13058.rs +++ b/src/test/compile-fail/issue-13058.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::iter::{Range,range}; +use std::ops::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - range(min, max) + min..max } } @@ -24,7 +24,7 @@ fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool { let cont_iter = cont.iter(); //~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements - let result = cont_iter.fold(Some(0u16), |state, val| { + let result = cont_iter.fold(Some(0), |state, val| { state.map_or(None, |mask| { let bit = 1 << val; if mask & bit == 0 {Some(mask|bit)} else {None} @@ -34,10 +34,10 @@ fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool } fn main() { - check((3_usize, 5_usize)); + check((3, 5)); //~^ ERROR mismatched types //~| expected `&_` -//~| found `(usize, usize)` +//~| found `(_, _)` //~| expected &-ptr //~| found tuple } diff --git a/src/test/run-pass/issue-13352.rs b/src/test/compile-fail/issue-13352.rs similarity index 86% rename from src/test/run-pass/issue-13352.rs rename to src/test/compile-fail/issue-13352.rs index a834371203..a8c8c8b40c 100644 --- a/src/test/run-pass/issue-13352.rs +++ b/src/test/compile-fail/issue-13352.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc, libc)] + extern crate libc; use std::thunk::Thunk; @@ -19,4 +23,6 @@ fn main() { unsafe { libc::exit(0 as libc::c_int); } }); 2_usize + (loop {}); + //~^ ERROR E0277 + //~| ERROR E0277 } diff --git a/src/test/compile-fail/issue-13407.rs b/src/test/compile-fail/issue-13407.rs new file mode 100644 index 0000000000..f845eba406 --- /dev/null +++ b/src/test/compile-fail/issue-13407.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod A { + struct C; +} + +fn main() { + A::C = 1; + //~^ ERROR: illegal left-hand side expression + //~| ERROR: mismatched types +} diff --git a/src/test/compile-fail/issue-13446.rs b/src/test/compile-fail/issue-13446.rs index a0a7660428..53d1486288 100644 --- a/src/test/compile-fail/issue-13446.rs +++ b/src/test/compile-fail/issue-13446.rs @@ -16,4 +16,3 @@ static VEC: [u32; 256] = vec!(); fn main() {} - diff --git a/src/test/compile-fail/issue-13466.rs b/src/test/compile-fail/issue-13466.rs index 16128e52d6..a29a83c430 100644 --- a/src/test/compile-fail/issue-13466.rs +++ b/src/test/compile-fail/issue-13466.rs @@ -14,17 +14,17 @@ pub fn main() { // The expected arm type `Option` has one type parameter, while // the actual arm `Result` has two. typeck should not be // tricked into looking up a non-existing second type parameter. - let _x: usize = match Some(1_usize) { + let _x: usize = match Some(1) { Ok(u) => u, //~^ ERROR mismatched types - //~| expected `core::option::Option` + //~| expected `core::option::Option<_>` //~| found `core::result::Result<_, _>` //~| expected enum `core::option::Option` //~| found enum `core::result::Result` Err(e) => panic!(e) //~^ ERROR mismatched types - //~| expected `core::option::Option` + //~| expected `core::option::Option<_>` //~| found `core::result::Result<_, _>` //~| expected enum `core::option::Option` //~| found enum `core::result::Result` diff --git a/src/test/compile-fail/issue-13482-2.rs b/src/test/compile-fail/issue-13482-2.rs index 86a79416c7..f907be161f 100644 --- a/src/test/compile-fail/issue-13482-2.rs +++ b/src/test/compile-fail/issue-13482-2.rs @@ -10,6 +10,8 @@ // compile-flags:-Z verbose +#![feature(slice_patterns)] + fn main() { let x = [1,2]; let y = match x { diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs index a345ce7961..2fbfd6cc84 100644 --- a/src/test/compile-fail/issue-13482.rs +++ b/src/test/compile-fail/issue-13482.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { let x = [1,2]; let y = match x { diff --git a/src/test/compile-fail/issue-13641.rs b/src/test/compile-fail/issue-13641.rs index 3f5d29a821..51b6dc0d07 100644 --- a/src/test/compile-fail/issue-13641.rs +++ b/src/test/compile-fail/issue-13641.rs @@ -17,9 +17,9 @@ mod a { fn main() { a::Foo::new(); - //~^ ERROR: static method `new` is inaccessible + //~^ ERROR: method `new` is inaccessible //~^^ NOTE: struct `Foo` is private a::Bar::new(); - //~^ ERROR: static method `new` is inaccessible + //~^ ERROR: method `new` is inaccessible //~^^ NOTE: enum `Bar` is private } diff --git a/src/test/compile-fail/issue-13853-3.rs b/src/test/compile-fail/issue-13853-3.rs deleted file mode 100644 index 7ca158c3e3..0000000000 --- a/src/test/compile-fail/issue-13853-3.rs +++ /dev/null @@ -1,36 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "lib"] - -use std::marker::PhantomData; - -enum NodeContents<'a> { - Children(Vec>), -} - -impl<'a> Drop for NodeContents<'a> { - //~^ ERROR cannot implement a destructor on a structure with type parameters - fn drop( &mut self ) { - } -} - -struct Node<'a> { - contents: NodeContents<'a>, - marker: PhantomData<&'a ()>, -} - -impl<'a> Node<'a> { - fn noName(contents: NodeContents<'a>) -> Node<'a> { - Node { contents: contents, marker: PhantomData } - } -} - -fn main() {} diff --git a/src/test/compile-fail/issue-14092.rs b/src/test/compile-fail/issue-14092.rs index 0ab37a8882..c87dcb8ae7 100644 --- a/src/test/compile-fail/issue-14092.rs +++ b/src/test/compile-fail/issue-14092.rs @@ -11,4 +11,3 @@ fn fn1(0: Box) {} //~ ERROR: wrong number of type arguments: expected 1, found 0 fn main() {} - diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs index 74eea0c57a..ce5fa1f1fe 100644 --- a/src/test/compile-fail/issue-14254.rs +++ b/src/test/compile-fail/issue-14254.rs @@ -29,7 +29,7 @@ impl Foo for *const BarTy { baz(); //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`? a; - //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + //~^ ERROR: unresolved name `a` } } @@ -42,11 +42,11 @@ impl<'a> Foo for &'a BarTy { y; //~^ ERROR: unresolved name `y`. Did you mean `self.y`? a; - //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + //~^ ERROR: unresolved name `a` bah; //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? b; - //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`? + //~^ ERROR: unresolved name `b` } } @@ -59,11 +59,11 @@ impl<'a> Foo for &'a mut BarTy { y; //~^ ERROR: unresolved name `y`. Did you mean `self.y`? a; - //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`? + //~^ ERROR: unresolved name `a` bah; //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`? b; - //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`? + //~^ ERROR: unresolved name `b` } } diff --git a/src/test/compile-fail/issue-14845.rs b/src/test/compile-fail/issue-14845.rs index d7ff6f2fe6..3f994102a1 100644 --- a/src/test/compile-fail/issue-14845.rs +++ b/src/test/compile-fail/issue-14845.rs @@ -22,7 +22,7 @@ fn main() { //~| expected u8 //~| found array of 1 elements - let local = [0u8]; + let local: [u8; 1] = [0]; let _v = &local as *mut u8; //~^ ERROR mismatched types //~| expected `*mut u8` diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs index 8f79022405..3853434e12 100644 --- a/src/test/compile-fail/issue-15094.rs +++ b/src/test/compile-fail/issue-15094.rs @@ -16,11 +16,10 @@ struct Debuger { x: T } -impl ops::Fn<(),> for Debuger { +impl ops::FnOnce<(),> for Debuger { type Output = (); - - fn call(&self, _args: ()) { -//~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn + fn call_once(self, _args: ()) { +//~^ ERROR `call_once` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn println!("{:?}", self.x); } } diff --git a/src/test/compile-fail/issue-15381.rs b/src/test/compile-fail/issue-15381.rs index 817e4ae165..653ba165e7 100644 --- a/src/test/compile-fail/issue-15381.rs +++ b/src/test/compile-fail/issue-15381.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { let values: Vec = vec![1,2,3,4,5,6,7,8]; diff --git a/src/test/compile-fail/issue-16149.rs b/src/test/compile-fail/issue-16149.rs index a924cc9f9b..4954c95fcd 100644 --- a/src/test/compile-fail/issue-16149.rs +++ b/src/test/compile-fail/issue-16149.rs @@ -19,4 +19,3 @@ fn main() { _ => false }; } - diff --git a/src/test/compile-fail/issue-16338.rs b/src/test/compile-fail/issue-16338.rs index ba936561ae..ba369734da 100644 --- a/src/test/compile-fail/issue-16338.rs +++ b/src/test/compile-fail/issue-16338.rs @@ -18,4 +18,3 @@ fn main() { //~| expected &-ptr //~| found struct `core::raw::Slice` } - diff --git a/src/test/compile-fail/issue-16538.rs b/src/test/compile-fail/issue-16538.rs index 6d2cfcab04..a4e0f69b63 100644 --- a/src/test/compile-fail/issue-16538.rs +++ b/src/test/compile-fail/issue-16538.rs @@ -19,8 +19,7 @@ mod Y { } static foo: *const Y::X = Y::foo(Y::x as *const Y::X); -//~^ ERROR cannot refer to other statics by value -//~| ERROR the trait `core::marker::Sync` is not implemented for the type +//~^ ERROR the trait `core::marker::Sync` is not implemented for the type //~| ERROR function calls in statics are limited to struct and enum constructors fn main() {} diff --git a/src/test/compile-fail/issue-16725.rs b/src/test/compile-fail/issue-16725.rs index 218e9dba06..cadf602a4c 100644 --- a/src/test/compile-fail/issue-16725.rs +++ b/src/test/compile-fail/issue-16725.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-16725.rs +// aux-build:issue_16725.rs -extern crate "issue-16725" as foo; +extern crate issue_16725 as foo; fn main() { unsafe { foo::bar(); } //~^ ERROR: function `bar` is private } - diff --git a/src/test/compile-fail/issue-16747.rs b/src/test/compile-fail/issue-16747.rs index a213234b89..64334fe439 100644 --- a/src/test/compile-fail/issue-16747.rs +++ b/src/test/compile-fail/issue-16747.rs @@ -18,11 +18,10 @@ trait Collection { fn len(&self) -> usize; } struct List<'a, T: ListItem<'a>> { //~^ ERROR the parameter type `T` may not live long enough -//~^^ HELP consider adding an explicit lifetime bound -//~^^^ NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at +//~^^ NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at slice: &'a [T] } - +//~^ HELP consider adding an explicit lifetime bound impl<'a, T: ListItem<'a>> Collection for List<'a, T> { fn len(&self) -> usize { 0 diff --git a/src/test/compile-fail/issue-16922.rs b/src/test/compile-fail/issue-16922.rs new file mode 100644 index 0000000000..b525d5f64f --- /dev/null +++ b/src/test/compile-fail/issue-16922.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::any::Any; + +fn foo(value: &T) -> Box { + Box::new(value) as Box + //~^ ERROR: cannot infer an appropriate lifetime +} + +fn main() { + let _ = foo(&5); +} diff --git a/src/test/compile-fail/issue-17263.rs b/src/test/compile-fail/issue-17263.rs index 543063b3fc..f40d51f1d2 100644 --- a/src/test/compile-fail/issue-17263.rs +++ b/src/test/compile-fail/issue-17263.rs @@ -13,12 +13,12 @@ struct Foo { a: isize, b: isize } fn main() { - let mut x = box Foo { a: 1, b: 2 }; + let mut x: Box<_> = box Foo { a: 1, b: 2 }; let (a, b) = (&mut x.a, &mut x.b); //~^ ERROR cannot borrow `x` (here through borrowing `x.b`) as mutable more than once at a time //~^^ NOTE previous borrow of `x` occurs here (through borrowing `x.a`) - let mut foo = box Foo { a: 1, b: 2 }; + let mut foo: Box<_> = box Foo { a: 1, b: 2 }; let (c, d) = (&mut foo.a, &foo.b); //~^ ERROR cannot borrow `foo` (here through borrowing `foo.b`) as immutable //~^^ NOTE previous borrow of `foo` occurs here (through borrowing `foo.a`) diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/compile-fail/issue-17283.rs index 6573137909..a481fec6bf 100644 --- a/src/test/compile-fail/issue-17283.rs +++ b/src/test/compile-fail/issue-17283.rs @@ -16,7 +16,7 @@ struct Foo { } fn main() { - let x = 1_usize; + let x = 1; let y: Foo; // `x { ... }` should not be interpreted as a struct literal here diff --git a/src/test/compile-fail/issue-17441.rs b/src/test/compile-fail/issue-17441.rs index 321b8b260d..68ddef6718 100644 --- a/src/test/compile-fail/issue-17441.rs +++ b/src/test/compile-fail/issue-17441.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - fn main() { let _foo = &[1_usize, 2] as [usize]; //~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]` //~^^ HELP consider using an implicit coercion to `&[usize]` instead - let _bar = box 1_usize as std::fmt::Show; - //~^ ERROR cast to unsized type: `Box` as `core::fmt::Show` - //~^^ HELP did you mean `Box`? - let _baz = 1_usize as std::fmt::Show; - //~^ ERROR cast to unsized type: `usize` as `core::fmt::Show` + + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let _bar = Box::new(1_usize) as std::fmt::Debug; + //~^ ERROR cast to unsized type: `Box` as `core::fmt::Debug` + //~^^ HELP did you mean `Box`? + + let _baz = 1_usize as std::fmt::Debug; + //~^ ERROR cast to unsized type: `usize` as `core::fmt::Debug` //~^^ HELP consider using a box or reference as appropriate + let _quux = [1_usize, 2] as [usize]; //~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]` //~^^ HELP consider using a box or reference as appropriate diff --git a/src/test/compile-fail/issue-17651.rs b/src/test/compile-fail/issue-17651.rs index 172f37af83..9e49abc463 100644 --- a/src/test/compile-fail/issue-17651.rs +++ b/src/test/compile-fail/issue-17651.rs @@ -11,10 +11,8 @@ // Test that moves of unsized values within closures are caught // and rejected. -#![feature(box_syntax)] - fn main() { - (|| box *[0_usize].as_slice())(); - //~^ ERROR cannot move out of borrowed content - //~^^ ERROR cannot move a value of type [usize] + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + (|| Box::new(*(&[0][..])))(); + //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `[_]` } diff --git a/src/test/compile-fail/issue-17718-const-bad-values.rs b/src/test/compile-fail/issue-17718-const-bad-values.rs index 2347d3f3d5..6ee869d65a 100644 --- a/src/test/compile-fail/issue-17718-const-bad-values.rs +++ b/src/test/compile-fail/issue-17718-const-bad-values.rs @@ -17,4 +17,3 @@ const C2: &'static mut usize = &mut S; //~^^ ERROR: references in constants may only refer to immutable values fn main() {} - diff --git a/src/test/compile-fail/issue-17718-const-privacy.rs b/src/test/compile-fail/issue-17718-const-privacy.rs index a9af30a3ff..021edbee56 100644 --- a/src/test/compile-fail/issue-17718-const-privacy.rs +++ b/src/test/compile-fail/issue-17718-const-privacy.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-17718-const-privacy.rs +// aux-build:issue_17718_const_privacy.rs -extern crate "issue-17718-const-privacy" as other; +extern crate issue_17718_const_privacy as other; use a::B; //~ ERROR: const `B` is private use other::{ diff --git a/src/test/compile-fail/issue-17718-patterns.rs b/src/test/compile-fail/issue-17718-patterns.rs index b7f58791bf..4e63f667d2 100644 --- a/src/test/compile-fail/issue-17718-patterns.rs +++ b/src/test/compile-fail/issue-17718-patterns.rs @@ -13,7 +13,7 @@ static mut A2: usize = 1; const A3: usize = 1; fn main() { - match 1_usize { + match 1 { A1 => {} //~ ERROR: static variables cannot be referenced in a pattern A2 => {} //~ ERROR: static variables cannot be referenced in a pattern A3 => {} diff --git a/src/test/compile-fail/issue-17913.rs b/src/test/compile-fail/issue-17913.rs index 8035cffabd..80e5f2b6e2 100644 --- a/src/test/compile-fail/issue-17913.rs +++ b/src/test/compile-fail/issue-17913.rs @@ -16,13 +16,13 @@ #[cfg(target_pointer_width = "64")] fn main() { let n = 0_usize; - let a = box [&n; 0xF000000000000000_usize]; + let a: Box<_> = box [&n; 0xF000000000000000_usize]; println!("{}", a[0xFFFFFF_usize]); } #[cfg(target_pointer_width = "32")] fn main() { let n = 0_usize; - let a = box [&n; 0xFFFFFFFF_usize]; + let a: Box<_> = box [&n; 0xFFFFFFFF_usize]; println!("{}", a[0xFFFFFF_usize]); } diff --git a/src/test/compile-fail/issue-17933.rs b/src/test/compile-fail/issue-17933.rs index bd04740849..657b31fa83 100644 --- a/src/test/compile-fail/issue-17933.rs +++ b/src/test/compile-fail/issue-17933.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub static X: usize = 1_usize; +pub static X: usize = 1; fn main() { - match 1_usize { + match 1 { self::X => { }, //~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead _ => { }, diff --git a/src/test/compile-fail/issue-18107.rs b/src/test/compile-fail/issue-18107.rs index d5fb22bdeb..60ab616d59 100644 --- a/src/test/compile-fail/issue-18107.rs +++ b/src/test/compile-fail/issue-18107.rs @@ -16,7 +16,7 @@ fn _create_render(_: &()) -> AbstractRenderer //~^ ERROR: the trait `core::marker::Sized` is not implemented { - match 0_usize { + match 0 { _ => unimplemented!() } } diff --git a/src/test/compile-fail/issue-18252.rs b/src/test/compile-fail/issue-18252.rs index 54c51405bd..e3e56c7f97 100644 --- a/src/test/compile-fail/issue-18252.rs +++ b/src/test/compile-fail/issue-18252.rs @@ -13,5 +13,5 @@ enum Foo { } fn main() { - let f = Foo::Variant(42_usize); //~ ERROR uses it like a function + let f = Foo::Variant(42); //~ ERROR uses it like a function } diff --git a/src/test/compile-fail/issue-18389.rs b/src/test/compile-fail/issue-18389.rs index 20323e9900..271c31bd37 100644 --- a/src/test/compile-fail/issue-18389.rs +++ b/src/test/compile-fail/issue-18389.rs @@ -12,16 +12,16 @@ use std::any::Any; use std::any::TypeId; +use std::marker::MarkerTrait; -pub trait Pt {} -pub trait Rt {} +pub trait Pt : MarkerTrait {} +pub trait Rt : MarkerTrait {} trait Private { fn call(&self, p: P, r: R); } -pub trait Public: Private< +pub trait Public: Private< //~ ERROR private trait in exported type parameter bound ::P, -//~^ ERROR illegal recursive type; insert an enum or struct in the cycle, if this is desired ::R > { type P; diff --git a/src/test/compile-fail/issue-18400.rs b/src/test/compile-fail/issue-18400.rs index 015f1fa603..f8d85f9393 100644 --- a/src/test/compile-fail/issue-18400.rs +++ b/src/test/compile-fail/issue-18400.rs @@ -33,7 +33,4 @@ fn main() { 0.contains(bits); //~^ ERROR overflow - //~| ERROR overflow - //~| ERROR overflow - //~| ERROR mismatched types } diff --git a/src/test/compile-fail/issue-18566.rs b/src/test/compile-fail/issue-18566.rs index dd3844b1a0..41e82d0cd8 100644 --- a/src/test/compile-fail/issue-18566.rs +++ b/src/test/compile-fail/issue-18566.rs @@ -28,7 +28,7 @@ impl Tr for usize { } fn main() { - let s = &mut 1_usize; + let s = &mut 1; MyPtr(s).poke(s); //~^ ERROR cannot borrow `*s` as mutable more than once at a time diff --git a/src/test/compile-fail/issue-18783.rs b/src/test/compile-fail/issue-18783.rs index 13908bda9d..5eb3c439df 100644 --- a/src/test/compile-fail/issue-18783.rs +++ b/src/test/compile-fail/issue-18783.rs @@ -8,24 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - use std::cell::RefCell; +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + fn main() { - let mut y = 1_usize; + let mut y = 1; let c = RefCell::new(vec![]); - c.push(box || y = 0); - c.push(box || y = 0); + c.push(Box::new(|| y = 0)); + c.push(Box::new(|| y = 0)); //~^ ERROR cannot borrow `y` as mutable more than once at a time } fn ufcs() { - let mut y = 1_usize; + let mut y = 1; let c = RefCell::new(vec![]); - Push::push(&c, box || y = 0); - Push::push(&c, box || y = 0); + Push::push(&c, Box::new(|| y = 0)); + Push::push(&c, Box::new(|| y = 0)); //~^ ERROR cannot borrow `y` as mutable more than once at a time } diff --git a/src/test/compile-fail/issue-18919.rs b/src/test/compile-fail/issue-18919.rs new file mode 100644 index 0000000000..8c2c52e6fa --- /dev/null +++ b/src/test/compile-fail/issue-18919.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type FuncType<'f> = Fn(&isize) -> isize + 'f; + +fn ho_func(f: Option) { + //~^ ERROR: the trait `core::marker::Sized` is not implemented for the type +} + +fn main() {} diff --git a/src/test/compile-fail/issue-18959.rs b/src/test/compile-fail/issue-18959.rs index 368f3c16f5..ebda248180 100644 --- a/src/test/compile-fail/issue-18959.rs +++ b/src/test/compile-fail/issue-18959.rs @@ -17,7 +17,11 @@ impl Foo for Thing { fn foo(&self, _: &T) {} } -#[inline(never)] fn foo(b: &Bar) { b.foo(&0_usize) } +#[inline(never)] +fn foo(b: &Bar) { + b.foo(&0) + //~^ ERROR the trait `Foo` is not implemented for the type `Bar` +} fn main() { let mut thing = Thing; diff --git a/src/test/compile-fail/issue-19244-1.rs b/src/test/compile-fail/issue-19244-1.rs index 0850705aee..5c11787d46 100644 --- a/src/test/compile-fail/issue-19244-1.rs +++ b/src/test/compile-fail/issue-19244-1.rs @@ -12,5 +12,7 @@ const TUP: (usize,) = (42,); fn main() { let a: [isize; TUP.1]; - //~^ ERROR expected constant expr for array length: tuple index out of bounds + //~^ ERROR array length constant evaluation error: tuple index out of bounds + //~| ERROR attempted out-of-bounds tuple index + //~| ERROR attempted out-of-bounds tuple index } diff --git a/src/test/compile-fail/issue-19244-2.rs b/src/test/compile-fail/issue-19244-2.rs index 93a3fc87eb..d896f76865 100644 --- a/src/test/compile-fail/issue-19244-2.rs +++ b/src/test/compile-fail/issue-19244-2.rs @@ -13,5 +13,7 @@ const STRUCT: MyStruct = MyStruct { field: 42 }; fn main() { let a: [isize; STRUCT.nonexistent_field]; - //~^ ERROR expected constant expr for array length: nonexistent struct field + //~^ ERROR array length constant evaluation error: nonexistent struct field + //~| ERROR attempted access of field `nonexistent_field` + //~| ERROR attempted access of field `nonexistent_field` } diff --git a/src/test/compile-fail/issue-19660.rs b/src/test/compile-fail/issue-19660.rs index 77aba7335b..4435ee0cb2 100644 --- a/src/test/compile-fail/issue-19660.rs +++ b/src/test/compile-fail/issue-19660.rs @@ -21,6 +21,6 @@ impl PhantomFn for U { } trait Sized : PhantomFn {} #[start] -fn main(_: int, _: *const *const u8) -> int { +fn main(_: isize, _: *const *const u8) -> isize { 0 } diff --git a/src/test/compile-fail/issue-19883.rs b/src/test/compile-fail/issue-19883.rs index bbc5ee6c8f..c6ff82364b 100644 --- a/src/test/compile-fail/issue-19883.rs +++ b/src/test/compile-fail/issue-19883.rs @@ -15,18 +15,11 @@ trait From { } trait To { - // This is a typo, the return type should be `>::Output` - fn to>( - self - //~^ error: the trait `core::marker::Sized` is not implemented - ) -> + fn to>(self) -> >::Dst - //~^ error: the trait `core::marker::Sized` is not implemented + //~^ ERROR use of undeclared associated type `From::Dst` { - From::from( - //~^ error: the trait `core::marker::Sized` is not implemented - self - ) + From::from(self) } } diff --git a/src/test/compile-fail/issue-19982.rs b/src/test/compile-fail/issue-19982.rs new file mode 100644 index 0000000000..9dbca99734 --- /dev/null +++ b/src/test/compile-fail/issue-19982.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +struct Foo; + +impl Fn<(&(),)> for Foo { } //~ ERROR missing lifetime specifier + +fn main() {} diff --git a/src/test/compile-fail/issue-19991.rs b/src/test/compile-fail/issue-19991.rs index 2d73b98ec1..6c9b0004f7 100644 --- a/src/test/compile-fail/issue-19991.rs +++ b/src/test/compile-fail/issue-19991.rs @@ -14,9 +14,9 @@ fn main() { if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause //~| expected `()` - //~| found `i32` + //~| found `_` //~| expected () - //~| found i32 - 765i32 + //~| found integral variable + 765 }; } diff --git a/src/test/compile-fail/issue-20225.rs b/src/test/compile-fail/issue-20225.rs new file mode 100644 index 0000000000..fe427e0245 --- /dev/null +++ b/src/test/compile-fail/issue-20225.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +struct Foo; + +impl<'a, T> Fn<(&'a T,)> for Foo { + extern "rust-call" fn call(&self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait: expected &-ptr +} + +impl<'a, T> FnMut<(&'a T,)> for Foo { + extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait: expected &-ptr +} + +impl<'a, T> FnOnce<(&'a T,)> for Foo { + type Output = (); + + extern "rust-call" fn call_once(self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait: expected &-ptr +} + +fn main() {} diff --git a/src/test/compile-fail/issue-20261.rs b/src/test/compile-fail/issue-20261.rs new file mode 100644 index 0000000000..33e00f9a82 --- /dev/null +++ b/src/test/compile-fail/issue-20261.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + for (ref i,) in [].iter() { //~ ERROR: type mismatch resolving + i.clone(); + //~^ ERROR: the type of this value must be known in this context + //~| ERROR: reached the recursion limit while auto-dereferencing + } +} diff --git a/src/test/compile-fail/issue-20714.rs b/src/test/compile-fail/issue-20714.rs new file mode 100644 index 0000000000..cb322f0072 --- /dev/null +++ b/src/test/compile-fail/issue-20714.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct G; + +fn main() { + let g = G(); //~ ERROR: expected function, found `G` +} diff --git a/src/test/compile-fail/issue-20801.rs b/src/test/compile-fail/issue-20801.rs index 929c8ec0fd..fe7807042e 100644 --- a/src/test/compile-fail/issue-20801.rs +++ b/src/test/compile-fail/issue-20801.rs @@ -25,11 +25,11 @@ fn mut_ref() -> &'static mut T { } fn mut_ptr() -> *mut T { - unsafe { 0u8 as *mut T } + unsafe { 0 as *mut T } } fn const_ptr() -> *const T { - unsafe { 0u8 as *const T } + unsafe { 0 as *const T } } pub fn main() { diff --git a/src/test/compile-fail/issue-21202.rs b/src/test/compile-fail/issue-21202.rs index 5c1de6dfc5..2bce838c1c 100644 --- a/src/test/compile-fail/issue-21202.rs +++ b/src/test/compile-fail/issue-21202.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-21202.rs +// aux-build:issue_21202.rs -extern crate "issue-21202" as crate1; +extern crate issue_21202 as crate1; use crate1::A; @@ -18,7 +18,7 @@ mod B { use crate1::A::Foo; fn bar(f: Foo) { Foo::foo(&f); - //~^ ERROR: function `foo` is private + //~^ ERROR: method `foo` is private } } diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index 37dbcaf39b..ea305c96af 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -16,7 +16,8 @@ impl vec_monad for Vec { fn bind(&self, mut f: F) where F: FnMut(A) -> Vec { let mut r = panic!(); for elt in self { r = r + f(*elt); } - //~^ ERROR binary operation `+` cannot be applied to type `collections::vec::Vec` + //~^ ERROR E0277 + //~| ERROR E0277 } } fn main() { diff --git a/src/test/compile-fail/issue-2150.rs b/src/test/compile-fail/issue-2150.rs index 505885e6c4..8b109b0a5c 100644 --- a/src/test/compile-fail/issue-2150.rs +++ b/src/test/compile-fail/issue-2150.rs @@ -15,7 +15,7 @@ fn fail_len(v: Vec ) -> usize { let mut i = 3; panic!(); - for x in &v { i += 1_usize; } + for x in &v { i += 1; } //~^ ERROR: unreachable statement return i; } diff --git a/src/test/compile-fail/issue-22426-1.rs b/src/test/compile-fail/issue-22426-1.rs new file mode 100644 index 0000000000..f026a5db55 --- /dev/null +++ b/src/test/compile-fail/issue-22426-1.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match 42 { + x < 7 => (), + //~^ error: unexpected token: `<` + _ => () + } +} diff --git a/src/test/compile-fail/issue-22426-2.rs b/src/test/compile-fail/issue-22426-2.rs new file mode 100644 index 0000000000..ea5180e3ee --- /dev/null +++ b/src/test/compile-fail/issue-22426-2.rs @@ -0,0 +1,12 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn a(B<) {} + //~^ error: unexpected token: `<` diff --git a/src/test/compile-fail/issue-22426-3.rs b/src/test/compile-fail/issue-22426-3.rs new file mode 100644 index 0000000000..2e0b5d6b80 --- /dev/null +++ b/src/test/compile-fail/issue-22426-3.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo(T, T); + +impl Foo { + fn foo(&self) { + match *self { + Foo(x, y) => { + //~^ error: unexpected token: `<` + println!("Goodbye, World!") + } + } + } +} diff --git a/src/test/compile-fail/issue-22912.rs b/src/test/compile-fail/issue-22912.rs new file mode 100644 index 0000000000..f4536ceb8e --- /dev/null +++ b/src/test/compile-fail/issue-22912.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct PublicType; +struct PrivateType; + +pub trait PublicTrait { + type Item; +} + +trait PrivateTrait { + type Item; +} + +impl PublicTrait for PublicType { + type Item = PrivateType; //~ ERROR private type in exported type signature +} + +// OK +impl PublicTrait for PrivateType { + type Item = PrivateType; +} + +// OK +impl PrivateTrait for PublicType { + type Item = PrivateType; +} + +// OK +impl PrivateTrait for PrivateType { + type Item = PrivateType; +} + +fn main() {} diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs new file mode 100644 index 0000000000..ff5ac9de8d --- /dev/null +++ b/src/test/compile-fail/issue-23080-2.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +unsafe trait Trait: MarkerTrait { +//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items + type Output; +} + +unsafe impl Trait for .. {} + +fn call_method(x: T) {} + +fn main() { + // ICE + call_method(()); +} diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs new file mode 100644 index 0000000000..99373a6969 --- /dev/null +++ b/src/test/compile-fail/issue-23080.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +unsafe trait Trait { +//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items + fn method(&self) { + println!("Hello"); + } +} + +unsafe impl Trait for .. {} + +fn call_method(x: T) { + x.method(); +} + +fn main() { + // ICE + call_method(()); +} diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs index f0ae0eb59f..48cc27e228 100644 --- a/src/test/compile-fail/issue-2356.rs +++ b/src/test/compile-fail/issue-2356.rs @@ -36,7 +36,7 @@ impl Groom for cat { shave(4); //~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`? purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` } } @@ -45,13 +45,13 @@ impl cat { fn purr_louder() { static_method(); - //~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method` + //~^ ERROR: unresolved name `static_method` purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` purr(); - //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`? + //~^ ERROR: unresolved name `purr` } } @@ -65,7 +65,7 @@ impl cat { fn purr(&self) { grow_older(); - //~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older` + //~^ ERROR: unresolved name `grow_older` shave(); //~^ ERROR: unresolved name `shave` } @@ -79,7 +79,7 @@ impl cat { whiskers = 4; //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`? purr_louder(); - //~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder` + //~^ ERROR: unresolved name `purr_louder` } } diff --git a/src/test/compile-fail/issue-3008-2.rs b/src/test/compile-fail/issue-3008-2.rs index 1e8f81a05e..c744dff0c0 100644 --- a/src/test/compile-fail/issue-3008-2.rs +++ b/src/test/compile-fail/issue-3008-2.rs @@ -15,4 +15,3 @@ struct bar { x: bar } fn main() { } - diff --git a/src/test/compile-fail/issue-3521-2.rs b/src/test/compile-fail/issue-3521-2.rs index 678618d721..ad5bc4e445 100644 --- a/src/test/compile-fail/issue-3521-2.rs +++ b/src/test/compile-fail/issue-3521-2.rs @@ -11,7 +11,9 @@ fn main() { let foo = 100; - static y: isize = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant + static y: isize = foo + 1; + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `foo` println!("{}", y); } diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs index c49959c16a..f06aa45ac3 100644 --- a/src/test/compile-fail/issue-3521.rs +++ b/src/test/compile-fail/issue-3521.rs @@ -13,7 +13,9 @@ fn main() { #[derive(Debug)] enum Stuff { - Bar = foo //~ ERROR attempt to use a non-constant value in a constant + Bar = foo + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `foo` } println!("{}", Stuff::Bar); diff --git a/src/test/compile-fail/issue-3668-2.rs b/src/test/compile-fail/issue-3668-2.rs index 0577b15272..a09c8090de 100644 --- a/src/test/compile-fail/issue-3668-2.rs +++ b/src/test/compile-fail/issue-3668-2.rs @@ -9,7 +9,9 @@ // except according to those terms. fn f(x:isize) { - static child: isize = x + 1; //~ ERROR attempt to use a non-constant value in a constant + static child: isize = x + 1; + //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `x` } fn main() {} diff --git a/src/test/compile-fail/issue-3668.rs b/src/test/compile-fail/issue-3668.rs index 9c31dc1e38..9b7476244f 100644 --- a/src/test/compile-fail/issue-3668.rs +++ b/src/test/compile-fail/issue-3668.rs @@ -17,6 +17,7 @@ impl PTrait for P { fn getChildOption(&self) -> Option> { static childVal: Box
    ' has overflowed its stack struct R { - b: int, + b: isize, } impl Drop for R { diff --git a/src/test/run-fail/issue-23354-2.rs b/src/test/run-fail/issue-23354-2.rs new file mode 100644 index 0000000000..b120d3222f --- /dev/null +++ b/src/test/run-fail/issue-23354-2.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:panic evaluated + +#[allow(unused_variables)] +fn main() { + // This used to trigger an LLVM assertion during compilation + let x = [panic!("panic evaluated"); 2]; +} diff --git a/src/test/run-fail/issue-23354.rs b/src/test/run-fail/issue-23354.rs new file mode 100644 index 0000000000..f6b937c825 --- /dev/null +++ b/src/test/run-fail/issue-23354.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:panic evaluated + +#[allow(unused_variables)] +fn main() { + let x = [panic!("panic evaluated"); 0]; +} diff --git a/src/test/run-fail/issue-2444.rs b/src/test/run-fail/issue-2444.rs index 2b20540501..ce91af95d9 100644 --- a/src/test/run-fail/issue-2444.rs +++ b/src/test/run-fail/issue-2444.rs @@ -14,7 +14,7 @@ use std::sync::Arc; enum e { ee(Arc) } -fn foo() -> e {panic!();} +fn foo() -> e {panic!();} fn main() { let _f = foo(); diff --git a/src/test/run-fail/issue-948.rs b/src/test/run-fail/issue-948.rs index e51e8d93eb..272d85d7b5 100644 --- a/src/test/run-fail/issue-948.rs +++ b/src/test/run-fail/issue-948.rs @@ -12,7 +12,7 @@ #![allow(unused_variables)] -struct Point { x: int, y: int } +struct Point { x: isize, y: isize } fn main() { let origin = Point {x: 0, y: 0}; diff --git a/src/test/run-fail/match-bot-panic.rs b/src/test/run-fail/match-bot-panic.rs index 2b1672ad4e..c1f90bb8f2 100644 --- a/src/test/run-fail/match-bot-panic.rs +++ b/src/test/run-fail/match-bot-panic.rs @@ -17,6 +17,6 @@ fn foo(s: String) { } fn main() { let i = - match Some::(3) { None:: => { panic!() } Some::(_) => { panic!() } }; + match Some::(3) { None:: => { panic!() } Some::(_) => { panic!() } }; foo(i); } diff --git a/src/test/run-fail/match-disc-bot.rs b/src/test/run-fail/match-disc-bot.rs index da08f53fcd..90b729a6dd 100644 --- a/src/test/run-fail/match-disc-bot.rs +++ b/src/test/run-fail/match-disc-bot.rs @@ -10,5 +10,5 @@ // error-pattern:quux fn f() -> ! { panic!("quux") } -fn g() -> int { match f() { true => { 1 } false => { 0 } } } +fn g() -> isize { match f() { true => { 1 } false => { 0 } } } fn main() { g(); } diff --git a/src/test/run-fail/match-wildcards.rs b/src/test/run-fail/match-wildcards.rs index 5c1a9e1a5e..54e24de316 100644 --- a/src/test/run-fail/match-wildcards.rs +++ b/src/test/run-fail/match-wildcards.rs @@ -9,7 +9,7 @@ // except according to those terms. // error-pattern:squirrelcupcake -fn cmp() -> int { +fn cmp() -> isize { match (Some('a'), None::) { (Some(_), _) => { panic!("squirrelcupcake"); } (_, Some(_)) => { panic!(); } diff --git a/src/test/run-fail/overflowing-add.rs b/src/test/run-fail/overflowing-add.rs new file mode 100644 index 0000000000..cd13b817c2 --- /dev/null +++ b/src/test/run-fail/overflowing-add.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'arithmetic operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn value() -> u8 { 200 } + +fn main() { + let _x = value() + value() + value(); +} diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs new file mode 100644 index 0000000000..5415915338 --- /dev/null +++ b/src/test/run-fail/overflowing-lsh-1.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + let _x = 1_i32 << id(32); +} diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs new file mode 100644 index 0000000000..fd3e801457 --- /dev/null +++ b/src/test/run-fail/overflowing-lsh-2.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + let _x = 1 << id(-1); +} diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs new file mode 100644 index 0000000000..58914bab3f --- /dev/null +++ b/src/test/run-fail/overflowing-lsh-3.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + let _x = 1_u64 << id(64); +} diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs new file mode 100644 index 0000000000..ed25876cec --- /dev/null +++ b/src/test/run-fail/overflowing-lsh-4.rs @@ -0,0 +1,34 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// This function is checking that our automatic truncation does not +// sidestep the overflow checking. + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + // this signals overflow when checking is on + let x = 1_i8 << id(17); + + // ... but when checking is off, the fallback will truncate the + // input to its lower three bits (= 1). Note that this is *not* + // the behavior of the x86 processor for 8- and 16-bit types, + // but it is necessary to avoid undefined behavior from LLVM. + // + // We check that here, by ensuring the result has only been + // shifted by one place; if overflow checking is turned off, then + // this assertion will pass (and the compiletest driver will + // report that the test did not produce the error expected above). + assert_eq!(x, 2_i8); +} diff --git a/src/test/run-fail/overflowing-mul.rs b/src/test/run-fail/overflowing-mul.rs new file mode 100644 index 0000000000..5d2f539624 --- /dev/null +++ b/src/test/run-fail/overflowing-mul.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'arithmetic operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn value() -> u8 { 200 } + +fn main() { + let x = value() * 4; +} diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs new file mode 100644 index 0000000000..c36a16f18f --- /dev/null +++ b/src/test/run-fail/overflowing-rsh-1.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + let _x = -1_i32 >> id(32); +} diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs new file mode 100644 index 0000000000..f619ebe9fb --- /dev/null +++ b/src/test/run-fail/overflowing-rsh-2.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + let _x = -1_i32 >> id(-1); +} diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs new file mode 100644 index 0000000000..c261e195fd --- /dev/null +++ b/src/test/run-fail/overflowing-rsh-3.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + let _x = -1_i64 >> id(64); +} diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs new file mode 100644 index 0000000000..6e79a13d4e --- /dev/null +++ b/src/test/run-fail/overflowing-rsh-4.rs @@ -0,0 +1,34 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'shift operation overflowed' +// compile-flags: -C debug-assertions + +// This function is checking that our (type-based) automatic +// truncation does not sidestep the overflow checking. + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + // this signals overflow when checking is on + let x = 2_i8 >> id(17); + + // ... but when checking is off, the fallback will truncate the + // input to its lower three bits (= 1). Note that this is *not* + // the behavior of the x86 processor for 8- and 16-bit types, + // but it is necessary to avoid undefined behavior from LLVM. + // + // We check that here, by ensuring the result is not zero; if + // overflow checking is turned off, then this assertion will pass + // (and the compiletest driver will report that the test did not + // produce the error expected above). + assert_eq!(x, 1_i8); +} diff --git a/src/test/run-fail/overflowing-sub.rs b/src/test/run-fail/overflowing-sub.rs new file mode 100644 index 0000000000..b089dccbaa --- /dev/null +++ b/src/test/run-fail/overflowing-sub.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern:thread '
    ' panicked at 'arithmetic operation overflowed' +// compile-flags: -C debug-assertions + +// (Work around constant-evaluation) +fn value() -> u8 { 42 } + +fn main() { + let _x = value() - (value() + 1); +} diff --git a/src/test/run-fail/panic-arg.rs b/src/test/run-fail/panic-arg.rs index 4d4f931751..0e029b6ecb 100644 --- a/src/test/run-fail/panic-arg.rs +++ b/src/test/run-fail/panic-arg.rs @@ -9,6 +9,6 @@ // except according to those terms. // error-pattern:woe -fn f(a: int) { println!("{}", a); } +fn f(a: isize) { println!("{}", a); } fn main() { f(panic!("woe")); } diff --git a/src/test/run-fail/panic-macro-any-wrapped.rs b/src/test/run-fail/panic-macro-any-wrapped.rs index 89e47bf46a..4d0f7c29cb 100644 --- a/src/test/run-fail/panic-macro-any-wrapped.rs +++ b/src/test/run-fail/panic-macro-any-wrapped.rs @@ -10,9 +10,6 @@ // error-pattern:panicked at 'Box' -#![allow(unknown_features)] -#![feature(box_syntax)] - fn main() { - panic!(box 612_i64); + panic!(Box::new(612_i64)); } diff --git a/src/test/run-fail/result-get-panic.rs b/src/test/run-fail/result-get-panic.rs index df14efd6c3..dbded10754 100644 --- a/src/test/run-fail/result-get-panic.rs +++ b/src/test/run-fail/result-get-panic.rs @@ -13,5 +13,5 @@ use std::result::Result::Err; fn main() { - println!("{}", Err::("kitty".to_string()).unwrap()); + println!("{}", Err::("kitty".to_string()).unwrap()); } diff --git a/src/test/run-fail/rt-set-exit-status-panic.rs b/src/test/run-fail/rt-set-exit-status-panic.rs index fd7c3f8cc0..249e2e1ac2 100644 --- a/src/test/run-fail/rt-set-exit-status-panic.rs +++ b/src/test/run-fail/rt-set-exit-status-panic.rs @@ -10,14 +10,16 @@ // error-pattern:whatever +#![feature(exit_status, rustc_private)] + #[macro_use] extern crate log; -use std::os; +use std::env; fn main() { error!("whatever"); // Setting the exit status only works when the scheduler terminates // normally. In this case we're going to panic, so instead of // returning 50 the process will return the typical rt failure code. - os::set_exit_status(50); + env::set_exit_status(50); panic!(); } diff --git a/src/test/run-fail/rt-set-exit-status-panic2.rs b/src/test/run-fail/rt-set-exit-status-panic2.rs index 775d38c8b3..fddff3c5a9 100644 --- a/src/test/run-fail/rt-set-exit-status-panic2.rs +++ b/src/test/run-fail/rt-set-exit-status-panic2.rs @@ -10,12 +10,14 @@ // error-pattern:whatever +#![feature(exit_status, rustc_private)] + #[macro_use] extern crate log; -use std::os; +use std::env; use std::thread; struct r { - x:int, + x:isize, } // Setting the exit status after the runtime has already @@ -23,11 +25,11 @@ struct r { // runtime's exit code impl Drop for r { fn drop(&mut self) { - os::set_exit_status(50); + env::set_exit_status(50); } } -fn r(x:int) -> r { +fn r(x:isize) -> r { r { x: x } @@ -35,7 +37,7 @@ fn r(x:int) -> r { fn main() { error!("whatever"); - let _t = thread::spawn(move|| { + let _t = thread::scoped(move|| { let _i = r(5); }); panic!(); diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs index 39ece8a464..c33a8d2d03 100644 --- a/src/test/run-fail/rt-set-exit-status.rs +++ b/src/test/run-fail/rt-set-exit-status.rs @@ -10,12 +10,14 @@ // error-pattern:whatever +#![feature(rustc_private, exit_status)] + #[macro_use] extern crate log; -use std::os; +use std::env; fn main() { error!("whatever"); // 101 is the code the runtime uses on task panic and the value // compiletest expects run-fail tests to return. - os::set_exit_status(101); + env::set_exit_status(101); } diff --git a/src/test/run-fail/test-should-fail-bad-message.rs b/src/test/run-fail/test-should-fail-bad-message.rs index 5a5bb53a33..e18c5d9631 100644 --- a/src/test/run-fail/test-should-fail-bad-message.rs +++ b/src/test/run-fail/test-should-fail-bad-message.rs @@ -14,7 +14,7 @@ // ignore-pretty: does not work well with `--test` #[test] -#[should_fail(expected = "foobar")] +#[should_panic(expected = "foobar")] fn test_foo() { panic!("blah") } diff --git a/src/test/run-fail/test-tasks-invalid-value.rs b/src/test/run-fail/test-tasks-invalid-value.rs index 8c9cd2d63c..94ed641c79 100644 --- a/src/test/run-fail/test-tasks-invalid-value.rs +++ b/src/test/run-fail/test-tasks-invalid-value.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// This checks that RUST_TEST_TASKS not being 1, 2, ... is detected +// This checks that RUST_TEST_THREADS not being 1, 2, ... is detected // properly. // error-pattern:should be a positive integer // compile-flags: --test -// exec-env:RUST_TEST_TASKS=foo +// exec-env:RUST_TEST_THREADS=foo // ignore-pretty: does not work well with `--test` #[test] diff --git a/src/test/run-fail/unique-panic.rs b/src/test/run-fail/unique-panic.rs index 9f643c0979..83b2bb91f0 100644 --- a/src/test/run-fail/unique-panic.rs +++ b/src/test/run-fail/unique-panic.rs @@ -10,7 +10,4 @@ // error-pattern: panic -#![allow(unknown_features)] -#![feature(box_syntax)] - -fn main() { box panic!(); } +fn main() { Box::new(panic!()); } diff --git a/src/test/run-fail/unwind-rec.rs b/src/test/run-fail/unwind-rec.rs index 1c72686b60..6df279b047 100644 --- a/src/test/run-fail/unwind-rec.rs +++ b/src/test/run-fail/unwind-rec.rs @@ -11,11 +11,11 @@ // error-pattern:fail -fn build() -> Vec { +fn build() -> Vec { panic!(); } -struct Blk { node: Vec } +struct Blk { node: Vec } fn main() { let _blk = Blk { diff --git a/src/test/run-fail/unwind-rec2.rs b/src/test/run-fail/unwind-rec2.rs index 943b4cd767..d5d60d1892 100644 --- a/src/test/run-fail/unwind-rec2.rs +++ b/src/test/run-fail/unwind-rec2.rs @@ -11,15 +11,15 @@ // error-pattern:fail -fn build1() -> Vec { +fn build1() -> Vec { vec!(0,0,0,0,0,0,0) } -fn build2() -> Vec { +fn build2() -> Vec { panic!(); } -struct Blk { node: Vec , span: Vec } +struct Blk { node: Vec , span: Vec } fn main() { let _blk = Blk { diff --git a/src/test/run-fail/unwind-unique.rs b/src/test/run-fail/unwind-unique.rs index e1176b1bcd..f4ba789d6b 100644 --- a/src/test/run-fail/unwind-unique.rs +++ b/src/test/run-fail/unwind-unique.rs @@ -10,14 +10,11 @@ // error-pattern:fail -#![allow(unknown_features)] -#![feature(box_syntax)] - fn failfn() { panic!(); } fn main() { - box 0; + Box::new(0); failfn(); } diff --git a/src/test/run-fail/vec-overrun.rs b/src/test/run-fail/vec-overrun.rs index c378e852f8..da52cd56a1 100644 --- a/src/test/run-fail/vec-overrun.rs +++ b/src/test/run-fail/vec-overrun.rs @@ -12,8 +12,8 @@ fn main() { - let v: Vec = vec!(10); - let x: uint = 0; + let v: Vec = vec!(10); + let x: usize = 0; assert_eq!(v[x], 10); // Bounds-check panic. diff --git a/src/test/run-fail/while-body-panics.rs b/src/test/run-fail/while-body-panics.rs index 6a7d0a1d73..cfe499f8a4 100644 --- a/src/test/run-fail/while-body-panics.rs +++ b/src/test/run-fail/while-body-panics.rs @@ -11,4 +11,4 @@ #![allow(while_true)] // error-pattern:quux -fn main() { let _x: int = { while true { panic!("quux"); } ; 8 } ; } +fn main() { let _x: isize = { while true { panic!("quux"); } ; 8 } ; } diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile b/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile index 961342591a..c14006cc2e 100644 --- a/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile +++ b/src/test/run-make/allow-non-lint-warnings-cmdline/Makefile @@ -9,4 +9,3 @@ all: foo # This is just to make sure the above command actually succeeds foo: $(RUSTC) foo.rs -A warnings - diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs b/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs index 19ce5d0a7c..a9e18f5a8f 100644 --- a/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs +++ b/src/test/run-make/allow-non-lint-warnings-cmdline/foo.rs @@ -9,7 +9,7 @@ // except according to those terms. #[derive()] -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Foo; pub fn main() { } diff --git a/src/test/run-make/allow-warnings-cmdline-stability/Makefile b/src/test/run-make/allow-warnings-cmdline-stability/Makefile index 64b7f58cae..3eecaf9314 100644 --- a/src/test/run-make/allow-warnings-cmdline-stability/Makefile +++ b/src/test/run-make/allow-warnings-cmdline-stability/Makefile @@ -13,7 +13,3 @@ bar: foo: bar $(RUSTC) foo.rs -A warnings - - - - diff --git a/src/test/run-make/allow-warnings-cmdline-stability/foo.rs b/src/test/run-make/allow-warnings-cmdline-stability/foo.rs index fb23a21401..a36cc474c2 100644 --- a/src/test/run-make/allow-warnings-cmdline-stability/foo.rs +++ b/src/test/run-make/allow-warnings-cmdline-stability/foo.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(test_feature)] + extern crate bar; pub fn main() { bar::baz() } diff --git a/src/test/run-make/bare-outfile/Makefile b/src/test/run-make/bare-outfile/Makefile new file mode 100644 index 0000000000..97d09c837c --- /dev/null +++ b/src/test/run-make/bare-outfile/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(rustc) -o foo foo.rs diff --git a/src/test/run-make/bare-outfile/foo.rs b/src/test/run-make/bare-outfile/foo.rs new file mode 100644 index 0000000000..63e747901a --- /dev/null +++ b/src/test/run-make/bare-outfile/foo.rs @@ -0,0 +1,12 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { +} diff --git a/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs b/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs index 89352a16d8..02af5244b8 100644 --- a/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs +++ b/src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs @@ -8,8 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(old_io, old_path)] + use std::env; -use std::old_io::{File, Command}; +use std::fs::File; +use std::process::Command; +use std::io::Write; +use std::path::Path; // creates broken.rs, which has the Ident \x00name_0,ctxt_0\x00 // embedded within it, and then attempts to compile broken.rs with the @@ -22,21 +27,18 @@ fn main() { let main_file = tmpdir.join("broken.rs"); let _ = File::create(&main_file).unwrap() - .write_str("pub fn main() { + .write_all(b"pub fn main() { let \x00name_0,ctxt_0\x00 = 3; println!(\"{}\", \x00name_0,ctxt_0\x00); - }"); + }").unwrap(); // rustc is passed to us with --out-dir and -L etc., so we // can't exec it directly let result = Command::new("sh") .arg("-c") - .arg(&format!("{} {}", - rustc, - main_file.as_str() - .unwrap())) + .arg(&format!("{} {}", rustc, main_file.display())) .output().unwrap(); - let err = String::from_utf8_lossy(&result.error); + let err = String::from_utf8_lossy(&result.stderr); // positive test so that this test will be updated when the // compiler changes. diff --git a/src/test/run-make/compiler-lookup-paths/c.rs b/src/test/run-make/compiler-lookup-paths/c.rs index 8a801d589f..b5c54558a4 100644 --- a/src/test/run-make/compiler-lookup-paths/c.rs +++ b/src/test/run-make/compiler-lookup-paths/c.rs @@ -10,4 +10,3 @@ #![crate_type = "lib"] extern crate b; - diff --git a/src/test/run-make/crate-name-priority/foo1.rs b/src/test/run-make/crate-name-priority/foo1.rs index 0f02f10057..a397d6bc74 100644 --- a/src/test/run-make/crate-name-priority/foo1.rs +++ b/src/test/run-make/crate-name-priority/foo1.rs @@ -11,4 +11,3 @@ #![crate_name = "foo"] fn main() {} - diff --git a/src/test/run-make/debug-assertions/Makefile b/src/test/run-make/debug-assertions/Makefile new file mode 100644 index 0000000000..7129756276 --- /dev/null +++ b/src/test/run-make/debug-assertions/Makefile @@ -0,0 +1,21 @@ +-include ../tools.mk + +all: + $(RUSTC) debug.rs -C debug-assertions=no + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=0 + $(call RUN,debug) bad + $(RUSTC) debug.rs -C opt-level=1 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=2 + $(call RUN,debug) good + $(RUSTC) debug.rs -C opt-level=3 + $(call RUN,debug) good + $(RUSTC) debug.rs -O + $(call RUN,debug) good + $(RUSTC) debug.rs + $(call RUN,debug) bad + $(RUSTC) debug.rs -C debug-assertions=yes -O + $(call RUN,debug) bad + $(RUSTC) debug.rs -C debug-assertions=yes -C opt-level=1 + $(call RUN,debug) bad diff --git a/src/test/run-make/debug-assertions/debug.rs b/src/test/run-make/debug-assertions/debug.rs new file mode 100644 index 0000000000..a0ccc75afd --- /dev/null +++ b/src/test/run-make/debug-assertions/debug.rs @@ -0,0 +1,42 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(warnings)] + +use std::env; +use std::thread; + +fn main() { + let should_fail = env::args().nth(1) == Some("bad".to_string()); + + assert_eq!(thread::spawn(debug_assert_eq).join().is_err(), should_fail); + assert_eq!(thread::spawn(debug_assert).join().is_err(), should_fail); + assert_eq!(thread::spawn(overflow).join().is_err(), should_fail); +} + +fn debug_assert_eq() { + let mut hit1 = false; + let mut hit2 = false; + debug_assert_eq!({ hit1 = true; 1 }, { hit2 = true; 2 }); + assert!(!hit1); + assert!(!hit2); +} + +fn debug_assert() { + let mut hit = false; + debug_assert!({ hit = true; false }); + assert!(!hit); +} + +fn overflow() { + fn add(a: u8, b: u8) -> u8 { a + b } + + add(200u8, 200u8); +} diff --git a/src/test/run-make/extern-flag-disambiguates/Makefile b/src/test/run-make/extern-flag-disambiguates/Makefile index 049b76c1b6..81930e969a 100644 --- a/src/test/run-make/extern-flag-disambiguates/Makefile +++ b/src/test/run-make/extern-flag-disambiguates/Makefile @@ -23,4 +23,3 @@ all: @echo after $(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib $(call RUN,d) - diff --git a/src/test/run-make/extern-flag-fun/bar.rs b/src/test/run-make/extern-flag-fun/bar.rs index 2152aa79c3..e6c7602573 100644 --- a/src/test/run-make/extern-flag-fun/bar.rs +++ b/src/test/run-make/extern-flag-fun/bar.rs @@ -7,4 +7,3 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. - diff --git a/src/test/run-make/extern-fn-reachable/main.rs b/src/test/run-make/extern-fn-reachable/main.rs index 0f759efb02..b93bdbaa16 100644 --- a/src/test/run-make/extern-fn-reachable/main.rs +++ b/src/test/run-make/extern-fn-reachable/main.rs @@ -8,17 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(std_misc, old_path, os)] + use std::dynamic_lib::DynamicLibrary; use std::os; +use std::path::Path; pub fn main() { unsafe { let path = Path::new("libdylib.so"); let a = DynamicLibrary::open(Some(&path)).unwrap(); - assert!(a.symbol::("fun1").is_ok()); - assert!(a.symbol::("fun2").is_err()); - assert!(a.symbol::("fun3").is_err()); - assert!(a.symbol::("fun4").is_ok()); - assert!(a.symbol::("fun5").is_ok()); + assert!(a.symbol::("fun1").is_ok()); + assert!(a.symbol::("fun2").is_err()); + assert!(a.symbol::("fun3").is_err()); + assert!(a.symbol::("fun4").is_ok()); + assert!(a.symbol::("fun5").is_ok()); } } diff --git a/src/test/run-make/extern-fn-with-packed-struct/test.rs b/src/test/run-make/extern-fn-with-packed-struct/test.rs index 838ef33884..c0f55893a3 100644 --- a/src/test/run-make/extern-fn-with-packed-struct/test.rs +++ b/src/test/run-make/extern-fn-with-packed-struct/test.rs @@ -9,7 +9,7 @@ // except according to those terms. #[repr(packed)] -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] struct Foo { a: i8, b: i16, diff --git a/src/test/run-make/extern-overrides-distribution/main.rs b/src/test/run-make/extern-overrides-distribution/main.rs index 92b353c892..451841e736 100644 --- a/src/test/run-make/extern-overrides-distribution/main.rs +++ b/src/test/run-make/extern-overrides-distribution/main.rs @@ -13,4 +13,3 @@ extern crate libc; fn main() { libc::foo(); } - diff --git a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot index bee4a120d5..51c6b14e1d 100644 --- a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot @@ -22,12 +22,12 @@ digraph block { N3 -> N4; N4 -> N5; N5 -> N6; - N6 -> N8; - N8 -> N9; + N6 -> N9; N9 -> N10; N10 -> N11; N11 -> N12; - N12 -> N13; + N12 -> N8; + N8 -> N13; N13 -> N14; N14 -> N15; N15 -> N7; diff --git a/src/test/run-make/graphviz-flowgraph/f07.rs b/src/test/run-make/graphviz-flowgraph/f07.rs index 39f71d309f..f36b8d0abc 100644 --- a/src/test/run-make/graphviz-flowgraph/f07.rs +++ b/src/test/run-make/graphviz-flowgraph/f07.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + pub fn pat_vec_7() { match [7, 77, 777, 7777] { [x, y, ..] => x + y diff --git a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot index 76e6651351..fb7d2ad97b 100644 --- a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot @@ -32,16 +32,16 @@ digraph block { N6 -> N7; N7 -> N8; N8 -> N9; - N9 -> N11; - N11 -> N12; - N12 -> N13; + N9 -> N12; + N12 -> N11; + N11 -> N13; N13 -> N14; N14 -> N15; N15 -> N10; - N11 -> N16; - N16 -> N17; + N9 -> N17; N17 -> N18; - N18 -> N19; + N18 -> N16; + N16 -> N19; N19 -> N20; N20 -> N21; N21 -> N22; diff --git a/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot index b4ec986ef2..21e84fb858 100644 --- a/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f20.dot-expected.dot @@ -1,17 +1,17 @@ digraph block { N0[label="entry"]; N1[label="exit"]; - N2[label="expr 2usize"]; - N3[label="expr 0usize"]; - N4[label="expr 20usize"]; - N5[label="expr [2usize, 0usize, 20usize]"]; + N2[label="expr 2"]; + N3[label="expr 0"]; + N4[label="expr 20"]; + N5[label="expr [2, 0, 20]"]; N6[label="local v"]; - N7[label="stmt let v = [2usize, 0usize, 20usize];"]; + N7[label="stmt let v = [2, 0, 20];"]; N8[label="expr v"]; - N9[label="expr 20usize"]; - N10[label="expr v[20usize]"]; - N11[label="stmt v[20usize];"]; - N12[label="block { let v = [2usize, 0usize, 20usize]; v[20usize]; }"]; + N9[label="expr 20"]; + N10[label="expr v[20]"]; + N11[label="stmt v[20];"]; + N12[label="block { let v = [2, 0, 20]; v[20]; }"]; N0 -> N2; N2 -> N3; N3 -> N4; diff --git a/src/test/run-make/graphviz-flowgraph/f20.rs b/src/test/run-make/graphviz-flowgraph/f20.rs index d65de18b54..d734993235 100644 --- a/src/test/run-make/graphviz-flowgraph/f20.rs +++ b/src/test/run-make/graphviz-flowgraph/f20.rs @@ -9,6 +9,6 @@ // except according to those terms. pub fn expr_index_20() { - let v = [2_usize, 0_usize, 20_usize]; - v[20_usize]; + let v = [2, 0, 20]; + v[20]; } diff --git a/src/test/run-make/interdependent-c-libraries/Makefile b/src/test/run-make/interdependent-c-libraries/Makefile index 7654917b46..cf7683479f 100644 --- a/src/test/run-make/interdependent-c-libraries/Makefile +++ b/src/test/run-make/interdependent-c-libraries/Makefile @@ -12,4 +12,3 @@ all: $(call STATICLIB,foo) $(call STATICLIB,bar) $(RUSTC) foo.rs $(RUSTC) bar.rs $(RUSTC) main.rs -Z print-link-args - diff --git a/src/test/run-make/interdependent-c-libraries/bar.rs b/src/test/run-make/interdependent-c-libraries/bar.rs index 5311af2959..88fc98615f 100644 --- a/src/test/run-make/interdependent-c-libraries/bar.rs +++ b/src/test/run-make/interdependent-c-libraries/bar.rs @@ -20,4 +20,3 @@ extern { pub fn doit() { unsafe { bar(); } } - diff --git a/src/test/run-make/intrinsic-unreachable/exit-ret.rs b/src/test/run-make/intrinsic-unreachable/exit-ret.rs index 02c03445ef..f5be5a055c 100644 --- a/src/test/run-make/intrinsic-unreachable/exit-ret.rs +++ b/src/test/run-make/intrinsic-unreachable/exit-ret.rs @@ -11,7 +11,7 @@ #![feature(asm)] #![crate_type="lib"] -pub fn exit(n: uint) { +pub fn exit(n: usize) { unsafe { // Pretend this asm is an exit() syscall. asm!("" :: "r"(n) :: "volatile"); diff --git a/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs b/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs index 835e068c15..81ed446595 100644 --- a/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs +++ b/src/test/run-make/intrinsic-unreachable/exit-unreachable.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(asm)] +#![feature(asm, core)] #![crate_type="lib"] use std::intrinsics; -pub fn exit(n: uint) -> ! { +pub fn exit(n: usize) -> ! { unsafe { // Pretend this asm is an exit() syscall. asm!("" :: "r"(n) :: "volatile"); diff --git a/src/test/run-make/issue-14500/Makefile b/src/test/run-make/issue-14500/Makefile index 446c6e5c81..c19d3d5c30 100644 --- a/src/test/run-make/issue-14500/Makefile +++ b/src/test/run-make/issue-14500/Makefile @@ -11,4 +11,3 @@ all: $(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a $(CC) foo.c -lbar -o $(call RUN_BINFILE,foo) $(EXTRACFLAGS) $(call RUN,foo) - diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index c96210896f..0d42e0be58 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_private, path, convert)] + extern crate rustc; extern crate rustc_driver; +extern crate rustc_lint; extern crate syntax; use rustc::session::{build_session, Session}; @@ -17,6 +20,8 @@ use rustc::session::config::{basic_options, build_configuration, Input, OutputTy use rustc_driver::driver::{compile_input, CompileController}; use syntax::diagnostics::registry::Registry; +use std::path::PathBuf; + fn main() { let src = r#" fn main() {} @@ -28,9 +33,9 @@ fn main() { panic!("expected rustc path"); } - let tmpdir = Path::new(&args[1]); + let tmpdir = PathBuf::from(&args[1]); - let mut sysroot = Path::new(&args[3]); + let mut sysroot = PathBuf::from(&args[3]); sysroot.pop(); sysroot.pop(); @@ -39,17 +44,18 @@ fn main() { compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); } -fn basic_sess(sysroot: Path) -> Session { +fn basic_sess(sysroot: PathBuf) -> Session { let mut opts = basic_options(); opts.output_types = vec![OutputTypeExe]; opts.maybe_sysroot = Some(sysroot); let descriptions = Registry::new(&rustc::diagnostics::DIAGNOSTICS); let sess = build_session(opts, None, descriptions); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); sess } -fn compile(code: String, output: Path, sysroot: Path) { +fn compile(code: String, output: PathBuf, sysroot: PathBuf) { let sess = basic_sess(sysroot); let cfg = build_configuration(&sess); let control = CompileController::basic(); diff --git a/src/test/run-make/issue-7349/foo.rs b/src/test/run-make/issue-7349/foo.rs index 3a2ced80ef..6c39b33be0 100644 --- a/src/test/run-make/issue-7349/foo.rs +++ b/src/test/run-make/issue-7349/foo.rs @@ -23,8 +23,8 @@ extern "C" fn outer_foreign() { } fn main() { - outer::(); - outer::(); - outer_foreign::(); - outer_foreign::(); + outer::(); + outer::(); + outer_foreign::(); + outer_foreign::(); } diff --git a/src/test/run-make/libs-and-bins/Makefile b/src/test/run-make/libs-and-bins/Makefile index 4d975d2f71..cc3b257a5c 100644 --- a/src/test/run-make/libs-and-bins/Makefile +++ b/src/test/run-make/libs-and-bins/Makefile @@ -4,4 +4,3 @@ all: $(RUSTC) foo.rs $(call RUN,foo) rm $(TMPDIR)/$(call DYLIB_GLOB,foo) - diff --git a/src/test/run-make/link-path-order/Makefile b/src/test/run-make/link-path-order/Makefile index b8ebe6db6f..116c7ae991 100644 --- a/src/test/run-make/link-path-order/Makefile +++ b/src/test/run-make/link-path-order/Makefile @@ -14,4 +14,3 @@ all: $(TMPDIR)/libcorrect.a $(TMPDIR)/libwrong.a $(call RUN,should_succeed) $(RUSTC) main.rs -o $(TMPDIR)/should_fail -L $(WRONG_DIR) -L $(CORRECT_DIR) $(call FAIL,should_fail) - diff --git a/src/test/run-make/link-path-order/main.rs b/src/test/run-make/link-path-order/main.rs index cd286af602..c1787eb03f 100644 --- a/src/test/run-make/link-path-order/main.rs +++ b/src/test/run-make/link-path-order/main.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(libc, exit_status)] + extern crate libc; #[link(name="foo")] @@ -21,6 +23,6 @@ fn main() { }; if result != 1 { - std::os::set_exit_status(255); + std::env::set_exit_status(255); } } diff --git a/src/test/run-make/linkage-attr-on-static/Makefile b/src/test/run-make/linkage-attr-on-static/Makefile index 6bcde96335..1871a5bbdc 100644 --- a/src/test/run-make/linkage-attr-on-static/Makefile +++ b/src/test/run-make/linkage-attr-on-static/Makefile @@ -5,4 +5,3 @@ all: $(AR) rcs $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o $(RUSTC) bar.rs -lfoo -L $(TMPDIR) $(call RUN,bar) || exit 1 - diff --git a/src/test/run-make/lto-syntax-extension/main.rs b/src/test/run-make/lto-syntax-extension/main.rs index a38b2cfb96..c9395f557f 100644 --- a/src/test/run-make/lto-syntax-extension/main.rs +++ b/src/test/run-make/lto-syntax-extension/main.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_private)] + extern crate lib; #[macro_use] extern crate log; diff --git a/src/test/run-make/manual-link/Makefile b/src/test/run-make/manual-link/Makefile index d053695615..dccf0d99b0 100644 --- a/src/test/run-make/manual-link/Makefile +++ b/src/test/run-make/manual-link/Makefile @@ -4,4 +4,3 @@ all: $(TMPDIR)/libbar.a $(RUSTC) foo.rs -lstatic=bar $(RUSTC) main.rs $(call RUN,main) - diff --git a/src/test/run-make/many-crates-but-no-match/Makefile b/src/test/run-make/many-crates-but-no-match/Makefile index da5fc78f32..edf8e9df46 100644 --- a/src/test/run-make/many-crates-but-no-match/Makefile +++ b/src/test/run-make/many-crates-but-no-match/Makefile @@ -16,7 +16,7 @@ A3=$(TMPDIR)/a3 # A hack to match distinct lines of output from a single run. LOG=$(TMPDIR)/log.txt -all: +all: mkdir -p $(A1) $(A2) $(A3) $(RUSTC) --crate-type=rlib crateA1.rs mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A1) diff --git a/src/test/run-make/metadata-flag-frobs-symbols/foo.rs b/src/test/run-make/metadata-flag-frobs-symbols/foo.rs index ed04eed8cf..baabdc9ad7 100644 --- a/src/test/run-make/metadata-flag-frobs-symbols/foo.rs +++ b/src/test/run-make/metadata-flag-frobs-symbols/foo.rs @@ -11,6 +11,6 @@ #![crate_name = "foo"] #![crate_type = "rlib"] -static FOO: uint = 3; +static FOO: usize = 3; -pub fn foo() -> &'static uint { &FOO } +pub fn foo() -> &'static usize { &FOO } diff --git a/src/test/run-make/mismatching-target-triples/bar.rs b/src/test/run-make/mismatching-target-triples/bar.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/mismatching-target-triples/foo.rs b/src/test/run-make/mismatching-target-triples/foo.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/missing-crate-dependency/Makefile b/src/test/run-make/missing-crate-dependency/Makefile index 3f8b97f256..275658047d 100644 --- a/src/test/run-make/missing-crate-dependency/Makefile +++ b/src/test/run-make/missing-crate-dependency/Makefile @@ -1,6 +1,6 @@ -include ../tools.mk -all: +all: $(RUSTC) --crate-type=rlib crateA.rs $(RUSTC) --crate-type=rlib crateB.rs $(call REMOVE_RLIBS,crateA) diff --git a/src/test/run-make/mixing-deps/both.rs b/src/test/run-make/mixing-deps/both.rs index 7696c27ad7..c44335e2bb 100644 --- a/src/test/run-make/mixing-deps/both.rs +++ b/src/test/run-make/mixing-deps/both.rs @@ -11,4 +11,4 @@ #![crate_type = "rlib"] #![crate_type = "dylib"] -pub static foo: int = 4; +pub static foo: isize = 4; diff --git a/src/test/run-make/mixing-deps/dylib.rs b/src/test/run-make/mixing-deps/dylib.rs index d60cc05cc9..78af525f38 100644 --- a/src/test/run-make/mixing-deps/dylib.rs +++ b/src/test/run-make/mixing-deps/dylib.rs @@ -13,4 +13,4 @@ extern crate both; use std::mem; -pub fn addr() -> uint { unsafe { mem::transmute(&both::foo) } } +pub fn addr() -> usize { unsafe { mem::transmute(&both::foo) } } diff --git a/src/test/run-make/mixing-deps/prog.rs b/src/test/run-make/mixing-deps/prog.rs index 8006987e9f..c3d88016fd 100644 --- a/src/test/run-make/mixing-deps/prog.rs +++ b/src/test/run-make/mixing-deps/prog.rs @@ -14,6 +14,6 @@ extern crate both; use std::mem; fn main() { - assert_eq!(unsafe { mem::transmute::<&int, uint>(&both::foo) }, + assert_eq!(unsafe { mem::transmute::<&isize, usize>(&both::foo) }, dylib::addr()); } diff --git a/src/test/run-make/mixing-formats/baz2.rs b/src/test/run-make/mixing-formats/baz2.rs index 4cfa65330b..c5066ccd65 100644 --- a/src/test/run-make/mixing-formats/baz2.rs +++ b/src/test/run-make/mixing-formats/baz2.rs @@ -12,4 +12,3 @@ extern crate bar1; extern crate bar2; fn main() {} - diff --git a/src/test/run-make/no-duplicate-libs/bar.rs b/src/test/run-make/no-duplicate-libs/bar.rs index 0bec614818..29f52f97a8 100644 --- a/src/test/run-make/no-duplicate-libs/bar.rs +++ b/src/test/run-make/no-duplicate-libs/bar.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, no_std)] +#![feature(lang_items, no_std, libc)] #![no_std] #![crate_type = "dylib"] diff --git a/src/test/run-make/no-duplicate-libs/foo.rs b/src/test/run-make/no-duplicate-libs/foo.rs index 9e8afdc569..ae424c6569 100644 --- a/src/test/run-make/no-duplicate-libs/foo.rs +++ b/src/test/run-make/no-duplicate-libs/foo.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, no_std)] +#![feature(lang_items, no_std, libc)] #![no_std] #![crate_type = "dylib"] diff --git a/src/test/run-make/obey-crate-type-flag/test.rs b/src/test/run-make/obey-crate-type-flag/test.rs index 8eb82b48ea..e6c8b8eb17 100644 --- a/src/test/run-make/obey-crate-type-flag/test.rs +++ b/src/test/run-make/obey-crate-type-flag/test.rs @@ -10,4 +10,3 @@ #![crate_type = "rlib"] #![crate_type = "dylib"] - diff --git a/src/test/run-make/output-with-hyphens/Makefile b/src/test/run-make/output-with-hyphens/Makefile new file mode 100644 index 0000000000..783d826a53 --- /dev/null +++ b/src/test/run-make/output-with-hyphens/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + $(RUSTC) foo-bar.rs + [ -f $(TMPDIR)/$(call BIN,foo-bar) ] + [ -f $(TMPDIR)/libfoo_bar.rlib ] diff --git a/src/test/compile-fail/deriving-is-deprecated.rs b/src/test/run-make/output-with-hyphens/foo-bar.rs similarity index 85% rename from src/test/compile-fail/deriving-is-deprecated.rs rename to src/test/run-make/output-with-hyphens/foo-bar.rs index 060e178eef..2f93b2d1ea 100644 --- a/src/test/compile-fail/deriving-is-deprecated.rs +++ b/src/test/run-make/output-with-hyphens/foo-bar.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#[deriving(Clone)] //~ ERROR `deriving` has been renamed to `derive` -struct Foo; +#![crate_type = "lib"] +#![crate_type = "bin"] fn main() {} diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/pretty-expanded/input.rs b/src/test/run-make/pretty-expanded/input.rs index b6137c3eba..04bf17dc28 100644 --- a/src/test/run-make/pretty-expanded/input.rs +++ b/src/test/run-make/pretty-expanded/input.rs @@ -15,8 +15,8 @@ extern crate serialize; #[derive(Encodable)] pub struct A; -#[derive(Encodable)] pub struct B(int); -#[derive(Encodable)] pub struct C { x: int } +#[derive(Encodable)] pub struct B(isize); +#[derive(Encodable)] pub struct C { x: isize } #[derive(Encodable)] pub enum D {} #[derive(Encodable)] pub enum E { y } -#[derive(Encodable)] pub enum F { z(int) } +#[derive(Encodable)] pub enum F { z(isize) } diff --git a/src/test/run-make/pretty-print-path-suffix/foo_method.pp b/src/test/run-make/pretty-print-path-suffix/foo_method.pp index acf3f90cb0..4879fbfe6d 100644 --- a/src/test/run-make/pretty-print-path-suffix/foo_method.pp +++ b/src/test/run-make/pretty-print-path-suffix/foo_method.pp @@ -12,5 +12,5 @@ -fn foo_method(&self) -> &'static str { return "i am very similiar to foo."; } +fn foo_method(&self) -> &'static str { return "i am very similar to foo."; } /* nest::S::foo_method */ diff --git a/src/test/run-make/pretty-print-path-suffix/input.rs b/src/test/run-make/pretty-print-path-suffix/input.rs index 4942540126..8ea86a94f9 100644 --- a/src/test/run-make/pretty-print-path-suffix/input.rs +++ b/src/test/run-make/pretty-print-path-suffix/input.rs @@ -22,7 +22,7 @@ pub mod nest { struct S; impl S { fn foo_method(&self) -> &'static str { - return "i am very similiar to foo."; + return "i am very similar to foo."; } } } diff --git a/src/test/run-make/rustdoc-default-impl/Makefile b/src/test/run-make/rustdoc-default-impl/Makefile new file mode 100644 index 0000000000..338cf9d205 --- /dev/null +++ b/src/test/run-make/rustdoc-default-impl/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: foo.rs bar.rs + $(RUSTC) foo.rs --crate-type lib + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc bar.rs -L $(TMPDIR) diff --git a/src/test/compile-fail/deprecated-phase.rs b/src/test/run-make/rustdoc-default-impl/bar.rs similarity index 77% rename from src/test/compile-fail/deprecated-phase.rs rename to src/test/run-make/rustdoc-default-impl/bar.rs index 1401494d98..60a2f7202f 100644 --- a/src/test/compile-fail/deprecated-phase.rs +++ b/src/test/run-make/rustdoc-default-impl/bar.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[phase(blah)] -//~^ ERROR #[phase] is deprecated extern crate foo; -fn main() {} +pub use foo::bar; + +pub fn wut() { +} diff --git a/src/test/run-make/rustdoc-default-impl/foo.rs b/src/test/run-make/rustdoc-default-impl/foo.rs new file mode 100644 index 0000000000..8f11629be6 --- /dev/null +++ b/src/test/run-make/rustdoc-default-impl/foo.rs @@ -0,0 +1,36 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] +#![feature(core)] + +pub mod bar { + use std::marker; + + pub trait Bar: marker::MarkerTrait + 'static {} + + impl Bar for .. {} + + pub trait Foo { + fn foo(&self) {} + } + + impl Foo { + pub fn test(&self) {} + } + + pub struct TypeId; + + impl TypeId { + pub fn of() -> TypeId { + panic!() + } + } +} diff --git a/src/test/run-make/rustdoc-extern-default-method/Makefile b/src/test/run-make/rustdoc-extern-default-method/Makefile new file mode 100644 index 0000000000..ffc4a08f80 --- /dev/null +++ b/src/test/run-make/rustdoc-extern-default-method/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: lib.rs ext.rs + $(HOST_RPATH_ENV) $(RUSTC) ext.rs + $(HOST_RPATH_ENV) $(RUSTDOC) -L $(TMPDIR) -w html -o $(TMPDIR)/doc lib.rs + $(HTMLDOCCK) $(TMPDIR)/doc lib.rs diff --git a/src/test/run-make/rustdoc-extern-default-method/ext.rs b/src/test/run-make/rustdoc-extern-default-method/ext.rs new file mode 100644 index 0000000000..861562753f --- /dev/null +++ b/src/test/run-make/rustdoc-extern-default-method/ext.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="lib"] + +pub trait Trait { + fn provided(&self) {} +} + +pub struct Struct; + +impl Trait for Struct { + fn provided(&self) {} +} diff --git a/src/test/run-make/rustdoc-extern-default-method/lib.rs b/src/test/run-make/rustdoc-extern-default-method/lib.rs new file mode 100644 index 0000000000..df92764dc9 --- /dev/null +++ b/src/test/run-make/rustdoc-extern-default-method/lib.rs @@ -0,0 +1,14 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate ext; + +// @count lib/struct.Struct.html '//*[@id="method.provided"]' 1 +pub use ext::Struct; diff --git a/src/test/run-make/rustdoc-extern-method/Makefile b/src/test/run-make/rustdoc-extern-method/Makefile index c87684f59e..55cbd2da6a 100644 --- a/src/test/run-make/rustdoc-extern-method/Makefile +++ b/src/test/run-make/rustdoc-extern-method/Makefile @@ -5,4 +5,3 @@ all: foo.rs bar.rs $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) -L $(TMPDIR) -w html -o $(TMPDIR)/doc bar.rs $(HTMLDOCCK) $(TMPDIR)/doc bar.rs - diff --git a/src/test/run-make/rustdoc-extern-method/bar.rs b/src/test/run-make/rustdoc-extern-method/bar.rs index 672090c13a..26a05f8490 100644 --- a/src/test/run-make/rustdoc-extern-method/bar.rs +++ b/src/test/run-make/rustdoc-extern-method/bar.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(unboxed_closures)] + extern crate foo; // @has bar/trait.Foo.html //pre "pub trait Foo" diff --git a/src/test/run-make/rustdoc-extern-method/foo.rs b/src/test/run-make/rustdoc-extern-method/foo.rs index fc5f03e8bd..96a7a8378b 100644 --- a/src/test/run-make/rustdoc-extern-method/foo.rs +++ b/src/test/run-make/rustdoc-extern-method/foo.rs @@ -9,6 +9,7 @@ // except according to those terms. #![crate_type="lib"] +#![feature(unboxed_closures)] pub trait Foo { extern "rust-call" fn foo(&self, _: ()) -> i32; diff --git a/src/test/run-make/rustdoc-negative-impl/Makefile b/src/test/run-make/rustdoc-negative-impl/Makefile index 1316ee256e..c1b1683efd 100644 --- a/src/test/run-make/rustdoc-negative-impl/Makefile +++ b/src/test/run-make/rustdoc-negative-impl/Makefile @@ -3,4 +3,3 @@ all: foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs $(HTMLDOCCK) $(TMPDIR)/doc foo.rs - diff --git a/src/test/run-make/rustdoc-recursion/Makefile b/src/test/run-make/rustdoc-recursion/Makefile index b7fc6d6c0a..ba971836e5 100644 --- a/src/test/run-make/rustdoc-recursion/Makefile +++ b/src/test/run-make/rustdoc-recursion/Makefile @@ -9,4 +9,3 @@ all: else all: endif - diff --git a/src/test/run-make/rustdoc-recursion/foo.rs b/src/test/run-make/rustdoc-recursion/foo.rs index 29a909f139..7505d20566 100644 --- a/src/test/run-make/rustdoc-recursion/foo.rs +++ b/src/test/run-make/rustdoc-recursion/foo.rs @@ -22,4 +22,3 @@ mod m { pub use super::*; } } - diff --git a/src/test/run-make/rustdoc-smoke/foo.rs b/src/test/run-make/rustdoc-smoke/foo.rs index f6b73021be..494eb03d72 100644 --- a/src/test/run-make/rustdoc-smoke/foo.rs +++ b/src/test/run-make/rustdoc-smoke/foo.rs @@ -29,8 +29,8 @@ pub mod bar { pub trait Doge { fn dummy(&self) { } } // @has foo/bar/struct.Foo.html - pub struct Foo { x: int, y: uint } + pub struct Foo { x: isize, y: usize } // @has foo/bar/fn.prawns.html - pub fn prawns((a, b): (int, uint), Foo { x, y }: Foo) { } + pub fn prawns((a, b): (isize, usize), Foo { x, y }: Foo) { } } diff --git a/src/test/run-make/rustdoc-src-links/Makefile b/src/test/run-make/rustdoc-src-links/Makefile new file mode 100644 index 0000000000..419603e82f --- /dev/null +++ b/src/test/run-make/rustdoc-src-links/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk +all: + $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs + $(HTMLDOCCK) $(TMPDIR)/doc foo.rs + $(HTMLDOCCK) $(TMPDIR)/doc qux/mod.rs diff --git a/src/test/run-make/rustdoc-src-links/foo.rs b/src/test/run-make/rustdoc-src-links/foo.rs new file mode 100644 index 0000000000..9a964f1125 --- /dev/null +++ b/src/test/run-make/rustdoc-src-links/foo.rs @@ -0,0 +1,43 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name = "foo"] + +//! Dox +// @has src/foo/foo.rs.html +// @has foo/index.html '//a/@href' '../src/foo/foo.rs.html' + +pub mod qux; + +// @has foo/bar/index.html '//a/@href' '../../src/foo/foo.rs.html' +pub mod bar { + + /// Dox + // @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/foo.rs.html' + pub mod baz { + /// Dox + // @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/foo.rs.html' + pub fn baz() { } + } + + /// Dox + // @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/foo.rs.html' + pub trait Foobar { fn dummy(&self) { } } + + // @has foo/bar/struct.Foo.html '//a/@href' '../../src/foo/foo.rs.html' + pub struct Foo { x: i32, y: u32 } + + // @has foo/bar/fn.prawns.html '//a/@href' '../../src/foo/foo.rs.html' + pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { } +} + +/// Dox +// @has foo/fn.modfn.html '//a/@href' '../src/foo/foo.rs.html' +pub fn modfn() { } diff --git a/src/test/run-make/rustdoc-src-links/qux/mod.rs b/src/test/run-make/rustdoc-src-links/qux/mod.rs new file mode 100644 index 0000000000..9b1563d32a --- /dev/null +++ b/src/test/run-make/rustdoc-src-links/qux/mod.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Dox +// @has src/foo/qux/mod.rs.html +// @has foo/qux/index.html '//a/@href' '../../src/foo/qux/mod.rs.html' + +// @has foo/qux/bar/index.html '//a/@href' '../../../src/foo/qux/mod.rs.html' +pub mod bar { + + /// Dox + // @has foo/qux/bar/baz/index.html '//a/@href' '../../../../src/foo/qux/mod.rs.html' + pub mod baz { + /// Dox + // @has foo/qux/bar/baz/fn.baz.html '//a/@href' '../../../../src/foo/qux/mod.rs.html' + pub fn baz() { } + } + + /// Dox + // @has foo/qux/bar/trait.Foobar.html '//a/@href' '../../../src/foo/qux/mod.rs.html' + pub trait Foobar { fn dummy(&self) { } } + + // @has foo/qux/bar/struct.Foo.html '//a/@href' '../../../src/foo/qux/mod.rs.html' + pub struct Foo { x: i32, y: u32 } + + // @has foo/qux/bar/fn.prawns.html '//a/@href' '../../../src/foo/qux/mod.rs.html' + pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { } +} + +/// Dox +// @has foo/qux/fn.modfn.html '//a/@href' '../../src/foo/qux/mod.rs.html' +pub fn modfn() { } diff --git a/src/test/run-make/rustdoc-viewpath-self/Makefile b/src/test/run-make/rustdoc-viewpath-self/Makefile index 1316ee256e..c1b1683efd 100644 --- a/src/test/run-make/rustdoc-viewpath-self/Makefile +++ b/src/test/run-make/rustdoc-viewpath-self/Makefile @@ -3,4 +3,3 @@ all: foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs $(HTMLDOCCK) $(TMPDIR)/doc foo.rs - diff --git a/src/test/run-make/rustdoc-where/Makefile b/src/test/run-make/rustdoc-where/Makefile index 1316ee256e..c1b1683efd 100644 --- a/src/test/run-make/rustdoc-where/Makefile +++ b/src/test/run-make/rustdoc-where/Makefile @@ -3,4 +3,3 @@ all: foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs $(HTMLDOCCK) $(TMPDIR)/doc foo.rs - diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index 38381da367..9d1ab00359 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -10,12 +10,12 @@ #![ crate_name = "test" ] #![allow(unstable)] -#![feature(box_syntax)] +#![feature(box_syntax, old_io, rustc_private, core)] extern crate graphviz; // A simple rust project -extern crate "flate" as myflate; +extern crate flate as myflate; use std::collections::{HashMap,HashSet}; use std::cell::RefCell; @@ -39,23 +39,23 @@ static bob: Option<&'static [isize]> = None; // buglink test - see issue #1337. fn test_alias(i: Option<::Item>) { - let s = sub_struct{ field2: 45u32, }; + let s = sub_struct{ field2: 45, }; // import tests fn foo(x: &Float) {} let _: Option = from_i32(45); - let x = 42_usize; + let x = 42; myflate::deflate_bytes(&[]); - let x = (3, 4_usize); + let x = (3, 4); let y = x.1; } -struct TupStruct(int, int, Box); +struct TupStruct(isize, isize, Box); -fn test_tup_struct(x: TupStruct) -> int { +fn test_tup_struct(x: TupStruct) -> isize { x.1 } @@ -179,7 +179,7 @@ enum SomeEnum<'a> { MyTypes(MyType, MyType) } -#[derive(Copy)] +#[derive(Copy, Clone)] enum SomeOtherEnum { SomeConst1, SomeConst2, @@ -245,9 +245,10 @@ fn hello((z, a) : (u32, String), ex: X) { let x = 32.0f32; let _ = (x + ((x * x) + 1.0).sqrt()).ln(); - let s: Box = box some_fields {field1: 43}; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let s: Box = Box::new(some_fields {field1: 43}); let s2: Box = box some_fields {field1: 43}; - let s3 = box nofields; + let s3: Box<_> = box nofields; s.Method(43); s3.Method(43); @@ -282,7 +283,7 @@ pub struct blah { } fn main() { // foo - let s = box some_fields {field1: 43}; + let s: Box<_> = box some_fields {field1: 43}; hello((43, "a".to_string()), *s); sub::sub2::hello(); sub2::sub3::hello(); diff --git a/src/test/run-make/sepcomp-cci-copies/cci_lib.rs b/src/test/run-make/sepcomp-cci-copies/cci_lib.rs index a7cd85db4a..62bc329428 100644 --- a/src/test/run-make/sepcomp-cci-copies/cci_lib.rs +++ b/src/test/run-make/sepcomp-cci-copies/cci_lib.rs @@ -11,6 +11,6 @@ #![crate_type = "rlib"] #[inline] -pub fn cci_fn() -> uint { +pub fn cci_fn() -> usize { 1234 } diff --git a/src/test/run-make/sepcomp-cci-copies/foo.rs b/src/test/run-make/sepcomp-cci-copies/foo.rs index b0642b64cd..e00cab20f6 100644 --- a/src/test/run-make/sepcomp-cci-copies/foo.rs +++ b/src/test/run-make/sepcomp-cci-copies/foo.rs @@ -9,21 +9,21 @@ // except according to those terms. extern crate cci_lib; -use cci_lib::{cci_fn}; +use cci_lib::cci_fn; -fn call1() -> uint { +fn call1() -> usize { cci_fn() } mod a { use cci_lib::cci_fn; - pub fn call2() -> uint { + pub fn call2() -> usize { cci_fn() } } mod b { - pub fn call3() -> uint { + pub fn call3() -> usize { 0 } } diff --git a/src/test/run-make/sepcomp-separate/foo.rs b/src/test/run-make/sepcomp-separate/foo.rs index fe6a7b5a18..bfa2162e27 100644 --- a/src/test/run-make/sepcomp-separate/foo.rs +++ b/src/test/run-make/sepcomp-separate/foo.rs @@ -8,18 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn magic_fn() -> uint { +fn magic_fn() -> usize { 1234 } mod a { - pub fn magic_fn() -> uint { + pub fn magic_fn() -> usize { 2345 } } mod b { - pub fn magic_fn() -> uint { + pub fn magic_fn() -> usize { 3456 } } diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs old mode 100755 new mode 100644 diff --git a/src/test/run-make/symbols-are-reasonable/lib.rs b/src/test/run-make/symbols-are-reasonable/lib.rs index e1f36ecda5..8ba705bfb6 100644 --- a/src/test/run-make/symbols-are-reasonable/lib.rs +++ b/src/test/run-make/symbols-are-reasonable/lib.rs @@ -12,9 +12,9 @@ pub static X: &'static str = "foobarbaz"; pub static Y: &'static [u8] = include_bytes!("lib.rs"); trait Foo { fn dummy(&self) { } } -impl Foo for uint {} +impl Foo for usize {} pub fn dummy() { // force the vtable to be created - let _x = &1_usize as &Foo; + let _x = &1us as &Foo; } diff --git a/src/test/run-make/target-cpu-native/Makefile b/src/test/run-make/target-cpu-native/Makefile new file mode 100644 index 0000000000..0c9d93ecb2 --- /dev/null +++ b/src/test/run-make/target-cpu-native/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) foo.rs -C target-cpu=native + $(call RUN,foo) diff --git a/src/libcoretest/num/uint.rs b/src/test/run-make/target-cpu-native/foo.rs similarity index 94% rename from src/libcoretest/num/uint.rs rename to src/test/run-make/target-cpu-native/foo.rs index 395e55cf25..f7a9f96906 100644 --- a/src/libcoretest/num/uint.rs +++ b/src/test/run-make/target-cpu-native/foo.rs @@ -8,4 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -uint_module!(uint, uint); +fn main() { +} diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index acda8705b1..b13c41be55 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -22,7 +22,7 @@ trait Copy : PhantomFn { } trait Sized : PhantomFn { } #[lang="start"] -fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 } +fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 } extern { fn _foo() -> [u8; 16]; diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 23c422bc7a..7b604bedfd 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -83,4 +83,3 @@ REMOVE_RLIBS = rm $(TMPDIR)/$(call RLIB_GLOB,$(1)) $(TMPDIR)/lib%.o: %.c $(CC) -c -o $@ $< - diff --git a/src/test/run-make/unicode-input/multiple_files.rs b/src/test/run-make/unicode-input/multiple_files.rs index ce3e69918f..aa2ce78577 100644 --- a/src/test/run-make/unicode-input/multiple_files.rs +++ b/src/test/run-make/unicode-input/multiple_files.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{char, env}; -use std::old_io::{File, Command}; +#![feature(rand)] + +use std::fs::File; +use std::io::prelude::*; +use std::path::Path; +use std::process::Command; use std::rand::{thread_rng, Rng}; +use std::{char, env}; // creates unicode_input_multiple_files_{main,chars}.rs, where the // former imports the latter. `_chars` just contains an identifier @@ -40,7 +45,7 @@ fn main() { let main_file = tmpdir.join("unicode_input_multiple_files_main.rs"); { let _ = File::create(&main_file).unwrap() - .write_str("mod unicode_input_multiple_files_chars;"); + .write_all(b"mod unicode_input_multiple_files_chars;").unwrap(); } for _ in 0..100 { @@ -48,7 +53,7 @@ fn main() { let randoms = tmpdir.join("unicode_input_multiple_files_chars.rs"); let mut w = File::create(&randoms).unwrap(); for _ in 0..30 { - let _ = w.write_char(random_char()); + write!(&mut w, "{}", random_char()).unwrap(); } } @@ -58,10 +63,9 @@ fn main() { .arg("-c") .arg(&format!("{} {}", rustc, - main_file.as_str() - .unwrap())) + main_file.display())) .output().unwrap(); - let err = String::from_utf8_lossy(&result.error); + let err = String::from_utf8_lossy(&result.stderr); // positive test so that this test will be updated when the // compiler changes. diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs index ef6c799336..a70a160076 100644 --- a/src/test/run-make/unicode-input/span_length.rs +++ b/src/test/run-make/unicode-input/span_length.rs @@ -8,8 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::{File, Command}; +#![feature(rand, core)] + +use std::fs::File; +use std::io::prelude::*; use std::iter::repeat; +use std::path::Path; +use std::process::Command; use std::rand::{thread_rng, Rng}; use std::{char, env}; @@ -54,11 +59,11 @@ fn main() { .arg("-c") .arg(&format!("{} {}", rustc, - main_file.as_str() + main_file.to_str() .unwrap())) .output().unwrap(); - let err = String::from_utf8_lossy(&result.error); + let err = String::from_utf8_lossy(&result.stderr); // the span should end the line (e.g no extra ~'s) let expected_span = format!("^{}\n", repeat("~").take(n - 1) @@ -73,17 +78,16 @@ fn main() { } // Extra characters. Every line is preceded by `filename:lineno ` - let offset = main_file.as_str().unwrap().len() + 3; + let offset = main_file.to_str().unwrap().len() + 3; let result = Command::new("sh") .arg("-c") .arg(format!("{} {}", rustc, - main_file.as_str() - .unwrap()).as_slice()) + main_file.display())) .output().unwrap(); - let err = String::from_utf8_lossy(result.error.as_slice()); + let err = String::from_utf8_lossy(&result.stderr); // Test both the length of the snake and the leading spaces up to it @@ -91,10 +95,10 @@ fn main() { let expected_span = format!("\n{}^{}\n", repeat(" ").take(offset + 7).collect::(), repeat("~").take(8).collect::()); - assert!(err.contains(expected_span.as_slice())); + assert!(err.contains(&expected_span)); // Second snake is 8 ~s long, with 36 preceding spaces let expected_span = format!("\n{}^{}\n", repeat(" ").take(offset + 36).collect::(), repeat("~").take(8).collect::()); - assert!(err.contains(expected_span.as_slice())); + assert!(err.contains(&expected_span)); } diff --git a/src/test/run-make/volatile-intrinsics/main.rs b/src/test/run-make/volatile-intrinsics/main.rs index 6dffb53e4a..217dee4b88 100644 --- a/src/test/run-make/volatile-intrinsics/main.rs +++ b/src/test/run-make/volatile-intrinsics/main.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + use std::intrinsics::{volatile_load, volatile_store}; pub fn main() { unsafe { - let mut i : int = 1; + let mut i : isize = 1; volatile_store(&mut i, 2); assert_eq!(volatile_load(&i), 2); } diff --git a/src/test/run-make/weird-output-filenames/Makefile b/src/test/run-make/weird-output-filenames/Makefile index 5d6e629ffc..8b69c68279 100644 --- a/src/test/run-make/weird-output-filenames/Makefile +++ b/src/test/run-make/weird-output-filenames/Makefile @@ -10,3 +10,6 @@ all: cp foo.rs $(TMPDIR)/+foo+bar $(RUSTC) $(TMPDIR)/+foo+bar 2>&1 \ | grep "invalid character.*in crate name:" + cp foo.rs $(TMPDIR)/-foo.rs + $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \ + | grep 'crate names cannot start with a `-`' diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 9e164522d7..4bacde0aad 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -12,7 +12,7 @@ // ignore-android -#![feature(rustc_private)] +#![feature(rustc_private, path)] #![feature(core)] extern crate getopts; @@ -25,6 +25,7 @@ use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; use syntax::diagnostics; +use std::path::PathBuf; struct TestCalls { count: u32 @@ -43,14 +44,15 @@ impl<'a> CompilerCalls<'a> for TestCalls { _: &getopts::Matches, _: &Session, _: &Input, - _: &Option, - _: &Option) + _: &Option, + _: &Option) -> Compilation { self.count *= 3; Compilation::Stop } - fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { + fn some_input(&mut self, input: Input, input_path: Option) + -> (Input, Option) { self.count *= 5; (input, input_path) } @@ -58,10 +60,10 @@ impl<'a> CompilerCalls<'a> for TestCalls { fn no_input(&mut self, _: &getopts::Matches, _: &config::Options, - _: &Option, - _: &Option, + _: &Option, + _: &Option, _: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { + -> Option<(Input, Option)> { panic!("This shouldn't happen"); } @@ -75,7 +77,6 @@ fn main() { let mut tc = TestCalls { count: 1 }; // we should never get use this filename, but lets make sure they are valid args. let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::run_compiler(args.as_slice(), &mut tc); + rustc_driver::run_compiler(&args, &mut tc); assert!(tc.count == 30); } - diff --git a/src/test/run-pass-fulldeps/create-dir-all-bare.rs b/src/test/run-pass-fulldeps/create-dir-all-bare.rs new file mode 100644 index 0000000000..e4fb7c1990 --- /dev/null +++ b/src/test/run-pass-fulldeps/create-dir-all-bare.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android + +#![feature(rustc_private)] + +extern crate rustc_back; + +use std::env; +use std::fs; +use rustc_back::tempdir::TempDir; + +fn main() { + let td = TempDir::new("create-dir-all-bare").unwrap(); + env::set_current_dir(td.path()).unwrap(); + fs::create_dir_all("create-dir-all-bare").unwrap(); +} diff --git a/src/test/run-pass-fulldeps/derive-totalsum.rs b/src/test/run-pass-fulldeps/derive-totalsum.rs new file mode 100644 index 0000000000..848b2425e4 --- /dev/null +++ b/src/test/run-pass-fulldeps/derive-totalsum.rs @@ -0,0 +1,59 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:custom_derive_plugin.rs +// ignore-stage1 + +#![feature(plugin, custom_derive)] +#![plugin(custom_derive_plugin)] + +trait TotalSum { + fn total_sum(&self) -> isize; +} + +impl TotalSum for isize { + fn total_sum(&self) -> isize { + *self + } +} + +struct Seven; + +impl TotalSum for Seven { + fn total_sum(&self) -> isize { + 7 + } +} + +#[derive(TotalSum)] +struct Foo { + seven: Seven, + bar: Bar, + baz: isize, +} + +#[derive(TotalSum)] +struct Bar { + quux: isize, + bleh: isize, +} + + +pub fn main() { + let v = Foo { + seven: Seven, + bar: Bar { + quux: 9, + bleh: 3, + }, + baz: 80, + }; + assert_eq!(v.total_sum(), 99); +} diff --git a/src/test/run-pass-fulldeps/issue-13560.rs b/src/test/run-pass-fulldeps/issue-13560.rs index cd79a95dac..1541e809b6 100644 --- a/src/test/run-pass-fulldeps/issue-13560.rs +++ b/src/test/run-pass-fulldeps/issue-13560.rs @@ -16,7 +16,7 @@ // Regression test for issue #13560, the test itself is all in the dependent // libraries. The fail which previously failed to compile is the one numbered 3. -extern crate "issue-13560-2" as t2; -extern crate "issue-13560-3" as t3; +extern crate issue_13560_2 as t2; +extern crate issue_13560_3 as t3; fn main() {} diff --git a/src/test/run-pass-fulldeps/issue-15778-pass.rs b/src/test/run-pass-fulldeps/issue-15778-pass.rs new file mode 100644 index 0000000000..a767779687 --- /dev/null +++ b/src/test/run-pass-fulldeps/issue-15778-pass.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:lint_for_crate.rs +// ignore-stage1 +// compile-flags: -D crate-not-okay + +#![feature(plugin, custom_attribute)] +#![plugin(lint_for_crate)] +#![crate_okay] + +pub fn main() { } diff --git a/src/test/run-pass-fulldeps/issue-16822.rs b/src/test/run-pass-fulldeps/issue-16822.rs index 6306627df0..172d3e31d4 100644 --- a/src/test/run-pass-fulldeps/issue-16822.rs +++ b/src/test/run-pass-fulldeps/issue-16822.rs @@ -10,12 +10,12 @@ // aux-build:issue-16822.rs -extern crate "issue-16822" as lib; +extern crate issue_16822 as lib; use std::cell::RefCell; struct App { - i: int + i: isize } impl lib::Update for App { diff --git a/src/test/run-pass-fulldeps/issue-16992.rs b/src/test/run-pass-fulldeps/issue-16992.rs index 9e3ad8ee28..40947b2e25 100644 --- a/src/test/run-pass-fulldeps/issue-16992.rs +++ b/src/test/run-pass-fulldeps/issue-16992.rs @@ -11,7 +11,7 @@ // ignore-pretty // ignore-android -#![feature(quote)] +#![feature(quote, rustc_private)] extern crate syntax; diff --git a/src/test/run-pass-fulldeps/issue-18502.rs b/src/test/run-pass-fulldeps/issue-18502.rs index 91b24b3b2a..8367fc110e 100644 --- a/src/test/run-pass-fulldeps/issue-18502.rs +++ b/src/test/run-pass-fulldeps/issue-18502.rs @@ -10,7 +10,7 @@ // aux-build:issue-18502.rs -extern crate "issue-18502" as fmt; +extern crate issue_18502 as fmt; fn main() { ::fmt::baz(); diff --git a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs index aeb6a89a98..e1ef32b64d 100644 --- a/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs +++ b/src/test/run-pass-fulldeps/issue-18763-quote-token-tree.rs @@ -11,7 +11,7 @@ // ignore-android // ignore-pretty: does not work well with `--test` -#![feature(quote)] +#![feature(quote, rustc_private)] extern crate syntax; @@ -20,11 +20,11 @@ use syntax::ext::base::ExtCtxt; fn syntax_extension(cx: &ExtCtxt) { let _toks_1 = vec![quote_tokens!(cx, /** comment */ fn foo() {})]; let name = quote_tokens!(cx, bar); - let _toks_2 = vec![quote_item!(cx, static $name:int = 2;)]; + let _toks_2 = vec![quote_item!(cx, static $name:isize = 2;)]; let _toks_4 = quote_tokens!(cx, $name:static $name:sizeof); let _toks_3 = vec![quote_item!(cx, /// comment - fn foo() { let $name:int = 3; } + fn foo() { let $name:isize = 3; } )]; } diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs index 58ccd79b71..7a2846c31b 100644 --- a/src/test/run-pass-fulldeps/macro-crate.rs +++ b/src/test/run-pass-fulldeps/macro-crate.rs @@ -11,7 +11,7 @@ // aux-build:macro_crate_test.rs // ignore-stage1 -#![feature(plugin)] +#![feature(plugin, custom_attribute)] #![plugin(macro_crate_test)] #[macro_use] #[no_link] diff --git a/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs b/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs new file mode 100644 index 0000000000..5383b11cf5 --- /dev/null +++ b/src/test/run-pass-fulldeps/mbe_matching_test_macro.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:procedural_mbe_matching.rs +// ignore-stage1 + +#![feature(plugin)] +#![plugin(procedural_mbe_matching)] + +#[no_link] +extern crate procedural_mbe_matching; + +pub fn main() { + let abc = 123u32; + assert_eq!(matches!(Some(123), None | Some(0)), false); + assert_eq!(matches!(Some(123), None | Some(123)), true); + assert_eq!(matches!(true, true), true); +} diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 252d297d12..7e11b9d9f2 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -60,11 +60,11 @@ fn main() { check_pp(ext_cx, abc, pprust::print_expr, "23".to_string()); - let ty = quote_ty!(cx, int); - check_pp(ext_cx, ty, pprust::print_type, "int".to_string()); + let ty = quote_ty!(cx, isize); + check_pp(ext_cx, ty, pprust::print_type, "isize".to_string()); - let item = quote_item!(cx, static x : int = 10;).get(); - check_pp(ext_cx, item, pprust::print_item, "static x: int = 10;".to_string()); + let item = quote_item!(cx, static x : isize = 10;).get(); + check_pp(ext_cx, item, pprust::print_item, "static x: isize = 10;".to_string()); let stmt = quote_stmt!(cx, let x = 20;); check_pp(ext_cx, *stmt, pprust::print_stmt, "let x = 20;".to_string()); @@ -74,6 +74,9 @@ fn main() { let arm = quote_arm!(cx, (ref x, ref y) => (x, y)); check_pp(ext_cx, arm, pprust::print_stmt, "(ref x, ref y) = (x, y)".to_string()); + + let attr = quote_attr!(cx, #![cfg(foo = "bar")]); + check_pp(ext_cx, attr, pprust::print_attribute, "#![cfg(foo = "bar")]".to_string()); } fn check_pp(cx: fake_ext_ctxt, diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index e76c379177..f6ae71f8b6 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -11,7 +11,7 @@ // ignore-android // ignore-pretty: does not work well with `--test` -#![feature(quote)] +#![feature(quote, rustc_private)] extern crate syntax; @@ -23,9 +23,9 @@ fn syntax_extension(cx: &ExtCtxt) { let p_toks : Vec = quote_tokens!(cx, (x, 1 .. 4, *)); let a: P = quote_expr!(cx, 1 + 2); - let _b: Option> = quote_item!(cx, static foo : int = $e_toks; ); + let _b: Option> = quote_item!(cx, static foo : isize = $e_toks; ); let _c: P = quote_pat!(cx, (x, 1 .. 4, *) ); - let _d: P = quote_stmt!(cx, let x = $a; ); + let _d: Option> = quote_stmt!(cx, let x = $a; ); let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) ); let _e: P = quote_expr!(cx, match foo { $p_toks => 10 } ); @@ -36,10 +36,12 @@ fn syntax_extension(cx: &ExtCtxt) { let i: Option> = quote_item!(cx, #[derive(Eq)] struct Foo; ); assert!(i.is_some()); - let _j: P = quote_method!(cx, fn foo(&self) {}); - let _k: P = quote_method!(cx, #[doc = "hello"] fn foo(&self) {}); + let _l: P = quote_ty!(cx, &isize); - let _l: P = quote_ty!(cx, &int); + let _m: Vec = quote_matcher!(cx, $($foo:tt,)* bar); + let _n: syntax::ast::Attribute = quote_attr!(cx, #![cfg(foo, bar = "baz")]); + + let _o: Option> = quote_item!(cx, fn foo() {}); } fn main() { diff --git a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs index 848ea738ed..928368fabd 100644 --- a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs +++ b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs @@ -11,7 +11,7 @@ // ignore-android // ignore-pretty: does not work well with `--test` -#![feature(quote)] +#![feature(quote, rustc_private)] #![deny(unused_variable)] extern crate syntax; diff --git a/src/test/run-pass-fulldeps/rename-directory.rs b/src/test/run-pass-fulldeps/rename-directory.rs new file mode 100644 index 0000000000..a1e016bf2e --- /dev/null +++ b/src/test/run-pass-fulldeps/rename-directory.rs @@ -0,0 +1,41 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This test can't be a unit test in std, +// because it needs TempDir, which is in extra + +// ignore-android +// pretty-expanded FIXME #23616 + +#![feature(rustc_private, path_ext)] + +extern crate rustc_back; + +use std::ffi::CString; +use std::fs::{self, File, PathExt}; +use rustc_back::tempdir::TempDir; + +fn rename_directory() { + let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed"); + let tmpdir = tmpdir.path(); + let old_path = tmpdir.join("foo/bar/baz"); + fs::create_dir_all(&old_path).unwrap(); + let test_file = &old_path.join("temp.txt"); + + File::create(test_file).unwrap(); + + let new_path = tmpdir.join("quux/blat"); + fs::create_dir_all(&new_path).unwrap(); + fs::rename(&old_path, &new_path.join("newdir")); + assert!(new_path.join("newdir").is_dir()); + assert!(new_path.join("newdir/temp.txt").exists()); +} + +pub fn main() { rename_directory() } diff --git a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs index b7570eb092..23096828c4 100644 --- a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs +++ b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs @@ -12,7 +12,7 @@ // aux-build:syntax_extension_with_dll_deps_2.rs // ignore-stage1 -#![feature(plugin)] +#![feature(plugin, rustc_private)] #![plugin(syntax_extension_with_dll_deps_2)] fn main() { diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs index aecec44f6f..0bbb9ed128 100644 --- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -36,4 +36,3 @@ pub fn main() { assert!(DROP_RAN); } } - diff --git a/src/test/run-pass-valgrind/cleanup-stdin.rs b/src/test/run-pass-valgrind/cleanup-stdin.rs index c16f1f4c84..301c4b9178 100644 --- a/src/test/run-pass-valgrind/cleanup-stdin.rs +++ b/src/test/run-pass-valgrind/cleanup-stdin.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(old_io, io)] + fn main() { let _ = std::old_io::stdin(); + let _ = std::io::stdin(); } diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index c49a684de9..d051b7b491 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - static mut DROP_RAN: bool = false; struct Foo; @@ -28,7 +26,8 @@ struct Fat { pub fn main() { { - let _x: Box> = box Fat { f: Foo }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let _x: Box> = Box::>::new(Fat { f: Foo }); } unsafe { assert!(DROP_RAN); diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs index 2c7b89d680..59b593b1ab 100644 --- a/src/test/run-pass-valgrind/dst-dtor-2.rs +++ b/src/test/run-pass-valgrind/dst-dtor-2.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - -static mut DROP_RAN: int = 0; +static mut DROP_RAN: isize = 0; struct Foo; impl Drop for Foo { @@ -25,7 +23,8 @@ struct Fat { pub fn main() { { - let _x: Box> = box Fat { f: [Foo, Foo, Foo] }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let _x: Box> = Box::>::new(Fat { f: [Foo, Foo, Foo] }); } unsafe { assert!(DROP_RAN == 3); diff --git a/src/test/run-pass/alias-uninit-value.rs b/src/test/run-pass/alias-uninit-value.rs index b1bebf0b3e..77b9efb001 100644 --- a/src/test/run-pass/alias-uninit-value.rs +++ b/src/test/run-pass/alias-uninit-value.rs @@ -12,12 +12,14 @@ // Regression test for issue #374 +// pretty-expanded FIXME #23616 + enum sty { ty_nil, } -struct RawT {struct_: sty, cname: Option, hash: uint} +struct RawT {struct_: sty, cname: Option, hash: usize} fn mk_raw_ty(st: sty, cname: Option) -> RawT { - return RawT {struct_: st, cname: cname, hash: 0_usize}; + return RawT {struct_: st, cname: cname, hash: 0}; } pub fn main() { mk_raw_ty(sty::ty_nil, None::); } diff --git a/src/test/run-pass/alloca-from-derived-tydesc.rs b/src/test/run-pass/alloca-from-derived-tydesc.rs index c356d1d527..23a1e79980 100644 --- a/src/test/run-pass/alloca-from-derived-tydesc.rs +++ b/src/test/run-pass/alloca-from-derived-tydesc.rs @@ -9,10 +9,12 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + enum option { some(T), none, } struct R {v: Vec> } fn f() -> Vec { return Vec::new(); } -pub fn main() { let mut r: R = R {v: Vec::new()}; r.v = f(); } +pub fn main() { let mut r: R = R {v: Vec::new()}; r.v = f(); } diff --git a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs index 0ef6660311..b40774e2be 100644 --- a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs +++ b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:anon-extern-mod-cross-crate-1.rs +// pretty-expanded FIXME #23616 + extern crate anonexternmod; use anonexternmod::rust_get_test_int; diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs index 78e1cdabb4..e96b0cc144 100644 --- a/src/test/run-pass/anon-extern-mod.rs +++ b/src/test/run-pass/anon-extern-mod.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; #[link(name = "rust_test_helpers")] diff --git a/src/test/run-pass/anon-trait-static-method.rs b/src/test/run-pass/anon-trait-static-method.rs index 98975c7f02..5889bfce3c 100644 --- a/src/test/run-pass/anon-trait-static-method.rs +++ b/src/test/run-pass/anon-trait-static-method.rs @@ -9,7 +9,7 @@ // except according to those terms. struct Foo { - x: int + x: isize } impl Foo { diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs index dfce311529..7101cfb557 100644 --- a/src/test/run-pass/argument-passing.rs +++ b/src/test/run-pass/argument-passing.rs @@ -9,18 +9,20 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct X { - x: int + x: isize } -fn f1(a: &mut X, b: &mut int, c: int) -> int { +fn f1(a: &mut X, b: &mut isize, c: isize) -> isize { let r = a.x + *b + c; a.x = 0; *b = 10; return r; } -fn f2(a: int, f: F) -> int where F: FnOnce(int) { f(1); return a; } +fn f2(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; } pub fn main() { let mut a = X {x: 1}; diff --git a/src/test/run-pass/arith-0.rs b/src/test/run-pass/arith-0.rs index 24c63e5aff..a4365efbbb 100644 --- a/src/test/run-pass/arith-0.rs +++ b/src/test/run-pass/arith-0.rs @@ -11,7 +11,7 @@ pub fn main() { - let a: int = 10; + let a: isize = 10; println!("{}", a); assert_eq!(a * (a - 1), 90); } diff --git a/src/test/run-pass/arith-1.rs b/src/test/run-pass/arith-1.rs index 1e043d77fa..fd281ea117 100644 --- a/src/test/run-pass/arith-1.rs +++ b/src/test/run-pass/arith-1.rs @@ -11,7 +11,7 @@ pub fn main() { - let i32_a: int = 10; + let i32_a: isize = 10; assert_eq!(i32_a, 10); assert_eq!(i32_a - 10, 0); assert_eq!(i32_a / 10, 1); @@ -22,8 +22,8 @@ pub fn main() { assert_eq!(i32_a * i32_a * i32_a, 1000); assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000); assert_eq!(i32_a * i32_a / i32_a * i32_a, 100); - assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as uint), 368640); - let i32_b: int = 0x10101010; + assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640); + let i32_b: isize = 0x10101010; assert_eq!(i32_b + 1 - 1, i32_b); assert_eq!(i32_b << 1, i32_b << 1); assert_eq!(i32_b >> 1, i32_b >> 1); diff --git a/src/test/run-pass/arith-2.rs b/src/test/run-pass/arith-2.rs index 70df6e46e5..0f4523c681 100644 --- a/src/test/run-pass/arith-2.rs +++ b/src/test/run-pass/arith-2.rs @@ -10,8 +10,10 @@ +// pretty-expanded FIXME #23616 + pub fn main() { - let i32_c: int = 0x10101010; + let i32_c: isize = 0x10101010; assert!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3) == i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3)); } diff --git a/src/test/run-pass/arith-unsigned.rs b/src/test/run-pass/arith-unsigned.rs index 43288d9044..8a0fc8adc1 100644 --- a/src/test/run-pass/arith-unsigned.rs +++ b/src/test/run-pass/arith-unsigned.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(type_limits)] // Unsigned integer operations diff --git a/src/test/run-pass/artificial-block.rs b/src/test/run-pass/artificial-block.rs index 7bc1354c3c..3348a6754e 100644 --- a/src/test/run-pass/artificial-block.rs +++ b/src/test/run-pass/artificial-block.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f() -> int { { return 3; } } +// pretty-expanded FIXME #23616 + +fn f() -> isize { { return 3; } } pub fn main() { assert!((f() == 3)); } diff --git a/src/test/run-pass/as-precedence.rs b/src/test/run-pass/as-precedence.rs index 0760f13200..8e38128975 100644 --- a/src/test/run-pass/as-precedence.rs +++ b/src/test/run-pass/as-precedence.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { - assert_eq!(3 as uint * 3, 9); - assert_eq!(3 as (uint) * 3, 9); - assert_eq!(3 as (uint) / 3, 1); - assert_eq!(3 as uint + 3, 6); - assert_eq!(3 as (uint) + 3, 6); + assert_eq!(3 as usize * 3, 9); + assert_eq!(3 as (usize) * 3, 9); + assert_eq!(3 as (usize) / 3, 1); + assert_eq!(3 as usize + 3, 6); + assert_eq!(3 as (usize) + 3, 6); } - diff --git a/src/test/run-pass/asm-concat-src.rs b/src/test/run-pass/asm-concat-src.rs index 9df96b35ce..716c3d47a0 100644 --- a/src/test/run-pass/asm-concat-src.rs +++ b/src/test/run-pass/asm-concat-src.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(asm)] pub fn main() { diff --git a/src/test/run-pass/asm-in-out-operand.rs b/src/test/run-pass/asm-in-out-operand.rs index 3ac8e4d0ee..32924bcf74 100644 --- a/src/test/run-pass/asm-in-out-operand.rs +++ b/src/test/run-pass/asm-in-out-operand.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(asm)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -34,8 +36,8 @@ pub fn main() { assert_eq!(2147483648, next_power_of_2(2147483647)); } - let mut y: int = 5; - let x: int; + let mut y: isize = 5; + let x: isize; unsafe { // Treat the output as initialization. asm!( diff --git a/src/test/run-pass/asm-out-assign.rs b/src/test/run-pass/asm-out-assign.rs index 0f6fec133d..3cb7f6400d 100644 --- a/src/test/run-pass/asm-out-assign.rs +++ b/src/test/run-pass/asm-out-assign.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(asm)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn main() { - let x: int; + let x: isize; unsafe { // Treat the output as initialization. asm!("mov $1, $0" : "=r"(x) : "r"(5_usize)); diff --git a/src/test/run-pass/assert-eq-macro-success.rs b/src/test/run-pass/assert-eq-macro-success.rs index e55a2d39cb..9662e1ff33 100644 --- a/src/test/run-pass/assert-eq-macro-success.rs +++ b/src/test/run-pass/assert-eq-macro-success.rs @@ -8,15 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] - #[derive(PartialEq, Debug)] -struct Point { x : int } +struct Point { x : isize } pub fn main() { assert_eq!(14,14); assert_eq!("abc".to_string(),"abc".to_string()); - assert_eq!(box Point{x:34},box Point{x:34}); + assert_eq!(Box::new(Point{x:34}),Box::new(Point{x:34})); assert_eq!(&Point{x:34},&Point{x:34}); } diff --git a/src/test/run-pass/assign-assign.rs b/src/test/run-pass/assign-assign.rs index 0f5d27015f..110f4720ce 100644 --- a/src/test/run-pass/assign-assign.rs +++ b/src/test/run-pass/assign-assign.rs @@ -9,8 +9,10 @@ // except according to those terms. // Issue 483 - Assignment expressions result in nil +// pretty-expanded FIXME #23616 + fn test_assign() { - let mut x: int; + let mut x: isize; let y: () = x = 10; assert_eq!(x, 10); assert_eq!(y, ()); @@ -23,7 +25,7 @@ fn test_assign() { } fn test_assign_op() { - let mut x: int = 0; + let mut x: isize = 0; let y: () = x += 10; assert_eq!(x, 10); assert_eq!(y, ()); diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs index 57c5051160..473f744a3f 100644 --- a/src/test/run-pass/assignability-trait.rs +++ b/src/test/run-pass/assignability-trait.rs @@ -12,6 +12,8 @@ // making method calls, but only if there aren't any matches without // it. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] trait iterable { @@ -30,7 +32,7 @@ impl iterable for Vec { } } -fn length>(x: T) -> uint { +fn length>(x: T) -> usize { let mut len = 0; x.iterate(|_y| { len += 1; @@ -40,17 +42,17 @@ fn length>(x: T) -> uint { } pub fn main() { - let x: Vec = vec!(0,1,2,3); + let x: Vec = vec!(0,1,2,3); // Call a method - x.iterate(|y| { assert!(x[*y as uint] == *y); true }); + x.iterate(|y| { assert!(x[*y as usize] == *y); true }); // Call a parameterized function assert_eq!(length(x.clone()), x.len()); // Call a parameterized function, with type arguments that require // a borrow - assert_eq!(length::(&*x), x.len()); + assert_eq!(length::(&*x), x.len()); // Now try it with a type that *needs* to be borrowed let z = [0,1,2,3]; // Call a parameterized function - assert_eq!(length::(&z), z.len()); + assert_eq!(length::(&z), z.len()); } diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs index f5521f7da8..d4ed2ee2d6 100644 --- a/src/test/run-pass/associated-types-basic.rs +++ b/src/test/run-pass/associated-types-basic.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::marker::MarkerTrait; trait Foo : MarkerTrait { @@ -15,11 +19,11 @@ trait Foo : MarkerTrait { } impl Foo for i32 { - type T = int; + type T = isize; } fn main() { let x: ::T = 22; - let y: int = 44; + let y: isize = 44; assert_eq!(x * 2, y); } diff --git a/src/test/run-pass/associated-types-binding-in-trait.rs b/src/test/run-pass/associated-types-binding-in-trait.rs index b47b0109bd..39fc224148 100644 --- a/src/test/run-pass/associated-types-binding-in-trait.rs +++ b/src/test/run-pass/associated-types-binding-in-trait.rs @@ -11,6 +11,8 @@ // Test a case where the associated type binding (to `bool`, in this // case) is derived from the trait definition. Issue #21636. +// pretty-expanded FIXME #23616 + use std::vec; pub trait BitIter { diff --git a/src/test/run-pass/associated-types-binding-in-where-clause.rs b/src/test/run-pass/associated-types-binding-in-where-clause.rs index 2f9a0b328b..82ebac7e5d 100644 --- a/src/test/run-pass/associated-types-binding-in-where-clause.rs +++ b/src/test/run-pass/associated-types-binding-in-where-clause.rs @@ -10,17 +10,19 @@ // Test equality constraints on associated types in a where clause. +// pretty-expanded FIXME #23616 + pub trait Foo { type A; fn boo(&self) -> ::A; } #[derive(PartialEq)] -struct Bar; +pub struct Bar; -impl Foo for int { - type A = uint; - fn boo(&self) -> uint { 42 } +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } } impl Foo for char { @@ -32,7 +34,7 @@ fn foo_bar>(x: I) -> Bar { x.boo() } -fn foo_uint>(x: I) -> uint { +fn foo_uint>(x: I) -> usize { x.boo() } diff --git a/src/test/run-pass/associated-types-bound.rs b/src/test/run-pass/associated-types-bound.rs index 9f97d69ce3..2301821f66 100644 --- a/src/test/run-pass/associated-types-bound.rs +++ b/src/test/run-pass/associated-types-bound.rs @@ -10,6 +10,8 @@ // Test equality constrai32s on associated types in a where clause. +// pretty-expanded FIXME #23616 + pub trait ToI32 { fn to_i32(&self) -> i32; } diff --git a/src/test/run-pass/associated-types-cc.rs b/src/test/run-pass/associated-types-cc.rs index 948192f4fc..b2be87be4c 100644 --- a/src/test/run-pass/associated-types-cc.rs +++ b/src/test/run-pass/associated-types-cc.rs @@ -13,7 +13,7 @@ // Test that we are able to reference cross-crate traits that employ // associated types. -extern crate "associated-types-cc-lib" as bar; +extern crate associated_types_cc_lib as bar; use bar::Bar; diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index aa65b0ed10..1a8da67555 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -14,6 +14,8 @@ // `Target=[A]`, then the impl marked with `(*)` is seen to conflict // with all the others. +// pretty-expanded FIXME #23616 + use std::marker::PhantomData; use std::ops::Deref; diff --git a/src/test/run-pass/associated-types-constant-type.rs b/src/test/run-pass/associated-types-constant-type.rs index 57e9230336..5729fab475 100644 --- a/src/test/run-pass/associated-types-constant-type.rs +++ b/src/test/run-pass/associated-types-constant-type.rs @@ -8,32 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait SignedUnsigned { type Opposite; fn convert(self) -> Self::Opposite; } -impl SignedUnsigned for int { - type Opposite = uint; +impl SignedUnsigned for isize { + type Opposite = usize; - fn convert(self) -> uint { - self as uint + fn convert(self) -> usize { + self as usize } } -impl SignedUnsigned for uint { - type Opposite = int; +impl SignedUnsigned for usize { + type Opposite = isize; - fn convert(self) -> int { - self as int + fn convert(self) -> isize { + self as isize } } -fn get(x: int) -> ::Opposite { +fn get(x: isize) -> ::Opposite { x.convert() } fn main() { let x = get(22); - assert_eq!(22_usize, x); + assert_eq!(22, x); } diff --git a/src/test/run-pass/associated-types-doubleendediterator-object.rs b/src/test/run-pass/associated-types-doubleendediterator-object.rs index 7365e05217..5dc289194f 100644 --- a/src/test/run-pass/associated-types-doubleendediterator-object.rs +++ b/src/test/run-pass/associated-types-doubleendediterator-object.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn pairwise_sub(mut t: Box>) -> int { +fn pairwise_sub(mut t: Box>) -> isize { let mut result = 0; loop { let front = t.next(); @@ -25,6 +27,7 @@ fn pairwise_sub(mut t: Box>) -> int { fn main() { let v = vec!(1, 2, 3, 4, 5, 6); - let r = pairwise_sub(box v.into_iter()); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let r = pairwise_sub(Box::new(v.into_iter())); assert_eq!(r, 9); } diff --git a/src/test/run-pass/associated-types-duplicate-binding-in-env-hrtb.rs b/src/test/run-pass/associated-types-duplicate-binding-in-env-hrtb.rs index 8b7ea61dc7..8ca3bc0254 100644 --- a/src/test/run-pass/associated-types-duplicate-binding-in-env-hrtb.rs +++ b/src/test/run-pass/associated-types-duplicate-binding-in-env-hrtb.rs @@ -12,6 +12,8 @@ // (modulo bound lifetime names) appears in the environment // twice. Issue #21965. +// pretty-expanded FIXME #23616 + fn foo(t: T) -> i32 where T : for<'a> Fn(&'a u8) -> i32, T : for<'b> Fn(&'b u8) -> i32, diff --git a/src/test/run-pass/associated-types-duplicate-binding-in-env.rs b/src/test/run-pass/associated-types-duplicate-binding-in-env.rs index 62ac218795..5878f5dd51 100644 --- a/src/test/run-pass/associated-types-duplicate-binding-in-env.rs +++ b/src/test/run-pass/associated-types-duplicate-binding-in-env.rs @@ -11,6 +11,8 @@ // Check that we do not report ambiguities when the same predicate // appears in the environment twice. Issue #21965. +// pretty-expanded FIXME #23616 + trait Foo { type B; diff --git a/src/test/run-pass/associated-types-enum-field-named.rs b/src/test/run-pass/associated-types-enum-field-named.rs index a499aa6733..8cf97fe62f 100644 --- a/src/test/run-pass/associated-types-enum-field-named.rs +++ b/src/test/run-pass/associated-types-enum-field-named.rs @@ -10,6 +10,8 @@ // Test associated types appearing in struct-like enum variants. +// pretty-expanded FIXME #23616 + use self::VarValue::*; pub trait UnifyKey { diff --git a/src/test/run-pass/associated-types-enum-field-numbered.rs b/src/test/run-pass/associated-types-enum-field-numbered.rs index e710c53327..3c57da6b4a 100644 --- a/src/test/run-pass/associated-types-enum-field-numbered.rs +++ b/src/test/run-pass/associated-types-enum-field-numbered.rs @@ -10,6 +10,8 @@ // Test associated types appearing in tuple-like enum variants. +// pretty-expanded FIXME #23616 + use self::VarValue::*; pub trait UnifyKey { diff --git a/src/test/run-pass/associated-types-eq-obj.rs b/src/test/run-pass/associated-types-eq-obj.rs index 0ec8a36619..feccd1d2dc 100644 --- a/src/test/run-pass/associated-types-eq-obj.rs +++ b/src/test/run-pass/associated-types-eq-obj.rs @@ -10,12 +10,14 @@ // Test equality constraints on associated types inside of an object type +// pretty-expanded FIXME #23616 + pub trait Foo { type A; fn boo(&self) -> ::A; } -struct Bar; +pub struct Bar; impl Foo for char { type A = Bar; diff --git a/src/test/run-pass/associated-types-in-default-method.rs b/src/test/run-pass/associated-types-in-default-method.rs index 0ae6103715..2a1b9bdd2f 100644 --- a/src/test/run-pass/associated-types-in-default-method.rs +++ b/src/test/run-pass/associated-types-in-default-method.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Get { type Value; fn get(&self) -> &::Value; @@ -17,12 +19,12 @@ trait Get { } struct Struct { - x: int, + x: isize, } impl Get for Struct { - type Value = int; - fn get(&self) -> &int { + type Value = isize; + fn get(&self) -> &isize { &self.x } } diff --git a/src/test/run-pass/associated-types-in-fn.rs b/src/test/run-pass/associated-types-in-fn.rs index 4104f520a0..40b10fbfca 100644 --- a/src/test/run-pass/associated-types-in-fn.rs +++ b/src/test/run-pass/associated-types-in-fn.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Get { type Value; fn get(&self) -> &::Value; } struct Struct { - x: int, + x: isize, } impl Get for Struct { - type Value = int; - fn get(&self) -> &int { + type Value = isize; + fn get(&self) -> &isize { &self.x } } diff --git a/src/test/run-pass/associated-types-in-impl-generics.rs b/src/test/run-pass/associated-types-in-impl-generics.rs index 59f05e1184..99a9b7c23f 100644 --- a/src/test/run-pass/associated-types-in-impl-generics.rs +++ b/src/test/run-pass/associated-types-in-impl-generics.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Get { type Value; fn get(&self) -> &::Value; } struct Struct { - x: int, + x: isize, } impl Get for Struct { - type Value = int; - fn get(&self) -> &int { + type Value = isize; + fn get(&self) -> &isize { &self.x } } diff --git a/src/test/run-pass/associated-types-in-inherent-method.rs b/src/test/run-pass/associated-types-in-inherent-method.rs index 951497709f..0012d9d759 100644 --- a/src/test/run-pass/associated-types-in-inherent-method.rs +++ b/src/test/run-pass/associated-types-in-inherent-method.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Get { type Value; fn get(&self) -> &::Value; } struct Struct { - x: int, + x: isize, } impl Get for Struct { - type Value = int; - fn get(&self) -> &int { + type Value = isize; + fn get(&self) -> &isize { &self.x } } diff --git a/src/test/run-pass/associated-types-issue-20220.rs b/src/test/run-pass/associated-types-issue-20220.rs index a253fbde56..718ea54279 100644 --- a/src/test/run-pass/associated-types-issue-20220.rs +++ b/src/test/run-pass/associated-types-issue-20220.rs @@ -10,6 +10,8 @@ // Test references to `Self::Item` in the trait. Issue #20220. +// pretty-expanded FIXME #23616 + use std::vec; trait IntoIteratorX { diff --git a/src/test/run-pass/associated-types-issue-20371.rs b/src/test/run-pass/associated-types-issue-20371.rs index 40ef7f3531..a601dc0739 100644 --- a/src/test/run-pass/associated-types-issue-20371.rs +++ b/src/test/run-pass/associated-types-issue-20371.rs @@ -11,8 +11,12 @@ // Test that we are able to have an impl that defines an associated type // before the actual trait. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::marker::MarkerTrait; -impl X for f64 { type Y = int; } +impl X for f64 { type Y = isize; } trait X : MarkerTrait { type Y; } fn main() {} diff --git a/src/test/run-pass/associated-types-issue-21212.rs b/src/test/run-pass/associated-types-issue-21212.rs index 3c91577362..057677a008 100644 --- a/src/test/run-pass/associated-types-issue-21212.rs +++ b/src/test/run-pass/associated-types-issue-21212.rs @@ -13,6 +13,8 @@ // where clauses in the environment which in turn required normalizing // `Self::Input`. +// pretty-expanded FIXME #23616 + pub trait Parser { type Input; diff --git a/src/test/run-pass/associated-types-iterator-binding.rs b/src/test/run-pass/associated-types-iterator-binding.rs index f8258466a7..24c5a3e9a8 100644 --- a/src/test/run-pass/associated-types-iterator-binding.rs +++ b/src/test/run-pass/associated-types-iterator-binding.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn pairwise_sub>(mut t: T) -> int { +// pretty-expanded FIXME #23616 + +fn pairwise_sub>(mut t: T) -> isize { let mut result = 0; loop { let front = t.next(); diff --git a/src/test/run-pass/associated-types-nested-projections.rs b/src/test/run-pass/associated-types-nested-projections.rs index 2ee8ef0d3d..a26b428a4e 100644 --- a/src/test/run-pass/associated-types-nested-projections.rs +++ b/src/test/run-pass/associated-types-nested-projections.rs @@ -10,6 +10,10 @@ // Test that we can resolve nested projection types. Issue #20666. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::marker::MarkerTrait; use std::slice; diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs index de96af83f5..d95ad2e883 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs @@ -11,6 +11,9 @@ // Test that we normalize associated types that appear in a bound that // contains a binding. Issue #21664. +// pretty-expanded FIXME #23616 + +#![feature(core)] #![allow(dead_code)] use std::marker::MarkerTrait; diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs index 8617750ca5..d8e4c5218d 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs @@ -11,6 +11,8 @@ // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. +// pretty-expanded FIXME #23616 + use std::marker::PhantomData; struct Splits<'a, T:'a, P>(PhantomData<(&'a T, P)>); diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs index 94cfcb8365..ff08e7b69b 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -11,6 +11,8 @@ // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. +// pretty-expanded FIXME #23616 + use std::marker::PhantomData; struct Splits<'a, T, P>(PhantomData<(&'a(),T,P)>); diff --git a/src/test/run-pass/associated-types-normalize-unifield-struct.rs b/src/test/run-pass/associated-types-normalize-unifield-struct.rs index 2288e19aae..3dffae9929 100644 --- a/src/test/run-pass/associated-types-normalize-unifield-struct.rs +++ b/src/test/run-pass/associated-types-normalize-unifield-struct.rs @@ -12,16 +12,18 @@ // various special paths in the `type_is_immediate` function. +// pretty-expanded FIXME #23616 + pub trait OffsetState: Sized {} pub trait Offset { type State: OffsetState; fn dummy(&self) { } } -#[derive(Copy)] pub struct X; +#[derive(Copy, Clone)] pub struct X; impl Offset for X { type State = Y; } -#[derive(Copy)] pub struct Y; +#[derive(Copy, Clone)] pub struct Y; impl OffsetState for Y {} pub fn now() -> DateTime { from_utc(Y) } diff --git a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs new file mode 100644 index 0000000000..151a9da948 --- /dev/null +++ b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs @@ -0,0 +1,111 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Various uses of `T::Item` syntax where the bound that supplies +// `Item` originates in a where-clause, not the declaration of +// `T`. Issue #20300. + +// pretty-expanded FIXME #23616 + +#![feature(core)] + +use std::marker::{MarkerTrait, PhantomData}; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; +use std::sync::atomic::Ordering::SeqCst; + +static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT; + +// Preamble. +trait Trait : MarkerTrait { type Item; } +struct Struct; +impl Trait for Struct { + type Item = u32; +} + +// Where-clause attached on the method which declares `T`. +struct A; +impl A { + fn foo(_x: T::Item) where T: Trait { + COUNTER.fetch_add(1, SeqCst); + } +} + +// Where-clause attached on the method to a parameter from the struct. +struct B(PhantomData); +impl B { + fn foo(_x: T::Item) where T: Trait { + COUNTER.fetch_add(10, SeqCst); + } +} + +// Where-clause attached to free fn. +fn c(_: T::Item) where T : Trait { + COUNTER.fetch_add(100, SeqCst); +} + +// Where-clause attached to defaulted and non-defaulted trait method. +trait AnotherTrait { + fn method(&self, _: T::Item) where T: Trait; + fn default_method(&self, _: T::Item) where T: Trait { + COUNTER.fetch_add(1000, SeqCst); + } +} +struct D; +impl AnotherTrait for D { + fn method(&self, _: T::Item) where T: Trait { + COUNTER.fetch_add(10000, SeqCst); + } +} + +// Where-clause attached to trait and impl containing the method. +trait YetAnotherTrait + where T : Trait +{ + fn method(&self, _: T::Item); + fn default_method(&self, _: T::Item) { + COUNTER.fetch_add(100000, SeqCst); + } +} +struct E(PhantomData); +impl YetAnotherTrait for E + where T : Trait +{ + fn method(&self, _: T::Item) { + COUNTER.fetch_add(1000000, SeqCst); + } +} + +// Where-clause attached to inherent impl containing the method. +struct F(PhantomData); +impl F where T : Trait { + fn method(&self, _: T::Item) { + COUNTER.fetch_add(10000000, SeqCst); + } +} + +// Where-clause attached to struct. +#[allow(dead_code)] +struct G where T : Trait { + data: T::Item, + phantom: PhantomData, +} + +fn main() { + A::foo::(22); + B::::foo(22); + c::(22); + D.method::(22); + D.default_method::(22); + E(PhantomData::).method(22); + E(PhantomData::).default_method(22); + F(PhantomData::).method(22); + G:: { data: 22, phantom: PhantomData }; + assert_eq!(COUNTER.load(SeqCst), 11111111); +} diff --git a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs index 24dae20b3e..e150d01582 100644 --- a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs +++ b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs @@ -20,8 +20,8 @@ trait Not { } trait Int: Not + Sized { - fn count_ones(self) -> uint; - fn count_zeros(self) -> uint { + fn count_ones(self) -> usize; + fn count_zeros(self) -> usize { // neither works let x: Self = self.not(); 0 diff --git a/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs b/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs index c65d2db9b0..2518ccf1cb 100644 --- a/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs +++ b/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs @@ -10,6 +10,8 @@ // Test where the impl self type uses a projection from a constant type. +// pretty-expanded FIXME #23616 + trait Int { type T; diff --git a/src/test/run-pass/associated-types-projection-in-object-type.rs b/src/test/run-pass/associated-types-projection-in-object-type.rs index a9c34a605c..3b146792fd 100644 --- a/src/test/run-pass/associated-types-projection-in-object-type.rs +++ b/src/test/run-pass/associated-types-projection-in-object-type.rs @@ -13,6 +13,8 @@ // appear in associated type bindings in object types, which were not // being properly flagged. +// pretty-expanded FIXME #23616 + use std::ops::{Shl, Shr}; use std::cell::RefCell; diff --git a/src/test/run-pass/associated-types-projection-in-supertrait.rs b/src/test/run-pass/associated-types-projection-in-supertrait.rs index 4d2358fae2..dbc2164c93 100644 --- a/src/test/run-pass/associated-types-projection-in-supertrait.rs +++ b/src/test/run-pass/associated-types-projection-in-supertrait.rs @@ -11,6 +11,8 @@ // Test that we are handle to correctly handle a projection type // that appears in a supertrait bound. Issue #20559. +// pretty-expanded FIXME #23616 + trait A { type TA; diff --git a/src/test/run-pass/associated-types-projection-in-where-clause.rs b/src/test/run-pass/associated-types-projection-in-where-clause.rs index 3f3f4fbd1d..80e3aa09e3 100644 --- a/src/test/run-pass/associated-types-projection-in-where-clause.rs +++ b/src/test/run-pass/associated-types-projection-in-where-clause.rs @@ -10,6 +10,8 @@ // Test a where clause that uses a non-normalized projection type. +// pretty-expanded FIXME #23616 + trait Int { type T; diff --git a/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs b/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs index abbde16fae..a69de216ab 100644 --- a/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs +++ b/src/test/run-pass/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { type Bar; fn get_bar() -> >::Bar; diff --git a/src/test/run-pass/associated-types-ref-from-struct.rs b/src/test/run-pass/associated-types-ref-from-struct.rs index 3c7cc7c497..ce09ec60bd 100644 --- a/src/test/run-pass/associated-types-ref-from-struct.rs +++ b/src/test/run-pass/associated-types-ref-from-struct.rs @@ -10,6 +10,8 @@ // Test associated type references in structure fields. +// pretty-expanded FIXME #23616 + trait Test { type V; diff --git a/src/test/run-pass/associated-types-ref-in-struct-literal.rs b/src/test/run-pass/associated-types-ref-in-struct-literal.rs index 67fe11d8fe..945340008d 100644 --- a/src/test/run-pass/associated-types-ref-in-struct-literal.rs +++ b/src/test/run-pass/associated-types-ref-in-struct-literal.rs @@ -10,14 +10,16 @@ // Test associated type references in a struct literal. Issue #20535. +// pretty-expanded FIXME #23616 + pub trait Foo { type Bar; fn dummy(&self) { } } -impl Foo for int { - type Bar = int; +impl Foo for isize { + type Bar = isize; } struct Thing { diff --git a/src/test/run-pass/associated-types-region-erasure-issue-20582.rs b/src/test/run-pass/associated-types-region-erasure-issue-20582.rs index 03ab8f7e43..16e49f146a 100644 --- a/src/test/run-pass/associated-types-region-erasure-issue-20582.rs +++ b/src/test/run-pass/associated-types-region-erasure-issue-20582.rs @@ -11,6 +11,8 @@ // Regression test for #20582. This test caused an ICE related to // inconsistent region erasure in trans. +// pretty-expanded FIXME #23616 + struct Foo<'a> { buf: &'a[u8] } diff --git a/src/test/run-pass/associated-types-resolve-lifetime.rs b/src/test/run-pass/associated-types-resolve-lifetime.rs index a4b0b1a6e0..824291ea60 100644 --- a/src/test/run-pass/associated-types-resolve-lifetime.rs +++ b/src/test/run-pass/associated-types-resolve-lifetime.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Get { fn get(&self) -> T; } trait Trait<'a> { type T: 'static; - type U: Get<&'a int>; + type U: Get<&'a isize>; fn dummy(&'a self) { } } diff --git a/src/test/run-pass/associated-types-return.rs b/src/test/run-pass/associated-types-return.rs index fe24ab6bbe..f190e81d8a 100644 --- a/src/test/run-pass/associated-types-return.rs +++ b/src/test/run-pass/associated-types-return.rs @@ -10,22 +10,24 @@ // Test equality constraints on associated types in a where clause. +// pretty-expanded FIXME #23616 + pub trait Foo { type A; fn boo(&self) -> ::A; } #[derive(PartialEq)] -struct Bar; +pub struct Bar; -impl Foo for int { - type A = uint; - fn boo(&self) -> uint { 42 } +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } } impl Foo for Bar { - type A = int; - fn boo(&self) -> int { 43 } + type A = isize; + fn boo(&self) -> isize { 43 } } impl Foo for char { @@ -43,7 +45,7 @@ fn foo2(x: I) -> ::A { pub fn main() { let a = 42; - assert!(foo2(a) == 42_usize); + assert!(foo2(a) == 42); let a = Bar; assert!(foo2(a) == 43); diff --git a/src/test/run-pass/associated-types-simple.rs b/src/test/run-pass/associated-types-simple.rs index 9e388dc3d3..5a2761365b 100644 --- a/src/test/run-pass/associated-types-simple.rs +++ b/src/test/run-pass/associated-types-simple.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Get { type Value; fn get(&self) -> &::Value; } struct Struct { - x: int, + x: isize, } impl Get for Struct { - type Value = int; - fn get(&self) -> &int { + type Value = isize; + fn get(&self) -> &isize { &self.x } } diff --git a/src/test/run-pass/associated-types-stream.rs b/src/test/run-pass/associated-types-stream.rs index ef7fbe87b3..a2b7cf2106 100644 --- a/src/test/run-pass/associated-types-stream.rs +++ b/src/test/run-pass/associated-types-stream.rs @@ -11,6 +11,8 @@ // Test references to the trait `Stream` in the bounds for associated // types defined on `Stream`. Issue #20551. +// pretty-expanded FIXME #23616 + trait Stream { type Car; type Cdr: Stream; diff --git a/src/test/run-pass/associated-types-struct-field-named.rs b/src/test/run-pass/associated-types-struct-field-named.rs index 8667f6c843..d1872e4fb5 100644 --- a/src/test/run-pass/associated-types-struct-field-named.rs +++ b/src/test/run-pass/associated-types-struct-field-named.rs @@ -11,6 +11,8 @@ // Test that we correctly normalize the type of a struct field // which has an associated type. +// pretty-expanded FIXME #23616 + pub trait UnifyKey { type Value; @@ -36,8 +38,8 @@ impl UnifyKey for u32 { pub fn main() { let node: Node = Node { key: 1, value: Some(22) }; - assert_eq!(foo(&node), Some(22_u32)); + assert_eq!(foo(&node), Some(22)); let node: Node = Node { key: 1, value: Some(22) }; - assert_eq!(foo(&node), Some(22_i32)); + assert_eq!(foo(&node), Some(22)); } diff --git a/src/test/run-pass/associated-types-struct-field-numbered.rs b/src/test/run-pass/associated-types-struct-field-numbered.rs index 9503f78a71..3d97c503dc 100644 --- a/src/test/run-pass/associated-types-struct-field-numbered.rs +++ b/src/test/run-pass/associated-types-struct-field-numbered.rs @@ -11,6 +11,8 @@ // Test that we correctly normalize the type of a struct field // which has an associated type. +// pretty-expanded FIXME #23616 + pub trait UnifyKey { type Value; @@ -33,8 +35,8 @@ impl UnifyKey for u32 { pub fn main() { let node: Node = Node(1, Some(22)); - assert_eq!(foo(&node), Some(22_u32)); + assert_eq!(foo(&node), Some(22)); let node: Node = Node(1, Some(22)); - assert_eq!(foo(&node), Some(22_i32)); + assert_eq!(foo(&node), Some(22)); } diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index c068065ac6..353b49b49c 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -10,14 +10,16 @@ // Test paths to associated types using the type-parameter-only sugar. +// pretty-expanded FIXME #23616 + pub trait Foo { type A; fn boo(&self) -> Self::A; } -impl Foo for int { - type A = uint; - fn boo(&self) -> uint { +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 5 } } @@ -41,5 +43,5 @@ impl C for B { } pub fn main() { - let z: uint = bar(2, 4_usize); + let z: usize = bar(2, 4); } diff --git a/src/test/run-pass/astconv-cycle-between-trait-and-type.rs b/src/test/run-pass/astconv-cycle-between-trait-and-type.rs index 0c6d91eda2..ef2dc48fe1 100644 --- a/src/test/run-pass/astconv-cycle-between-trait-and-type.rs +++ b/src/test/run-pass/astconv-cycle-between-trait-and-type.rs @@ -13,6 +13,8 @@ // carries a predicate that references the trait (`u32 : Trait1`, // substituted). +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Trait1 : Trait2> { diff --git a/src/test/run-pass/attr-before-view-item.rs b/src/test/run-pass/attr-before-view-item.rs index 951a716879..cdd1b96de1 100644 --- a/src/test/run-pass/attr-before-view-item.rs +++ b/src/test/run-pass/attr-before-view-item.rs @@ -10,7 +10,9 @@ // error-pattern:expected item -#![feature(custom_attribute)] +// pretty-expanded FIXME #23616 + +#![feature(custom_attribute, test)] #[foo = "bar"] extern crate test; diff --git a/src/test/run-pass/attr-before-view-item2.rs b/src/test/run-pass/attr-before-view-item2.rs index ad8ce608bd..cd02b5a9e7 100644 --- a/src/test/run-pass/attr-before-view-item2.rs +++ b/src/test/run-pass/attr-before-view-item2.rs @@ -10,7 +10,9 @@ // error-pattern:expected item -#![feature(custom_attribute)] +// pretty-expanded FIXME #23616 + +#![feature(custom_attribute, test)] mod m { #[foo = "bar"] diff --git a/src/test/run-pass/attr-main-2.rs b/src/test/run-pass/attr-main-2.rs index fd0ae0729a..4680f47fad 100644 --- a/src/test/run-pass/attr-main-2.rs +++ b/src/test/run-pass/attr-main-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(main)] pub fn main() { diff --git a/src/test/run-pass/attr-main.rs b/src/test/run-pass/attr-main.rs index 29b504bed5..e8a12ee3ac 100644 --- a/src/test/run-pass/attr-main.rs +++ b/src/test/run-pass/attr-main.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(main)] #[main] diff --git a/src/test/run-pass/attr-mix-new.rs b/src/test/run-pass/attr-mix-new.rs index 7980937ce2..bcfb4b330f 100644 --- a/src/test/run-pass/attr-mix-new.rs +++ b/src/test/run-pass/attr-mix-new.rs @@ -7,6 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_attribute)] #![feature(custom_attribute)] diff --git a/src/test/run-pass/attr-no-drop-flag-size.rs b/src/test/run-pass/attr-no-drop-flag-size.rs index bd79991784..af8e4b7d4a 100644 --- a/src/test/run-pass/attr-no-drop-flag-size.rs +++ b/src/test/run-pass/attr-no-drop-flag-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] #![feature(unsafe_no_drop_flag)] @@ -24,5 +26,5 @@ impl Drop for Test { } pub fn main() { - assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::(), size_of::>()); } diff --git a/src/test/run-pass/attr-start.rs b/src/test/run-pass/attr-start.rs index 2bf0940420..bfafe04d60 100644 --- a/src/test/run-pass/attr-start.rs +++ b/src/test/run-pass/attr-start.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(start)] #[start] -fn start(_argc: int, _argv: *const *const u8) -> int { +fn start(_argc: isize, _argv: *const *const u8) -> isize { return 0; } diff --git a/src/test/run-pass/attr.rs b/src/test/run-pass/attr.rs index 129d69b6e6..57e1b38c9c 100644 --- a/src/test/run-pass/attr.rs +++ b/src/test/run-pass/attr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(main)] #[main] diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index 7c126fc420..2df0bb3559 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -43,7 +43,7 @@ fn test_rbml<'a, 'b, A: #[derive(Decodable, Encodable)] enum Expr { - Val(uint), + Val(usize), Plus(@Expr, @Expr), Minus(@Expr, @Expr) } @@ -103,23 +103,23 @@ impl cmp::Eq for Quark { impl cmp::Eq for CLike { fn eq(&self, other: &CLike) -> bool { - (*self) as int == *other as int + (*self) as isize == *other as isize } fn ne(&self, other: &CLike) -> bool { !self.eq(other) } } #[derive(Decodable, Encodable, Eq)] struct Spanned { - lo: uint, - hi: uint, + lo: usize, + hi: usize, node: T, } #[derive(Decodable, Encodable)] -struct SomeStruct { v: Vec } +struct SomeStruct { v: Vec } #[derive(Decodable, Encodable)] -struct Point {x: uint, y: uint} +struct Point {x: usize, y: usize} #[derive(Decodable, Encodable)] enum Quark { @@ -131,19 +131,19 @@ enum Quark { enum CLike { A, B, C } pub fn main() { - let a = &Plus(@Minus(@Val(3_usize), @Val(10_usize)), @Plus(@Val(22_usize), @Val(5_usize))); + let a = &Plus(@Minus(@Val(3), @Val(10)), @Plus(@Val(22), @Val(5))); test_rbml(a); - let a = &Spanned {lo: 0_usize, hi: 5_usize, node: 22_usize}; + let a = &Spanned {lo: 0, hi: 5, node: 22}; test_rbml(a); - let a = &Point {x: 3_usize, y: 5_usize}; + let a = &Point {x: 3, y: 5}; test_rbml(a); - let a = &Top(22_usize); + let a = &Top(22); test_rbml(a); - let a = &Bottom(222_usize); + let a = &Bottom(222); test_rbml(a); let a = &A; diff --git a/src/test/run-pass/auto-instantiate.rs b/src/test/run-pass/auto-instantiate.rs index cd4c66cb32..4a1bfa3eb4 100644 --- a/src/test/run-pass/auto-instantiate.rs +++ b/src/test/run-pass/auto-instantiate.rs @@ -10,7 +10,7 @@ #[derive(Debug)] struct Pair { a: T, b: U } -struct Triple { x: int, y: int, z: int } +struct Triple { x: isize, y: isize, z: isize } fn f(x: T, y: U) -> Pair { return Pair {a: x, b: y}; } diff --git a/src/test/run-pass/auto-loop.rs b/src/test/run-pass/auto-loop.rs index 2cc7451e13..2e79183755 100644 --- a/src/test/run-pass/auto-loop.rs +++ b/src/test/run-pass/auto-loop.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut sum = 0; let xs = vec!(1, 2, 3, 4, 5); diff --git a/src/test/run-pass/auto-ref-bounded-ty-param.rs b/src/test/run-pass/auto-ref-bounded-ty-param.rs index ee3738518c..77ec0e1791 100644 --- a/src/test/run-pass/auto-ref-bounded-ty-param.rs +++ b/src/test/run-pass/auto-ref-bounded-ty-param.rs @@ -13,7 +13,7 @@ trait Foo { } struct Bar { - x: int + x: isize } trait Baz { diff --git a/src/test/run-pass/auto-ref-sliceable.rs b/src/test/run-pass/auto-ref-sliceable.rs index 652f21c2ae..6dab0e5197 100644 --- a/src/test/run-pass/auto-ref-sliceable.rs +++ b/src/test/run-pass/auto-ref-sliceable.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait Pushable { fn push_val(&mut self, t: T); } @@ -23,5 +25,5 @@ pub fn main() { let mut v = vec!(1); v.push_val(2); v.push_val(3); - assert_eq!(v, vec!(1, 2, 3)); + assert_eq!(v, [1, 2, 3]); } diff --git a/src/test/run-pass/auto-ref.rs b/src/test/run-pass/auto-ref.rs index 6dc6790542..0ad2303a76 100644 --- a/src/test/run-pass/auto-ref.rs +++ b/src/test/run-pass/auto-ref.rs @@ -9,7 +9,7 @@ // except according to those terms. struct Foo { - x: int, + x: isize, } trait Stuff { diff --git a/src/test/run-pass/autobind.rs b/src/test/run-pass/autobind.rs index ed471ed007..7d30b549eb 100644 --- a/src/test/run-pass/autobind.rs +++ b/src/test/run-pass/autobind.rs @@ -9,9 +9,11 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn f(x: Vec) -> T { return x.into_iter().next().unwrap(); } -fn g(act: F) -> int where F: FnOnce(Vec) -> int { return act(vec!(1, 2, 3)); } +fn g(act: F) -> isize where F: FnOnce(Vec) -> isize { return act(vec!(1, 2, 3)); } pub fn main() { assert_eq!(g(f), 1); diff --git a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs index fc643ec594..a4c6cdd544 100644 --- a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs +++ b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo { - x: int, + x: isize, } impl Foo { diff --git a/src/test/run-pass/autoderef-method-on-trait.rs b/src/test/run-pass/autoderef-method-on-trait.rs index 9e88eb6da6..d7eee85f50 100644 --- a/src/test/run-pass/autoderef-method-on-trait.rs +++ b/src/test/run-pass/autoderef-method-on-trait.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait double { - fn double(self: Box) -> uint; + fn double(self: Box) -> usize; } -impl double for uint { - fn double(self: Box) -> uint { *self * 2_usize } +impl double for usize { + fn double(self: Box) -> usize { *self * 2 } } pub fn main() { - let x = box() (box 3_usize as Box); - assert_eq!(x.double(), 6_usize); + let x: Box<_> = box() (box 3us as Box); + assert_eq!(x.double(), 6); } diff --git a/src/test/run-pass/autoderef-method-priority.rs b/src/test/run-pass/autoderef-method-priority.rs index 67dd25ddc5..6c52035b70 100644 --- a/src/test/run-pass/autoderef-method-priority.rs +++ b/src/test/run-pass/autoderef-method-priority.rs @@ -8,22 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait double { - fn double(self) -> uint; + fn double(self) -> usize; } -impl double for uint { - fn double(self) -> uint { self } +impl double for usize { + fn double(self) -> usize { self } } -impl double for Box { - fn double(self) -> uint { *self * 2_usize } +impl double for Box { + fn double(self) -> usize { *self * 2 } } pub fn main() { - let x = box 3_usize; - assert_eq!(x.double(), 6_usize); + let x: Box<_> = box 3; + assert_eq!(x.double(), 6); } diff --git a/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs b/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs index 6437c78161..809ab0a352 100644 --- a/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs +++ b/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait double { - fn double(self: Box) -> uint; + fn double(self: Box) -> usize; } -impl double for Box { - fn double(self: Box>) -> uint { **self * 2_usize } +impl double for Box { + fn double(self: Box>) -> usize { **self * 2 } } pub fn main() { - let x = box box box box box 3_usize; - assert_eq!(x.double(), 6_usize); + let x: Box>>>> = box box box box box 3; + assert_eq!(x.double(), 6); } diff --git a/src/test/run-pass/autoderef-method-twice.rs b/src/test/run-pass/autoderef-method-twice.rs index 8cbc151f0c..9c7828c893 100644 --- a/src/test/run-pass/autoderef-method-twice.rs +++ b/src/test/run-pass/autoderef-method-twice.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait double { - fn double(self: Box) -> uint; + fn double(self: Box) -> usize; } -impl double for uint { - fn double(self: Box) -> uint { *self * 2_usize } +impl double for usize { + fn double(self: Box) -> usize { *self * 2 } } pub fn main() { - let x = box box 3_usize; - assert_eq!(x.double(), 6_usize); + let x: Box> = box box 3; + assert_eq!(x.double(), 6); } diff --git a/src/test/run-pass/autoderef-method.rs b/src/test/run-pass/autoderef-method.rs index c8fa3c9fd5..e63dd07eb0 100644 --- a/src/test/run-pass/autoderef-method.rs +++ b/src/test/run-pass/autoderef-method.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait double { - fn double(self: Box) -> uint; + fn double(self: Box) -> usize; } -impl double for uint { - fn double(self: Box) -> uint { *self * 2_usize } +impl double for usize { + fn double(self: Box) -> usize { *self * 2 } } pub fn main() { - let x = box 3_usize; - assert_eq!(x.double(), 6_usize); + let x: Box<_> = box 3; + assert_eq!(x.double(), 6); } diff --git a/src/test/run-pass/autoref-intermediate-types-issue-3585.rs b/src/test/run-pass/autoref-intermediate-types-issue-3585.rs index 87157b9334..0f935776fc 100644 --- a/src/test/run-pass/autoref-intermediate-types-issue-3585.rs +++ b/src/test/run-pass/autoref-intermediate-types-issue-3585.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -22,13 +24,13 @@ impl Foo for Box { } } -impl Foo for uint { +impl Foo for usize { fn foo(&self) -> String { format!("{}", *self) } } pub fn main() { - let x = box 3_usize; + let x: Box<_> = box 3; assert_eq!(x.foo(), "box 3".to_string()); } diff --git a/src/test/run-pass/backtrace-debuginfo-aux.rs b/src/test/run-pass/backtrace-debuginfo-aux.rs new file mode 100644 index 0000000000..f0d36ea976 --- /dev/null +++ b/src/test/run-pass/backtrace-debuginfo-aux.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-test: not a test, used by backtrace-debuginfo.rs to test file!() + +#[inline(never)] +pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { + f((file!(), line!())) +} + +#[inline(always)] +pub fn callback_inlined(f: F) where F: FnOnce((&'static str, u32)) { + f((file!(), line!())) +} diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs new file mode 100644 index 0000000000..2a74e36aff --- /dev/null +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -0,0 +1,161 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-g +// ignore-pretty as this critically relies on line numbers + +use std::io; +use std::io::prelude::*; +use std::env; + +#[path = "backtrace-debuginfo-aux.rs"] mod aux; + +macro_rules! pos { + () => ((file!(), line!())) +} + +#[cfg(all(unix, + not(target_os = "macos"), + not(target_os = "ios"), + not(target_os = "android"), + not(all(target_os = "linux", target_arch = "arm"))))] +macro_rules! dump_and_die { + ($($pos:expr),*) => ({ + // FIXME(#18285): we cannot include the current position because + // the macro span takes over the last frame's file/line. + dump_filelines(&[$($pos),*]); + panic!(); + }) +} + +// this does not work on Windows, Android, OSX or iOS +#[cfg(any(not(unix), + target_os = "macos", + target_os = "ios", + target_os = "android", + all(target_os = "linux", target_arch = "arm")))] +macro_rules! dump_and_die { + ($($pos:expr),*) => ({ let _ = [$($pos),*]; }) +} + +// we can't use a function as it will alter the backtrace +macro_rules! check { + ($counter:expr; $($pos:expr),*) => ({ + if *$counter == 0 { + dump_and_die!($($pos),*) + } else { + *$counter -= 1; + } + }) +} + +type Pos = (&'static str, u32); + +// this goes to stdout and each line has to be occurred +// in the following backtrace to stderr with a correct order. +fn dump_filelines(filelines: &[Pos]) { + for &(file, line) in filelines.iter().rev() { + // extract a basename + let basename = file.split(&['/', '\\'][..]).last().unwrap(); + println!("{}:{}", basename, line); + } +} + +#[inline(never)] +fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { + check!(counter; main_pos, outer_pos); + check!(counter; main_pos, outer_pos); + let inner_pos = pos!(); aux::callback(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); aux::callback_inlined(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); +} + +#[inline(always)] +fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { + check!(counter; main_pos, outer_pos); + check!(counter; main_pos, outer_pos); + + #[inline(always)] + fn inner_further_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { + check!(counter; main_pos, outer_pos, inner_pos); + } + inner_further_inlined(counter, main_pos, outer_pos, pos!()); + + let inner_pos = pos!(); aux::callback(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); aux::callback_inlined(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); + + // this tests a distinction between two independent calls to the inlined function. + // (un)fortunately, LLVM somehow merges two consecutive such calls into one node. + inner_further_inlined(counter, main_pos, outer_pos, pos!()); +} + +#[inline(never)] +fn outer(mut counter: i32, main_pos: Pos) { + inner(&mut counter, main_pos, pos!()); + inner_inlined(&mut counter, main_pos, pos!()); +} + +fn check_trace(output: &str, error: &str) { + // reverse the position list so we can start with the last item (which was the first line) + let mut remaining: Vec<&str> = output.lines().map(|s| s.trim()).rev().collect(); + + assert!(error.contains("stack backtrace"), "no backtrace in the error: {}", error); + for line in error.lines() { + if !remaining.is_empty() && line.contains(remaining.last().unwrap()) { + remaining.pop(); + } + } + assert!(remaining.is_empty(), + "trace does not match position list: {}\n---\n{}", error, output); +} + +fn run_test(me: &str) { + use std::str; + use std::process::Command; + + let mut template = Command::new(me); + template.env("RUST_BACKTRACE", "1"); + + let mut i = 0; + loop { + let out = Command::new(me) + .env("RUST_BACKTRACE", "1") + .arg(i.to_string()).output().unwrap(); + let output = str::from_utf8(&out.stdout).unwrap(); + let error = str::from_utf8(&out.stderr).unwrap(); + if out.status.success() { + assert!(output.contains("done."), "bad output for successful run: {}", output); + break; + } else { + check_trace(output, error); + } + i += 1; + } +} + +#[inline(never)] +fn main() { + let args: Vec = env::args().collect(); + if args.len() >= 2 { + let case = args[1].parse().unwrap(); + writeln!(&mut io::stderr(), "test case {}", case).unwrap(); + outer(case, pos!()); + println!("done."); + } else { + run_test(&args[0]); + } +} diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 6f76322cb7..14d8bce061 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -12,7 +12,7 @@ // ignore-windows FIXME #13259 #![feature(unboxed_closures)] -#![feature(unsafe_destructor)] +#![feature(unsafe_destructor, old_io, collections)] use std::env; use std::old_io::process::Command; @@ -53,7 +53,9 @@ fn runtest(me: &str) { "bad output: {}", s); // Make sure the stack trace is *not* printed - let p = template.clone().arg("fail").spawn().unwrap(); + // (Remove RUST_BACKTRACE from our own environment, in case developer + // is running `make check` with it on.) + let p = template.clone().arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap(); let out = p.wait_with_output().unwrap(); assert!(!out.status.success()); let s = str::from_utf8(&out.error).unwrap(); @@ -78,9 +80,9 @@ fn runtest(me: &str) { let s = str::from_utf8(&out.error).unwrap(); let mut i = 0; for _ in 0..2 { - i += s[i + 10..].find_str("stack backtrace").unwrap() + 10; + i += s[i + 10..].find("stack backtrace").unwrap() + 10; } - assert!(s[i + 10..].find_str("stack backtrace").is_none(), + assert!(s[i + 10..].find("stack backtrace").is_none(), "bad output4: {}", s); } diff --git a/src/test/run-pass/bare-fn-implements-fn-mut.rs b/src/test/run-pass/bare-fn-implements-fn-mut.rs index 758776298e..e8118e90a9 100644 --- a/src/test/run-pass/bare-fn-implements-fn-mut.rs +++ b/src/test/run-pass/bare-fn-implements-fn-mut.rs @@ -35,4 +35,3 @@ fn main() { assert_eq!(call_g(g, "foo".to_string(), "bar".to_string()), "foobar"); } - diff --git a/src/test/run-pass/big-literals.rs b/src/test/run-pass/big-literals.rs index 8afb33c766..ab9d892ce2 100644 --- a/src/test/run-pass/big-literals.rs +++ b/src/test/run-pass/big-literals.rs @@ -8,11 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + +// Catch mistakes in the overflowing literals lint. +#![deny(overflowing_literals)] + pub fn main() { - assert_eq!(0xffffffffu32, (-1 as u32)); - assert_eq!(4294967295u32, (-1 as u32)); - assert_eq!(0xffffffffffffffffu64, (-1 as u64)); - assert_eq!(18446744073709551615u64, (-1 as u64)); + assert_eq!(0xffffffff, (!0 as u32)); + assert_eq!(4294967295, (!0 as u32)); + assert_eq!(0xffffffffffffffff, (!0 as u64)); + assert_eq!(18446744073709551615, (!0 as u64)); - assert_eq!(-2147483648i32 - 1i32, 2147483647i32); + assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647); } diff --git a/src/test/run-pass/binary-minus-without-space.rs b/src/test/run-pass/binary-minus-without-space.rs index dc3b142f23..1fe9dde844 100644 --- a/src/test/run-pass/binary-minus-without-space.rs +++ b/src/test/run-pass/binary-minus-without-space.rs @@ -10,6 +10,8 @@ // Check that issue #954 stays fixed +// pretty-expanded FIXME #23616 + pub fn main() { match -1 { -1 => {}, _ => panic!("wat") } assert_eq!(1-1, 0); diff --git a/src/test/run-pass/bind-by-move.rs b/src/test/run-pass/bind-by-move.rs index a9fa8449d0..5a6e801501 100644 --- a/src/test/run-pass/bind-by-move.rs +++ b/src/test/run-pass/bind-by-move.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::Arc; fn dispose(_x: Arc) { } diff --git a/src/test/run-pass/bind-field-short-with-modifiers.rs b/src/test/run-pass/bind-field-short-with-modifiers.rs index 470577d729..e61ff61a21 100644 --- a/src/test/run-pass/bind-field-short-with-modifiers.rs +++ b/src/test/run-pass/bind-field-short-with-modifiers.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - struct Foo { x: int, y: int } + struct Foo { x: isize, y: isize } let mut f = Foo { x: 10, y: 0 }; match f { Foo { ref mut x, .. } => *x = 11, diff --git a/src/test/run-pass/binops-issue-22743.rs b/src/test/run-pass/binops-issue-22743.rs new file mode 100644 index 0000000000..da7a3ae684 --- /dev/null +++ b/src/test/run-pass/binops-issue-22743.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Mul; + +#[derive(Copy, Clone)] +pub struct Foo { + x: f64, +} + +impl Mul for f64 { + type Output = Foo; + + fn mul(self, rhs: Foo) -> Foo { + // intentionally do something that is not * + Foo { x: self + rhs.x } + } +} + +pub fn main() { + let f: Foo = Foo { x: 5.0 }; + let val: f64 = 3.0; + let f2: Foo = val * f; + assert_eq!(f2.x, 8.0); +} diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index b36eb4bf2f..2b8fcd303b 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -61,11 +61,11 @@ fn test_ptr() { #[derive(PartialEq, Debug)] struct p { - x: int, - y: int, + x: isize, + y: isize, } -fn p(x: int, y: int) -> p { +fn p(x: isize, y: isize) -> p { p { x: x, y: y @@ -78,8 +78,8 @@ fn test_class() { unsafe { println!("q = {:x}, r = {:x}", - (::std::mem::transmute::<*const p, uint>(&q)), - (::std::mem::transmute::<*const p, uint>(&r))); + (::std::mem::transmute::<*const p, usize>(&q)), + (::std::mem::transmute::<*const p, usize>(&r))); } assert_eq!(q, r); r.y = 17; diff --git a/src/test/run-pass/bitv-perf-test.rs b/src/test/run-pass/bitv-perf-test.rs index 7bb9f042fe..c9a2e07dd8 100644 --- a/src/test/run-pass/bitv-perf-test.rs +++ b/src/test/run-pass/bitv-perf-test.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, collections)] extern crate collections; use std::collections::BitVec; fn bitv_test() { - let mut v1 = box BitVec::from_elem(31, false); - let v2 = box BitVec::from_elem(31, true); + let mut v1: Box<_> = box BitVec::from_elem(31, false); + let v2: Box<_> = box BitVec::from_elem(31, true); v1.union(&*v2); } diff --git a/src/test/run-pass/bitwise.rs b/src/test/run-pass/bitwise.rs index 8418681b6b..a9f19c12b0 100644 --- a/src/test/run-pass/bitwise.rs +++ b/src/test/run-pass/bitwise.rs @@ -8,20 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(negate_unsigned)] #[cfg(any(target_arch = "x86", target_arch = "arm"))] fn target() { - assert_eq!(-1000 as uint >> 3_usize, 536870787_usize); + assert_eq!(-1000 as usize >> 3_usize, 536870787_usize); } #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] fn target() { - assert_eq!(-1000 as uint >> 3_usize, 2305843009213693827_usize); + assert_eq!(-1000 as usize >> 3_usize, 2305843009213693827_usize); } fn general() { - let mut a: int = 1; - let mut b: int = 2; + let mut a: isize = 1; + let mut b: isize = 2; a ^= b; b ^= a; a = a ^ b; diff --git a/src/test/run-pass/blind-item-mixed-crate-use-item.rs b/src/test/run-pass/blind-item-mixed-crate-use-item.rs index 80c73e5e60..3b6614c18f 100644 --- a/src/test/run-pass/blind-item-mixed-crate-use-item.rs +++ b/src/test/run-pass/blind-item-mixed-crate-use-item.rs @@ -11,6 +11,8 @@ // aux-build:blind-item-mixed-crate-use-item-foo.rs // aux-build:blind-item-mixed-crate-use-item-foo2.rs +// pretty-expanded FIXME #23616 + mod m { pub fn f(_: T, _: (), _: ()) { } pub fn g(_: T, _: (), _: ()) { } @@ -19,14 +21,14 @@ mod m { const BAR: () = (); struct Data; use m::f; -extern crate "blind-item-mixed-crate-use-item-foo" as foo; +extern crate blind_item_mixed_crate_use_item_foo as foo; fn main() { const BAR2: () = (); struct Data2; use m::g; - extern crate "blind-item-mixed-crate-use-item-foo2" as foo2; + extern crate blind_item_mixed_crate_use_item_foo2 as foo2; f(Data, BAR, foo::X); g(Data2, BAR2, foo2::Y); diff --git a/src/test/run-pass/blind-item-mixed-use-item.rs b/src/test/run-pass/blind-item-mixed-use-item.rs index a3dad01acf..6244ba6fcc 100644 --- a/src/test/run-pass/blind-item-mixed-use-item.rs +++ b/src/test/run-pass/blind-item-mixed-use-item.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod m { pub fn f(_: T, _: ()) { } pub fn g(_: T, _: ()) { } diff --git a/src/test/run-pass/block-arg-call-as.rs b/src/test/run-pass/block-arg-call-as.rs index d319aaa2f8..5944438e20 100644 --- a/src/test/run-pass/block-arg-call-as.rs +++ b/src/test/run-pass/block-arg-call-as.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn asBlock(f: F) -> uint where F: FnOnce() -> uint { +// pretty-expanded FIXME #23616 + +fn asBlock(f: F) -> usize where F: FnOnce() -> usize { return f(); } pub fn main() { - let x = asBlock(|| 22_usize); - assert_eq!(x, 22_usize); + let x = asBlock(|| 22); + assert_eq!(x, 22); } diff --git a/src/test/run-pass/block-explicit-types.rs b/src/test/run-pass/block-explicit-types.rs index 54b650d762..835d356d8a 100644 --- a/src/test/run-pass/block-explicit-types.rs +++ b/src/test/run-pass/block-explicit-types.rs @@ -10,5 +10,5 @@ pub fn main() { fn as_buf(s: String, f: F) -> T where F: FnOnce(String) -> T { f(s) } - as_buf("foo".to_string(), |foo: String| -> () println!("{}", foo) ); + as_buf("foo".to_string(), |foo: String| -> () { println!("{}", foo) }); } diff --git a/src/test/run-pass/block-expr-precedence.rs b/src/test/run-pass/block-expr-precedence.rs index ace372dd2d..01bd8ce10c 100644 --- a/src/test/run-pass/block-expr-precedence.rs +++ b/src/test/run-pass/block-expr-precedence.rs @@ -13,6 +13,8 @@ // no-reformat +// pretty-expanded FIXME #23616 + /* * * When you write a block-expression thing followed by diff --git a/src/test/run-pass/block-fn-coerce.rs b/src/test/run-pass/block-fn-coerce.rs index f3c874a5af..0addd33c1e 100644 --- a/src/test/run-pass/block-fn-coerce.rs +++ b/src/test/run-pass/block-fn-coerce.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn force(f: F) -> int where F: FnOnce() -> int { return f(); } +// pretty-expanded FIXME #23616 + +fn force(f: F) -> isize where F: FnOnce() -> isize { return f(); } pub fn main() { - fn f() -> int { return 7; } + fn f() -> isize { return 7; } assert_eq!(force(f), 7); let g = {||force(f)}; assert_eq!(g(), 7); diff --git a/src/test/run-pass/block-iter-1.rs b/src/test/run-pass/block-iter-1.rs index d5d26f42ef..7cbe8104de 100644 --- a/src/test/run-pass/block-iter-1.rs +++ b/src/test/run-pass/block-iter-1.rs @@ -11,8 +11,8 @@ fn iter_vec(v: Vec , mut f: F) where F: FnMut(&T) { for x in &v { f(x); } } pub fn main() { - let v = vec![1i32, 2, 3, 4, 5, 6, 7]; - let mut odds = 0i32; + let v = vec![1, 2, 3, 4, 5, 6, 7]; + let mut odds = 0; iter_vec(v, |i| { if *i % 2 == 1 { odds += 1; diff --git a/src/test/run-pass/block-iter-2.rs b/src/test/run-pass/block-iter-2.rs index 8c079ca4b0..7701f6114c 100644 --- a/src/test/run-pass/block-iter-2.rs +++ b/src/test/run-pass/block-iter-2.rs @@ -11,7 +11,7 @@ fn iter_vec(v: Vec, mut f: F) where F: FnMut(&T) { for x in &v { f(x); } } pub fn main() { - let v = vec![1i32, 2, 3, 4, 5]; + let v = vec![1, 2, 3, 4, 5]; let mut sum = 0; iter_vec(v.clone(), |i| { iter_vec(v.clone(), |j| { diff --git a/src/test/run-pass/bool-not.rs b/src/test/run-pass/bool-not.rs index e98087810b..c46684af6e 100644 --- a/src/test/run-pass/bool-not.rs +++ b/src/test/run-pass/bool-not.rs @@ -11,6 +11,8 @@ +// pretty-expanded FIXME #23616 + pub fn main() { if !false { assert!((true)); } else { assert!((false)); } if !true { assert!((false)); } else { assert!((true)); } diff --git a/src/test/run-pass/bool.rs b/src/test/run-pass/bool.rs index edf6b397ff..a2b19d3205 100644 --- a/src/test/run-pass/bool.rs +++ b/src/test/run-pass/bool.rs @@ -10,6 +10,8 @@ // Basic boolean tests +// pretty-expanded FIXME #23616 + use std::cmp::Ordering::{Equal, Greater, Less}; use std::ops::{BitAnd, BitOr, BitXor}; diff --git a/src/test/run-pass/borrow-by-val-method-receiver.rs b/src/test/run-pass/borrow-by-val-method-receiver.rs index 4cc39b4b5d..7efda12192 100644 --- a/src/test/run-pass/borrow-by-val-method-receiver.rs +++ b/src/test/run-pass/borrow-by-val-method-receiver.rs @@ -9,11 +9,13 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn foo(self); } -impl<'a> Foo for &'a [int] { +impl<'a> Foo for &'a [isize] { fn foo(self) {} } diff --git a/src/test/run-pass/borrow-tuple-fields.rs b/src/test/run-pass/borrow-tuple-fields.rs index 2e5688d8b7..7cf61bd569 100644 --- a/src/test/run-pass/borrow-tuple-fields.rs +++ b/src/test/run-pass/borrow-tuple-fields.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo(int, int); +// pretty-expanded FIXME #23616 + +struct Foo(isize, isize); fn main() { let x = (1, 2); diff --git a/src/test/run-pass/borrowck-assign-to-subfield.rs b/src/test/run-pass/borrowck-assign-to-subfield.rs index 10b5825cdd..ee74a05440 100644 --- a/src/test/run-pass/borrowck-assign-to-subfield.rs +++ b/src/test/run-pass/borrowck-assign-to-subfield.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { struct A { - a: int, + a: isize, w: B, } struct B { - a: int + a: isize } let mut p = A { a: 1, diff --git a/src/test/run-pass/borrowck-binding-mutbl.rs b/src/test/run-pass/borrowck-binding-mutbl.rs index 34ad2b2def..10e9a1b51e 100644 --- a/src/test/run-pass/borrowck-binding-mutbl.rs +++ b/src/test/run-pass/borrowck-binding-mutbl.rs @@ -9,9 +9,11 @@ // except according to those terms. -struct F { f: Vec } +// pretty-expanded FIXME #23616 -fn impure(_v: &[int]) { +struct F { f: Vec } + +fn impure(_v: &[isize]) { } pub fn main() { diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index 9fcd87418b..24c7285b1f 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn borrow(x: &int, f: F) where F: FnOnce(&int) { +fn borrow(x: &isize, f: F) where F: FnOnce(&isize) { f(x) } -fn test1(x: &Box) { +fn test1(x: &Box) { borrow(&*(*x).clone(), |p| { - let x_a = &**x as *const int; - assert!((x_a as uint) != (p as *const int as uint)); + let x_a = &**x as *const isize; + assert!((x_a as usize) != (p as *const isize as usize)); assert_eq!(unsafe{*x_a}, *p); }) } diff --git a/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs b/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs index b7aa2989ac..b716a1a27a 100644 --- a/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs +++ b/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs @@ -11,14 +11,16 @@ // Test that freezing an `&mut` pointer while referent is // frozen is legal. // -// Example from src/middle/borrowck/doc.rs +// Example from src/librustc_borrowck/borrowck/README.md -fn foo<'a>(mut t0: &'a mut int, - mut t1: &'a mut int) { - let p: &int = &*t0; // Freezes `*t0` +// pretty-expanded FIXME #23616 + +fn foo<'a>(mut t0: &'a mut isize, + mut t1: &'a mut isize) { + let p: &isize = &*t0; // Freezes `*t0` let mut t2 = &t0; - let q: &int = &**t2; // Freezes `*t0`, but that's ok... - let r: &int = &*t0; // ...after all, could do same thing directly. + let q: &isize = &**t2; // Freezes `*t0`, but that's ok... + let r: &isize = &*t0; // ...after all, could do same thing directly. } pub fn main() { diff --git a/src/test/run-pass/borrowck-closures-two-imm.rs b/src/test/run-pass/borrowck-closures-two-imm.rs index c907778339..6ccb2203bc 100644 --- a/src/test/run-pass/borrowck-closures-two-imm.rs +++ b/src/test/run-pass/borrowck-closures-two-imm.rs @@ -14,8 +14,10 @@ // that the main function can read the variable too while // the closures are in scope. Issue #6801. +// pretty-expanded FIXME #23616 + fn a() -> i32 { - let mut x = 3i32; + let mut x = 3; x += 1; let c1 = || x * 4; let c2 = || x * 5; @@ -27,7 +29,7 @@ fn get(x: &i32) -> i32 { } fn b() -> i32 { - let mut x = 3i32; + let mut x = 3; x += 1; let c1 = || get(&x); let c2 = || get(&x); @@ -35,7 +37,7 @@ fn b() -> i32 { } fn c() -> i32 { - let mut x = 3i32; + let mut x = 3; x += 1; let c1 = || x * 5; let c2 = || get(&x); diff --git a/src/test/run-pass/borrowck-field-sensitivity.rs b/src/test/run-pass/borrowck-field-sensitivity.rs index 89d8019004..d97564a291 100644 --- a/src/test/run-pass/borrowck-field-sensitivity.rs +++ b/src/test/run-pass/borrowck-field-sensitivity.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct A { a: int, b: Box } -struct B { a: Box, b: Box } +struct A { a: isize, b: Box } +struct B { a: Box, b: Box } fn move_after_copy() { let x = A { a: 1, b: box 2 }; @@ -270,4 +272,3 @@ fn main() { borrow_after_assign_after_uninit(); move_after_assign_after_uninit(); } - diff --git a/src/test/run-pass/borrowck-fixed-length-vecs.rs b/src/test/run-pass/borrowck-fixed-length-vecs.rs index ee561fdb0b..3f38a8df04 100644 --- a/src/test/run-pass/borrowck-fixed-length-vecs.rs +++ b/src/test/run-pass/borrowck-fixed-length-vecs.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = [22]; let y = &x[0]; diff --git a/src/test/run-pass/borrowck-freeze-frozen-mut.rs b/src/test/run-pass/borrowck-freeze-frozen-mut.rs index 30a921c9bd..eaa78553d8 100644 --- a/src/test/run-pass/borrowck-freeze-frozen-mut.rs +++ b/src/test/run-pass/borrowck-freeze-frozen-mut.rs @@ -10,11 +10,13 @@ // Test that a `&mut` inside of an `&` is freezable. +// pretty-expanded FIXME #23616 + struct MutSlice<'a, T:'a> { data: &'a mut [T] } -fn get<'a, T>(ms: &'a MutSlice<'a, T>, index: uint) -> &'a T { +fn get<'a, T>(ms: &'a MutSlice<'a, T>, index: usize) -> &'a T { &ms.data[index] } diff --git a/src/test/run-pass/borrowck-lend-args.rs b/src/test/run-pass/borrowck-lend-args.rs index 9b8fa8f9f7..f1f0274c5c 100644 --- a/src/test/run-pass/borrowck-lend-args.rs +++ b/src/test/run-pass/borrowck-lend-args.rs @@ -9,17 +9,19 @@ // except according to those terms. -fn borrow(_v: &int) {} +// pretty-expanded FIXME #23616 -fn borrow_from_arg_imm_ref(v: Box) { +fn borrow(_v: &isize) {} + +fn borrow_from_arg_imm_ref(v: Box) { borrow(&*v); } -fn borrow_from_arg_mut_ref(v: &mut Box) { +fn borrow_from_arg_mut_ref(v: &mut Box) { borrow(&**v); } -fn borrow_from_arg_copy(v: Box) { +fn borrow_from_arg_copy(v: Box) { borrow(&*v); } diff --git a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs index ae5734a09b..b40504f37d 100644 --- a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs +++ b/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs @@ -11,15 +11,17 @@ // Check that we do not ICE when compiling this // macro, which reuses the expression `$id` +// pretty-expanded FIXME #23616 + #![feature(box_patterns)] #![feature(box_syntax)] struct Foo { - a: int + a: isize } pub enum Bar { - Bar1, Bar2(int, Box), + Bar1, Bar2(isize, Box), } impl Foo { @@ -36,7 +38,7 @@ impl Foo { } } - fn check_id(&mut self, s: int) { panic!() } + fn check_id(&mut self, s: isize) { panic!() } } pub fn main() { } diff --git a/src/test/run-pass/borrowck-move-by-capture-ok.rs b/src/test/run-pass/borrowck-move-by-capture-ok.rs index 1be57674fa..7c03c6a9a4 100644 --- a/src/test/run-pass/borrowck-move-by-capture-ok.rs +++ b/src/test/run-pass/borrowck-move-by-capture-ok.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #![feature(unboxed_closures)] pub fn main() { - let bar = box 3; - let h = || -> int *bar; + let bar: Box<_> = box 3; + let h = || -> isize { *bar }; assert_eq!(h(), 3); } - diff --git a/src/test/run-pass/borrowck-mut-uniq.rs b/src/test/run-pass/borrowck-mut-uniq.rs index 2dbaec8fbb..f535c5fcfc 100644 --- a/src/test/run-pass/borrowck-mut-uniq.rs +++ b/src/test/run-pass/borrowck-mut-uniq.rs @@ -14,9 +14,9 @@ use std::mem::swap; #[derive(Debug)] -struct Ints {sum: Box, values: Vec } +struct Ints {sum: Box, values: Vec } -fn add_int(x: &mut Ints, v: int) { +fn add_int(x: &mut Ints, v: isize) { *x.sum += v; let mut values = Vec::new(); swap(&mut values, &mut x.values); @@ -24,18 +24,18 @@ fn add_int(x: &mut Ints, v: int) { swap(&mut values, &mut x.values); } -fn iter_ints(x: &Ints, mut f: F) -> bool where F: FnMut(&int) -> bool { +fn iter_ints(x: &Ints, mut f: F) -> bool where F: FnMut(&isize) -> bool { let l = x.values.len(); - (0_usize..l).all(|i| f(&x.values[i])) + (0..l).all(|i| f(&x.values[i])) } pub fn main() { - let mut ints = box Ints {sum: box 0, values: Vec::new()}; + let mut ints: Box<_> = box Ints {sum: box 0, values: Vec::new()}; add_int(&mut *ints, 22); add_int(&mut *ints, 44); iter_ints(&*ints, |i| { - println!("int = {:?}", *i); + println!("isize = {:?}", *i); true }); diff --git a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs b/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs index 092d7c1317..4d37bcb5a4 100644 --- a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs +++ b/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs @@ -9,13 +9,15 @@ // except according to those terms. -fn want_slice(v: &[int]) -> int { +// pretty-expanded FIXME #23616 + +fn want_slice(v: &[isize]) -> isize { let mut sum = 0; for i in v { sum += *i; } sum } -fn has_mut_vec(v: Vec ) -> int { +fn has_mut_vec(v: Vec ) -> isize { want_slice(&v) } diff --git a/src/test/run-pass/borrowck-nested-calls.rs b/src/test/run-pass/borrowck-nested-calls.rs index 315f6c80d4..fa50eaa6a8 100644 --- a/src/test/run-pass/borrowck-nested-calls.rs +++ b/src/test/run-pass/borrowck-nested-calls.rs @@ -12,12 +12,12 @@ // Test that (safe) nested calls with `&mut` receivers are permitted. -struct Foo {a: uint, b: uint} +struct Foo {a: usize, b: usize} impl Foo { - pub fn inc_a(&mut self, v: uint) { self.a += v; } + pub fn inc_a(&mut self, v: usize) { self.a += v; } - pub fn next_b(&mut self) -> uint { + pub fn next_b(&mut self) -> usize { let b = self.b; self.b += 1; b diff --git a/src/test/run-pass/borrowck-pat-enum.rs b/src/test/run-pass/borrowck-pat-enum.rs index 74ce8ef2e4..b29cb63f6f 100644 --- a/src/test/run-pass/borrowck-pat-enum.rs +++ b/src/test/run-pass/borrowck-pat-enum.rs @@ -10,7 +10,7 @@ // ignore-pretty -fn match_ref(v: Option) -> int { +fn match_ref(v: Option) -> isize { match v { Some(ref i) => { *i @@ -19,24 +19,24 @@ fn match_ref(v: Option) -> int { } } -fn match_ref_unused(v: Option) { +fn match_ref_unused(v: Option) { match v { Some(_) => {} None => {} } } -fn impure(_i: int) { +fn impure(_i: isize) { } -fn match_imm_reg(v: &Option) { +fn match_imm_reg(v: &Option) { match *v { Some(ref i) => {impure(*i)} // OK because immutable None => {} } } -fn match_mut_reg(v: &mut Option) { +fn match_mut_reg(v: &mut Option) { match *v { Some(ref i) => {impure(*i)} // OK, frozen None => {} diff --git a/src/test/run-pass/borrowck-pat-reassign-no-binding.rs b/src/test/run-pass/borrowck-pat-reassign-no-binding.rs index 4ccbf6b5b0..c3b69333dc 100644 --- a/src/test/run-pass/borrowck-pat-reassign-no-binding.rs +++ b/src/test/run-pass/borrowck-pat-reassign-no-binding.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut x = None; match x { diff --git a/src/test/run-pass/borrowck-rvalues-mutable.rs b/src/test/run-pass/borrowck-rvalues-mutable.rs index d4de4ef34d..1b20f6c706 100644 --- a/src/test/run-pass/borrowck-rvalues-mutable.rs +++ b/src/test/run-pass/borrowck-rvalues-mutable.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Counter { - value: uint + value: usize } impl Counter { - fn new(v: uint) -> Counter { + fn new(v: usize) -> Counter { Counter {value: v} } @@ -22,11 +24,11 @@ impl Counter { self } - fn get(&self) -> uint { + fn get(&self) -> usize { self.value } - fn get_and_inc(&mut self) -> uint { + fn get_and_inc(&mut self) -> usize { let v = self.value; self.value += 1; v diff --git a/src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs b/src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs index 02c7dc38db..36a84a62d4 100644 --- a/src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs +++ b/src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs @@ -12,15 +12,17 @@ // limited to the deref operation itself, and does not infect the // block as a whole. +// pretty-expanded FIXME #23616 + struct Box { - x: uint + x: usize } impl Box { - fn get(&self) -> &uint { + fn get(&self) -> &usize { &self.x } - fn set(&mut self, x: uint) { + fn set(&mut self, x: usize) { self.x = x; } } diff --git a/src/test/run-pass/borrowck-static-item-in-fn.rs b/src/test/run-pass/borrowck-static-item-in-fn.rs index 366752f46b..d51d0b1d2e 100644 --- a/src/test/run-pass/borrowck-static-item-in-fn.rs +++ b/src/test/run-pass/borrowck-static-item-in-fn.rs @@ -10,6 +10,8 @@ // Regression test for issue #7740 +// pretty-expanded FIXME #23616 + pub fn main() { static A: &'static char = &'A'; } diff --git a/src/test/run-pass/borrowck-trait-lifetime.rs b/src/test/run-pass/borrowck-trait-lifetime.rs index a2b0fa5663..0bfa8f4865 100644 --- a/src/test/run-pass/borrowck-trait-lifetime.rs +++ b/src/test/run-pass/borrowck-trait-lifetime.rs @@ -11,6 +11,8 @@ // This test verifies that casting from the same lifetime on a value // to the same lifetime on a trait succeeds. See issue #10766. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] use std::marker; diff --git a/src/test/run-pass/borrowck-uniq-via-ref.rs b/src/test/run-pass/borrowck-uniq-via-ref.rs index 84bd70c78d..0ec87599c6 100644 --- a/src/test/run-pass/borrowck-uniq-via-ref.rs +++ b/src/test/run-pass/borrowck-uniq-via-ref.rs @@ -9,8 +9,10 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct Rec { - f: Box, + f: Box, } struct Outer { @@ -22,12 +24,12 @@ struct Inner { } struct Innermost { - h: Box, + h: Box, } -fn borrow(_v: &int) {} +fn borrow(_v: &isize) {} -fn box_mut(v: &mut Box) { +fn box_mut(v: &mut Box) { borrow(&**v); // OK: &mut -> &imm } @@ -39,7 +41,7 @@ fn box_mut_recs(v: &mut Outer) { borrow(&*v.f.g.h); // OK: &mut -> &imm } -fn box_imm(v: &Box) { +fn box_imm(v: &Box) { borrow(&**v); // OK } diff --git a/src/test/run-pass/borrowck-univariant-enum.rs b/src/test/run-pass/borrowck-univariant-enum.rs index d95594119b..a5c68c5ecf 100644 --- a/src/test/run-pass/borrowck-univariant-enum.rs +++ b/src/test/run-pass/borrowck-univariant-enum.rs @@ -9,11 +9,13 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cell::Cell; -#[derive(Copy)] +#[derive(Copy, Clone)] enum newtype { - newvar(int) + newvar(isize) } pub fn main() { diff --git a/src/test/run-pass/borrowck-use-mut-borrow.rs b/src/test/run-pass/borrowck-use-mut-borrow.rs index 7be12ff3cc..7ad81b6be6 100644 --- a/src/test/run-pass/borrowck-use-mut-borrow.rs +++ b/src/test/run-pass/borrowck-use-mut-borrow.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct A { a: int, b: Box } +struct A { a: isize, b: Box } fn field_copy_after_field_borrow() { let mut x = A { a: 1, b: box 2 }; @@ -57,4 +59,3 @@ fn main() { field_move_after_field_borrow(); fu_field_move_after_field_borrow(); } - diff --git a/src/test/run-pass/borrowed-ptr-pattern-2.rs b/src/test/run-pass/borrowed-ptr-pattern-2.rs index efd932933d..aaf962577f 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-2.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(s: &String) -> bool { match &**s { "kitty" => true, diff --git a/src/test/run-pass/borrowed-ptr-pattern-3.rs b/src/test/run-pass/borrowed-ptr-pattern-3.rs index 030e055c4c..c8cc29b9bd 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-3.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-3.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo<'r>(s: &'r uint) -> bool { +// pretty-expanded FIXME #23616 + +fn foo<'r>(s: &'r usize) -> bool { match s { &3 => true, _ => false diff --git a/src/test/run-pass/borrowed-ptr-pattern-infallible.rs b/src/test/run-pass/borrowed-ptr-pattern-infallible.rs index e57c001ea0..69cb27dcf8 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-infallible.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-infallible.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let (&x, &y) = (&3, &'a'); assert_eq!(x, 3); diff --git a/src/test/run-pass/borrowed-ptr-pattern-option.rs b/src/test/run-pass/borrowed-ptr-pattern-option.rs index 9f17b9d7f9..14b6c32a11 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-option.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-option.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn select<'r>(x: &'r Option, y: &'r Option) -> &'r Option { +// pretty-expanded FIXME #23616 + +fn select<'r>(x: &'r Option, y: &'r Option) -> &'r Option { match (x, y) { (&None, &None) => x, (&Some(_), _) => x, diff --git a/src/test/run-pass/borrowed-ptr-pattern.rs b/src/test/run-pass/borrowed-ptr-pattern.rs index 7ccb40c8e7..52322c4123 100644 --- a/src/test/run-pass/borrowed-ptr-pattern.rs +++ b/src/test/run-pass/borrowed-ptr-pattern.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(x: &T) -> T{ match x { &ref a => (*a).clone() diff --git a/src/test/run-pass/box-new.rs b/src/test/run-pass/box-new.rs index 168218e1b1..a2d76d3399 100644 --- a/src/test/run-pass/box-new.rs +++ b/src/test/run-pass/box-new.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let _a = Box::new(1); } diff --git a/src/test/run-pass/box-of-array-of-drop-1.rs b/src/test/run-pass/box-of-array-of-drop-1.rs new file mode 100644 index 0000000000..a93a488c1b --- /dev/null +++ b/src/test/run-pass/box-of-array-of-drop-1.rs @@ -0,0 +1,52 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we cleanup a fixed size Box<[D; k]> properly when D has a +// destructor. + +use std::thread; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + +static LOG: AtomicUsize = ATOMIC_USIZE_INIT; + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]); + let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]); + let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]); + let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]); + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing + // the input to `_b3`. Therefore, we drop the elements of the + // partially filled array first, before we get around to dropping + // the elements of `_b1` and _b2`. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky. See similar notes in nested-vec-3; + // in essence, I would not be surprised if we change the ordering + // given in `expect` in the future. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/src/test/run-pass/box-of-array-of-drop-2.rs b/src/test/run-pass/box-of-array-of-drop-2.rs new file mode 100644 index 0000000000..715571364c --- /dev/null +++ b/src/test/run-pass/box-of-array-of-drop-2.rs @@ -0,0 +1,52 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we cleanup dynamic sized Box<[D]> properly when D has a +// destructor. + +use std::thread; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + +static LOG: AtomicUsize = ATOMIC_USIZE_INIT; + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]); + let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]); + let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]); + let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]); + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing + // the input to `_b3`. Therefore, we drop the elements of the + // partially filled array first, before we get around to dropping + // the elements of `_b1` and _b2`. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky. See similar notes in nested-vec-3; + // in essence, I would not be surprised if we change the ordering + // given in `expect` in the future. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/src/test/run-pass/break-value.rs b/src/test/run-pass/break-value.rs index efc3ab32a1..e5a035fb56 100644 --- a/src/test/run-pass/break-value.rs +++ b/src/test/run-pass/break-value.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn int_id(x: int) -> int { return x; } +// pretty-expanded FIXME #23616 + +fn int_id(x: isize) -> isize { return x; } pub fn main() { loop { int_id(break); } } diff --git a/src/test/run-pass/break.rs b/src/test/run-pass/break.rs index 6498c4b461..80934c4851 100644 --- a/src/test/run-pass/break.rs +++ b/src/test/run-pass/break.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut i = 0; while i < 20 { i += 1; if i == 10 { break; } } diff --git a/src/test/run-pass/bug-7183-generics.rs b/src/test/run-pass/bug-7183-generics.rs index a3bb02d1d0..5467ed10e9 100644 --- a/src/test/run-pass/bug-7183-generics.rs +++ b/src/test/run-pass/bug-7183-generics.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Speak : Sized { fn say(&self, s:&str) -> String; fn hi(&self) -> String { hello(self) } @@ -17,7 +19,7 @@ fn hello(s:&S) -> String{ s.say("hello") } -impl Speak for int { +impl Speak for isize { fn say(&self, s:&str) -> String { format!("{}: {}", s, *self) } @@ -37,8 +39,8 @@ pub fn main() { assert_eq!(3.hi(), "hello: 3".to_string()); assert_eq!(Some(Some(3)).hi(), "something!something!hello: 3".to_string()); - assert_eq!(None::.hi(), "hello - none".to_string()); + assert_eq!(None::.hi(), "hello - none".to_string()); - assert_eq!(Some(None::).hi(), "something!hello - none".to_string()); + assert_eq!(Some(None::).hi(), "something!hello - none".to_string()); assert_eq!(Some(3).hi(), "something!hello: 3".to_string()); } diff --git a/src/test/run-pass/bug-7295.rs b/src/test/run-pass/bug-7295.rs index 143ebfdabf..89fd51bd5f 100644 --- a/src/test/run-pass/bug-7295.rs +++ b/src/test/run-pass/bug-7295.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub trait Foo { fn func1(&self, t: U, w: T); diff --git a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs index 379ac12a95..eb6d102833 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs @@ -14,6 +14,8 @@ // a Send. Basically this just makes sure rustc is using // each_bound_trait_and_supertraits in type_contents correctly. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::{channel, Sender}; trait Bar : Send { } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs index cd019c21a3..082f5944fd 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -14,6 +14,8 @@ // Tests "capabilities" granted by traits with super-builtin-kinds, // even when using them cross-crate. +// pretty-expanded FIXME #23616 + extern crate trait_superkinds_in_metadata; use std::sync::mpsc::{channel, Sender, Receiver}; @@ -30,7 +32,7 @@ fn foo(val: T, chan: Sender) { } pub fn main() { - let (tx, rx): (Sender>, Receiver>) = channel(); + let (tx, rx): (Sender>, Receiver>) = channel(); foo(X(31337), tx); assert!(rx.recv().unwrap() == X(31337)); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities.rs b/src/test/run-pass/builtin-superkinds-capabilities.rs index dc61508eec..594fb5ec70 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities.rs @@ -12,6 +12,8 @@ // builtin-kinds, e.g., if a trait requires Send to implement, then // at usage site of that trait, we know we have the Send capability. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::{channel, Sender, Receiver}; trait Foo : Send { } @@ -23,7 +25,7 @@ fn foo(val: T, chan: Sender) { } pub fn main() { - let (tx, rx): (Sender, Receiver) = channel(); + let (tx, rx): (Sender, Receiver) = channel(); foo(31337, tx); assert!(rx.recv().unwrap() == 31337); } diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index 7eaed91012..c026ffc6d3 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -13,12 +13,14 @@ // Tests (correct) usage of trait super-builtin-kinds cross-crate. +// pretty-expanded FIXME #23616 + extern crate trait_superkinds_in_metadata; use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; -use trait_superkinds_in_metadata::{RequiresCopy}; +use trait_superkinds_in_metadata::RequiresCopy; use std::marker; -#[derive(Copy)] +#[derive(Copy, Clone)] struct X(T); impl RequiresShare for X { } diff --git a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs index 964c28dc94..6bc81f4a36 100644 --- a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs @@ -12,6 +12,8 @@ // super-builtin-kind of a trait, if the type parameter is never used, // the type can implement the trait anyway. +// pretty-expanded FIXME #23616 + use std::marker; trait Foo : Send { } diff --git a/src/test/run-pass/builtin-superkinds-self-type.rs b/src/test/run-pass/builtin-superkinds-self-type.rs index 1d05a7baa5..924a8c023f 100644 --- a/src/test/run-pass/builtin-superkinds-self-type.rs +++ b/src/test/run-pass/builtin-superkinds-self-type.rs @@ -11,6 +11,8 @@ // Tests the ability for the Self type in default methods to use // capabilities granted by builtin kinds as supertraits. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::{Sender, channel}; trait Foo : Send + Sized + 'static { diff --git a/src/test/run-pass/builtin-superkinds-simple.rs b/src/test/run-pass/builtin-superkinds-simple.rs index 9643e2986d..8a954de9d0 100644 --- a/src/test/run-pass/builtin-superkinds-simple.rs +++ b/src/test/run-pass/builtin-superkinds-simple.rs @@ -10,8 +10,10 @@ // Simple test case of implementing a trait with super-builtin-kinds. +// pretty-expanded FIXME #23616 + trait Foo : Send { } -impl Foo for int { } +impl Foo for isize { } pub fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-typaram.rs b/src/test/run-pass/builtin-superkinds-typaram.rs index d96679c69f..6d41774c05 100644 --- a/src/test/run-pass/builtin-superkinds-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-typaram.rs @@ -11,6 +11,8 @@ // Tests correct implementation of traits with super-builtin-kinds // using a bounded type parameter. +// pretty-expanded FIXME #23616 + trait Foo : Send { } impl Foo for T { } diff --git a/src/test/run-pass/by-value-self-in-mut-slot.rs b/src/test/run-pass/by-value-self-in-mut-slot.rs index aa88004cd1..464c24fc8b 100644 --- a/src/test/run-pass/by-value-self-in-mut-slot.rs +++ b/src/test/run-pass/by-value-self-in-mut-slot.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct X { - a: int + a: isize } trait Changer { diff --git a/src/test/run-pass/byte-literals.rs b/src/test/run-pass/byte-literals.rs index 874dbdc662..fbe2a65bc8 100644 --- a/src/test/run-pass/byte-literals.rs +++ b/src/test/run-pass/byte-literals.rs @@ -13,9 +13,13 @@ static FOO: u8 = b'\xF0'; static BAR: &'static [u8] = b"a\xF0\t"; +static BAR_FIXED: &'static [u8; 3] = b"a\xF0\t"; static BAZ: &'static [u8] = br"a\n"; pub fn main() { + let bar: &'static [u8] = b"a\xF0\t"; + let bar_fixed: &'static [u8; 3] = b"a\xF0\t"; + assert_eq!(b'a', 97u8); assert_eq!(b'\n', 10u8); assert_eq!(b'\r', 13u8); @@ -44,8 +48,11 @@ pub fn main() { b", expected); let expected: &[_] = &[97u8, 240u8, 9u8]; assert_eq!(BAR, expected); + assert_eq!(BAR_FIXED, expected); + assert_eq!(bar, expected); + assert_eq!(bar_fixed, expected); - let val: &[_] = &[97u8, 10u8]; + let val = &[97u8, 10u8]; match val { b"a\n" => {}, _ => panic!(), @@ -53,9 +60,9 @@ pub fn main() { let buf = vec!(97u8, 98, 99, 100); assert_eq!(match &buf[0..3] { - b"def" => 1_usize, - b"abc" => 2_usize, - _ => 3_usize + b"def" => 1, + b"abc" => 2, + _ => 3 }, 2); let expected: &[_] = &[97u8, 92u8, 110u8]; diff --git a/src/test/run-pass/c-stack-as-value.rs b/src/test/run-pass/c-stack-as-value.rs index 6a1dde24d6..b678f149fa 100644 --- a/src/test/run-pass/c-stack-as-value.rs +++ b/src/test/run-pass/c-stack-as-value.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + mod rustrt { extern crate libc; diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 6246ee9c6c..dcf1b55400 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate + +// pretty-expanded FIXME #23616 + +#![feature(libc, std_misc)] extern crate libc; @@ -23,9 +26,9 @@ mod mlibc { } } -fn atol(s: String) -> int { +fn atol(s: String) -> isize { let c = CString::new(s).unwrap(); - unsafe { mlibc::atol(c.as_ptr()) as int } + unsafe { mlibc::atol(c.as_ptr()) as isize } } fn atoll(s: String) -> i64 { diff --git a/src/test/run-pass/call-closure-from-overloaded-op.rs b/src/test/run-pass/call-closure-from-overloaded-op.rs index 29fcdf504d..e3ee282ec2 100644 --- a/src/test/run-pass/call-closure-from-overloaded-op.rs +++ b/src/test/run-pass/call-closure-from-overloaded-op.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo() -> int { 22 } +// pretty-expanded FIXME #23616 + +fn foo() -> isize { 22 } pub fn main() { - let mut x: Vec int> = Vec::new(); + let mut x: Vec isize> = Vec::new(); x.push(foo); assert_eq!((x[0])(), 22); } diff --git a/src/test/run-pass/can-copy-pod.rs b/src/test/run-pass/can-copy-pod.rs index 099374b593..31b2793352 100644 --- a/src/test/run-pass/can-copy-pod.rs +++ b/src/test/run-pass/can-copy-pod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ @@ -21,5 +23,3 @@ fn can_copy_copy(v: T) { } pub fn main() {} - - diff --git a/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs b/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs index 631133cc7f..d2eb5c33ea 100644 --- a/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs +++ b/src/test/run-pass/cancel-clean-via-immediate-rvalue-ref.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/capture-clauses-boxed-closures.rs b/src/test/run-pass/capture-clauses-boxed-closures.rs index 1a85797fa6..5bf6f5fb04 100644 --- a/src/test/run-pass/capture-clauses-boxed-closures.rs +++ b/src/test/run-pass/capture-clauses-boxed-closures.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn each(x: &[T], mut f: F) where F: FnMut(&T) { for val in x { f(val) @@ -20,4 +22,3 @@ fn main() { each(&elems, |val| sum += *val); assert_eq!(sum, 15); } - diff --git a/src/test/run-pass/capture-clauses-unboxed-closures.rs b/src/test/run-pass/capture-clauses-unboxed-closures.rs index dd417f1a9e..448ed76fe9 100644 --- a/src/test/run-pass/capture-clauses-unboxed-closures.rs +++ b/src/test/run-pass/capture-clauses-unboxed-closures.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) { @@ -17,8 +19,8 @@ fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) { } fn main() { - let mut sum = 0_usize; - let elems = [ 1_usize, 2, 3, 4, 5 ]; - each(&elems, |val: &uint| sum += *val); + let mut sum = 0; + let elems = [ 1, 2, 3, 4, 5 ]; + each(&elems, |val: &usize| sum += *val); assert_eq!(sum, 15); } diff --git a/src/test/run-pass/capturing-logging.rs b/src/test/run-pass/capturing-logging.rs index 70cc0463a6..f9b429a935 100644 --- a/src/test/run-pass/capturing-logging.rs +++ b/src/test/run-pass/capturing-logging.rs @@ -10,8 +10,10 @@ // exec-env:RUST_LOG=info +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, old_io, rustc_private, std_misc)] #[macro_use] extern crate log; @@ -19,8 +21,8 @@ extern crate log; use log::{set_logger, Logger, LogRecord}; use std::sync::mpsc::channel; use std::fmt; -use std::old_io::{ChanReader, ChanWriter}; -use std::thread::Thread; +use std::old_io::{ChanReader, ChanWriter, Reader, Writer}; +use std::thread; struct MyWriter(ChanWriter); @@ -34,7 +36,7 @@ impl Logger for MyWriter { fn main() { let (tx, rx) = channel(); let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx)); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { set_logger(box MyWriter(w) as Box); debug!("debug"); info!("info"); diff --git a/src/test/run-pass/cast-in-array-size.rs b/src/test/run-pass/cast-in-array-size.rs index 717ca3ff9f..6f1fafba56 100644 --- a/src/test/run-pass/cast-in-array-size.rs +++ b/src/test/run-pass/cast-in-array-size.rs @@ -10,11 +10,13 @@ // issues #10618 and #16382 -const SIZE: int = 25; +// pretty-expanded FIXME #23616 + +const SIZE: isize = 25; fn main() { - let _a: [bool; 1 as uint]; - let _b: [int; SIZE as uint] = [1; SIZE as uint]; - let _c: [bool; '\n' as uint] = [true; '\n' as uint]; - let _d: [bool; true as uint] = [true; true as uint]; + let _a: [bool; 1 as usize]; + let _b: [isize; SIZE as usize] = [1; SIZE as usize]; + let _c: [bool; '\n' as usize] = [true; '\n' as usize]; + let _d: [bool; true as usize] = [true; true as usize]; } diff --git a/src/test/run-pass/cast-region-to-uint.rs b/src/test/run-pass/cast-region-to-uint.rs index a298a08a1b..f5180ea260 100644 --- a/src/test/run-pass/cast-region-to-uint.rs +++ b/src/test/run-pass/cast-region-to-uint.rs @@ -9,6 +9,6 @@ // except according to those terms. pub fn main() { - let x = 3; - println!("&x={:x}", (&x as *const int as uint)); + let x: isize = 3; + println!("&x={:x}", (&x as *const isize as usize)); } diff --git a/src/test/run-pass/cast.rs b/src/test/run-pass/cast.rs index f8a680b2a9..03a73555f8 100644 --- a/src/test/run-pass/cast.rs +++ b/src/test/run-pass/cast.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let i: int = 'Q' as int; + let i: isize = 'Q' as isize; assert_eq!(i, 0x51); let u: u32 = i as u32; assert_eq!(u, 0x51 as u32); assert_eq!(u, 'Q' as u32); assert_eq!(i as u8, 'Q' as u8); assert_eq!(i as u8 as i8, 'Q' as u8 as i8); - assert_eq!(0x51u8 as char, 'Q'); + assert_eq!(0x51 as char, 'Q'); assert_eq!(0 as u32, false as u32); } diff --git a/src/test/run-pass/cci_borrow.rs b/src/test/run-pass/cci_borrow.rs index 00c600ed00..cd8f783a2e 100644 --- a/src/test/run-pass/cci_borrow.rs +++ b/src/test/run-pass/cci_borrow.rs @@ -17,8 +17,8 @@ extern crate cci_borrow_lib; use cci_borrow_lib::foo; pub fn main() { - let p = box 22_usize; + let p: Box<_> = box 22; let r = foo(&*p); println!("r={}", r); - assert_eq!(r, 22_usize); + assert_eq!(r, 22); } diff --git a/src/test/run-pass/cci_capture_clause.rs b/src/test/run-pass/cci_capture_clause.rs index 8b2947ba3e..80b75af6e4 100644 --- a/src/test/run-pass/cci_capture_clause.rs +++ b/src/test/run-pass/cci_capture_clause.rs @@ -13,6 +13,8 @@ // This test makes sure we can do cross-crate inlining on functions // that use capture clauses. +// pretty-expanded FIXME #23616 + extern crate cci_capture_clause; pub fn main() { diff --git a/src/test/run-pass/cci_impl_exe.rs b/src/test/run-pass/cci_impl_exe.rs index c4b55b9962..bda3b73e29 100644 --- a/src/test/run-pass/cci_impl_exe.rs +++ b/src/test/run-pass/cci_impl_exe.rs @@ -17,7 +17,7 @@ pub fn main() { //let bt0 = sys::frame_address(); //println!("%?", bt0); - 3_usize.to(10_usize, |i| { + 3.to(10, |i| { println!("{}", i); //let bt1 = sys::frame_address(); diff --git a/src/test/run-pass/cci_iter_exe.rs b/src/test/run-pass/cci_iter_exe.rs index e4b26ba74b..5b91af7a19 100644 --- a/src/test/run-pass/cci_iter_exe.rs +++ b/src/test/run-pass/cci_iter_exe.rs @@ -13,10 +13,10 @@ extern crate cci_iter_lib; pub fn main() { - //let bt0 = sys::rusti::frame_address(1u32); + //let bt0 = sys::rusti::frame_address(1); //println!("%?", bt0); cci_iter_lib::iter(&[1, 2, 3], |i| { println!("{}", *i); - //assert!(bt0 == sys::rusti::frame_address(2u32)); + //assert!(bt0 == sys::rusti::frame_address(2)); }) } diff --git a/src/test/run-pass/cci_nested_exe.rs b/src/test/run-pass/cci_nested_exe.rs index 778e82a8fe..6654698830 100644 --- a/src/test/run-pass/cci_nested_exe.rs +++ b/src/test/run-pass/cci_nested_exe.rs @@ -10,6 +10,8 @@ // aux-build:cci_nested_lib.rs +// pretty-expanded FIXME #23616 + #![feature(globs)] extern crate cci_nested_lib; diff --git a/src/test/run-pass/cci_no_inline_exe.rs b/src/test/run-pass/cci_no_inline_exe.rs index 2040bd7ad7..cc76ed530c 100644 --- a/src/test/run-pass/cci_no_inline_exe.rs +++ b/src/test/run-pass/cci_no_inline_exe.rs @@ -21,7 +21,7 @@ pub fn main() { // actually working. //let bt0 = sys::frame_address(); //println!("%?", bt0); - iter(vec!(1_usize, 2_usize, 3_usize), |i| { + iter(vec!(1, 2, 3), |i| { println!("{}", i); //let bt1 = sys::frame_address(); diff --git a/src/test/run-pass/cell-does-not-clone.rs b/src/test/run-pass/cell-does-not-clone.rs index ea1d0b625f..c87a3e8bb9 100644 --- a/src/test/run-pass/cell-does-not-clone.rs +++ b/src/test/run-pass/cell-does-not-clone.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cell::Cell; #[derive(Copy)] struct Foo { - x: int + x: isize } impl Clone for Foo { diff --git a/src/test/run-pass/cfg-attr-cfg.rs b/src/test/run-pass/cfg-attr-cfg.rs index 09ab701948..74022d4c6c 100644 --- a/src/test/run-pass/cfg-attr-cfg.rs +++ b/src/test/run-pass/cfg-attr-cfg.rs @@ -11,5 +11,7 @@ // main is conditionally compiled, but the conditional compilation // is conditional too! +// pretty-expanded FIXME #23616 + #[cfg_attr(foo, cfg(bar))] fn main() { } diff --git a/src/test/run-pass/cfg-attr-crate.rs b/src/test/run-pass/cfg-attr-crate.rs index e6bd8afad2..25d689475f 100644 --- a/src/test/run-pass/cfg-attr-crate.rs +++ b/src/test/run-pass/cfg-attr-crate.rs @@ -10,6 +10,8 @@ // https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 +// pretty-expanded FIXME #23616 + #![cfg_attr(not_used, no_std)] fn main() { } diff --git a/src/test/run-pass/cfg-family.rs b/src/test/run-pass/cfg-family.rs index 24120b69c7..415607aa72 100644 --- a/src/test/run-pass/cfg-family.rs +++ b/src/test/run-pass/cfg-family.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[cfg(windows)] pub fn main() { } diff --git a/src/test/run-pass/cfg-macros-foo.rs b/src/test/run-pass/cfg-macros-foo.rs index aeb6fcbbc0..5fa1bc47f8 100644 --- a/src/test/run-pass/cfg-macros-foo.rs +++ b/src/test/run-pass/cfg-macros-foo.rs @@ -13,6 +13,8 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-notfoo.rs) +// pretty-expanded FIXME #23616 + #[cfg(foo)] #[macro_use] mod foo { diff --git a/src/test/run-pass/cfg-macros-notfoo.rs b/src/test/run-pass/cfg-macros-notfoo.rs index adc27d5562..7cddac1603 100644 --- a/src/test/run-pass/cfg-macros-notfoo.rs +++ b/src/test/run-pass/cfg-macros-notfoo.rs @@ -13,6 +13,8 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-foo.rs) +// pretty-expanded FIXME #23616 + #[cfg(foo)] #[macro_use] mod foo { diff --git a/src/test/run-pass/cfg-match-arm.rs b/src/test/run-pass/cfg-match-arm.rs index 02f02862f6..05dc7d5242 100644 --- a/src/test/run-pass/cfg-match-arm.rs +++ b/src/test/run-pass/cfg-match-arm.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { Bar, Baz, diff --git a/src/test/run-pass/cfg-target-family.rs b/src/test/run-pass/cfg-target-family.rs index 784c9326a0..b6954f7c2e 100644 --- a/src/test/run-pass/cfg-target-family.rs +++ b/src/test/run-pass/cfg-target-family.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[cfg(target_family = "windows")] pub fn main() { } diff --git a/src/test/run-pass/cfg_inner_static.rs b/src/test/run-pass/cfg_inner_static.rs index 04912fc200..b3d5ddc428 100644 --- a/src/test/run-pass/cfg_inner_static.rs +++ b/src/test/run-pass/cfg_inner_static.rs @@ -10,6 +10,8 @@ // aux-build:cfg_inner_static.rs +// pretty-expanded FIXME #23616 + extern crate cfg_inner_static; pub fn main() { diff --git a/src/test/run-pass/cfgs-on-items.rs b/src/test/run-pass/cfgs-on-items.rs index b7cf3c4d22..5c22d5c869 100644 --- a/src/test/run-pass/cfgs-on-items.rs +++ b/src/test/run-pass/cfgs-on-items.rs @@ -11,24 +11,26 @@ // compile-flags: --cfg fooA --cfg fooB // fooA AND !bar +// pretty-expanded FIXME #23616 + #[cfg(all(fooA, not(bar)))] -fn foo1() -> int { 1 } +fn foo1() -> isize { 1 } // !fooA AND !bar #[cfg(all(not(fooA), not(bar)))] -fn foo2() -> int { 2 } +fn foo2() -> isize { 2 } // fooC OR (fooB AND !bar) #[cfg(any(fooC, all(fooB, not(bar))))] -fn foo2() -> int { 3 } +fn foo2() -> isize { 3 } // fooA AND bar #[cfg(all(fooA, bar))] -fn foo3() -> int { 2 } +fn foo3() -> isize { 2 } // !(fooA AND bar) #[cfg(not(all(fooA, bar)))] -fn foo3() -> int { 3 } +fn foo3() -> isize { 3 } pub fn main() { assert_eq!(1, foo1()); diff --git a/src/test/run-pass/char.rs b/src/test/run-pass/char.rs index f982d3723b..801b01918e 100644 --- a/src/test/run-pass/char.rs +++ b/src/test/run-pass/char.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + pub fn main() { let c: char = 'x'; let d: char = 'x'; diff --git a/src/test/run-pass/check-static-mut-slices.rs b/src/test/run-pass/check-static-mut-slices.rs index af25c43005..19c3458ef7 100644 --- a/src/test/run-pass/check-static-mut-slices.rs +++ b/src/test/run-pass/check-static-mut-slices.rs @@ -10,7 +10,9 @@ // Checks that mutable static items can have mutable slices -static mut TEST: &'static mut [int] = &mut [1]; +// pretty-expanded FIXME #23616 + +static mut TEST: &'static mut [isize] = &mut [1]; pub fn main() { unsafe { diff --git a/src/test/run-pass/check-static-recursion-foreign.rs b/src/test/run-pass/check-static-recursion-foreign.rs index 4e05c263a4..554853ade5 100644 --- a/src/test/run-pass/check-static-recursion-foreign.rs +++ b/src/test/run-pass/check-static-recursion-foreign.rs @@ -12,7 +12,9 @@ // aux-build:check_static_recursion_foreign_helper.rs -#![feature(custom_attribute)] +// pretty-expanded FIXME #23616 + +#![feature(custom_attribute, libc)] extern crate check_static_recursion_foreign_helper; extern crate libc; diff --git a/src/test/run-pass/check-static-slice.rs b/src/test/run-pass/check-static-slice.rs index 6e2cfedf9e..8a7ae1de9b 100644 --- a/src/test/run-pass/check-static-slice.rs +++ b/src/test/run-pass/check-static-slice.rs @@ -11,22 +11,24 @@ // Check that the various ways of getting to a reference to a vec (both sized // and unsized) work properly. -const aa: [int; 3] = [1, 2, 3]; -const ab: &'static [int; 3] = &aa; -const ac: &'static [int] = ab; -const ad: &'static [int] = &aa; -const ae: &'static [int; 3] = &[1, 2, 3]; -const af: &'static [int] = &[1, 2, 3]; +// pretty-expanded FIXME #23616 -static ca: int = aa[0]; -static cb: int = ab[1]; -static cc: int = ac[2]; -static cd: int = ad[0]; -static ce: int = ae[1]; -static cf: int = af[2]; +const aa: [isize; 3] = [1, 2, 3]; +const ab: &'static [isize; 3] = &aa; +const ac: &'static [isize] = ab; +const ad: &'static [isize] = &aa; +const ae: &'static [isize; 3] = &[1, 2, 3]; +const af: &'static [isize] = &[1, 2, 3]; + +static ca: isize = aa[0]; +static cb: isize = ab[1]; +static cc: isize = ac[2]; +static cd: isize = ad[0]; +static ce: isize = ae[1]; +static cf: isize = af[2]; fn main () { - let b: &[int] = &[1, 2, 3]; + let b: &[isize] = &[1, 2, 3]; assert!(ac == b); assert!(ad == b); assert!(af == b); diff --git a/src/test/run-pass/child-outlives-parent.rs b/src/test/run-pass/child-outlives-parent.rs index 39af96a58e..7da1416602 100644 --- a/src/test/run-pass/child-outlives-parent.rs +++ b/src/test/run-pass/child-outlives-parent.rs @@ -10,10 +10,14 @@ // Reported as issue #126, child leaks the string. -use std::thread::Thread; +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + +use std::thread; fn child2(_s: String) { } pub fn main() { - let _x = Thread::spawn(move|| child2("hi".to_string())); + let _x = thread::spawn(move|| child2("hi".to_string())); } diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs index 9a388c9bc2..da51ad761c 100644 --- a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs +++ b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs @@ -25,6 +25,6 @@ fn print_out(thing: Box, expected: String) { } pub fn main() { - let nyan: Box = box cat(0_usize, 2, "nyan".to_string()) as Box; + let nyan: Box = box cat(0, 2, "nyan".to_string()) as Box; print_out(nyan, "nyan".to_string()); } diff --git a/src/test/run-pass/class-cast-to-trait-multiple-types.rs b/src/test/run-pass/class-cast-to-trait-multiple-types.rs index 4f1654e603..e5acad3a3a 100644 --- a/src/test/run-pass/class-cast-to-trait-multiple-types.rs +++ b/src/test/run-pass/class-cast-to-trait-multiple-types.rs @@ -10,17 +10,17 @@ trait noisy { - fn speak(&mut self) -> int; + fn speak(&mut self) -> isize; } struct dog { - barks: uint, + barks: usize, - volume: int, + volume: isize, } impl dog { - fn bark(&mut self) -> int { + fn bark(&mut self) -> isize { println!("Woof {} {}", self.barks, self.volume); self.barks += 1_usize; if self.barks % 3_usize == 0_usize { @@ -35,7 +35,7 @@ impl dog { } impl noisy for dog { - fn speak(&mut self) -> int { + fn speak(&mut self) -> isize { self.bark() } } @@ -49,26 +49,26 @@ fn dog() -> dog { #[derive(Clone)] struct cat { - meows: uint, + meows: usize, - how_hungry: int, + how_hungry: isize, name: String, } impl noisy for cat { - fn speak(&mut self) -> int { - self.meow() as int + fn speak(&mut self) -> isize { + self.meow() as isize } } impl cat { - pub fn meow_count(&self) -> uint { + pub fn meow_count(&self) -> usize { self.meows } } impl cat { - fn meow(&mut self) -> uint { + fn meow(&mut self) -> usize { println!("Meow"); self.meows += 1_usize; if self.meows % 5_usize == 0_usize { @@ -78,7 +78,7 @@ impl cat { } } -fn cat(in_x: uint, in_y: int, in_name: String) -> cat { +fn cat(in_x: usize, in_y: isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/run-pass/class-cast-to-trait.rs b/src/test/run-pass/class-cast-to-trait.rs index 476594c270..adb0b6cd0a 100644 --- a/src/test/run-pass/class-cast-to-trait.rs +++ b/src/test/run-pass/class-cast-to-trait.rs @@ -16,8 +16,8 @@ trait noisy { } struct cat { - meows: uint, - how_hungry: int, + meows: usize, + how_hungry: isize, name: String, } @@ -42,14 +42,14 @@ impl cat { impl cat { fn meow(&mut self) { println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { + self.meows += 1; + if self.meows % 5 == 0 { self.how_hungry += 1; } } } -fn cat(in_x : uint, in_y : int, in_name: String) -> cat { +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, @@ -59,7 +59,7 @@ fn cat(in_x : uint, in_y : int, in_name: String) -> cat { pub fn main() { - let mut nyan = cat(0_usize, 2, "nyan".to_string()); + let mut nyan = cat(0, 2, "nyan".to_string()); let mut nyan: &mut noisy = &mut nyan; nyan.speak(); } diff --git a/src/test/run-pass/class-dtor.rs b/src/test/run-pass/class-dtor.rs index 14247ad775..05ec2bc0ac 100644 --- a/src/test/run-pass/class-dtor.rs +++ b/src/test/run-pass/class-dtor.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { - done : extern fn(uint), - meows : uint, + done : extern fn(usize), + meows : usize, } impl Drop for cat { @@ -19,9 +21,9 @@ impl Drop for cat { } } -fn cat(done: extern fn(uint)) -> cat { +fn cat(done: extern fn(usize)) -> cat { cat { - meows: 0_usize, + meows: 0, done: done } } diff --git a/src/test/run-pass/class-exports.rs b/src/test/run-pass/class-exports.rs index 4c7d0e6951..675acf1dd6 100644 --- a/src/test/run-pass/class-exports.rs +++ b/src/test/run-pass/class-exports.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* Test that exporting a class also exports its public fields and methods */ @@ -16,7 +17,7 @@ use kitty::cat; mod kitty { pub struct cat { - meows: uint, + meows: usize, name: String, } @@ -27,7 +28,7 @@ mod kitty { pub fn cat(in_name: String) -> cat { cat { name: in_name, - meows: 0_usize + meows: 0 } } } diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index c3ced512af..4c494293b5 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -11,25 +11,25 @@ use std::cmp; -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum cat_type { tuxedo, tabby, tortoiseshell } impl cmp::PartialEq for cat_type { fn eq(&self, other: &cat_type) -> bool { - ((*self) as uint) == ((*other) as uint) + ((*self) as usize) == ((*other) as usize) } fn ne(&self, other: &cat_type) -> bool { !(*self).eq(other) } } // Very silly -- this just returns the value of the name field -// for any int value that's less than the meows field +// for any isize value that's less than the meows field // ok: T should be in scope when resolving the trait ref for map struct cat { // Yes, you can have negative meows - meows : int, + meows : isize, - how_hungry : int, + how_hungry : isize, name : T, } @@ -46,26 +46,26 @@ impl cat { return false; } } - fn len(&self) -> uint { self.meows as uint } + fn len(&self) -> usize { self.meows as usize } fn is_empty(&self) -> bool { self.meows == 0 } fn clear(&mut self) {} - fn contains_key(&self, k: &int) -> bool { *k <= self.meows } + fn contains_key(&self, k: &isize) -> bool { *k <= self.meows } - fn find(&self, k: &int) -> Option<&T> { + fn find(&self, k: &isize) -> Option<&T> { if *k <= self.meows { Some(&self.name) } else { None } } - fn insert(&mut self, k: int, _: T) -> bool { + fn insert(&mut self, k: isize, _: T) -> bool { self.meows += k; true } - fn find_mut(&mut self, _k: &int) -> Option<&mut T> { panic!() } + fn find_mut(&mut self, _k: &isize) -> Option<&mut T> { panic!() } - fn remove(&mut self, k: &int) -> bool { + fn remove(&mut self, k: &isize) -> bool { if self.find(k).is_some() { self.meows -= *k; true } else { @@ -73,20 +73,20 @@ impl cat { } } - fn pop(&mut self, _k: &int) -> Option { panic!() } + fn pop(&mut self, _k: &isize) -> Option { panic!() } - fn swap(&mut self, _k: int, _v: T) -> Option { panic!() } + fn swap(&mut self, _k: isize, _v: T) -> Option { panic!() } } impl cat { - pub fn get(&self, k: &int) -> &T { + pub fn get(&self, k: &isize) -> &T { match self.find(k) { Some(v) => { v } None => { panic!("epic fail"); } } } - pub fn new(in_x: int, in_y: int, in_name: T) -> cat { + pub fn new(in_x: isize, in_y: isize, in_name: T) -> cat { cat{meows: in_x, how_hungry: in_y, name: in_name } } } diff --git a/src/test/run-pass/class-implement-trait-cross-crate.rs b/src/test/run-pass/class-implement-trait-cross-crate.rs index bd05221b8c..5a1dc930ef 100644 --- a/src/test/run-pass/class-implement-trait-cross-crate.rs +++ b/src/test/run-pass/class-implement-trait-cross-crate.rs @@ -13,9 +13,9 @@ extern crate cci_class_trait; use cci_class_trait::animals::noisy; struct cat { - meows: uint, + meows: usize, - how_hungry : int, + how_hungry : isize, name : String, } @@ -47,7 +47,7 @@ impl cat { } } -fn cat(in_x : uint, in_y : int, in_name: String) -> cat { +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/run-pass/class-implement-traits.rs b/src/test/run-pass/class-implement-traits.rs index 87e6e5f675..394af6b9ec 100644 --- a/src/test/run-pass/class-implement-traits.rs +++ b/src/test/run-pass/class-implement-traits.rs @@ -15,9 +15,9 @@ trait noisy { #[derive(Clone)] struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, name : String, } @@ -48,7 +48,7 @@ impl noisy for cat { fn speak(&mut self) { self.meow(); } } -fn cat(in_x : uint, in_y : int, in_name: String) -> cat { +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/run-pass/class-method-cross-crate.rs b/src/test/run-pass/class-method-cross-crate.rs index 47cc500e44..a5c60e3a7b 100644 --- a/src/test/run-pass/class-method-cross-crate.rs +++ b/src/test/run-pass/class-method-cross-crate.rs @@ -9,12 +9,14 @@ // except according to those terms. // aux-build:cci_class_2.rs +// pretty-expanded FIXME #23616 + extern crate cci_class_2; use cci_class_2::kitties::cat; pub fn main() { - let nyan : cat = cat(52_usize, 99); - let kitty = cat(1000_usize, 2); + let nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); nyan.speak(); diff --git a/src/test/run-pass/class-methods-cross-crate.rs b/src/test/run-pass/class-methods-cross-crate.rs index d62a726dcd..73abaf7d34 100644 --- a/src/test/run-pass/class-methods-cross-crate.rs +++ b/src/test/run-pass/class-methods-cross-crate.rs @@ -9,14 +9,16 @@ // except according to those terms. // aux-build:cci_class_3.rs +// pretty-expanded FIXME #23616 + extern crate cci_class_3; use cci_class_3::kitties::cat; pub fn main() { - let mut nyan : cat = cat(52_usize, 99); - let kitty = cat(1000_usize, 2); + let mut nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); nyan.speak(); - assert_eq!(nyan.meow_count(), 53_usize); + assert_eq!(nyan.meow_count(), 53); } diff --git a/src/test/run-pass/class-methods.rs b/src/test/run-pass/class-methods.rs index 18fb03ec93..d454bdd73a 100644 --- a/src/test/run-pass/class-methods.rs +++ b/src/test/run-pass/class-methods.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, } impl cat { - pub fn speak(&mut self) { self.meows += 1_usize; } - pub fn meow_count(&mut self) -> uint { self.meows } + pub fn speak(&mut self) { self.meows += 1; } + pub fn meow_count(&mut self) -> usize { self.meows } } -fn cat(in_x: uint, in_y: int) -> cat { +fn cat(in_x: usize, in_y: isize) -> cat { cat { meows: in_x, how_hungry: in_y @@ -27,10 +29,10 @@ fn cat(in_x: uint, in_y: int) -> cat { } pub fn main() { - let mut nyan: cat = cat(52_usize, 99); - let kitty = cat(1000_usize, 2); + let mut nyan: cat = cat(52, 99); + let kitty = cat(1000, 2); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); nyan.speak(); - assert_eq!(nyan.meow_count(), 53_usize); + assert_eq!(nyan.meow_count(), 53); } diff --git a/src/test/run-pass/class-poly-methods-cross-crate.rs b/src/test/run-pass/class-poly-methods-cross-crate.rs index edbbc4f5b3..6537a931fa 100644 --- a/src/test/run-pass/class-poly-methods-cross-crate.rs +++ b/src/test/run-pass/class-poly-methods-cross-crate.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:cci_class_6.rs +// pretty-expanded FIXME #23616 + extern crate cci_class_6; use cci_class_6::kitties::cat; diff --git a/src/test/run-pass/class-poly-methods.rs b/src/test/run-pass/class-poly-methods.rs index b529b0a077..27f872d532 100644 --- a/src/test/run-pass/class-poly-methods.rs +++ b/src/test/run-pass/class-poly-methods.rs @@ -9,21 +9,23 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { info : Vec , - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, } impl cat { pub fn speak(&mut self, stuff: Vec ) { self.meows += stuff.len(); } - pub fn meow_count(&mut self) -> uint { self.meows } + pub fn meow_count(&mut self) -> usize { self.meows } } -fn cat(in_x : uint, in_y : int, in_info: Vec ) -> cat { +fn cat(in_x : usize, in_y : isize, in_info: Vec ) -> cat { cat { meows: in_x, how_hungry: in_y, @@ -32,12 +34,12 @@ fn cat(in_x : uint, in_y : int, in_info: Vec ) -> cat { } pub fn main() { - let mut nyan : cat = cat::(52_usize, 99, vec!(9)); - let mut kitty = cat(1000_usize, 2, vec!("tabby".to_string())); + let mut nyan : cat = cat::(52, 99, vec!(9)); + let mut kitty = cat(1000, 2, vec!("tabby".to_string())); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); nyan.speak(vec!(1,2,3)); - assert_eq!(nyan.meow_count(), 55_usize); + assert_eq!(nyan.meow_count(), 55); kitty.speak(vec!("meow".to_string(), "mew".to_string(), "purr".to_string(), "chirp".to_string())); - assert_eq!(kitty.meow_count(), 1004_usize); + assert_eq!(kitty.meow_count(), 1004); } diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index 575c32baea..52853658c8 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -14,9 +14,9 @@ use std::fmt; struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, name : String, } @@ -39,14 +39,14 @@ impl cat { impl cat { fn meow(&mut self) { println!("Meow"); - self.meows += 1_usize; - if self.meows % 5_usize == 0_usize { + self.meows += 1; + if self.meows % 5 == 0 { self.how_hungry += 1; } } } -fn cat(in_x : uint, in_y : int, in_name: String) -> cat { +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, @@ -54,7 +54,7 @@ fn cat(in_x : uint, in_y : int, in_name: String) -> cat { } } -impl fmt::String for cat { +impl fmt::Display for cat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) } @@ -67,6 +67,6 @@ fn print_out(thing: Box, expected: String) { } pub fn main() { - let nyan: Box = box cat(0_usize, 2, "nyan".to_string()) as Box; + let nyan: Box = box cat(0, 2, "nyan".to_string()) as Box; print_out(nyan, "nyan".to_string()); } diff --git a/src/test/run-pass/class-str-field.rs b/src/test/run-pass/class-str-field.rs index 2fb8610092..e3b9b56db0 100644 --- a/src/test/run-pass/class-str-field.rs +++ b/src/test/run-pass/class-str-field.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { name : String, diff --git a/src/test/run-pass/class-typarams.rs b/src/test/run-pass/class-typarams.rs index b56a749d33..cc9a118ba1 100644 --- a/src/test/run-pass/class-typarams.rs +++ b/src/test/run-pass/class-typarams.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::marker::PhantomData; struct cat { - meows : uint, - how_hungry : int, + meows : usize, + how_hungry : isize, m: PhantomData } impl cat { - pub fn speak(&mut self) { self.meows += 1_usize; } - pub fn meow_count(&mut self) -> uint { self.meows } + pub fn speak(&mut self) { self.meows += 1; } + pub fn meow_count(&mut self) -> usize { self.meows } } -fn cat(in_x : uint, in_y : int) -> cat { +fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y, @@ -31,6 +33,6 @@ fn cat(in_x : uint, in_y : int) -> cat { pub fn main() { - let _nyan : cat = cat::(52_usize, 99); - // let mut kitty = cat(1000_usize, 2); + let _nyan : cat = cat::(52, 99); + // let mut kitty = cat(1000, 2); } diff --git a/src/test/run-pass/classes-cross-crate.rs b/src/test/run-pass/classes-cross-crate.rs index aae17abcc5..36d7bd6b3c 100644 --- a/src/test/run-pass/classes-cross-crate.rs +++ b/src/test/run-pass/classes-cross-crate.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:cci_class_4.rs +// pretty-expanded FIXME #23616 + extern crate cci_class_4; use cci_class_4::kitties::cat; diff --git a/src/test/run-pass/classes-self-referential.rs b/src/test/run-pass/classes-self-referential.rs index a54a821a7b..487d20729d 100644 --- a/src/test/run-pass/classes-self-referential.rs +++ b/src/test/run-pass/classes-self-referential.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct kitten { cat: Option, } diff --git a/src/test/run-pass/classes-simple-cross-crate.rs b/src/test/run-pass/classes-simple-cross-crate.rs index 8037d77807..cfa13dbe62 100644 --- a/src/test/run-pass/classes-simple-cross-crate.rs +++ b/src/test/run-pass/classes-simple-cross-crate.rs @@ -9,12 +9,14 @@ // except according to those terms. // aux-build:cci_class.rs +// pretty-expanded FIXME #23616 + extern crate cci_class; use cci_class::kitties::cat; pub fn main() { - let nyan : cat = cat(52_usize, 99); - let kitty = cat(1000_usize, 2); + let nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); } diff --git a/src/test/run-pass/classes-simple-method.rs b/src/test/run-pass/classes-simple-method.rs index b15d6544fe..0d9f859d2d 100644 --- a/src/test/run-pass/classes-simple-method.rs +++ b/src/test/run-pass/classes-simple-method.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, } impl cat { pub fn speak(&mut self) {} } -fn cat(in_x : uint, in_y : int) -> cat { +fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y @@ -26,8 +28,8 @@ fn cat(in_x : uint, in_y : int) -> cat { } pub fn main() { - let mut nyan : cat = cat(52_usize, 99); - let kitty = cat(1000_usize, 2); + let mut nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); nyan.speak(); diff --git a/src/test/run-pass/classes-simple.rs b/src/test/run-pass/classes-simple.rs index 9bf8df3ce4..f520623a75 100644 --- a/src/test/run-pass/classes-simple.rs +++ b/src/test/run-pass/classes-simple.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, } -fn cat(in_x : uint, in_y : int) -> cat { +fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y @@ -22,8 +24,8 @@ fn cat(in_x : uint, in_y : int) -> cat { } pub fn main() { - let nyan : cat = cat(52_usize, 99); - let kitty = cat(1000_usize, 2); + let nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); assert_eq!(nyan.how_hungry, 99); assert_eq!(kitty.how_hungry, 2); } diff --git a/src/test/run-pass/classes.rs b/src/test/run-pass/classes.rs index 4fabca491b..fa0dda1123 100644 --- a/src/test/run-pass/classes.rs +++ b/src/test/run-pass/classes.rs @@ -9,9 +9,9 @@ // except according to those terms. struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, name : String, } @@ -40,7 +40,7 @@ impl cat { } } -fn cat(in_x : uint, in_y : int, in_name: String) -> cat { +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { cat { meows: in_x, how_hungry: in_y, diff --git a/src/test/run-pass/cleanup-arm-conditional.rs b/src/test/run-pass/cleanup-arm-conditional.rs index 0d155ae085..b62f2b2a8e 100644 --- a/src/test/run-pass/cleanup-arm-conditional.rs +++ b/src/test/run-pass/cleanup-arm-conditional.rs @@ -21,20 +21,22 @@ // Test that cleanup scope for temporaries created in a match // arm is confined to the match arm itself. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, os)] use std::os; -struct Test { x: int } +struct Test { x: isize } impl Test { - fn get_x(&self) -> Option> { + fn get_x(&self) -> Option> { Some(box self.x) } } -fn do_something(t: &Test) -> int { +fn do_something(t: &Test) -> isize { // The cleanup scope for the result of `t.get_x()` should be the // arm itself and not the match, otherwise we'll (potentially) get @@ -52,4 +54,3 @@ pub fn main() { let t = Test { x: 1 }; do_something(&t); } - diff --git a/src/test/run-pass/cleanup-rvalue-during-if-and-while.rs b/src/test/run-pass/cleanup-rvalue-during-if-and-while.rs index 83f93cb81a..1d0030fd3d 100644 --- a/src/test/run-pass/cleanup-rvalue-during-if-and-while.rs +++ b/src/test/run-pass/cleanup-rvalue-during-if-and-while.rs @@ -12,12 +12,14 @@ // This test verifies that temporaries created for `while`'s and `if` // conditions are dropped after the condition is evaluated. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct Temporary; -static mut DROPPED: int = 0; +static mut DROPPED: isize = 0; impl Drop for Temporary { fn drop(&mut self) { diff --git a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs index 96ae7e3d33..3b5421e5af 100644 --- a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs +++ b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -24,6 +24,8 @@ // It's unclear how likely such a bug is to recur, but it seems like a // scenario worth testing. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -33,17 +35,17 @@ enum Conzabble { Bickwick(Foo) } -struct Foo { field: Box } +struct Foo { field: Box } -fn do_it(x: &[uint]) -> Foo { +fn do_it(x: &[usize]) -> Foo { panic!() } -fn get_bar(x: uint) -> Vec { vec!(x * 2) } +fn get_bar(x: usize) -> Vec { vec!(x * 2) } pub fn fails() { let x = 2; - let mut y = Vec::new(); + let mut y: Vec> = Vec::new(); y.push(box Conzabble::Bickwick(do_it(&get_bar(x)))); } diff --git a/src/test/run-pass/cleanup-shortcircuit.rs b/src/test/run-pass/cleanup-shortcircuit.rs index 59f63a79c3..0cfe739018 100644 --- a/src/test/run-pass/cleanup-shortcircuit.rs +++ b/src/test/run-pass/cleanup-shortcircuit.rs @@ -20,6 +20,8 @@ // Test that cleanups for the RHS of shortcircuiting operators work. +// pretty-expanded FIXME #23616 + use std::env; pub fn main() { @@ -33,7 +35,6 @@ pub fn main() { if args.len() >= 2 && args[1] == "signal" { // Raise a segfault. - unsafe { *(0 as *mut int) = 0; } + unsafe { *(0 as *mut isize) = 0; } } } - diff --git a/src/test/run-pass/clone-with-exterior.rs b/src/test/run-pass/clone-with-exterior.rs index 8eeae7a28a..16efceb9d7 100644 --- a/src/test/run-pass/clone-with-exterior.rs +++ b/src/test/run-pass/clone-with-exterior.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, std_misc)] -use std::thread::Thread; +use std::thread; struct Pair { - a: int, - b: int + a: isize, + b: isize } pub fn main() { - let z = box Pair { a : 10, b : 12}; + let z: Box<_> = box Pair { a : 10, b : 12}; - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { assert_eq!(z.a, 10); assert_eq!(z.b, 12); }); diff --git a/src/test/run-pass/closure-bounds-can-capture-chan.rs b/src/test/run-pass/closure-bounds-can-capture-chan.rs index 816b28c3a9..dbbac8a163 100644 --- a/src/test/run-pass/closure-bounds-can-capture-chan.rs +++ b/src/test/run-pass/closure-bounds-can-capture-chan.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::sync::mpsc::channel; diff --git a/src/test/run-pass/closure-inference.rs b/src/test/run-pass/closure-inference.rs index 3bd0273216..06b6e1b5ab 100644 --- a/src/test/run-pass/closure-inference.rs +++ b/src/test/run-pass/closure-inference.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(i: isize) -> isize { i + 1 } fn apply(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) } diff --git a/src/test/run-pass/closure-inference2.rs b/src/test/run-pass/closure-inference2.rs index fa16ea0014..328a27b3f1 100644 --- a/src/test/run-pass/closure-inference2.rs +++ b/src/test/run-pass/closure-inference2.rs @@ -10,6 +10,8 @@ // Test a rather underspecified example: +// pretty-expanded FIXME #23616 + pub fn main() { let f = {|i| i}; assert_eq!(f(2), 2); diff --git a/src/test/run-pass/closure-reform.rs b/src/test/run-pass/closure-reform.rs index a4495c3c68..fefab45714 100644 --- a/src/test/run-pass/closure-reform.rs +++ b/src/test/run-pass/closure-reform.rs @@ -11,7 +11,7 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -#![feature(unboxed_closures)] +#![feature(unboxed_closures, old_io)] use std::mem; use std::old_io::stdio::println; @@ -66,4 +66,3 @@ pub fn main() { call_bare_again(println); } - diff --git a/src/test/run-pass/cmp-default.rs b/src/test/run-pass/cmp-default.rs index fd040d1091..2b7557c7bc 100644 --- a/src/test/run-pass/cmp-default.rs +++ b/src/test/run-pass/cmp-default.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cmp::Ordering; // Test default methods in PartialOrd and PartialEq @@ -22,7 +24,7 @@ impl PartialEq for Fool { } } -struct Int(int); +struct Int(isize); impl PartialEq for Int { fn eq(&self, other: &Int) -> bool { @@ -40,7 +42,7 @@ impl PartialOrd for Int { } } -struct RevInt(int); +struct RevInt(isize); impl PartialEq for RevInt { fn eq(&self, other: &RevInt) -> bool { diff --git a/src/test/run-pass/coerce-expect-unsized.rs b/src/test/run-pass/coerce-expect-unsized.rs index ee19d9e69b..6926879856 100644 --- a/src/test/run-pass/coerce-expect-unsized.rs +++ b/src/test/run-pass/coerce-expect-unsized.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -17,25 +19,34 @@ use std::fmt::Debug; // rvalue expressions to be unsized. See #20169 for more information. pub fn main() { - let _: Box<[int]> = box { [1, 2, 3] }; - let _: Box<[int]> = box if true { [1, 2, 3] } else { [1, 3, 4] }; - let _: Box<[int]> = box match true { true => [1, 2, 3], false => [1, 3, 4] }; - let _: Box _> = box { |x| (x as u8) }; - let _: Box = box if true { false } else { true }; - let _: Box = box match true { true => 'a', false => 'b' }; - - let _: &[int] = &{ [1, 2, 3] }; - let _: &[int] = &if true { [1, 2, 3] } else { [1, 3, 4] }; - let _: &[int] = &match true { true => [1, 2, 3], false => [1, 3, 4] }; - let _: &Fn(int) -> _ = &{ |x| (x as u8) }; + // FIXME #22405: We cannot infer the type `Box<[isize; k]>` for + // the r-value expression from the context `Box<[isize]>`, and + // therefore the `box EXPR` desugaring breaks down. + // + // One could reasonably claim that the `box EXPR` desugaring is + // effectively regressing half of Issue #20169. Hopefully we will + // eventually fix that, at which point the `Box::new` calls below + // should be replaced wth uses of `box`. + + let _: Box<[isize]> = Box::new({ [1, 2, 3] }); + let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] }); + let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] }); + let _: Box _> = Box::new({ |x| (x as u8) }); + let _: Box = Box::new(if true { false } else { true }); + let _: Box = Box::new(match true { true => 'a', false => 'b' }); + + let _: &[isize] = &{ [1, 2, 3] }; + let _: &[isize] = &if true { [1, 2, 3] } else { [1, 3, 4] }; + let _: &[isize] = &match true { true => [1, 2, 3], false => [1, 3, 4] }; + let _: &Fn(isize) -> _ = &{ |x| (x as u8) }; let _: &Debug = &if true { false } else { true }; let _: &Debug = &match true { true => 'a', false => 'b' }; - let _: Box<[int]> = Box::new([1, 2, 3]); - let _: Box _> = Box::new(|x| (x as u8)); + let _: Box<[isize]> = Box::new([1, 2, 3]); + let _: Box _> = Box::new(|x| (x as u8)); - let _: Vec _>> = vec![ + let _: Vec _>> = vec![ Box::new(|x| (x as u8)), - box |x| (x as i16 as u8), + Box::new(|x| (x as i16 as u8)), ]; } diff --git a/src/test/run-pass/coerce-match-calls.rs b/src/test/run-pass/coerce-match-calls.rs index 34c9875f1d..c2f6b4c4ac 100644 --- a/src/test/run-pass/coerce-match-calls.rs +++ b/src/test/run-pass/coerce-match-calls.rs @@ -10,12 +10,14 @@ // Check that coercions are propagated through match and if expressions. +// pretty-expanded FIXME #23616 + use std::boxed::Box; pub fn main() { - let _: Box<[int]> = if true { Box::new([1, 2, 3]) } else { Box::new([1]) }; + let _: Box<[isize]> = if true { Box::new([1, 2, 3]) } else { Box::new([1]) }; - let _: Box<[int]> = match true { true => Box::new([1, 2, 3]), false => Box::new([1]) }; + let _: Box<[isize]> = match true { true => Box::new([1, 2, 3]), false => Box::new([1]) }; // Check we don't get over-keen at propagating coercions in the case of casts. let x = if true { 42 } else { 42u8 } as u16; diff --git a/src/test/run-pass/coerce-match.rs b/src/test/run-pass/coerce-match.rs index 098a08b078..6bf5c4d596 100644 --- a/src/test/run-pass/coerce-match.rs +++ b/src/test/run-pass/coerce-match.rs @@ -10,13 +10,19 @@ // Check that coercions are propagated through match and if expressions. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let _: Box<[int]> = if true { box [1, 2, 3] } else { box [1] }; + let _: Box<[isize]> = + if true { let b: Box<_> = box [1, 2, 3]; b } else { let b: Box<_> = box [1]; b }; - let _: Box<[int]> = match true { true => box [1, 2, 3], false => box [1] }; + let _: Box<[isize]> = match true { + true => { let b: Box<_> = box [1, 2, 3]; b } + false => { let b: Box<_> = box [1]; b } + }; // Check we don't get over-keen at propagating coercions in the case of casts. let x = if true { 42 } else { 42u8 } as u16; diff --git a/src/test/run-pass/coerce-overloaded-autoderef.rs b/src/test/run-pass/coerce-overloaded-autoderef.rs index ec8d58616d..a053311a04 100644 --- a/src/test/run-pass/coerce-overloaded-autoderef.rs +++ b/src/test/run-pass/coerce-overloaded-autoderef.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::rc::Rc; // Examples from the "deref coercions" RFC, at rust-lang/rfcs#241. diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs index 0bbabcb859..581764d4a3 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-arg.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn negate(x: &int) -> int { +// pretty-expanded FIXME #23616 + +fn negate(x: &isize) -> isize { -*x } -fn negate_mut(y: &mut int) -> int { +fn negate_mut(y: &mut isize) -> isize { negate(y) } -fn negate_imm(y: &int) -> int { +fn negate_imm(y: &isize) -> isize { negate(y) } diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs index 419df84bdf..6000b358ac 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct SpeechMaker { - speeches: uint + speeches: usize } impl SpeechMaker { - pub fn how_many(&self) -> uint { self.speeches } + pub fn how_many(&self) -> usize { self.speeches } } -fn foo(speaker: &SpeechMaker) -> uint { +fn foo(speaker: &SpeechMaker) -> usize { speaker.how_many() + 33 } diff --git a/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs b/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs index b6b30e2fe9..1786d5b54f 100644 --- a/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs +++ b/src/test/run-pass/coerce-reborrow-imm-vec-arg.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn sum(x: &[int]) -> int { +// pretty-expanded FIXME #23616 + +fn sum(x: &[isize]) -> isize { let mut sum = 0; for y in x { sum += *y; } return sum; } -fn sum_mut(y: &mut [int]) -> int { +fn sum_mut(y: &mut [isize]) -> isize { sum(y) } -fn sum_imm(y: &[int]) -> int { +fn sum_imm(y: &[isize]) -> isize { sum(y) } diff --git a/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs index ade18a7125..2e41ff3a56 100644 --- a/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs @@ -9,16 +9,18 @@ // except according to those terms. -fn bar(v: &mut [uint]) -> Vec { +// pretty-expanded FIXME #23616 + +fn bar(v: &mut [usize]) -> Vec { v.to_vec() } -fn bip(v: &[uint]) -> Vec { +fn bip(v: &[usize]) -> Vec { v.to_vec() } pub fn main() { - let mut the_vec = vec!(1_usize, 2, 3, 100); + let mut the_vec = vec!(1, 2, 3, 100); assert_eq!(the_vec.clone(), bar(&mut the_vec)); assert_eq!(the_vec.clone(), bip(&the_vec)); } diff --git a/src/test/run-pass/coerce-reborrow-mut-ptr-arg.rs b/src/test/run-pass/coerce-reborrow-mut-ptr-arg.rs index 4a680027b4..b70146ea2d 100644 --- a/src/test/run-pass/coerce-reborrow-mut-ptr-arg.rs +++ b/src/test/run-pass/coerce-reborrow-mut-ptr-arg.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct SpeechMaker { - speeches: uint + speeches: usize } fn talk(x: &mut SpeechMaker) { diff --git a/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs index 2f866955ff..5f4cc569ac 100644 --- a/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct SpeechMaker { - speeches: uint + speeches: usize } impl SpeechMaker { diff --git a/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs b/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs index f87f2e07c9..803f86e0fb 100644 --- a/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs +++ b/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs @@ -9,11 +9,13 @@ // except according to those terms. -fn reverse(v: &mut [uint]) { +// pretty-expanded FIXME #23616 + +fn reverse(v: &mut [usize]) { v.reverse(); } -fn bar(v: &mut [uint]) { +fn bar(v: &mut [usize]) { reverse(v); reverse(v); reverse(v); @@ -22,5 +24,5 @@ fn bar(v: &mut [uint]) { pub fn main() { let mut the_vec = vec!(1, 2, 3, 100); bar(&mut the_vec); - assert_eq!(the_vec, vec!(100, 3, 2, 1)); + assert_eq!(the_vec, [100, 3, 2, 1]); } diff --git a/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs b/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs index 4f97e6a208..a5fac12735 100644 --- a/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs @@ -9,7 +9,9 @@ // except according to those terms. -fn bar(v: &mut [uint]) { +// pretty-expanded FIXME #23616 + +fn bar(v: &mut [usize]) { v.reverse(); v.reverse(); v.reverse(); @@ -18,5 +20,5 @@ fn bar(v: &mut [uint]) { pub fn main() { let mut the_vec = vec!(1, 2, 3, 100); bar(&mut the_vec); - assert_eq!(the_vec, vec!(100, 3, 2, 1)); + assert_eq!(the_vec, [100, 3, 2, 1]); } diff --git a/src/test/run-pass/coerce-unify-return.rs b/src/test/run-pass/coerce-unify-return.rs index eeba9042f7..2299a03b2a 100644 --- a/src/test/run-pass/coerce-unify-return.rs +++ b/src/test/run-pass/coerce-unify-return.rs @@ -11,6 +11,8 @@ // Check that coercions unify the expected return type of a polymorphic // function call, instead of leaving the type variables as they were. +// pretty-expanded FIXME #23616 + struct Foo; impl Foo { fn foo(self, x: T) -> Option { Some(x) } diff --git a/src/test/run-pass/coherence-bigint-int.rs b/src/test/run-pass/coherence-bigint-int.rs index baf2f57206..9ad4f6b9d7 100644 --- a/src/test/run-pass/coherence-bigint-int.rs +++ b/src/test/run-pass/coherence-bigint-int.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; use lib::Remote1; pub struct BigInt; diff --git a/src/test/run-pass/coherence-bigint-vecint.rs b/src/test/run-pass/coherence-bigint-vecint.rs index cdc5bc1171..ac4b98cfc8 100644 --- a/src/test/run-pass/coherence-bigint-vecint.rs +++ b/src/test/run-pass/coherence-bigint-vecint.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; use lib::Remote1; pub struct BigInt; diff --git a/src/test/run-pass/coherence-blanket.rs b/src/test/run-pass/coherence-blanket.rs index e02117d1ca..32743aafa8 100644 --- a/src/test/run-pass/coherence-blanket.rs +++ b/src/test/run-pass/coherence-blanket.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; use lib::Remote1; pub trait Local { diff --git a/src/test/run-pass/coherence-covered-type-parameter.rs b/src/test/run-pass/coherence-covered-type-parameter.rs index 27f1f2dafb..890470d8ac 100644 --- a/src/test/run-pass/coherence-covered-type-parameter.rs +++ b/src/test/run-pass/coherence-covered-type-parameter.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; use lib::Remote; struct Foo(T); diff --git a/src/test/run-pass/coherence-impl-in-fn.rs b/src/test/run-pass/coherence-impl-in-fn.rs index 6edd7390f0..b0630b5164 100644 --- a/src/test/run-pass/coherence-impl-in-fn.rs +++ b/src/test/run-pass/coherence-impl-in-fn.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - #[derive(Copy)] + #[derive(Copy, Clone)] enum x { foo } impl ::std::cmp::PartialEq for x { fn eq(&self, other: &x) -> bool { - (*self) as int == (*other) as int + (*self) as isize == (*other) as isize } fn ne(&self, other: &x) -> bool { !(*self).eq(other) } } diff --git a/src/test/run-pass/coherence-iterator-vec-any-elem.rs b/src/test/run-pass/coherence-iterator-vec-any-elem.rs index 6dc2ff4588..04a6cd5882 100644 --- a/src/test/run-pass/coherence-iterator-vec-any-elem.rs +++ b/src/test/run-pass/coherence-iterator-vec-any-elem.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; use lib::Remote1; struct Foo(T); diff --git a/src/test/run-pass/coherence-iterator-vec.rs b/src/test/run-pass/coherence-iterator-vec.rs index 7077503f73..8a3301dee2 100644 --- a/src/test/run-pass/coherence-iterator-vec.rs +++ b/src/test/run-pass/coherence-iterator-vec.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// aux-build:coherence_lib.rs -extern crate "coherence-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; use lib::Remote1; struct Foo(T); diff --git a/src/test/run-pass/coherence-multidispatch-tuple.rs b/src/test/run-pass/coherence-multidispatch-tuple.rs index 04a69bbf3a..07477f96c0 100644 --- a/src/test/run-pass/coherence-multidispatch-tuple.rs +++ b/src/test/run-pass/coherence-multidispatch-tuple.rs @@ -8,22 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +// pretty-expanded FIXME #23616 + +use std::fmt::Debug; use std::default::Default; // Test that an impl for homogeneous pairs does not conflict with a // heterogeneous pair. trait MyTrait { - fn get(&self) -> uint; + fn get(&self) -> usize; } impl MyTrait for (T,T) { - fn get(&self) -> uint { 0 } + fn get(&self) -> usize { 0 } } -impl MyTrait for (uint,int) { - fn get(&self) -> uint { 0 } +impl MyTrait for (usize,isize) { + fn get(&self) -> usize { 0 } } fn main() { diff --git a/src/test/run-pass/coherence-negative-impls-safe.rs b/src/test/run-pass/coherence-negative-impls-safe.rs index 7844ef3fac..2f42ab4988 100644 --- a/src/test/run-pass/coherence-negative-impls-safe.rs +++ b/src/test/run-pass/coherence-negative-impls-safe.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(optin_builtin_traits)] use std::marker::Send; diff --git a/src/test/run-pass/coherence-where-clause.rs b/src/test/run-pass/coherence-where-clause.rs index 9f980e161b..8ab340d1bf 100644 --- a/src/test/run-pass/coherence-where-clause.rs +++ b/src/test/run-pass/coherence-where-clause.rs @@ -25,7 +25,7 @@ impl MyTrait for T #[derive(Clone, Copy, Debug, PartialEq)] struct MyType { - dummy: uint + dummy: usize } impl MyTrait for MyType { diff --git a/src/test/run-pass/coherence_copy_like.rs b/src/test/run-pass/coherence_copy_like.rs new file mode 100644 index 0000000000..db9893613a --- /dev/null +++ b/src/test/run-pass/coherence_copy_like.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +use std::marker::MarkerTrait; + +struct MyType { x: i32 } + +trait MyTrait : MarkerTrait { } +impl MyTrait for T { } +impl MyTrait for MyType { } +impl<'a> MyTrait for &'a MyType { } +impl MyTrait for Box { } +impl<'a> MyTrait for &'a Box { } + +fn main() { } diff --git a/src/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs index 841aaa94e9..21ff6d6938 100644 --- a/src/test/run-pass/colorful-write-macros.rs +++ b/src/test/run-pass/colorful-write-macros.rs @@ -8,14 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// no-pretty-expanded - -#![allow(unused_must_use, dead_code, deprecated)] -use std::old_io::MemWriter; +use std::io::Write; use std::fmt; struct Foo<'a> { - writer: &'a mut (Writer+'a), + writer: &'a mut (Write+'a), other: &'a str, } @@ -32,8 +29,8 @@ fn borrowing_writer_from_struct_and_formatting_struct_field(foo: Foo) { } fn main() { - let mut w = MemWriter::new(); - write!(&mut w as &mut Writer, ""); + let mut w = Vec::new(); + write!(&mut w as &mut Write, ""); write!(&mut w, ""); // should coerce println!("ok"); diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs index 16a21adc3f..859599596a 100644 --- a/src/test/run-pass/comm.rs +++ b/src/test/run-pass/comm.rs @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { child(&tx) }); + let _t = thread::scoped(move|| { child(&tx) }); let y = rx.recv().unwrap(); println!("received"); println!("{}", y); assert_eq!(y, 10); } -fn child(c: &Sender) { +fn child(c: &Sender) { println!("sending"); c.send(10).unwrap(); println!("value sent"); diff --git a/src/test/run-pass/compare-generic-enums.rs b/src/test/run-pass/compare-generic-enums.rs index c6f4fecf8a..6994558487 100644 --- a/src/test/run-pass/compare-generic-enums.rs +++ b/src/test/run-pass/compare-generic-enums.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type an_int = int; +// pretty-expanded FIXME #23616 -fn cmp(x: Option, y: Option) -> bool { +type an_int = isize; + +fn cmp(x: Option, y: Option) -> bool { x == y } diff --git a/src/test/run-pass/complex.rs b/src/test/run-pass/complex.rs index f8c8ac20d7..6bb9503c2b 100644 --- a/src/test/run-pass/complex.rs +++ b/src/test/run-pass/complex.rs @@ -11,20 +11,20 @@ -type t = int; +type t = isize; fn nothing() { } fn putstr(_s: String) { } -fn putint(_i: int) { - let mut i: int = 33; +fn putint(_i: isize) { + let mut i: isize = 33; while i < 36 { putstr("hi".to_string()); i = i + 1; } } -fn zerg(i: int) -> int { return i; } +fn zerg(i: isize) -> isize { return i; } -fn foo(x: int) -> int { +fn foo(x: isize) -> isize { let mut y: t = x + 2; putstr("hello".to_string()); while y < 10 { putint(y); if y * 3 == 4 { y = y + 2; nothing(); } } @@ -35,7 +35,7 @@ fn foo(x: int) -> int { } pub fn main() { - let x: int = 2 + 2; + let x: isize = 2 + 2; println!("{}", x); println!("hello, world"); println!("{}", 10); diff --git a/src/test/run-pass/concat.rs b/src/test/run-pass/concat.rs index b0c3a5922b..7441d1f21b 100644 --- a/src/test/run-pass/concat.rs +++ b/src/test/run-pass/concat.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert_eq!(format!(concat!("foo", "bar", "{}"), "baz"), "foobarbaz".to_string()); assert_eq!(format!(concat!()), "".to_string()); @@ -15,12 +17,12 @@ pub fn main() { assert_eq!(concat!("qux", "quux",).to_string(), "quxquux".to_string()); assert_eq!( - concat!(1, 2, 3_usize, 4f32, 4.0, 'a', true), + concat!(1, 2, 3, 4f32, 4.0, 'a', true), "12344.0atrue" ); assert!(match "12344.0atrue" { - concat!(1, 2, 3_usize, 4f32, 4.0, 'a', true) => true, + concat!(1, 2, 3, 4f32, 4.0, 'a', true) => true, _ => false }) } diff --git a/src/test/run-pass/conditional-compile-arch.rs b/src/test/run-pass/conditional-compile-arch.rs index 0e9447bd24..e51270fdc8 100644 --- a/src/test/run-pass/conditional-compile-arch.rs +++ b/src/test/run-pass/conditional-compile-arch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[cfg(target_arch = "x86")] pub fn main() { } diff --git a/src/test/run-pass/conditional-compile.rs b/src/test/run-pass/conditional-compile.rs index 178fc3dcd4..e6660bb9ae 100644 --- a/src/test/run-pass/conditional-compile.rs +++ b/src/test/run-pass/conditional-compile.rs @@ -1,4 +1,3 @@ - // 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. @@ -10,6 +9,8 @@ // except according to those terms. // Crate use statements +// pretty-expanded FIXME #23616 + #[cfg(bogus)] use flippity; @@ -30,7 +31,7 @@ mod rustrt { } #[cfg(bogus)] -type t = int; +type t = isize; type t = bool; @@ -41,21 +42,21 @@ enum tg { bar, } #[cfg(bogus)] struct r { - i: int, + i: isize, } #[cfg(bogus)] -fn r(i:int) -> r { +fn r(i:isize) -> r { r { i: i } } struct r { - i: int, + i: isize, } -fn r(i:int) -> r { +fn r(i:isize) -> r { r { i: i } @@ -99,8 +100,8 @@ fn test_in_fn_ctxt() { f(); #[cfg(bogus)] - static i: int = 0; - static i: int = 1; + static i: isize = 0; + static i: isize = 1; assert_eq!(i, 1); } @@ -121,7 +122,7 @@ mod test_use_statements { mod test_methods { struct Foo { - bar: uint + bar: usize } impl Fooable for Foo { diff --git a/src/test/run-pass/conditional-debug-macro-off.rs b/src/test/run-pass/conditional-debug-macro-off.rs index b5a5f57d07..192e647f5c 100644 --- a/src/test/run-pass/conditional-debug-macro-off.rs +++ b/src/test/run-pass/conditional-debug-macro-off.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --cfg ndebug +// compile-flags: -C debug-assertions=no // exec-env:RUST_LOG=conditional-debug-macro-off=4 +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + #[macro_use] extern crate log; diff --git a/src/test/run-pass/const-autoderef.rs b/src/test/run-pass/const-autoderef.rs index 71312fb387..1349b7f814 100644 --- a/src/test/run-pass/const-autoderef.rs +++ b/src/test/run-pass/const-autoderef.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + static A: [u8; 1] = ['h' as u8]; static B: u8 = (&A)[0]; static C: &'static &'static &'static &'static [u8; 1] = & & & &A; diff --git a/src/test/run-pass/const-big-enum.rs b/src/test/run-pass/const-big-enum.rs index ca1d79e83e..158c695c54 100644 --- a/src/test/run-pass/const-big-enum.rs +++ b/src/test/run-pass/const-big-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { Bar(u32), Baz, diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs index 1268fc4e43..1a95220cda 100644 --- a/src/test/run-pass/const-binops.rs +++ b/src/test/run-pass/const-binops.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ use std::num::Float; @@ -17,40 +19,40 @@ macro_rules! assert_approx_eq { }) } -static A: int = -4 + 3; -static A2: uint = 3 + 3; +static A: isize = -4 + 3; +static A2: usize = 3 + 3; static B: f64 = 3.0 + 2.7; -static C: int = 3 - 4; -static D: uint = 3 - 3; +static C: isize = 3 - 4; +static D: usize = 3 - 3; static E: f64 = 3.0 - 2.7; -static E2: int = -3 * 3; -static F: uint = 3 * 3; +static E2: isize = -3 * 3; +static F: usize = 3 * 3; static G: f64 = 3.3 * 3.3; -static H: int = 3 / -1; -static I: uint = 3 / 3; +static H: isize = 3 / -1; +static I: usize = 3 / 3; static J: f64 = 3.3 / 3.3; static N: bool = true && false; static O: bool = true || false; -static P: int = 3 & 1; -static Q: uint = 1 & 3; +static P: isize = 3 & 1; +static Q: usize = 1 & 3; -static R: int = 3 | 1; -static S: uint = 1 | 3; +static R: isize = 3 | 1; +static S: usize = 1 | 3; -static T: int = 3 ^ 1; -static U: uint = 1 ^ 3; +static T: isize = 3 ^ 1; +static U: usize = 1 ^ 3; -static V: int = 1 << 3; +static V: isize = 1 << 3; // NOTE: better shr coverage -static W: int = 1024 >> 4; -static X: uint = 1024 >> 4; +static W: isize = 1024 >> 4; +static X: usize = 1024 >> 4; static Y: bool = 1 == 1; static Z: bool = 1.0f64 == 1.0; diff --git a/src/test/run-pass/const-block-cross-crate-fn.rs b/src/test/run-pass/const-block-cross-crate-fn.rs index 16360ff08d..853e8dc62b 100644 --- a/src/test/run-pass/const-block-cross-crate-fn.rs +++ b/src/test/run-pass/const-block-cross-crate-fn.rs @@ -10,6 +10,8 @@ // aux-build:cci_const_block.rs +// pretty-expanded FIXME #23616 + extern crate cci_const_block; pub fn main() { diff --git a/src/test/run-pass/const-block-item-macro-codegen.rs b/src/test/run-pass/const-block-item-macro-codegen.rs index 03afe79895..b9e8dbf41d 100644 --- a/src/test/run-pass/const-block-item-macro-codegen.rs +++ b/src/test/run-pass/const-block-item-macro-codegen.rs @@ -11,14 +11,16 @@ // General test that function items in static blocks // can be generated with a macro. +// pretty-expanded FIXME #23616 + struct MyType { desc: &'static str, - data: uint, - code: fn(uint, uint) -> uint + data: usize, + code: fn(usize, usize) -> usize } impl MyType { - fn eval(&self, a: uint) -> uint { + fn eval(&self, a: usize) -> usize { (self.code)(self.data, a) } } @@ -26,7 +28,7 @@ impl MyType { macro_rules! codegen { ($e:expr, $v:expr) => { { - fn generated(a: uint, b: uint) -> uint { + fn generated(a: usize, b: usize) -> usize { a - ($e * b) } MyType { diff --git a/src/test/run-pass/const-block-item.rs b/src/test/run-pass/const-block-item.rs index d55b420db0..897e538226 100644 --- a/src/test/run-pass/const-block-item.rs +++ b/src/test/run-pass/const-block-item.rs @@ -8,37 +8,39 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod foo { pub trait Value { - fn value(&self) -> uint; + fn value(&self) -> usize; } } -static BLOCK_USE: uint = { +static BLOCK_USE: usize = { use foo::Value; 100 }; -static BLOCK_PUB_USE: uint = { +static BLOCK_PUB_USE: usize = { pub use foo::Value; 200 }; -static BLOCK_STRUCT_DEF: uint = { +static BLOCK_STRUCT_DEF: usize = { struct Foo { - a: uint + a: usize } Foo{ a: 300 }.a }; -static BLOCK_FN_DEF: fn(uint) -> uint = { - fn foo(a: uint) -> uint { +static BLOCK_FN_DEF: fn(usize) -> usize = { + fn foo(a: usize) -> usize { a + 10 } foo }; -static BLOCK_MACRO_RULES: uint = { +static BLOCK_MACRO_RULES: usize = { macro_rules! baz { () => (412) } diff --git a/src/test/run-pass/const-block.rs b/src/test/run-pass/const-block.rs index cdb96e5dcb..1337a91fe0 100644 --- a/src/test/run-pass/const-block.rs +++ b/src/test/run-pass/const-block.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] #![allow(unused_unsafe)] @@ -58,6 +60,6 @@ pub fn main() { assert_eq!(BLOCK_FN(300), 300); assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200)); // FIXME #13972 - // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *const isize as usize, 0xdeadbeef_us); - // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *const isize as usize, 0xdeadbeef_us); + // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *const isize as usize, 0xdeadbeef); + // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *const isize as usize, 0xdeadbeef); } diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs index 93a7d3e1c3..5c2985ffa7 100644 --- a/src/test/run-pass/const-bound.rs +++ b/src/test/run-pass/const-bound.rs @@ -11,19 +11,18 @@ // Make sure const bounds work on things, and test that a few types // are const. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 fn foo(x: T) -> T { x } -struct F { field: int } +struct F { field: isize } pub fn main() { /*foo(1); foo("hi".to_string()); foo(~[1, 2, 3]); foo(F{field: 42}); - foo((1, 2_usize)); + foo((1, 2)); foo(@1);*/ - foo(box 1); + foo(Box::new(1)); } diff --git a/src/test/run-pass/const-cast-ptr-int.rs b/src/test/run-pass/const-cast-ptr-int.rs index 50e460bd17..bbe3020ea1 100644 --- a/src/test/run-pass/const-cast-ptr-int.rs +++ b/src/test/run-pass/const-cast-ptr-int.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ptr; struct TestStruct { diff --git a/src/test/run-pass/const-cast.rs b/src/test/run-pass/const-cast.rs index b7e9c0338d..f660dc5fa4 100644 --- a/src/test/run-pass/const-cast.rs +++ b/src/test/run-pass/const-cast.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; struct TestStruct { diff --git a/src/test/run-pass/const-const.rs b/src/test/run-pass/const-const.rs index ba2947f736..d75a5a7eb1 100644 --- a/src/test/run-pass/const-const.rs +++ b/src/test/run-pass/const-const.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const a: int = 1; -const b: int = a + 2; +// pretty-expanded FIXME #23616 + +const a: isize = 1; +const b: isize = a + 2; pub fn main() { assert_eq!(b, 3); diff --git a/src/test/run-pass/const-contents.rs b/src/test/run-pass/const-contents.rs index 616826f9f9..2dfb88dee0 100644 --- a/src/test/run-pass/const-contents.rs +++ b/src/test/run-pass/const-contents.rs @@ -10,12 +10,14 @@ // Issue #570 -static lsl : int = 1 << 2; -static add : int = 1 + 2; +// pretty-expanded FIXME #23616 + +static lsl : isize = 1 << 2; +static add : isize = 1 + 2; static addf : f64 = 1.0 + 2.0; -static not : int = !0; +static not : isize = !0; static notb : bool = !true; -static neg : int = -(1); +static neg : isize = -(1); pub fn main() { assert_eq!(lsl, 4); diff --git a/src/test/run-pass/const-cross-crate-const.rs b/src/test/run-pass/const-cross-crate-const.rs index bcf58431d0..e36a55361e 100644 --- a/src/test/run-pass/const-cross-crate-const.rs +++ b/src/test/run-pass/const-cross-crate-const.rs @@ -10,10 +10,12 @@ // aux-build:cci_const.rs +// pretty-expanded FIXME #23616 + extern crate cci_const; static foo: &'static str = cci_const::foopy; -static a: uint = cci_const::uint_val; -static b: uint = cci_const::uint_expr + 5; +static a: usize = cci_const::uint_val; +static b: usize = cci_const::uint_expr + 5; pub fn main() { assert_eq!(a, 12); diff --git a/src/test/run-pass/const-cross-crate-extern.rs b/src/test/run-pass/const-cross-crate-extern.rs index a299c74aa5..98f42f9124 100644 --- a/src/test/run-pass/const-cross-crate-extern.rs +++ b/src/test/run-pass/const-cross-crate-extern.rs @@ -10,6 +10,8 @@ // aux-build:cci_const.rs +// pretty-expanded FIXME #23616 + extern crate cci_const; use cci_const::bar; static foo: extern "C" fn() = bar; diff --git a/src/test/run-pass/const-deref.rs b/src/test/run-pass/const-deref.rs index 480fb50a1f..1648332fe2 100644 --- a/src/test/run-pass/const-deref.rs +++ b/src/test/run-pass/const-deref.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const C: &'static int = &1000; -static D: int = *C; +// pretty-expanded FIXME #23616 + +const C: &'static isize = &1000; +static D: isize = *C; pub fn main() { assert_eq!(D, 1000); diff --git a/src/test/run-pass/const-enum-byref-self.rs b/src/test/run-pass/const-enum-byref-self.rs index 25145bf363..e99e1aac8a 100644 --- a/src/test/run-pass/const-enum-byref-self.rs +++ b/src/test/run-pass/const-enum-byref-self.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum E { V, VV(int) } +// pretty-expanded FIXME #23616 + +enum E { V, VV(isize) } static C: E = E::V; impl E { diff --git a/src/test/run-pass/const-enum-byref.rs b/src/test/run-pass/const-enum-byref.rs index bc5daf4164..4905eaace6 100644 --- a/src/test/run-pass/const-enum-byref.rs +++ b/src/test/run-pass/const-enum-byref.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum E { V, VV(int) } +// pretty-expanded FIXME #23616 + +enum E { V, VV(isize) } static C: E = E::V; fn f(a: &E) { diff --git a/src/test/run-pass/const-enum-cast.rs b/src/test/run-pass/const-enum-cast.rs index 966effab33..3d73933c6f 100644 --- a/src/test/run-pass/const-enum-cast.rs +++ b/src/test/run-pass/const-enum-cast.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum A { A1, A2 } enum B { B1=0, B2=2 } pub fn main () { - static c1: int = A::A2 as int; - static c2: int = B::B2 as int; - let a1 = A::A2 as int; - let a2 = B::B2 as int; + static c1: isize = A::A2 as isize; + static c2: isize = B::B2 as isize; + let a1 = A::A2 as isize; + let a2 = B::B2 as isize; assert_eq!(c1, 1); assert_eq!(c2, 2); assert_eq!(a1, 1); diff --git a/src/test/run-pass/const-enum-ptr.rs b/src/test/run-pass/const-enum-ptr.rs index 0953f35e44..d34b5381df 100644 --- a/src/test/run-pass/const-enum-ptr.rs +++ b/src/test/run-pass/const-enum-ptr.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum E { V0, V1(int) } +// pretty-expanded FIXME #23616 + +enum E { V0, V1(isize) } static C: &'static E = &E::V0; pub fn main() { diff --git a/src/test/run-pass/const-enum-struct.rs b/src/test/run-pass/const-enum-struct.rs index 0c3656e193..71a9703ec3 100644 --- a/src/test/run-pass/const-enum-struct.rs +++ b/src/test/run-pass/const-enum-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { V16(u16), V32(u32) } struct S { a: E, b: u16, c: u16 } static C: S = S { a: E::V16(0xDEAD), b: 0x600D, c: 0xBAD }; diff --git a/src/test/run-pass/const-enum-struct2.rs b/src/test/run-pass/const-enum-struct2.rs index 6996da8bc3..ca56cb5b01 100644 --- a/src/test/run-pass/const-enum-struct2.rs +++ b/src/test/run-pass/const-enum-struct2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { V0, V16(u16) } struct S { a: E, b: u16, c: u16 } static C: S = S { a: E::V0, b: 0x600D, c: 0xBAD }; diff --git a/src/test/run-pass/const-enum-structlike.rs b/src/test/run-pass/const-enum-structlike.rs index ac48752b0a..113f20e21e 100644 --- a/src/test/run-pass/const-enum-structlike.rs +++ b/src/test/run-pass/const-enum-structlike.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { S0 { s: String }, - S1 { u: uint } + S1 { u: usize } } static C: E = E::S1 { u: 23 }; diff --git a/src/test/run-pass/const-enum-tuple.rs b/src/test/run-pass/const-enum-tuple.rs index 7ea5a3fed7..2ab28f5fb2 100644 --- a/src/test/run-pass/const-enum-tuple.rs +++ b/src/test/run-pass/const-enum-tuple.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { V16(u16), V32(u32) } static C: (E, u16, u16) = (E::V16(0xDEAD), 0x600D, 0xBAD); diff --git a/src/test/run-pass/const-enum-tuple2.rs b/src/test/run-pass/const-enum-tuple2.rs index 968c45a329..fe1b2e051c 100644 --- a/src/test/run-pass/const-enum-tuple2.rs +++ b/src/test/run-pass/const-enum-tuple2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { V0, V16(u16) } static C: (E, u16, u16) = (E::V0, 0x600D, 0xBAD); diff --git a/src/test/run-pass/const-enum-tuplestruct.rs b/src/test/run-pass/const-enum-tuplestruct.rs index 697321e0c7..7f9de49404 100644 --- a/src/test/run-pass/const-enum-tuplestruct.rs +++ b/src/test/run-pass/const-enum-tuplestruct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { V16(u16), V32(u32) } struct S(E, u16, u16); static C: S = S(E::V16(0xDEAD), 0x600D, 0xBAD); diff --git a/src/test/run-pass/const-enum-tuplestruct2.rs b/src/test/run-pass/const-enum-tuplestruct2.rs index 254580c4e6..3d7b6c9f49 100644 --- a/src/test/run-pass/const-enum-tuplestruct2.rs +++ b/src/test/run-pass/const-enum-tuplestruct2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { V0, V16(u16) } struct S(E, u16, u16); static C: S = S(E::V0, 0x600D, 0xBAD); diff --git a/src/test/run-pass/const-enum-vec-index.rs b/src/test/run-pass/const-enum-vec-index.rs index 4c8124d28a..fcaf8b8844 100644 --- a/src/test/run-pass/const-enum-vec-index.rs +++ b/src/test/run-pass/const-enum-vec-index.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum E { V1(int), V0 } +// pretty-expanded FIXME #23616 + +enum E { V1(isize), V0 } const C: &'static [E] = &[E::V0, E::V1(0xDEADBEE)]; static C0: E = C[0]; static C1: E = C[1]; diff --git a/src/test/run-pass/const-enum-vec-ptr.rs b/src/test/run-pass/const-enum-vec-ptr.rs index d5c299fd86..936d72ac65 100644 --- a/src/test/run-pass/const-enum-vec-ptr.rs +++ b/src/test/run-pass/const-enum-vec-ptr.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum E { V1(int), V0 } +// pretty-expanded FIXME #23616 + +enum E { V1(isize), V0 } static C: &'static [E] = &[E::V0, E::V1(0xDEADBEE), E::V0]; pub fn main() { diff --git a/src/test/run-pass/const-enum-vector.rs b/src/test/run-pass/const-enum-vector.rs index 6eb5c2dab3..6fdf0c3948 100644 --- a/src/test/run-pass/const-enum-vector.rs +++ b/src/test/run-pass/const-enum-vector.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum E { V1(int), V0 } +// pretty-expanded FIXME #23616 + +enum E { V1(isize), V0 } static C: [E; 3] = [E::V0, E::V1(0xDEADBEE), E::V0]; pub fn main() { diff --git a/src/test/run-pass/const-expr-in-fixed-length-vec.rs b/src/test/run-pass/const-expr-in-fixed-length-vec.rs index 6317c2eec1..6cf9239e2e 100644 --- a/src/test/run-pass/const-expr-in-fixed-length-vec.rs +++ b/src/test/run-pass/const-expr-in-fixed-length-vec.rs @@ -11,9 +11,11 @@ // Check that constant expressions can be used for declaring the // type of a fixed length vector. +// pretty-expanded FIXME #23616 + pub fn main() { - const FOO: uint = 2; - let _v: [int; FOO*3]; + const FOO: usize = 2; + let _v: [isize; FOO*3]; } diff --git a/src/test/run-pass/const-expr-in-vec-repeat.rs b/src/test/run-pass/const-expr-in-vec-repeat.rs index 0b097c0b06..fc3e6749f6 100644 --- a/src/test/run-pass/const-expr-in-vec-repeat.rs +++ b/src/test/run-pass/const-expr-in-vec-repeat.rs @@ -10,9 +10,11 @@ // Check that constant expressions can be used in vec repeat syntax. +// pretty-expanded FIXME #23616 + pub fn main() { - const FOO: uint = 2; + const FOO: usize = 2; let _v = [0; FOO*3*2/2]; } diff --git a/src/test/run-pass/const-extern-function.rs b/src/test/run-pass/const-extern-function.rs index 069ca6ecf4..ff829711a4 100644 --- a/src/test/run-pass/const-extern-function.rs +++ b/src/test/run-pass/const-extern-function.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern fn foopy() {} static f: extern "C" fn() = foopy; diff --git a/src/test/run-pass/const-fields-and-indexing.rs b/src/test/run-pass/const-fields-and-indexing.rs index 0819e0becb..55d6b60c19 100644 --- a/src/test/run-pass/const-fields-and-indexing.rs +++ b/src/test/run-pass/const-fields-and-indexing.rs @@ -8,21 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const x : [int; 4] = [1,2,3,4]; -static p : int = x[2]; -const y : &'static [int] = &[1,2,3,4]; -static q : int = y[2]; +const x : [isize; 4] = [1,2,3,4]; +static p : isize = x[2]; +const y : &'static [isize] = &[1,2,3,4]; +static q : isize = y[2]; -struct S {a: int, b: int} +struct S {a: isize, b: isize} const s : S = S {a: 10, b: 20}; -static t : int = s.b; +static t : isize = s.b; -struct K {a: int, b: int, c: D} -struct D { d: int, e: int } +struct K {a: isize, b: isize, c: D} +struct D { d: isize, e: isize } const k : K = K {a: 10, b: 20, c: D {d: 30, e: 40}}; -static m : int = k.c.e; +static m : isize = k.c.e; pub fn main() { println!("{}", p); diff --git a/src/test/run-pass/const-fn-val.rs b/src/test/run-pass/const-fn-val.rs index 8394c53cba..3e1058dc27 100644 --- a/src/test/run-pass/const-fn-val.rs +++ b/src/test/run-pass/const-fn-val.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo() -> int { +// pretty-expanded FIXME #23616 + +fn foo() -> isize { return 0xca7f000d; } -struct Bar where F: FnMut() -> int { f: F } +struct Bar where F: FnMut() -> isize { f: F } -static mut b : Bar int> = Bar { f: foo as fn() -> int}; +static mut b : Bar isize> = Bar { f: foo as fn() -> isize}; pub fn main() { unsafe { assert_eq!((b.f)(), 0xca7f000d); } diff --git a/src/test/run-pass/const-negative.rs b/src/test/run-pass/const-negative.rs index 4e2be013c1..59b2c3e36a 100644 --- a/src/test/run-pass/const-negative.rs +++ b/src/test/run-pass/const-negative.rs @@ -10,7 +10,9 @@ // Issue #358 -static toplevel_mod: int = -1; +// pretty-expanded FIXME #23616 + +static toplevel_mod: isize = -1; pub fn main() { assert_eq!(toplevel_mod, -1); diff --git a/src/test/run-pass/const-nullary-enum.rs b/src/test/run-pass/const-nullary-enum.rs index 5397a29311..fcad89470d 100644 --- a/src/test/run-pass/const-nullary-enum.rs +++ b/src/test/run-pass/const-nullary-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { Bar, Baz, diff --git a/src/test/run-pass/const-nullary-univariant-enum.rs b/src/test/run-pass/const-nullary-univariant-enum.rs index 86b194f2eb..51926ececc 100644 --- a/src/test/run-pass/const-nullary-univariant-enum.rs +++ b/src/test/run-pass/const-nullary-univariant-enum.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] enum Foo { Bar = 0xDEADBEE } @@ -16,8 +18,8 @@ enum Foo { static X: Foo = Foo::Bar; pub fn main() { - assert_eq!((X as uint), 0xDEADBEE); - assert_eq!((Y as uint), 0xDEADBEE); + assert_eq!((X as usize), 0xDEADBEE); + assert_eq!((Y as usize), 0xDEADBEE); } static Y: Foo = Foo::Bar; diff --git a/src/test/run-pass/const-region-ptrs-noncopy.rs b/src/test/run-pass/const-region-ptrs-noncopy.rs index e8081005d4..8932853fbf 100644 --- a/src/test/run-pass/const-region-ptrs-noncopy.rs +++ b/src/test/run-pass/const-region-ptrs-noncopy.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + type Big = [u64; 8]; -struct Pair<'a> { a: int, b: &'a Big } +struct Pair<'a> { a: isize, b: &'a Big } const x: &'static Big = &([13, 14, 10, 13, 11, 14, 14, 15]); const y: &'static Pair<'static> = &Pair {a: 15, b: x}; diff --git a/src/test/run-pass/const-region-ptrs.rs b/src/test/run-pass/const-region-ptrs.rs index e5d3f0ece0..c783d4b818 100644 --- a/src/test/run-pass/const-region-ptrs.rs +++ b/src/test/run-pass/const-region-ptrs.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Pair<'a> { a: int, b: &'a int } +struct Pair<'a> { a: isize, b: &'a isize } -const x: &'static int = &10; +const x: &'static isize = &10; const y: &'static Pair<'static> = &Pair {a: 15, b: x}; diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index e846501be6..c5ff134ff0 100644 --- a/src/test/run-pass/const-str-ptr.rs +++ b/src/test/run-pass/const-str-ptr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::{str, string}; const A: [u8; 2] = ['h' as u8, 'i' as u8]; diff --git a/src/test/run-pass/const-struct-offsets.rs b/src/test/run-pass/const-struct-offsets.rs index 98dbf1eaa6..4f38a6431b 100644 --- a/src/test/run-pass/const-struct-offsets.rs +++ b/src/test/run-pass/const-struct-offsets.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { IntVal(i32), Int64Val(i64) diff --git a/src/test/run-pass/const-struct.rs b/src/test/run-pass/const-struct.rs index 27c514160c..3cd58c6c52 100644 --- a/src/test/run-pass/const-struct.rs +++ b/src/test/run-pass/const-struct.rs @@ -11,7 +11,7 @@ use std::cmp; #[derive(Debug)] -struct foo { a: int, b: int, c: int } +struct foo { a: isize, b: isize, c: isize } impl cmp::PartialEq for foo { fn eq(&self, other: &foo) -> bool { diff --git a/src/test/run-pass/const-tuple-struct.rs b/src/test/run-pass/const-tuple-struct.rs index 54116dd408..ccf1b06bac 100644 --- a/src/test/run-pass/const-tuple-struct.rs +++ b/src/test/run-pass/const-tuple-struct.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Bar(int, int); +// pretty-expanded FIXME #23616 + +struct Bar(isize, isize); static X: Bar = Bar(1, 2); diff --git a/src/test/run-pass/const-unit-struct.rs b/src/test/run-pass/const-unit-struct.rs index 7e6d9f0bee..320f41006e 100644 --- a/src/test/run-pass/const-unit-struct.rs +++ b/src/test/run-pass/const-unit-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo; static X: Foo = Foo; diff --git a/src/test/run-pass/const-vec-of-fns.rs b/src/test/run-pass/const-vec-of-fns.rs index 4b07b1d3b0..f16fbac007 100644 --- a/src/test/run-pass/const-vec-of-fns.rs +++ b/src/test/run-pass/const-vec-of-fns.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /*! * Try to double-check that static fns have the right size (with or * without dummy env ptr, as appropriate) by iterating a size-2 array. diff --git a/src/test/run-pass/const-vec-syntax.rs b/src/test/run-pass/const-vec-syntax.rs index c0566277e4..a577bbd827 100644 --- a/src/test/run-pass/const-vec-syntax.rs +++ b/src/test/run-pass/const-vec-syntax.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(_: &[int]) {} +// pretty-expanded FIXME #23616 + +fn f(_: &[isize]) {} pub fn main() { let v = [ 1, 2, 3 ]; diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs index 26874b9f9d..758812054c 100644 --- a/src/test/run-pass/const-vecs-and-slices.rs +++ b/src/test/run-pass/const-vecs-and-slices.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static x : [int; 4] = [1,2,3,4]; -static y : &'static [int] = &[1,2,3,4]; -static z : &'static [int; 4] = &[1,2,3,4]; -static zz : &'static [int] = &[1,2,3,4]; +static x : [isize; 4] = [1,2,3,4]; +static y : &'static [isize] = &[1,2,3,4]; +static z : &'static [isize; 4] = &[1,2,3,4]; +static zz : &'static [isize] = &[1,2,3,4]; pub fn main() { println!("{}", x[1]); diff --git a/src/test/run-pass/const.rs b/src/test/run-pass/const.rs index 8f78d54c70..95ae514636 100644 --- a/src/test/run-pass/const.rs +++ b/src/test/run-pass/const.rs @@ -10,6 +10,6 @@ -static i: int = 10; +static i: isize = 10; pub fn main() { println!("{}", i); } diff --git a/src/test/run-pass/consts-in-patterns.rs b/src/test/run-pass/consts-in-patterns.rs index e8f4948a16..c2f7cf4d62 100644 --- a/src/test/run-pass/consts-in-patterns.rs +++ b/src/test/run-pass/consts-in-patterns.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const FOO: int = 10; -const BAR: int = 3; +// pretty-expanded FIXME #23616 + +const FOO: isize = 10; +const BAR: isize = 3; pub fn main() { - let x: int = 3; + let x: isize = 3; let y = match x { FOO => 1, BAR => 2, diff --git a/src/test/run-pass/copy-out-of-array-1.rs b/src/test/run-pass/copy-out-of-array-1.rs index 2b57c1ea0d..5c5765454d 100644 --- a/src/test/run-pass/copy-out-of-array-1.rs +++ b/src/test/run-pass/copy-out-of-array-1.rs @@ -12,9 +12,10 @@ // // (Compare with compile-fail/move-out-of-array-1.rs) -struct C { _x: u8 } +// pretty-expanded FIXME #23616 -impl Copy for C { } +#[derive(Copy, Clone)] +struct C { _x: u8 } fn main() { fn d() -> C { C { _x: 0 } } diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 88d5b74708..03bf385125 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -16,6 +16,7 @@ // instead of in std. #![reexport_test_harness_main = "test_main"] +#![feature(old_io, libc, std_misc)] extern crate libc; @@ -23,7 +24,7 @@ use std::old_io::{Process, Command, timer}; use std::time::Duration; use std::str; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; macro_rules! succeed { ($e:expr) => ( match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) } @@ -51,7 +52,7 @@ pub fn sleeper() -> Process { fn test_destroy_twice() { let mut p = sleeper(); - succeed!(p.signal_exit()); // this shouldnt crash... + succeed!(p.signal_exit()); // this shouldn't crash... let _ = p.signal_exit(); // ...and nor should this (and nor should the destructor) } @@ -85,7 +86,7 @@ pub fn test_destroy_actually_kills(force: bool) { let (tx, rx1) = channel(); let mut t = timer::Timer::new().unwrap(); let rx2 = t.oneshot(Duration::milliseconds(1000)); - Thread::spawn(move|| { + thread::spawn(move|| { select! { _ = rx2.recv() => unsafe { libc::exit(1) }, _ = rx1.recv() => {} diff --git a/src/test/run-pass/crate-leading-sep.rs b/src/test/run-pass/crate-leading-sep.rs index d8b3371325..ede78ff803 100644 --- a/src/test/run-pass/crate-leading-sep.rs +++ b/src/test/run-pass/crate-leading-sep.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { use ::std::mem; mem::drop(2_usize); diff --git a/src/test/run-pass/crate-method-reexport-grrrrrrr.rs b/src/test/run-pass/crate-method-reexport-grrrrrrr.rs index 1a3e87b55b..43507f0cb0 100644 --- a/src/test/run-pass/crate-method-reexport-grrrrrrr.rs +++ b/src/test/run-pass/crate-method-reexport-grrrrrrr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -22,7 +24,7 @@ extern crate crate_method_reexport_grrrrrrr2; pub fn main() { use crate_method_reexport_grrrrrrr2::rust::add; use crate_method_reexport_grrrrrrr2::rust::cx; - let x = box() (); + let x: Box<_> = box () (); x.cx(); let y = (); y.add("hi".to_string()); diff --git a/src/test/run-pass/crate-name-attr-used.rs b/src/test/run-pass/crate-name-attr-used.rs index f04a760e5f..a108f4dc56 100644 --- a/src/test/run-pass/crate-name-attr-used.rs +++ b/src/test/run-pass/crate-name-attr-used.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--crate-name crate-name-attr-used -F unused-attributes +// compile-flags:--crate-name crate_name_attr_used -F unused-attributes -#![crate_name = "crate-name-attr-used"] +// pretty-expanded FIXME #23616 + +#![crate_name = "crate_name_attr_used"] fn main() {} diff --git a/src/test/run-pass/cross-crate-const-pat.rs b/src/test/run-pass/cross-crate-const-pat.rs index 14be5773e8..a85541bb8b 100644 --- a/src/test/run-pass/cross-crate-const-pat.rs +++ b/src/test/run-pass/cross-crate-const-pat.rs @@ -10,6 +10,8 @@ // aux-build:cci_const.rs +// pretty-expanded FIXME #23616 + extern crate cci_const; pub fn main() { diff --git a/src/test/run-pass/cross-crate-newtype-struct-pat.rs b/src/test/run-pass/cross-crate-newtype-struct-pat.rs index c2083c8e70..986108c5d8 100644 --- a/src/test/run-pass/cross-crate-newtype-struct-pat.rs +++ b/src/test/run-pass/cross-crate-newtype-struct-pat.rs @@ -10,6 +10,8 @@ // aux-build:newtype_struct_xc.rs +// pretty-expanded FIXME #23616 + extern crate newtype_struct_xc; pub fn main() { diff --git a/src/test/run-pass/cycle-generic-bound.rs b/src/test/run-pass/cycle-generic-bound.rs new file mode 100644 index 0000000000..94e4665bb8 --- /dev/null +++ b/src/test/run-pass/cycle-generic-bound.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #15477. This test just needs to compile. + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomFn; + +trait Chromosome> : PhantomFn<(Self,X)> { +} + +fn main() { } diff --git a/src/test/run-pass/cycle-trait-type-trait.rs b/src/test/run-pass/cycle-trait-type-trait.rs new file mode 100644 index 0000000000..50bc9e971f --- /dev/null +++ b/src/test/run-pass/cycle-trait-type-trait.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a case where a supertrait references a type that references +// the original trait. This poses no problem at the moment. + +// pretty-expanded FIXME #23616 + +trait Chromosome: Get> { +} + +trait Get { + fn get(&self) -> A; +} + +struct Struct { c: C } + +fn main() { } diff --git a/src/test/run-pass/dead-code-leading-underscore.rs b/src/test/run-pass/dead-code-leading-underscore.rs index b588ea9cfd..6e3f8a2881 100644 --- a/src/test/run-pass/dead-code-leading-underscore.rs +++ b/src/test/run-pass/dead-code-leading-underscore.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![deny(dead_code)] -static _X: uint = 0; +static _X: usize = 0; fn _foo() {} struct _Y { - _z: uint + _z: usize } enum _Z {} @@ -24,7 +26,7 @@ impl _Y { fn _bar() {} } -type _A = int; +type _A = isize; mod _bar { fn _qux() {} diff --git a/src/test/run-pass/deep.rs b/src/test/run-pass/deep.rs index 2f82e729ad..16636fadbf 100644 --- a/src/test/run-pass/deep.rs +++ b/src/test/run-pass/deep.rs @@ -11,8 +11,10 @@ -fn f(x: int) -> int { - if x == 1 { return 1; } else { let y: int = 1 + f(x - 1); return y; } +// pretty-expanded FIXME #23616 + +fn f(x: isize) -> isize { + if x == 1 { return 1; } else { let y: isize = 1 + f(x - 1); return y; } } pub fn main() { assert!((f(5000) == 5000)); } diff --git a/src/test/run-pass/default-method-parsing.rs b/src/test/run-pass/default-method-parsing.rs index 639ea59585..5ccb66a76b 100644 --- a/src/test/run-pass/default-method-parsing.rs +++ b/src/test/run-pass/default-method-parsing.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { - fn m(&self, _:int) { } + fn m(&self, _:isize) { } } pub fn main() { } diff --git a/src/test/run-pass/default-method-simple.rs b/src/test/run-pass/default-method-simple.rs index 547f342243..61de804a80 100644 --- a/src/test/run-pass/default-method-simple.rs +++ b/src/test/run-pass/default-method-simple.rs @@ -18,7 +18,7 @@ trait Foo { } struct A { - x: int + x: isize } impl Foo for A { diff --git a/src/test/run-pass/default-method-supertrait-vtable.rs b/src/test/run-pass/default-method-supertrait-vtable.rs index 727cada21f..3b1e04be78 100644 --- a/src/test/run-pass/default-method-supertrait-vtable.rs +++ b/src/test/run-pass/default-method-supertrait-vtable.rs @@ -14,24 +14,24 @@ // Tests that we can call a function bounded over a supertrait from // a default method -fn require_y(x: T) -> int { x.y() } +fn require_y(x: T) -> isize { x.y() } trait Y { - fn y(self) -> int; + fn y(self) -> isize; } trait Z: Y + Sized { - fn x(self) -> int { + fn x(self) -> isize { require_y(self) } } -impl Y for int { - fn y(self) -> int { self } +impl Y for isize { + fn y(self) -> isize { self } } -impl Z for int {} +impl Z for isize {} pub fn main() { assert_eq!(12.x(), 12); diff --git a/src/test/run-pass/deprecated-derive.rs b/src/test/run-pass/deprecated-derive.rs new file mode 100644 index 0000000000..494d62c773 --- /dev/null +++ b/src/test/run-pass/deprecated-derive.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Show)] +//~^ WARNING derive(Show) is deprecated +struct Test1; + +fn main() { } diff --git a/src/test/run-pass/deref-lval.rs b/src/test/run-pass/deref-lval.rs index 41c74250b3..fc97b22a4a 100644 --- a/src/test/run-pass/deref-lval.rs +++ b/src/test/run-pass/deref-lval.rs @@ -14,7 +14,7 @@ use std::cell::Cell; pub fn main() { - let x = box Cell::new(5); + let x: Box<_> = box Cell::new(5); x.set(1000); println!("{}", x.get()); } diff --git a/src/test/run-pass/deref-mut-on-ref.rs b/src/test/run-pass/deref-mut-on-ref.rs index f43be17786..8820003d3b 100644 --- a/src/test/run-pass/deref-mut-on-ref.rs +++ b/src/test/run-pass/deref-mut-on-ref.rs @@ -10,14 +10,16 @@ // Test that `&mut T` implements `DerefMut` +// pretty-expanded FIXME #23616 + use std::ops::{Deref, DerefMut}; -fn inc + DerefMut>(mut t: T) { +fn inc + DerefMut>(mut t: T) { *t += 1; } fn main() { - let mut x: int = 5; + let mut x: isize = 5; inc(&mut x); assert_eq!(x, 6); } diff --git a/src/test/run-pass/deref-on-ref.rs b/src/test/run-pass/deref-on-ref.rs index e95d942c8c..84bfbd8229 100644 --- a/src/test/run-pass/deref-on-ref.rs +++ b/src/test/run-pass/deref-on-ref.rs @@ -10,6 +10,8 @@ // Test that `&T` and `&mut T` implement `Deref` +// pretty-expanded FIXME #23616 + use std::ops::Deref; fn deref>(t: T) -> U { @@ -17,11 +19,11 @@ fn deref>(t: T) -> U { } fn main() { - let x: int = 3; + let x: isize = 3; let y = deref(&x); assert_eq!(y, 3); - let mut x: int = 4; + let mut x: isize = 4; let y = deref(&mut x); assert_eq!(y, 4); } diff --git a/src/test/run-pass/deref-rc.rs b/src/test/run-pass/deref-rc.rs index fbb8a3a172..761b29258f 100644 --- a/src/test/run-pass/deref-rc.rs +++ b/src/test/run-pass/deref-rc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::rc::Rc; fn main() { diff --git a/src/test/run-pass/deref.rs b/src/test/run-pass/deref.rs index b4ee0246d8..4722ddd64c 100644 --- a/src/test/run-pass/deref.rs +++ b/src/test/run-pass/deref.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let x: Box = box 10; - let _y: int = *x; + let x: Box = box 10; + let _y: isize = *x; } diff --git a/src/test/run-pass/derive-no-std.rs b/src/test/run-pass/derive-no-std.rs index d3034c2d48..fbc6c28fd4 100644 --- a/src/test/run-pass/derive-no-std.rs +++ b/src/test/run-pass/derive-no-std.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(no_std)] +#![feature(no_std, core, rand, collections, rustc_private)] #![no_std] extern crate core; extern crate rand; -extern crate "serialize" as rustc_serialize; +extern crate serialize as rustc_serialize; extern crate collections; // Issue #16803 diff --git a/src/test/run-pass/deriving-associated-types.rs b/src/test/run-pass/deriving-associated-types.rs new file mode 100644 index 0000000000..59eb5506c4 --- /dev/null +++ b/src/test/run-pass/deriving-associated-types.rs @@ -0,0 +1,210 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core, debug_builders)] + +pub trait DeclaredTrait { + type Type; +} + +impl DeclaredTrait for i32 { + type Type = i32; +} + +pub trait WhereTrait { + type Type; +} + +impl WhereTrait for i32 { + type Type = i32; +} + +// Make sure we don't add a bound that just shares a name with an associated +// type. +pub mod module { + pub type Type = i32; +} + +#[derive(PartialEq, Debug)] +struct PrivateStruct(T); + +#[derive(PartialEq, Debug)] +struct TupleStruct( + module::Type, + Option, + A, + PrivateStruct, + B, + B::Type, + Option, + ::Type, + Option<::Type>, + C, + C::Type, + Option, + ::Type, + Option<::Type>, + ::Type, +) where C: WhereTrait; + +#[derive(PartialEq, Debug)] +pub struct Struct where C: WhereTrait { + m1: module::Type, + m2: Option, + a1: A, + a2: PrivateStruct, + b: B, + b1: B::Type, + b2: Option, + b3: ::Type, + b4: Option<::Type>, + c: C, + c1: C::Type, + c2: Option, + c3: ::Type, + c4: Option<::Type>, + d: ::Type, +} + +#[derive(PartialEq, Debug)] +enum Enum where C: WhereTrait { + Unit, + Seq( + module::Type, + Option, + A, + PrivateStruct, + B, + B::Type, + Option, + ::Type, + Option<::Type>, + C, + C::Type, + Option, + ::Type, + Option<::Type>, + ::Type, + ), + Map { + m1: module::Type, + m2: Option, + a1: A, + a2: PrivateStruct, + b: B, + b1: B::Type, + b2: Option, + b3: ::Type, + b4: Option<::Type>, + c: C, + c1: C::Type, + c2: Option, + c3: ::Type, + c4: Option<::Type>, + d: ::Type, + }, +} + +fn main() { + let e: TupleStruct< + i32, + i32, + i32, + > = TupleStruct( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Struct< + i32, + i32, + i32, + > = Struct { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); + + let e = Enum::Unit::; + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Seq( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Map { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); +} diff --git a/src/test/run-pass/deriving-bounds.rs b/src/test/run-pass/deriving-bounds.rs index 6869a60838..4204d9b5c3 100644 --- a/src/test/run-pass/deriving-bounds.rs +++ b/src/test/run-pass/deriving-bounds.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] struct Test; pub fn main() {} diff --git a/src/test/run-pass/deriving-clone-enum.rs b/src/test/run-pass/deriving-clone-enum.rs index ce34852a91..22daffc486 100644 --- a/src/test/run-pass/deriving-clone-enum.rs +++ b/src/test/run-pass/deriving-clone-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] enum E { A, diff --git a/src/test/run-pass/deriving-clone-generic-enum.rs b/src/test/run-pass/deriving-clone-generic-enum.rs index e174ffae75..8a07bad696 100644 --- a/src/test/run-pass/deriving-clone-generic-enum.rs +++ b/src/test/run-pass/deriving-clone-generic-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] enum E { A(T), @@ -16,5 +18,5 @@ enum E { } pub fn main() { - let _ = E::A::(1).clone(); + let _ = E::A::(1).clone(); } diff --git a/src/test/run-pass/deriving-clone-generic-struct.rs b/src/test/run-pass/deriving-clone-generic-struct.rs index 329c7dab3e..d80f14c369 100644 --- a/src/test/run-pass/deriving-clone-generic-struct.rs +++ b/src/test/run-pass/deriving-clone-generic-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] struct S { foo: (), diff --git a/src/test/run-pass/deriving-clone-generic-tuple-struct.rs b/src/test/run-pass/deriving-clone-generic-tuple-struct.rs index bb07b08859..f2f2ec3de7 100644 --- a/src/test/run-pass/deriving-clone-generic-tuple-struct.rs +++ b/src/test/run-pass/deriving-clone-generic-tuple-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] struct S(T, ()); diff --git a/src/test/run-pass/deriving-clone-struct.rs b/src/test/run-pass/deriving-clone-struct.rs index 51e615b370..8bca834508 100644 --- a/src/test/run-pass/deriving-clone-struct.rs +++ b/src/test/run-pass/deriving-clone-struct.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] struct S { - _int: int, + _int: isize, _i8: i8, _i16: i16, _i32: i32, _i64: i64, - _uint: uint, + _uint: usize, _u8: u8, _u16: u16, _u32: u32, diff --git a/src/test/run-pass/deriving-clone-tuple-struct.rs b/src/test/run-pass/deriving-clone-tuple-struct.rs index e2784c26db..8be029ba2a 100644 --- a/src/test/run-pass/deriving-clone-tuple-struct.rs +++ b/src/test/run-pass/deriving-clone-tuple-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] struct S((), ()); diff --git a/src/test/run-pass/deriving-cmp-generic-enum.rs b/src/test/run-pass/deriving-cmp-generic-enum.rs index b3194d5820..07ad8f706e 100644 --- a/src/test/run-pass/deriving-cmp-generic-enum.rs +++ b/src/test/run-pass/deriving-cmp-generic-enum.rs @@ -10,6 +10,8 @@ // no-pretty-expanded FIXME #15189 +// pretty-expanded FIXME #23616 + #[derive(PartialEq, Eq, PartialOrd, Ord)] enum E { E0, diff --git a/src/test/run-pass/deriving-cmp-generic-struct-enum.rs b/src/test/run-pass/deriving-cmp-generic-struct-enum.rs index 8b54536f3a..5f7d184f19 100644 --- a/src/test/run-pass/deriving-cmp-generic-struct-enum.rs +++ b/src/test/run-pass/deriving-cmp-generic-struct-enum.rs @@ -10,6 +10,8 @@ // no-pretty-expanded FIXME #15189 +// pretty-expanded FIXME #23616 + #[derive(PartialEq, Eq, PartialOrd, Ord)] enum ES { ES1 { x: T }, diff --git a/src/test/run-pass/deriving-cmp-generic-struct.rs b/src/test/run-pass/deriving-cmp-generic-struct.rs index 86887c3411..ea0017380b 100644 --- a/src/test/run-pass/deriving-cmp-generic-struct.rs +++ b/src/test/run-pass/deriving-cmp-generic-struct.rs @@ -10,6 +10,8 @@ // no-pretty-expanded FIXME #15189 +// pretty-expanded FIXME #23616 + #[derive(PartialEq, Eq, PartialOrd, Ord)] struct S { x: T, diff --git a/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs b/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs index c7d7f8ded8..702071676b 100644 --- a/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs +++ b/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs @@ -10,6 +10,8 @@ // no-pretty-expanded FIXME #15189 +// pretty-expanded FIXME #23616 + #[derive(PartialEq, Eq, PartialOrd, Ord)] struct TS(T,T); diff --git a/src/test/run-pass/deriving-cmp-shortcircuit.rs b/src/test/run-pass/deriving-cmp-shortcircuit.rs index bc55b9132c..1669f3fdd3 100644 --- a/src/test/run-pass/deriving-cmp-shortcircuit.rs +++ b/src/test/run-pass/deriving-cmp-shortcircuit.rs @@ -12,6 +12,8 @@ // where possible, by having a type that panics when compared as the // second element, so this passes iff the instances shortcircuit. +// pretty-expanded FIXME #23616 + use std::cmp::Ordering; pub struct FailCmp; @@ -31,7 +33,7 @@ impl Ord for FailCmp { #[derive(PartialEq,PartialOrd,Eq,Ord)] struct ShortCircuit { - x: int, + x: isize, y: FailCmp } diff --git a/src/test/run-pass/deriving-default-box.rs b/src/test/run-pass/deriving-default-box.rs index b00ceb6ed2..574a620ef0 100644 --- a/src/test/run-pass/deriving-default-box.rs +++ b/src/test/run-pass/deriving-default-box.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -20,6 +22,7 @@ struct A { pub fn main() { let a: A = Default::default(); - let b: Box<[_]> = box []; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let b: Box<[_]> = Box::<[bool; 0]>::new([]); assert_eq!(a.foo, b); } diff --git a/src/test/run-pass/deriving-encodable-decodable-box.rs b/src/test/run-pass/deriving-encodable-decodable-box.rs index 838d05cf0d..6ccedb0ad9 100644 --- a/src/test/run-pass/deriving-encodable-decodable-box.rs +++ b/src/test/run-pass/deriving-encodable-decodable-box.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(old_orphan_check)] +#![feature(rustc_private)] extern crate serialize; @@ -23,7 +25,8 @@ struct A { } fn main() { - let obj = A { foo: box [true, false] }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let obj = A { foo: Box::new([true, false]) }; let s = json::encode(&obj).unwrap(); let obj2: A = json::decode(&s).unwrap(); assert!(obj.foo == obj2.foo); diff --git a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs index 7d581927c3..d216062bb2 100644 --- a/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs @@ -11,7 +11,9 @@ // This briefly tests the capability of `Cell` and `RefCell` to implement the // `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]` -#![feature(old_orphan_check)] +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] extern crate serialize; @@ -21,7 +23,7 @@ use serialize::json; #[derive(Encodable, Decodable)] struct A { - baz: int + baz: isize } #[derive(Encodable, Decodable)] diff --git a/src/test/run-pass/deriving-encodable-decodable.rs b/src/test/run-pass/deriving-encodable-decodable.rs index ea43163775..cc6b88c788 100644 --- a/src/test/run-pass/deriving-encodable-decodable.rs +++ b/src/test/run-pass/deriving-encodable-decodable.rs @@ -27,22 +27,22 @@ use serialize::{Encodable, Decodable}; #[derive(Encodable, Decodable, Eq, Rand)] struct A; #[derive(Encodable, Decodable, Eq, Rand)] -struct B(int); +struct B(isize); #[derive(Encodable, Decodable, Eq, Rand)] -struct C(int, int, uint); +struct C(isize, isize, usize); #[derive(Encodable, Decodable, Eq, Rand)] struct D { - a: int, - b: uint, + a: isize, + b: usize, } #[derive(Encodable, Decodable, Eq, Rand)] enum E { E1, - E2(uint), + E2(usize), E3(D), - E4{ x: uint }, + E4{ x: usize }, } #[derive(Encodable, Decodable, Eq, Rand)] @@ -74,6 +74,6 @@ pub fn main() { for _ in 0..20 { roundtrip::(); roundtrip::(); - roundtrip::>(); + roundtrip::>(); } } diff --git a/src/test/run-pass/deriving-enum-single-variant.rs b/src/test/run-pass/deriving-enum-single-variant.rs index 7ce7c5fd41..d45247c593 100644 --- a/src/test/run-pass/deriving-enum-single-variant.rs +++ b/src/test/run-pass/deriving-enum-single-variant.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub type task_id = int; +// pretty-expanded FIXME #23616 + +pub type task_id = isize; #[derive(PartialEq)] pub enum Task { diff --git a/src/test/run-pass/deriving-eq-ord-boxed-slice.rs b/src/test/run-pass/deriving-eq-ord-boxed-slice.rs index 3b89c943ed..03c93d3ab9 100644 --- a/src/test/run-pass/deriving-eq-ord-boxed-slice.rs +++ b/src/test/run-pass/deriving-eq-ord-boxed-slice.rs @@ -8,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] - #[derive(PartialEq, PartialOrd, Eq, Ord)] struct Foo(Box<[u8]>); pub fn main() { - let a = Foo(box [0, 1, 2]); - let b = Foo(box [0, 1, 2]); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let a = Foo(Box::new([0, 1, 2])); + let b = Foo(Box::new([0, 1, 2])); assert!(a == b); println!("{}", a != b); println!("{}", a < b); diff --git a/src/test/run-pass/deriving-global.rs b/src/test/run-pass/deriving-global.rs index 6777cbdab9..105d421b40 100644 --- a/src/test/run-pass/deriving-global.rs +++ b/src/test/run-pass/deriving-global.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check)] +#![feature(rand, rustc_private)] extern crate serialize; extern crate rand; @@ -22,21 +22,21 @@ mod submod { Clone, Debug, Rand, Encodable, Decodable)] - enum A { A1(uint), A2(int) } + enum A { A1(usize), A2(isize) } #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Rand, Encodable, Decodable)] - struct B { x: uint, y: int } + struct B { x: usize, y: isize } #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Rand, Encodable, Decodable)] - struct C(uint, int); + struct C(usize, isize); } diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index 5fe7c8bb94..ce7ba9f25e 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(hash)] + use std::hash::{Hash, SipHasher}; #[derive(Hash)] struct Person { - id: uint, + id: usize, name: String, - phone: uint, + phone: usize, } fn hash(t: &T) -> u64 { diff --git a/src/test/run-pass/deriving-in-fn.rs b/src/test/run-pass/deriving-in-fn.rs index bf2c2b01e6..435d15aab8 100644 --- a/src/test/run-pass/deriving-in-fn.rs +++ b/src/test/run-pass/deriving-in-fn.rs @@ -11,7 +11,7 @@ pub fn main() { #[derive(Debug)] struct Foo { - foo: int, + foo: isize, } let f = Foo { foo: 10 }; diff --git a/src/test/run-pass/deriving-in-macro.rs b/src/test/run-pass/deriving-in-macro.rs index c9b60d22ec..b23075e6d0 100644 --- a/src/test/run-pass/deriving-in-macro.rs +++ b/src/test/run-pass/deriving-in-macro.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! define_vec { () => ( mod foo { diff --git a/src/test/run-pass/deriving-meta-multiple.rs b/src/test/run-pass/deriving-meta-multiple.rs index 62ec2f8e59..a2d22699fc 100644 --- a/src/test/run-pass/deriving-meta-multiple.rs +++ b/src/test/run-pass/deriving-meta-multiple.rs @@ -1,4 +1,3 @@ - // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -9,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::hash::{Hash, SipHasher}; // testing multiple separate deriving attributes @@ -16,8 +17,8 @@ use std::hash::{Hash, SipHasher}; #[derive(Clone)] #[derive(Hash)] struct Foo { - bar: uint, - baz: int + bar: usize, + baz: isize } fn hash(_t: &T) {} diff --git a/src/test/run-pass/deriving-meta.rs b/src/test/run-pass/deriving-meta.rs index 82cf9db323..f1c930828d 100644 --- a/src/test/run-pass/deriving-meta.rs +++ b/src/test/run-pass/deriving-meta.rs @@ -1,4 +1,3 @@ - // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -9,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::hash::{Hash, SipHasher}; #[derive(PartialEq, Clone, Hash)] struct Foo { - bar: uint, - baz: int + bar: usize, + baz: isize } fn hash(_t: &T) {} diff --git a/src/test/run-pass/deriving-primitive.rs b/src/test/run-pass/deriving-primitive.rs index eb3cb30594..4399d741ca 100644 --- a/src/test/run-pass/deriving-primitive.rs +++ b/src/test/run-pass/deriving-primitive.rs @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + use std::num::FromPrimitive; -use std::int; +use std::isize; #[derive(PartialEq, FromPrimitive, Debug)] enum A { - Foo = int::MAX, + Foo = isize::MAX, Bar = 1, Baz = 3, Qux, } pub fn main() { - let x: Option = FromPrimitive::from_int(int::MAX); + let x: Option = FromPrimitive::from_int(isize::MAX); assert_eq!(x, Some(A::Foo)); let x: Option = FromPrimitive::from_int(1); diff --git a/src/test/run-pass/deriving-rand.rs b/src/test/run-pass/deriving-rand.rs index d6e5fedf18..b960c2ddd4 100644 --- a/src/test/run-pass/deriving-rand.rs +++ b/src/test/run-pass/deriving-rand.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(rand)] + use std::rand; #[derive(Rand)] struct A; #[derive(Rand)] -struct B(int, int); +struct B(isize, isize); #[derive(Rand)] struct C { @@ -25,7 +29,7 @@ struct C { #[derive(Rand)] enum D { D0, - D1(uint), + D1(usize), D2 { x: (), y: () } } diff --git a/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs b/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs index 3277435e48..7a0d35f6f4 100644 --- a/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs +++ b/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs @@ -14,7 +14,7 @@ use std::cmp::Ordering::{Less,Equal,Greater}; #[derive(Eq,Ord)] struct A<'a> { - x: &'a int + x: &'a isize } pub fn main() { let (a, b) = (A { x: &1 }, A { x: &2 }); diff --git a/src/test/run-pass/deriving-self-lifetime.rs b/src/test/run-pass/deriving-self-lifetime.rs index 44609b6d65..89771ed13b 100644 --- a/src/test/run-pass/deriving-self-lifetime.rs +++ b/src/test/run-pass/deriving-self-lifetime.rs @@ -12,7 +12,7 @@ #[derive(Eq,Ord)] struct A<'a> { - x: &'a int + x: &'a isize } pub fn main() { diff --git a/src/test/run-pass/deriving-show-2.rs b/src/test/run-pass/deriving-show-2.rs index acd07bc98d..2b7438fd84 100644 --- a/src/test/run-pass/deriving-show-2.rs +++ b/src/test/run-pass/deriving-show-2.rs @@ -15,19 +15,19 @@ enum A {} #[derive(Debug)] enum B { B1, B2, B3 } #[derive(Debug)] -enum C { C1(int), C2(B), C3(String) } +enum C { C1(isize), C2(B), C3(String) } #[derive(Debug)] -enum D { D1{ a: int } } +enum D { D1{ a: isize } } #[derive(Debug)] struct E; #[derive(Debug)] -struct F(int); +struct F(isize); #[derive(Debug)] -struct G(int, int); +struct G(isize, isize); #[derive(Debug)] -struct H { a: int } +struct H { a: isize } #[derive(Debug)] -struct I { a: int, b: int } +struct I { a: isize, b: isize } #[derive(Debug)] struct J(Custom); diff --git a/src/test/run-pass/deriving-show.rs b/src/test/run-pass/deriving-show.rs index 7986b97685..1f30f3eced 100644 --- a/src/test/run-pass/deriving-show.rs +++ b/src/test/run-pass/deriving-show.rs @@ -12,16 +12,16 @@ struct Unit; #[derive(Debug)] -struct Tuple(int, uint); +struct Tuple(isize, usize); #[derive(Debug)] -struct Struct { x: int, y: uint } +struct Struct { x: isize, y: usize } #[derive(Debug)] enum Enum { Nullary, - Variant(int, uint), - StructVariant { x: int, y : uint } + Variant(isize, usize), + StructVariant { x: isize, y : usize } } macro_rules! t { diff --git a/src/test/run-pass/deriving-via-extension-enum.rs b/src/test/run-pass/deriving-via-extension-enum.rs index 9761a87d4a..f43f516219 100644 --- a/src/test/run-pass/deriving-via-extension-enum.rs +++ b/src/test/run-pass/deriving-via-extension-enum.rs @@ -10,7 +10,7 @@ #[derive(PartialEq, Debug)] enum Foo { - Bar(int, int), + Bar(isize, isize), Baz(f64, f64) } diff --git a/src/test/run-pass/deriving-via-extension-hash-enum.rs b/src/test/run-pass/deriving-via-extension-hash-enum.rs index 10bd1b2944..249661f003 100644 --- a/src/test/run-pass/deriving-via-extension-hash-enum.rs +++ b/src/test/run-pass/deriving-via-extension-hash-enum.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Hash)] enum Foo { - Bar(int, char), - Baz(char, int) + Bar(isize, char), + Baz(char, isize) } #[derive(Hash)] diff --git a/src/test/run-pass/deriving-via-extension-hash-struct.rs b/src/test/run-pass/deriving-via-extension-hash-struct.rs index 19809def9a..42f0e45627 100644 --- a/src/test/run-pass/deriving-via-extension-hash-struct.rs +++ b/src/test/run-pass/deriving-via-extension-hash-struct.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Hash)] struct Foo { - x: int, - y: int, - z: int + x: isize, + y: isize, + z: isize } pub fn main() {} diff --git a/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs b/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs index ed92a3baab..5f9d9b6fb2 100644 --- a/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs +++ b/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs @@ -10,7 +10,7 @@ #[derive(PartialEq, Debug)] enum S { - X { x: int, y: int }, + X { x: isize, y: isize }, Y } diff --git a/src/test/run-pass/deriving-via-extension-struct-tuple.rs b/src/test/run-pass/deriving-via-extension-struct-tuple.rs index 9319a4f752..f9e1ea4a62 100644 --- a/src/test/run-pass/deriving-via-extension-struct-tuple.rs +++ b/src/test/run-pass/deriving-via-extension-struct-tuple.rs @@ -9,7 +9,7 @@ // except according to those terms. #[derive(PartialEq, Debug)] -struct Foo(int, int, String); +struct Foo(isize, isize, String); pub fn main() { let a1 = Foo(5, 6, "abc".to_string()); diff --git a/src/test/run-pass/deriving-via-extension-struct.rs b/src/test/run-pass/deriving-via-extension-struct.rs index e32e080cac..624fb4a58e 100644 --- a/src/test/run-pass/deriving-via-extension-struct.rs +++ b/src/test/run-pass/deriving-via-extension-struct.rs @@ -10,9 +10,9 @@ #[derive(PartialEq, Debug)] struct Foo { - x: int, - y: int, - z: int, + x: isize, + y: isize, + z: isize, } pub fn main() { diff --git a/src/test/run-pass/deriving-via-extension-type-params.rs b/src/test/run-pass/deriving-via-extension-type-params.rs index 890b4e6978..4d88dbbca3 100644 --- a/src/test/run-pass/deriving-via-extension-type-params.rs +++ b/src/test/run-pass/deriving-via-extension-type-params.rs @@ -1,4 +1,3 @@ - // 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. @@ -11,9 +10,9 @@ #[derive(PartialEq, Hash, Debug)] struct Foo { - x: int, + x: isize, y: T, - z: int + z: isize } pub fn main() { diff --git a/src/test/run-pass/destructure-array-1.rs b/src/test/run-pass/destructure-array-1.rs index 43271162c1..e2c9608571 100644 --- a/src/test/run-pass/destructure-array-1.rs +++ b/src/test/run-pass/destructure-array-1.rs @@ -11,6 +11,10 @@ // Ensure that we can do a destructuring bind of a fixed-size array, // even when the element type has a destructor. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + struct D { x: u8 } impl Drop for D { fn drop(&mut self) { } } diff --git a/src/test/run-pass/die-macro.rs b/src/test/run-pass/die-macro.rs index 565e33ce01..6a81ebe67b 100644 --- a/src/test/run-pass/die-macro.rs +++ b/src/test/run-pass/die-macro.rs @@ -10,12 +10,14 @@ // Just testing that panic!() type checks in statement or expr +// pretty-expanded FIXME #23616 + #![allow(unreachable_code)] fn f() { panic!(); - let _x: int = panic!(); + let _x: isize = panic!(); } pub fn main() { diff --git a/src/test/run-pass/discrim-explicit-23030.rs b/src/test/run-pass/discrim-explicit-23030.rs new file mode 100644 index 0000000000..aed7b1527c --- /dev/null +++ b/src/test/run-pass/discrim-explicit-23030.rs @@ -0,0 +1,156 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 23030: Workaround overflowing discriminant +// with explicit assignments. + +// See also compile-fail/overflow-discrim.rs, which shows what +// happens if you leave the OhNo explicit cases out here. + +use std::{i8,u8,i16,u16,i32,u32,i64,u64,isize,usize}; + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = i8::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i8; + assert_eq!(z, 0); +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = u8::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = i16::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i16; + assert_eq!(z, 0); +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = u16::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = i32::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i32; + assert_eq!(z, 0); +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = u32::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = i64::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i64; + assert_eq!(z, 0); +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = u64::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_isize() { + #[repr(isize)] + enum A { + Ok = isize::MAX - 1, + Ok2, + OhNo = isize::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as isize; + assert_eq!(z, 0); +} + +fn f_usize() { + #[repr(usize)] + enum A { + Ok = usize::MAX - 1, + Ok2, + OhNo = usize::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn main() { + f_i8(); f_u8(); + f_i16(); f_u16(); + f_i32(); f_u32(); + f_i64(); f_u64(); + + f_isize(); f_usize(); +} diff --git a/src/test/run-pass/div-mod.rs b/src/test/run-pass/div-mod.rs index 331cd36a69..237cfe19dc 100644 --- a/src/test/run-pass/div-mod.rs +++ b/src/test/run-pass/div-mod.rs @@ -11,9 +11,11 @@ +// pretty-expanded FIXME #23616 + pub fn main() { - let x: int = 15; - let y: int = 5; + let x: isize = 15; + let y: isize = 5; assert_eq!(x / 5, 3); assert_eq!(x / 4, 3); assert_eq!(x / 3, 5); diff --git a/src/test/run-pass/double-ref.rs b/src/test/run-pass/double-ref.rs index 8018f681f3..13ce6a07e3 100644 --- a/src/test/run-pass/double-ref.rs +++ b/src/test/run-pass/double-ref.rs @@ -8,24 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn check_expr() { - let _: & uint = &1_usize; - let _: & & uint = &&1_usize; - let _: & & & uint = &&&1_usize; - let _: & & & uint = & &&1_usize; - let _: & & & & uint = &&&&1_usize; - let _: & & & & uint = & &&&1_usize; - let _: & & & & & uint = &&&&&1_usize; + let _: & usize = &1; + let _: & & usize = &&1; + let _: & & & usize = &&&1; + let _: & & & usize = & &&1; + let _: & & & & usize = &&&&1; + let _: & & & & usize = & &&&1; + let _: & & & & & usize = &&&&&1; } fn check_ty() { - let _: &uint = & 1_usize; - let _: &&uint = & & 1_usize; - let _: &&&uint = & & & 1_usize; - let _: & &&uint = & & & 1_usize; - let _: &&&&uint = & & & & 1_usize; - let _: & &&&uint = & & & & 1_usize; - let _: &&&&&uint = & & & & & 1_usize; + let _: &usize = & 1; + let _: &&usize = & & 1; + let _: &&&usize = & & & 1; + let _: & &&usize = & & & 1; + let _: &&&&usize = & & & & 1; + let _: & &&&usize = & & & & 1; + let _: &&&&&usize = & & & & & 1; } fn check_pat() { diff --git a/src/test/run-pass/drop-flag-sanity-check.rs b/src/test/run-pass/drop-flag-sanity-check.rs new file mode 100644 index 0000000000..02f6cc70fd --- /dev/null +++ b/src/test/run-pass/drop-flag-sanity-check.rs @@ -0,0 +1,69 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z force-dropflag-checks=on + +// Quick-and-dirty test to ensure -Z force-dropflag-checks=on works as +// expected. Note that the inlined drop-flag is slated for removal +// (RFC 320); when that happens, the -Z flag and this test should +// simply be removed. +// +// See also drop-flag-skip-sanity-check.rs. + +#![feature(old_io)] + +use std::env; +use std::old_io::process::{Command, ExitSignal, ExitStatus}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "test" { + return test(); + } + + let mut p = Command::new(&args[0]).arg("test").spawn().unwrap(); + // The invocation should fail due to the drop-flag sanity check. + assert!(!p.wait().unwrap().success()); +} + +#[derive(Debug)] +struct Corrupted { + x: u8 +} + +impl Drop for Corrupted { + fn drop(&mut self) { println!("dropping"); } +} + +fn test() { + { + let mut c1 = Corrupted { x: 1 }; + let mut c2 = Corrupted { x: 2 }; + unsafe { + let p1 = &mut c1 as *mut Corrupted as *mut u8; + let p2 = &mut c2 as *mut Corrupted as *mut u8; + for i in 0..std::mem::size_of::() { + // corrupt everything, *including the drop flag. + // + // (We corrupt via two different means to safeguard + // against the hypothetical assignment of the + // dtor_needed/dtor_done values to v and v+k. that + // happen to match with one of the corruption values + // below.) + *p1.offset(i as isize) += 2; + *p2.offset(i as isize) += 3; + } + } + // Here, at the end of the scope of `c1` and `c2`, the + // drop-glue should detect the corruption of (at least one of) + // the drop-flags. + } + println!("We should never get here."); +} diff --git a/src/test/run-pass/drop-flag-skip-sanity-check.rs b/src/test/run-pass/drop-flag-skip-sanity-check.rs new file mode 100644 index 0000000000..7066b4017a --- /dev/null +++ b/src/test/run-pass/drop-flag-skip-sanity-check.rs @@ -0,0 +1,69 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z force-dropflag-checks=off + +// Quick-and-dirty test to ensure -Z force-dropflag-checks=off works as +// expected. Note that the inlined drop-flag is slated for removal +// (RFC 320); when that happens, the -Z flag and this test should +// simply be removed. +// +// See also drop-flag-sanity-check.rs. + +#![feature(old_io)] + +use std::env; +use std::old_io::process::{Command, ExitSignal, ExitStatus}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "test" { + return test(); + } + + let mut p = Command::new(&args[0]).arg("test").spawn().unwrap(); + // Invocatinn should succeed as drop-flag sanity check is skipped. + assert!(p.wait().unwrap().success()); +} + +#[derive(Debug)] +struct Corrupted { + x: u8 +} + +impl Drop for Corrupted { + fn drop(&mut self) { println!("dropping"); } +} + +fn test() { + { + let mut c1 = Corrupted { x: 1 }; + let mut c2 = Corrupted { x: 2 }; + unsafe { + let p1 = &mut c1 as *mut Corrupted as *mut u8; + let p2 = &mut c2 as *mut Corrupted as *mut u8; + for i in 0..std::mem::size_of::() { + // corrupt everything, *including the drop flag. + // + // (We corrupt via two different means to safeguard + // against the hypothetical assignment of the + // dtor_needed/dtor_done values to v and v+k. that + // happen to match with one of the corruption values + // below.) + *p1.offset(i as isize) += 2; + *p2.offset(i as isize) += 3; + } + } + // Here, at the end of the scope of `c1` and `c2`, the + // drop-glue should detect the corruption of (at least one of) + // the drop-flags. + } + println!("We should never get here."); +} diff --git a/src/test/run-pass/drop-on-empty-block-exit.rs b/src/test/run-pass/drop-on-empty-block-exit.rs index f875d0644a..268de8ec55 100644 --- a/src/test/run-pass/drop-on-empty-block-exit.rs +++ b/src/test/run-pass/drop-on-empty-block-exit.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -enum t { foo(Box), } +enum t { foo(Box), } pub fn main() { let tt = t::foo(box 10); diff --git a/src/test/run-pass/drop-on-ret.rs b/src/test/run-pass/drop-on-ret.rs index 0786974e11..fc517fa592 100644 --- a/src/test/run-pass/drop-on-ret.rs +++ b/src/test/run-pass/drop-on-ret.rs @@ -11,7 +11,9 @@ -fn f() -> int { +// pretty-expanded FIXME #23616 + +fn f() -> isize { if true { let _s: String = "should not leak".to_string(); return 1; diff --git a/src/test/run-pass/drop-struct-as-object.rs b/src/test/run-pass/drop-struct-as-object.rs index 7a3b6df539..efb98160a3 100644 --- a/src/test/run-pass/drop-struct-as-object.rs +++ b/src/test/run-pass/drop-struct-as-object.rs @@ -11,21 +11,23 @@ // Test that destructor on a struct runs successfully after the struct // is boxed and converted to an object. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -static mut value: uint = 0; +static mut value: usize = 0; struct Cat { - name : uint, + name : usize, } trait Dummy { - fn get(&self) -> uint; + fn get(&self) -> usize; } impl Dummy for Cat { - fn get(&self) -> uint { self.name } + fn get(&self) -> usize { self.name } } impl Drop for Cat { diff --git a/src/test/run-pass/drop-trait-enum.rs b/src/test/run-pass/drop-trait-enum.rs index f94da9fc74..ce675547a6 100644 --- a/src/test/run-pass/drop-trait-enum.rs +++ b/src/test/run-pass/drop-trait-enum.rs @@ -32,7 +32,7 @@ impl Drop for SendOnDrop { enum Foo { SimpleVariant(Sender), - NestedVariant(Box, SendOnDrop, Sender), + NestedVariant(Box, SendOnDrop, Sender), FailingVariant { on_drop: SendOnDrop } } @@ -62,7 +62,7 @@ pub fn main() { let (sender, receiver) = channel(); { - let v = Foo::NestedVariant(box 42_usize, SendOnDrop { sender: sender.clone() }, sender); + let v = Foo::NestedVariant(box 42, SendOnDrop { sender: sender.clone() }, sender); } assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); assert_eq!(receiver.recv().unwrap(), Message::Dropped); @@ -79,10 +79,10 @@ pub fn main() { let (sender, receiver) = channel(); let t = { thread::spawn(move|| { - let mut v = Foo::NestedVariant(box 42usize, SendOnDrop { + let mut v = Foo::NestedVariant(box 42, SendOnDrop { sender: sender.clone() }, sender.clone()); - v = Foo::NestedVariant(box 42_usize, + v = Foo::NestedVariant(box 42, SendOnDrop { sender: sender.clone() }, sender.clone()); v = Foo::SimpleVariant(sender.clone()); diff --git a/src/test/run-pass/drop-trait.rs b/src/test/run-pass/drop-trait.rs index 8cbfee6c78..21740eb393 100644 --- a/src/test/run-pass/drop-trait.rs +++ b/src/test/run-pass/drop-trait.rs @@ -9,7 +9,7 @@ // except according to those terms. struct Foo { - x: int + x: isize } impl Drop for Foo { diff --git a/src/test/run-pass/drop-uninhabited-enum.rs b/src/test/run-pass/drop-uninhabited-enum.rs index f8c54fbab8..9fa085b670 100644 --- a/src/test/run-pass/drop-uninhabited-enum.rs +++ b/src/test/run-pass/drop-uninhabited-enum.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { } impl Drop for Foo { diff --git a/src/test/run-pass/drop-with-type-ascription-1.rs b/src/test/run-pass/drop-with-type-ascription-1.rs index f9fcf8ced2..ea9edff494 100644 --- a/src/test/run-pass/drop-with-type-ascription-1.rs +++ b/src/test/run-pass/drop-with-type-ascription-1.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(str_words)] + fn main() { let foo = "hello".to_string(); let foo: Vec<&str> = foo.words().collect(); let invalid_string = &foo[0]; assert_eq!(*invalid_string, "hello"); } - diff --git a/src/test/run-pass/drop-with-type-ascription-2.rs b/src/test/run-pass/drop-with-type-ascription-2.rs index f3d79f0c7d..3d4af80e30 100644 --- a/src/test/run-pass/drop-with-type-ascription-2.rs +++ b/src/test/run-pass/drop-with-type-ascription-2.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + fn main() { let args = vec!("foobie", "asdf::asdf"); - let arr: Vec<&str> = args[1].split_str("::").collect(); + let arr: Vec<&str> = args[1].split("::").collect(); assert_eq!(arr[0], "asdf"); assert_eq!(arr[0], "asdf"); } - diff --git a/src/test/run-pass/dropck_tarena_sound_drop.rs b/src/test/run-pass/dropck_tarena_sound_drop.rs index ad71f72586..df29b8e10c 100644 --- a/src/test/run-pass/dropck_tarena_sound_drop.rs +++ b/src/test/run-pass/dropck_tarena_sound_drop.rs @@ -16,8 +16,10 @@ // shows a similar setup, but restricts `f` so that the struct `C<'a>` // is force-fed a lifetime equal to that of the borrowed arena. +// pretty-expanded FIXME #23616 + #![allow(unstable)] -#![feature(unsafe_destructor)] +#![feature(unsafe_destructor, rustc_private)] extern crate arena; diff --git a/src/test/run-pass/dst-coercions.rs b/src/test/run-pass/dst-coercions.rs index 30ed0b8e40..6b5bd6ad35 100644 --- a/src/test/run-pass/dst-coercions.rs +++ b/src/test/run-pass/dst-coercions.rs @@ -10,6 +10,8 @@ // Test coercions involving DST and/or raw pointers +// pretty-expanded FIXME #23616 + struct S; trait T { fn dummy(&self) { } } impl T for S {} diff --git a/src/test/run-pass/dst-deref-mut.rs b/src/test/run-pass/dst-deref-mut.rs index 909f7f4897..3b2b7493fd 100644 --- a/src/test/run-pass/dst-deref-mut.rs +++ b/src/test/run-pass/dst-deref-mut.rs @@ -10,37 +10,37 @@ // Test that a custom deref with a fat pointer return type does not ICE -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 use std::ops::{Deref, DerefMut}; pub struct Arr { - ptr: Box<[uint]> + ptr: Box<[usize]> } impl Deref for Arr { - type Target = [uint]; + type Target = [usize]; - fn deref(&self) -> &[uint] { + fn deref(&self) -> &[usize] { panic!(); } } impl DerefMut for Arr { - fn deref_mut(&mut self) -> &mut [uint] { + fn deref_mut(&mut self) -> &mut [usize] { &mut *self.ptr } } pub fn foo(arr: &mut Arr) { - let x: &mut [uint] = &mut **arr; + let x: &mut [usize] = &mut **arr; assert!(x[0] == 1); assert!(x[1] == 2); assert!(x[2] == 3); } fn main() { - let mut a = Arr { ptr: box [1, 2, 3] }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let mut a = Arr { ptr: Box::new([1, 2, 3]) }; foo(&mut a); } diff --git a/src/test/run-pass/dst-deref.rs b/src/test/run-pass/dst-deref.rs index ad4456b5b5..c8e658beef 100644 --- a/src/test/run-pass/dst-deref.rs +++ b/src/test/run-pass/dst-deref.rs @@ -10,32 +10,32 @@ // Test that a custom deref with a fat pointer return type does not ICE -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 use std::ops::Deref; pub struct Arr { - ptr: Box<[uint]> + ptr: Box<[usize]> } impl Deref for Arr { - type Target = [uint]; + type Target = [usize]; - fn deref(&self) -> &[uint] { + fn deref(&self) -> &[usize] { &*self.ptr } } pub fn foo(arr: &Arr) { assert!(arr.len() == 3); - let x: &[uint] = &**arr; + let x: &[usize] = &**arr; assert!(x[0] == 1); assert!(x[1] == 2); assert!(x[2] == 3); } fn main() { - let a = Arr { ptr: box [1, 2, 3] }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let a = Arr { ptr: Box::new([1, 2, 3]) }; foo(&a); } diff --git a/src/test/run-pass/dst-index.rs b/src/test/run-pass/dst-index.rs index 0c7ecfceff..df4cd74740 100644 --- a/src/test/run-pass/dst-index.rs +++ b/src/test/run-pass/dst-index.rs @@ -11,26 +11,30 @@ // Test that overloaded index expressions with DST result types // work and don't ICE. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::ops::Index; use std::fmt::Debug; struct S; -impl Index for S { +impl Index for S { type Output = str; - fn index<'a>(&'a self, _: &uint) -> &'a str { + fn index<'a>(&'a self, _: usize) -> &'a str { "hello" } } struct T; -impl Index for T { +impl Index for T { type Output = Debug + 'static; - fn index<'a>(&'a self, idx: &uint) -> &'a (Debug + 'static) { - static X: uint = 42; + fn index<'a>(&'a self, idx: usize) -> &'a (Debug + 'static) { + static X: usize = 42; &X as &(Debug + 'static) } } diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs index 226025cd80..5e0e5bd03f 100644 --- a/src/test/run-pass/dst-raw.rs +++ b/src/test/run-pass/dst-raw.rs @@ -10,15 +10,17 @@ // Test DST raw pointers +// pretty-expanded FIXME #23616 + trait Trait { - fn foo(&self) -> int; + fn foo(&self) -> isize; } struct A { - f: int + f: isize } impl Trait for A { - fn foo(&self) -> int { + fn foo(&self) -> isize { self.f } } @@ -54,7 +56,7 @@ pub fn main() { } // raw slice with explicit cast - let a = &[1, 2, 3] as *const [_]; + let a = &[1, 2, 3] as *const [i32]; unsafe { let b = (*a)[2]; assert!(b == 3); @@ -94,7 +96,7 @@ pub fn main() { assert!(len == 3); } - let a = &mut [1, 2, 3] as *mut [_]; + let a = &mut [1, 2, 3] as *mut [i32]; unsafe { let b = (*a)[2]; assert!(b == 3); diff --git a/src/test/run-pass/dst-struct-sole.rs b/src/test/run-pass/dst-struct-sole.rs index 74f4b9e923..9bf286c434 100644 --- a/src/test/run-pass/dst-struct-sole.rs +++ b/src/test/run-pass/dst-struct-sole.rs @@ -10,12 +10,14 @@ // As dst-struct.rs, but the unsized field is the only field in the struct. +// pretty-expanded FIXME #23616 + struct Fat { ptr: T } // x is a fat pointer -fn foo(x: &Fat<[int]>) { +fn foo(x: &Fat<[isize]>) { let y = &x.ptr; assert!(x.ptr.len() == 3); assert!(y[0] == 1); @@ -30,7 +32,7 @@ fn foo2(x: &Fat<[T]>) { assert!(x.ptr[1].to_bar() == bar); } -#[derive(Copy, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq)] struct Bar; trait ToBar { @@ -49,11 +51,11 @@ pub fn main() { foo(&f1); let f2 = &f1; foo(f2); - let f3: &Fat<[int]> = f2; + let f3: &Fat<[isize]> = f2; foo(f3); - let f4: &Fat<[int]> = &f1; + let f4: &Fat<[isize]> = &f1; foo(f4); - let f5: &Fat<[int]> = &Fat { ptr: [1, 2, 3] }; + let f5: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] }; foo(f5); // With a vec of Bars. @@ -70,14 +72,14 @@ pub fn main() { foo2(f5); // Assignment. - let f5: &mut Fat<[int]> = &mut Fat { ptr: [1, 2, 3] }; + let f5: &mut Fat<[isize]> = &mut Fat { ptr: [1, 2, 3] }; f5.ptr[1] = 34; assert!(f5.ptr[0] == 1); assert!(f5.ptr[1] == 34); assert!(f5.ptr[2] == 3); // Zero size vec. - let f5: &Fat<[int]> = &Fat { ptr: [] }; + let f5: &Fat<[isize]> = &Fat { ptr: [] }; assert!(f5.ptr.len() == 0); let f5: &Fat<[Bar]> = &Fat { ptr: [] }; assert!(f5.ptr.len() == 0); diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs index ee5193adbc..5198dd43d6 100644 --- a/src/test/run-pass/dst-struct.rs +++ b/src/test/run-pass/dst-struct.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct Fat { - f1: int, + f1: isize, f2: &'static str, ptr: T } // x is a fat pointer -fn foo(x: &Fat<[int]>) { +fn foo(x: &Fat<[isize]>) { let y = &x.ptr; assert!(x.ptr.len() == 3); assert!(y[0] == 1); @@ -37,7 +39,7 @@ fn foo2(x: &Fat<[T]>) { assert!(x.f2 == "some str"); } -fn foo3(x: &Fat>) { +fn foo3(x: &Fat>) { let y = &x.ptr.ptr; assert!(x.f1 == 5); assert!(x.f2 == "some str"); @@ -49,7 +51,7 @@ fn foo3(x: &Fat>) { } -#[derive(Copy, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq)] struct Bar; trait ToBar { @@ -68,11 +70,11 @@ pub fn main() { foo(&f1); let f2 = &f1; foo(f2); - let f3: &Fat<[int]> = f2; + let f3: &Fat<[isize]> = f2; foo(f3); - let f4: &Fat<[int]> = &f1; + let f4: &Fat<[isize]> = &f1; foo(f4); - let f5: &Fat<[int]> = &Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; foo(f5); // With a vec of Bars. @@ -89,14 +91,14 @@ pub fn main() { foo2(f5); // Assignment. - let f5: &mut Fat<[int]> = &mut Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + let f5: &mut Fat<[isize]> = &mut Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; f5.ptr[1] = 34; assert!(f5.ptr[0] == 1); assert!(f5.ptr[1] == 34); assert!(f5.ptr[2] == 3); // Zero size vec. - let f5: &Fat<[int]> = &Fat { f1: 5, f2: "some str", ptr: [] }; + let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [] }; assert!(f5.ptr.len() == 0); let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [] }; assert!(f5.ptr.len() == 0); @@ -106,25 +108,28 @@ pub fn main() { foo3(&f1); let f2 = &f1; foo3(f2); - let f3: &Fat> = f2; + let f3: &Fat> = f2; foo3(f3); - let f4: &Fat> = &f1; + let f4: &Fat> = &f1; foo3(f4); - let f5: &Fat> = + let f5: &Fat> = &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} }; foo3(f5); // Box. - let f1 = box [1, 2, 3]; + let f1 = Box::new([1, 2, 3]); assert!((*f1)[1] == 2); - let f2: Box<[int]> = f1; + let f2: Box<[isize]> = f1; assert!((*f2)[1] == 2); // Nested Box. - let f1 : Box> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + let f1 : Box> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; foo(&*f1); - let f2 : Box> = f1; + let f2 : Box> = f1; foo(&*f2); - let f3 : Box> = box Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let f3 : Box> = + Box::>::new(Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }); foo(&*f3); } diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs index fd1c7247e3..370bc28822 100644 --- a/src/test/run-pass/dst-trait.rs +++ b/src/test/run-pass/dst-trait.rs @@ -8,33 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct Fat { - f1: int, + f1: isize, f2: &'static str, ptr: T } -#[derive(Copy, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq)] struct Bar; -#[derive(Copy, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq)] struct Bar1 { - f: int + f: isize } trait ToBar { fn to_bar(&self) -> Bar; - fn to_val(&self) -> int; + fn to_val(&self) -> isize; } impl ToBar for Bar { fn to_bar(&self) -> Bar { *self } - fn to_val(&self) -> int { + fn to_val(&self) -> isize { 0 } } @@ -42,7 +44,7 @@ impl ToBar for Bar1 { fn to_bar(&self) -> Bar { Bar } - fn to_val(&self) -> int { + fn to_val(&self) -> isize { self.f } } @@ -95,7 +97,9 @@ pub fn main() { assert!(f6.ptr.to_bar() == Bar); // &* - let f7: Box = box Bar1 {f :42}; + // + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let f7: Box = Box::new(Bar1 {f :42}); bar(&*f7); // Deep nesting diff --git a/src/test/run-pass/dupe-first-attr.rc b/src/test/run-pass/dupe-first-attr.rc index 30d6b934fa..d95f1506a9 100644 --- a/src/test/run-pass/dupe-first-attr.rc +++ b/src/test/run-pass/dupe-first-attr.rc @@ -11,6 +11,8 @@ // Regression test for a problem with the first mod attribute // being applied to every mod +// pretty-expanded FIXME #23616 + #[cfg(target_os = "linux")] mod hello; @@ -26,6 +28,9 @@ mod hello; #[cfg(target_os = "dragonfly")] mod hello; +#[cfg(target_os = "bitrig")] +mod hello; + #[cfg(target_os = "android")] mod hello; diff --git a/src/test/run-pass/duplicated-external-mods.rs b/src/test/run-pass/duplicated-external-mods.rs index 65e2b178ab..91c9887300 100644 --- a/src/test/run-pass/duplicated-external-mods.rs +++ b/src/test/run-pass/duplicated-external-mods.rs @@ -10,7 +10,8 @@ // aux-build:anon-extern-mod-cross-crate-1.rs // aux-build:anon-extern-mod-cross-crate-1.rs +// pretty-expanded FIXME #23616 + extern crate anonexternmod; pub fn main() { } - diff --git a/src/test/run-pass/early-ret-binop-add.rs b/src/test/run-pass/early-ret-binop-add.rs index 97e873e9af..7bd292e66f 100644 --- a/src/test/run-pass/early-ret-binop-add.rs +++ b/src/test/run-pass/early-ret-binop-add.rs @@ -8,5 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn wsucc(n: int) -> int { 0 + { return n + 1 } } +// pretty-expanded FIXME #23616 + +use std::num::Int; + +fn wsucc(n: T) -> T { n + { return n } } + pub fn main() { } diff --git a/src/test/run-pass/early-vtbl-resolution.rs b/src/test/run-pass/early-vtbl-resolution.rs index 89fee7358a..2d2cf6fbf0 100644 --- a/src/test/run-pass/early-vtbl-resolution.rs +++ b/src/test/run-pass/early-vtbl-resolution.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait thing { fn foo(&self) -> Option; } -impl thing for int { +impl thing for isize { fn foo(&self) -> Option { None } } fn foo_func>(x: B) -> Option { x.foo() } -struct A { a: int } +struct A { a: isize } pub fn main() { let _x: Option = foo_func(0); diff --git a/src/test/run-pass/else-if.rs b/src/test/run-pass/else-if.rs index 476d3f42d6..79c2f45067 100644 --- a/src/test/run-pass/else-if.rs +++ b/src/test/run-pass/else-if.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + pub fn main() { if 1 == 2 { assert!((false)); diff --git a/src/test/run-pass/empty-allocation-non-null.rs b/src/test/run-pass/empty-allocation-non-null.rs index 269e0ee6ce..cec528fa04 100644 --- a/src/test/run-pass/empty-allocation-non-null.rs +++ b/src/test/run-pass/empty-allocation-non-null.rs @@ -8,18 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + +// pretty-expanded FIXME #23616 pub fn main() { - assert!(Some(box() ()).is_some()); + assert!(Some(Box::new(())).is_some()); - let xs: Box<[()]> = box []; + let xs: Box<[()]> = Box::<[(); 0]>::new([]); assert!(Some(xs).is_some()); struct Foo; - assert!(Some(box Foo).is_some()); + assert!(Some(Box::new(Foo)).is_some()); - let ys: Box<[Foo]> = box []; + let ys: Box<[Foo]> = Box::<[Foo; 0]>::new([]); assert!(Some(ys).is_some()); } diff --git a/src/test/run-pass/empty-allocation-rvalue-non-null.rs b/src/test/run-pass/empty-allocation-rvalue-non-null.rs index e95d58c706..f52a21a997 100644 --- a/src/test/run-pass/empty-allocation-rvalue-non-null.rs +++ b/src/test/run-pass/empty-allocation-rvalue-non-null.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 pub fn main() { - let x = *box() (); + let x = *Box::new(()); } diff --git a/src/test/run-pass/empty-mutable-vec.rs b/src/test/run-pass/empty-mutable-vec.rs index 42a1e56328..757579faa1 100644 --- a/src/test/run-pass/empty-mutable-vec.rs +++ b/src/test/run-pass/empty-mutable-vec.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_mut)] -pub fn main() { let mut _v: Vec = Vec::new(); } +pub fn main() { let mut _v: Vec = Vec::new(); } diff --git a/src/test/run-pass/empty-tag.rs b/src/test/run-pass/empty-tag.rs index 95af729e5e..e60cd02ce9 100644 --- a/src/test/run-pass/empty-tag.rs +++ b/src/test/run-pass/empty-tag.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum chan { chan_t, } impl PartialEq for chan { fn eq(&self, other: &chan) -> bool { - ((*self) as uint) == ((*other) as uint) + ((*self) as usize) == ((*other) as usize) } fn ne(&self, other: &chan) -> bool { !(*self).eq(other) } } diff --git a/src/test/run-pass/enum-alignment.rs b/src/test/run-pass/enum-alignment.rs index 27560986e0..df779d0d71 100644 --- a/src/test/run-pass/enum-alignment.rs +++ b/src/test/run-pass/enum-alignment.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; -fn addr_of(ptr: &T) -> uint { - ptr as *const T as uint +fn addr_of(ptr: &T) -> usize { + ptr as *const T as usize } fn is_aligned(ptr: &T) -> bool { unsafe { - let addr: uint = mem::transmute(ptr); + let addr: usize = mem::transmute(ptr); (addr % mem::min_align_of::()) == 0 } } diff --git a/src/test/run-pass/enum-clike-ffi-as-int.rs b/src/test/run-pass/enum-clike-ffi-as-int.rs index 1cbcaac379..f129a51534 100644 --- a/src/test/run-pass/enum-clike-ffi-as-int.rs +++ b/src/test/run-pass/enum-clike-ffi-as-int.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /*! * C-like enums have to be represented as LLVM ints, not wrapped in a * struct, because it's important for the FFI that they interoperate @@ -29,11 +31,11 @@ enum Foo { } #[inline(never)] -extern "C" fn foo(_x: uint) -> Foo { Foo::B } +extern "C" fn foo(_x: usize) -> Foo { Foo::B } pub fn main() { unsafe { - let f: extern "C" fn(uint) -> u32 = ::std::mem::transmute(foo); + let f: extern "C" fn(usize) -> u32 = ::std::mem::transmute(foo); assert_eq!(f(0xDEADBEEF), Foo::B as u32); } } diff --git a/src/test/run-pass/enum-discr.rs b/src/test/run-pass/enum-discr.rs index 97997bec26..5c01d544cf 100644 --- a/src/test/run-pass/enum-discr.rs +++ b/src/test/run-pass/enum-discr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Animal { Cat = 0, Dog = 1, @@ -25,6 +27,6 @@ enum Hero { pub fn main() { let pet: Animal = Animal::Snake; let hero: Hero = Hero::Superman; - assert!(pet as uint == 3); - assert!(hero as int == -2); + assert!(pet as usize == 3); + assert!(hero as isize == -2); } diff --git a/src/test/run-pass/enum-discrim-autosizing.rs b/src/test/run-pass/enum-discrim-autosizing.rs index ef34115739..239f9821b9 100644 --- a/src/test/run-pass/enum-discrim-autosizing.rs +++ b/src/test/run-pass/enum-discrim-autosizing.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::size_of; enum Ei8 { diff --git a/src/test/run-pass/enum-discrim-manual-sizing.rs b/src/test/run-pass/enum-discrim-manual-sizing.rs index 16eaac082a..b23cfa9f32 100644 --- a/src/test/run-pass/enum-discrim-manual-sizing.rs +++ b/src/test/run-pass/enum-discrim-manual-sizing.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::size_of; #[repr(i8)] @@ -58,13 +60,13 @@ enum Eu64 { Bu64 = 1 } -#[repr(int)] +#[repr(isize)] enum Eint { Aint = 0, Bint = 1 } -#[repr(uint)] +#[repr(usize)] enum Euint { Auint = 0, Buint = 1 @@ -79,6 +81,6 @@ pub fn main() { assert_eq!(size_of::(), 4); assert_eq!(size_of::(), 8); assert_eq!(size_of::(), 8); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); } diff --git a/src/test/run-pass/enum-discrim-range-overflow.rs b/src/test/run-pass/enum-discrim-range-overflow.rs index b45040f6a1..f1306b3f08 100644 --- a/src/test/run-pass/enum-discrim-range-overflow.rs +++ b/src/test/run-pass/enum-discrim-range-overflow.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub enum E64 { H64 = 0x7FFF_FFFF_FFFF_FFFF, L64 = 0x8000_0000_0000_0000 diff --git a/src/test/run-pass/enum-discrim-width-stuff.rs b/src/test/run-pass/enum-discrim-width-stuff.rs index 0242e53aa8..46238c4572 100644 --- a/src/test/run-pass/enum-discrim-width-stuff.rs +++ b/src/test/run-pass/enum-discrim-width-stuff.rs @@ -12,7 +12,7 @@ macro_rules! check { ($m:ident, $t:ty, $v:expr) => {{ mod $m { use std::mem::size_of; - #[derive(Copy, Debug)] + #[derive(Copy, Clone, Debug)] enum E { V = $v, A = 0 diff --git a/src/test/run-pass/enum-disr-val-pretty.rs b/src/test/run-pass/enum-disr-val-pretty.rs index a4bd361f18..9a2f45d007 100644 --- a/src/test/run-pass/enum-disr-val-pretty.rs +++ b/src/test/run-pass/enum-disr-val-pretty.rs @@ -10,6 +10,8 @@ // pp-exact +// pretty-expanded FIXME #23616 + enum color { red = 1, green, blue, imaginary = -1, } pub fn main() { @@ -19,6 +21,6 @@ pub fn main() { test_color(color::imaginary, -1, "imaginary".to_string()); } -fn test_color(color: color, val: int, _name: String) { - assert!(color as int == val); +fn test_color(color: color, val: isize, _name: String) { + assert!(color as isize == val); } diff --git a/src/test/run-pass/enum-export-inheritance.rs b/src/test/run-pass/enum-export-inheritance.rs index 6330d6196a..4cf8fff237 100644 --- a/src/test/run-pass/enum-export-inheritance.rs +++ b/src/test/run-pass/enum-export-inheritance.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod a { pub enum Foo { Bar, diff --git a/src/test/run-pass/enum-null-pointer-opt.rs b/src/test/run-pass/enum-null-pointer-opt.rs index 023376ce47..9fc799a97f 100644 --- a/src/test/run-pass/enum-null-pointer-opt.rs +++ b/src/test/run-pass/enum-null-pointer-opt.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] extern crate core; @@ -20,13 +23,13 @@ trait Trait { fn dummy(&self) { } } fn main() { // Functions - assert_eq!(size_of::(), size_of::>()); - assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::(), size_of::>()); // Slices - &str / &[T] / &mut [T] assert_eq!(size_of::<&str>(), size_of::>()); - assert_eq!(size_of::<&[int]>(), size_of::>()); - assert_eq!(size_of::<&mut [int]>(), size_of::>()); + assert_eq!(size_of::<&[isize]>(), size_of::>()); + assert_eq!(size_of::<&mut [isize]>(), size_of::>()); // Traits - Box / &Trait / &mut Trait assert_eq!(size_of::>(), size_of::>>()); @@ -34,33 +37,33 @@ fn main() { assert_eq!(size_of::<&mut Trait>(), size_of::>()); // Pointers - Box - assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); // The optimization can't apply to raw pointers - assert!(size_of::>() != size_of::<*const int>()); - assert!(Some(0 as *const int).is_some()); // Can't collapse None to null + assert!(size_of::>() != size_of::<*const isize>()); + assert!(Some(0 as *const isize).is_some()); // Can't collapse None to null struct Foo { - _a: Box + _a: Box } - struct Bar(Box); + struct Bar(Box); // Should apply through structs assert_eq!(size_of::(), size_of::>()); assert_eq!(size_of::(), size_of::>()); // and tuples - assert_eq!(size_of::<(u8, Box)>(), size_of::)>>()); + assert_eq!(size_of::<(u8, Box)>(), size_of::)>>()); // and fixed-size arrays - assert_eq!(size_of::<[Box; 1]>(), size_of::; 1]>>()); + assert_eq!(size_of::<[Box; 1]>(), size_of::; 1]>>()); // Should apply to NonZero - assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); assert_eq!(size_of::>(), size_of::>>()); // Should apply to types that use NonZero internally - assert_eq!(size_of::>(), size_of::>>()); - assert_eq!(size_of::>(), size_of::>>()); - assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); // Should apply to types that have NonZero transitively assert_eq!(size_of::(), size_of::>()); diff --git a/src/test/run-pass/enum-nullable-const-null-with-fields.rs b/src/test/run-pass/enum-nullable-const-null-with-fields.rs index 4b839d740f..3a7c7ea9a7 100644 --- a/src/test/run-pass/enum-nullable-const-null-with-fields.rs +++ b/src/test/run-pass/enum-nullable-const-null-with-fields.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::result::Result; use std::result::Result::Ok; -static C: Result<(), Box> = Ok(()); +static C: Result<(), Box> = Ok(()); // This is because of yet another bad assertion (ICE) about the null side of a nullable enum. // So we won't actually compile if the bug is present, but we check the value in main anyway. diff --git a/src/test/run-pass/enum-nullable-simplifycfg-misopt.rs b/src/test/run-pass/enum-nullable-simplifycfg-misopt.rs index 468e5f5f4b..99554aafb0 100644 --- a/src/test/run-pass/enum-nullable-simplifycfg-misopt.rs +++ b/src/test/run-pass/enum-nullable-simplifycfg-misopt.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/enum-size-variance.rs b/src/test/run-pass/enum-size-variance.rs index 39ab831695..0bf5df5d61 100644 --- a/src/test/run-pass/enum-size-variance.rs +++ b/src/test/run-pass/enum-size-variance.rs @@ -17,26 +17,26 @@ enum Enum1 { } enum Enum2 { A, B, C } -enum Enum3 { D(int), E, F } +enum Enum3 { D(isize), E, F } -enum Enum4 { H(int), I(int), J } +enum Enum4 { H(isize), I(isize), J } enum Enum5 { //~ ERROR three times larger - L(int, int, int, int), //~ NOTE this variant is the largest - M(int), + L(isize, isize, isize, isize), //~ NOTE this variant is the largest + M(isize), N } enum Enum6 { O(T), P(U), - Q(int) + Q(isize) } #[allow(enum_size_variance)] enum Enum7 { - R(int, int, int, int), - S(int), + R(isize, isize, isize, isize), + S(isize), T } pub fn main() { } diff --git a/src/test/run-pass/enum-variants.rs b/src/test/run-pass/enum-variants.rs index 4a3a115669..77e6141d55 100644 --- a/src/test/run-pass/enum-variants.rs +++ b/src/test/run-pass/enum-variants.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] diff --git a/src/test/run-pass/enum-vec-initializer.rs b/src/test/run-pass/enum-vec-initializer.rs index 86a998100b..037ee5f777 100644 --- a/src/test/run-pass/enum-vec-initializer.rs +++ b/src/test/run-pass/enum-vec-initializer.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Flopsy { Bunny = 2 } -const BAR:uint = Flopsy::Bunny as uint; -const BAR2:uint = BAR; +const BAR:usize = Flopsy::Bunny as usize; +const BAR2:usize = BAR; pub fn main() { - let _v = [0; Flopsy::Bunny as uint]; + let _v = [0; Flopsy::Bunny as usize]; let _v = [0; BAR]; let _v = [0; BAR2]; - const BAR3:uint = BAR2; + const BAR3:usize = BAR2; let _v = [0; BAR3]; } diff --git a/src/test/run-pass/env-home-dir.rs b/src/test/run-pass/env-home-dir.rs index 0e1ab73c02..7fb9611212 100644 --- a/src/test/run-pass/env-home-dir.rs +++ b/src/test/run-pass/env-home-dir.rs @@ -8,14 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(path)] + use std::env::*; +use std::path::PathBuf; #[cfg(unix)] fn main() { let oldhome = var("HOME"); set_var("HOME", "/home/MountainView"); - assert!(home_dir() == Some(Path::new("/home/MountainView"))); + assert!(home_dir() == Some(PathBuf::from("/home/MountainView"))); remove_var("HOME"); if cfg!(target_os = "android") { @@ -36,14 +41,14 @@ fn main() { assert!(home_dir().is_some()); set_var("HOME", "/home/MountainView"); - assert!(home_dir() == Some(Path::new("/home/MountainView"))); + assert!(home_dir() == Some(PathBuf::from("/home/MountainView"))); remove_var("HOME"); set_var("USERPROFILE", "/home/MountainView"); - assert!(home_dir() == Some(Path::new("/home/MountainView"))); + assert!(home_dir() == Some(PathBuf::from("/home/MountainView"))); set_var("HOME", "/home/MountainView"); set_var("USERPROFILE", "/home/PaloAlto"); - assert!(home_dir() == Some(Path::new("/home/MountainView"))); + assert!(home_dir() == Some(PathBuf::from("/home/MountainView"))); } diff --git a/src/test/run-pass/env-vars.rs b/src/test/run-pass/env-vars.rs index 659e5b3a8c..33bc6c596d 100644 --- a/src/test/run-pass/env-vars.rs +++ b/src/test/run-pass/env-vars.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::env::*; fn main() { diff --git a/src/test/run-pass/eq-multidispatch.rs b/src/test/run-pass/eq-multidispatch.rs index 2dcf6bf6d0..3ca254021e 100644 --- a/src/test/run-pass/eq-multidispatch.rs +++ b/src/test/run-pass/eq-multidispatch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(PartialEq)] struct Bar; struct Baz; diff --git a/src/test/run-pass/estr-uniq.rs b/src/test/run-pass/estr-uniq.rs index b562558822..0b24658a8f 100644 --- a/src/test/run-pass/estr-uniq.rs +++ b/src/test/run-pass/estr-uniq.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] pub fn main() { diff --git a/src/test/run-pass/evec-internal.rs b/src/test/run-pass/evec-internal.rs index 28b5f781b5..b3771f3848 100644 --- a/src/test/run-pass/evec-internal.rs +++ b/src/test/run-pass/evec-internal.rs @@ -13,16 +13,16 @@ // Doesn't work; needs a design decision. pub fn main() { - let x : [int; 5] = [1,2,3,4,5]; - let _y : [int; 5] = [1,2,3,4,5]; + let x : [isize; 5] = [1,2,3,4,5]; + let _y : [isize; 5] = [1,2,3,4,5]; let mut z = [1,2,3,4,5]; z = x; assert_eq!(z[0], 1); assert_eq!(z[4], 5); - let a : [int; 5] = [1,1,1,1,1]; - let b : [int; 5] = [2,2,2,2,2]; - let c : [int; 5] = [2,2,2,2,3]; + let a : [isize; 5] = [1,1,1,1,1]; + let b : [isize; 5] = [2,2,2,2,2]; + let c : [isize; 5] = [2,2,2,2,3]; log(debug, a); diff --git a/src/test/run-pass/evec-slice.rs b/src/test/run-pass/evec-slice.rs index 734ac30665..52ccbe52d4 100644 --- a/src/test/run-pass/evec-slice.rs +++ b/src/test/run-pass/evec-slice.rs @@ -11,16 +11,16 @@ #![allow(dead_assignment)] pub fn main() { - let x : &[int] = &[1,2,3,4,5]; - let mut z : &[int] = &[1,2,3,4,5]; + let x : &[isize] = &[1,2,3,4,5]; + let mut z : &[isize] = &[1,2,3,4,5]; z = x; assert_eq!(z[0], 1); assert_eq!(z[4], 5); - let a : &[int] = &[1,1,1,1,1]; - let b : &[int] = &[2,2,2,2,2]; - let c : &[int] = &[2,2,2,2,3]; - let cc : &[int] = &[2,2,2,2,2,2]; + let a : &[isize] = &[1,1,1,1,1]; + let b : &[isize] = &[2,2,2,2,2]; + let c : &[isize] = &[2,2,2,2,3]; + let cc : &[isize] = &[2,2,2,2,2,2]; println!("{:?}", a); diff --git a/src/test/run-pass/exec-env.rs b/src/test/run-pass/exec-env.rs index a71016fd88..a249307324 100644 --- a/src/test/run-pass/exec-env.rs +++ b/src/test/run-pass/exec-env.rs @@ -10,6 +10,8 @@ // exec-env:TEST_EXEC_ENV=22 +// pretty-expanded FIXME #23616 + use std::env; pub fn main() { diff --git a/src/test/run-pass/explicit-i-suffix.rs b/src/test/run-pass/explicit-i-suffix.rs index 96c58b106f..fa3970b628 100644 --- a/src/test/run-pass/explicit-i-suffix.rs +++ b/src/test/run-pass/explicit-i-suffix.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let x: int = 8; + let x: isize = 8; let y = 9; x + y; - let q: int = -8; + let q: isize = -8; let r = -9; q + r; } diff --git a/src/test/run-pass/explicit-self-closures.rs b/src/test/run-pass/explicit-self-closures.rs index ef9dc377bc..cb3a28d19d 100644 --- a/src/test/run-pass/explicit-self-closures.rs +++ b/src/test/run-pass/explicit-self-closures.rs @@ -10,12 +10,14 @@ // Test to make sure that explicit self params work inside closures +// pretty-expanded FIXME #23616 + struct Box { - x: uint + x: usize } impl Box { - pub fn set_many(&mut self, xs: &[uint]) { + pub fn set_many(&mut self, xs: &[usize]) { for x in xs { self.x = *x; } } } diff --git a/src/test/run-pass/explicit-self-generic.rs b/src/test/run-pass/explicit-self-generic.rs index 382c5c58e9..ee50d3bdf0 100644 --- a/src/test/run-pass/explicit-self-generic.rs +++ b/src/test/run-pass/explicit-self-generic.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -#[derive(Copy)] -struct LM { resize_at: uint, size: uint } +#[derive(Copy, Clone)] +struct LM { resize_at: usize, size: usize } enum HashMap { HashMap_(LM, Vec<(K,V)>) @@ -25,7 +27,7 @@ fn linear_map() -> HashMap { } impl HashMap { - pub fn len(&mut self) -> uint { + pub fn len(&mut self) -> usize { match *self { HashMap::HashMap_(ref l, _) => l.size } @@ -33,6 +35,6 @@ impl HashMap { } pub fn main() { - let mut m = box linear_map::<(),()>(); + let mut m: Box<_> = box linear_map::<(),()>(); assert_eq!(m.len(), 0); } diff --git a/src/test/run-pass/explicit-self-objects-uniq.rs b/src/test/run-pass/explicit-self-objects-uniq.rs index 501ba01b4c..08ea638f93 100644 --- a/src/test/run-pass/explicit-self-objects-uniq.rs +++ b/src/test/run-pass/explicit-self-objects-uniq.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,7 +18,7 @@ trait Foo { } struct S { - x: int + x: isize } impl Foo for S { diff --git a/src/test/run-pass/explicit-self.rs b/src/test/run-pass/explicit-self.rs index e5d8ec3f8a..b81090555e 100644 --- a/src/test/run-pass/explicit-self.rs +++ b/src/test/run-pass/explicit-self.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -50,7 +52,7 @@ struct thing { #[derive(Clone)] struct A { - a: int + a: isize } fn thing(x: A) -> thing { @@ -60,17 +62,17 @@ fn thing(x: A) -> thing { } impl thing { - pub fn bar(self: Box) -> int { self.x.a } - pub fn quux(&self) -> int { self.x.a } + pub fn bar(self: Box) -> isize { self.x.a } + pub fn quux(&self) -> isize { self.x.a } pub fn baz<'a>(&'a self) -> &'a A { &self.x } - pub fn spam(self) -> int { self.x.a } + pub fn spam(self) -> isize { self.x.a } } trait Nus { fn f(&self); } impl Nus for thing { fn f(&self) {} } pub fn main() { - let y = box thing(A {a: 10}); + let y: Box<_> = box thing(A {a: 10}); assert_eq!(y.clone().bar(), 10); assert_eq!(y.quux(), 10); diff --git a/src/test/run-pass/explicit_self_xcrate_exe.rs b/src/test/run-pass/explicit_self_xcrate_exe.rs index ee74fc0b0a..eaaf92fbea 100644 --- a/src/test/run-pass/explicit_self_xcrate_exe.rs +++ b/src/test/run-pass/explicit_self_xcrate_exe.rs @@ -10,6 +10,8 @@ // aux-build:explicit_self_xcrate.rs +// pretty-expanded FIXME #23616 + extern crate explicit_self_xcrate; use explicit_self_xcrate::{Foo, Bar}; diff --git a/src/test/run-pass/exponential-notation.rs b/src/test/run-pass/exponential-notation.rs index bfe22712de..7e947c0be4 100644 --- a/src/test/run-pass/exponential-notation.rs +++ b/src/test/run-pass/exponential-notation.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + use std::num::strconv::ExponentFormat::{ExpBin, ExpDec}; use std::num::strconv::SignificantDigits::DigMax; use std::num::strconv::SignFormat::{SignAll, SignNeg}; diff --git a/src/test/run-pass/export-abstract-tag.rs b/src/test/run-pass/export-abstract-tag.rs index 983ebbee98..7333d739f4 100644 --- a/src/test/run-pass/export-abstract-tag.rs +++ b/src/test/run-pass/export-abstract-tag.rs @@ -11,6 +11,8 @@ // We can export tags without exporting the variants to create a simple // sort of ADT. +// pretty-expanded FIXME #23616 + mod foo { pub enum t { t1, } diff --git a/src/test/run-pass/export-glob-imports-target.rs b/src/test/run-pass/export-glob-imports-target.rs index da0a3e9e10..4f821ebcc1 100644 --- a/src/test/run-pass/export-glob-imports-target.rs +++ b/src/test/run-pass/export-glob-imports-target.rs @@ -13,10 +13,12 @@ // Modified to not use export since it's going away. --pcw +// pretty-expanded FIXME #23616 + mod foo { use foo::bar::*; pub mod bar { - pub static a : int = 10; + pub static a : isize = 10; } pub fn zum() { let _b = a; diff --git a/src/test/run-pass/export-multi.rs b/src/test/run-pass/export-multi.rs index 2e44bf5be5..e7c35fcd75 100644 --- a/src/test/run-pass/export-multi.rs +++ b/src/test/run-pass/export-multi.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use m::f; use m::g; diff --git a/src/test/run-pass/export-non-interference3.rs b/src/test/run-pass/export-non-interference3.rs index 091c389840..b7ef4df7ed 100644 --- a/src/test/run-pass/export-non-interference3.rs +++ b/src/test/run-pass/export-non-interference3.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/export-tag-variant.rs b/src/test/run-pass/export-tag-variant.rs index 01fcf02ec1..6257332a66 100644 --- a/src/test/run-pass/export-tag-variant.rs +++ b/src/test/run-pass/export-tag-variant.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod foo { pub enum t { t1, } } diff --git a/src/test/run-pass/export-unexported-dep.rs b/src/test/run-pass/export-unexported-dep.rs deleted file mode 100644 index 807d28feb6..0000000000 --- a/src/test/run-pass/export-unexported-dep.rs +++ /dev/null @@ -1,31 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This tests that exports can have visible dependencies on things -// that are not exported, allowing for a sort of poor-man's ADT - -mod foo { - // not exported - #[derive(Copy)] - enum t { t1, t2, } - - impl PartialEq for t { - fn eq(&self, other: &t) -> bool { - ((*self) as uint) == ((*other) as uint) - } - fn ne(&self, other: &t) -> bool { !(*self).eq(other) } - } - - pub fn f() -> t { return t::t1; } - - pub fn g(v: t) { assert!((v == t::t1)); } -} - -pub fn main() { foo::g(foo::f()); } diff --git a/src/test/run-pass/expr-block-fn.rs b/src/test/run-pass/expr-block-fn.rs index ed246e2cb7..c88721471b 100644 --- a/src/test/run-pass/expr-block-fn.rs +++ b/src/test/run-pass/expr-block-fn.rs @@ -10,8 +10,10 @@ +// pretty-expanded FIXME #23616 + fn test_fn() { - fn ten() -> int { return 10; } + fn ten() -> isize { return 10; } let rs = ten; assert!((rs() == 10)); } diff --git a/src/test/run-pass/expr-block-generic-unique2.rs b/src/test/run-pass/expr-block-generic-unique2.rs index e41ce37cc3..bd29367739 100644 --- a/src/test/run-pass/expr-block-generic-unique2.rs +++ b/src/test/run-pass/expr-block-generic-unique2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -17,8 +19,8 @@ fn test_generic(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> boo } fn test_vec() { - fn compare_vec(v1: Box, v2: Box) -> bool { return v1 == v2; } - test_generic::, _>(box 1, compare_vec); + fn compare_vec(v1: Box, v2: Box) -> bool { return v1 == v2; } + test_generic::, _>(box 1, compare_vec); } pub fn main() { test_vec(); } diff --git a/src/test/run-pass/expr-block-generic.rs b/src/test/run-pass/expr-block-generic.rs index 91b847d47c..d26c6e62f5 100644 --- a/src/test/run-pass/expr-block-generic.rs +++ b/src/test/run-pass/expr-block-generic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { let actual: T = { expected.clone() }; assert!(eq(expected, actual)); @@ -20,8 +22,8 @@ fn test_bool() { #[derive(Clone)] struct Pair { - a: int, - b: int, + a: isize, + b: isize, } fn test_rec() { diff --git a/src/test/run-pass/expr-block-slot.rs b/src/test/run-pass/expr-block-slot.rs index cfb764e85f..57b5a426f5 100644 --- a/src/test/run-pass/expr-block-slot.rs +++ b/src/test/run-pass/expr-block-slot.rs @@ -10,8 +10,10 @@ // Regression test for issue #377 -struct A { a: int } -struct V { v: int } +// pretty-expanded FIXME #23616 + +struct A { a: isize } +struct V { v: isize } pub fn main() { let a = { let b = A {a: 3}; b }; diff --git a/src/test/run-pass/expr-block-unique.rs b/src/test/run-pass/expr-block-unique.rs index d10b209965..496a575c6c 100644 --- a/src/test/run-pass/expr-block-unique.rs +++ b/src/test/run-pass/expr-block-unique.rs @@ -9,7 +9,9 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -pub fn main() { let x = { box 100 }; assert!((*x == 100)); } +pub fn main() { let x: Box<_> = { box 100 }; assert!((*x == 100)); } diff --git a/src/test/run-pass/expr-block.rs b/src/test/run-pass/expr-block.rs index ee1d955b0d..64f86237ab 100644 --- a/src/test/run-pass/expr-block.rs +++ b/src/test/run-pass/expr-block.rs @@ -13,9 +13,11 @@ // Tests for standalone blocks as expressions +// pretty-expanded FIXME #23616 + fn test_basic() { let rs: bool = { true }; assert!((rs)); } -struct RS { v1: int, v2: int } +struct RS { v1: isize, v2: isize } fn test_rec() { let rs = { RS {v1: 10, v2: 20} }; assert!((rs.v2 == 20)); } diff --git a/src/test/run-pass/expr-copy.rs b/src/test/run-pass/expr-copy.rs index 6c6c508574..ca394f991f 100644 --- a/src/test/run-pass/expr-copy.rs +++ b/src/test/run-pass/expr-copy.rs @@ -9,12 +9,14 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn f(arg: &mut A) { arg.a = 100; } -#[derive(Copy)] -struct A { a: int } +#[derive(Copy, Clone)] +struct A { a: isize } pub fn main() { let mut x = A {a: 10}; diff --git a/src/test/run-pass/expr-empty-ret.rs b/src/test/run-pass/expr-empty-ret.rs index afc7dfaf9b..02ac2a0b67 100644 --- a/src/test/run-pass/expr-empty-ret.rs +++ b/src/test/run-pass/expr-empty-ret.rs @@ -10,6 +10,8 @@ // Issue #521 +// pretty-expanded FIXME #23616 + fn f() { let _x = match true { true => { 10 } diff --git a/src/test/run-pass/expr-fn.rs b/src/test/run-pass/expr-fn.rs index 0ea1f3fcda..0c9151cec7 100644 --- a/src/test/run-pass/expr-fn.rs +++ b/src/test/run-pass/expr-fn.rs @@ -9,13 +9,15 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn test_int() { - fn f() -> int { 10 } + fn f() -> isize { 10 } assert_eq!(f(), 10); } fn test_vec() { - fn f() -> Vec { vec!(10, 11) } + fn f() -> Vec { vec!(10, 11) } let vect = f(); assert_eq!(vect[1], 11); } @@ -26,22 +28,22 @@ fn test_generic() { } fn test_alt() { - fn f() -> int { match true { false => { 10 } true => { 20 } } } + fn f() -> isize { match true { false => { 10 } true => { 20 } } } assert_eq!(f(), 20); } fn test_if() { - fn f() -> int { if true { 10 } else { 20 } } + fn f() -> isize { if true { 10 } else { 20 } } assert_eq!(f(), 10); } fn test_block() { - fn f() -> int { { 10 } } + fn f() -> isize { { 10 } } assert_eq!(f(), 10); } fn test_ret() { - fn f() -> int { + fn f() -> isize { return 10 // no semi } @@ -51,7 +53,7 @@ fn test_ret() { // From issue #372 fn test_372() { - fn f() -> int { let x = { 3 }; x } + fn f() -> isize { let x = { 3 }; x } assert_eq!(f(), 3); } diff --git a/src/test/run-pass/expr-if-generic.rs b/src/test/run-pass/expr-if-generic.rs index fb2a120e6f..47e79de6b1 100644 --- a/src/test/run-pass/expr-if-generic.rs +++ b/src/test/run-pass/expr-if-generic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn test_generic(expected: T, not_expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool, @@ -23,8 +25,8 @@ fn test_bool() { #[derive(Clone)] struct Pair { - a: int, - b: int, + a: isize, + b: isize, } fn test_rec() { diff --git a/src/test/run-pass/expr-if-panic-all.rs b/src/test/run-pass/expr-if-panic-all.rs index 52ccee0581..1e631c2047 100644 --- a/src/test/run-pass/expr-if-panic-all.rs +++ b/src/test/run-pass/expr-if-panic-all.rs @@ -10,6 +10,8 @@ // When all branches of an if expression result in panic, the entire if // expression results in panic. +// pretty-expanded FIXME #23616 + pub fn main() { let _x = if true { 10 diff --git a/src/test/run-pass/expr-if-panic.rs b/src/test/run-pass/expr-if-panic.rs index 87c7954fa4..e8594db803 100644 --- a/src/test/run-pass/expr-if-panic.rs +++ b/src/test/run-pass/expr-if-panic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn test_if_panic() { let x = if false { panic!() } else { 10 }; assert!((x == 10)); diff --git a/src/test/run-pass/expr-if-struct.rs b/src/test/run-pass/expr-if-struct.rs index ee2c071504..e79daed4c3 100644 --- a/src/test/run-pass/expr-if-struct.rs +++ b/src/test/run-pass/expr-if-struct.rs @@ -14,20 +14,20 @@ // Tests for if as expressions returning nominal types -#[derive(Copy)] -struct I { i: int } +#[derive(Copy, Clone)] +struct I { i: isize } fn test_rec() { let rs = if true { I {i: 100} } else { I {i: 101} }; assert_eq!(rs.i, 100); } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum mood { happy, sad, } impl PartialEq for mood { fn eq(&self, other: &mood) -> bool { - ((*self) as uint) == ((*other) as uint) + ((*self) as usize) == ((*other) as usize) } fn ne(&self, other: &mood) -> bool { !(*self).eq(other) } } diff --git a/src/test/run-pass/expr-if-unique.rs b/src/test/run-pass/expr-if-unique.rs index 317e543493..99c5053588 100644 --- a/src/test/run-pass/expr-if-unique.rs +++ b/src/test/run-pass/expr-if-unique.rs @@ -9,13 +9,15 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] // Tests for if as expressions returning boxed types fn test_box() { - let rs = if true { box 100 } else { box 101 }; + let rs: Box<_> = if true { box 100 } else { box 101 }; assert_eq!(*rs, 100); } diff --git a/src/test/run-pass/expr-if.rs b/src/test/run-pass/expr-if.rs index 23446b3f65..345f17707c 100644 --- a/src/test/run-pass/expr-if.rs +++ b/src/test/run-pass/expr-if.rs @@ -13,6 +13,8 @@ // Tests for if as expressions +// pretty-expanded FIXME #23616 + fn test_if() { let rs: bool = if true { true } else { false }; assert!((rs)); } fn test_else() { diff --git a/src/test/run-pass/expr-match-generic-unique1.rs b/src/test/run-pass/expr-match-generic-unique1.rs index 9de1379f48..7cd0f6a758 100644 --- a/src/test/run-pass/expr-match-generic-unique1.rs +++ b/src/test/run-pass/expr-match-generic-unique1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/expr-match-generic-unique2.rs b/src/test/run-pass/expr-match-generic-unique2.rs index 489cd8437d..95f47d005d 100644 --- a/src/test/run-pass/expr-match-generic-unique2.rs +++ b/src/test/run-pass/expr-match-generic-unique2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -20,8 +22,8 @@ fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { } fn test_vec() { - fn compare_box(v1: Box, v2: Box) -> bool { return v1 == v2; } - test_generic::, _>(box 1, compare_box); + fn compare_box(v1: Box, v2: Box) -> bool { return v1 == v2; } + test_generic::, _>(box 1, compare_box); } pub fn main() { test_vec(); } diff --git a/src/test/run-pass/expr-match-generic.rs b/src/test/run-pass/expr-match-generic.rs index 8e66827e01..f8e82de9a0 100644 --- a/src/test/run-pass/expr-match-generic.rs +++ b/src/test/run-pass/expr-match-generic.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + type compare = extern "Rust" fn(T, T) -> bool; fn test_generic(expected: T, eq: compare) { @@ -23,8 +25,8 @@ fn test_bool() { #[derive(Clone)] struct Pair { - a: int, - b: int, + a: isize, + b: isize, } fn test_rec() { diff --git a/src/test/run-pass/expr-match-panic-all.rs b/src/test/run-pass/expr-match-panic-all.rs index 3a8955917d..664ead10aa 100644 --- a/src/test/run-pass/expr-match-panic-all.rs +++ b/src/test/run-pass/expr-match-panic-all.rs @@ -13,6 +13,8 @@ // When all branches of a match expression result in panic, the entire // match expression results in panic. +// pretty-expanded FIXME #23616 + pub fn main() { let _x = match true { diff --git a/src/test/run-pass/expr-match-panic.rs b/src/test/run-pass/expr-match-panic.rs index da24d4c57c..40e7a6175c 100644 --- a/src/test/run-pass/expr-match-panic.rs +++ b/src/test/run-pass/expr-match-panic.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn test_simple() { let r = match true { true => { true } false => { panic!() } }; assert_eq!(r, true); diff --git a/src/test/run-pass/expr-match-struct.rs b/src/test/run-pass/expr-match-struct.rs index e4ce71200b..2dcb0f833e 100644 --- a/src/test/run-pass/expr-match-struct.rs +++ b/src/test/run-pass/expr-match-struct.rs @@ -13,20 +13,20 @@ // Tests for match as expressions resulting in struct types -#[derive(Copy)] -struct R { i: int } +#[derive(Copy, Clone)] +struct R { i: isize } fn test_rec() { let rs = match true { true => R {i: 100}, _ => panic!() }; assert_eq!(rs.i, 100); } -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum mood { happy, sad, } impl PartialEq for mood { fn eq(&self, other: &mood) -> bool { - ((*self) as uint) == ((*other) as uint) + ((*self) as usize) == ((*other) as usize) } fn ne(&self, other: &mood) -> bool { !(*self).eq(other) } } diff --git a/src/test/run-pass/expr-match-unique.rs b/src/test/run-pass/expr-match-unique.rs index 57ccfe1d5e..51eda4c766 100644 --- a/src/test/run-pass/expr-match-unique.rs +++ b/src/test/run-pass/expr-match-unique.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] // Tests for match as expressions resulting in boxed types fn test_box() { - let res = match true { true => { box 100 }, _ => panic!() }; + let res: Box<_> = match true { true => { box 100 }, _ => panic!() }; assert_eq!(*res, 100); } diff --git a/src/test/run-pass/expr-match.rs b/src/test/run-pass/expr-match.rs index b8996de419..2282391ef6 100644 --- a/src/test/run-pass/expr-match.rs +++ b/src/test/run-pass/expr-match.rs @@ -13,6 +13,8 @@ // Tests for using match as an expression +// pretty-expanded FIXME #23616 + fn test_basic() { let mut rs: bool = match true { true => { true } false => { false } }; assert!((rs)); diff --git a/src/test/run-pass/expr-scope.rs b/src/test/run-pass/expr-scope.rs index 324ff59dcb..a1d8621884 100644 --- a/src/test/run-pass/expr-scope.rs +++ b/src/test/run-pass/expr-scope.rs @@ -10,5 +10,7 @@ // Regression test for issue #762 +// pretty-expanded FIXME #23616 + pub fn f() { } pub fn main() { return ::f(); } diff --git a/src/test/run-pass/ext-expand-inner-exprs.rs b/src/test/run-pass/ext-expand-inner-exprs.rs index d204f808e4..46cd73e115 100644 --- a/src/test/run-pass/ext-expand-inner-exprs.rs +++ b/src/test/run-pass/ext-expand-inner-exprs.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + static FOO : &'static str = concat!(concat!("hel", "lo"), "world"); pub fn main() { diff --git a/src/test/run-pass/exterior.rs b/src/test/run-pass/exterior.rs index bba8cbdb83..9a039e8bc3 100644 --- a/src/test/run-pass/exterior.rs +++ b/src/test/run-pass/exterior.rs @@ -9,10 +9,12 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cell::Cell; -#[derive(Copy)] -struct Point {x: int, y: int, z: int} +#[derive(Copy, Clone)] +struct Point {x: isize, y: isize, z: isize} fn f(p: &Cell) { assert!((p.get().z == 12)); diff --git a/src/test/run-pass/extern-1.rs b/src/test/run-pass/extern-1.rs index e4b9b9dfa1..67f6a3e8fc 100644 --- a/src/test/run-pass/extern-1.rs +++ b/src/test/run-pass/extern-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern fn f() { } diff --git a/src/test/run-pass/extern-call-deep.rs b/src/test/run-pass/extern-call-deep.rs index 93a5752d00..2138b12fb1 100644 --- a/src/test/run-pass/extern-call-deep.rs +++ b/src/test/run-pass/extern-call-deep.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(libc)] + extern crate libc; mod rustrt { diff --git a/src/test/run-pass/extern-call-deep2.rs b/src/test/run-pass/extern-call-deep2.rs index 3c4c1da52e..198745f5b1 100644 --- a/src/test/run-pass/extern-call-deep2.rs +++ b/src/test/run-pass/extern-call-deep2.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(libc)] + extern crate libc; -use std::thread::Thread; +use std::thread; mod rustrt { extern crate libc; @@ -40,9 +42,9 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t { pub fn main() { // Make sure we're on a task with small Rust stacks (main currently // has a large stack) - let _t = Thread::spawn(move|| { + thread::scoped(move|| { let result = count(1000); println!("result = {}", result); assert_eq!(result, 1000); - }); + }).join(); } diff --git a/src/test/run-pass/extern-call-direct.rs b/src/test/run-pass/extern-call-direct.rs index 34d2b577f2..38cd4a8d79 100644 --- a/src/test/run-pass/extern-call-direct.rs +++ b/src/test/run-pass/extern-call-direct.rs @@ -10,7 +10,9 @@ // Test direct calls to extern fns. -extern fn f(x: uint) -> uint { x * 2 } +// pretty-expanded FIXME #23616 + +extern fn f(x: usize) -> usize { x * 2 } pub fn main() { let x = f(22); diff --git a/src/test/run-pass/extern-call-indirect.rs b/src/test/run-pass/extern-call-indirect.rs index 52697d96b3..4f1abbeb5c 100644 --- a/src/test/run-pass/extern-call-indirect.rs +++ b/src/test/run-pass/extern-call-indirect.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(libc)] + extern crate libc; mod rustrt { diff --git a/src/test/run-pass/extern-call-scrub.rs b/src/test/run-pass/extern-call-scrub.rs index 0dca7514dc..e8c9bc7633 100644 --- a/src/test/run-pass/extern-call-scrub.rs +++ b/src/test/run-pass/extern-call-scrub.rs @@ -12,8 +12,10 @@ // make sure the stack pointers are maintained properly in both // directions +#![feature(libc, std_misc)] + extern crate libc; -use std::thread::Thread; +use std::thread; mod rustrt { extern crate libc; @@ -44,7 +46,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t { pub fn main() { // Make sure we're on a task with small Rust stacks (main currently // has a large stack) - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let result = count(12); println!("result = {}", result); assert_eq!(result, 2048); diff --git a/src/test/run-pass/extern-calling-convention-test.rs b/src/test/run-pass/extern-calling-convention-test.rs index bdb1326aa1..12f9c22c91 100644 --- a/src/test/run-pass/extern-calling-convention-test.rs +++ b/src/test/run-pass/extern-calling-convention-test.rs @@ -10,6 +10,8 @@ // aux-build:extern_calling_convention.rs +// pretty-expanded FIXME #23616 + extern crate extern_calling_convention; use extern_calling_convention::foo; diff --git a/src/test/run-pass/extern-compare-with-return-type.rs b/src/test/run-pass/extern-compare-with-return-type.rs index 3febff1870..09411c9c6e 100644 --- a/src/test/run-pass/extern-compare-with-return-type.rs +++ b/src/test/run-pass/extern-compare-with-return-type.rs @@ -10,25 +10,26 @@ // Tests that we can compare various kinds of extern fn signatures. +// pretty-expanded FIXME #23616 + extern fn voidret1() {} extern fn voidret2() {} -extern fn uintret() -> uint { 22 } +extern fn uintret() -> usize { 22 } -extern fn uintvoidret(_x: uint) {} +extern fn uintvoidret(_x: usize) {} -extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z } -type uintuintuintuintret = extern fn(uint,uint,uint) -> uint; +extern fn uintuintuintuintret(x: usize, y: usize, z: usize) -> usize { x+y+z } +type uintuintuintuintret = extern fn(usize,usize,usize) -> usize; pub fn main() { assert!(voidret1 as extern fn() == voidret1 as extern fn()); assert!(voidret1 as extern fn() != voidret2 as extern fn()); - assert!(uintret as extern fn() -> uint == uintret as extern fn() -> uint); + assert!(uintret as extern fn() -> usize == uintret as extern fn() -> usize); - assert!(uintvoidret as extern fn(uint) == uintvoidret as extern fn(uint)); + assert!(uintvoidret as extern fn(usize) == uintvoidret as extern fn(usize)); assert!(uintuintuintuintret as uintuintuintuintret == uintuintuintuintret as uintuintuintuintret); } - diff --git a/src/test/run-pass/extern-crosscrate.rs b/src/test/run-pass/extern-crosscrate.rs index 18e20332ad..7157d0658b 100644 --- a/src/test/run-pass/extern-crosscrate.rs +++ b/src/test/run-pass/extern-crosscrate.rs @@ -10,6 +10,8 @@ //aux-build:extern-crosscrate-source.rs +#![feature(libc)] + extern crate externcallback; extern crate libc; diff --git a/src/test/run-pass/extern-foreign-crate.rs b/src/test/run-pass/extern-foreign-crate.rs index 59ee9a14e2..1757ff51fe 100644 --- a/src/test/run-pass/extern-foreign-crate.rs +++ b/src/test/run-pass/extern-foreign-crate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate "std" as mystd; +// pretty-expanded FIXME #23616 + +extern crate std as mystd; pub fn main() {} diff --git a/src/test/run-pass/extern-methods.rs b/src/test/run-pass/extern-methods.rs new file mode 100644 index 0000000000..246f65931b --- /dev/null +++ b/src/test/run-pass/extern-methods.rs @@ -0,0 +1,42 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![feature(core)] + +use std::marker::MarkerTrait; + +trait A : MarkerTrait { + extern "fastcall" fn test1(i: i32); + extern fn test2(i: i32); +} + +struct S; +impl S { + extern "stdcall" fn test3(i: i32) { + assert_eq!(i, 3); + } +} + +impl A for S { + extern "fastcall" fn test1(i: i32) { + assert_eq!(i, 1); + } + extern fn test2(i: i32) { + assert_eq!(i, 2); + } +} + +fn main() { + ::test1(1); + ::test2(2); + S::test3(3); +} diff --git a/src/test/run-pass/extern-mod-abi.rs b/src/test/run-pass/extern-mod-abi.rs index 84fd1b40bf..74f47f0870 100644 --- a/src/test/run-pass/extern-mod-abi.rs +++ b/src/test/run-pass/extern-mod-abi.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern "C" { fn pow(x: f64, y: f64) -> f64; } diff --git a/src/test/run-pass/extern-mod-ordering-exe.rs b/src/test/run-pass/extern-mod-ordering-exe.rs index d6c6389fdb..1c64716b82 100644 --- a/src/test/run-pass/extern-mod-ordering-exe.rs +++ b/src/test/run-pass/extern-mod-ordering-exe.rs @@ -10,6 +10,8 @@ // aux-build:extern_mod_ordering_lib.rs +// pretty-expanded FIXME #23616 + extern crate extern_mod_ordering_lib; use extern_mod_ordering_lib::extern_mod_ordering_lib as the_lib; diff --git a/src/test/run-pass/extern-mod-syntax.rs b/src/test/run-pass/extern-mod-syntax.rs index 3e430b6e72..37404ee7e6 100644 --- a/src/test/run-pass/extern-mod-syntax.rs +++ b/src/test/run-pass/extern-mod-syntax.rs @@ -1,4 +1,3 @@ - // 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. @@ -10,6 +9,7 @@ // except according to those terms. #![allow(unused_imports)] +#![feature(rustc_private)] extern crate serialize; use serialize::json::Object; diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs index 1f48dc3bcf..9d304ea9e1 100644 --- a/src/test/run-pass/extern-pass-TwoU16s.rs +++ b/src/test/run-pass/extern-pass-TwoU16s.rs @@ -11,7 +11,7 @@ // Test a foreign function that accepts and returns a struct // by value. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct TwoU16s { one: u16, two: u16 } diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs index 171e2a647c..8dae0473fd 100644 --- a/src/test/run-pass/extern-pass-TwoU32s.rs +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -11,7 +11,7 @@ // Test a foreign function that accepts and returns a struct // by value. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct TwoU32s { one: u32, two: u32 } diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index 83555f6bb1..14aeea3465 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -11,7 +11,7 @@ // Test a foreign function that accepts and returns a struct // by value. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct TwoU64s { one: u64, two: u64 } diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs index d2b13445e6..75a109e442 100644 --- a/src/test/run-pass/extern-pass-TwoU8s.rs +++ b/src/test/run-pass/extern-pass-TwoU8s.rs @@ -11,7 +11,7 @@ // Test a foreign function that accepts and returns a struct // by value. -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct TwoU8s { one: u8, two: u8 } diff --git a/src/test/run-pass/extern-pass-char.rs b/src/test/run-pass/extern-pass-char.rs index 49c3bf62db..bbdf5cf64a 100644 --- a/src/test/run-pass/extern-pass-char.rs +++ b/src/test/run-pass/extern-pass-char.rs @@ -10,6 +10,8 @@ // Test a function that takes/returns a u8. +// pretty-expanded FIXME #23616 + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_u8(v: u8) -> u8; @@ -17,6 +19,6 @@ extern { pub fn main() { unsafe { - assert_eq!(22_u8, rust_dbg_extern_identity_u8(22_u8)); + assert_eq!(22, rust_dbg_extern_identity_u8(22)); } } diff --git a/src/test/run-pass/extern-pass-double.rs b/src/test/run-pass/extern-pass-double.rs index c33c9ee302..24c461f43a 100644 --- a/src/test/run-pass/extern-pass-double.rs +++ b/src/test/run-pass/extern-pass-double.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_double(v: f64) -> f64; diff --git a/src/test/run-pass/extern-pass-empty.rs b/src/test/run-pass/extern-pass-empty.rs index 272dfc9814..17b0bb580f 100644 --- a/src/test/run-pass/extern-pass-empty.rs +++ b/src/test/run-pass/extern-pass-empty.rs @@ -10,6 +10,8 @@ // Test a foreign function that accepts empty struct. +// pretty-expanded FIXME #23616 + struct TwoU8s { one: u8, two: u8, diff --git a/src/test/run-pass/extern-pass-u32.rs b/src/test/run-pass/extern-pass-u32.rs index 07c04af8e1..f93d7a3ff9 100644 --- a/src/test/run-pass/extern-pass-u32.rs +++ b/src/test/run-pass/extern-pass-u32.rs @@ -10,6 +10,8 @@ // Test a function that takes/returns a u32. +// pretty-expanded FIXME #23616 + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; @@ -17,6 +19,6 @@ extern { pub fn main() { unsafe { - assert_eq!(22_u32, rust_dbg_extern_identity_u32(22_u32)); + assert_eq!(22, rust_dbg_extern_identity_u32(22)); } } diff --git a/src/test/run-pass/extern-pass-u64.rs b/src/test/run-pass/extern-pass-u64.rs index e19c73ebe2..961a3dce16 100644 --- a/src/test/run-pass/extern-pass-u64.rs +++ b/src/test/run-pass/extern-pass-u64.rs @@ -10,6 +10,8 @@ // Test a call to a function that takes/returns a u64. +// pretty-expanded FIXME #23616 + #[link(name = "rust_test_helpers")] extern { pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; @@ -17,6 +19,6 @@ extern { pub fn main() { unsafe { - assert_eq!(22_u64, rust_dbg_extern_identity_u64(22_u64)); + assert_eq!(22, rust_dbg_extern_identity_u64(22)); } } diff --git a/src/test/run-pass/extern-pub.rs b/src/test/run-pass/extern-pub.rs index cefc266b5c..29bcdef5dc 100644 --- a/src/test/run-pass/extern-pub.rs +++ b/src/test/run-pass/extern-pub.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern { pub fn free(p: *const u8); } diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs index ca9767307f..f149a13462 100644 --- a/src/test/run-pass/extern-return-TwoU16s.rs +++ b/src/test/run-pass/extern-return-TwoU16s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct TwoU16s { one: u16, two: u16 } diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs index 8d650459da..4e9c44ef75 100644 --- a/src/test/run-pass/extern-return-TwoU32s.rs +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct TwoU32s { one: u32, two: u32 } diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs index 924aaf811f..fffd77fa89 100644 --- a/src/test/run-pass/extern-return-TwoU64s.rs +++ b/src/test/run-pass/extern-return-TwoU64s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct TwoU64s { one: u64, two: u64 } diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs index 1dbce403cc..fdf43d4332 100644 --- a/src/test/run-pass/extern-return-TwoU8s.rs +++ b/src/test/run-pass/extern-return-TwoU8s.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct TwoU8s { one: u8, two: u8 } diff --git a/src/test/run-pass/extern-rust.rs b/src/test/run-pass/extern-rust.rs index 8ba39a2451..e7f707bc33 100644 --- a/src/test/run-pass/extern-rust.rs +++ b/src/test/run-pass/extern-rust.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[repr(C)] pub struct Foo(u32); diff --git a/src/test/run-pass/extern-stress.rs b/src/test/run-pass/extern-stress.rs deleted file mode 100644 index b9e08e47b3..0000000000 --- a/src/test/run-pass/extern-stress.rs +++ /dev/null @@ -1,49 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This creates a bunch of descheduling tasks that run concurrently -// while holding onto C stacks - -extern crate libc; -use std::thread::Thread; - -mod rustrt { - extern crate libc; - - #[link(name = "rust_test_helpers")] - extern { - pub fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1 { - data - } else { - Thread::yield_now(); - count(data - 1) + count(data - 1) - } -} - -fn count(n: libc::uintptr_t) -> libc::uintptr_t { - unsafe { - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - (0_usize..100).map(|_| { - Thread::scoped(move|| { - assert_eq!(count(5), 16); - }) - }).collect::>(); -} diff --git a/src/test/run-pass/extern-take-value.rs b/src/test/run-pass/extern-take-value.rs index 1934ef8024..c016e4e62f 100644 --- a/src/test/run-pass/extern-take-value.rs +++ b/src/test/run-pass/extern-take-value.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern fn f() { } diff --git a/src/test/run-pass/extern-yield.rs b/src/test/run-pass/extern-yield.rs deleted file mode 100644 index 80428d787f..0000000000 --- a/src/test/run-pass/extern-yield.rs +++ /dev/null @@ -1,48 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate libc; -use std::thread::Thread; - -mod rustrt { - extern crate libc; - - #[link(name = "rust_test_helpers")] - extern { - pub fn rust_dbg_call(cb: extern "C" fn (libc::uintptr_t) -> libc::uintptr_t, - data: libc::uintptr_t) - -> libc::uintptr_t; - } -} - -extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1 { - data - } else { - count(data - 1) + count(data - 1) - } -} - -fn count(n: libc::uintptr_t) -> libc::uintptr_t { - unsafe { - Thread::yield_now(); - rustrt::rust_dbg_call(cb, n) - } -} - -pub fn main() { - (0..10_usize).map(|i| { - Thread::scoped(move|| { - let result = count(5); - println!("result = {}", result); - assert_eq!(result, 16); - }) - }).collect::>(); -} diff --git a/src/test/run-pass/extoption_env-not-defined.rs b/src/test/run-pass/extoption_env-not-defined.rs index 891133c78d..aaa8f6cf26 100644 --- a/src/test/run-pass/extoption_env-not-defined.rs +++ b/src/test/run-pass/extoption_env-not-defined.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert!(option_env!("__HOPEFULLY_DOESNT_EXIST__").is_none()); } diff --git a/src/test/run-pass/fact.rs b/src/test/run-pass/fact.rs index 172ec2f090..5cb2abbfb0 100644 --- a/src/test/run-pass/fact.rs +++ b/src/test/run-pass/fact.rs @@ -11,7 +11,7 @@ -fn f(x: int) -> int { +fn f(x: isize) -> isize { // println!("in f:"); println!("{}", x); @@ -22,7 +22,7 @@ fn f(x: int) -> int { } else { // println!("recurring"); - let y: int = x * f(x - 1); + let y: isize = x * f(x - 1); // println!("returned"); println!("{}", y); diff --git a/src/test/run-pass/field-destruction-order.rs b/src/test/run-pass/field-destruction-order.rs index 1d4c08f0bb..aab32a7e7b 100644 --- a/src/test/run-pass/field-destruction-order.rs +++ b/src/test/run-pass/field-destruction-order.rs @@ -21,6 +21,8 @@ // declarations, but we currently run them top-to-bottom. I don't think the // order really matters that much as long as we define what it is. +// pretty-expanded FIXME #23616 + struct A; struct B; struct C { diff --git a/src/test/run-pass/filter-block-view-items.rs b/src/test/run-pass/filter-block-view-items.rs index 37f7d84aaf..fbdf817e9a 100644 --- a/src/test/run-pass/filter-block-view-items.rs +++ b/src/test/run-pass/filter-block-view-items.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { // Make sure that this view item is filtered out because otherwise it would // trigger a compilation error diff --git a/src/test/run-pass/fixed_length_copy.rs b/src/test/run-pass/fixed_length_copy.rs index bbd7b9130e..019537a2ab 100644 --- a/src/test/run-pass/fixed_length_copy.rs +++ b/src/test/run-pass/fixed_length_copy.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let arr = [1,2,3]; let arr2 = arr; diff --git a/src/test/run-pass/fixup-deref-mut.rs b/src/test/run-pass/fixup-deref-mut.rs index a673a67089..900da3c2d6 100644 --- a/src/test/run-pass/fixup-deref-mut.rs +++ b/src/test/run-pass/fixup-deref-mut.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ops::{Deref, DerefMut}; // Generic unique/owned smaht pointer. @@ -30,12 +32,12 @@ impl DerefMut for Own { } struct Point { - x: int, - y: int + x: isize, + y: isize } impl Point { - fn get(&mut self) -> (int, int) { + fn get(&mut self) -> (isize, isize) { (self.x, self.y) } } diff --git a/src/test/run-pass/float-nan.rs b/src/test/run-pass/float-nan.rs index 4d9f7d507f..b375f12208 100644 --- a/src/test/run-pass/float-nan.rs +++ b/src/test/run-pass/float-nan.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + use std::num::Float; pub fn main() { diff --git a/src/test/run-pass/float2.rs b/src/test/run-pass/float2.rs index 9c75979628..f84cbe5235 100644 --- a/src/test/run-pass/float2.rs +++ b/src/test/run-pass/float2.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + pub fn main() { let a = 1.5e6f64; let b = 1.5E6f64; diff --git a/src/test/run-pass/floatlits.rs b/src/test/run-pass/floatlits.rs index 09df423d2d..d45c689bfd 100644 --- a/src/test/run-pass/floatlits.rs +++ b/src/test/run-pass/floatlits.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + pub fn main() { let f = 4.999999999999f64; assert!((f > 4.90f64)); diff --git a/src/test/run-pass/fn-abi.rs b/src/test/run-pass/fn-abi.rs index 0bbd5ecdc3..521ed6db65 100644 --- a/src/test/run-pass/fn-abi.rs +++ b/src/test/run-pass/fn-abi.rs @@ -11,6 +11,8 @@ // Ensure that declarations and types which use `extern fn` both have the same // ABI (#9309). +// pretty-expanded FIXME #23616 + extern { fn printf(); } diff --git a/src/test/run-pass/fn-bare-assign.rs b/src/test/run-pass/fn-bare-assign.rs index fd8721e29e..d83dc78580 100644 --- a/src/test/run-pass/fn-bare-assign.rs +++ b/src/test/run-pass/fn-bare-assign.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(i: int, called: &mut bool) { +// pretty-expanded FIXME #23616 + +fn f(i: isize, called: &mut bool) { assert_eq!(i, 10); *called = true; } -fn g(f: fn(int, v: &mut bool), called: &mut bool) { +fn g(f: fn(isize, v: &mut bool), called: &mut bool) { f(10, called); } diff --git a/src/test/run-pass/fn-bare-coerce-to-block.rs b/src/test/run-pass/fn-bare-coerce-to-block.rs index 09508b9b13..4ec32d2346 100644 --- a/src/test/run-pass/fn-bare-coerce-to-block.rs +++ b/src/test/run-pass/fn-bare-coerce-to-block.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn bare() {} fn likes_block(f: F) where F: FnOnce() { f() } diff --git a/src/test/run-pass/fn-bare-size.rs b/src/test/run-pass/fn-bare-size.rs index cdde98331e..117cf13584 100644 --- a/src/test/run-pass/fn-bare-size.rs +++ b/src/test/run-pass/fn-bare-size.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; pub fn main() { // Bare functions should just be a pointer - assert_eq!(mem::size_of::(), mem::size_of::()); + assert_eq!(mem::size_of::(), mem::size_of::()); } diff --git a/src/test/run-pass/fn-bare-spawn.rs b/src/test/run-pass/fn-bare-spawn.rs index 4fc2c69ceb..0a3c891627 100644 --- a/src/test/run-pass/fn-bare-spawn.rs +++ b/src/test/run-pass/fn-bare-spawn.rs @@ -10,11 +10,13 @@ // This is what the signature to spawn should look like with bare functions +// pretty-expanded FIXME #23616 + fn spawn(val: T, f: fn(T)) { f(val); } -fn f(i: int) { +fn f(i: isize) { assert_eq!(i, 100); } diff --git a/src/test/run-pass/fn-coerce-field.rs b/src/test/run-pass/fn-coerce-field.rs index bf6926050b..74d107d15a 100644 --- a/src/test/run-pass/fn-coerce-field.rs +++ b/src/test/run-pass/fn-coerce-field.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct r where F: FnOnce() { field: F, } diff --git a/src/test/run-pass/fn-item-type-cast.rs b/src/test/run-pass/fn-item-type-cast.rs index bfd02f5e27..f8b1582c51 100644 --- a/src/test/run-pass/fn-item-type-cast.rs +++ b/src/test/run-pass/fn-item-type-cast.rs @@ -10,9 +10,11 @@ // Test explicit coercions from a fn item type to a fn pointer type. -fn foo(x: int) -> int { x * 2 } -fn bar(x: int) -> int { x * 4 } -type IntMap = fn(int) -> int; +// pretty-expanded FIXME #23616 + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } +type IntMap = fn(isize) -> isize; fn eq(x: T, y: T) { } diff --git a/src/test/run-pass/fn-item-type-coerce.rs b/src/test/run-pass/fn-item-type-coerce.rs index 8427a0f444..67899bfd68 100644 --- a/src/test/run-pass/fn-item-type-coerce.rs +++ b/src/test/run-pass/fn-item-type-coerce.rs @@ -10,9 +10,11 @@ // Test implicit coercions from a fn item type to a fn pointer type. -fn foo(x: int) -> int { x * 2 } -fn bar(x: int) -> int { x * 4 } -type IntMap = fn(int) -> int; +// pretty-expanded FIXME #23616 + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } +type IntMap = fn(isize) -> isize; fn eq(x: T, y: T) { } diff --git a/src/test/run-pass/fn-lval.rs b/src/test/run-pass/fn-lval.rs index f21dbc6f98..13c96f4346 100644 --- a/src/test/run-pass/fn-lval.rs +++ b/src/test/run-pass/fn-lval.rs @@ -11,8 +11,10 @@ -fn foo(_f: fn(int) -> int) { } +// pretty-expanded FIXME #23616 -fn id(x: int) -> int { return x; } +fn foo(_f: fn(isize) -> isize) { } + +fn id(x: isize) -> isize { return x; } pub fn main() { foo(id); } diff --git a/src/test/run-pass/fn-pattern-expected-type-2.rs b/src/test/run-pass/fn-pattern-expected-type-2.rs index 4e2c8facaf..66a7123c79 100644 --- a/src/test/run-pass/fn-pattern-expected-type-2.rs +++ b/src/test/run-pass/fn-pattern-expected-type-2.rs @@ -9,7 +9,7 @@ // except according to those terms. pub fn main() { - let v : &[(int,int)] = &[ (1, 2), (3, 4), (5, 6) ]; + let v : &[(isize,isize)] = &[ (1, 2), (3, 4), (5, 6) ]; for &(x, y) in v { println!("{}", y); println!("{}", x); diff --git a/src/test/run-pass/fn-pattern-expected-type.rs b/src/test/run-pass/fn-pattern-expected-type.rs index 3e81ca5125..352d0b13c6 100644 --- a/src/test/run-pass/fn-pattern-expected-type.rs +++ b/src/test/run-pass/fn-pattern-expected-type.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let f = |(x, y): (int, int)| { + let f = |(x, y): (isize, isize)| { assert_eq!(x, 1); assert_eq!(y, 2); }; diff --git a/src/test/run-pass/fn-type-infer.rs b/src/test/run-pass/fn-type-infer.rs index 3441789119..3e1674a97e 100644 --- a/src/test/run-pass/fn-type-infer.rs +++ b/src/test/run-pass/fn-type-infer.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_variable)] pub fn main() { diff --git a/src/test/run-pass/for-destruct.rs b/src/test/run-pass/for-destruct.rs index 7a9b8a45b2..9d8c432e98 100644 --- a/src/test/run-pass/for-destruct.rs +++ b/src/test/run-pass/for-destruct.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Pair { x: int, y: int } +// pretty-expanded FIXME #23616 + +struct Pair { x: isize, y: isize } pub fn main() { for elt in &(vec!(Pair {x: 10, y: 20}, Pair {x: 30, y: 0})) { diff --git a/src/test/run-pass/for-loop-goofiness.rs b/src/test/run-pass/for-loop-goofiness.rs index 7754751120..4b6b6dcf1d 100644 --- a/src/test/run-pass/for-loop-goofiness.rs +++ b/src/test/run-pass/for-loop-goofiness.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum BogusOption { None, Some(T), } -type Iterator = int; +type Iterator = isize; pub fn main() { let x = [ 3, 3, 3 ]; @@ -21,4 +23,3 @@ pub fn main() { assert_eq!(*i, 3); } } - diff --git a/src/test/run-pass/for-loop-into-iterator.rs b/src/test/run-pass/for-loop-into-iterator.rs index 7564efbd9e..109ca26056 100644 --- a/src/test/run-pass/for-loop-into-iterator.rs +++ b/src/test/run-pass/for-loop-into-iterator.rs @@ -10,6 +10,8 @@ // Test that for loops can do what RFC #235 claims +// pretty-expanded FIXME #23616 + fn main() { let mut v = vec![1]; diff --git a/src/test/run-pass/for-loop-no-std.rs b/src/test/run-pass/for-loop-no-std.rs index 30c2aec33a..6deaec1905 100644 --- a/src/test/run-pass/for-loop-no-std.rs +++ b/src/test/run-pass/for-loop-no-std.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, no_std)] +// pretty-expanded FIXME #23616 + +#![feature(lang_items, start, no_std, core, collections)] #![no_std] -extern crate "std" as other; +extern crate std as other; #[macro_use] extern crate core; #[macro_use] extern crate collections; @@ -19,7 +21,7 @@ extern crate "std" as other; use core::slice::SliceExt; #[start] -fn start(_argc: int, _argv: *const *const u8) -> int { +fn start(_argc: isize, _argv: *const *const u8) -> isize { for _ in [1,2,3].iter() { } 0 } diff --git a/src/test/run-pass/for-loop-panic.rs b/src/test/run-pass/for-loop-panic.rs index d2de1ed8c7..908932fe39 100644 --- a/src/test/run-pass/for-loop-panic.rs +++ b/src/test/run-pass/for-loop-panic.rs @@ -9,4 +9,6 @@ // except according to those terms. -pub fn main() { let x: Vec = Vec::new(); for _ in &x { panic!("moop"); } } +// pretty-expanded FIXME #23616 + +pub fn main() { let x: Vec = Vec::new(); for _ in &x { panic!("moop"); } } diff --git a/src/test/run-pass/foreach-external-iterators-break.rs b/src/test/run-pass/foreach-external-iterators-break.rs index 25d625e27f..bc04125989 100644 --- a/src/test/run-pass/foreach-external-iterators-break.rs +++ b/src/test/run-pass/foreach-external-iterators-break.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = [1; 100]; let mut y = 0; diff --git a/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs b/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs index a4988bf016..cc02ee1459 100644 --- a/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs +++ b/src/test/run-pass/foreach-external-iterators-hashmap-break-restart.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + extern crate collections; use std::collections::HashMap; diff --git a/src/test/run-pass/foreach-external-iterators-hashmap.rs b/src/test/run-pass/foreach-external-iterators-hashmap.rs index ed4328d94f..065e4cfb76 100644 --- a/src/test/run-pass/foreach-external-iterators-hashmap.rs +++ b/src/test/run-pass/foreach-external-iterators-hashmap.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + extern crate collections; use std::collections::HashMap; diff --git a/src/test/run-pass/foreach-external-iterators-loop.rs b/src/test/run-pass/foreach-external-iterators-loop.rs index d9abed5012..60cfc9be07 100644 --- a/src/test/run-pass/foreach-external-iterators-loop.rs +++ b/src/test/run-pass/foreach-external-iterators-loop.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = [1; 100]; let mut y = 0; diff --git a/src/test/run-pass/foreach-external-iterators-nested.rs b/src/test/run-pass/foreach-external-iterators-nested.rs index 3817e1b0ed..a075c08b73 100644 --- a/src/test/run-pass/foreach-external-iterators-nested.rs +++ b/src/test/run-pass/foreach-external-iterators-nested.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = [1; 100]; let y = [2; 100]; diff --git a/src/test/run-pass/foreach-external-iterators.rs b/src/test/run-pass/foreach-external-iterators.rs index 8403a1669f..2248132d82 100644 --- a/src/test/run-pass/foreach-external-iterators.rs +++ b/src/test/run-pass/foreach-external-iterators.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = [1; 100]; let mut y = 0; diff --git a/src/test/run-pass/foreach-nested.rs b/src/test/run-pass/foreach-nested.rs index f646699495..075539b621 100644 --- a/src/test/run-pass/foreach-nested.rs +++ b/src/test/run-pass/foreach-nested.rs @@ -9,13 +9,15 @@ // except according to those terms. -fn two(mut it: F) where F: FnMut(int) { it(0); it(1); } +// pretty-expanded FIXME #23616 + +fn two(mut it: F) where F: FnMut(isize) { it(0); it(1); } pub fn main() { - let mut a: Vec = vec!(-1, -1, -1, -1); - let mut p: int = 0; + let mut a: Vec = vec!(-1, -1, -1, -1); + let mut p: isize = 0; two(|i| { - two(|j| { a[p as uint] = 10 * i + j; p += 1; }) + two(|j| { a[p as usize] = 10 * i + j; p += 1; }) }); assert_eq!(a[0], 0); assert_eq!(a[1], 1); diff --git a/src/test/run-pass/foreach-put-structured.rs b/src/test/run-pass/foreach-put-structured.rs index 029dddb7a2..028e31d76a 100644 --- a/src/test/run-pass/foreach-put-structured.rs +++ b/src/test/run-pass/foreach-put-structured.rs @@ -10,15 +10,15 @@ -fn pairs(mut it: F) where F: FnMut((int, int)) { - let mut i: int = 0; - let mut j: int = 0; +fn pairs(mut it: F) where F: FnMut((isize, isize)) { + let mut i: isize = 0; + let mut j: isize = 0; while i < 10 { it((i, j)); i += 1; j += i; } } pub fn main() { - let mut i: int = 10; - let mut j: int = 0; + let mut i: isize = 10; + let mut j: isize = 0; pairs(|p| { let (_0, _1) = p; println!("{}", _0); diff --git a/src/test/run-pass/foreach-simple-outer-slot.rs b/src/test/run-pass/foreach-simple-outer-slot.rs index 9ccb2dd56c..674c2e3448 100644 --- a/src/test/run-pass/foreach-simple-outer-slot.rs +++ b/src/test/run-pass/foreach-simple-outer-slot.rs @@ -12,14 +12,14 @@ pub fn main() { - let mut sum: int = 0; + let mut sum: isize = 0; first_ten(|i| { println!("main"); println!("{}", i); sum = sum + i; }); println!("sum"); println!("{}", sum); assert_eq!(sum, 45); } -fn first_ten(mut it: F) where F: FnMut(int) { - let mut i: int = 0; +fn first_ten(mut it: F) where F: FnMut(isize) { + let mut i: isize = 0; while i < 10 { println!("first_ten"); it(i); i = i + 1; } } diff --git a/src/test/run-pass/foreign-call-no-runtime.rs b/src/test/run-pass/foreign-call-no-runtime.rs index 3f226a1985..2d3ff62a00 100644 --- a/src/test/run-pass/foreign-call-no-runtime.rs +++ b/src/test/run-pass/foreign-call-no-runtime.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-aarch64 +#![feature(libc)] + extern crate libc; use std::mem; @@ -30,7 +33,7 @@ pub fn main() { extern fn callback(data: libc::uintptr_t) { unsafe { - let data: *const int = mem::transmute(data); + let data: *const isize = mem::transmute(data); assert_eq!(*data, 100); } } diff --git a/src/test/run-pass/foreign-dupe.rs b/src/test/run-pass/foreign-dupe.rs index 39c7d6dda0..fd779d6650 100644 --- a/src/test/run-pass/foreign-dupe.rs +++ b/src/test/run-pass/foreign-dupe.rs @@ -10,6 +10,10 @@ // calling pin_task and that's having weird side-effects. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + mod rustrt1 { extern crate libc; diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index 24b711328a..5db83d50b6 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate + +// pretty-expanded FIXME #23616 + +#![feature(std_misc, libc)] extern crate libc; use std::ffi::CString; @@ -22,15 +25,15 @@ mod mlibc { } } -fn strlen(str: String) -> uint { +fn strlen(str: String) -> usize { // C string is terminated with a zero let s = CString::new(str).unwrap(); unsafe { - mlibc::my_strlen(s.as_ptr()) as uint + mlibc::my_strlen(s.as_ptr()) as usize } } pub fn main() { let len = strlen("Rust".to_string()); - assert_eq!(len, 4_usize); + assert_eq!(len, 4); } diff --git a/src/test/run-pass/foreign-fn-with-byval.rs b/src/test/run-pass/foreign-fn-with-byval.rs index 09317abce9..7883c22f90 100644 --- a/src/test/run-pass/foreign-fn-with-byval.rs +++ b/src/test/run-pass/foreign-fn-with-byval.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] pub struct S { x: u64, y: u64, diff --git a/src/test/run-pass/foreign-mod-unused-const.rs b/src/test/run-pass/foreign-mod-unused-const.rs index e1ed0b8ea3..70d4801ae3 100644 --- a/src/test/run-pass/foreign-mod-unused-const.rs +++ b/src/test/run-pass/foreign-mod-unused-const.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate + +// pretty-expanded FIXME #23616 + +#![feature(libc)] extern crate libc; diff --git a/src/test/run-pass/foreign-no-abi.rs b/src/test/run-pass/foreign-no-abi.rs index 2af02feb21..a9b3f60566 100644 --- a/src/test/run-pass/foreign-no-abi.rs +++ b/src/test/run-pass/foreign-no-abi.rs @@ -10,6 +10,10 @@ // ABI is cdecl by default +// pretty-expanded FIXME #23616 + +#![feature(libc)] + mod rustrt { extern crate libc; diff --git a/src/test/run-pass/foreign-struct.rs b/src/test/run-pass/foreign-struct.rs index e242071fb2..8b48731ee0 100644 --- a/src/test/run-pass/foreign-struct.rs +++ b/src/test/run-pass/foreign-struct.rs @@ -10,6 +10,8 @@ // Passing enums by value +// pretty-expanded FIXME #23616 + pub enum void { } mod bindgen { diff --git a/src/test/run-pass/foreign2.rs b/src/test/run-pass/foreign2.rs index ce2f895566..d83bd940d1 100644 --- a/src/test/run-pass/foreign2.rs +++ b/src/test/run-pass/foreign2.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate + +// pretty-expanded FIXME #23616 + +#![feature(libc)] extern crate libc; diff --git a/src/test/run-pass/format-nan.rs b/src/test/run-pass/format-nan.rs index 1024bc21d2..bdbbeaa951 100644 --- a/src/test/run-pass/format-nan.rs +++ b/src/test/run-pass/format-nan.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { use std::f64; let x = "NaN".to_string(); @@ -15,4 +17,3 @@ pub fn main() { assert_eq!(format!("{:e}", f64::NAN), x); assert_eq!(format!("{:E}", f64::NAN), x); } - diff --git a/src/test/run-pass/format-no-std.rs b/src/test/run-pass/format-no-std.rs index a15a176c22..9204cdfd75 100644 --- a/src/test/run-pass/format-no-std.rs +++ b/src/test/run-pass/format-no-std.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, no_std)] +// pretty-expanded FIXME #23616 + +#![feature(lang_items, start, no_std, core, collections)] #![no_std] -extern crate "std" as other; +extern crate std as other; #[macro_use] extern crate core; #[macro_use] extern crate collections; @@ -19,7 +21,7 @@ extern crate "std" as other; use collections::string::ToString; #[start] -fn start(_argc: int, _argv: *const *const u8) -> int { +fn start(_argc: isize, _argv: *const *const u8) -> isize { let s = format!("{}", 1_isize); assert_eq!(s, "1".to_string()); diff --git a/src/test/run-pass/format-ref-cell.rs b/src/test/run-pass/format-ref-cell.rs index 2122759b3d..ce26fbd4c0 100644 --- a/src/test/run-pass/format-ref-cell.rs +++ b/src/test/run-pass/format-ref-cell.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cell::RefCell; pub fn main() { diff --git a/src/test/run-pass/fsu-moves-and-copies.rs b/src/test/run-pass/fsu-moves-and-copies.rs index 0f8d7c2436..fecaf279d0 100644 --- a/src/test/run-pass/fsu-moves-and-copies.rs +++ b/src/test/run-pass/fsu-moves-and-copies.rs @@ -11,33 +11,35 @@ // Issue 4691: Ensure that functional-struct-updates operates // correctly and moves rather than copy when appropriate. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, core)] use std::marker::NoCopy as NP; -struct ncint { np: NP, v: int } -fn ncint(v: int) -> ncint { ncint { np: NP, v: v } } +struct ncint { np: NP, v: isize } +fn ncint(v: isize) -> ncint { ncint { np: NP, v: v } } -struct NoFoo { copied: int, nocopy: ncint, } +struct NoFoo { copied: isize, nocopy: ncint, } impl NoFoo { - fn new(x:int,y:int) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } } + fn new(x:isize,y:isize) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } } } -struct MoveFoo { copied: int, moved: Box, } +struct MoveFoo { copied: isize, moved: Box, } impl MoveFoo { - fn new(x:int,y:int) -> MoveFoo { MoveFoo { copied: x, moved: box y } } + fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: box y } } } struct DropNoFoo { inner: NoFoo } impl DropNoFoo { - fn new(x:int,y:int) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } } + fn new(x:isize,y:isize) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } } } impl Drop for DropNoFoo { fn drop(&mut self) { } } struct DropMoveFoo { inner: MoveFoo } impl DropMoveFoo { - fn new(x:int,y:int) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } } + fn new(x:isize,y:isize) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } } } impl Drop for DropMoveFoo { fn drop(&mut self) { } } diff --git a/src/test/run-pass/fun-call-variants.rs b/src/test/run-pass/fun-call-variants.rs index 3955bedb16..0fe4bbcb7a 100644 --- a/src/test/run-pass/fun-call-variants.rs +++ b/src/test/run-pass/fun-call-variants.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn ho(f: F) -> int where F: FnOnce(int) -> int { let n: int = f(3); return n; } +// pretty-expanded FIXME #23616 -fn direct(x: int) -> int { return x + 1; } +fn ho(f: F) -> isize where F: FnOnce(isize) -> isize { let n: isize = f(3); return n; } + +fn direct(x: isize) -> isize { return x + 1; } pub fn main() { - let a: int = direct(3); // direct - let b: int = ho(direct); // indirect unbound + let a: isize = direct(3); // direct + let b: isize = ho(direct); // indirect unbound assert_eq!(a, b); } diff --git a/src/test/run-pass/fun-indirect-call.rs b/src/test/run-pass/fun-indirect-call.rs index 4bff06f2a0..48dfcb73da 100644 --- a/src/test/run-pass/fun-indirect-call.rs +++ b/src/test/run-pass/fun-indirect-call.rs @@ -11,10 +11,12 @@ -fn f() -> int { return 42; } +// pretty-expanded FIXME #23616 + +fn f() -> isize { return 42; } pub fn main() { - let g: fn() -> int = f; - let i: int = g(); + let g: fn() -> isize = f; + let i: isize = g(); assert_eq!(i, 42); } diff --git a/src/test/run-pass/func-arg-incomplete-pattern.rs b/src/test/run-pass/func-arg-incomplete-pattern.rs index b23d8db3cf..2833723708 100644 --- a/src/test/run-pass/func-arg-incomplete-pattern.rs +++ b/src/test/run-pass/func-arg-incomplete-pattern.rs @@ -11,22 +11,24 @@ // Test that we do not leak when the arg pattern must drop part of the // argument (in this case, the `y` field). +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct Foo { - x: Box, - y: Box, + x: Box, + y: Box, } -fn foo(Foo {x, ..}: Foo) -> *const uint { - let addr: *const uint = &*x; +fn foo(Foo {x, ..}: Foo) -> *const usize { + let addr: *const usize = &*x; addr } pub fn main() { - let obj = box 1; - let objptr: *const uint = &*obj; + let obj: Box<_> = box 1; + let objptr: *const usize = &*obj; let f = Foo {x: obj, y: box 2}; let xptr = foo(f); assert_eq!(objptr, xptr); diff --git a/src/test/run-pass/func-arg-ref-pattern.rs b/src/test/run-pass/func-arg-ref-pattern.rs index 5d44a9461b..fcc00afb00 100644 --- a/src/test/run-pass/func-arg-ref-pattern.rs +++ b/src/test/run-pass/func-arg-ref-pattern.rs @@ -14,22 +14,24 @@ // boxes. Make sure that we don't free the box as we match the // pattern. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] -fn getaddr(box ref x: Box) -> *const uint { - let addr: *const uint = &*x; +fn getaddr(box ref x: Box) -> *const usize { + let addr: *const usize = &*x; addr } -fn checkval(box ref x: Box) -> uint { +fn checkval(box ref x: Box) -> usize { *x } pub fn main() { - let obj = box 1; - let objptr: *const uint = &*obj; + let obj: Box<_> = box 1; + let objptr: *const usize = &*obj; let xptr = getaddr(obj); assert_eq!(objptr, xptr); diff --git a/src/test/run-pass/func-arg-wild-pattern.rs b/src/test/run-pass/func-arg-wild-pattern.rs index 97ba561bae..4f74ca0ff7 100644 --- a/src/test/run-pass/func-arg-wild-pattern.rs +++ b/src/test/run-pass/func-arg-wild-pattern.rs @@ -11,7 +11,9 @@ // Test that we can compile code that uses a `_` in function argument // patterns. -fn foo((x, _): (int, int)) -> int { +// pretty-expanded FIXME #23616 + +fn foo((x, _): (isize, isize)) -> isize { x } diff --git a/src/test/run-pass/functional-struct-upd.rs b/src/test/run-pass/functional-struct-upd.rs index 8c686aba5f..240d49d718 100644 --- a/src/test/run-pass/functional-struct-upd.rs +++ b/src/test/run-pass/functional-struct-upd.rs @@ -10,8 +10,8 @@ #[derive(Debug)] struct Foo { - x: int, - y: int + x: isize, + y: isize } pub fn main() { diff --git a/src/test/run-pass/generic-alias-unique.rs b/src/test/run-pass/generic-alias-unique.rs index db468ba180..b8d7c2140b 100644 --- a/src/test/run-pass/generic-alias-unique.rs +++ b/src/test/run-pass/generic-alias-unique.rs @@ -14,8 +14,8 @@ fn id(t: T) -> T { return t; } pub fn main() { - let expected = box 100; - let actual = id::>(expected.clone()); + let expected: Box<_> = box 100; + let actual = id::>(expected.clone()); println!("{}", *actual); assert_eq!(*expected, *actual); } diff --git a/src/test/run-pass/generic-default-type-params-cross-crate.rs b/src/test/run-pass/generic-default-type-params-cross-crate.rs index bf02b82d1a..4cf9f93bca 100644 --- a/src/test/run-pass/generic-default-type-params-cross-crate.rs +++ b/src/test/run-pass/generic-default-type-params-cross-crate.rs @@ -10,6 +10,8 @@ // aux-build:default_type_params_xc.rs +// pretty-expanded FIXME #23616 + extern crate default_type_params_xc; struct Vec(Option<(T,A)>); @@ -17,8 +19,8 @@ struct Vec(Option<(T,A)>); struct Foo; fn main() { - let _a = Vec::(None); - let _b = Vec::(None); - let _c = default_type_params_xc::FakeVec:: { f: None }; - let _d = default_type_params_xc::FakeVec:: { f: None }; + let _a = Vec::(None); + let _b = Vec::(None); + let _c = default_type_params_xc::FakeVec:: { f: None }; + let _d = default_type_params_xc::FakeVec:: { f: None }; } diff --git a/src/test/run-pass/generic-default-type-params.rs b/src/test/run-pass/generic-default-type-params.rs index e7ef1d42f5..e30cb76579 100644 --- a/src/test/run-pass/generic-default-type-params.rs +++ b/src/test/run-pass/generic-default-type-params.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo { +struct Foo { a: A } -impl Foo { - fn bar_int(&self) -> int { +impl Foo { + fn bar_int(&self) -> isize { self.a } } @@ -26,7 +26,7 @@ impl Foo { impl Foo { fn bar(&self) { - let (i, c): (int, char) = self.a; + let (i, c): (isize, char) = self.a; assert_eq!(Foo { a: i }.bar_int(), i); assert_eq!(Foo { a: c }.bar_char(), c); } @@ -39,7 +39,7 @@ impl Foo { } fn default_foo(x: Foo) { - let (i, c): (int, char) = x.a; + let (i, c): (isize, char) = x.a; assert_eq!(i, 1); assert_eq!(c, 'a'); diff --git a/src/test/run-pass/generic-derived-type.rs b/src/test/run-pass/generic-derived-type.rs index 0db03b4674..74a71873e2 100644 --- a/src/test/run-pass/generic-derived-type.rs +++ b/src/test/run-pass/generic-derived-type.rs @@ -22,7 +22,7 @@ fn f(t: T) -> Pair { } pub fn main() { - let b = f::(10); + let b = f::(10); println!("{}" ,b.a); println!("{}", b.b); assert_eq!(b.a, 10); diff --git a/src/test/run-pass/generic-exterior-unique.rs b/src/test/run-pass/generic-exterior-unique.rs index a2f7bdfd81..0e3ce3869b 100644 --- a/src/test/run-pass/generic-exterior-unique.rs +++ b/src/test/run-pass/generic-exterior-unique.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,7 +18,7 @@ struct Recbox {x: Box} fn reclift(t: T) -> Recbox { return Recbox {x: box t}; } pub fn main() { - let foo: int = 17; - let rbfoo: Recbox = reclift::(foo); + let foo: isize = 17; + let rbfoo: Recbox = reclift::(foo); assert_eq!(*rbfoo.x, foo); } diff --git a/src/test/run-pass/generic-extern-mangle.rs b/src/test/run-pass/generic-extern-mangle.rs index 6e3d19b05d..7a765703e2 100644 --- a/src/test/run-pass/generic-extern-mangle.rs +++ b/src/test/run-pass/generic-extern-mangle.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::num::Int; +// pretty-expanded FIXME #23616 -extern "C" fn foo(a: T, b: T) -> T { a + b } +#![feature(core)] + +use std::ops::Add; + +extern "C" fn foo(a: T, b: T) -> T::Output { a + b } fn main() { - assert_eq!(99u8, foo(255u8, 100u8)); - assert_eq!(99u16, foo(65535u16, 100u16)); + assert_eq!(100u8, foo(0u8, 100u8)); + assert_eq!(100u16, foo(0u16, 100u16)); } diff --git a/src/test/run-pass/generic-fn-infer.rs b/src/test/run-pass/generic-fn-infer.rs index 2f88a54e3f..e01f507372 100644 --- a/src/test/run-pass/generic-fn-infer.rs +++ b/src/test/run-pass/generic-fn-infer.rs @@ -13,6 +13,8 @@ // Issue #45: infer type parameters in function applications +// pretty-expanded FIXME #23616 + fn id(x: T) -> T { return x; } -pub fn main() { let x: int = 42; let y: int = id(x); assert!((x == y)); } +pub fn main() { let x: isize = 42; let y: isize = id(x); assert!((x == y)); } diff --git a/src/test/run-pass/generic-fn-twice.rs b/src/test/run-pass/generic-fn-twice.rs index 6b503e711e..b37c73f7f7 100644 --- a/src/test/run-pass/generic-fn-twice.rs +++ b/src/test/run-pass/generic-fn-twice.rs @@ -11,8 +11,10 @@ +// pretty-expanded FIXME #23616 + mod foomod { pub fn foo() { } } -pub fn main() { foomod::foo::(); foomod::foo::(); } +pub fn main() { foomod::foo::(); foomod::foo::(); } diff --git a/src/test/run-pass/generic-fn.rs b/src/test/run-pass/generic-fn.rs index 8da8c68084..0ba0ed4bf7 100644 --- a/src/test/run-pass/generic-fn.rs +++ b/src/test/run-pass/generic-fn.rs @@ -12,8 +12,8 @@ fn id(x: T) -> T { return x; } -#[derive(Copy)] -struct Triple {x: int, y: int, z: int} +#[derive(Copy, Clone)] +struct Triple {x: isize, y: isize, z: isize} pub fn main() { let mut x = 62; @@ -22,7 +22,7 @@ pub fn main() { let mut b = 'b'; let p: Triple = Triple {x: 65, y: 66, z: 67}; let mut q: Triple = Triple {x: 68, y: 69, z: 70}; - y = id::(x); + y = id::(x); println!("{}", y); assert_eq!(x, y); b = id::(a); diff --git a/src/test/run-pass/generic-ivec-leak.rs b/src/test/run-pass/generic-ivec-leak.rs index eb0546063f..b14a610122 100644 --- a/src/test/run-pass/generic-ivec-leak.rs +++ b/src/test/run-pass/generic-ivec-leak.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum wrapper { wrapped(T), } pub fn main() { let _w = wrapper::wrapped(vec!(1, 2, 3, 4, 5)); } diff --git a/src/test/run-pass/generic-newtype-struct.rs b/src/test/run-pass/generic-newtype-struct.rs index 4e3c820405..24b5172800 100644 --- a/src/test/run-pass/generic-newtype-struct.rs +++ b/src/test/run-pass/generic-newtype-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct S(T); pub fn main() { diff --git a/src/test/run-pass/generic-object.rs b/src/test/run-pass/generic-object.rs index 986b35cbec..44b32f62f9 100644 --- a/src/test/run-pass/generic-object.rs +++ b/src/test/run-pass/generic-object.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,17 +18,17 @@ trait Foo { } struct S { - x: int + x: isize } -impl Foo for S { - fn get(&self) -> int { +impl Foo for S { + fn get(&self) -> isize { self.x } } pub fn main() { let x = box S { x: 1 }; - let y = x as Box>; + let y = x as Box>; assert_eq!(y.get(), 1); } diff --git a/src/test/run-pass/generic-recursive-tag.rs b/src/test/run-pass/generic-recursive-tag.rs index 845375d9b8..863e0d7e33 100644 --- a/src/test/run-pass/generic-recursive-tag.rs +++ b/src/test/run-pass/generic-recursive-tag.rs @@ -16,9 +16,9 @@ enum list { cons(Box, Box>), nil, } pub fn main() { - let _a: list = - list::cons::(box 10, - box list::cons::(box 12, - box list::cons::(box 13, - box list::nil::))); + let _a: list = + list::cons::(box 10, + box list::cons::(box 12, + box list::cons::(box 13, + box list::nil::))); } diff --git a/src/test/run-pass/generic-static-methods.rs b/src/test/run-pass/generic-static-methods.rs index 7f84efcdd5..49f8d6a3ad 100644 --- a/src/test/run-pass/generic-static-methods.rs +++ b/src/test/run-pass/generic-static-methods.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait vec_utils { fn map_(x: &Self, f: F) -> Vec where F: FnMut(&T) -> U; } @@ -24,5 +26,5 @@ impl vec_utils for Vec { } pub fn main() { - assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), vec!(2,3,4)); + assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), [2,3,4]); } diff --git a/src/test/run-pass/generic-tag-corruption.rs b/src/test/run-pass/generic-tag-corruption.rs index e39957e2bf..d61ae520ad 100644 --- a/src/test/run-pass/generic-tag-corruption.rs +++ b/src/test/run-pass/generic-tag-corruption.rs @@ -12,6 +12,8 @@ // This used to cause memory corruption in stage 0. +// pretty-expanded FIXME #23616 + enum thing { some(K), } pub fn main() { let _x = thing::some("hi".to_string()); } diff --git a/src/test/run-pass/generic-tag-local.rs b/src/test/run-pass/generic-tag-local.rs index 24c31ab4ee..9518d59027 100644 --- a/src/test/run-pass/generic-tag-local.rs +++ b/src/test/run-pass/generic-tag-local.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + enum clam { a(T), } pub fn main() { let _c = clam::a(3); } diff --git a/src/test/run-pass/generic-tag-match.rs b/src/test/run-pass/generic-tag-match.rs index 64eb4e4986..830c982e13 100644 --- a/src/test/run-pass/generic-tag-match.rs +++ b/src/test/run-pass/generic-tag-match.rs @@ -18,4 +18,4 @@ fn altfoo(f: foo) { assert!((hit)); } -pub fn main() { altfoo::(foo::arm::(10)); } +pub fn main() { altfoo::(foo::arm::(10)); } diff --git a/src/test/run-pass/generic-tag-values.rs b/src/test/run-pass/generic-tag-values.rs index 6ed8558836..fef26593ea 100644 --- a/src/test/run-pass/generic-tag-values.rs +++ b/src/test/run-pass/generic-tag-values.rs @@ -10,11 +10,11 @@ enum noption { some(T), } -struct Pair { x: int, y: int } +struct Pair { x: isize, y: isize } pub fn main() { - let nop: noption = noption::some::(5); - match nop { noption::some::(n) => { println!("{}", n); assert!((n == 5)); } } + let nop: noption = noption::some::(5); + match nop { noption::some::(n) => { println!("{}", n); assert!((n == 5)); } } let nop2: noption = noption::some(Pair{x: 17, y: 42}); match nop2 { noption::some(t) => { diff --git a/src/test/run-pass/generic-tag.rs b/src/test/run-pass/generic-tag.rs index b0d4944ba5..942bdb97ba 100644 --- a/src/test/run-pass/generic-tag.rs +++ b/src/test/run-pass/generic-tag.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] #![allow(unknown_features)] @@ -16,6 +18,6 @@ enum option { some(Box), none, } pub fn main() { - let mut a: option = option::some::(box 10); - a = option::none::; + let mut a: option = option::some::(box 10); + a = option::none::; } diff --git a/src/test/run-pass/generic-temporary.rs b/src/test/run-pass/generic-temporary.rs index 3db794d88f..8b63fb94b5 100644 --- a/src/test/run-pass/generic-temporary.rs +++ b/src/test/run-pass/generic-temporary.rs @@ -9,9 +9,9 @@ // except according to those terms. -fn mk() -> int { return 1; } +fn mk() -> isize { return 1; } -fn chk(a: int) { println!("{}", a); assert!((a == 1)); } +fn chk(a: isize) { println!("{}", a); assert!((a == 1)); } fn apply(produce: fn() -> T, consume: fn(T)) { @@ -19,7 +19,7 @@ fn apply(produce: fn() -> T, } pub fn main() { - let produce: fn() -> int = mk; - let consume: fn(v: int) = chk; - apply::(produce, consume); + let produce: fn() -> isize = mk; + let consume: fn(v: isize) = chk; + apply::(produce, consume); } diff --git a/src/test/run-pass/generic-type-synonym.rs b/src/test/run-pass/generic-type-synonym.rs index a1cf581fe4..2b3bd5ead9 100644 --- a/src/test/run-pass/generic-type-synonym.rs +++ b/src/test/run-pass/generic-type-synonym.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + struct Foo { a: T } diff --git a/src/test/run-pass/generic-type.rs b/src/test/run-pass/generic-type.rs index 0ff7cedc6c..73fc3a0d80 100644 --- a/src/test/run-pass/generic-type.rs +++ b/src/test/run-pass/generic-type.rs @@ -10,10 +10,12 @@ +// pretty-expanded FIXME #23616 + struct Pair {x: T, y: T} pub fn main() { - let x: Pair = Pair {x: 10, y: 12}; + let x: Pair = Pair {x: 10, y: 12}; assert_eq!(x.x, 10); assert_eq!(x.y, 12); } diff --git a/src/test/run-pass/generic-unique.rs b/src/test/run-pass/generic-unique.rs index 1d39c47417..9cf98364eb 100644 --- a/src/test/run-pass/generic-unique.rs +++ b/src/test/run-pass/generic-unique.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,6 +18,6 @@ struct Triple { x: T, y: T, z: T } fn box_it(x: Triple) -> Box> { return box x; } pub fn main() { - let x: Box> = box_it::(Triple{x: 1, y: 2, z: 3}); + let x: Box> = box_it::(Triple{x: 1, y: 2, z: 3}); assert_eq!(x.y, 2); } diff --git a/src/test/run-pass/getopts_ref.rs b/src/test/run-pass/getopts_ref.rs index 3c89900fe4..52b06ab292 100644 --- a/src/test/run-pass/getopts_ref.rs +++ b/src/test/run-pass/getopts_ref.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + extern crate getopts; use getopts::{optopt, getopts}; diff --git a/src/test/run-pass/global-scope.rs b/src/test/run-pass/global-scope.rs index 618916e856..64d9368a88 100644 --- a/src/test/run-pass/global-scope.rs +++ b/src/test/run-pass/global-scope.rs @@ -9,10 +9,12 @@ // except according to those terms. -pub fn f() -> int { return 1; } +// pretty-expanded FIXME #23616 + +pub fn f() -> isize { return 1; } pub mod foo { - pub fn f() -> int { return 2; } + pub fn f() -> isize { return 2; } pub fn g() { assert!((f() == 2)); assert!((::f() == 1)); } } diff --git a/src/test/run-pass/guards-not-exhaustive.rs b/src/test/run-pass/guards-not-exhaustive.rs index addd6a6383..f5f8091493 100644 --- a/src/test/run-pass/guards-not-exhaustive.rs +++ b/src/test/run-pass/guards-not-exhaustive.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] -enum Q { R(Option) } +// pretty-expanded FIXME #23616 -fn xyzzy(q: Q) -> uint { +#[derive(Copy, Clone)] +enum Q { R(Option) } + +fn xyzzy(q: Q) -> usize { match q { Q::R(S) if S.is_some() => { 0 } _ => 1 diff --git a/src/test/run-pass/guards.rs b/src/test/run-pass/guards.rs index 188106ec10..11c67b8af8 100644 --- a/src/test/run-pass/guards.rs +++ b/src/test/run-pass/guards.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] -struct Pair { x: int, y: int } +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] +struct Pair { x: isize, y: isize } pub fn main() { - let a: int = + let a: isize = match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } }; assert_eq!(a, 2); - let b: int = + let b: isize = match (Pair {x: 10, y: 20}) { x if x.x < 5 && x.y < 5 => { 1 } Pair {x: x, y: y} if x == 10 && y == 20 => { 2 } diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index 677038af9a..5c96aaf4bd 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -9,8 +9,7 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, std_misc)] /** A somewhat reduced test case to expose some Valgrind issues. @@ -26,26 +25,26 @@ mod map_reduce { use std::collections::HashMap; use std::sync::mpsc::{channel, Sender}; use std::str; - use std::thread::Thread; + use std::thread; pub type putter<'a> = Box; pub type mapper = extern fn(String, putter); - enum ctrl_proto { find_reducer(Vec, Sender), mapper_done, } + enum ctrl_proto { find_reducer(Vec, Sender), mapper_done, } fn start_mappers(ctrl: Sender, inputs: Vec) { for i in &inputs { let ctrl = ctrl.clone(); let i = i.clone(); - Thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); + thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); } } fn map_task(ctrl: Sender, input: String) { let mut intermediates = HashMap::new(); - fn emit(im: &mut HashMap, + fn emit(im: &mut HashMap, ctrl: Sender, key: String, _val: String) { if im.contains_key(&key) { @@ -61,7 +60,8 @@ mod map_reduce { } let ctrl_clone = ctrl.clone(); - ::map(input, box |a,b| emit(&mut intermediates, ctrl.clone(), a, b) ); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + ::map(input, Box::new(|a,b| emit(&mut intermediates, ctrl.clone(), a, b))); ctrl_clone.send(ctrl_proto::mapper_done).unwrap(); } @@ -71,13 +71,13 @@ mod map_reduce { // This task becomes the master control task. It spawns others // to do the rest. - let mut reducers: HashMap; + let mut reducers: HashMap; reducers = HashMap::new(); start_mappers(tx, inputs.clone()); - let mut num_mappers = inputs.len() as int; + let mut num_mappers = inputs.len() as isize; while num_mappers > 0 { match rx.recv().unwrap() { diff --git a/src/test/run-pass/hrtb-binder-levels-in-object-types.rs b/src/test/run-pass/hrtb-binder-levels-in-object-types.rs index 5a793f7065..bcd519bc25 100644 --- a/src/test/run-pass/hrtb-binder-levels-in-object-types.rs +++ b/src/test/run-pass/hrtb-binder-levels-in-object-types.rs @@ -13,12 +13,14 @@ // `&Typer<'tcx>` was getting an incorrect binder level, yielding // weird compilation ICEs and so forth. +// pretty-expanded FIXME #23616 + trait Typer<'tcx> { - fn method(&self, data: &'tcx int) -> &'tcx int { data } + fn method(&self, data: &'tcx isize) -> &'tcx isize { data } } struct Tcx<'tcx> { - fields: &'tcx int + fields: &'tcx isize } impl<'tcx> Typer<'tcx> for Tcx<'tcx> { diff --git a/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs b/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs index 9e857a3324..6761cc1287 100644 --- a/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs +++ b/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Typer<'tcx> { - fn method(&self, data: &'tcx int) -> &'tcx int { data } + fn method(&self, data: &'tcx isize) -> &'tcx isize { data } fn dummy(&self) { } } diff --git a/src/test/run-pass/hrtb-fn-like-trait-object.rs b/src/test/run-pass/hrtb-fn-like-trait-object.rs index c8992afe36..858179fb5f 100644 --- a/src/test/run-pass/hrtb-fn-like-trait-object.rs +++ b/src/test/run-pass/hrtb-fn-like-trait-object.rs @@ -10,11 +10,13 @@ // A basic test of using a higher-ranked trait bound. +// pretty-expanded FIXME #23616 + trait FnLike { fn call(&self, arg: A) -> R; } -type FnObject<'b> = for<'a> FnLike<&'a int, &'a int> + 'b; +type FnObject<'b> = for<'a> FnLike<&'a isize, &'a isize> + 'b; struct Identity; diff --git a/src/test/run-pass/hrtb-fn-like-trait.rs b/src/test/run-pass/hrtb-fn-like-trait.rs index 4067b922cf..8b4c2aec84 100644 --- a/src/test/run-pass/hrtb-fn-like-trait.rs +++ b/src/test/run-pass/hrtb-fn-like-trait.rs @@ -10,6 +10,8 @@ // A basic test of using a higher-ranked trait bound. +// pretty-expanded FIXME #23616 + trait FnLike { fn call(&self, arg: A) -> R; } @@ -23,7 +25,7 @@ impl<'a, T> FnLike<&'a T, &'a T> for Identity { } fn call_repeatedly(f: F) - where F : for<'a> FnLike<&'a int, &'a int> + where F : for<'a> FnLike<&'a isize, &'a isize> { let x = 3; let y = f.call(&x); diff --git a/src/test/run-pass/hrtb-opt-in-copy.rs b/src/test/run-pass/hrtb-opt-in-copy.rs index 7b16bb867e..b40f4d27a9 100644 --- a/src/test/run-pass/hrtb-opt-in-copy.rs +++ b/src/test/run-pass/hrtb-opt-in-copy.rs @@ -16,11 +16,13 @@ // did not consider that a match (something I would like to revise in // a later PR). +// pretty-expanded FIXME #23616 + #![allow(dead_code)] use std::marker::PhantomData; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Foo { x: T } type Ty<'tcx> = &'tcx TyS<'tcx>; @@ -29,7 +31,7 @@ enum TyS<'tcx> { Boop(PhantomData<*mut &'tcx ()>) } -#[derive(Copy)] +#[derive(Copy, Clone)] enum Bar<'tcx> { Baz(Foo>) } diff --git a/src/test/run-pass/hrtb-parse.rs b/src/test/run-pass/hrtb-parse.rs index d5307c0910..ecd0bc681c 100644 --- a/src/test/run-pass/hrtb-parse.rs +++ b/src/test/run-pass/hrtb-parse.rs @@ -11,6 +11,8 @@ // Test that we can parse all the various places that a `for` keyword // can appear representing universal quantification. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] #![allow(unused_variables)] #![allow(dead_code)] diff --git a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs index 88e6de6d3e..bc00a0758f 100644 --- a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs +++ b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs @@ -8,25 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] -// Test that `F : Fn(int) -> int + Send` is interpreted as two +// Test that `F : Fn(isize) -> isize + Send` is interpreted as two // distinct bounds on `F`. fn foo1(f: F) - where F : FnOnce(int) -> int + Send + where F : FnOnce(isize) -> isize + Send { bar(f); } fn foo2(f: F) - where F : FnOnce(int) -> int + Send + where F : FnOnce(isize) -> isize + Send { baz(f); } fn bar(f: F) { } -fn baz int>(f: F) { } +fn baz isize>(f: F) { } fn main() {} diff --git a/src/test/run-pass/hrtb-precedence-of-plus.rs b/src/test/run-pass/hrtb-precedence-of-plus.rs index b59e7b67d4..892f2f1ae9 100644 --- a/src/test/run-pass/hrtb-precedence-of-plus.rs +++ b/src/test/run-pass/hrtb-precedence-of-plus.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] #![feature(unboxed_closures)] -// Test that `Fn(int) -> int + 'static` parses as `(Fn(int) -> int) + -// 'static` and not `Fn(int) -> (int + 'static)`. The latter would +// Test that `Fn(isize) -> isize + 'static` parses as `(Fn(isize) -> isize) + +// 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would // cause a compilation error. Issue #18772. -fn adder(y: int) -> Box int + 'static> { - box move |x| y + x +fn adder(y: isize) -> Box isize + 'static> { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Box::new(move |x| y + x) } fn main() {} diff --git a/src/test/run-pass/hrtb-resolve-lifetime.rs b/src/test/run-pass/hrtb-resolve-lifetime.rs index 9b37b8e49e..bdbcda8909 100644 --- a/src/test/run-pass/hrtb-resolve-lifetime.rs +++ b/src/test/run-pass/hrtb-resolve-lifetime.rs @@ -10,11 +10,13 @@ // A basic test of using a higher-ranked trait bound. +// pretty-expanded FIXME #23616 + trait FnLike { fn call(&self, arg: A) -> R; } -type FnObject<'b> = for<'a> FnLike<&'a int, &'a int> + 'b; +type FnObject<'b> = for<'a> FnLike<&'a isize, &'a isize> + 'b; fn main() { } diff --git a/src/test/run-pass/hrtb-trait-object-paren-notation.rs b/src/test/run-pass/hrtb-trait-object-paren-notation.rs index 1b62a8e809..7741f1904f 100644 --- a/src/test/run-pass/hrtb-trait-object-paren-notation.rs +++ b/src/test/run-pass/hrtb-trait-object-paren-notation.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] // A basic test of using a higher-ranked trait bound. diff --git a/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs b/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs index c90c3643d4..48d0959630 100644 --- a/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs +++ b/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs @@ -12,18 +12,20 @@ // PrinterSupport<'b>`, gets properly expanded when it appears in a // closure type. This used to result in messed up De Bruijn indices. +// pretty-expanded FIXME #23616 + trait PrinterSupport<'ast> { - fn ast_map(&self) -> Option<&'ast uint> { None } + fn ast_map(&self) -> Option<&'ast usize> { None } } struct NoAnn<'ast> { - f: Option<&'ast uint> + f: Option<&'ast usize> } impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { } -fn foo<'ast, G>(f: Option<&'ast uint>, g: G) where G: FnOnce(&PrinterSupport) { +fn foo<'ast, G>(f: Option<&'ast usize>, g: G) where G: FnOnce(&PrinterSupport) { let annotation = NoAnn { f: f }; g(&annotation) } diff --git a/src/test/run-pass/hrtb-unboxed-closure-trait.rs b/src/test/run-pass/hrtb-unboxed-closure-trait.rs index c34e1a4862..008e7ddbc9 100644 --- a/src/test/run-pass/hrtb-unboxed-closure-trait.rs +++ b/src/test/run-pass/hrtb-unboxed-closure-trait.rs @@ -12,11 +12,11 @@ #![feature(unboxed_closures)] -fn foo(f: F) { +fn foo(f: F) { let x = 22; f(&x); } fn main() { - foo(|x: &int| println!("{}", *x)); + foo(|x: &isize| println!("{}", *x)); } diff --git a/src/test/run-pass/huge-largest-array.rs b/src/test/run-pass/huge-largest-array.rs index 5083bd2320..2345bb01d8 100644 --- a/src/test/run-pass/huge-largest-array.rs +++ b/src/test/run-pass/huge-largest-array.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::size_of; #[cfg(target_pointer_width = "32")] diff --git a/src/test/run-pass/hygiene-dodging-1.rs b/src/test/run-pass/hygiene-dodging-1.rs index 3969394a26..e5acc4a2ed 100644 --- a/src/test/run-pass/hygiene-dodging-1.rs +++ b/src/test/run-pass/hygiene-dodging-1.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod x { - pub fn g() -> uint {14} + pub fn g() -> usize {14} } pub fn main(){ diff --git a/src/test/run-pass/hygienic-labels-in-let.rs b/src/test/run-pass/hygienic-labels-in-let.rs index cca0e5b163..589d6e1581 100644 --- a/src/test/run-pass/hygienic-labels-in-let.rs +++ b/src/test/run-pass/hygienic-labels-in-let.rs @@ -34,7 +34,7 @@ macro_rules! run_once { pub fn main() { let mut i = 0; - let j: int = { + let j: isize = { 'x: loop { // this 'x should refer to the outer loop, lexically loop_x!(break 'x); @@ -44,7 +44,7 @@ pub fn main() { }; assert_eq!(j, 1); - let k: int = { + let k: isize = { 'x: for _ in 0..1 { // ditto loop_x!(break 'x); @@ -54,7 +54,7 @@ pub fn main() { }; assert_eq!(k, 1); - let l: int = { + let l: isize = { 'x: for _ in 0..1 { // ditto while_true!(break 'x); @@ -64,7 +64,7 @@ pub fn main() { }; assert_eq!(l, 1); - let n: int = { + let n: isize = { 'x: for _ in 0..1 { // ditto run_once!(continue 'x); diff --git a/src/test/run-pass/hygienic-labels.rs b/src/test/run-pass/hygienic-labels.rs index 0d8da2a934..2d530275ea 100644 --- a/src/test/run-pass/hygienic-labels.rs +++ b/src/test/run-pass/hygienic-labels.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! loop_x { ($e: expr) => { // $e shouldn't be able to interact with this 'x diff --git a/src/test/run-pass/i32-sub.rs b/src/test/run-pass/i32-sub.rs index e5451431ad..2cc4e880bb 100644 --- a/src/test/run-pass/i32-sub.rs +++ b/src/test/run-pass/i32-sub.rs @@ -11,4 +11,6 @@ -pub fn main() { let mut x: i32 = -400_i32; x = 0_i32 - x; assert!((x == 400_i32)); } +// pretty-expanded FIXME #23616 + +pub fn main() { let mut x: i32 = -400; x = 0 - x; assert!((x == 400)); } diff --git a/src/test/run-pass/i8-incr.rs b/src/test/run-pass/i8-incr.rs index fbb4e446dd..5dd53a268b 100644 --- a/src/test/run-pass/i8-incr.rs +++ b/src/test/run-pass/i8-incr.rs @@ -11,10 +11,12 @@ +// pretty-expanded FIXME #23616 + pub fn main() { - let mut x: i8 = -12i8; - let y: i8 = -12i8; - x = x + 1i8; - x = x - 1i8; + let mut x: i8 = -12; + let y: i8 = -12; + x = x + 1; + x = x - 1; assert_eq!(x, y); } diff --git a/src/test/run-pass/if-bot.rs b/src/test/run-pass/if-bot.rs index 44c834d233..e66a8c8572 100644 --- a/src/test/run-pass/if-bot.rs +++ b/src/test/run-pass/if-bot.rs @@ -9,6 +9,6 @@ // except according to those terms. pub fn main() { - let i: int = if false { panic!() } else { 5 }; + let i: isize = if false { panic!() } else { 5 }; println!("{}", i); } diff --git a/src/test/run-pass/if-check.rs b/src/test/run-pass/if-check.rs index d2a1a3c71a..c72cd10a08 100644 --- a/src/test/run-pass/if-check.rs +++ b/src/test/run-pass/if-check.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn even(x: uint) -> bool { - if x < 2_usize { +fn even(x: usize) -> bool { + if x < 2 { return false; - } else if x == 2_usize { return true; } else { return even(x - 2_usize); } + } else if x == 2 { return true; } else { return even(x - 2); } } -fn foo(x: uint) { +fn foo(x: usize) { if even(x) { println!("{}", x); } else { @@ -22,4 +22,4 @@ fn foo(x: uint) { } } -pub fn main() { foo(2_usize); } +pub fn main() { foo(2); } diff --git a/src/test/run-pass/if-let.rs b/src/test/run-pass/if-let.rs index 2d2f77b099..c41d02f9b3 100644 --- a/src/test/run-pass/if-let.rs +++ b/src/test/run-pass/if-let.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = Some(3); if let Some(y) = x { @@ -20,7 +22,7 @@ pub fn main() { worked = true; } assert!(worked); - let clause: uint; + let clause: usize; if let None = Some("test") { clause = 1; } else if 4_usize > 5 { @@ -40,8 +42,8 @@ pub fn main() { enum Foo { One, - Two(uint), - Three(String, int) + Two(usize), + Three(String, isize) } let foo = Foo::Three("three".to_string(), 42); diff --git a/src/test/run-pass/if-ret.rs b/src/test/run-pass/if-ret.rs index b589c083a9..8d475a99b8 100644 --- a/src/test/run-pass/if-ret.rs +++ b/src/test/run-pass/if-ret.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo() { if (return) { } } pub fn main() { foo(); } diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index ab83fb90d3..41c859214e 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -17,6 +17,7 @@ #![feature(box_syntax)] use std::fmt; +use std::usize; struct A; struct B; @@ -137,6 +138,13 @@ pub fn main() { t!(format!("{:+10.3e}", 1.2345e6f64), " +1.234e6"); t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6"); + // Test that pointers don't get truncated. + { + let val = usize::MAX; + let exp = format!("{:#x}", val); + t!(format!("{:p}", val as *const isize), exp); + } + // Escaping t!(format!("{{"), "{"); t!(format!("}}"), "}"); @@ -146,7 +154,7 @@ pub fn main() { test_order(); // make sure that format! doesn't move out of local variables - let a = box 3; + let a: Box<_> = box 3; format!("{}", a); format!("{}", a); diff --git a/src/test/run-pass/ignore-all-the-things.rs b/src/test/run-pass/ignore-all-the-things.rs index 65fc24ae74..711f2dd6c6 100644 --- a/src/test/run-pass/ignore-all-the-things.rs +++ b/src/test/run-pass/ignore-all-the-things.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] -struct Foo(int, int, int, int); -struct Bar{a: int, b: int, c: int, d: int} +struct Foo(isize, isize, isize, isize); +struct Bar{a: isize, b: isize, c: isize, d: isize} pub fn main() { let Foo(..) = Foo(5, 5, 5, 5); diff --git a/src/test/run-pass/impl-implicit-trait.rs b/src/test/run-pass/impl-implicit-trait.rs index a33fc4f2e7..7f1d576e09 100644 --- a/src/test/run-pass/impl-implicit-trait.rs +++ b/src/test/run-pass/impl-implicit-trait.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum option_ { none_, some_(T), @@ -19,7 +21,7 @@ impl option_ { enum option__ { none__, - some__(int) + some__(isize) } impl option__ { diff --git a/src/test/run-pass/impl-inherent-non-conflict.rs b/src/test/run-pass/impl-inherent-non-conflict.rs new file mode 100644 index 0000000000..210bc34bcd --- /dev/null +++ b/src/test/run-pass/impl-inherent-non-conflict.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Ensure that an user-defined type admits multiple inherent methods +// with the same name, which can be called on values that have a +// precise enough type to allow distinguishing between the methods. + +// pretty-expanded FIXME #23616 + +struct Foo(T); + +impl Foo { + fn bar(&self) -> i32 { self.0 as i32 } +} + +impl Foo { + fn bar(&self) -> i32 { -(self.0 as i32) } +} + +fn main() { + let foo_u = Foo::(5); + assert_eq!(foo_u.bar(), 5); + + let foo_i = Foo::(3); + assert_eq!(foo_i.bar(), -3); +} diff --git a/src/test/run-pass/impl-inherent-prefer-over-trait.rs b/src/test/run-pass/impl-inherent-prefer-over-trait.rs new file mode 100644 index 0000000000..26f12e9730 --- /dev/null +++ b/src/test/run-pass/impl-inherent-prefer-over-trait.rs @@ -0,0 +1,40 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +struct Foo; + +trait Trait { + fn bar(&self); +} + +// Inherent impls should be preferred over trait ones. +impl Foo { + fn bar(&self) {} +} + +impl Trait { + fn baz(_: &Foo) {} +} + +impl Trait for Foo { + fn bar(&self) { panic!("wrong method called!") } +} + +fn main() { + Foo.bar(); + Foo::bar(&Foo); + ::bar(&Foo); + + // Should work even if Trait::baz doesn't exist. + // N.B: `::bar` would be ambiguous. + ::baz(&Foo); +} diff --git a/src/test/run-pass/impl-not-adjacent-to-type.rs b/src/test/run-pass/impl-not-adjacent-to-type.rs new file mode 100644 index 0000000000..2ba7375d67 --- /dev/null +++ b/src/test/run-pass/impl-not-adjacent-to-type.rs @@ -0,0 +1,26 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +mod foo { + pub struct Point { + pub x: i32, + pub y: i32, + } +} + +impl foo::Point { + fn x(&self) -> i32 { self.x } +} + +fn main() { + assert_eq!((foo::Point { x: 1, y: 3}).x(), 1); +} diff --git a/src/test/run-pass/impl-privacy-xc-1.rs b/src/test/run-pass/impl-privacy-xc-1.rs index d7e53f3c38..97945f4c4d 100644 --- a/src/test/run-pass/impl-privacy-xc-1.rs +++ b/src/test/run-pass/impl-privacy-xc-1.rs @@ -10,6 +10,8 @@ // aux-build:impl_privacy_xc_1.rs +// pretty-expanded FIXME #23616 + extern crate impl_privacy_xc_1; pub fn main() { diff --git a/src/test/run-pass/import-crate-with-invalid-spans.rs b/src/test/run-pass/import-crate-with-invalid-spans.rs new file mode 100644 index 0000000000..39c175f60d --- /dev/null +++ b/src/test/run-pass/import-crate-with-invalid-spans.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:crate_with_invalid_spans.rs + +// pretty-expanded FIXME #23616 + +extern crate crate_with_invalid_spans; + +fn main() { + // The AST of `exported_generic` stored in crate_with_invalid_spans's + // metadata should contain an invalid span where span.lo > span.hi. + // Let's make sure the compiler doesn't crash when encountering this. + let _ = crate_with_invalid_spans::exported_generic(32u32, 7u32); +} diff --git a/src/test/run-pass/import-from.rs b/src/test/run-pass/import-from.rs index bbf914411f..9ac35fbb38 100644 --- a/src/test/run-pass/import-from.rs +++ b/src/test/run-pass/import-from.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use spam::{ham, eggs}; mod spam { diff --git a/src/test/run-pass/import-glob-crate.rs b/src/test/run-pass/import-glob-crate.rs index f7874cc56f..eb9ec6fe98 100644 --- a/src/test/run-pass/import-glob-crate.rs +++ b/src/test/run-pass/import-glob-crate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] use std::mem::*; diff --git a/src/test/run-pass/import-in-block.rs b/src/test/run-pass/import-in-block.rs index 4567651e89..532cdbbee3 100644 --- a/src/test/run-pass/import-in-block.rs +++ b/src/test/run-pass/import-in-block.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { use std::mem::replace; let mut x = 5; diff --git a/src/test/run-pass/import-trailing-comma.rs b/src/test/run-pass/import-trailing-comma.rs index 42a90b3e39..c474485362 100644 --- a/src/test/run-pass/import-trailing-comma.rs +++ b/src/test/run-pass/import-trailing-comma.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use foo::bar::{baz, quux,}; mod foo { diff --git a/src/test/run-pass/import.rs b/src/test/run-pass/import.rs index 3470b54ccb..c2b459d288 100644 --- a/src/test/run-pass/import.rs +++ b/src/test/run-pass/import.rs @@ -9,7 +9,7 @@ // except according to those terms. mod foo { - pub fn x(y: int) { println!("{}", y); } + pub fn x(y: isize) { println!("{}", y); } } mod bar { diff --git a/src/test/run-pass/import2.rs b/src/test/run-pass/import2.rs index d684c30aca..4086acc0a8 100644 --- a/src/test/run-pass/import2.rs +++ b/src/test/run-pass/import2.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/import3.rs b/src/test/run-pass/import3.rs index 4a3358488d..2c09eff7b1 100644 --- a/src/test/run-pass/import3.rs +++ b/src/test/run-pass/import3.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/import4.rs b/src/test/run-pass/import4.rs index 44f6b6140f..229813ff55 100644 --- a/src/test/run-pass/import4.rs +++ b/src/test/run-pass/import4.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/import5.rs b/src/test/run-pass/import5.rs index 18cc1aa084..0cad094d55 100644 --- a/src/test/run-pass/import5.rs +++ b/src/test/run-pass/import5.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/import6.rs b/src/test/run-pass/import6.rs index 802dfc1f2e..545bd7cee5 100644 --- a/src/test/run-pass/import6.rs +++ b/src/test/run-pass/import6.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/import7.rs b/src/test/run-pass/import7.rs index 15e935c8f4..4b9d132895 100644 --- a/src/test/run-pass/import7.rs +++ b/src/test/run-pass/import7.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/import8.rs b/src/test/run-pass/import8.rs index 119107404d..0f3891bf06 100644 --- a/src/test/run-pass/import8.rs +++ b/src/test/run-pass/import8.rs @@ -1,4 +1,3 @@ - // 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. @@ -14,7 +13,7 @@ use foo::x; use foo::x as z; mod foo { - pub fn x(y: int) { println!("{}", y); } + pub fn x(y: isize) { println!("{}", y); } } pub fn main() { x(10); z(10); } diff --git a/src/test/run-pass/inconsistent-lifetime-mismatch.rs b/src/test/run-pass/inconsistent-lifetime-mismatch.rs index d87b59537d..9a0d8e201c 100644 --- a/src/test/run-pass/inconsistent-lifetime-mismatch.rs +++ b/src/test/run-pass/inconsistent-lifetime-mismatch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(_: &[&str]) {} fn bad(a: &str, b: &str) { diff --git a/src/test/run-pass/infer-container-across-object-cast.rs b/src/test/run-pass/infer-container-across-object-cast.rs deleted file mode 100644 index 979e76b1ff..0000000000 --- a/src/test/run-pass/infer-container-across-object-cast.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Given ` as Box`, we should be able to infer that a -// `Box<_>` is the expected type. - -trait Foo { fn foo(&self) -> u32; } -impl Foo for u32 { fn foo(&self) -> u32 { *self } } - -// (another impl to ensure trait-matching cannot just choose from a singleton set) -impl Foo for () { fn foo(&self) -> u32 { -176 } } - -trait Boxed { fn make() -> Self; } -impl Boxed for Box { fn make() -> Self { Box::new(7) } } - -// (another impl to ensure trait-matching cannot just choose from a singleton set) -impl Boxed for () { fn make() -> Self { () } } - -fn boxed_foo() { - let b7 = Boxed::make() as Box; - assert_eq!(b7.foo(), 7); -} - -trait Refed<'a,T> { fn make(&'a T) -> Self; } -impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } } - -// (another impl to ensure trait-matching cannot just choose from a singleton set) -impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } } - -fn refed_foo() { - let a = 8; - let b7 = Refed::make(&a) as &Foo; - assert_eq!(b7.foo(), 8); -} - -fn check_subtyping_works() { - fn inner<'short, 'long:'short>(_s: &'short u32, - l: &'long u32) -> &'short (Foo+'short) { - Refed::make(l) as &Foo - } - - let a = 9; - let b = 10; - let r = inner(&b, &a); - assert_eq!(r.foo(), 9); -} - -pub fn main() { - boxed_foo(); - refed_foo(); - check_subtyping_works(); -} diff --git a/src/test/run-pass/infer-fn-tail-expr.rs b/src/test/run-pass/infer-fn-tail-expr.rs index f240a5e6de..f00005fc7d 100644 --- a/src/test/run-pass/infer-fn-tail-expr.rs +++ b/src/test/run-pass/infer-fn-tail-expr.rs @@ -11,6 +11,8 @@ // issue #680 -fn f() -> Vec { Vec::new() } +// pretty-expanded FIXME #23616 + +fn f() -> Vec { Vec::new() } pub fn main() { } diff --git a/src/test/run-pass/inferred-suffix-in-pattern-range.rs b/src/test/run-pass/inferred-suffix-in-pattern-range.rs index be561dfffa..fcbd4b3323 100644 --- a/src/test/run-pass/inferred-suffix-in-pattern-range.rs +++ b/src/test/run-pass/inferred-suffix-in-pattern-range.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = 2; let x_message = match x { diff --git a/src/test/run-pass/infinite-loops.rs b/src/test/run-pass/infinite-loops.rs index e4168ea145..e8c5996f4f 100644 --- a/src/test/run-pass/infinite-loops.rs +++ b/src/test/run-pass/infinite-loops.rs @@ -14,7 +14,7 @@ */ // ignore-test -fn loopy(n: int) { +fn loopy(n: isize) { if n > 0 { spawn(move|| { loopy(n - 1) }); spawn(move|| { loopy(n - 1) }); } loop { } } diff --git a/src/test/run-pass/inherent-trait-method-order.rs b/src/test/run-pass/inherent-trait-method-order.rs index 6643636c57..042268435c 100644 --- a/src/test/run-pass/inherent-trait-method-order.rs +++ b/src/test/run-pass/inherent-trait-method-order.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo; impl Foo { @@ -31,4 +33,3 @@ fn main() { let x = &(&(&Foo)); x.foo(); } - diff --git a/src/test/run-pass/init-large-type.rs b/src/test/run-pass/init-large-type.rs index 8ee6054f8b..26d58d34b9 100644 --- a/src/test/run-pass/init-large-type.rs +++ b/src/test/run-pass/init-large-type.rs @@ -12,9 +12,11 @@ // Doing it incorrectly causes massive slowdown in LLVM during // optimisation. -#![feature(intrinsics)] +// pretty-expanded FIXME #23616 -use std::thread::Thread; +#![feature(intrinsics, std_misc)] + +use std::thread; extern "rust-intrinsic" { pub fn init() -> T; @@ -24,7 +26,7 @@ const SIZE: usize = 1024 * 1024; fn main() { // do the test in a new thread to avoid (spurious?) stack overflows - let _ = Thread::scoped(|| { + let _ = thread::scoped(|| { let _memory: [u8; SIZE] = unsafe { init() }; }).join(); } diff --git a/src/test/run-pass/init-res-into-things.rs b/src/test/run-pass/init-res-into-things.rs index ee793359fb..eb50fbed77 100644 --- a/src/test/run-pass/init-res-into-things.rs +++ b/src/test/run-pass/init-res-into-things.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #![feature(unsafe_destructor)] @@ -18,7 +20,7 @@ use std::cell::Cell; // as a move unless the stored thing is used afterwards. struct r<'a> { - i: &'a Cell, + i: &'a Cell, } struct BoxR<'a> { x: r<'a> } @@ -30,7 +32,7 @@ impl<'a> Drop for r<'a> { } } -fn r(i: &Cell) -> r { +fn r(i: &Cell) -> r { r { i: i } @@ -67,7 +69,7 @@ fn test_tup() { fn test_unique() { let i = &Cell::new(0); { - let _a = box r(i); + let _a: Box<_> = box r(i); } assert_eq!(i.get(), 1); } @@ -75,7 +77,7 @@ fn test_unique() { fn test_unique_rec() { let i = &Cell::new(0); { - let _a = box BoxR { + let _a: Box<_> = box BoxR { x: r(i) }; } diff --git a/src/test/run-pass/inner-attrs-on-impl.rs b/src/test/run-pass/inner-attrs-on-impl.rs index afb2b21b04..a807e582ff 100644 --- a/src/test/run-pass/inner-attrs-on-impl.rs +++ b/src/test/run-pass/inner-attrs-on-impl.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo; impl Foo { diff --git a/src/test/run-pass/inner-static.rs b/src/test/run-pass/inner-static.rs index e4026a8fd0..48f2006ed5 100644 --- a/src/test/run-pass/inner-static.rs +++ b/src/test/run-pass/inner-static.rs @@ -10,6 +10,8 @@ // aux-build:inner_static.rs +// pretty-expanded FIXME #23616 + extern crate inner_static; pub fn main() { diff --git a/src/test/run-pass/instantiable.rs b/src/test/run-pass/instantiable.rs index 35897d5b82..28fba70eb2 100644 --- a/src/test/run-pass/instantiable.rs +++ b/src/test/run-pass/instantiable.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ptr; // check that we do not report a type like this as uninstantiable, // even though it would be if the nxt field had type @foo: struct foo(X); -struct X { x: uint, nxt: *const foo } +struct X { x: usize, nxt: *const foo } pub fn main() { let _x = foo(X {x: 0, nxt: ptr::null()}); diff --git a/src/test/run-pass/int.rs b/src/test/run-pass/int.rs index 169be05428..9495552af4 100644 --- a/src/test/run-pass/int.rs +++ b/src/test/run-pass/int.rs @@ -11,4 +11,6 @@ -pub fn main() { let _x: int = 10; } +// pretty-expanded FIXME #23616 + +pub fn main() { let _x: isize = 10; } diff --git a/src/test/run-pass/integer-literal-radix.rs b/src/test/run-pass/integer-literal-radix.rs index ea8825d22d..b782925fa9 100644 --- a/src/test/run-pass/integer-literal-radix.rs +++ b/src/test/run-pass/integer-literal-radix.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let a = 0xBEEF_isize; let b = 0o755_isize; diff --git a/src/test/run-pass/integer-literal-suffix-inference-2.rs b/src/test/run-pass/integer-literal-suffix-inference-2.rs index 05973a545a..e953cf2fda 100644 --- a/src/test/run-pass/integer-literal-suffix-inference-2.rs +++ b/src/test/run-pass/integer-literal-suffix-inference-2.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(_: *const ()) {} fn main() { let a = 3; foo(&a as *const _ as *const ()); } - diff --git a/src/test/run-pass/integer-literal-suffix-inference-3.rs b/src/test/run-pass/integer-literal-suffix-inference-3.rs index 05b275a0d8..31aca964de 100644 --- a/src/test/run-pass/integer-literal-suffix-inference-3.rs +++ b/src/test/run-pass/integer-literal-suffix-inference-3.rs @@ -11,4 +11,3 @@ fn main() { println!("{}", std::mem::size_of_val(&1)); } - diff --git a/src/test/run-pass/integer-literal-suffix-inference.rs b/src/test/run-pass/integer-literal-suffix-inference.rs index 542efe3345..57f80bb14e 100644 --- a/src/test/run-pass/integer-literal-suffix-inference.rs +++ b/src/test/run-pass/integer-literal-suffix-inference.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { fn id_i8(n: i8) -> i8 { n } fn id_i16(n: i16) -> i16 { n } fn id_i32(n: i32) -> i32 { n } fn id_i64(n: i64) -> i64 { n } - fn id_uint(n: uint) -> uint { n } + fn id_uint(n: usize) -> usize { n } fn id_u8(n: u8) -> u8 { n } fn id_u16(n: u16) -> u16 { n } fn id_u32(n: u32) -> u32 { n } @@ -40,7 +42,7 @@ pub fn main() { id_i64(j); id_i64(-9_223_372_036_854_775_808); - let _i: uint = 1; + let _i: usize = 1; let j = 1; id_uint(j); id_uint(1); diff --git a/src/test/run-pass/into-iterator-type-inference-shift.rs b/src/test/run-pass/into-iterator-type-inference-shift.rs index 26a0abc76a..9ccf1c3bbb 100644 --- a/src/test/run-pass/into-iterator-type-inference-shift.rs +++ b/src/test/run-pass/into-iterator-type-inference-shift.rs @@ -9,10 +9,14 @@ // except according to those terms. // Regression test for type inference failure around shifting. In this -// case, the iteration yields an int, but we hadn't run the full type +// case, the iteration yields an isize, but we hadn't run the full type // propagation yet, and so we just saw a type variable, yielding an // error. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::u8; trait IntoIterator { @@ -31,7 +35,7 @@ impl IntoIterator for I where I: Iterator { fn desugared_for_loop_bad(byte: u8) -> u8 { let mut result = 0; - let mut x = IntoIterator::into_iter(range(0, u8::BITS)); + let mut x = IntoIterator::into_iter(0..u8::BITS); let mut y = Iterator::next(&mut x); let mut z = y.unwrap(); byte >> z; diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index f852bac404..44dd191eb3 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(intrinsics, main)] mod rusti { extern "rust-intrinsic" { - pub fn pref_align_of() -> uint; - pub fn min_align_of() -> uint; + pub fn pref_align_of() -> usize; + pub fn min_align_of() -> usize; } } @@ -27,8 +29,8 @@ mod m { #[cfg(target_arch = "x86")] pub fn main() { unsafe { - assert_eq!(::rusti::pref_align_of::(), 8_usize); - assert_eq!(::rusti::min_align_of::(), 4_usize); + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 4); } } @@ -36,8 +38,20 @@ mod m { #[cfg(any(target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))] pub fn main() { unsafe { - assert_eq!(::rusti::pref_align_of::(), 8_usize); - assert_eq!(::rusti::min_align_of::(), 8_usize); + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); + } + } +} + +#[cfg(target_os = "bitrig")] +mod m { + #[main] + #[cfg(target_arch = "x86_64")] + pub fn main() { + unsafe { + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); } } } @@ -48,8 +62,8 @@ mod m { #[cfg(target_arch = "x86")] pub fn main() { unsafe { - assert_eq!(::rusti::pref_align_of::(), 8_usize); - assert_eq!(::rusti::min_align_of::(), 8_usize); + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); } } @@ -57,8 +71,8 @@ mod m { #[cfg(target_arch = "x86_64")] pub fn main() { unsafe { - assert_eq!(::rusti::pref_align_of::(), 8_usize); - assert_eq!(::rusti::min_align_of::(), 8_usize); + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); } } } @@ -69,8 +83,8 @@ mod m { #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] pub fn main() { unsafe { - assert_eq!(::rusti::pref_align_of::(), 8_usize); - assert_eq!(::rusti::min_align_of::(), 8_usize); + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); } } } diff --git a/src/test/run-pass/intrinsic-assume.rs b/src/test/run-pass/intrinsic-assume.rs index abf9b94c59..fc886d7e30 100644 --- a/src/test/run-pass/intrinsic-assume.rs +++ b/src/test/run-pass/intrinsic-assume.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::intrinsics::assume; unsafe fn f(x: i32) -> i32 { @@ -22,4 +26,3 @@ fn main() { let x = unsafe { f(34) }; assert_eq!(x, 42); } - diff --git a/src/test/run-pass/intrinsic-atomics-cc.rs b/src/test/run-pass/intrinsic-atomics-cc.rs index e6a81dbe5d..c5fe02b919 100644 --- a/src/test/run-pass/intrinsic-atomics-cc.rs +++ b/src/test/run-pass/intrinsic-atomics-cc.rs @@ -10,6 +10,8 @@ // aux-build:cci_intrinsic.rs +// pretty-expanded FIXME #23616 + extern crate cci_intrinsic; use cci_intrinsic::atomic_xchg; diff --git a/src/test/run-pass/intrinsic-atomics.rs b/src/test/run-pass/intrinsic-atomics.rs index d3f62f9d04..61a9f6109a 100644 --- a/src/test/run-pass/intrinsic-atomics.rs +++ b/src/test/run-pass/intrinsic-atomics.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #![feature(intrinsics)] @@ -40,7 +42,7 @@ mod rusti { pub fn main() { unsafe { - let mut x = box 1; + let mut x: Box<_> = box 1; assert_eq!(rusti::atomic_load(&*x), 1); *x = 5; diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index 0daf661c2f..98f069f77f 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #![feature(intrinsics)] +// needed to check for drop fill word. +#![feature(filling_drop)] -use std::mem::transmute; +use std::mem::{self, transmute}; mod rusti { extern "rust-intrinsic" { @@ -23,11 +27,12 @@ mod rusti { pub fn main() { unsafe { - let x = box 1; + let x: Box<_> = box 1; let mut y = rusti::init(); - let mut z: *const uint = transmute(&x); + let mut z: *const usize = transmute(&x); rusti::move_val_init(&mut y, x); assert_eq!(*y, 1); - assert_eq!(*z, 0); // `x` is nulled out, not directly visible + // `x` is nulled out, not directly visible + assert_eq!(*z, mem::POST_DROP_USIZE); } } diff --git a/src/test/run-pass/intrinsic-return-address.rs b/src/test/run-pass/intrinsic-return-address.rs index 91af669340..1ff910356e 100644 --- a/src/test/run-pass/intrinsic-return-address.rs +++ b/src/test/run-pass/intrinsic-return-address.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(intrinsics)] use std::ptr; @@ -22,9 +24,9 @@ extern "rust-intrinsic" { fn return_address() -> *const u8; } -fn f(result: &mut uint) -> Point { +fn f(result: &mut usize) -> Point { unsafe { - *result = return_address() as uint; + *result = return_address() as usize; Point { x: 1.0, y: 2.0, @@ -37,7 +39,6 @@ fn f(result: &mut uint) -> Point { fn main() { let mut intrinsic_reported_address = 0; let pt = f(&mut intrinsic_reported_address); - let actual_address = &pt as *const Point as uint; + let actual_address = &pt as *const Point as usize; assert_eq!(intrinsic_reported_address, actual_address); } - diff --git a/src/test/run-pass/intrinsic-uninit.rs b/src/test/run-pass/intrinsic-uninit.rs index 34fd8effd4..3d2c1ec5c1 100644 --- a/src/test/run-pass/intrinsic-uninit.rs +++ b/src/test/run-pass/intrinsic-uninit.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(intrinsics)] mod rusti { @@ -16,5 +18,5 @@ mod rusti { } } pub fn main() { - let _a : int = unsafe {rusti::uninit()}; + let _a : isize = unsafe {rusti::uninit()}; } diff --git a/src/test/run-pass/intrinsic-unreachable.rs b/src/test/run-pass/intrinsic-unreachable.rs index 5e8b758cdf..86a370a094 100644 --- a/src/test/run-pass/intrinsic-unreachable.rs +++ b/src/test/run-pass/intrinsic-unreachable.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::intrinsics; // See also src/test/run-make/intrinsic-unreachable. -unsafe fn f(x: uint) -> uint { +unsafe fn f(x: usize) -> usize { match x { 17 => 23, _ => intrinsics::unreachable(), diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 2b0f7cc7d7..15dbe796ef 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(negate_unsigned)] #![feature(intrinsics)] mod rusti { @@ -37,83 +40,83 @@ pub fn main() { unsafe { use rusti::*; - assert_eq!(ctpop8(0u8), 0u8); - assert_eq!(ctpop16(0u16), 0u16); - assert_eq!(ctpop32(0u32), 0u32); - assert_eq!(ctpop64(0u64), 0u64); - - assert_eq!(ctpop8(1u8), 1u8); - assert_eq!(ctpop16(1u16), 1u16); - assert_eq!(ctpop32(1u32), 1u32); - assert_eq!(ctpop64(1u64), 1u64); - - assert_eq!(ctpop8(10u8), 2u8); - assert_eq!(ctpop16(10u16), 2u16); - assert_eq!(ctpop32(10u32), 2u32); - assert_eq!(ctpop64(10u64), 2u64); - - assert_eq!(ctpop8(100u8), 3u8); - assert_eq!(ctpop16(100u16), 3u16); - assert_eq!(ctpop32(100u32), 3u32); - assert_eq!(ctpop64(100u64), 3u64); - - assert_eq!(ctpop8(-1u8), 8u8); - assert_eq!(ctpop16(-1u16), 16u16); - assert_eq!(ctpop32(-1u32), 32u32); - assert_eq!(ctpop64(-1u64), 64u64); - - assert_eq!(ctlz8(0u8), 8u8); - assert_eq!(ctlz16(0u16), 16u16); - assert_eq!(ctlz32(0u32), 32u32); - assert_eq!(ctlz64(0u64), 64u64); - - assert_eq!(ctlz8(1u8), 7u8); - assert_eq!(ctlz16(1u16), 15u16); - assert_eq!(ctlz32(1u32), 31u32); - assert_eq!(ctlz64(1u64), 63u64); - - assert_eq!(ctlz8(10u8), 4u8); - assert_eq!(ctlz16(10u16), 12u16); - assert_eq!(ctlz32(10u32), 28u32); - assert_eq!(ctlz64(10u64), 60u64); - - assert_eq!(ctlz8(100u8), 1u8); - assert_eq!(ctlz16(100u16), 9u16); - assert_eq!(ctlz32(100u32), 25u32); - assert_eq!(ctlz64(100u64), 57u64); - - assert_eq!(cttz8(-1u8), 0u8); - assert_eq!(cttz16(-1u16), 0u16); - assert_eq!(cttz32(-1u32), 0u32); - assert_eq!(cttz64(-1u64), 0u64); - - assert_eq!(cttz8(0u8), 8u8); - assert_eq!(cttz16(0u16), 16u16); - assert_eq!(cttz32(0u32), 32u32); - assert_eq!(cttz64(0u64), 64u64); - - assert_eq!(cttz8(1u8), 0u8); - assert_eq!(cttz16(1u16), 0u16); - assert_eq!(cttz32(1u32), 0u32); - assert_eq!(cttz64(1u64), 0u64); - - assert_eq!(cttz8(10u8), 1u8); - assert_eq!(cttz16(10u16), 1u16); - assert_eq!(cttz32(10u32), 1u32); - assert_eq!(cttz64(10u64), 1u64); - - assert_eq!(cttz8(100u8), 2u8); - assert_eq!(cttz16(100u16), 2u16); - assert_eq!(cttz32(100u32), 2u32); - assert_eq!(cttz64(100u64), 2u64); - - assert_eq!(cttz8(-1u8), 0u8); - assert_eq!(cttz16(-1u16), 0u16); - assert_eq!(cttz32(-1u32), 0u32); - assert_eq!(cttz64(-1u64), 0u64); - - assert_eq!(bswap16(0x0A0Bu16), 0x0B0Au16); - assert_eq!(bswap32(0x0ABBCC0Du32), 0x0DCCBB0Au32); - assert_eq!(bswap64(0x0122334455667708u64), 0x0877665544332201u64); + assert_eq!(ctpop8(0), 0); + assert_eq!(ctpop16(0), 0); + assert_eq!(ctpop32(0), 0); + assert_eq!(ctpop64(0), 0); + + assert_eq!(ctpop8(1), 1); + assert_eq!(ctpop16(1), 1); + assert_eq!(ctpop32(1), 1); + assert_eq!(ctpop64(1), 1); + + assert_eq!(ctpop8(10), 2); + assert_eq!(ctpop16(10), 2); + assert_eq!(ctpop32(10), 2); + assert_eq!(ctpop64(10), 2); + + assert_eq!(ctpop8(100), 3); + assert_eq!(ctpop16(100), 3); + assert_eq!(ctpop32(100), 3); + assert_eq!(ctpop64(100), 3); + + assert_eq!(ctpop8(-1), 8); + assert_eq!(ctpop16(-1), 16); + assert_eq!(ctpop32(-1), 32); + assert_eq!(ctpop64(-1), 64); + + assert_eq!(ctlz8(0), 8); + assert_eq!(ctlz16(0), 16); + assert_eq!(ctlz32(0), 32); + assert_eq!(ctlz64(0), 64); + + assert_eq!(ctlz8(1), 7); + assert_eq!(ctlz16(1), 15); + assert_eq!(ctlz32(1), 31); + assert_eq!(ctlz64(1), 63); + + assert_eq!(ctlz8(10), 4); + assert_eq!(ctlz16(10), 12); + assert_eq!(ctlz32(10), 28); + assert_eq!(ctlz64(10), 60); + + assert_eq!(ctlz8(100), 1); + assert_eq!(ctlz16(100), 9); + assert_eq!(ctlz32(100), 25); + assert_eq!(ctlz64(100), 57); + + assert_eq!(cttz8(-1), 0); + assert_eq!(cttz16(-1), 0); + assert_eq!(cttz32(-1), 0); + assert_eq!(cttz64(-1), 0); + + assert_eq!(cttz8(0), 8); + assert_eq!(cttz16(0), 16); + assert_eq!(cttz32(0), 32); + assert_eq!(cttz64(0), 64); + + assert_eq!(cttz8(1), 0); + assert_eq!(cttz16(1), 0); + assert_eq!(cttz32(1), 0); + assert_eq!(cttz64(1), 0); + + assert_eq!(cttz8(10), 1); + assert_eq!(cttz16(10), 1); + assert_eq!(cttz32(10), 1); + assert_eq!(cttz64(10), 1); + + assert_eq!(cttz8(100), 2); + assert_eq!(cttz16(100), 2); + assert_eq!(cttz32(100), 2); + assert_eq!(cttz64(100), 2); + + assert_eq!(cttz8(-1), 0); + assert_eq!(cttz16(-1), 0); + assert_eq!(cttz32(-1), 0); + assert_eq!(cttz64(-1), 0); + + assert_eq!(bswap16(0x0A0B), 0x0B0A); + assert_eq!(bswap32(0x0ABBCC0D), 0x0DCCBB0A); + assert_eq!(bswap64(0x0122334455667708), 0x0877665544332201); } } diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index ed88b3c65e..841ff297a2 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(intrinsics)] +// pretty-expanded FIXME #23616 + +#![feature(intrinsics, core)] macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ @@ -65,8 +66,8 @@ pub fn main() { assert_approx_eq!(sqrtf32(64f32), 8f32); assert_approx_eq!(sqrtf64(64f64), 8f64); - assert_approx_eq!(powif32(25f32, -2i32), 0.0016f32); - assert_approx_eq!(powif64(23.2f64, 2i32), 538.24f64); + assert_approx_eq!(powif32(25f32, -2), 0.0016f32); + assert_approx_eq!(powif64(23.2f64, 2), 538.24f64); assert_approx_eq!(sinf32(0f32), 0f32); assert_approx_eq!(sinf64(f64::consts::PI / 2f64), 1f64); diff --git a/src/test/run-pass/invoke-external-foreign.rs b/src/test/run-pass/invoke-external-foreign.rs index ef5ef2f215..1aae8131d8 100644 --- a/src/test/run-pass/invoke-external-foreign.rs +++ b/src/test/run-pass/invoke-external-foreign.rs @@ -14,6 +14,8 @@ // successfully (and safely) invoke external, cdecl // functions from outside the crate. +// pretty-expanded FIXME #23616 + extern crate foreign_lib; pub fn main() { diff --git a/src/test/run-pass/irrefutable-unit.rs b/src/test/run-pass/irrefutable-unit.rs index 51adeea394..0c2fbb01f4 100644 --- a/src/test/run-pass/irrefutable-unit.rs +++ b/src/test/run-pass/irrefutable-unit.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let ((),()) = ((),()); } diff --git a/src/test/run-pass/issue-10025.rs b/src/test/run-pass/issue-10025.rs index 8f494ea81f..1ca2476a10 100644 --- a/src/test/run-pass/issue-10025.rs +++ b/src/test/run-pass/issue-10025.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + unsafe extern fn foo() {} unsafe extern "C" fn bar() {} diff --git a/src/test/run-pass/issue-10028.rs b/src/test/run-pass/issue-10028.rs index 826c23a782..53d6f67f11 100644 --- a/src/test/run-pass/issue-10028.rs +++ b/src/test/run-pass/issue-10028.rs @@ -10,7 +10,9 @@ // aux-build:issue-10028.rs -extern crate "issue-10028" as issue10028; +// pretty-expanded FIXME #23616 + +extern crate issue_10028 as issue10028; use issue10028::ZeroLengthThingWithDestructor; diff --git a/src/test/run-pass/issue-10031.rs b/src/test/run-pass/issue-10031.rs index a94ed4ed5b..4dc1487b9a 100644 --- a/src/test/run-pass/issue-10031.rs +++ b/src/test/run-pass/issue-10031.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:issue_10031_aux.rs +// pretty-expanded FIXME #23616 + extern crate issue_10031_aux; pub fn main() { diff --git a/src/test/run-pass/issue-10228.rs b/src/test/run-pass/issue-10228.rs index 52b6677428..b5c97bd10e 100644 --- a/src/test/run-pass/issue-10228.rs +++ b/src/test/run-pass/issue-10228.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum StdioContainer { CreatePipe(bool) } diff --git a/src/test/run-pass/issue-10392.rs b/src/test/run-pass/issue-10392.rs index 1aa9c96de1..2d695c75d3 100644 --- a/src/test/run-pass/issue-10392.rs +++ b/src/test/run-pass/issue-10392.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct A { foo: int } -struct B { a: int, b: int, c: int } +// pretty-expanded FIXME #23616 + +struct A { foo: isize } +struct B { a: isize, b: isize, c: isize } fn mka() -> A { panic!() } fn mkb() -> B { panic!() } diff --git a/src/test/run-pass/issue-10456.rs b/src/test/run-pass/issue-10456.rs index da73c4b27a..10b4162305 100644 --- a/src/test/run-pass/issue-10456.rs +++ b/src/test/run-pass/issue-10456.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct Foo; pub trait Bar { diff --git a/src/test/run-pass/issue-10626.rs b/src/test/run-pass/issue-10626.rs index 29e4801d0a..2c0811b69e 100644 --- a/src/test/run-pass/issue-10626.rs +++ b/src/test/run-pass/issue-10626.rs @@ -12,6 +12,8 @@ // Make sure that if a process doesn't have its stdio/stderr descriptors set up // that we don't die in a large ball of fire +#![feature(old_io)] + use std::env; use std::old_io::process; diff --git a/src/test/run-pass/issue-10638.rs b/src/test/run-pass/issue-10638.rs index bc77b4c534..379bdffbbb 100644 --- a/src/test/run-pass/issue-10638.rs +++ b/src/test/run-pass/issue-10638.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { //// I am not a doc comment! ////////////////// still not a doc comment diff --git a/src/test/run-pass/issue-10682.rs b/src/test/run-pass/issue-10682.rs index 883e52b61d..c049bdfe83 100644 --- a/src/test/run-pass/issue-10682.rs +++ b/src/test/run-pass/issue-10682.rs @@ -11,10 +11,12 @@ // Regression test for issue #10682 // Nested `proc` usage can't use outer owned data +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn work(_: Box) {} +fn work(_: Box) {} fn foo(_: F) {} pub fn main() { diff --git a/src/test/run-pass/issue-10683.rs b/src/test/run-pass/issue-10683.rs index a01d2e6f1a..eb2177202a 100644 --- a/src/test/run-pass/issue-10683.rs +++ b/src/test/run-pass/issue-10683.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ascii::AsciiExt; static NAME: &'static str = "hello world"; diff --git a/src/test/run-pass/issue-10714.rs b/src/test/run-pass/issue-10714.rs index 90e87f96f7..795ad8fb35 100644 --- a/src/test/run-pass/issue-10714.rs +++ b/src/test/run-pass/issue-10714.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum v {} pub fn main() { let y: v = unsafe { ::std::mem::uninitialized() }; diff --git a/src/test/run-pass/issue-10718.rs b/src/test/run-pass/issue-10718.rs index c3ec3fc40e..0a6e454e18 100644 --- a/src/test/run-pass/issue-10718.rs +++ b/src/test/run-pass/issue-10718.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn f(p: F) { diff --git a/src/test/run-pass/issue-10734.rs b/src/test/run-pass/issue-10734.rs index a6af2327c9..49694f2755 100644 --- a/src/test/run-pass/issue-10734.rs +++ b/src/test/run-pass/issue-10734.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_no_drop_flag)] -static mut drop_count: uint = 0; +static mut drop_count: usize = 0; #[unsafe_no_drop_flag] struct Foo { diff --git a/src/test/run-pass/issue-10763.rs b/src/test/run-pass/issue-10763.rs index 92ea6026ff..3789b93ad7 100644 --- a/src/test/run-pass/issue-10763.rs +++ b/src/test/run-pass/issue-10763.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern "Rust" fn foo() {} fn main() {} diff --git a/src/test/run-pass/issue-10764.rs b/src/test/run-pass/issue-10764.rs index f824b5fd4d..cfabf699fa 100644 --- a/src/test/run-pass/issue-10764.rs +++ b/src/test/run-pass/issue-10764.rs @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + extern "Rust" fn main() {} diff --git a/src/test/run-pass/issue-10767.rs b/src/test/run-pass/issue-10767.rs index c717053cff..9d680d1962 100644 --- a/src/test/run-pass/issue-10767.rs +++ b/src/test/run-pass/issue-10767.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/issue-10802.rs b/src/test/run-pass/issue-10802.rs index 174a69e113..bb32263509 100644 --- a/src/test/run-pass/issue-10802.rs +++ b/src/test/run-pass/issue-10802.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -42,13 +44,13 @@ impl Whatever { fn main() { { - let f = box DroppableStruct; + let f: Box<_> = box DroppableStruct; let _a = Whatever::new(box f as Box); } assert!(unsafe { DROPPED }); unsafe { DROPPED = false; } { - let f = box DroppableEnum::DroppableVariant1; + let f: Box<_> = box DroppableEnum::DroppableVariant1; let _a = Whatever::new(box f as Box); } assert!(unsafe { DROPPED }); diff --git a/src/test/run-pass/issue-10806.rs b/src/test/run-pass/issue-10806.rs index 69a23e8099..49883f15d3 100644 --- a/src/test/run-pass/issue-10806.rs +++ b/src/test/run-pass/issue-10806.rs @@ -9,30 +9,32 @@ // except according to those terms. -pub fn foo() -> int { +// pretty-expanded FIXME #23616 + +pub fn foo() -> isize { 3 } -pub fn bar() -> int { +pub fn bar() -> isize { 4 } pub mod baz { use {foo, bar}; - pub fn quux() -> int { + pub fn quux() -> isize { foo() + bar() } } pub mod grault { use {foo}; - pub fn garply() -> int { + pub fn garply() -> isize { foo() } } pub mod waldo { use {}; - pub fn plugh() -> int { + pub fn plugh() -> isize { 0 } } diff --git a/src/test/run-pass/issue-10853.rs b/src/test/run-pass/issue-10853.rs index 1717075885..2e6d278037 100644 --- a/src/test/run-pass/issue-10853.rs +++ b/src/test/run-pass/issue-10853.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![deny(missing_docs)] #![doc="module"] diff --git a/src/test/run-pass/issue-10902.rs b/src/test/run-pass/issue-10902.rs index 7fab6662ee..9f0417a8be 100644 --- a/src/test/run-pass/issue-10902.rs +++ b/src/test/run-pass/issue-10902.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub mod two_tuple { pub trait T { fn dummy(&self) { } } pub struct P<'a>(&'a (T + 'a), &'a (T + 'a)); diff --git a/src/test/run-pass/issue-11085.rs b/src/test/run-pass/issue-11085.rs index 9440e0c287..c024c6297b 100644 --- a/src/test/run-pass/issue-11085.rs +++ b/src/test/run-pass/issue-11085.rs @@ -10,15 +10,17 @@ // compile-flags: --cfg foo +// pretty-expanded FIXME #23616 + struct Foo { #[cfg(fail)] bar: baz, - foo: int, + foo: isize, } struct Foo2 { #[cfg(foo)] - foo: int, + foo: isize, } enum Bar1 { @@ -35,8 +37,8 @@ enum Bar2 { enum Bar3 { Bar3_1 { #[cfg(fail)] - foo: int, - bar: int, + foo: isize, + bar: isize, } } diff --git a/src/test/run-pass/issue-1112.rs b/src/test/run-pass/issue-1112.rs index 22c88c874f..3d131b5103 100644 --- a/src/test/run-pass/issue-1112.rs +++ b/src/test/run-pass/issue-1112.rs @@ -11,6 +11,8 @@ // Issue #1112 // Alignment of interior pointers to dynamic-size types +// pretty-expanded FIXME #23616 + struct X { a: T, b: u8, @@ -22,23 +24,23 @@ struct X { } pub fn main() { - let x: X = X { + let x: X = X { a: 12345678, - b: 9u8, + b: 9, c: true, - d: 10u8, - e: 11u16, - f: 12u8, - g: 13u8 + d: 10, + e: 11, + f: 12, + g: 13 }; bar(x); } fn bar(x: X) { - assert_eq!(x.b, 9u8); + assert_eq!(x.b, 9); assert_eq!(x.c, true); - assert_eq!(x.d, 10u8); - assert_eq!(x.e, 11u16); - assert_eq!(x.f, 12u8); - assert_eq!(x.g, 13u8); + assert_eq!(x.d, 10); + assert_eq!(x.e, 11); + assert_eq!(x.f, 12); + assert_eq!(x.g, 13); } diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs index 1325b51a54..41b54727b6 100644 --- a/src/test/run-pass/issue-11205.rs +++ b/src/test/run-pass/issue-11205.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] -#![allow(unknown_features)] -#![feature(box_syntax)] + +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. trait Foo { fn dummy(&self) { } } -impl Foo for int {} +impl Foo for isize {} fn foo(_: [&Foo; 2]) {} fn foos(_: &[&Foo]) {} fn foog(_: &[T], _: &[T]) {} @@ -39,16 +41,16 @@ fn main() { let r = &1; foog(x, &[r]); - let x: [Box; 2] = [box 1, box 2]; + let x: [Box; 2] = [Box::new(1), Box::new(2)]; bar(x); - bar([box 1, box 2]); + bar([Box::new(1), Box::new(2)]); - let x: &[Box] = &[box 1, box 2]; + let x: &[Box] = &[Box::new(1), Box::new(2)]; bars(x); - bars(&[box 1, box 2]); + bars(&[Box::new(1), Box::new(2)]); - let x: &[Box] = &[box 1, box 2]; - foog(x, &[box 1]); + let x: &[Box] = &[Box::new(1), Box::new(2)]; + foog(x, &[Box::new(1)]); struct T<'a> { t: [&'a (Foo+'a); 2] @@ -85,9 +87,9 @@ fn main() { t: &'a [Box] } let _n = M { - t: &[box 1, box 2] + t: &[Box::new(1), Box::new(2)] }; - let x: [Box; 2] = [box 1, box 2]; + let x: [Box; 2] = [Box::new(1), Box::new(2)]; let _n = M { t: &x }; diff --git a/src/test/run-pass/issue-11224.rs b/src/test/run-pass/issue-11224.rs index 02c82d9c94..14017ee178 100644 --- a/src/test/run-pass/issue-11224.rs +++ b/src/test/run-pass/issue-11224.rs @@ -10,6 +10,8 @@ // aux-build:issue-11224.rs -extern crate "issue-11224" as unused; +// pretty-expanded FIXME #23616 + +extern crate issue_11224 as unused; pub fn main() {} diff --git a/src/test/run-pass/issue-11225-1.rs b/src/test/run-pass/issue-11225-1.rs index a45d129ade..a74fdbe3de 100644 --- a/src/test/run-pass/issue-11225-1.rs +++ b/src/test/run-pass/issue-11225-1.rs @@ -10,7 +10,9 @@ // aux-build:issue-11225-1.rs -extern crate "issue-11225-1" as foo; +// pretty-expanded FIXME #23616 + +extern crate issue_11225_1 as foo; pub fn main() { foo::foo(1); diff --git a/src/test/run-pass/issue-11225-2.rs b/src/test/run-pass/issue-11225-2.rs index f07957b30e..c6fc5e8b48 100644 --- a/src/test/run-pass/issue-11225-2.rs +++ b/src/test/run-pass/issue-11225-2.rs @@ -10,7 +10,9 @@ // aux-build:issue-11225-2.rs -extern crate "issue-11225-2" as foo; +// pretty-expanded FIXME #23616 + +extern crate issue_11225_2 as foo; pub fn main() { foo::foo(1); diff --git a/src/test/run-pass/issue-11267.rs b/src/test/run-pass/issue-11267.rs index 6fb2c532e0..1a1227c792 100644 --- a/src/test/run-pass/issue-11267.rs +++ b/src/test/run-pass/issue-11267.rs @@ -15,11 +15,11 @@ struct Empty; trait T { fn next(&mut self) -> Option; } -impl T for Empty { - fn next(&mut self) -> Option { None } +impl T for Empty { + fn next(&mut self) -> Option { None } } -fn do_something_with(a : &mut T) { +fn do_something_with(a : &mut T) { println!("{:?}", a.next()) } diff --git a/src/test/run-pass/issue-11384.rs b/src/test/run-pass/issue-11384.rs index 26634fabf5..5b4bd6c9f2 100644 --- a/src/test/run-pass/issue-11384.rs +++ b/src/test/run-pass/issue-11384.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Common { fn dummy(&self) { } } impl<'t, T> Common for (T, &'t T) {} diff --git a/src/test/run-pass/issue-11508.rs b/src/test/run-pass/issue-11508.rs index 1fc72fd2cb..21ed30683f 100644 --- a/src/test/run-pass/issue-11508.rs +++ b/src/test/run-pass/issue-11508.rs @@ -10,7 +10,7 @@ // aux-build:issue-11508.rs -extern crate "issue-11508" as rand; +extern crate issue_11508 as rand; use rand::{Closed01, random}; diff --git a/src/test/run-pass/issue-11529.rs b/src/test/run-pass/issue-11529.rs index 4a74e4be4c..e5d95874be 100644 --- a/src/test/run-pass/issue-11529.rs +++ b/src/test/run-pass/issue-11529.rs @@ -10,7 +10,9 @@ // aux-build:issue-11529.rs -extern crate "issue-11529" as a; +// pretty-expanded FIXME #23616 + +extern crate issue_11529 as a; fn main() { let one = 1; diff --git a/src/test/run-pass/issue-11552.rs b/src/test/run-pass/issue-11552.rs index b99a5b7ab3..1f91c6aaa4 100644 --- a/src/test/run-pass/issue-11552.rs +++ b/src/test/run-pass/issue-11552.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] @@ -15,7 +17,7 @@ #[derive(Clone)] enum Noun { - Atom(int), + Atom(isize), Cell(Box, Box) } diff --git a/src/test/run-pass/issue-11577.rs b/src/test/run-pass/issue-11577.rs index 687de48474..ecb7a3a369 100644 --- a/src/test/run-pass/issue-11577.rs +++ b/src/test/run-pass/issue-11577.rs @@ -1,3 +1,5 @@ +// pretty-expanded FIXME #23616 + // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -11,10 +13,10 @@ // Destructuring struct variants would ICE where regular structs wouldn't enum Foo { - VBar { num: int } + VBar { num: isize } } -struct SBar { num: int } +struct SBar { num: isize } pub fn main() { let vbar = Foo::VBar { num: 1 }; diff --git a/src/test/run-pass/issue-11592.rs b/src/test/run-pass/issue-11592.rs new file mode 100644 index 0000000000..432e7ff202 --- /dev/null +++ b/src/test/run-pass/issue-11592.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Ensure the private trait Bar isn't complained about. + +#![deny(missing_docs)] + +mod foo { + trait Bar { fn bar(&self) { } } + impl Bar for i8 { fn bar(&self) { } } +} + +fn main() { } diff --git a/src/test/run-pass/issue-11612.rs b/src/test/run-pass/issue-11612.rs index 3c69377b37..de1b0525d8 100644 --- a/src/test/run-pass/issue-11612.rs +++ b/src/test/run-pass/issue-11612.rs @@ -12,6 +12,8 @@ // We weren't updating the auto adjustments with all the resolved // type information after type check. +// pretty-expanded FIXME #23616 + trait A { fn dummy(&self) { } } struct B<'a, T:'a> { diff --git a/src/test/run-pass/issue-11677.rs b/src/test/run-pass/issue-11677.rs index 7cccac4483..a3eec42831 100644 --- a/src/test/run-pass/issue-11677.rs +++ b/src/test/run-pass/issue-11677.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] -#![allow(unknown_features)] -#![feature(box_syntax)] // this code used to cause an ICE @@ -24,9 +24,10 @@ struct S {f: Box+'static>, g: Box+'static>} struct F; -impl X for F { +impl X for F { } fn main() { - S {f: box F, g: box F}; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + S {f: Box::new(F), g: Box::new(F) }; } diff --git a/src/test/run-pass/issue-11709.rs b/src/test/run-pass/issue-11709.rs index 4a07b5fc43..3ad78f088f 100644 --- a/src/test/run-pass/issue-11709.rs +++ b/src/test/run-pass/issue-11709.rs @@ -15,6 +15,8 @@ // when this bug was opened. The cases where the compiler // panics before the fix have a comment. +#![feature(std_misc)] + use std::thunk::Thunk; struct S {x:()} @@ -23,7 +25,7 @@ fn test(slot: &mut Option>) -> () { let a = slot.take(); let _a = match a { // `{let .. a(); }` would break - Some(a) => { let _a = a.invoke(()); }, + Some(a) => { let _a = a(); }, None => (), }; } diff --git a/src/test/run-pass/issue-11736.rs b/src/test/run-pass/issue-11736.rs index b901e95ff5..fde04efc8b 100644 --- a/src/test/run-pass/issue-11736.rs +++ b/src/test/run-pass/issue-11736.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + extern crate collections; use std::collections::BitVec; @@ -15,9 +19,9 @@ use std::num::Float; fn main() { // Generate sieve of Eratosthenes for n up to 1e6 - let n = 1000000_usize; + let n = 1000000; let mut sieve = BitVec::from_elem(n+1, true); - let limit: uint = (n as f32).sqrt() as uint; + let limit: usize = (n as f32).sqrt() as usize; for i in 2..limit+1 { if sieve[i] { let mut j = 0; @@ -32,4 +36,3 @@ fn main() { } } } - diff --git a/src/test/run-pass/issue-11820.rs b/src/test/run-pass/issue-11820.rs new file mode 100644 index 0000000000..6d2243db30 --- /dev/null +++ b/src/test/run-pass/issue-11820.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +struct NoClone; + +fn main() { + let rnc = &NoClone; + let rsnc = &Some(NoClone); + + let _: &NoClone = rnc.clone(); + let _: &Option = rsnc.clone(); +} diff --git a/src/test/run-pass/issue-11869.rs b/src/test/run-pass/issue-11869.rs index 12a6d9a82c..8a9b3e4b14 100644 --- a/src/test/run-pass/issue-11869.rs +++ b/src/test/run-pass/issue-11869.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct A { a: String } diff --git a/src/test/run-pass/issue-11881.rs b/src/test/run-pass/issue-11881.rs index 10d694957f..35c25b33a9 100644 --- a/src/test/run-pass/issue-11881.rs +++ b/src/test/run-pass/issue-11881.rs @@ -8,21 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check)] +// pretty-expanded FIXME #23616 + +#![feature(rustc_private, old_io)] extern crate rbml; extern crate serialize; -use std::old_io; +use std::io::Cursor; +use std::io::prelude::*; use std::fmt; -use std::old_io::{IoResult, SeekStyle}; use std::slice; use serialize::{Encodable, Encoder}; use serialize::json; use rbml::writer; -use rbml::io::SeekableMemWriter; #[derive(Encodable)] struct Foo { @@ -31,7 +32,7 @@ struct Foo { #[derive(Encodable)] struct Bar { - froboz: uint, + froboz: usize, } enum WireProtocol { @@ -40,17 +41,17 @@ enum WireProtocol { // ... } -fn encode_json(val: &T, wr: &mut SeekableMemWriter) { +fn encode_json(val: &T, wr: &mut Cursor>) { write!(wr, "{}", json::as_json(val)); } -fn encode_rbml(val: &T, wr: &mut SeekableMemWriter) { +fn encode_rbml(val: &T, wr: &mut Cursor>) { let mut encoder = writer::Encoder::new(wr); val.encode(&mut encoder); } pub fn main() { let target = Foo{baz: false,}; - let mut wr = SeekableMemWriter::new(); + let mut wr = Cursor::new(Vec::new()); let proto = WireProtocol::JSON; match proto { WireProtocol::JSON => encode_json(&target, &mut wr), diff --git a/src/test/run-pass/issue-11940.rs b/src/test/run-pass/issue-11940.rs index 1540679b09..8732def0a1 100644 --- a/src/test/run-pass/issue-11940.rs +++ b/src/test/run-pass/issue-11940.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + const TEST_STR: &'static str = "abcd"; fn main() { diff --git a/src/test/run-pass/issue-11958.rs b/src/test/run-pass/issue-11958.rs index 00613f35f1..def85b4766 100644 --- a/src/test/run-pass/issue-11958.rs +++ b/src/test/run-pass/issue-11958.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![forbid(warnings)] +#![feature(std_misc)] // Pretty printing tests complain about `use std::predule::*` #![allow(unused_imports)] @@ -19,6 +22,6 @@ use std::thunk::Thunk; pub fn main() { - let mut x = 1i32; - let _thunk = Thunk::new(move|| { x = 2; }); + let mut x = 1; + let _thunk = Box::new(move|| { x = 2; }); } diff --git a/src/test/run-pass/issue-12133-1.rs b/src/test/run-pass/issue-12133-1.rs index bf5976e921..d47bb818c4 100644 --- a/src/test/run-pass/issue-12133-1.rs +++ b/src/test/run-pass/issue-12133-1.rs @@ -11,7 +11,9 @@ // aux-build:issue-12133-rlib.rs // aux-build:issue-12133-dylib.rs -extern crate "issue-12133-rlib" as a; -extern crate "issue-12133-dylib" as b; +// pretty-expanded FIXME #23616 + +extern crate issue_12133_rlib as a; +extern crate issue_12133_dylib as b; fn main() {} diff --git a/src/test/run-pass/issue-12133-2.rs b/src/test/run-pass/issue-12133-2.rs index 50977a7e03..580c487af0 100644 --- a/src/test/run-pass/issue-12133-2.rs +++ b/src/test/run-pass/issue-12133-2.rs @@ -12,7 +12,9 @@ // aux-build:issue-12133-dylib.rs // no-prefer-dynamic -extern crate "issue-12133-rlib" as a; -extern crate "issue-12133-dylib" as b; +// pretty-expanded FIXME #23616 + +extern crate issue_12133_rlib as a; +extern crate issue_12133_dylib as b; fn main() {} diff --git a/src/test/run-pass/issue-12133-3.rs b/src/test/run-pass/issue-12133-3.rs index ab990e5529..79a5307854 100644 --- a/src/test/run-pass/issue-12133-3.rs +++ b/src/test/run-pass/issue-12133-3.rs @@ -12,6 +12,8 @@ // aux-build:issue-12133-dylib.rs // aux-build:issue-12133-dylib2.rs -extern crate "issue-12133-dylib2" as other; +// pretty-expanded FIXME #23616 + +extern crate issue_12133_dylib2 as other; fn main() {} diff --git a/src/test/run-pass/issue-12285.rs b/src/test/run-pass/issue-12285.rs index 563771212a..3a5b7e8692 100644 --- a/src/test/run-pass/issue-12285.rs +++ b/src/test/run-pass/issue-12285.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct S; fn main() { diff --git a/src/test/run-pass/issue-1251.rs b/src/test/run-pass/issue-1251.rs index debb7df112..ddd30ed3bb 100644 --- a/src/test/run-pass/issue-1251.rs +++ b/src/test/run-pass/issue-1251.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + #![crate_id="rust_get_test_int"] mod rustrt { diff --git a/src/test/run-pass/issue-1257.rs b/src/test/run-pass/issue-1257.rs index 7d5bd9d6a7..44ebe362c7 100644 --- a/src/test/run-pass/issue-1257.rs +++ b/src/test/run-pass/issue-1257.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main () { let mut line = "".to_string(); let mut i = 0; diff --git a/src/test/run-pass/issue-12612.rs b/src/test/run-pass/issue-12612.rs index 9ceb7366e4..bdf8f84a95 100644 --- a/src/test/run-pass/issue-12612.rs +++ b/src/test/run-pass/issue-12612.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-12612-1.rs -// aux-build:issue-12612-2.rs +// aux-build:issue_12612_1.rs +// aux-build:issue_12612_2.rs -extern crate "issue-12612-1" as foo; -extern crate "issue-12612-2" as bar; +// pretty-expanded FIXME #23616 + +extern crate issue_12612_1 as foo; +extern crate issue_12612_2 as bar; mod test { use bar::baz; diff --git a/src/test/run-pass/issue-12660.rs b/src/test/run-pass/issue-12660.rs index 6b3fa587bc..331f9d991d 100644 --- a/src/test/run-pass/issue-12660.rs +++ b/src/test/run-pass/issue-12660.rs @@ -10,6 +10,8 @@ // aux-build:issue-12660-aux.rs +// pretty-expanded FIXME #23616 + extern crate issue12660aux; use issue12660aux::{my_fn, MyStruct}; diff --git a/src/test/run-pass/issue-12677.rs b/src/test/run-pass/issue-12677.rs index ef68daa8ce..493bdb30e3 100644 --- a/src/test/run-pass/issue-12677.rs +++ b/src/test/run-pass/issue-12677.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let s = "Hello"; let first = s.bytes(); diff --git a/src/test/run-pass/issue-12684.rs b/src/test/run-pass/issue-12684.rs index e66b5d21e1..2b89915516 100644 --- a/src/test/run-pass/issue-12684.rs +++ b/src/test/run-pass/issue-12684.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io, std_misc)] + use std::time::Duration; use std::thread; diff --git a/src/test/run-pass/issue-12699.rs b/src/test/run-pass/issue-12699.rs index b55d647775..ac5a9b728b 100644 --- a/src/test/run-pass/issue-12699.rs +++ b/src/test/run-pass/issue-12699.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io, std_misc)] + use std::old_io::timer; use std::time::Duration; diff --git a/src/test/compile-fail/issue-12729.rs b/src/test/run-pass/issue-12729.rs similarity index 80% rename from src/test/compile-fail/issue-12729.rs rename to src/test/run-pass/issue-12729.rs index ae033bbf38..1852ed2128 100644 --- a/src/test/compile-fail/issue-12729.rs +++ b/src/test/run-pass/issue-12729.rs @@ -8,16 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength +// pretty-expanded FIXME #23616 pub struct Foo; mod bar { use Foo; - impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module + impl Foo { fn baz(&self) {} } } fn main() {} - diff --git a/src/test/run-pass/issue-12744.rs b/src/test/run-pass/issue-12744.rs index 2f7ba315aa..56d1d3599c 100644 --- a/src/test/run-pass/issue-12744.rs +++ b/src/test/run-pass/issue-12744.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] - fn main() { - fn test() -> Box { box 1 } + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + fn test() -> Box { Box::new(1) } println!("{:?}", test()) } diff --git a/src/test/run-pass/issue-12860.rs b/src/test/run-pass/issue-12860.rs index a05cc9c0f7..dddfb9bacf 100644 --- a/src/test/run-pass/issue-12860.rs +++ b/src/test/run-pass/issue-12860.rs @@ -8,16 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] extern crate collections; use std::collections::HashSet; -#[derive(Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] struct XYZ { - x: int, - y: int, - z: int + x: isize, + y: isize, + z: isize } fn main() { diff --git a/src/test/run-pass/issue-12909.rs b/src/test/run-pass/issue-12909.rs index b7dc98b92e..e153219073 100644 --- a/src/test/run-pass/issue-12909.rs +++ b/src/test/run-pass/issue-12909.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::collections::HashMap; fn copy(&x: &T) -> T { @@ -15,12 +17,12 @@ fn copy(&x: &T) -> T { } fn main() { - let arr = [(1, 1_usize), (2, 2), (3, 3)]; + let arr = [(1, 1), (2, 2), (3, 3)]; let v1: Vec<&_> = arr.iter().collect(); let v2: Vec<_> = arr.iter().map(copy).collect(); let m1: HashMap<_, _> = arr.iter().map(copy).collect(); - let m2: HashMap = arr.iter().map(copy).collect(); - let m3: HashMap<_, uint> = arr.iter().map(copy).collect(); + let m2: HashMap = arr.iter().map(copy).collect(); + let m3: HashMap<_, usize> = arr.iter().map(copy).collect(); } diff --git a/src/test/run-pass/issue-13027.rs b/src/test/run-pass/issue-13027.rs index 056c86b01f..dadd480dc6 100644 --- a/src/test/run-pass/issue-13027.rs +++ b/src/test/run-pass/issue-13027.rs @@ -13,9 +13,11 @@ // Tests that match expression handles overlapped literal and range // properly in the presence of guard function. -fn val() -> uint { 1 } +#![feature(slice_patterns)] -static CONST: uint = 1; +fn val() -> usize { 1 } + +static CONST: usize = 1; pub fn main() { lit_shadow_range(); @@ -174,7 +176,7 @@ fn range_shadow_multi_pats() { fn misc() { enum Foo { - Bar(uint, bool) + Bar(usize, bool) } // This test basically mimics how trace_macros! macro is implemented, // which is a rare combination of vector patterns, multiple wild-card diff --git a/src/test/run-pass/issue-13105.rs b/src/test/run-pass/issue-13105.rs index 64807dc44e..14de9e9030 100644 --- a/src/test/run-pass/issue-13105.rs +++ b/src/test/run-pass/issue-13105.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::marker::MarkerTrait; trait Foo : MarkerTrait { diff --git a/src/test/run-pass/issue-13167.rs b/src/test/run-pass/issue-13167.rs index 21b54ba0e7..414f6768e0 100644 --- a/src/test/run-pass/issue-13167.rs +++ b/src/test/run-pass/issue-13167.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::slice; pub struct PhfMapEntries<'a, T: 'a> { @@ -21,7 +23,7 @@ impl<'a, T> Iterator for PhfMapEntries<'a, T> { self.iter.by_ref().map(|&(key, ref value)| (key, value)).next() } - fn size_hint(&self) -> (uint, Option) { + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } diff --git a/src/test/run-pass/issue-13204.rs b/src/test/run-pass/issue-13204.rs index c29dc4319d..ec9d777974 100644 --- a/src/test/run-pass/issue-13204.rs +++ b/src/test/run-pass/issue-13204.rs @@ -11,8 +11,10 @@ // Test that when instantiating trait default methods, typeck handles // lifetime parameters defined on the method bound correctly. +// pretty-expanded FIXME #23616 + pub trait Foo { - fn bar<'a, I: Iterator>(&self, it: I) -> uint { + fn bar<'a, I: Iterator>(&self, it: I) -> usize { let mut xs = it.filter(|_| true); xs.count() } diff --git a/src/test/run-pass/issue-13214.rs b/src/test/run-pass/issue-13214.rs index 191e9ce8b6..7a3d3f4ff4 100644 --- a/src/test/run-pass/issue-13214.rs +++ b/src/test/run-pass/issue-13214.rs @@ -11,6 +11,8 @@ // defining static with struct that contains enum // with &'static str variant used to cause ICE +// pretty-expanded FIXME #23616 + pub enum Foo { Bar, Baz(&'static str), diff --git a/src/test/run-pass/issue-13259-windows-tcb-trash.rs b/src/test/run-pass/issue-13259-windows-tcb-trash.rs index 329ab7c921..34960b2645 100644 --- a/src/test/run-pass/issue-13259-windows-tcb-trash.rs +++ b/src/test/run-pass/issue-13259-windows-tcb-trash.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; #[cfg(windows)] diff --git a/src/test/run-pass/issue-13264.rs b/src/test/run-pass/issue-13264.rs index 3c76a827fb..7acabf31c8 100644 --- a/src/test/run-pass/issue-13264.rs +++ b/src/test/run-pass/issue-13264.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ops::Deref; struct Root { @@ -22,7 +24,7 @@ impl Deref for Root { } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct JSRef { node: *const Node } @@ -60,10 +62,10 @@ impl JSRef { struct Node; impl Node { - fn RemoveChild(&self, _a: uint) { + fn RemoveChild(&self, _a: usize) { } - fn AddChild(&self, _a: uint) { + fn AddChild(&self, _a: usize) { } } diff --git a/src/test/run-pass/issue-13304.rs b/src/test/run-pass/issue-13304.rs index 4a7d6be55a..c260aa95b5 100644 --- a/src/test/run-pass/issue-13304.rs +++ b/src/test/run-pass/issue-13304.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast +// ignore-aarch64 +#![feature(io, process_capture)] use std::env; -use std::old_io; +use std::io::prelude::*; +use std::io; +use std::process::{Command, Stdio}; use std::str; fn main() { @@ -25,17 +28,19 @@ fn main() { fn parent() { let args: Vec = env::args().collect(); - let mut p = old_io::process::Command::new(&args[0]) - .arg("child").spawn().unwrap(); - p.stdin.as_mut().unwrap().write_str("test1\ntest2\ntest3").unwrap(); + let mut p = Command::new(&args[0]).arg("child") + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) + .spawn().unwrap(); + p.stdin.as_mut().unwrap().write_all(b"test1\ntest2\ntest3").unwrap(); let out = p.wait_with_output().unwrap(); assert!(out.status.success()); - let s = str::from_utf8(&out.output).unwrap(); - assert_eq!(s, "test1\n\ntest2\n\ntest3\n"); + let s = str::from_utf8(&out.stdout).unwrap(); + assert_eq!(s, "test1\ntest2\ntest3\n"); } fn child() { - let mut stdin = old_io::stdin(); + let mut stdin = io::stdin(); for line in stdin.lock().lines() { println!("{}", line.unwrap()); } diff --git a/src/test/run-pass/issue-13323.rs b/src/test/run-pass/issue-13323.rs index 44167ad209..90d16aaf14 100644 --- a/src/test/run-pass/issue-13323.rs +++ b/src/test/run-pass/issue-13323.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/issue-13405.rs b/src/test/run-pass/issue-13405.rs index 05943943d9..c8b26dc4ae 100644 --- a/src/test/run-pass/issue-13405.rs +++ b/src/test/run-pass/issue-13405.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo<'a> { i: &'a bool, - j: Option<&'a int>, + j: Option<&'a isize>, } impl<'a> Foo<'a> { - fn bar(&mut self, j: &int) { + fn bar(&mut self, j: &isize) { let child = Foo { i: self.i, j: Some(j) diff --git a/src/test/run-pass/issue-13494.rs b/src/test/run-pass/issue-13494.rs index 95562d75c3..d1b1647de7 100644 --- a/src/test/run-pass/issue-13494.rs +++ b/src/test/run-pass/issue-13494.rs @@ -11,8 +11,12 @@ // This test may not always fail, but it can be flaky if the race it used to // expose is still present. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread::Thread; +use std::thread; fn helper(rx: Receiver>) { for tx in rx.iter() { @@ -22,8 +26,8 @@ fn helper(rx: Receiver>) { fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { helper(rx) }); - let (snd, rcv) = channel::(); + let _t = thread::scoped(move|| { helper(rx) }); + let (snd, rcv) = channel::(); for _ in 1..100000 { snd.send(1).unwrap(); let (tx2, rx2) = channel(); @@ -33,4 +37,5 @@ fn main() { _ = rcv.recv() => () } } + drop(tx); } diff --git a/src/test/run-pass/issue-13507-2.rs b/src/test/run-pass/issue-13507-2.rs index 1c0283070a..0b35ccf26f 100644 --- a/src/test/run-pass/issue-13507-2.rs +++ b/src/test/run-pass/issue-13507-2.rs @@ -9,6 +9,11 @@ // except according to those terms. // aux-build:issue13507.rs + +// pretty-expanded FIXME #23616 + +#![feature(core)] + extern crate issue13507; use issue13507::testtypes; diff --git a/src/test/run-pass/issue-13620.rs b/src/test/run-pass/issue-13620.rs index c67dd4b93a..4c46831418 100644 --- a/src/test/run-pass/issue-13620.rs +++ b/src/test/run-pass/issue-13620.rs @@ -11,7 +11,9 @@ // aux-build:issue-13620-1.rs // aux-build:issue-13620-2.rs -extern crate "issue-13620-2" as crate2; +// pretty-expanded FIXME #23616 + +extern crate issue_13620_2 as crate2; fn main() { (crate2::FOO2.foo)(); diff --git a/src/test/run-pass/issue-13655.rs b/src/test/run-pass/issue-13655.rs index 81a8b29461..11219b04f2 100644 --- a/src/test/run-pass/issue-13655.rs +++ b/src/test/run-pass/issue-13655.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] use std::ops::Fn; struct Foo(T); impl Fn<()> for Foo { - type Output = T; extern "rust-call" fn call(&self, _: ()) -> T { match *self { Foo(t) => t @@ -22,6 +21,20 @@ impl Fn<()> for Foo { } } +impl FnMut<()> for Foo { + extern "rust-call" fn call_mut(&mut self, _: ()) -> T { + self.call(()) + } +} + +impl FnOnce<()> for Foo { + type Output = T; + + extern "rust-call" fn call_once(self, _: ()) -> T { + self.call(()) + } +} + fn main() { let t: u8 = 1; println!("{}", Foo(t)()); diff --git a/src/test/run-pass/issue-13665.rs b/src/test/run-pass/issue-13665.rs index 5ccbe9a798..f4902c8e0a 100644 --- a/src/test/run-pass/issue-13665.rs +++ b/src/test/run-pass/issue-13665.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo<'r>() { let maybe_value_ref: Option<&'r u8> = None; diff --git a/src/test/run-pass/issue-13703.rs b/src/test/run-pass/issue-13703.rs index c9c78f6408..173b8dda05 100644 --- a/src/test/run-pass/issue-13703.rs +++ b/src/test/run-pass/issue-13703.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct Foo<'a, 'b: 'a> { foo: &'a &'b int } +// pretty-expanded FIXME #23616 + +pub struct Foo<'a, 'b: 'a> { foo: &'a &'b isize } pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<& & ()>) { let _y = x.foo; } fn main() {} diff --git a/src/test/run-pass/issue-13763.rs b/src/test/run-pass/issue-13763.rs index 81b6892b0f..fb82cccc87 100644 --- a/src/test/run-pass/issue-13763.rs +++ b/src/test/run-pass/issue-13763.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::u8; -const NUM: uint = u8::BITS as uint; +const NUM: usize = u8::BITS as usize; -struct MyStruct { nums: [uint; 8] } +struct MyStruct { nums: [usize; 8] } fn main() { diff --git a/src/test/run-pass/issue-13775.rs b/src/test/run-pass/issue-13775.rs index 8731662afa..3b70bea719 100644 --- a/src/test/run-pass/issue-13775.rs +++ b/src/test/run-pass/issue-13775.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { - fn bar(&self, int) {} + fn bar(&self, isize) {} } fn main() {} diff --git a/src/test/run-pass/issue-13808.rs b/src/test/run-pass/issue-13808.rs index 3c5ece87b7..c85c011758 100644 --- a/src/test/run-pass/issue-13808.rs +++ b/src/test/run-pass/issue-13808.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 struct Foo<'a> { listener: Box, @@ -17,7 +16,8 @@ struct Foo<'a> { impl<'a> Foo<'a> { fn new(listener: F) -> Foo<'a> where F: FnMut() + 'a { - Foo { listener: box listener } + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Foo { listener: Box::new(listener) } } } diff --git a/src/test/run-pass/issue-13837.rs b/src/test/run-pass/issue-13837.rs index c6847ce55d..d90b9cffb6 100644 --- a/src/test/run-pass/issue-13837.rs +++ b/src/test/run-pass/issue-13837.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct TestStruct { - x: *const [int; 2] + x: *const [isize; 2] } unsafe impl Sync for TestStruct {} -static TEST_VALUE : TestStruct = TestStruct{x: 0x1234 as *const [int; 2]}; +static TEST_VALUE : TestStruct = TestStruct{x: 0x1234 as *const [isize; 2]}; fn main() {} diff --git a/src/test/run-pass/issue-13867.rs b/src/test/run-pass/issue-13867.rs index 960884c4aa..a902e141bb 100644 --- a/src/test/run-pass/issue-13867.rs +++ b/src/test/run-pass/issue-13867.rs @@ -11,8 +11,10 @@ // Test that codegen works correctly when there are multiple refutable // patterns in match expression. +// pretty-expanded FIXME #23616 + enum Foo { - FooUint(uint), + FooUint(usize), FooNullary, } diff --git a/src/test/run-pass/issue-13872.rs b/src/test/run-pass/issue-13872.rs index a58477e647..e9fb7945d0 100644 --- a/src/test/run-pass/issue-13872.rs +++ b/src/test/run-pass/issue-13872.rs @@ -12,7 +12,9 @@ // aux-build:issue-13872-2.rs // aux-build:issue-13872-3.rs -extern crate "issue-13872-3" as other; +// pretty-expanded FIXME #23616 + +extern crate issue_13872_3 as other; fn main() { other::foo(); diff --git a/src/test/run-pass/issue-14021.rs b/src/test/run-pass/issue-14021.rs index e850ecbba6..907967d115 100644 --- a/src/test/run-pass/issue-14021.rs +++ b/src/test/run-pass/issue-14021.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(old_orphan_check)] +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/issue-14082.rs b/src/test/run-pass/issue-14082.rs index dd9a7c97c9..d159d55c77 100644 --- a/src/test/run-pass/issue-14082.rs +++ b/src/test/run-pass/issue-14082.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_imports, dead_code)] use foo::Foo; diff --git a/src/test/run-pass/issue-14254.rs b/src/test/run-pass/issue-14254.rs index ad4ed03e6e..ed96eee6dd 100644 --- a/src/test/run-pass/issue-14254.rs +++ b/src/test/run-pass/issue-14254.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn bar(&self); fn baz(&self) { } @@ -15,7 +17,7 @@ trait Foo { } struct BarTy { - x : int, + x : isize, y : f64, } @@ -66,34 +68,34 @@ impl Foo for Box { } // If these fail, it's necessary to update rustc_resolve and the cfail tests. -impl Foo for *const int { +impl Foo for *const isize { fn bar(&self) { self.baz(); - Foo::bah(None::<*const int>); + Foo::bah(None::<*const isize>); } } // If these fail, it's necessary to update rustc_resolve and the cfail tests. -impl<'a> Foo for &'a int { +impl<'a> Foo for &'a isize { fn bar(&self) { self.baz(); - Foo::bah(None::<&int>); + Foo::bah(None::<&isize>); } } // If these fail, it's necessary to update rustc_resolve and the cfail tests. -impl<'a> Foo for &'a mut int { +impl<'a> Foo for &'a mut isize { fn bar(&self) { self.baz(); - Foo::bah(None::<&mut int>); + Foo::bah(None::<&mut isize>); } } // If these fail, it's necessary to update rustc_resolve and the cfail tests. -impl Foo for Box { +impl Foo for Box { fn bar(&self) { self.baz(); - Foo::bah(None::>); + Foo::bah(None::>); } } diff --git a/src/test/run-pass/issue-14308.rs b/src/test/run-pass/issue-14308.rs index 0e4b4a2c9c..f67d0946e9 100644 --- a/src/test/run-pass/issue-14308.rs +++ b/src/test/run-pass/issue-14308.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct A(int); +// pretty-expanded FIXME #23616 + +struct A(isize); struct B; fn main() { diff --git a/src/test/run-pass/issue-14330.rs b/src/test/run-pass/issue-14330.rs index f983f233ee..dd5b7e722f 100644 --- a/src/test/run-pass/issue-14330.rs +++ b/src/test/run-pass/issue-14330.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[macro_use] extern crate "std" as std2; +// pretty-expanded FIXME #23616 + +#[macro_use] extern crate std as std2; fn main() {} diff --git a/src/test/run-pass/issue-14393.rs b/src/test/run-pass/issue-14393.rs index 6c9c7e2fd3..88af650749 100644 --- a/src/test/run-pass/issue-14393.rs +++ b/src/test/run-pass/issue-14393.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { match ("", 1_usize) { (_, 42_usize) => (), diff --git a/src/test/run-pass/issue-14399.rs b/src/test/run-pass/issue-14399.rs index db7eacce9d..aa91f125e4 100644 --- a/src/test/run-pass/issue-14399.rs +++ b/src/test/run-pass/issue-14399.rs @@ -13,6 +13,8 @@ // value was coerced to a trait object. (v.clone() returns Box // which is coerced to Box). +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -23,6 +25,6 @@ trait A { fn foo(&self) {} } impl A for B1 {} fn main() { - let v = box B1; + let v: Box<_> = box B1; let _c: Box = v.clone(); } diff --git a/src/test/run-pass/issue-14421.rs b/src/test/run-pass/issue-14421.rs index c595f98cd0..046d888030 100644 --- a/src/test/run-pass/issue-14421.rs +++ b/src/test/run-pass/issue-14421.rs @@ -10,7 +10,9 @@ // aux-build:issue-14421.rs -extern crate "issue-14421" as bug_lib; +// pretty-expanded FIXME #23616 + +extern crate issue_14421 as bug_lib; use bug_lib::B; use bug_lib::make; @@ -19,4 +21,3 @@ pub fn main() { let mut an_A: B = make(); an_A.foo(); } - diff --git a/src/test/run-pass/issue-14422.rs b/src/test/run-pass/issue-14422.rs index 439998c597..178a219f5b 100644 --- a/src/test/run-pass/issue-14422.rs +++ b/src/test/run-pass/issue-14422.rs @@ -10,7 +10,9 @@ // aux-build:issue-14422.rs -extern crate "issue-14422" as bug_lib; +// pretty-expanded FIXME #23616 + +extern crate issue_14422 as bug_lib; use bug_lib::B; use bug_lib::make; diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs index 723db9485c..ab9633ca1f 100644 --- a/src/test/run-pass/issue-14456.rs +++ b/src/test/run-pass/issue-14456.rs @@ -8,11 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(io, process_capture)] -use std::old_io::process; -use std::old_io::Command; -use std::old_io; use std::env; +use std::io::prelude::*; +use std::io; +use std::process::{Command, Stdio}; fn main() { let args: Vec = env::args().collect(); @@ -21,22 +24,23 @@ fn main() { } test(); - } fn child() { - old_io::stdout().write_line("foo").unwrap(); - old_io::stderr().write_line("bar").unwrap(); - let mut stdin = old_io::stdin(); - assert_eq!(stdin.lock().read_line().err().unwrap().kind, old_io::EndOfFile); + writeln!(&mut io::stdout(), "foo").unwrap(); + writeln!(&mut io::stderr(), "bar").unwrap(); + let mut stdin = io::stdin(); + let mut s = String::new(); + stdin.lock().read_line(&mut s).unwrap(); + assert_eq!(s.len(), 0); } fn test() { let args: Vec = env::args().collect(); let mut p = Command::new(&args[0]).arg("child") - .stdin(process::Ignored) - .stdout(process::Ignored) - .stderr(process::Ignored) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) .spawn().unwrap(); assert!(p.wait().unwrap().success()); } diff --git a/src/test/run-pass/issue-1451.rs b/src/test/run-pass/issue-1451.rs index 027826e99c..1cbe986e88 100644 --- a/src/test/run-pass/issue-1451.rs +++ b/src/test/run-pass/issue-1451.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_variable)] struct T { f: extern "Rust" fn() } diff --git a/src/test/run-pass/issue-14589.rs b/src/test/run-pass/issue-14589.rs index 71d88ee621..b0893e21af 100644 --- a/src/test/run-pass/issue-14589.rs +++ b/src/test/run-pass/issue-14589.rs @@ -11,13 +11,14 @@ // All 3 expressions should work in that the argument gets // coerced to a trait object -#![allow(unknown_features)] -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + +// pretty-expanded FIXME #23616 fn main() { - send::>(box Output(0)); - Test::>::foo(box Output(0)); - Test::>::new().send(box Output(0)); + send::>(Box::new(Output(0))); + Test::>::foo(Box::new(Output(0))); + Test::>::new().send(Box::new(Output(0))); } fn send(_: T) {} @@ -30,5 +31,5 @@ impl Test { } trait Foo { fn dummy(&self) { }} -struct Output(int); +struct Output(isize); impl Foo for Output {} diff --git a/src/test/run-pass/issue-1460.rs b/src/test/run-pass/issue-1460.rs index 44465fe5f8..6e1cfc7186 100644 --- a/src/test/run-pass/issue-1460.rs +++ b/src/test/run-pass/issue-1460.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - {|i| if 1 == i { }}; + {|i: u32| if 1 == i { }}; } diff --git a/src/test/run-pass/issue-14837.rs b/src/test/run-pass/issue-14837.rs index 1155027d42..5589acdda3 100644 --- a/src/test/run-pass/issue-14837.rs +++ b/src/test/run-pass/issue-14837.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[deny(dead_code)] pub enum Foo { Bar { - baz: int + baz: isize } } diff --git a/src/test/run-pass/issue-14865.rs b/src/test/run-pass/issue-14865.rs index c322346c2a..e78736b77f 100644 --- a/src/test/run-pass/issue-14865.rs +++ b/src/test/run-pass/issue-14865.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum X { - Foo(uint), + Foo(usize), Bar(bool) } diff --git a/src/test/run-pass/issue-14901.rs b/src/test/run-pass/issue-14901.rs index abb15dae00..7e7886e3a6 100644 --- a/src/test/run-pass/issue-14901.rs +++ b/src/test/run-pass/issue-14901.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io)] + use std::old_io::Reader; enum Wrapper<'a> { diff --git a/src/test/run-pass/issue-14919.rs b/src/test/run-pass/issue-14919.rs index 933e7e40f0..371e926ab1 100644 --- a/src/test/run-pass/issue-14919.rs +++ b/src/test/run-pass/issue-14919.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 trait Matcher { - fn next_match(&mut self) -> Option<(uint, uint)>; + fn next_match(&mut self) -> Option<(usize, usize)>; } struct CharPredMatcher<'a, 'b> { @@ -21,7 +20,7 @@ struct CharPredMatcher<'a, 'b> { } impl<'a, 'b> Matcher for CharPredMatcher<'a, 'b> { - fn next_match(&mut self) -> Option<(uint, uint)> { + fn next_match(&mut self) -> Option<(usize, usize)> { None } } @@ -32,9 +31,10 @@ trait IntoMatcher<'a, T> { 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> { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. CharPredMatcher { str: s, - pred: box self, + pred: Box::new(self), } } } @@ -44,9 +44,9 @@ struct MatchIndices { } impl Iterator for MatchIndices { - type Item = (uint, uint); + type Item = (usize, usize); - fn next(&mut self) -> Option<(uint, uint)> { + fn next(&mut self) -> Option<(usize, usize)> { self.matcher.next_match() } } @@ -59,5 +59,5 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi fn main() { let s = "abcbdef"; match_indices(s, |c: char| c == 'b') - .collect::>(); + .collect::>(); } diff --git a/src/test/run-pass/issue-14933.rs b/src/test/run-pass/issue-14933.rs index 549ed08aaf..f6815b7608 100644 --- a/src/test/run-pass/issue-14933.rs +++ b/src/test/run-pass/issue-14933.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub type BigRat = T; +// pretty-expanded FIXME #23616 + +pub type BigRat = T; fn main() {} diff --git a/src/test/run-pass/issue-14936.rs b/src/test/run-pass/issue-14936.rs index ace1f00b02..2361c385b4 100644 --- a/src/test/run-pass/issue-14936.rs +++ b/src/test/run-pass/issue-14936.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(asm)] type History = Vec<&'static str>; @@ -20,8 +22,8 @@ fn wrap(x:A, which: &'static str, history: &mut History) -> A { macro_rules! demo { ( $output_constraint:tt ) => { { - let mut x: int = 0; - let y: int = 1; + let mut x: isize = 0; + let y: isize = 1; let mut history: History = vec!(); unsafe { diff --git a/src/test/run-pass/issue-14940.rs b/src/test/run-pass/issue-14940.rs index ed0e3bddbe..a530384d36 100644 --- a/src/test/run-pass/issue-14940.rs +++ b/src/test/run-pass/issue-14940.rs @@ -8,13 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io, io)] + use std::env; -use std::old_io::{stdio, Command}; +use std::process::Command; +use std::io::{self, Write}; fn main() { let mut args = env::args(); if args.len() > 1 { - let mut out = stdio::stdout(); + let mut out = io::stdout(); out.write(&['a' as u8; 128 * 1024]).unwrap(); } else { let out = Command::new(&args.next().unwrap()).arg("child").output(); diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index 6335f79be6..ec482a776d 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -8,17 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] trait Foo { fn dummy(&self) { }} struct Bar; impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar { - type Output = (); extern "rust-call" fn call(&self, _: (&'a Foo,)) {} } +impl<'a> std::ops::FnMut<(&'a (Foo+'a),)> for Bar { + extern "rust-call" fn call_mut(&mut self, a: (&'a Foo,)) { self.call(a) } +} + +impl<'a> std::ops::FnOnce<(&'a (Foo+'a),)> for Bar { + type Output = (); + extern "rust-call" fn call_once(self, a: (&'a Foo,)) { self.call(a) } +} + struct Baz; impl Foo for Baz {} diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index 53d0f7dae0..5accaf3634 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::ops::Fn; @@ -34,9 +36,21 @@ impl Alloy { } impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile { + extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} +} + +impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile { + extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) { + self.call((_res,)) + } +} + +impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile { type Output = (); - extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} + extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) { + self.call((_res,)) + } } impl Ingot for HelloWorld { diff --git a/src/test/run-pass/issue-15043.rs b/src/test/run-pass/issue-15043.rs index edca9cbaa3..adf56388ac 100644 --- a/src/test/run-pass/issue-15043.rs +++ b/src/test/run-pass/issue-15043.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(warnings)] struct S(T); -static s1: S>=S(S(0)); -static s2: S=S(0); +static s1: S>=S(S(0)); +static s2: S=S(0); fn main() { - let foo: S>=S(S(0)); - let foo: S=S(0); + let foo: S>=S(S(0)); + let foo: S=S(0); } diff --git a/src/test/run-pass/issue-15080.rs b/src/test/run-pass/issue-15080.rs index 9752b01e52..4369dc6292 100644 --- a/src/test/run-pass/issue-15080.rs +++ b/src/test/run-pass/issue-15080.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + fn main() { let mut x: &[_] = &[1, 2, 3, 4]; diff --git a/src/test/run-pass/issue-15104.rs b/src/test/run-pass/issue-15104.rs index c6c9e80045..db04e10cfe 100644 --- a/src/test/run-pass/issue-15104.rs +++ b/src/test/run-pass/issue-15104.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + fn main() { assert_eq!(count_members(&[1, 2, 3, 4]), 4); } -fn count_members(v: &[uint]) -> uint { +fn count_members(v: &[usize]) -> usize { match v { [] => 0, [_] => 1, diff --git a/src/test/run-pass/issue-15108.rs b/src/test/run-pass/issue-15108.rs index 8ae3d07236..aaf1e5fc18 100644 --- a/src/test/run-pass/issue-15108.rs +++ b/src/test/run-pass/issue-15108.rs @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() {} diff --git a/src/test/run-pass/issue-15129.rs b/src/test/run-pass/issue-15129.rs index 6782310fa0..54705c6bf1 100644 --- a/src/test/run-pass/issue-15129.rs +++ b/src/test/run-pass/issue-15129.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub enum T { T1(()), T2(()) } pub enum V { - V1(int), + V1(isize), V2(bool) } diff --git a/src/test/run-pass/issue-15149.rs b/src/test/run-pass/issue-15149.rs index aa176d5b0f..ee348d9cb0 100644 --- a/src/test/run-pass/issue-15149.rs +++ b/src/test/run-pass/issue-15149.rs @@ -1,5 +1,3 @@ -// no-prefer-dynamic - // 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. @@ -10,12 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::slice::SliceExt; -use std::old_io::{fs, USER_RWX}; -use std::process; +// no-prefer-dynamic + +// pretty-expanded FIXME #23616 + +#![feature(fs, process, env, path, rand)] + use std::env; -use std::old_path::BytesContainer; +use std::fs; +use std::process; use std::rand::random; +use std::str; fn main() { // If we're the child, make sure we were invoked correctly @@ -25,7 +28,7 @@ fn main() { // checking that it ends_with the executable name. This // is needed because of Windows, which has a different behavior. // See #15149 for more info. - return assert!(args[0].ends_with(&format!("mytest{}", env::consts::EXE_SUFFIX)[])); + return assert!(args[0].ends_with(&format!("mytest{}", env::consts::EXE_SUFFIX))); } test(); @@ -34,21 +37,20 @@ fn main() { fn test() { // If we're the parent, copy our own binary to a new directory. let my_path = env::current_exe().unwrap(); - let my_dir = my_path.dir_path(); + let my_dir = my_path.parent().unwrap(); let random_u32: u32 = random(); - let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}", - random_u32))); - fs::mkdir(&child_dir, USER_RWX).unwrap(); + let child_dir = my_dir.join(&format!("issue-15149-child-{}", random_u32)); + fs::create_dir(&child_dir).unwrap(); - let child_path = child_dir.join(format!("mytest{}", - env::consts::EXE_SUFFIX)); + let child_path = child_dir.join(&format!("mytest{}", + env::consts::EXE_SUFFIX)); fs::copy(&my_path, &child_path).unwrap(); // Append the new directory to our own PATH. let path = { let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap()).collect(); - paths.push(child_dir.clone()); + paths.push(child_dir.to_path_buf()); env::join_paths(paths.iter()).unwrap() }; @@ -58,9 +60,9 @@ fn test() { assert!(child_output.status.success(), format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}", - child_output.stdout.container_as_str().unwrap(), - child_output.stderr.container_as_str().unwrap())); + str::from_utf8(&child_output.stdout).unwrap(), + str::from_utf8(&child_output.stderr).unwrap())); - fs::rmdir_recursive(&child_dir).unwrap(); + fs::remove_dir_all(&child_dir).unwrap(); } diff --git a/src/test/run-pass/issue-15155.rs b/src/test/run-pass/issue-15155.rs index 3a63e63355..e1ecaaab02 100644 --- a/src/test/run-pass/issue-15155.rs +++ b/src/test/run-pass/issue-15155.rs @@ -28,5 +28,3 @@ fn main() { test_trait::(); test_trait::(); } - - diff --git a/src/test/run-pass/issue-15221.rs b/src/test/run-pass/issue-15221.rs index 49e5b14aff..bb89fb2fa1 100644 --- a/src/test/run-pass/issue-15221.rs +++ b/src/test/run-pass/issue-15221.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! inner { ($e:pat ) => ($e) } @@ -20,4 +22,3 @@ fn main() { let outer!(g1) = 13; g1; } - diff --git a/src/test/run-pass/issue-15261.rs b/src/test/run-pass/issue-15261.rs index fbbd40895b..239fef1232 100644 --- a/src/test/run-pass/issue-15261.rs +++ b/src/test/run-pass/issue-15261.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static mut n_mut: uint = 0; +// pretty-expanded FIXME #23616 -static n: &'static uint = unsafe{ &n_mut }; +static mut n_mut: usize = 0; + +static n: &'static usize = unsafe{ &n_mut }; fn main() {} diff --git a/src/test/run-pass/issue-15444.rs b/src/test/run-pass/issue-15444.rs index 0f4978d78d..e9a9eabcd9 100644 --- a/src/test/run-pass/issue-15444.rs +++ b/src/test/run-pass/issue-15444.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait MyTrait { fn foo(&self); } @@ -20,11 +22,11 @@ fn bar(t: &T) { t.foo() } -fn thing(a: int, b: int) -> int { +fn thing(a: isize, b: isize) -> isize { a + b } fn main() { - let thing: fn(int, int) -> int = thing; // coerce to fn type + let thing: fn(isize, isize) -> isize = thing; // coerce to fn type bar(&thing); } diff --git a/src/test/run-pass/issue-15562.rs b/src/test/run-pass/issue-15562.rs index 82f53ea7cd..f1ef57e44b 100644 --- a/src/test/run-pass/issue-15562.rs +++ b/src/test/run-pass/issue-15562.rs @@ -10,7 +10,9 @@ // aux-build:issue-15562.rs -extern crate "issue-15562" as i; +// pretty-expanded FIXME #23616 + +extern crate issue_15562 as i; pub fn main() { extern { diff --git a/src/test/run-pass/issue-15571.rs b/src/test/run-pass/issue-15571.rs index ab9554f65d..3dc76f4a08 100644 --- a/src/test/run-pass/issue-15571.rs +++ b/src/test/run-pass/issue-15571.rs @@ -12,7 +12,7 @@ #![feature(box_syntax)] fn match_on_local() { - let mut foo = Some(box 5); + let mut foo: Option> = Some(box 5); match foo { None => {}, Some(x) => { @@ -33,7 +33,7 @@ fn match_on_arg(mut foo: Option>) { } fn match_on_binding() { - match Some(box 7) { + match Some(Box::new(7)) { mut foo => { match foo { None => {}, @@ -47,7 +47,7 @@ fn match_on_binding() { } fn match_on_upvar() { - let mut foo = Some(box 8i32); + let mut foo: Option> = Some(box 8); let f = move|| { match foo { None => {}, diff --git a/src/test/run-pass/issue-15673.rs b/src/test/run-pass/issue-15673.rs index a6b8a04eeb..6c76f1595d 100644 --- a/src/test/run-pass/issue-15673.rs +++ b/src/test/run-pass/issue-15673.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::iter::AdditiveIterator; fn main() { let x: [u64; 3] = [1, 2, 3]; - assert_eq!(6, (0_usize..3).map(|i| x[i]).sum()); + assert_eq!(6, (0..3).map(|i| x[i]).sum()); } diff --git a/src/test/run-pass/issue-15689-1.rs b/src/test/run-pass/issue-15689-1.rs index 06e9e652ed..9fc1cce56b 100644 --- a/src/test/run-pass/issue-15689-1.rs +++ b/src/test/run-pass/issue-15689-1.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(PartialEq)] enum Test<'a> { - Slice(&'a int) + Slice(&'a isize) } fn main() { diff --git a/src/test/run-pass/issue-15689-2.rs b/src/test/run-pass/issue-15689-2.rs index 8da82c498b..922b18c01d 100644 --- a/src/test/run-pass/issue-15689-2.rs +++ b/src/test/run-pass/issue-15689-2.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] enum Test<'a> { - Slice(&'a int) + Slice(&'a isize) } fn main() {} diff --git a/src/test/run-pass/issue-15730.rs b/src/test/run-pass/issue-15730.rs index 72daa0cba4..929580019f 100644 --- a/src/test/run-pass/issue-15730.rs +++ b/src/test/run-pass/issue-15730.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let mut array = [1, 2, 3]; let pie_slice = &array[1..2]; diff --git a/src/test/run-pass/issue-15734.rs b/src/test/run-pass/issue-15734.rs index e66ac8ff53..67ce6a1c44 100644 --- a/src/test/run-pass/issue-15734.rs +++ b/src/test/run-pass/issue-15734.rs @@ -11,59 +11,61 @@ // If `Index` used an associated type for its output, this test would // work more smoothly. -#![feature(old_orphan_check)] +// pretty-expanded FIXME #23616 + +#![feature(core)] use std::ops::Index; -struct Mat { data: Vec, cols: uint, } +struct Mat { data: Vec, cols: usize, } impl Mat { - fn new(data: Vec, cols: uint) -> Mat { + fn new(data: Vec, cols: usize) -> Mat { Mat { data: data, cols: cols } } - fn row<'a>(&'a self, row: uint) -> Row<&'a Mat> { + fn row<'a>(&'a self, row: usize) -> Row<&'a Mat> { Row { mat: self, row: row, } } } -impl Index<(uint, uint)> for Mat { +impl Index<(usize, usize)> for Mat { type Output = T; - fn index<'a>(&'a self, &(row, col): &(uint, uint)) -> &'a T { + fn index<'a>(&'a self, (row, col): (usize, usize)) -> &'a T { &self.data[row * self.cols + col] } } -impl<'a, T> Index<(uint, uint)> for &'a Mat { +impl<'a, T> Index<(usize, usize)> for &'a Mat { type Output = T; - fn index<'b>(&'b self, index: &(uint, uint)) -> &'b T { + fn index<'b>(&'b self, index: (usize, usize)) -> &'b T { (*self).index(index) } } -struct Row { mat: M, row: uint, } +struct Row { mat: M, row: usize, } -impl> Index for Row { +impl> Index for Row { type Output = T; - fn index<'a>(&'a self, col: &uint) -> &'a T { - &self.mat[(self.row, *col)] + fn index<'a>(&'a self, col: usize) -> &'a T { + &self.mat[(self.row, col)] } } fn main() { - let m = Mat::new(vec!(1_usize, 2, 3, 4, 5, 6), 3); + let m = Mat::new(vec!(1, 2, 3, 4, 5, 6), 3); let r = m.row(1); - assert!(r.index(&2) == &6); + assert!(r.index(2) == &6); + assert!(r[2] == 6); assert!(r[2] == 6); - assert!(r[2_usize] == 6_usize); assert!(6 == r[2]); let e = r[2]; assert!(e == 6); - let e: uint = r[2]; + let e: usize = r[2]; assert!(e == 6); } diff --git a/src/test/run-pass/issue-15763.rs b/src/test/run-pass/issue-15763.rs index 7bfd8e0ab7..b5251d63ff 100644 --- a/src/test/run-pass/issue-15763.rs +++ b/src/test/run-pass/issue-15763.rs @@ -13,7 +13,7 @@ #[derive(PartialEq, Debug)] struct Bar { - x: int + x: isize } impl Drop for Bar { fn drop(&mut self) { @@ -24,17 +24,17 @@ impl Drop for Bar { #[derive(PartialEq, Debug)] struct Foo { x: Bar, - a: int + a: isize } -fn foo() -> Result { +fn foo() -> Result { return Ok(Foo { x: Bar { x: 22 }, a: return Err(32) }); } -fn baz() -> Result { +fn baz() -> Result { Ok(Foo { x: Bar { x: 22 }, a: return Err(32) @@ -42,41 +42,41 @@ fn baz() -> Result { } // explicit immediate return -fn aa() -> int { +fn aa() -> isize { return 3; } // implicit immediate return -fn bb() -> int { +fn bb() -> isize { 3 } // implicit outptr return -fn cc() -> Result { +fn cc() -> Result { Ok(3) } // explicit outptr return -fn dd() -> Result { +fn dd() -> Result { return Ok(3); } trait A { - fn aaa(&self) -> int { + fn aaa(&self) -> isize { 3 } - fn bbb(&self) -> int { + fn bbb(&self) -> isize { return 3; } - fn ccc(&self) -> Result { + fn ccc(&self) -> Result { Ok(3) } - fn ddd(&self) -> Result { + fn ddd(&self) -> Result { return Ok(3); } } -impl A for int {} +impl A for isize {} fn main() { assert_eq!(foo(), Err(32)); @@ -87,12 +87,12 @@ fn main() { assert_eq!(cc().unwrap(), 3); assert_eq!(dd().unwrap(), 3); - let i = box 32 as Box; + let i = box 32is as Box; assert_eq!(i.aaa(), 3); - let i = box 32 as Box; + let i = box 32is as Box; assert_eq!(i.bbb(), 3); - let i = box 32 as Box; + let i = box 32is as Box; assert_eq!(i.ccc().unwrap(), 3); - let i = box 32 as Box; + let i = box 32is as Box; assert_eq!(i.ddd().unwrap(), 3); } diff --git a/src/test/run-pass/issue-15774.rs b/src/test/run-pass/issue-15774.rs index 77fa862f7d..eb3322e037 100644 --- a/src/test/run-pass/issue-15774.rs +++ b/src/test/run-pass/issue-15774.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![deny(warnings)] #![allow(unused_imports)] -enum Foo { A } +pub enum Foo { A } mod bar { pub fn normal(x: ::Foo) { use Foo::A; diff --git a/src/test/run-pass/issue-15793.rs b/src/test/run-pass/issue-15793.rs index 933fa881ee..21baf47ee6 100644 --- a/src/test/run-pass/issue-15793.rs +++ b/src/test/run-pass/issue-15793.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum NestedEnum { First, Second, @@ -19,7 +21,7 @@ enum Enum { } #[inline(never)] -fn foo(x: Enum) -> int { +fn foo(x: Enum) -> isize { match x { Enum::Variant1(true) => 1, Enum::Variant1(false) => 2, diff --git a/src/test/run-pass/issue-15858.rs b/src/test/run-pass/issue-15858.rs index 6a4f78442d..265db3fe13 100644 --- a/src/test/run-pass/issue-15858.rs +++ b/src/test/run-pass/issue-15858.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] static mut DROP_RAN: bool = false; @@ -23,7 +25,7 @@ impl Bar for BarImpl { } -struct Foo(B); +struct Foo(B); #[unsafe_destructor] impl Drop for Foo { diff --git a/src/test/run-pass/issue-15881-model-lexer-dotdotdot.rs b/src/test/run-pass/issue-15881-model-lexer-dotdotdot.rs index 18e1918aea..6b75e4e479 100644 --- a/src/test/run-pass/issue-15881-model-lexer-dotdotdot.rs +++ b/src/test/run-pass/issue-15881-model-lexer-dotdotdot.rs @@ -10,6 +10,8 @@ // // regression test for the model lexer handling the DOTDOTDOT syntax (#15877) +// pretty-expanded FIXME #23616 + pub fn main() { match 5_usize { 1_usize...5_usize => {} diff --git a/src/test/run-pass/issue-15924.rs b/src/test/run-pass/issue-15924.rs index 88b250af1c..e544585745 100644 --- a/src/test/run-pass/issue-15924.rs +++ b/src/test/run-pass/issue-15924.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unsafe_destructor)] +// pretty-expanded FIXME #23616 + +#![feature(unsafe_destructor, rustc_private)] extern crate serialize; @@ -16,7 +18,7 @@ use std::fmt; use serialize::{Encoder, Encodable}; use serialize::json; -struct Foo { +struct Foo { v: T, } diff --git a/src/test/run-pass/issue-16151.rs b/src/test/run-pass/issue-16151.rs index 5401d6a6fd..242bcb69be 100644 --- a/src/test/run-pass/issue-16151.rs +++ b/src/test/run-pass/issue-16151.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; -static mut DROP_COUNT: uint = 0; +static mut DROP_COUNT: usize = 0; struct Fragment; @@ -35,4 +37,3 @@ fn main() { assert_eq!(DROP_COUNT, 3); } } - diff --git a/src/test/run-pass/issue-16256.rs b/src/test/run-pass/issue-16256.rs index 48ea3a9329..b994fcb46b 100644 --- a/src/test/run-pass/issue-16256.rs +++ b/src/test/run-pass/issue-16256.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let mut buf = Vec::new(); |c: u8| buf.push(c); diff --git a/src/test/run-pass/issue-16272.rs b/src/test/run-pass/issue-16272.rs index 3bab78ab0d..9562d113ad 100644 --- a/src/test/run-pass/issue-16272.rs +++ b/src/test/run-pass/issue-16272.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::{process, Command}; +// ignore-aarch64 + +use std::process::Command; use std::env; fn main() { @@ -22,10 +24,8 @@ fn main() { } fn test() { - let status = Command::new(env::current_exe().unwrap()) + let status = Command::new(&env::current_exe().unwrap()) .arg("foo").arg("") - .stdout(process::InheritFd(1)) - .stderr(process::InheritFd(2)) .status().unwrap(); assert!(status.success()); } diff --git a/src/test/run-pass/issue-16278.rs b/src/test/run-pass/issue-16278.rs index ade312da21..41af72db20 100644 --- a/src/test/run-pass/issue-16278.rs +++ b/src/test/run-pass/issue-16278.rs @@ -17,4 +17,3 @@ fn main() {assert_eq!(b"", b"\ assert_eq!(b"\n", b" "); } - diff --git a/src/test/run-pass/issue-16441.rs b/src/test/run-pass/issue-16441.rs index 62c36e1d88..4624953dea 100644 --- a/src/test/run-pass/issue-16441.rs +++ b/src/test/run-pass/issue-16441.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Empty; // This used to cause an ICE diff --git a/src/test/run-pass/issue-16452.rs b/src/test/run-pass/issue-16452.rs index da48020749..b6056d0ab8 100644 --- a/src/test/run-pass/issue-16452.rs +++ b/src/test/run-pass/issue-16452.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { if true { return } match () { - () => { static MAGIC: uint = 0; } + () => { static MAGIC: usize = 0; } } } - diff --git a/src/test/run-pass/issue-16492.rs b/src/test/run-pass/issue-16492.rs index 67af19b851..fcb0462766 100644 --- a/src/test/run-pass/issue-16492.rs +++ b/src/test/run-pass/issue-16492.rs @@ -16,12 +16,12 @@ use std::rc::Rc; use std::cell::Cell; struct Field { - number: uint, - state: Rc> + number: usize, + state: Rc> } impl Field { - fn new(number: uint, state: Rc>) -> Field { + fn new(number: usize, state: Rc>) -> Field { Field { number: number, state: state diff --git a/src/test/run-pass/issue-16530.rs b/src/test/run-pass/issue-16530.rs index 7e3b796235..bf33221431 100644 --- a/src/test/run-pass/issue-16530.rs +++ b/src/test/run-pass/issue-16530.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(hash)] + use std::hash::{SipHasher, hash}; #[derive(Hash)] diff --git a/src/test/run-pass/issue-16560.rs b/src/test/run-pass/issue-16560.rs index 9448e60593..33842fab69 100644 --- a/src/test/run-pass/issue-16560.rs +++ b/src/test/run-pass/issue-16560.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::thread; @@ -15,7 +17,7 @@ use std::mem; fn main() { let y = 0u8; - let closure = move |x| y + x; + let closure = move |x: u8| y + x; // Check that both closures are capturing by value assert_eq!(1, mem::size_of_val(&closure)); diff --git a/src/test/run-pass/issue-16596.rs b/src/test/run-pass/issue-16596.rs index 1ba7b142e5..743dbbc9b9 100644 --- a/src/test/run-pass/issue-16596.rs +++ b/src/test/run-pass/issue-16596.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait MatrixRow { fn dummy(&self) { }} struct Mat; diff --git a/src/test/run-pass/issue-16597.rs b/src/test/run-pass/issue-16597.rs index 72e948e613..d074095dbd 100644 --- a/src/test/run-pass/issue-16597.rs +++ b/src/test/run-pass/issue-16597.rs @@ -15,5 +15,5 @@ mod test { use super::*; #[test] - fn test(){} + pub fn test(){} } diff --git a/src/test/run-pass/issue-1660.rs b/src/test/run-pass/issue-1660.rs index 5c8b4be0ce..2a59c3051d 100644 --- a/src/test/run-pass/issue-1660.rs +++ b/src/test/run-pass/issue-1660.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - static _x: int = 1<<2; + static _x: isize = 1<<2; } diff --git a/src/test/run-pass/issue-16643.rs b/src/test/run-pass/issue-16643.rs index 4e57c55c5f..54572296df 100644 --- a/src/test/run-pass/issue-16643.rs +++ b/src/test/run-pass/issue-16643.rs @@ -10,8 +10,10 @@ // aux-build:issue-16643.rs -extern crate "issue-16643" as i; +// pretty-expanded FIXME #23616 + +extern crate issue_16643 as i; pub fn main() { - i::TreeBuilder { h: 3u }.process_token(); + i::TreeBuilder { h: 3 }.process_token(); } diff --git a/src/test/run-pass/issue-16648.rs b/src/test/run-pass/issue-16648.rs index 0b58df56b6..f0ff9ce755 100644 --- a/src/test/run-pass/issue-16648.rs +++ b/src/test/run-pass/issue-16648.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + fn main() { - let x: (int, &[int]) = (2, &[1, 2]); + let x: (isize, &[isize]) = (2, &[1, 2]); assert_eq!(match x { (0, [_, _]) => 0, (1, _) => 1, diff --git a/src/test/run-pass/issue-16668.rs b/src/test/run-pass/issue-16668.rs index daf09047be..786c701a04 100644 --- a/src/test/run-pass/issue-16668.rs +++ b/src/test/run-pass/issue-16668.rs @@ -11,7 +11,6 @@ // ignore-pretty #![allow(unknown_features)] -#![feature(box_syntax)] #![feature(unboxed_closures)] struct Parser<'a, I, O> { @@ -20,13 +19,14 @@ struct Parser<'a, I, O> { impl<'a, I: 'a, O: 'a> Parser<'a, I, O> { fn compose(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. Parser { - parse: box move |x: I| { + parse: Box::new(move |x: I| { match (self.parse)(x) { Ok(r) => (rhs.parse)(r), Err(e) => Err(e) } - } + }) } } } diff --git a/src/test/run-pass/issue-16671.rs b/src/test/run-pass/issue-16671.rs index b06c4923c1..1ebe3a7f06 100644 --- a/src/test/run-pass/issue-16671.rs +++ b/src/test/run-pass/issue-16671.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// DON'T REENABLE THIS UNLESS YOU'VE ACTUALLY FIXED THE UNDERLYING ISSUE +// ignore-android seems to block forever #![forbid(warnings)] @@ -17,11 +19,13 @@ // A var moved into a proc, that has a mutable loan path should // not trigger a misleading unused_mut warning. +use std::io::prelude::*; use std::thread; pub fn main() { - let mut stdin = std::old_io::stdin(); + let mut stdin = std::io::stdin(); thread::spawn(move|| { - let _ = stdin.read_to_end(); - }); + let mut v = Vec::new(); + let _ = stdin.read_to_end(&mut v); + }).join().ok().unwrap(); } diff --git a/src/test/run-pass/issue-16739.rs b/src/test/run-pass/issue-16739.rs index 389baecafd..99ddaba4e5 100644 --- a/src/test/run-pass/issue-16739.rs +++ b/src/test/run-pass/issue-16739.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] // Test that unboxing shim for calling rust-call ABI methods through a // trait box works and does not cause an ICE. @@ -18,20 +20,36 @@ struct Foo { foo: u32 } impl FnMut<()> for Foo { - type Output = u32; extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo } } -impl FnMut<(u32,)> for Foo { +impl FnOnce<()> for Foo { type Output = u32; + extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } +} + +///////////////////////////////////////////////////////////////////////// + +impl FnMut<(u32,)> for Foo { extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } } -impl FnMut<(u32,u32)> for Foo { +impl FnOnce<(u32,)> for Foo { type Output = u32; + extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } +} + +///////////////////////////////////////////////////////////////////////// + +impl FnMut<(u32,u32)> for Foo { extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } } +impl FnOnce<(u32,u32)> for Foo { + type Output = u32; + extern "rust-call" fn call_once(mut self, args: (u32,u32)) -> u32 { self.call_mut(args) } +} + fn main() { let mut f = box Foo { foo: 42 } as Box u32>; assert_eq!(f.call_mut(()), 42); diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs index 2666130224..17d0969ce1 100644 --- a/src/test/run-pass/issue-16774.rs +++ b/src/test/run-pass/issue-16774.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #![feature(box_patterns)] @@ -15,7 +17,7 @@ use std::ops::{Deref, DerefMut}; -struct X(Box); +struct X(Box); static mut DESTRUCTOR_RAN: bool = false; @@ -29,16 +31,16 @@ impl Drop for X { } impl Deref for X { - type Target = int; + type Target = isize; - fn deref(&self) -> &int { + fn deref(&self) -> &isize { let &X(box ref x) = self; x } } impl DerefMut for X { - fn deref_mut(&mut self) -> &mut int { + fn deref_mut(&mut self) -> &mut isize { let &mut X(box ref mut x) = self; x } diff --git a/src/test/run-pass/issue-16783.rs b/src/test/run-pass/issue-16783.rs index c2bcbe045c..33cdbca14e 100644 --- a/src/test/run-pass/issue-16783.rs +++ b/src/test/run-pass/issue-16783.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = [1, 2, 3]; let y = x; diff --git a/src/test/run-pass/issue-16922.rs b/src/test/run-pass/issue-16922.rs new file mode 100644 index 0000000000..1fdc27eb12 --- /dev/null +++ b/src/test/run-pass/issue-16922.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +use std::any::Any; + +fn foo(_: &u8) { +} + +fn main() { + let _ = &foo as &Any; +} diff --git a/src/test/run-pass/issue-1696.rs b/src/test/run-pass/issue-1696.rs index 40e112d6fb..4c6c200c71 100644 --- a/src/test/run-pass/issue-1696.rs +++ b/src/test/run-pass/issue-1696.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(collections)] + extern crate collections; use std::collections::HashMap; diff --git a/src/test/run-pass/issue-1701.rs b/src/test/run-pass/issue-1701.rs index 9dc78ce0d4..b8c51f2cd3 100644 --- a/src/test/run-pass/issue-1701.rs +++ b/src/test/run-pass/issue-1701.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum pattern { tabby, tortoiseshell, calico } enum breed { beagle, rottweiler, pug } type name = String; diff --git a/src/test/run-pass/issue-17068.rs b/src/test/run-pass/issue-17068.rs index a0e6f2c9be..55a6d4cdba 100644 --- a/src/test/run-pass/issue-17068.rs +++ b/src/test/run-pass/issue-17068.rs @@ -10,7 +10,9 @@ // Test that regionck creates the right region links in the pattern // binding of a for loop -fn foo<'a>(v: &'a [uint]) -> &'a uint { +// pretty-expanded FIXME #23616 + +fn foo<'a>(v: &'a [usize]) -> &'a usize { for &ref x in v { return x; } unreachable!() } diff --git a/src/test/run-pass/issue-17074.rs b/src/test/run-pass/issue-17074.rs index d367e0e908..08c313ab0a 100644 --- a/src/test/run-pass/issue-17074.rs +++ b/src/test/run-pass/issue-17074.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static X2: u64 = -1 as u16 as u64; -static Y2: u64 = -1 as u32 as u64; -const X: u64 = -1 as u16 as u64; -const Y: u64 = -1 as u32 as u64; +// pretty-expanded FIXME #23616 + +static X2: u64 = !0 as u16 as u64; +static Y2: u64 = !0 as u32 as u64; +const X: u64 = !0 as u16 as u64; +const Y: u64 = !0 as u32 as u64; fn main() { assert_eq!(match 1 { diff --git a/src/test/run-pass/issue-17121.rs b/src/test/run-pass/issue-17121.rs index 2f0b8c9f19..366ef7543f 100644 --- a/src/test/run-pass/issue-17121.rs +++ b/src/test/run-pass/issue-17121.rs @@ -8,31 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io::BufReader; -use std::old_io::BufferedReader; -use std::old_io::File; -use std::old_io::IoResult; +// pretty-expanded FIXME #23616 -struct Lexer +use std::fs::File; +use std::io::{self, BufReader, Read}; + +struct Lexer { - reader: BufferedReader, + reader: BufReader, } -impl Lexer +impl Lexer { pub fn new_from_reader(r: R) -> Lexer { - Lexer{reader: BufferedReader::new(r)} + Lexer{reader: BufReader::new(r)} } - pub fn new_from_file(p: Path) -> IoResult> + pub fn new_from_file(p: &str) -> io::Result> { - Ok(Lexer::new_from_reader(try!(File::open(&p)))) + Ok(Lexer::new_from_reader(try!(File::open(p)))) } - pub fn new_from_str<'a>(s: &'a str) -> Lexer> + pub fn new_from_str<'a>(s: &'a str) -> Lexer<&'a [u8]> { - Lexer::new_from_reader(BufReader::new(s.as_bytes())) + Lexer::new_from_reader(s.as_bytes()) } } diff --git a/src/test/run-pass/issue-17216.rs b/src/test/run-pass/issue-17216.rs index ce5a0aa96e..f17834e8d3 100644 --- a/src/test/run-pass/issue-17216.rs +++ b/src/test/run-pass/issue-17216.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] struct Leak<'a> { @@ -25,9 +27,7 @@ fn main() { let mut dropped = false; { let leak = Leak { dropped: &mut dropped }; - // FIXME(#21721) "hack" used to be () but that can cause - // certain LLVM versions to abort during optimizations. - for (_, leaked) in Some(("hack", leak)).into_iter() {} + for ((), leaked) in Some(((), leak)).into_iter() {} } assert!(dropped); diff --git a/src/test/run-pass/issue-17233.rs b/src/test/run-pass/issue-17233.rs new file mode 100644 index 0000000000..756822d4f4 --- /dev/null +++ b/src/test/run-pass/issue-17233.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +const X1: &'static [u8] = &[b'1']; +const X2: &'static [u8] = b"1"; +const X3: &'static [u8; 1] = &[b'1']; +const X4: &'static [u8; 1] = b"1"; + +static Y1: u8 = X1[0]; +static Y2: u8 = X2[0]; +static Y3: u8 = X3[0]; +static Y4: u8 = X4[0]; + +fn main() { + assert_eq!(Y1, Y2); + assert_eq!(Y1, Y3); + assert_eq!(Y1, Y4); +} diff --git a/src/test/run-pass/issue-17302.rs b/src/test/run-pass/issue-17302.rs index b2abf2d2b1..35bd07c896 100644 --- a/src/test/run-pass/issue-17302.rs +++ b/src/test/run-pass/issue-17302.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + static mut DROPPED: [bool; 2] = [false, false]; -struct A(uint); -struct Foo { _a: A, _b: int } +struct A(usize); +struct Foo { _a: A, _b: isize } impl Drop for A { fn drop(&mut self) { diff --git a/src/test/run-pass/issue-17322.rs b/src/test/run-pass/issue-17322.rs index dd1cfb5e34..a9f5476d0f 100644 --- a/src/test/run-pass/issue-17322.rs +++ b/src/test/run-pass/issue-17322.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, io)] -use std::old_io; +use std::io::{self, Write}; -fn f(wr: &mut Writer) { - wr.write_str("hello").ok().expect("failed"); +fn f(wr: &mut Write) { + wr.write_all(b"hello").ok().expect("failed"); } fn main() { - let mut wr = box old_io::stdout() as Box; + let mut wr = box io::stdout() as Box; f(&mut wr); } diff --git a/src/test/run-pass/issue-17351.rs b/src/test/run-pass/issue-17351.rs index 0966d4ea45..6e93194647 100644 --- a/src/test/run-pass/issue-17351.rs +++ b/src/test/run-pass/issue-17351.rs @@ -8,6 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + +trait Str { fn foo(&self) {} } +impl Str for str {} +impl<'a, S: ?Sized> Str for &'a S where S: Str {} + fn main() { let _: &Str = &"x"; } diff --git a/src/test/run-pass/issue-17361.rs b/src/test/run-pass/issue-17361.rs index 092bcf661a..354b086175 100644 --- a/src/test/run-pass/issue-17361.rs +++ b/src/test/run-pass/issue-17361.rs @@ -10,6 +10,8 @@ // Test that astconv doesn't forget about mutability of &mut str +// pretty-expanded FIXME #23616 + fn main() { fn foo(_: &mut T) {} let _f: fn(&mut str) = foo; diff --git a/src/test/run-pass/issue-17503.rs b/src/test/run-pass/issue-17503.rs index a071224999..796277ce74 100644 --- a/src/test/run-pass/issue-17503.rs +++ b/src/test/run-pass/issue-17503.rs @@ -9,9 +9,9 @@ // except according to those terms. fn main() { - let s: &[int] = &[0, 1, 2, 3, 4]; - let ss: &&[int] = &s; - let sss: &&&[int] = &ss; + let s: &[isize] = &[0, 1, 2, 3, 4]; + let ss: &&[isize] = &s; + let sss: &&&[isize] = &ss; println!("{:?}", &s[..3]); println!("{:?}", &ss[3..]); diff --git a/src/test/run-pass/issue-17662.rs b/src/test/run-pass/issue-17662.rs index 7bd41cc5b5..36e12b96c8 100644 --- a/src/test/run-pass/issue-17662.rs +++ b/src/test/run-pass/issue-17662.rs @@ -10,14 +10,16 @@ // aux-build:issue-17662.rs -extern crate "issue-17662" as i; +// pretty-expanded FIXME #23616 + +extern crate issue_17662 as i; use std::marker; struct Bar<'a> { m: marker::PhantomData<&'a ()> } -impl<'a> i::Foo<'a, uint> for Bar<'a> { - fn foo(&self) -> uint { 5_usize } +impl<'a> i::Foo<'a, usize> for Bar<'a> { + fn foo(&self) -> usize { 5 } } pub fn main() { diff --git a/src/test/run-pass/issue-17718-parse-const.rs b/src/test/run-pass/issue-17718-parse-const.rs index 3ca6f473a7..1fc8f3274d 100644 --- a/src/test/run-pass/issue-17718-parse-const.rs +++ b/src/test/run-pass/issue-17718-parse-const.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const FOO: uint = 3; +// pretty-expanded FIXME #23616 + +const FOO: usize = 3; fn main() { assert_eq!(FOO, 3); diff --git a/src/test/run-pass/issue-17718-static-unsafe-interior.rs b/src/test/run-pass/issue-17718-static-unsafe-interior.rs index cdd03244df..29d72000d0 100644 --- a/src/test/run-pass/issue-17718-static-unsafe-interior.rs +++ b/src/test/run-pass/issue-17718-static-unsafe-interior.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::marker; use std::cell::UnsafeCell; @@ -32,13 +36,13 @@ enum UnsafeEnum { unsafe impl Sync for UnsafeEnum {} -static STATIC1: UnsafeEnum = UnsafeEnum::VariantSafe; +static STATIC1: UnsafeEnum = UnsafeEnum::VariantSafe; -static STATIC2: MyUnsafePack = MyUnsafePack(UnsafeCell { value: 1 }); -const CONST: MyUnsafePack = MyUnsafePack(UnsafeCell { value: 1 }); -static STATIC3: MyUnsafe = MyUnsafe{value: CONST}; +static STATIC2: MyUnsafePack = MyUnsafePack(UnsafeCell { value: 1 }); +const CONST: MyUnsafePack = MyUnsafePack(UnsafeCell { value: 1 }); +static STATIC3: MyUnsafe = MyUnsafe{value: CONST}; -static STATIC4: &'static MyUnsafePack = &STATIC2; +static STATIC4: &'static MyUnsafePack = &STATIC2; struct Wrap { value: T @@ -46,8 +50,8 @@ struct Wrap { unsafe impl Sync for Wrap {} -static UNSAFE: MyUnsafePack = MyUnsafePack(UnsafeCell{value: 2}); -static WRAPPED_UNSAFE: Wrap<&'static MyUnsafePack> = Wrap { value: &UNSAFE }; +static UNSAFE: MyUnsafePack = MyUnsafePack(UnsafeCell{value: 2}); +static WRAPPED_UNSAFE: Wrap<&'static MyUnsafePack> = Wrap { value: &UNSAFE }; fn main() { let a = &STATIC1; diff --git a/src/test/run-pass/issue-17718.rs b/src/test/run-pass/issue-17718.rs index e4782e2892..13e082eada 100644 --- a/src/test/run-pass/issue-17718.rs +++ b/src/test/run-pass/issue-17718.rs @@ -10,27 +10,31 @@ // aux-build:issue-17718.rs -extern crate "issue-17718" as other; +// pretty-expanded FIXME #23616 + +#![feature(core)] + +extern crate issue_17718 as other; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; -const C1: uint = 1; +const C1: usize = 1; const C2: AtomicUsize = ATOMIC_USIZE_INIT; const C3: fn() = foo; -const C4: uint = C1 * C1 + C1 / C1; -const C5: &'static uint = &C4; -const C6: uint = { - const C: uint = 3; +const C4: usize = C1 * C1 + C1 / C1; +const C5: &'static usize = &C4; +const C6: usize = { + const C: usize = 3; C }; -static S1: uint = 3; +static S1: usize = 3; static S2: AtomicUsize = ATOMIC_USIZE_INIT; mod test { - static A: uint = 4; - static B: &'static uint = &A; - static C: &'static uint = &(A); + static A: usize = 4; + static B: &'static usize = &A; + static C: &'static usize = &(A); } fn foo() {} diff --git a/src/test/run-pass/issue-17732.rs b/src/test/run-pass/issue-17732.rs index de9611f259..9a678f0015 100644 --- a/src/test/run-pass/issue-17732.rs +++ b/src/test/run-pass/issue-17732.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Person { type string; fn dummy(&self) { } diff --git a/src/test/run-pass/issue-17734.rs b/src/test/run-pass/issue-17734.rs index 3cff16409c..3cf9c62b40 100644 --- a/src/test/run-pass/issue-17734.rs +++ b/src/test/run-pass/issue-17734.rs @@ -10,8 +10,7 @@ // Test that generating drop glue for Box doesn't ICE -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 fn f(s: Box) -> Box { s @@ -19,7 +18,9 @@ fn f(s: Box) -> Box { fn main() { // There is currently no safe way to construct a `Box`, so improvise - let box_arr: Box<[u8]> = box ['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8]; + // + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let box_arr: Box<[u8]> = Box::new(['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8]); let box_str: Box = unsafe { std::mem::transmute(box_arr) }; assert_eq!(&*box_str, "hello"); f(box_str); diff --git a/src/test/run-pass/issue-17746.rs b/src/test/run-pass/issue-17746.rs new file mode 100644 index 0000000000..a66d5e1028 --- /dev/null +++ b/src/test/run-pass/issue-17746.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #17746 + +fn main() {} + +struct A; + +impl A { + fn b(&mut self) { + self.a() + } +} + +trait Foo { + fn dummy(&self) {} +} +trait Bar { + fn a(&self); +} + +impl Foo for A {} +impl Bar for T where T: Foo { + fn a(&self) {} +} diff --git a/src/test/run-pass/issue-17771.rs b/src/test/run-pass/issue-17771.rs index 2f1b0342b8..fc82144133 100644 --- a/src/test/run-pass/issue-17771.rs +++ b/src/test/run-pass/issue-17771.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Aaa { fn dummy(&self) { } } impl<'a> Aaa for &'a mut (Aaa + 'a) {} diff --git a/src/test/run-pass/issue-17816.rs b/src/test/run-pass/issue-17816.rs index a976eccf89..65a0b51095 100644 --- a/src/test/run-pass/issue-17816.rs +++ b/src/test/run-pass/issue-17816.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::marker::PhantomData; fn main() { struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F, marker: PhantomData<&'a ()> } - let f = |x: Vec<&str>| -> &str "foobar"; + let f = |x: Vec<&str>| -> &str { "foobar" }; let sym = Symbol { function: f, marker: PhantomData }; (sym.function)(vec![]); } diff --git a/src/test/run-pass/issue-17877.rs b/src/test/run-pass/issue-17877.rs index a7d9e6a4be..41fab9d9d5 100644 --- a/src/test/run-pass/issue-17877.rs +++ b/src/test/run-pass/issue-17877.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + fn main() { assert_eq!(match [0u8; 1024] { _ => 42_usize, diff --git a/src/test/run-pass/issue-17897.rs b/src/test/run-pass/issue-17897.rs index 3774aaa190..cf8c54fdd8 100644 --- a/src/test/run-pass/issue-17897.rs +++ b/src/test/run-pass/issue-17897.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +#![feature(unboxed_closures, std_misc)] use std::thunk::Thunk; -fn action(cb: Thunk) -> uint { - cb.invoke(1) +fn action(cb: Thunk<(usize,), usize>) -> usize { + cb(1) } pub fn main() { - println!("num: {}", action(Thunk::with_arg(move |u| u))); + println!("num: {}", action(Box::new(move |u| u))); } diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs index 58a0872a57..994001a82c 100644 --- a/src/test/run-pass/issue-17904.rs +++ b/src/test/run-pass/issue-17904.rs @@ -11,6 +11,8 @@ // Test that we can parse where clauses on various forms of tuple // structs. +// pretty-expanded FIXME #23616 + struct Bar(T) where T: Copy; struct Bleh(T, U) where T: Copy, U: Sized; struct Baz where T: Copy { diff --git a/src/test/run-pass/issue-18110.rs b/src/test/run-pass/issue-18110.rs index 3d6b23c880..eecdea66cf 100644 --- a/src/test/run-pass/issue-18110.rs +++ b/src/test/run-pass/issue-18110.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { ({return},); } diff --git a/src/test/run-pass/issue-18188.rs b/src/test/run-pass/issue-18188.rs index a4b09eb08e..059d25173c 100644 --- a/src/test/run-pass/issue-18188.rs +++ b/src/test/run-pass/issue-18188.rs @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, std_misc)] use std::thunk::Thunk; pub trait Promisable: Send + Sync {} impl Promisable for T {} -pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a,Result, Result> +pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a, (Result,), Result> where T: Promisable + Clone + 'a, E: Promisable + Clone + 'a, F: FnOnce(&T) -> Result + Send + 'a, G: FnOnce(Result) -> Result + 'a { - Thunk::with_arg(move |result: Result| { + Box::new(move |result: Result| { match result { Ok(ref t) => action(t), Err(ref e) => Err(e.clone()), diff --git a/src/test/run-pass/issue-1821.rs b/src/test/run-pass/issue-1821.rs index b7c4bb0fe0..bdff5ba484 100644 --- a/src/test/run-pass/issue-1821.rs +++ b/src/test/run-pass/issue-1821.rs @@ -11,6 +11,8 @@ // Issue #1821 - Don't recurse trying to typecheck this +// pretty-expanded FIXME #23616 + enum t { foo(Vec) } diff --git a/src/test/run-pass/issue-18232.rs b/src/test/run-pass/issue-18232.rs index 67b3239d35..376d6523cc 100644 --- a/src/test/run-pass/issue-18232.rs +++ b/src/test/run-pass/issue-18232.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Cursor<'a>(::std::marker::PhantomData<&'a ()>); trait CursorNavigator { diff --git a/src/test/run-pass/issue-18352.rs b/src/test/run-pass/issue-18352.rs index e5532b4550..4e60a7d9b5 100644 --- a/src/test/run-pass/issue-18352.rs +++ b/src/test/run-pass/issue-18352.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + const X: &'static str = "12345"; fn test(s: String) -> bool { diff --git a/src/test/run-pass/issue-18353.rs b/src/test/run-pass/issue-18353.rs index c734c1a322..1386c9d0da 100644 --- a/src/test/run-pass/issue-18353.rs +++ b/src/test/run-pass/issue-18353.rs @@ -11,6 +11,8 @@ // Test that wrapping an unsized struct in an enum which gets optimised does // not ICE. +// pretty-expanded FIXME #23616 + struct Str { f: [u8] } diff --git a/src/test/run-pass/issue-18412.rs b/src/test/run-pass/issue-18412.rs index 63f57e0a2e..41dacd3320 100644 --- a/src/test/run-pass/issue-18412.rs +++ b/src/test/run-pass/issue-18412.rs @@ -11,18 +11,20 @@ // Test that non-static methods can be assigned to local variables as // function pointers. +// pretty-expanded FIXME #23616 + trait Foo { - fn foo(&self) -> uint; + fn foo(&self) -> usize; } -struct A(uint); +struct A(usize); impl A { - fn bar(&self) -> uint { self.0 } + fn bar(&self) -> usize { self.0 } } impl Foo for A { - fn foo(&self) -> uint { self.bar() } + fn foo(&self) -> usize { self.bar() } } fn main() { diff --git a/src/test/run-pass/issue-18425.rs b/src/test/run-pass/issue-18425.rs index ec7481ead0..eb7e504ae1 100644 --- a/src/test/run-pass/issue-18425.rs +++ b/src/test/run-pass/issue-18425.rs @@ -11,9 +11,8 @@ // Check that trans doesn't ICE when translating an array repeat // expression with a count of 1 and a non-Copy element type. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 fn main() { - let _ = [box 1_usize; 1]; + let _ = [Box::new(1_usize); 1]; } diff --git a/src/test/run-pass/issue-18501.rs b/src/test/run-pass/issue-18501.rs index ce02694294..fb8158c6dd 100644 --- a/src/test/run-pass/issue-18501.rs +++ b/src/test/run-pass/issue-18501.rs @@ -13,7 +13,9 @@ // translating the def ID of the trait during AST decoding. // aux-build:issue-18501.rs -extern crate "issue-18501" as issue; +// pretty-expanded FIXME #23616 + +extern crate issue_18501 as issue; fn main() { issue::pass_method(); diff --git a/src/test/run-pass/issue-18514.rs b/src/test/run-pass/issue-18514.rs index c75abd62de..b0b2f068bb 100644 --- a/src/test/run-pass/issue-18514.rs +++ b/src/test/run-pass/issue-18514.rs @@ -15,7 +15,9 @@ // impl. // aux-build:issue-18514.rs -extern crate "issue-18514" as ice; +// pretty-expanded FIXME #23616 + +extern crate issue_18514 as ice; use ice::{Tr, St}; fn main() { diff --git a/src/test/run-pass/issue-18539.rs b/src/test/run-pass/issue-18539.rs index ce56f3e8d7..8de2d1e425 100644 --- a/src/test/run-pass/issue-18539.rs +++ b/src/test/run-pass/issue-18539.rs @@ -11,13 +11,15 @@ // Test that coercing bare fn's that return a zero sized type to // a closure doesn't cause an LLVM ERROR +// pretty-expanded FIXME #23616 + struct Foo; -fn uint_to_foo(_: uint) -> Foo { +fn uint_to_foo(_: usize) -> Foo { Foo } #[allow(unused_must_use)] fn main() { - (0_usize..10).map(uint_to_foo); + (0..10).map(uint_to_foo); } diff --git a/src/test/run-pass/issue-18619.rs b/src/test/run-pass/issue-18619.rs index 6b6296b0bd..a256e61921 100644 --- a/src/test/run-pass/issue-18619.rs +++ b/src/test/run-pass/issue-18619.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io)] + use std::old_io::FileType; pub fn main() { diff --git a/src/test/run-pass/issue-18652.rs b/src/test/run-pass/issue-18652.rs index 8f560258d9..a3affb7bf8 100644 --- a/src/test/run-pass/issue-18652.rs +++ b/src/test/run-pass/issue-18652.rs @@ -12,6 +12,8 @@ // once closure as an optimization by trans. This used to hit an // incorrect assert. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn main() { diff --git a/src/test/run-pass/issue-1866.rs b/src/test/run-pass/issue-1866.rs index 10ae2749a0..2c346b93f5 100644 --- a/src/test/run-pass/issue-1866.rs +++ b/src/test/run-pass/issue-1866.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod a { - pub type rust_task = uint; + pub type rust_task = usize; pub mod rustrt { use super::rust_task; extern { diff --git a/src/test/run-pass/issue-18661.rs b/src/test/run-pass/issue-18661.rs index bb2907241c..302f5ddcc6 100644 --- a/src/test/run-pass/issue-18661.rs +++ b/src/test/run-pass/issue-18661.rs @@ -11,7 +11,9 @@ // Test that param substitutions from the correct environment are // used when translating unboxed closure calls. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] pub fn inside(c: F) { c.call(()); diff --git a/src/test/run-pass/issue-18685.rs b/src/test/run-pass/issue-18685.rs index 698b61e575..e4537e158d 100644 --- a/src/test/run-pass/issue-18685.rs +++ b/src/test/run-pass/issue-18685.rs @@ -11,6 +11,8 @@ // Test that the self param space is not used in a conflicting // manner by unboxed closures within a default method on a trait +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] trait Tr { diff --git a/src/test/run-pass/issue-18711.rs b/src/test/run-pass/issue-18711.rs index 0338a4eff2..277ad3260c 100644 --- a/src/test/run-pass/issue-18711.rs +++ b/src/test/run-pass/issue-18711.rs @@ -11,10 +11,12 @@ // Test that we don't panic on a RefCell borrow conflict in certain // code paths involving unboxed closures. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] // aux-build:issue-18711.rs -extern crate "issue-18711" as issue; +extern crate issue_18711 as issue; fn main() { (|| issue::inner(()))(); diff --git a/src/test/run-pass/issue-18738.rs b/src/test/run-pass/issue-18738.rs index 30ad827c69..a92fcb01f5 100644 --- a/src/test/run-pass/issue-18738.rs +++ b/src/test/run-pass/issue-18738.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Eq, PartialEq, PartialOrd, Ord)] enum Test<'a> { - Int(&'a int), + Int(&'a isize), Slice(&'a [u8]), } diff --git a/src/test/run-pass/issue-18767.rs b/src/test/run-pass/issue-18767.rs index 2f23b8028e..8e51a900c0 100644 --- a/src/test/run-pass/issue-18767.rs +++ b/src/test/run-pass/issue-18767.rs @@ -11,6 +11,8 @@ // Test that regionck uses the right memcat for patterns in for loops // and doesn't ICE. +// pretty-expanded FIXME #23616 + fn main() { for &&x in Some(&0_usize).iter() { assert_eq!(x, 0) diff --git a/src/test/run-pass/issue-18859.rs b/src/test/run-pass/issue-18859.rs index 490f7eb6be..16e6c99f0e 100644 --- a/src/test/run-pass/issue-18859.rs +++ b/src/test/run-pass/issue-18859.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod foo { pub mod bar { pub mod baz { @@ -19,6 +21,6 @@ mod foo { } fn main() { - assert_eq!(module_path!(), "issue-18859"); - assert_eq!(foo::bar::baz::name(), "issue-18859::foo::bar::baz"); + assert_eq!(module_path!(), "issue_18859"); + assert_eq!(foo::bar::baz::name(), "issue_18859::foo::bar::baz"); } diff --git a/src/test/run-pass/issue-18906.rs b/src/test/run-pass/issue-18906.rs index 16dd84315e..7cc61dd253 100644 --- a/src/test/run-pass/issue-18906.rs +++ b/src/test/run-pass/issue-18906.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub trait Borrow { fn borrow(&self) -> &Borrowed; } diff --git a/src/test/run-pass/issue-19037.rs b/src/test/run-pass/issue-19037.rs index ac181c8db7..0735693a4b 100644 --- a/src/test/run-pass/issue-19037.rs +++ b/src/test/run-pass/issue-19037.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Str([u8]); #[derive(Clone)] diff --git a/src/test/run-pass/issue-19098.rs b/src/test/run-pass/issue-19098.rs index ef95b4d4f0..a0368063f2 100644 --- a/src/test/run-pass/issue-19098.rs +++ b/src/test/run-pass/issue-19098.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] pub trait Handler { fn handle(&self, &mut String); diff --git a/src/test/run-pass/issue-19100.rs b/src/test/run-pass/issue-19100.rs index 26eacd682e..0fd4b4394d 100644 --- a/src/test/run-pass/issue-19100.rs +++ b/src/test/run-pass/issue-19100.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +#[derive(Copy, Clone)] enum Foo { Bar, Baz diff --git a/src/test/run-pass/issue-19121.rs b/src/test/run-pass/issue-19121.rs index 222f67af43..e02d001ee9 100644 --- a/src/test/run-pass/issue-19121.rs +++ b/src/test/run-pass/issue-19121.rs @@ -11,6 +11,8 @@ // Test that a partially specified trait object with unspecified associated // type does not ICE. +// pretty-expanded FIXME #23616 + trait Foo { type A; diff --git a/src/test/run-pass/issue-19127.rs b/src/test/run-pass/issue-19127.rs index bc43874bfb..c5eb506932 100644 --- a/src/test/run-pass/issue-19127.rs +++ b/src/test/run-pass/issue-19127.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn foo T>(f: F) {} diff --git a/src/test/run-pass/issue-19129-1.rs b/src/test/run-pass/issue-19129-1.rs index 3436871b4d..f9b605c44e 100644 --- a/src/test/run-pass/issue-19129-1.rs +++ b/src/test/run-pass/issue-19129-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Trait { type Output; diff --git a/src/test/run-pass/issue-19129-2.rs b/src/test/run-pass/issue-19129-2.rs index cf0f48e025..47b8aaacda 100644 --- a/src/test/run-pass/issue-19129-2.rs +++ b/src/test/run-pass/issue-19129-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Trait { type Output; diff --git a/src/test/run-pass/issue-19244.rs b/src/test/run-pass/issue-19244.rs index 9af4d30c4f..f25450a891 100644 --- a/src/test/run-pass/issue-19244.rs +++ b/src/test/run-pass/issue-19244.rs @@ -8,14 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct MyStruct { field: uint } +// pretty-expanded FIXME #23616 + +struct MyStruct { field: usize } +struct Nested { nested: MyStruct } +struct Mix2 { nested: ((usize,),) } + const STRUCT: MyStruct = MyStruct { field: 42 }; -const TUP: (uint,) = (43,); +const TUP: (usize,) = (43,); +const NESTED_S: Nested = Nested { nested: MyStruct { field: 5 } }; +const NESTED_T: ((usize,),) = ((4,),); +const MIX_1: ((Nested,),) = ((Nested { nested: MyStruct { field: 3 } },),); +const MIX_2: Mix2 = Mix2 { nested: ((2,),) }; +const INSTANT_1: usize = (MyStruct { field: 1 }).field; +const INSTANT_2: usize = (0,).0; fn main() { let a = [0; STRUCT.field]; let b = [0; TUP.0]; + let c = [0; NESTED_S.nested.field]; + let d = [0; (NESTED_T.0).0]; + let e = [0; (MIX_1.0).0.nested.field]; + let f = [0; (MIX_2.nested.0).0]; + let g = [0; INSTANT_1]; + let h = [0; INSTANT_2]; - assert!(a.len() == 42); - assert!(b.len() == 43); + assert_eq!(a.len(), 42); + assert_eq!(b.len(), 43); + assert_eq!(c.len(), 5); + assert_eq!(d.len(), 4); + assert_eq!(e.len(), 3); + assert_eq!(f.len(), 2); + assert_eq!(g.len(), 1); + assert_eq!(h.len(), 0); } diff --git a/src/test/run-pass/issue-19293.rs b/src/test/run-pass/issue-19293.rs index 4a446a76de..95ca3efb09 100644 --- a/src/test/run-pass/issue-19293.rs +++ b/src/test/run-pass/issue-19293.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:issue_19293.rs +// pretty-expanded FIXME #23616 + extern crate issue_19293; use issue_19293::{Foo, MyEnum}; diff --git a/src/test/run-pass/issue-19340-1.rs b/src/test/run-pass/issue-19340-1.rs index 2f466d4ca8..e553c244c8 100644 --- a/src/test/run-pass/issue-19340-1.rs +++ b/src/test/run-pass/issue-19340-1.rs @@ -10,7 +10,9 @@ // aux-build:issue-19340-1.rs -extern crate "issue-19340-1" as lib; +// pretty-expanded FIXME #23616 + +extern crate issue_19340_1 as lib; use lib::Homura; diff --git a/src/test/run-pass/issue-19340-2.rs b/src/test/run-pass/issue-19340-2.rs index 8300220ede..d7747201cb 100644 --- a/src/test/run-pass/issue-19340-2.rs +++ b/src/test/run-pass/issue-19340-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Homura { Madoka { name: String, diff --git a/src/test/run-pass/issue-19358.rs b/src/test/run-pass/issue-19358.rs index 8b5269ab92..c0c210b3e9 100644 --- a/src/test/run-pass/issue-19358.rs +++ b/src/test/run-pass/issue-19358.rs @@ -20,7 +20,7 @@ struct Bar where T: Trait { bar: T, } -impl Trait for int {} +impl Trait for isize {} fn main() { let a = Foo { foo: 12 }; diff --git a/src/test/run-pass/issue-19398.rs b/src/test/run-pass/issue-19398.rs index e603167b26..2dc5a6e997 100644 --- a/src/test/run-pass/issue-19398.rs +++ b/src/test/run-pass/issue-19398.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait T { unsafe extern "Rust" fn foo(&self); } diff --git a/src/test/run-pass/issue-19479.rs b/src/test/run-pass/issue-19479.rs index 38a7af3a69..7557c1b44e 100644 --- a/src/test/run-pass/issue-19479.rs +++ b/src/test/run-pass/issue-19479.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Base { fn dummy(&self) { } } diff --git a/src/test/run-pass/issue-19499.rs b/src/test/run-pass/issue-19499.rs index 0578db8f85..069ceadf91 100644 --- a/src/test/run-pass/issue-19499.rs +++ b/src/test/run-pass/issue-19499.rs @@ -14,6 +14,8 @@ // reasonable examples) let to ambiguity errors about not being able // to infer sufficient type information. +// pretty-expanded FIXME #23616 + fn main() { let n = 0; let it = Some(1_usize).into_iter().inspect(|_| {n;}); diff --git a/src/test/run-pass/issue-19631.rs b/src/test/run-pass/issue-19631.rs index 7bb0d055b8..562d2e4169 100644 --- a/src/test/run-pass/issue-19631.rs +++ b/src/test/run-pass/issue-19631.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait PoolManager { type C; fn dummy(&self) { } diff --git a/src/test/run-pass/issue-19632.rs b/src/test/run-pass/issue-19632.rs index 4339339d74..1cb20011c2 100644 --- a/src/test/run-pass/issue-19632.rs +++ b/src/test/run-pass/issue-19632.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait PoolManager { type C; fn dummy(&self) { } diff --git a/src/test/run-pass/issue-1974.rs b/src/test/run-pass/issue-1974.rs index 9d71aea01d..7b33b4e7a4 100644 --- a/src/test/run-pass/issue-1974.rs +++ b/src/test/run-pass/issue-1974.rs @@ -10,6 +10,8 @@ // Issue 1974 // Don't double free the condition allocation +// pretty-expanded FIXME #23616 + pub fn main() { let s = "hej".to_string(); while s != "".to_string() { diff --git a/src/test/run-pass/issue-19811-escape-unicode.rs b/src/test/run-pass/issue-19811-escape-unicode.rs index 23400859e5..5b415c6388 100644 --- a/src/test/run-pass/issue-19811-escape-unicode.rs +++ b/src/test/run-pass/issue-19811-escape-unicode.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + fn main() { let mut escaped = String::from_str(""); for c in '\u{10401}'.escape_unicode() { diff --git a/src/test/run-pass/issue-19850.rs b/src/test/run-pass/issue-19850.rs index a9ce6c7a9e..15ca6a9d4c 100644 --- a/src/test/run-pass/issue-19850.rs +++ b/src/test/run-pass/issue-19850.rs @@ -11,9 +11,11 @@ // Test that `::Output` and `Self::Output` are accepted as type annotations in let // bindings +// pretty-expanded FIXME #23616 + trait Int { fn one() -> Self; - fn leading_zeros(self) -> uint; + fn leading_zeros(self) -> usize; } trait Foo { diff --git a/src/test/run-pass/issue-19982.rs b/src/test/run-pass/issue-19982.rs new file mode 100644 index 0000000000..9442b039bc --- /dev/null +++ b/src/test/run-pass/issue-19982.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![feature(core,unboxed_closures)] + +#[allow(dead_code)] +struct Foo; + +impl<'a> Fn<(&'a (),)> for Foo { + extern "rust-call" fn call(&self, (_,): (&(),)) {} +} + +impl<'a> FnMut<(&'a (),)> for Foo { + extern "rust-call" fn call_mut(&mut self, (_,): (&(),)) {} +} + +impl<'a> FnOnce<(&'a (),)> for Foo { + type Output = (); + + extern "rust-call" fn call_once(self, (_,): (&(),)) {} +} + +fn main() {} diff --git a/src/test/run-pass/issue-20009.rs b/src/test/run-pass/issue-20009.rs index 374460487d..9d433eabe6 100644 --- a/src/test/run-pass/issue-20009.rs +++ b/src/test/run-pass/issue-20009.rs @@ -10,6 +10,8 @@ // Check that associated types are `Sized` +// pretty-expanded FIXME #23616 + trait Trait { type Output; diff --git a/src/test/run-pass/issue-20055-box-trait.rs b/src/test/run-pass/issue-20055-box-trait.rs index 572a0d8252..7e89cfe24e 100644 --- a/src/test/run-pass/issue-20055-box-trait.rs +++ b/src/test/run-pass/issue-20055-box-trait.rs @@ -41,10 +41,10 @@ pub fn foo(box_1: fn () -> Box<[i8; 1]>, } pub fn main() { - fn box_1() -> Box<[i8; 1]> { Box::new( [1i8; 1] ) } - fn box_2() -> Box<[i8; 2]> { Box::new( [1i8; 2] ) } - fn box_3() -> Box<[i8; 3]> { Box::new( [1i8; 3] ) } - fn box_4() -> Box<[i8; 4]> { Box::new( [1i8; 4] ) } + fn box_1() -> Box<[i8; 1]> { Box::new( [1; 1] ) } + fn box_2() -> Box<[i8; 2]> { Box::new( [1; 2] ) } + fn box_3() -> Box<[i8; 3]> { Box::new( [1; 3] ) } + fn box_4() -> Box<[i8; 4]> { Box::new( [1; 4] ) } foo(box_1, box_2, box_3, box_4); } diff --git a/src/test/run-pass/issue-20055-box-unsized-array.rs b/src/test/run-pass/issue-20055-box-unsized-array.rs index f751be6f13..5af5186e94 100644 --- a/src/test/run-pass/issue-20055-box-unsized-array.rs +++ b/src/test/run-pass/issue-20055-box-unsized-array.rs @@ -29,10 +29,10 @@ pub fn foo(box_1: fn () -> Box<[i8; 1]>, } pub fn main() { - fn box_1() -> Box<[i8; 1]> { Box::new( [1i8] ) } - fn box_2() -> Box<[i8; 20]> { Box::new( [1i8; 20] ) } - fn box_3() -> Box<[i8; 300]> { Box::new( [1i8; 300] ) } - fn box_4() -> Box<[i8; 4000]> { Box::new( [1i8; 4000] ) } + fn box_1() -> Box<[i8; 1]> { Box::new( [1] ) } + fn box_2() -> Box<[i8; 20]> { Box::new( [1; 20] ) } + fn box_3() -> Box<[i8; 300]> { Box::new( [1; 300] ) } + fn box_4() -> Box<[i8; 4000]> { Box::new( [1; 4000] ) } foo(box_1, box_2, box_3, box_4); } diff --git a/src/test/run-pass/issue-20091.rs b/src/test/run-pass/issue-20091.rs index 4d20e6360a..1fe4434846 100644 --- a/src/test/run-pass/issue-20091.rs +++ b/src/test/run-pass/issue-20091.rs @@ -8,14 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-windows currently windows requires UTF-8 for spawning processes - -use std::old_io::Command; -use std::env; +// ignore-aarch64 +#![feature(std_misc, os)] +#[cfg(unix)] fn main() { + use std::process::Command; + use std::env; + use std::os::unix::prelude::*; + use std::ffi::OsStr; + if env::args().len() == 1 { - assert!(Command::new(env::current_exe().unwrap()).arg(b"\xff") + assert!(Command::new(&env::current_exe().unwrap()) + .arg(::from_bytes(b"\xff")) .status().unwrap().success()) } } + +#[cfg(windows)] +fn main() {} diff --git a/src/test/run-pass/issue-20313.rs b/src/test/run-pass/issue-20313.rs index 47791ceecb..0e5eaf857f 100644 --- a/src/test/run-pass/issue-20313.rs +++ b/src/test/run-pass/issue-20313.rs @@ -7,6 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(link_llvm_intrinsics)] extern { diff --git a/src/test/run-pass/issue-20343.rs b/src/test/run-pass/issue-20343.rs index 2f9e8feed2..70064f4e26 100644 --- a/src/test/run-pass/issue-20343.rs +++ b/src/test/run-pass/issue-20343.rs @@ -10,6 +10,8 @@ // Regression test for Issue #20343. +// pretty-expanded FIXME #23616 + #![deny(dead_code)] struct B { b: u32 } diff --git a/src/test/run-pass/issue-20389.rs b/src/test/run-pass/issue-20389.rs index 877cec48b5..03c7e9f8db 100644 --- a/src/test/run-pass/issue-20389.rs +++ b/src/test/run-pass/issue-20389.rs @@ -10,6 +10,8 @@ // aux-build:issue_20389.rs +// pretty-expanded FIXME #23616 + extern crate issue_20389; struct Foo; diff --git a/src/test/run-pass/issue-20396.rs b/src/test/run-pass/issue-20396.rs new file mode 100644 index 0000000000..f607ed373b --- /dev/null +++ b/src/test/run-pass/issue-20396.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Foo { + fn noop(&self, _: T); +} + +enum Bar { Bla(T) } + +struct Baz<'a> { + inner: for<'b> Foo> + 'a, +} + +fn main() {} diff --git a/src/test/run-pass/issue-20414.rs b/src/test/run-pass/issue-20414.rs index 92865c419b..d2e2d9bd6e 100644 --- a/src/test/run-pass/issue-20414.rs +++ b/src/test/run-pass/issue-20414.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Trait { - fn method(self) -> int; + fn method(self) -> isize; } struct Wrapper { @@ -17,7 +19,7 @@ struct Wrapper { } impl<'a, T> Trait for &'a Wrapper where &'a T: Trait { - fn method(self) -> int { + fn method(self) -> isize { let r: &'a T = &self.field; Trait::method(r); // these should both work r.method() diff --git a/src/test/run-pass/issue-20454.rs b/src/test/run-pass/issue-20454.rs index fbc4cca800..d527d9519c 100644 --- a/src/test/run-pass/issue-20454.rs +++ b/src/test/run-pass/issue-20454.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(std_misc)] + use std::thread; -fn main() { - thread::Thread::spawn(move || { // no need for -> () +fn _foo() { + let _t = thread::scoped(move || { // no need for -> () loop { println!("hello"); } }); } + +fn main() {} diff --git a/src/test/run-pass/issue-20575.rs b/src/test/run-pass/issue-20575.rs index f83150b951..e73492e7a7 100644 --- a/src/test/run-pass/issue-20575.rs +++ b/src/test/run-pass/issue-20575.rs @@ -10,10 +10,11 @@ // Test that overloaded calls work with zero arity closures -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 fn main() { - let functions: [Box Option<()>>; 1] = [box || None]; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let functions: [Box Option<()>>; 1] = [Box::new(|| None)]; let _: Option> = functions.iter().map(|f| (*f)()).collect(); } diff --git a/src/test/run-pass/issue-20644.rs b/src/test/run-pass/issue-20644.rs index 0d482548cc..72ccd82a21 100644 --- a/src/test/run-pass/issue-20644.rs +++ b/src/test/run-pass/issue-20644.rs @@ -11,24 +11,29 @@ // A reduced version of the rustbook ice. The problem this encountered // had to do with trans ignoring binders. -#![feature(associated_types)] -#![feature(macro_rules)] +// pretty-expanded FIXME #23616 + +#![feature(os)] use std::iter; use std::os; -use std::old_io::File; +use std::fs::File; +use std::io::prelude::*; +use std::env; +use std::path::Path; -#[allow(unused)] -pub fn parse_summary(_: R, _: &Path) { +pub fn parse_summary(_: R, _: &Path) { let path_from_root = Path::new(""); - Path::new(iter::repeat("../") + Path::new(&iter::repeat("../") .take(path_from_root.components().count() - 1) .collect::()); } -fn main() { - let cwd = os::getcwd().unwrap(); +fn foo() { + let cwd = env::current_dir().unwrap(); let src = cwd.clone(); - let summary = File::open(&src.join("SUMMARY.md")); + let summary = File::open(&src.join("SUMMARY.md")).unwrap(); let _ = parse_summary(summary, &src); } + +fn main() {} diff --git a/src/test/run-pass/issue-20676.rs b/src/test/run-pass/issue-20676.rs index 01a2322ae9..df4c392385 100644 --- a/src/test/run-pass/issue-20676.rs +++ b/src/test/run-pass/issue-20676.rs @@ -12,9 +12,11 @@ // UFCS-style calls to a method in `Trait` where `Self` was bound to a // trait object of type `Trait`. See also `ufcs-trait-object.rs`. +// pretty-expanded FIXME #23616 + use std::fmt; fn main() { - let a: &fmt::Debug = &1_i32; + let a: &fmt::Debug = &1; format!("{:?}", a); } diff --git a/src/test/run-pass/issue-2074.rs b/src/test/run-pass/issue-2074.rs index 5f2805ed35..bd844b7720 100644 --- a/src/test/run-pass/issue-2074.rs +++ b/src/test/run-pass/issue-2074.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(non_camel_case_types)] pub fn main() { let one = || { enum r { a }; - r::a as uint + r::a as usize }; let two = || { enum r { a }; - r::a as uint + r::a as usize }; one(); two(); } diff --git a/src/test/run-pass/issue-20763-1.rs b/src/test/run-pass/issue-20763-1.rs index 97c06ac982..98270099df 100644 --- a/src/test/run-pass/issue-20763-1.rs +++ b/src/test/run-pass/issue-20763-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait T0 { type O; fn dummy(&self) { } diff --git a/src/test/run-pass/issue-20763-2.rs b/src/test/run-pass/issue-20763-2.rs index d970176357..340670b412 100644 --- a/src/test/run-pass/issue-20763-2.rs +++ b/src/test/run-pass/issue-20763-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait T0 { type O; fn dummy(&self) { } diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs index 049e08d2b9..8b5e6f837d 100644 --- a/src/test/run-pass/issue-20797.rs +++ b/src/test/run-pass/issue-20797.rs @@ -8,35 +8,42 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-android -// ignore-windows - // Regression test for #20797. +// pretty-expanded FIXME #23616 + use std::default::Default; -use std::old_io::IoResult; -use std::old_io::fs; -use std::old_io::fs::PathExtensions; +use std::io; +use std::fs; +use std::path::PathBuf; + +pub trait PathExtensions { + fn is_dir(&self) -> bool { false } +} + +impl PathExtensions for PathBuf {} /// A strategy for acquiring more subpaths to walk. pub trait Strategy { - type P: PathExtensions; - /// Get additional subpaths from a given path. - fn get_more(&self, item: &Self::P) -> IoResult>; - /// Determine whether a path should be walked further. - /// This is run against each item from `get_more()`. - fn prune(&self, p: &Self::P) -> bool; + type P: PathExtensions; + /// Get additional subpaths from a given path. + fn get_more(&self, item: &Self::P) -> io::Result>; + /// Determine whether a path should be walked further. + /// This is run against each item from `get_more()`. + fn prune(&self, p: &Self::P) -> bool; } /// The basic fully-recursive strategy. Nothing is pruned. -#[derive(Copy, Default)] +#[derive(Copy, Clone, Default)] pub struct Recursive; impl Strategy for Recursive { - type P = Path; - fn get_more(&self, p: &Path) -> IoResult> { fs::readdir(p) } + type P = PathBuf; + fn get_more(&self, p: &PathBuf) -> io::Result> { + Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect()) + } - fn prune(&self, _: &Path) -> bool { false } + fn prune(&self, _: &PathBuf) -> bool { false } } /// A directory walker of `P` using strategy `S`. @@ -46,49 +53,51 @@ pub struct Subpaths { } impl Subpaths { - /// Create a directory walker with a root path and strategy. - pub fn new(p: &S::P, strategy: S) -> IoResult> { - let stack = try!(strategy.get_more(p)); - Ok(Subpaths { stack: stack, strategy: strategy }) - } + /// Create a directory walker with a root path and strategy. + pub fn new(p: &S::P, strategy: S) -> io::Result> { + let stack = try!(strategy.get_more(p)); + Ok(Subpaths { stack: stack, strategy: strategy }) + } } impl Subpaths { - /// Create a directory walker with a root path and a default strategy. - pub fn walk(p: &S::P) -> IoResult> { - Subpaths::new(p, Default::default()) - } + /// Create a directory walker with a root path and a default strategy. + pub fn walk(p: &S::P) -> io::Result> { + Subpaths::new(p, Default::default()) + } } impl Default for Subpaths { - fn default() -> Subpaths { - Subpaths { stack: Vec::new(), strategy: Default::default() } - } + fn default() -> Subpaths { + Subpaths { stack: Vec::new(), strategy: Default::default() } + } } impl Iterator for Subpaths { - type Item = S::P; - fn next (&mut self) -> Option { - let mut opt_path = self.stack.pop(); - while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { - opt_path = self.stack.pop(); - } - match opt_path { - Some(path) => { - if PathExtensions::is_dir(&path) { - let result = self.strategy.get_more(&path); - match result { - Ok(dirs) => { self.stack.extend(dirs.into_iter()); }, - Err(..) => { } - } + type Item = S::P; + fn next (&mut self) -> Option { + let mut opt_path = self.stack.pop(); + while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { + opt_path = self.stack.pop(); + } + match opt_path { + Some(path) => { + if path.is_dir() { + let result = self.strategy.get_more(&path); + match result { + Ok(dirs) => { self.stack.extend(dirs.into_iter()); }, + Err(..) => { } + } + } + Some(path) + } + None => None, } - Some(path) - } - None => None, } - } } -fn main() { - let mut walker: Subpaths = Subpaths::walk(&Path::new("/home")).unwrap(); +fn _foo() { + let _walker: Subpaths = Subpaths::walk(&PathBuf::from("/home")).unwrap(); } + +fn main() {} diff --git a/src/test/run-pass/issue-20823.rs b/src/test/run-pass/issue-20823.rs index 561b619547..c297998b64 100644 --- a/src/test/run-pass/issue-20823.rs +++ b/src/test/run-pass/issue-20823.rs @@ -14,4 +14,4 @@ #![deny(unstable)] #[test] -fn foo() {} +pub fn foo() {} diff --git a/src/test/run-pass/issue-21033.rs b/src/test/run-pass/issue-21033.rs index 30c166cc67..00e792c9a0 100644 --- a/src/test/run-pass/issue-21033.rs +++ b/src/test/run-pass/issue-21033.rs @@ -7,6 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/test/run-pass/issue-21058.rs b/src/test/run-pass/issue-21058.rs index 3cdd57aed5..d7a656be7a 100644 --- a/src/test/run-pass/issue-21058.rs +++ b/src/test/run-pass/issue-21058.rs @@ -8,22 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] struct NT(str); struct DST { a: u32, b: str } fn main() { - // get_tydesc should support unsized types + // type_name should support unsized types assert_eq!(unsafe {( // Slice - (*std::intrinsics::get_tydesc::<[u8]>()).name, + std::intrinsics::type_name::<[u8]>(), // str - (*std::intrinsics::get_tydesc::()).name, + std::intrinsics::type_name::(), // Trait - (*std::intrinsics::get_tydesc::()).name, + std::intrinsics::type_name::(), // Newtype - (*std::intrinsics::get_tydesc::()).name, + std::intrinsics::type_name::(), // DST - (*std::intrinsics::get_tydesc::()).name + std::intrinsics::type_name::() )}, ("[u8]", "str", "core::marker::Copy", "NT", "DST")); } diff --git a/src/test/run-pass/issue-21245.rs b/src/test/run-pass/issue-21245.rs index 9205b247e1..75d064a00f 100644 --- a/src/test/run-pass/issue-21245.rs +++ b/src/test/run-pass/issue-21245.rs @@ -13,6 +13,8 @@ // insufficient type propagation caused the type of the iterator to be // incorrectly unified with the `*const` type to which it is coerced. +// pretty-expanded FIXME #23616 + use std::ptr; trait IntoIterator { diff --git a/src/test/run-pass/issue-21296.rs b/src/test/run-pass/issue-21296.rs index f91fb064ae..5e2ac61caa 100644 --- a/src/test/run-pass/issue-21296.rs +++ b/src/test/run-pass/issue-21296.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[forbid(raw_pointer_derive)] #[derive(Copy)] struct Test(*const i32); +impl Clone for Test { + fn clone(&self) -> Test { *self } +} + fn main() {} diff --git a/src/test/run-pass/issue-21306.rs b/src/test/run-pass/issue-21306.rs index 235dddefac..cabda0b500 100644 --- a/src/test/run-pass/issue-21306.rs +++ b/src/test/run-pass/issue-21306.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::Arc; fn main() { diff --git a/src/test/run-pass/issue-21350.rs b/src/test/run-pass/issue-21350.rs index feafee9037..ff205cd694 100644 --- a/src/test/run-pass/issue-21350.rs +++ b/src/test/run-pass/issue-21350.rs @@ -10,6 +10,8 @@ // Make sure that "bare sequences" don't ICE in follow checking +// pretty-expanded FIXME #23616 + macro_rules! bare { $($id:expr),+ => ( $($id)+ ) } diff --git a/src/test/run-pass/issue-21361.rs b/src/test/run-pass/issue-21361.rs index bb20b3a321..ef86634125 100644 --- a/src/test/run-pass/issue-21361.rs +++ b/src/test/run-pass/issue-21361.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let v = vec![1, 2, 3]; let boxed: Box> = Box::new(v.into_iter()); diff --git a/src/test/run-pass/issue-21363.rs b/src/test/run-pass/issue-21363.rs index 71bb3d39fe..608c60d03b 100644 --- a/src/test/run-pass/issue-21363.rs +++ b/src/test/run-pass/issue-21363.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![no_implicit_prelude] trait Iterator { diff --git a/src/test/run-pass/issue-21384.rs b/src/test/run-pass/issue-21384.rs index 1d3984deac..41a9ca840b 100644 --- a/src/test/run-pass/issue-21384.rs +++ b/src/test/run-pass/issue-21384.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use ::std::ops::RangeFull; fn test(arg: T) -> T { @@ -15,7 +17,7 @@ fn test(arg: T) -> T { } #[derive(PartialEq)] -struct Test(int); +struct Test(isize); fn main() { // Check that ranges implement clone diff --git a/src/test/run-pass/issue-21402.rs b/src/test/run-pass/issue-21402.rs index 6be7cea292..7fd329da2b 100644 --- a/src/test/run-pass/issue-21402.rs +++ b/src/test/run-pass/issue-21402.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Hash)] struct Foo { a: Vec, diff --git a/src/test/run-pass/issue-21475.rs b/src/test/run-pass/issue-21475.rs new file mode 100644 index 0000000000..0666a1f133 --- /dev/null +++ b/src/test/run-pass/issue-21475.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +use m::{START, END}; + +fn main() { + match 42 { + m::START...m::END => {}, + 0...m::END => {}, + m::START...59 => {}, + _ => {}, + } +} + +mod m { + pub const START: u32 = 4; + pub const END: u32 = 14; +} diff --git a/src/test/run-pass/issue-21520.rs b/src/test/run-pass/issue-21520.rs index 3a813641a3..b512fd4919 100644 --- a/src/test/run-pass/issue-21520.rs +++ b/src/test/run-pass/issue-21520.rs @@ -11,6 +11,8 @@ // Test that the requirement (in `Bar`) that `T::Bar : 'static` does // not wind up propagating to `T`. +// pretty-expanded FIXME #23616 + pub trait Foo { type Bar; @@ -26,4 +28,3 @@ struct Bar } fn main() { } - diff --git a/src/test/run-pass/issue-21634.rs b/src/test/run-pass/issue-21634.rs index e5a2790917..fe540e1aab 100644 --- a/src/test/run-pass/issue-21634.rs +++ b/src/test/run-pass/issue-21634.rs @@ -9,14 +9,16 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { - if let Ok(x) = "3.1415".parse() { + if let Ok(x) = "3.1415".parse::() { assert_eq!(false, x <= 0.0); } - if let Ok(x) = "3.1415".parse() { + if let Ok(x) = "3.1415".parse::() { assert_eq!(3.1415, x + 0.0); } - if let Ok(mut x) = "3.1415".parse() { + if let Ok(mut x) = "3.1415".parse::() { assert_eq!(8.1415, { x += 5.0; x }); } } diff --git a/src/test/run-pass/issue-21655.rs b/src/test/run-pass/issue-21655.rs index b9b1e5f333..cb87770c56 100644 --- a/src/test/run-pass/issue-21655.rs +++ b/src/test/run-pass/issue-21655.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn test(it: &mut Iterator) { for x in it { assert_eq!(x, 1) diff --git a/src/test/run-pass/issue-21721.rs b/src/test/run-pass/issue-21721.rs new file mode 100644 index 0000000000..c34ab1b0ea --- /dev/null +++ b/src/test/run-pass/issue-21721.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +fn main() { + static NONE: Option<((), &'static u8)> = None; + let ptr = unsafe { + *(&NONE as *const _ as *const *const u8) + }; + assert!(ptr.is_null()); +} diff --git a/src/test/run-pass/issue-21726.rs b/src/test/run-pass/issue-21726.rs index 09d1a3bca6..e1d1b908e0 100644 --- a/src/test/run-pass/issue-21726.rs +++ b/src/test/run-pass/issue-21726.rs @@ -12,6 +12,8 @@ // subtyping of projection types that resulted in an unconstrained // region, yielding region inference failures. +// pretty-expanded FIXME #23616 + fn main() { } fn foo<'a>(s: &'a str) { diff --git a/src/test/run-pass/issue-2185.rs b/src/test/run-pass/issue-2185.rs index 20ff8d29b7..fb0d2f0ad8 100644 --- a/src/test/run-pass/issue-2185.rs +++ b/src/test/run-pass/issue-2185.rs @@ -17,8 +17,8 @@ // // Running /usr/local/bin/rustc: // issue-2185.rs:24:0: 26:1 error: conflicting implementations for a trait -// issue-2185.rs:24 impl iterable for 'static ||uint|| { -// issue-2185.rs:25 fn iter(&self, blk: |v: uint|) { self( |i| blk(i) ) } +// issue-2185.rs:24 impl iterable for 'static ||usize|| { +// issue-2185.rs:25 fn iter(&self, blk: |v: usize|) { self( |i| blk(i) ) } // issue-2185.rs:26 } // issue-2185.rs:20:0: 22:1 note: note conflicting implementation here // issue-2185.rs:20 impl iterable for 'static ||A|| { @@ -26,7 +26,7 @@ // issue-2185.rs:22 } // // … so it looks like it's just not possible to implement both -// the generic iterable and iterable for the type iterable. +// the generic iterable and iterable for the type iterable. // Is it okay if I just remove this test? // // but Niko responded: @@ -50,8 +50,8 @@ impl iterable for 'static ||A|| { fn iter(&self, blk: |A|) { self(blk); } } -impl iterable for 'static ||uint|| { - fn iter(&self, blk: |v: uint|) { self( |i| blk(i) ) } +impl iterable for 'static ||usize|| { + fn iter(&self, blk: |v: usize|) { self( |i| blk(i) ) } } fn filter>(self: IA, prd: 'static |A| -> bool, blk: |A|) { @@ -68,21 +68,21 @@ fn foldl>(self: IA, b0: B, blk: |B, A| -> B) -> B { b } -fn range(lo: uint, hi: uint, it: |uint|) { +fn range(lo: usize, hi: usize, it: |usize|) { let mut i = lo; while i < hi { it(i); - i += 1_usize; + i += 1; } } pub fn main() { - let range: 'static ||uint|| = |a| range(0_usize, 1000_usize, a); - let filt: 'static ||v: uint|| = |a| filter( + let range: 'static ||usize|| = |a| range(0, 1000, a); + let filt: 'static ||v: usize|| = |a| filter( range, - |&&n: uint| n % 3_usize != 0_usize && n % 5_usize != 0_usize, + |&&n: usize| n % 3 != 0 && n % 5 != 0, a); - let sum = foldl(filt, 0_usize, |accum, &&n: uint| accum + n ); + let sum = foldl(filt, 0, |accum, &&n: usize| accum + n ); println!("{}", sum); } diff --git a/src/test/run-pass/issue-21891.rs b/src/test/run-pass/issue-21891.rs index d6e6f23191..0e35de7cdc 100644 --- a/src/test/run-pass/issue-21891.rs +++ b/src/test/run-pass/issue-21891.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static foo: [uint; 3] = [1, 2, 3]; +// pretty-expanded FIXME #23616 -static slice_1: &'static [uint] = &foo; -static slice_2: &'static [uint] = &foo; +static foo: [usize; 3] = [1, 2, 3]; + +static slice_1: &'static [usize] = &foo; +static slice_2: &'static [usize] = &foo; fn main() {} diff --git a/src/test/run-pass/issue-2190-1.rs b/src/test/run-pass/issue-2190-1.rs index 3025741694..5c84c30aa7 100644 --- a/src/test/run-pass/issue-2190-1.rs +++ b/src/test/run-pass/issue-2190-1.rs @@ -8,17 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + use std::thread::Builder; use std::thunk::Thunk; -static generations: uint = 1024+256+128+49; +static generations: usize = 1024+256+128+49; fn spawn(f: Thunk<'static>) { - Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(())); + Builder::new().stack_size(32 * 1024).spawn(move|| f()); } -fn child_no(x: uint) -> Thunk<'static> { - Thunk::new(move|| { +fn child_no(x: usize) -> Thunk<'static> { + Box::new(move|| { if x < generations { spawn(child_no(x+1)); } diff --git a/src/test/run-pass/issue-21909.rs b/src/test/run-pass/issue-21909.rs index 55b61dd194..6a5d76de8d 100644 --- a/src/test/run-pass/issue-21909.rs +++ b/src/test/run-pass/issue-21909.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn dummy(&self, arg: X); } diff --git a/src/test/run-pass/issue-22036.rs b/src/test/run-pass/issue-22036.rs index c06a29c09f..e02ce5441a 100644 --- a/src/test/run-pass/issue-22036.rs +++ b/src/test/run-pass/issue-22036.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait DigitCollection: Sized { type Iter: Iterator; fn digit_iter(self) -> Self::Iter; @@ -28,6 +30,6 @@ impl DigitCollection for I where I: Iterator { } fn main() { - let xs = vec![1u8, 2, 3, 4, 5]; + let xs = vec![1, 2, 3, 4, 5]; assert_eq!(xs.into_iter().digit_sum(), 15); } diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs index a319ee5e60..38895e1414 100644 --- a/src/test/run-pass/issue-2214.rs +++ b/src/test/run-pass/issue-2214.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; use std::mem; use libc::{c_double, c_int}; -fn to_c_int(v: &mut int) -> &mut c_int { +fn to_c_int(v: &mut isize) -> &mut c_int { unsafe { mem::transmute_copy(&v) } } -fn lgamma(n: c_double, value: &mut int) -> c_double { +fn lgamma(n: c_double, value: &mut isize) -> c_double { unsafe { return m::lgamma(n, to_c_int(value)); } @@ -41,7 +44,7 @@ mod m { } pub fn main() { - let mut y: int = 5; - let x: &mut int = &mut y; + let mut y: isize = 5; + let x: &mut isize = &mut y; assert_eq!(lgamma(1.0 as c_double, x), 0.0 as c_double); } diff --git a/src/test/run-pass/issue-22356.rs b/src/test/run-pass/issue-22356.rs new file mode 100644 index 0000000000..a54490386d --- /dev/null +++ b/src/test/run-pass/issue-22356.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +use std::marker::{PhantomData, PhantomFn}; + +pub struct Handle(T, I); + +impl Handle { + pub fn get_info(&self) -> &I { + let Handle(_, ref info) = *self; + info + } +} + +pub struct BufferHandle { + raw: RawBufferHandle, + _marker: PhantomData, +} + +impl BufferHandle { + pub fn get_info(&self) -> &String { + self.raw.get_info() + } +} + +pub type RawBufferHandle = Handle<::Buffer, String>; + +pub trait Device: PhantomFn { + type Buffer; +} + +fn main() {} diff --git a/src/test/run-pass/issue-22426.rs b/src/test/run-pass/issue-22426.rs new file mode 100644 index 0000000000..ad6ade4c59 --- /dev/null +++ b/src/test/run-pass/issue-22426.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +fn main() { + match 42 { + x if x < 7 => (), + _ => () + } +} diff --git a/src/test/run-pass/issue-22536-copy-mustnt-zero.rs b/src/test/run-pass/issue-22536-copy-mustnt-zero.rs new file mode 100644 index 0000000000..8a0f04a2cf --- /dev/null +++ b/src/test/run-pass/issue-22536-copy-mustnt-zero.rs @@ -0,0 +1,38 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for Issue #22536: If a type implements Copy, then +// moving it must not zero the original memory. + +// pretty-expanded FIXME #23616 + +trait Resources { + type Buffer: Copy; + fn foo(&self) {} +} + +struct BufferHandle { + raw: ::Buffer, +} +impl Copy for BufferHandle {} +impl Clone for BufferHandle { + fn clone(&self) -> BufferHandle { *self } +} + +enum Res {} +impl Resources for Res { + type Buffer = u32; +} + +fn main() { + let b: BufferHandle = BufferHandle { raw: 1 }; + let c = b; + assert_eq!(c.raw, b.raw) +} diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs new file mode 100644 index 0000000000..2c4141b0bd --- /dev/null +++ b/src/test/run-pass/issue-22577.rs @@ -0,0 +1,37 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![feature(fs, net, fs_walk)] + +use std::{fs, net}; + +fn assert_both() {} +fn assert_send() {} + +fn main() { + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_send::(); + assert_both::(); + assert_both::(); + + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); +} diff --git a/src/test/run-pass/issue-22629.rs b/src/test/run-pass/issue-22629.rs new file mode 100644 index 0000000000..07ca79295b --- /dev/null +++ b/src/test/run-pass/issue-22629.rs @@ -0,0 +1,22 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test transitive analysis for associated types. Collected types +// should be normalized and new obligations generated. + +// pretty-expanded FIXME #23616 + +use std::borrow::{ToOwned, Cow}; + +fn assert_send(_: T) {} + +fn main() { + assert_send(Cow::Borrowed("foo")); +} diff --git a/src/test/run-pass/issue-22777.rs b/src/test/run-pass/issue-22777.rs new file mode 100644 index 0000000000..2dc4d775a9 --- /dev/null +++ b/src/test/run-pass/issue-22777.rs @@ -0,0 +1,57 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This test is reduced from libsyntax. It is just checking that we +// can successfully deal with a "deep" structure, which the drop-check +// was hitting a recursion limit on at one point. + +// pretty-expanded FIXME #23616 + +#![allow(non_camel_case_types)] + +pub fn noop_fold_impl_item() -> SmallVector { + loop { } +} + +pub struct SmallVector(P); +pub struct ImplItem(P); + +struct P(Box); + +struct S01_Method(P); +struct S02_Generics(P); +struct S03_TyParam(P); +struct S04_TyParamBound(S05_PolyTraitRef); +struct S05_PolyTraitRef(S06_TraitRef); +struct S06_TraitRef(S07_Path); +struct S07_Path(Vec); +struct S08_PathSegment(S09_PathParameters); +struct S09_PathParameters(P); +struct S10_ParenthesizedParameterData(Option>); +struct S11_Ty(P); +struct S12_Expr(P); +struct S13_Block(Vec>); +struct S14_Stmt(P); +struct S15_Decl(P); +struct S16_Local(P); +struct S17_Pat(P); +struct S18_Mac(Vec>); +struct S19_TokenTree(P); +struct S20_Token(P); +struct S21_Nonterminal(P); +struct S22_Item(P); +struct S23_EnumDef(Vec>); +struct S24_Variant(P); +struct S25_VariantKind(P); +struct S26_StructDef(Vec>); +struct S27_StructField(P); +struct S28_StructFieldKind; + +pub fn main() {} diff --git a/src/test/run-pass/issue-22828.rs b/src/test/run-pass/issue-22828.rs new file mode 100644 index 0000000000..d6a4d7834d --- /dev/null +++ b/src/test/run-pass/issue-22828.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test transitive analysis for associated types. Collected types +// should be normalized and new obligations generated. + +// pretty-expanded FIXME #23616 + +trait Foo { + type A; + fn foo(&self) {} +} + +impl Foo for usize { + type A = usize; +} + +struct Bar { inner: T::A } + +fn is_send() {} + +fn main() { + is_send::>(); +} diff --git a/src/test/run-pass/issue-2284.rs b/src/test/run-pass/issue-2284.rs index b8c9ada8b1..d606c52607 100644 --- a/src/test/run-pass/issue-2284.rs +++ b/src/test/run-pass/issue-2284.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Send { fn f(&self); } diff --git a/src/test/run-pass/issue-2288.rs b/src/test/run-pass/issue-2288.rs index 18bb6fe552..d16655a685 100644 --- a/src/test/run-pass/issue-2288.rs +++ b/src/test/run-pass/issue-2288.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -15,7 +17,7 @@ trait clam { fn chowder(&self, y: A); } -#[derive(Copy)] +#[derive(Copy, Clone)] struct foo { x: A, } @@ -38,6 +40,6 @@ fn f(x: Box>, a: A) { pub fn main() { let c = foo(42); - let d: Box> = box c as Box>; + let d: Box> = box c as Box>; f(d, c.x); } diff --git a/src/test/run-pass/issue-23037.rs b/src/test/run-pass/issue-23037.rs new file mode 100644 index 0000000000..5257daa047 --- /dev/null +++ b/src/test/run-pass/issue-23037.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core)] + +use std::simd::i32x4; +fn main() { + let foo = i32x4(1,2,3,4); + let bar = i32x4(40,30,20,10); + let baz = foo + bar; + assert!(baz.0 == 41 && baz.1 == 32 && baz.2 == 23 && baz.3 == 14); +} diff --git a/src/test/run-pass/issue-2311-2.rs b/src/test/run-pass/issue-2311-2.rs index 5529d51b40..c76bbaf968 100644 --- a/src/test/run-pass/issue-2311-2.rs +++ b/src/test/run-pass/issue-2311-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait clam { fn get(self) -> A; } diff --git a/src/test/run-pass/issue-2311.rs b/src/test/run-pass/issue-2311.rs index b6b3114e2a..5a086fd6fc 100644 --- a/src/test/run-pass/issue-2311.rs +++ b/src/test/run-pass/issue-2311.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait clam { fn get(self) -> A; } trait foo { fn bar>(&self, c: C) -> B; diff --git a/src/test/run-pass/issue-2312.rs b/src/test/run-pass/issue-2312.rs index 3f273b56ef..fa056191e6 100644 --- a/src/test/run-pass/issue-2312.rs +++ b/src/test/run-pass/issue-2312.rs @@ -10,9 +10,11 @@ // Testing that the B's are resolved +// pretty-expanded FIXME #23616 + trait clam { fn get(self) -> A; } -struct foo(int); +struct foo(isize); impl foo { pub fn bar>(&self, _c: C) -> B { panic!(); } diff --git a/src/test/run-pass/issue-2316-c.rs b/src/test/run-pass/issue-2316-c.rs index a6fac423bb..158e4570f2 100644 --- a/src/test/run-pass/issue-2316-c.rs +++ b/src/test/run-pass/issue-2316-c.rs @@ -11,6 +11,8 @@ // aux-build:issue_2316_a.rs // aux-build:issue_2316_b.rs +// pretty-expanded FIXME #23616 + extern crate issue_2316_b; use issue_2316_b::cloth; diff --git a/src/test/run-pass/issue-23435.rs b/src/test/run-pass/issue-23435.rs new file mode 100644 index 0000000000..9b727826e6 --- /dev/null +++ b/src/test/run-pass/issue-23435.rs @@ -0,0 +1,37 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do not ICE when a default method implementation has +// requirements (in this case, `Self : Baz`) that do not hold for some +// specific impl (in this case, `Foo : Bar`). This causes problems +// only when building a vtable, because that goes along and +// instantiates all the methods, even those that could not otherwise +// be called. + +// pretty-expanded FIXME #23616 + +struct Foo { + x: i32 +} + +trait Bar { + fn bar(&self) where Self : Baz { self.baz(); } +} + +trait Baz { + fn baz(&self); +} + +impl Bar for Foo { +} + +fn main() { + let x: &Bar = &Foo { x: 22 }; +} diff --git a/src/test/run-pass/issue-23485.rs b/src/test/run-pass/issue-23485.rs new file mode 100644 index 0000000000..f176c60346 --- /dev/null +++ b/src/test/run-pass/issue-23485.rs @@ -0,0 +1,58 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test for an ICE that occurred when a default method implementation +// was applied to a type that did not meet the prerequisites. The +// problem occurred specifically because normalizing +// `Self::Item::Target` was impossible in this case. + +use std::boxed::Box; +use std::marker::Sized; +use std::clone::Clone; +use std::ops::Deref; +use std::option::Option; +use std::option::Option::{Some,None}; + +trait Iterator { + type Item; + + fn next(&mut self) -> Option; + + fn clone_first(mut self) -> Option<::Target> where + Self: Sized, + Self::Item: Deref, + ::Target: Clone, + { + self.next().map(|x| x.clone()) + } +} + +struct Counter { + value: i32 +} + +struct Token { + value: i32 +} + +impl Iterator for Counter { + type Item = Token; + + fn next(&mut self) -> Option { + let x = self.value; + self.value += 1; + Some(Token { value: x }) + } +} + +fn main() { + let mut x: Box> = Box::new(Counter { value: 22 }); + assert_eq!(x.next().unwrap().value, 22); +} diff --git a/src/test/run-pass/issue-23550.rs b/src/test/run-pass/issue-23550.rs new file mode 100644 index 0000000000..9b5ca23565 --- /dev/null +++ b/src/test/run-pass/issue-23550.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core)] +#![allow(warnings)] + +use std::intrinsics; + +#[derive(Copy, Clone)] +struct Wrap(i64); + +// These volatile and atomic intrinsics used to cause an ICE + +unsafe fn test_bool(p: &mut bool, v: bool) { + intrinsics::volatile_load(p); + intrinsics::volatile_store(p, v); + intrinsics::atomic_load(p); + intrinsics::atomic_cxchg(p, v, v); + intrinsics::atomic_store(p, v); + intrinsics::atomic_xchg(p, v); +} + +unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) { + intrinsics::volatile_load(p); + intrinsics::volatile_store(p, v); + intrinsics::atomic_load(p); + intrinsics::atomic_cxchg(p, v, v); + intrinsics::atomic_store(p, v); + intrinsics::atomic_xchg(p, v); +} + +fn main() {} diff --git a/src/test/run-pass/issue-23781.rs b/src/test/run-pass/issue-23781.rs new file mode 100644 index 0000000000..23ac8d2b78 --- /dev/null +++ b/src/test/run-pass/issue-23781.rs @@ -0,0 +1,38 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt; + +struct Foo; +impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + println!("::fmt()"); + + write!(fmt, "") + } +} + +fn test1() { + let foo_str = format!("{:?}", Foo); + + println!("{}", foo_str); +} + +fn test2() { + println!("{:?}", Foo); +} + +fn main() { + // This works fine + test1(); + + // This fails + test2(); +} diff --git a/src/test/run-pass/issue-2380-b.rs b/src/test/run-pass/issue-2380-b.rs index 22976aac6e..b704162424 100644 --- a/src/test/run-pass/issue-2380-b.rs +++ b/src/test/run-pass/issue-2380-b.rs @@ -10,6 +10,8 @@ // aux-build:issue-2380.rs +// pretty-expanded FIXME #23616 + extern crate a; pub fn main() { diff --git a/src/test/run-pass/issue-2383.rs b/src/test/run-pass/issue-2383.rs index a5a05283f8..9c400aac1d 100644 --- a/src/test/run-pass/issue-2383.rs +++ b/src/test/run-pass/issue-2383.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + extern crate collections; use std::collections::VecDeque; diff --git a/src/test/run-pass/issue-2414-c.rs b/src/test/run-pass/issue-2414-c.rs index 0b891fbddc..2e047ae012 100644 --- a/src/test/run-pass/issue-2414-c.rs +++ b/src/test/run-pass/issue-2414-c.rs @@ -11,6 +11,8 @@ // aux-build:issue-2414-a.rs // aux-build:issue-2414-b.rs +// pretty-expanded FIXME #23616 + extern crate b; pub fn main() {} diff --git a/src/test/run-pass/issue-2428.rs b/src/test/run-pass/issue-2428.rs index 7ed26428be..402eb0349a 100644 --- a/src/test/run-pass/issue-2428.rs +++ b/src/test/run-pass/issue-2428.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let _foo = 100; - const quux: int = 5; + const quux: isize = 5; enum Stuff { Bar = quux } - assert_eq!(Stuff::Bar as int, quux); + assert_eq!(Stuff::Bar as isize, quux); } diff --git a/src/test/run-pass/issue-2445-b.rs b/src/test/run-pass/issue-2445-b.rs index 91f76fc5ae..c1d17d263d 100644 --- a/src/test/run-pass/issue-2445-b.rs +++ b/src/test/run-pass/issue-2445-b.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct c1 { x: T, } impl c1 { - pub fn f1(&self, _x: int) { + pub fn f1(&self, _x: isize) { } } @@ -24,12 +26,12 @@ fn c1(x: T) -> c1 { } impl c1 { - pub fn f2(&self, _x: int) { + pub fn f2(&self, _x: isize) { } } pub fn main() { - c1::(3).f1(4); - c1::(3).f2(4); + c1::(3).f1(4); + c1::(3).f2(4); } diff --git a/src/test/run-pass/issue-2445.rs b/src/test/run-pass/issue-2445.rs index 6356c87bfc..0b6cf5890f 100644 --- a/src/test/run-pass/issue-2445.rs +++ b/src/test/run-pass/issue-2445.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct c1 { x: T, } @@ -28,6 +30,6 @@ impl c1 { pub fn main() { - c1::(3).f1(4); - c1::(3).f2(4); + c1::(3).f1(4); + c1::(3).f2(4); } diff --git a/src/test/run-pass/issue-2463.rs b/src/test/run-pass/issue-2463.rs index 051ebd1ec0..f0b0614535 100644 --- a/src/test/run-pass/issue-2463.rs +++ b/src/test/run-pass/issue-2463.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Pair { f: int, g: int } +// pretty-expanded FIXME #23616 + +struct Pair { f: isize, g: isize } pub fn main() { diff --git a/src/test/run-pass/issue-2472.rs b/src/test/run-pass/issue-2472.rs index 53b0042405..0cbdbda637 100644 --- a/src/test/run-pass/issue-2472.rs +++ b/src/test/run-pass/issue-2472.rs @@ -10,6 +10,8 @@ // aux-build:issue_2472_b.rs +// pretty-expanded FIXME #23616 + extern crate issue_2472_b; use issue_2472_b::{S, T}; diff --git a/src/test/run-pass/issue-2487-a.rs b/src/test/run-pass/issue-2487-a.rs index aa61d52b2a..76450b351f 100644 --- a/src/test/run-pass/issue-2487-a.rs +++ b/src/test/run-pass/issue-2487-a.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct socket { - sock: int, + sock: isize, } @@ -31,6 +33,6 @@ fn socket() -> socket { fn closure(f: F) where F: FnOnce() { f() } -fn setsockopt_bytes(_sock: int) { } +fn setsockopt_bytes(_sock: isize) { } pub fn main() {} diff --git a/src/test/run-pass/issue-2502.rs b/src/test/run-pass/issue-2502.rs index a62e329f10..63179cd14a 100644 --- a/src/test/run-pass/issue-2502.rs +++ b/src/test/run-pass/issue-2502.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct font<'a> { fontbuf: &'a Vec , } diff --git a/src/test/run-pass/issue-2526-a.rs b/src/test/run-pass/issue-2526-a.rs index 18c59dc9ad..0c68c47023 100644 --- a/src/test/run-pass/issue-2526-a.rs +++ b/src/test/run-pass/issue-2526-a.rs @@ -10,6 +10,8 @@ // aux-build:issue-2526.rs +// pretty-expanded FIXME #23616 + #![allow(unused_imports)] extern crate issue_2526; diff --git a/src/test/run-pass/issue-2550.rs b/src/test/run-pass/issue-2550.rs index 395b2c4b45..87b0b198f9 100644 --- a/src/test/run-pass/issue-2550.rs +++ b/src/test/run-pass/issue-2550.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct C { - x: uint, + x: usize, } -fn C(x: uint) -> C { +fn C(x: usize) -> C { C { x: x } @@ -22,5 +24,5 @@ fn f(_x: T) { } pub fn main() { - f(C(1_usize)); + f(C(1)); } diff --git a/src/test/run-pass/issue-2611-3.rs b/src/test/run-pass/issue-2611-3.rs index c005699ce3..8cf80333e9 100644 --- a/src/test/run-pass/issue-2611-3.rs +++ b/src/test/run-pass/issue-2611-3.rs @@ -11,12 +11,14 @@ // Tests that impls are allowed to have looser, more permissive bounds // than the traits require. +// pretty-expanded FIXME #23616 + trait A { fn b(&self, x: C) -> C; } struct E { - f: int + f: isize } impl A for E { diff --git a/src/test/run-pass/issue-2631-b.rs b/src/test/run-pass/issue-2631-b.rs index 84f046499e..7413ebd350 100644 --- a/src/test/run-pass/issue-2631-b.rs +++ b/src/test/run-pass/issue-2631-b.rs @@ -11,6 +11,8 @@ // aux-build:issue-2631-a.rs +// pretty-expanded FIXME #23616 + extern crate req; use req::request; @@ -22,5 +24,5 @@ pub fn main() { let v = vec!(Rc::new("hi".to_string())); let mut m: req::header_map = HashMap::new(); m.insert("METHOD".to_string(), Rc::new(RefCell::new(v))); - request::(&m); + request::(&m); } diff --git a/src/test/run-pass/issue-2633-2.rs b/src/test/run-pass/issue-2633-2.rs index 80e9ca4702..7b5a055d33 100644 --- a/src/test/run-pass/issue-2633-2.rs +++ b/src/test/run-pass/issue-2633-2.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn a_val(x: Box, y: Box) -> int { +fn a_val(x: Box, y: Box) -> isize { *x + *y } pub fn main() { - let z = box 22; + let z: Box<_> = box 22; a_val(z.clone(), z.clone()); } diff --git a/src/test/run-pass/issue-2633.rs b/src/test/run-pass/issue-2633.rs index de99141c80..5841a9ec17 100644 --- a/src/test/run-pass/issue-2633.rs +++ b/src/test/run-pass/issue-2633.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +#[derive(Copy, Clone)] struct cat { meow: extern "Rust" fn(), } @@ -23,7 +23,7 @@ fn cat() -> cat { } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct KittyInfo {kitty: cat} // Code compiles and runs successfully if we add a + before the first arg diff --git a/src/test/run-pass/issue-2642.rs b/src/test/run-pass/issue-2642.rs index dc60155454..f0bc31fb39 100644 --- a/src/test/run-pass/issue-2642.rs +++ b/src/test/run-pass/issue-2642.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn f() { - let _x: uint = loop { loop { break; } }; + let _x: usize = loop { loop { break; } }; } pub fn main() { diff --git a/src/test/run-pass/issue-2708.rs b/src/test/run-pass/issue-2708.rs index 1f072af0f5..d3916db3f7 100644 --- a/src/test/run-pass/issue-2708.rs +++ b/src/test/run-pass/issue-2708.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct Font { - fontbuf: uint, - cairo_font: uint, - font_dtor: uint, + fontbuf: usize, + cairo_font: usize, + font_dtor: usize, } @@ -31,5 +33,5 @@ fn Font() -> Font { } pub fn main() { - let _f = box Font(); + let _f: Box<_> = box Font(); } diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index b8a541a0fc..71d1439dd2 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -1,4 +1,3 @@ - // 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. @@ -11,11 +10,9 @@ // // ignore-lexer-test FIXME #15883 -#![allow(unknown_features)] -#![feature(box_syntax)] -#![feature(unsafe_destructor)] +#![feature(unsafe_destructor, std_misc)] -pub type Task = int; +pub type Task = isize; // tjc: I don't know why pub mod pipes { @@ -24,7 +21,7 @@ pub mod pipes { use std::mem::{forget, transmute}; use std::mem::{replace, swap}; use std::mem; - use std::thread::Thread; + use std::thread; use std::marker::Send; pub struct Stuff { @@ -34,7 +31,7 @@ pub mod pipes { } #[derive(PartialEq, Debug)] - #[repr(int)] + #[repr(isize)] pub enum state { empty, full, @@ -52,19 +49,19 @@ pub mod pipes { pub fn packet() -> *const packet { unsafe { - let p: *const packet = mem::transmute(box Stuff{ + let p: *const packet = mem::transmute(Box::new(Stuff{ state: empty, blocked_task: None::, payload: None:: - }); + })); p } } mod rusti { - pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { panic!(); } - pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { panic!(); } - pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { panic!(); } + pub fn atomic_xchg(_dst: &mut isize, _src: isize) -> isize { panic!(); } + pub fn atomic_xchg_acq(_dst: &mut isize, _src: isize) -> isize { panic!(); } + pub fn atomic_xchg_rel(_dst: &mut isize, _src: isize) -> isize { panic!(); } } // We should consider moving this to ::std::unsafe, although I @@ -75,13 +72,13 @@ pub mod pipes { pub fn swap_state_acq(dst: &mut state, src: state) -> state { unsafe { - transmute(rusti::atomic_xchg_acq(transmute(dst), src as int)) + transmute(rusti::atomic_xchg_acq(transmute(dst), src as isize)) } } pub fn swap_state_rel(dst: &mut state, src: state) -> state { unsafe { - transmute(rusti::atomic_xchg_rel(transmute(dst), src as int)) + transmute(rusti::atomic_xchg_rel(transmute(dst), src as isize)) } } @@ -118,7 +115,7 @@ pub mod pipes { let old_state = swap_state_acq(&mut (*p).state, blocked); match old_state { - empty | blocked => { Thread::yield_now(); } + empty | blocked => { thread::yield_now(); } full => { let payload = replace(&mut p.payload, None); return Some(payload.unwrap()) @@ -165,7 +162,7 @@ pub mod pipes { } } - pub struct send_packet { + pub struct send_packet { p: Option<*const packet>, } @@ -195,7 +192,7 @@ pub mod pipes { } } - pub struct recv_packet { + pub struct recv_packet { p: Option<*const packet>, } diff --git a/src/test/run-pass/issue-2723-b.rs b/src/test/run-pass/issue-2723-b.rs index bab7b0d24d..7fee2fc16c 100644 --- a/src/test/run-pass/issue-2723-b.rs +++ b/src/test/run-pass/issue-2723-b.rs @@ -10,6 +10,8 @@ // aux-build:issue_2723_a.rs +// pretty-expanded FIXME #23616 + extern crate issue_2723_a; use issue_2723_a::f; diff --git a/src/test/run-pass/issue-2734.rs b/src/test/run-pass/issue-2734.rs index a7b53db6b0..18cd9a87e6 100644 --- a/src/test/run-pass/issue-2734.rs +++ b/src/test/run-pass/issue-2734.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/issue-2735-2.rs b/src/test/run-pass/issue-2735-2.rs index 0d1cf1c339..1506b2d6bf 100644 --- a/src/test/run-pass/issue-2735-2.rs +++ b/src/test/run-pass/issue-2735-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] use std::cell::Cell; diff --git a/src/test/run-pass/issue-2735-3.rs b/src/test/run-pass/issue-2735-3.rs index 658183cf6f..2282334d66 100644 --- a/src/test/run-pass/issue-2735-3.rs +++ b/src/test/run-pass/issue-2735-3.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] use std::cell::Cell; diff --git a/src/test/run-pass/issue-2735.rs b/src/test/run-pass/issue-2735.rs index 1594b94879..cd6c6a59e2 100644 --- a/src/test/run-pass/issue-2735.rs +++ b/src/test/run-pass/issue-2735.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/issue-2748-a.rs b/src/test/run-pass/issue-2748-a.rs index 23e26ca566..ac1e65ee77 100644 --- a/src/test/run-pass/issue-2748-a.rs +++ b/src/test/run-pass/issue-2748-a.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct CMap<'a> { buf: &'a [u8], } diff --git a/src/test/run-pass/issue-2748-b.rs b/src/test/run-pass/issue-2748-b.rs index 3ca8d49eb8..8f30d262f4 100644 --- a/src/test/run-pass/issue-2748-b.rs +++ b/src/test/run-pass/issue-2748-b.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn thing<'r>(x: &'r [int]) -> &'r [int] { x } +// pretty-expanded FIXME #23616 + +fn thing<'r>(x: &'r [isize]) -> &'r [isize] { x } pub fn main() { let x = &[1,2,3]; diff --git a/src/test/run-pass/issue-2804-2.rs b/src/test/run-pass/issue-2804-2.rs index 952ea1e9d3..6afb31619d 100644 --- a/src/test/run-pass/issue-2804-2.rs +++ b/src/test/run-pass/issue-2804-2.rs @@ -1,4 +1,3 @@ - // 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. @@ -12,12 +11,14 @@ // Minimized version of issue-2804.rs. Both check that callee IDs don't // clobber the previous node ID in a macro expr +#![feature(collections)] + extern crate collections; use std::collections::HashMap; -fn add_interfaces(managed_ip: String, device: HashMap) { - println!("{}, {}", managed_ip, device["interfaces".to_string()]); +fn add_interfaces(managed_ip: String, device: HashMap) { + println!("{}, {}", managed_ip, device["interfaces"]); } pub fn main() {} diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs index 25b933b8f9..a2b4e218a0 100644 --- a/src/test/run-pass/issue-2804.rs +++ b/src/test/run-pass/issue-2804.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(collections)] +#![feature(rustc_private)] + extern crate collections; extern crate serialize; @@ -37,7 +39,7 @@ fn lookup(table: json::Object, key: String, default: String) -> String } } -fn add_interface(_store: int, managed_ip: String, data: json::Json) -> (String, object) +fn add_interface(_store: isize, managed_ip: String, data: json::Json) -> (String, object) { match &data { &Json::Object(ref interface) => { @@ -55,10 +57,9 @@ fn add_interface(_store: int, managed_ip: String, data: json::Json) -> (String, } } -fn add_interfaces(store: int, managed_ip: String, device: HashMap) +fn add_interfaces(store: isize, managed_ip: String, device: HashMap) -> Vec<(String, object)> { - match device["interfaces".to_string()] - { + match device["interfaces"] { Json::Array(ref interfaces) => { interfaces.iter().map(|interface| { @@ -68,7 +69,7 @@ fn add_interfaces(store: int, managed_ip: String, device: HashMap { println!("Expected list for {} interfaces, found {}", managed_ip, - device["interfaces".to_string()]); + device["interfaces"]); Vec::new() } } diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs index 5f7a4d87b9..3f4c630cc2 100644 --- a/src/test/run-pass/issue-2895.rs +++ b/src/test/run-pass/issue-2895.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; struct Cat { - x: int + x: isize } struct Kitty { - x: int, + x: isize, } impl Drop for Kitty { @@ -24,12 +26,12 @@ impl Drop for Kitty { #[cfg(any(target_arch = "x86_64", target_arch="aarch64"))] pub fn main() { - assert_eq!(mem::size_of::(), 8 as uint); - assert_eq!(mem::size_of::(), 16 as uint); + assert_eq!(mem::size_of::(), 8 as usize); + assert_eq!(mem::size_of::(), 16 as usize); } #[cfg(any(target_arch = "x86", target_arch = "arm"))] pub fn main() { - assert_eq!(mem::size_of::(), 4 as uint); - assert_eq!(mem::size_of::(), 8 as uint); + assert_eq!(mem::size_of::(), 4 as usize); + assert_eq!(mem::size_of::(), 8 as usize); } diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index b55f369135..b05baa24b7 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -1,4 +1,3 @@ - // 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. @@ -10,7 +9,9 @@ // except according to those terms. -/// Map representation +// Map representation + +#![feature(old_io)] use std::old_io; use std::fmt; diff --git a/src/test/run-pass/issue-2935.rs b/src/test/run-pass/issue-2935.rs index 31599d0caa..fd8e1e6b03 100644 --- a/src/test/run-pass/issue-2935.rs +++ b/src/test/run-pass/issue-2935.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -//type t = { a: int }; +//type t = { a: isize }; // type t = { a: bool }; type t = bool; @@ -28,7 +28,7 @@ pub fn main() { // let y = box ({a: 4}); // let z = box ({a: 4} as it); // let z = box ({a: true} as it); - let z = box() (box true as Box); + let z: Box<_> = box () (box true as Box); // x.f(); // y.f(); // (*z).f(); diff --git a/src/test/run-pass/issue-2936.rs b/src/test/run-pass/issue-2936.rs index 183eb6e079..5c63230f5d 100644 --- a/src/test/run-pass/issue-2936.rs +++ b/src/test/run-pass/issue-2936.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait bar { fn get_bar(&self) -> T; } @@ -17,22 +19,22 @@ fn foo>(b: U) -> T { } struct cbar { - x: int, + x: isize, } -impl bar for cbar { - fn get_bar(&self) -> int { +impl bar for cbar { + fn get_bar(&self) -> isize { self.x } } -fn cbar(x: int) -> cbar { +fn cbar(x: isize) -> cbar { cbar { x: x } } pub fn main() { - let x: int = foo::(cbar(5)); + let x: isize = foo::(cbar(5)); assert_eq!(x, 5); } diff --git a/src/test/run-pass/issue-2989.rs b/src/test/run-pass/issue-2989.rs index 8767d397b6..8b6eb12f10 100644 --- a/src/test/run-pass/issue-2989.rs +++ b/src/test/run-pass/issue-2989.rs @@ -21,11 +21,11 @@ impl methods for () { // the position of this function is significant! - if it comes before methods // then it works, if it comes after it then it doesn't! fn to_bools(bitv: Storage) -> Vec { - (0_usize..8).map(|i| { + (0..8).map(|i| { let w = i / 64; let b = i % 64; - let x = 1u64 & (bitv.storage[w] >> b); - x == 1u64 + let x = 1 & (bitv.storage[w] >> b); + x == 1 }).collect() } @@ -35,7 +35,7 @@ pub fn main() { let bools = vec!(false, false, true, false, false, true, true, false); let bools2 = to_bools(Storage{storage: vec!(0b01100100)}); - for i in 0_usize..8 { + for i in 0..8 { println!("{} => {} vs {}", i, bools[i], bools2[i]); } diff --git a/src/test/run-pass/issue-3012-2.rs b/src/test/run-pass/issue-3012-2.rs index de2d4374d7..ecce5df0fc 100644 --- a/src/test/run-pass/issue-3012-2.rs +++ b/src/test/run-pass/issue-3012-2.rs @@ -10,8 +10,10 @@ // aux-build:issue-3012-1.rs +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, libc)] extern crate socketlib; extern crate libc; @@ -20,5 +22,5 @@ use socketlib::socket; pub fn main() { let fd: libc::c_int = 1 as libc::c_int; - let _sock = box socket::socket_handle(fd); + let _sock: Box<_> = box socket::socket_handle(fd); } diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index 25663f2605..d8499992f9 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, collections)] extern crate collections; use std::collections::HashMap; pub fn main() { - let x; - let mut buggy_map: HashMap = HashMap::new(); + let x: Box<_>; + let mut buggy_map: HashMap = HashMap::new(); x = box 1; buggy_map.insert(42, &*x); } diff --git a/src/test/run-pass/issue-3037.rs b/src/test/run-pass/issue-3037.rs index 1555098f29..83a522a69e 100644 --- a/src/test/run-pass/issue-3037.rs +++ b/src/test/run-pass/issue-3037.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum what { } fn what_to_string(x: what) -> String diff --git a/src/test/run-pass/issue-3052.rs b/src/test/run-pass/issue-3052.rs index 3e7deee6ec..8f013ee4f3 100644 --- a/src/test/run-pass/issue-3052.rs +++ b/src/test/run-pass/issue-3052.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 type Connection = Box) + 'static>; fn f() -> Option { - let mock_connection: Connection = box |_| {}; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let mock_connection: Connection = Box::new(|_| {}); Some(mock_connection) } diff --git a/src/test/run-pass/issue-3091.rs b/src/test/run-pass/issue-3091.rs index c4c2c2b7da..8e59e46fc3 100644 --- a/src/test/run-pass/issue-3091.rs +++ b/src/test/run-pass/issue-3091.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = 1; let y = 1; diff --git a/src/test/run-pass/issue-3121.rs b/src/test/run-pass/issue-3121.rs index b6ed85e9e4..777e5bf7a6 100644 --- a/src/test/run-pass/issue-3121.rs +++ b/src/test/run-pass/issue-3121.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -#[derive(Copy)] +#[derive(Copy, Clone)] enum side { mayo, catsup, vinegar } -#[derive(Copy)] +#[derive(Copy, Clone)] enum order { hamburger, fries(side), shake } -#[derive(Copy)] +#[derive(Copy, Clone)] enum meal { to_go(order), for_here(order) } fn foo(m: Box, cond: bool) { diff --git a/src/test/run-pass/issue-3149.rs b/src/test/run-pass/issue-3149.rs index ab64fb4fbf..fa33bd8fce 100644 --- a/src/test/run-pass/issue-3149.rs +++ b/src/test/run-pass/issue-3149.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn Matrix4(m11: T, m12: T, m13: T, m14: T, m21: T, m22: T, m23: T, m24: T, m31: T, m32: T, m33: T, m34: T, diff --git a/src/test/run-pass/issue-3220.rs b/src/test/run-pass/issue-3220.rs index 9c44a7cfcc..0a37a01303 100644 --- a/src/test/run-pass/issue-3220.rs +++ b/src/test/run-pass/issue-3220.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct thing { x: int, } +// pretty-expanded FIXME #23616 + +struct thing { x: isize, } impl Drop for thing { fn drop(&mut self) {} diff --git a/src/test/run-pass/issue-3290.rs b/src/test/run-pass/issue-3290.rs index c8d6e69801..3fa5b72c34 100644 --- a/src/test/run-pass/issue-3290.rs +++ b/src/test/run-pass/issue-3290.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut x = box 3; + let mut x: Box<_> = box 3; x = x; assert_eq!(*x, 3); } diff --git a/src/test/run-pass/issue-333.rs b/src/test/run-pass/issue-333.rs index 1217f32826..b611f11a0a 100644 --- a/src/test/run-pass/issue-333.rs +++ b/src/test/run-pass/issue-333.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn quux(x: T) -> T { let f = id::; return f(x); } fn id(x: T) -> T { return x; } diff --git a/src/test/run-pass/issue-3424.rs b/src/test/run-pass/issue-3424.rs index 0d85f61e51..29d963bb70 100644 --- a/src/test/run-pass/issue-3424.rs +++ b/src/test/run-pass/issue-3424.rs @@ -11,10 +11,9 @@ // rustc --test ignores2.rs && ./ignores2 #![allow(unknown_features)] -#![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, old_path, std_misc)] -use std::old_path::{Path}; +use std::old_path::Path; use std::old_path; use std::result; use std::thunk::Thunk; @@ -23,9 +22,10 @@ type rsrc_loader = Box (result::Result) + 'stati fn tester() { - let mut loader: rsrc_loader = box move|_path| { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let mut loader: rsrc_loader = Box::new(move|_path| { result::Result::Ok("more blah".to_string()) - }; + }); let path = old_path::Path::new("blah"); assert!(loader(&path).is_ok()); diff --git a/src/test/run-pass/issue-3429.rs b/src/test/run-pass/issue-3429.rs index e331a1a2d0..325a3ec715 100644 --- a/src/test/run-pass/issue-3429.rs +++ b/src/test/run-pass/issue-3429.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = 1_usize; let y = || x; diff --git a/src/test/run-pass/issue-3500.rs b/src/test/run-pass/issue-3500.rs index 99def5476f..f1d9f888b0 100644 --- a/src/test/run-pass/issue-3500.rs +++ b/src/test/run-pass/issue-3500.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = &Some(1); match x { diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index 754412ea94..c2ea24ac6b 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(collections)] + extern crate collections; use std::collections::HashMap; @@ -24,6 +26,6 @@ pub fn main() { let mut table = HashMap::new(); table.insert("one".to_string(), 1); table.insert("two".to_string(), 2); - assert!(check_strs(&format!("{:?}", table), "HashMap {\"one\": 1, \"two\": 2}") || - check_strs(&format!("{:?}", table), "HashMap {\"two\": 2, \"one\": 1}")); + assert!(check_strs(&format!("{:?}", table), "{\"one\": 1, \"two\": 2}") || + check_strs(&format!("{:?}", table), "{\"two\": 2, \"one\": 1}")); } diff --git a/src/test/run-pass/issue-3563-2.rs b/src/test/run-pass/issue-3563-2.rs index 2cf29296b8..65c21317cf 100644 --- a/src/test/run-pass/issue-3563-2.rs +++ b/src/test/run-pass/issue-3563-2.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Canvas { - fn add_point(&self, point: &int); - fn add_points(&self, shapes: &[int]) { + fn add_point(&self, point: &isize); + fn add_points(&self, shapes: &[isize]) { for pt in shapes { self.add_point(pt) } diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index f4b85e03ea..cfdc54a362 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -22,26 +22,28 @@ // that are already linked in. Using WriterUtil allows us to use the write_line // method. +#![feature(core)] + use std::fmt; use std::iter::repeat; use std::slice; // Represents a position on a canvas. -#[derive(Copy)] +#[derive(Copy, Clone)] struct Point { - x: int, - y: int, + x: isize, + y: isize, } // Represents an offset on a canvas. (This has the same structure as a Point. // but different semantics). -#[derive(Copy)] +#[derive(Copy, Clone)] struct Size { - width: int, - height: int, + width: isize, + height: isize, } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Rect { top_left: Point, size: Size, @@ -49,8 +51,8 @@ struct Rect { // Contains the information needed to do shape rendering via ASCII art. struct AsciiArt { - width: uint, - height: uint, + width: usize, + height: usize, fill: char, lines: Vec > , @@ -65,7 +67,7 @@ impl Drop for AsciiArt { // It's common to define a constructor sort of function to create struct instances. // If there is a canonical constructor it is typically named the same as the type. // Other constructor sort of functions are typically named from_foo, from_bar, etc. -fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt { +fn AsciiArt(width: usize, height: usize, fill: char) -> AsciiArt { // Use an anonymous function to build a vector of vectors containing // blank characters for each position in our canvas. let mut lines = Vec::new(); @@ -80,12 +82,12 @@ fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt { // Methods particular to the AsciiArt struct. impl AsciiArt { - fn add_pt(&mut self, x: int, y: int) { - if x >= 0 && x < self.width as int { - if y >= 0 && y < self.height as int { + fn add_pt(&mut self, x: isize, y: isize) { + if x >= 0 && x < self.width as isize { + if y >= 0 && y < self.height as isize { // Note that numeric types don't implicitly convert to each other. - let v = y as uint; - let h = x as uint; + let v = y as usize; + let h = x as usize; // Vector subscripting will normally copy the element, but &v[i] // will return a reference which is what we need because the @@ -101,7 +103,7 @@ impl AsciiArt { // Allows AsciiArt to be converted to a string using the libcore ToString trait. // Note that the %s fmt! specifier will not call this automatically. -impl fmt::String for AsciiArt { +impl fmt::Display for AsciiArt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Convert each line into a string. let lines = self.lines.iter() diff --git a/src/test/run-pass/issue-3574.rs b/src/test/run-pass/issue-3574.rs index e31f2ade12..9a521ba376 100644 --- a/src/test/run-pass/issue-3574.rs +++ b/src/test/run-pass/issue-3574.rs @@ -10,6 +10,8 @@ // rustc --test match_borrowed_str.rs.rs && ./match_borrowed_str.rs +// pretty-expanded FIXME #23616 + fn compare(x: &str, y: &str) -> bool { match x { "foo" => y == "foo", diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index 4a28c34e5d..2167a3df97 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -9,11 +9,10 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::Sender; -use std::thunk::Invoke; type RingBuffer = Vec ; type SamplesFn = Box; @@ -24,12 +23,12 @@ enum Msg } fn foo(name: String, samples_chan: Sender) { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let mut samples_chan = samples_chan; - // `box() (...)` syntax is needed to make pretty printer converge in one try: - let callback: SamplesFn = box() (move |buffer| { - for i in 0_usize..buffer.len() { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let callback: SamplesFn = Box::new(move |buffer| { + for i in 0..buffer.len() { println!("{}: {}", i, buffer[i]) } }); diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index 8a39676ca1..1093047479 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -12,6 +12,10 @@ // Incorrect struct size computation in the FFI, because of not taking // the alignment of elements into account. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; use libc::{c_uint, uint32_t, c_void}; diff --git a/src/test/run-pass/issue-3683.rs b/src/test/run-pass/issue-3683.rs index e6c816666e..096eec803f 100644 --- a/src/test/run-pass/issue-3683.rs +++ b/src/test/run-pass/issue-3683.rs @@ -12,14 +12,14 @@ trait Foo { - fn a(&self) -> int; - fn b(&self) -> int { + fn a(&self) -> isize; + fn b(&self) -> isize { self.a() + 2 } } -impl Foo for int { - fn a(&self) -> int { +impl Foo for isize { + fn a(&self) -> isize { 3 } } diff --git a/src/test/run-pass/issue-3743.rs b/src/test/run-pass/issue-3743.rs index 03699ff8d6..cd62c04a32 100644 --- a/src/test/run-pass/issue-3743.rs +++ b/src/test/run-pass/issue-3743.rs @@ -10,11 +10,10 @@ // If `Mul` used an associated type for its output, this test would // work more smoothly. -#![feature(old_orphan_check)] use std::ops::Mul; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Vec2 { x: f64, y: f64 diff --git a/src/test/run-pass/issue-3753.rs b/src/test/run-pass/issue-3753.rs index 58d7aa276f..e81025d846 100644 --- a/src/test/run-pass/issue-3753.rs +++ b/src/test/run-pass/issue-3753.rs @@ -12,15 +12,17 @@ // Issue Name: pub method preceded by attribute can't be parsed // Abstract: Visibility parsing failed when compiler parsing +#![feature(core)] + use std::f64; -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Point { x: f64, y: f64 } -#[derive(Copy)] +#[derive(Copy, Clone)] pub enum Shape { Circle(Point, f64), Rectangle(Point, Point) diff --git a/src/test/run-pass/issue-3794.rs b/src/test/run-pass/issue-3794.rs index 6ac252c07e..3d5f38e38c 100644 --- a/src/test/run-pass/issue-3794.rs +++ b/src/test/run-pass/issue-3794.rs @@ -17,7 +17,7 @@ trait T { #[derive(Debug)] struct S { - s: int, + s: isize, } impl T for S { diff --git a/src/test/run-pass/issue-3847.rs b/src/test/run-pass/issue-3847.rs index 9216c8aa1a..bd3a726991 100644 --- a/src/test/run-pass/issue-3847.rs +++ b/src/test/run-pass/issue-3847.rs @@ -9,12 +9,12 @@ // except according to those terms. mod buildings { - pub struct Tower { pub height: uint } + pub struct Tower { pub height: usize } } pub fn main() { let sears = buildings::Tower { height: 1451 }; - let h: uint = match sears { + let h: usize = match sears { buildings::Tower { height: h } => { h } }; diff --git a/src/test/run-pass/issue-3874.rs b/src/test/run-pass/issue-3874.rs index 9226bebd2d..a29a267586 100644 --- a/src/test/run-pass/issue-3874.rs +++ b/src/test/run-pass/issue-3874.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum PureCounter { PureCounterVariant(uint) } +// pretty-expanded FIXME #23616 -fn each(thing: PureCounter, blk: F) where F: FnOnce(&uint) { +enum PureCounter { PureCounterVariant(usize) } + +fn each(thing: PureCounter, blk: F) where F: FnOnce(&usize) { let PureCounter::PureCounterVariant(ref x) = thing; blk(x); } diff --git a/src/test/run-pass/issue-3878.rs b/src/test/run-pass/issue-3878.rs index c1d19f228d..c98110b905 100644 --- a/src/test/run-pass/issue-3878.rs +++ b/src/test/run-pass/issue-3878.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(path_statement)] #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let y = box 1; + let y: Box<_> = box 1; y; } diff --git a/src/test/run-pass/issue-3888-2.rs b/src/test/run-pass/issue-3888-2.rs index bf3d0b786a..24c1a5d05c 100644 --- a/src/test/run-pass/issue-3888-2.rs +++ b/src/test/run-pass/issue-3888-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn vec_peek<'r, T>(v: &'r [T]) -> &'r [T] { &v[1..5] } diff --git a/src/test/run-pass/issue-3895.rs b/src/test/run-pass/issue-3895.rs index b225400132..ca6d9faf88 100644 --- a/src/test/run-pass/issue-3895.rs +++ b/src/test/run-pass/issue-3895.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { enum State { BadChar, BadSyntax } diff --git a/src/test/run-pass/issue-3935.rs b/src/test/run-pass/issue-3935.rs index f534f744a2..1e200e0162 100644 --- a/src/test/run-pass/issue-3935.rs +++ b/src/test/run-pass/issue-3935.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(PartialEq)] struct Bike { name: String, diff --git a/src/test/run-pass/issue-3979-2.rs b/src/test/run-pass/issue-3979-2.rs index 39e9f5dcd2..4cd3c04bac 100644 --- a/src/test/run-pass/issue-3979-2.rs +++ b/src/test/run-pass/issue-3979-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn a_method(&self); } diff --git a/src/test/run-pass/issue-3979-generics.rs b/src/test/run-pass/issue-3979-generics.rs index 180bd292f8..61708acf7f 100644 --- a/src/test/run-pass/issue-3979-generics.rs +++ b/src/test/run-pass/issue-3979-generics.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ops::Add; trait Positioned { @@ -22,18 +24,18 @@ trait Movable>: Positioned { } } -struct Point { x: int, y: int } +struct Point { x: isize, y: isize } -impl Positioned for Point { - fn SetX(&mut self, x: int) { +impl Positioned for Point { + fn SetX(&mut self, x: isize) { self.x = x; } - fn X(&self) -> int { + fn X(&self) -> isize { self.x } } -impl Movable for Point {} +impl Movable for Point {} pub fn main() { let mut p = Point{ x: 1, y: 2}; diff --git a/src/test/run-pass/issue-3979-xcrate.rs b/src/test/run-pass/issue-3979-xcrate.rs index a062b4c717..0784877849 100644 --- a/src/test/run-pass/issue-3979-xcrate.rs +++ b/src/test/run-pass/issue-3979-xcrate.rs @@ -9,16 +9,18 @@ // except according to those terms. // aux-build:issue_3979_traits.rs +// pretty-expanded FIXME #23616 + extern crate issue_3979_traits; use issue_3979_traits::{Positioned, Movable}; -struct Point { x: int, y: int } +struct Point { x: isize, y: isize } impl Positioned for Point { - fn SetX(&mut self, x: int) { + fn SetX(&mut self, x: isize) { self.x = x; } - fn X(&self) -> int { + fn X(&self) -> isize { self.x } } diff --git a/src/test/run-pass/issue-3979.rs b/src/test/run-pass/issue-3979.rs index 4f69342830..341866e498 100644 --- a/src/test/run-pass/issue-3979.rs +++ b/src/test/run-pass/issue-3979.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,25 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Positioned { - fn SetX(&mut self, int); - fn X(&self) -> int; + fn SetX(&mut self, isize); + fn X(&self) -> isize; } trait Movable: Positioned { - fn translate(&mut self, dx: int) { + fn translate(&mut self, dx: isize) { let x = self.X(); self.SetX(x + dx); } } -struct Point { x: int, y: int } +struct Point { x: isize, y: isize } impl Positioned for Point { - fn SetX(&mut self, x: int) { + fn SetX(&mut self, x: isize) { self.x = x; } - fn X(&self) -> int { + fn X(&self) -> isize { self.x } } diff --git a/src/test/run-pass/issue-3991.rs b/src/test/run-pass/issue-3991.rs index 37144fb9cc..d89cf8c2e1 100644 --- a/src/test/run-pass/issue-3991.rs +++ b/src/test/run-pass/issue-3991.rs @@ -9,8 +9,10 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct HasNested { - nest: Vec > , + nest: Vec > , } impl HasNested { diff --git a/src/test/run-pass/issue-4016.rs b/src/test/run-pass/issue-4016.rs index 220332f635..122de97c99 100644 --- a/src/test/run-pass/issue-4016.rs +++ b/src/test/run-pass/issue-4016.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] extern crate serialize; diff --git a/src/test/run-pass/issue-4036.rs b/src/test/run-pass/issue-4036.rs index 48e32922ce..ae7bb8a684 100644 --- a/src/test/run-pass/issue-4036.rs +++ b/src/test/run-pass/issue-4036.rs @@ -12,6 +12,10 @@ // Issue #4036: Test for an issue that arose around fixing up type inference // byproducts in vtable records. +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + extern crate serialize; use serialize::{json, Decodable}; @@ -19,5 +23,5 @@ use serialize::{json, Decodable}; pub fn main() { let json = json::from_str("[1]").unwrap(); let mut decoder = json::Decoder::new(json); - let _x: Vec = Decodable::decode(&mut decoder).unwrap(); + let _x: Vec = Decodable::decode(&mut decoder).unwrap(); } diff --git a/src/test/run-pass/issue-4107.rs b/src/test/run-pass/issue-4107.rs index d660f300ad..18025c315c 100644 --- a/src/test/run-pass/issue-4107.rs +++ b/src/test/run-pass/issue-4107.rs @@ -8,21 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let _id: &Mat2 = &Matrix::identity(1.0); } pub trait Index { fn get(&self, Index) -> Result { panic!() } } -pub trait Dimensional: Index { } +pub trait Dimensional: Index { } pub struct Mat2 { x: T } pub struct Vec2 { x: T } impl Dimensional> for Mat2 { } -impl Index> for Mat2 { } +impl Index> for Mat2 { } impl Dimensional for Vec2 { } -impl Index for Vec2 { } +impl Index for Vec2 { } pub trait Matrix: Dimensional { fn identity(t:T) -> Self; diff --git a/src/test/run-pass/issue-4208.rs b/src/test/run-pass/issue-4208.rs index c186f1e57f..52f5d53c04 100644 --- a/src/test/run-pass/issue-4208.rs +++ b/src/test/run-pass/issue-4208.rs @@ -10,6 +10,8 @@ // aux-build:issue-4208-cc.rs +// pretty-expanded FIXME #23616 + extern crate numeric; use numeric::{sin, Angle}; diff --git a/src/test/run-pass/issue-4228.rs b/src/test/run-pass/issue-4228.rs index 8cae8dd791..3d283849b1 100644 --- a/src/test/run-pass/issue-4228.rs +++ b/src/test/run-pass/issue-4228.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo; impl Foo { diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs index 89cf2f69b3..c650fc25ee 100644 --- a/src/test/run-pass/issue-4241.rs +++ b/src/test/run-pass/issue-4241.rs @@ -15,23 +15,23 @@ extern crate extra; use extra::net::tcp::TcpSocketBuf; use std::io; -use std::int; +use std::isize; use std::io::{ReaderUtil,WriterUtil}; enum Result { Nil, - Int(int), + Int(isize), Data(~[u8]), List(~[Result]), Error(String), Status(String) } -priv fn parse_data(len: uint, io: @io::Reader) -> Result { +priv fn parse_data(len: usize, io: @io::Reader) -> Result { let res = if (len > 0) { - let bytes = io.read_bytes(len as uint); + let bytes = io.read_bytes(len as usize); assert_eq!(bytes.len(), len); Data(bytes) } else { @@ -42,7 +42,7 @@ priv fn parse_data(len: uint, io: @io::Reader) -> Result { return res; } -priv fn parse_list(len: uint, io: @io::Reader) -> Result { +priv fn parse_list(len: usize, io: @io::Reader) -> Result { let mut list: ~[Result] = ~[]; for _ in 0..len { let v = match io.read_char() { @@ -60,26 +60,26 @@ priv fn chop(s: String) -> String { } priv fn parse_bulk(io: @io::Reader) -> Result { - match from_str::(chop(io.read_line())) { + match from_str::(chop(io.read_line())) { None => panic!(), Some(-1) => Nil, - Some(len) if len >= 0 => parse_data(len as uint, io), + Some(len) if len >= 0 => parse_data(len as usize, io), Some(_) => panic!() } } priv fn parse_multi(io: @io::Reader) -> Result { - match from_str::(chop(io.read_line())) { + match from_str::(chop(io.read_line())) { None => panic!(), Some(-1) => Nil, Some(0) => List(~[]), - Some(len) if len >= 0 => parse_list(len as uint, io), + Some(len) if len >= 0 => parse_list(len as usize, io), Some(_) => panic!() } } priv fn parse_int(io: @io::Reader) -> Result { - match from_str::(chop(io.read_line())) { + match from_str::(chop(io.read_line())) { None => panic!(), Some(i) => Int(i) } diff --git a/src/test/run-pass/issue-4252.rs b/src/test/run-pass/issue-4252.rs index 9d5f8576c6..73ef35f045 100644 --- a/src/test/run-pass/issue-4252.rs +++ b/src/test/run-pass/issue-4252.rs @@ -18,10 +18,10 @@ trait X { } #[derive(Debug)] -struct Y(int); +struct Y(isize); #[derive(Debug)] -struct Z { +struct Z { x: T } diff --git a/src/test/run-pass/issue-4333.rs b/src/test/run-pass/issue-4333.rs index 28ab3c3ef1..48753e15a7 100644 --- a/src/test/run-pass/issue-4333.rs +++ b/src/test/run-pass/issue-4333.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::old_io; +// pretty-expanded FIXME #23616 + +#![feature(io)] + +use std::io; pub fn main() { - let stdout = &mut old_io::stdout() as &mut old_io::Writer; + let stdout = &mut io::stdout() as &mut io::Write; stdout.write(b"Hello!"); } diff --git a/src/test/run-pass/issue-4387.rs b/src/test/run-pass/issue-4387.rs index 02601ba2f2..9c4ae04bf7 100644 --- a/src/test/run-pass/issue-4387.rs +++ b/src/test/run-pass/issue-4387.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let _foo = [0; 2*4]; } diff --git a/src/test/run-pass/issue-4446.rs b/src/test/run-pass/issue-4446.rs index b40a726a2c..9f8d93461a 100644 --- a/src/test/run-pass/issue-4446.rs +++ b/src/test/run-pass/issue-4446.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io)] + use std::old_io::println; use std::sync::mpsc::channel; use std::thread; diff --git a/src/test/run-pass/issue-4448.rs b/src/test/run-pass/issue-4448.rs index ef30f9182b..d5d3122f68 100644 --- a/src/test/run-pass/issue-4448.rs +++ b/src/test/run-pass/issue-4448.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::channel; use std::thread; diff --git a/src/test/run-pass/issue-4464.rs b/src/test/run-pass/issue-4464.rs index 33a5c7a167..675ca2c3b7 100644 --- a/src/test/run-pass/issue-4464.rs +++ b/src/test/run-pass/issue-4464.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn broken(v: &[u8], i: uint, j: uint) -> &[u8] { &v[i..j] } +// pretty-expanded FIXME #23616 + +fn broken(v: &[u8], i: usize, j: usize) -> &[u8] { &v[i..j] } pub fn main() {} diff --git a/src/test/run-pass/issue-4542.rs b/src/test/run-pass/issue-4542.rs index 521e1b40f9..23e8f5b0bd 100644 --- a/src/test/run-pass/issue-4542.rs +++ b/src/test/run-pass/issue-4542.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::env; pub fn main() { diff --git a/src/test/run-pass/issue-4545.rs b/src/test/run-pass/issue-4545.rs index bf03b4c453..6cb7ccc0e9 100644 --- a/src/test/run-pass/issue-4545.rs +++ b/src/test/run-pass/issue-4545.rs @@ -10,5 +10,7 @@ // aux-build:issue-4545.rs -extern crate "issue-4545" as somelib; -pub fn main() { somelib::mk::(); } +// pretty-expanded FIXME #23616 + +extern crate issue_4545 as somelib; +pub fn main() { somelib::mk::(); } diff --git a/src/test/run-pass/issue-4734.rs b/src/test/run-pass/issue-4734.rs index c08d3503fa..82925852a6 100644 --- a/src/test/run-pass/issue-4734.rs +++ b/src/test/run-pass/issue-4734.rs @@ -11,12 +11,14 @@ // Ensures that destructors are run for expressions of the form "e;" where // `e` is a type which requires a destructor. +// pretty-expanded FIXME #23616 + #![allow(path_statement)] -struct A { n: int } +struct A { n: isize } struct B; -static mut NUM_DROPS: uint = 0; +static mut NUM_DROPS: usize = 0; impl Drop for A { fn drop(&mut self) { diff --git a/src/test/run-pass/issue-4735.rs b/src/test/run-pass/issue-4735.rs index bf422bd040..56e69a9f36 100644 --- a/src/test/run-pass/issue-4735.rs +++ b/src/test/run-pass/issue-4735.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate + +// pretty-expanded FIXME #23616 #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, libc)] extern crate libc; @@ -23,12 +24,12 @@ struct NonCopyable(*const c_void); impl Drop for NonCopyable { fn drop(&mut self) { let NonCopyable(p) = *self; - let _v = unsafe { transmute::<*const c_void, Box>(p) }; + let _v = unsafe { transmute::<*const c_void, Box>(p) }; } } pub fn main() { let t = box 0; - let p = unsafe { transmute::, *const c_void>(t) }; + let p = unsafe { transmute::, *const c_void>(t) }; let _z = NonCopyable(p); } diff --git a/src/test/run-pass/issue-4759-1.rs b/src/test/run-pass/issue-4759-1.rs index ce2f488b90..3532a395b7 100644 --- a/src/test/run-pass/issue-4759-1.rs +++ b/src/test/run-pass/issue-4759-1.rs @@ -7,9 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// -// ignore-lexer-test FIXME #15877 + +// pretty-expanded FIXME #23616 trait U { fn f(self); } -impl U for int { fn f(self) {} } +impl U for isize { fn f(self) {} } pub fn main() { 4.f(); } diff --git a/src/test/run-pass/issue-4759.rs b/src/test/run-pass/issue-4759.rs index 2245e80971..a26d6b05d7 100644 --- a/src/test/run-pass/issue-4759.rs +++ b/src/test/run-pass/issue-4759.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct T { a: Box } +struct T { a: Box } trait U { fn f(self); } -impl U for Box { +impl U for Box { fn f(self) { } } @@ -25,4 +27,3 @@ pub fn main() { let T { a: a } = T { a: box 0 }; a.f(); } - diff --git a/src/test/run-pass/issue-4830.rs b/src/test/run-pass/issue-4830.rs index 7fc1c10895..f615767c21 100644 --- a/src/test/run-pass/issue-4830.rs +++ b/src/test/run-pass/issue-4830.rs @@ -9,9 +9,11 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct Scheduler { /// The event loop used to drive the scheduler and perform I/O - event_loop: Box + event_loop: Box } pub fn main() { } diff --git a/src/test/run-pass/issue-4875.rs b/src/test/run-pass/issue-4875.rs index 9c1e782ffc..7ac96c21c6 100644 --- a/src/test/run-pass/issue-4875.rs +++ b/src/test/run-pass/issue-4875.rs @@ -10,6 +10,8 @@ // regression test for issue 4875 +// pretty-expanded FIXME #23616 + pub struct Foo { data: T, } diff --git a/src/test/run-pass/issue-5060.rs b/src/test/run-pass/issue-5060.rs index 7c3b0a5f1f..5726f236e2 100644 --- a/src/test/run-pass/issue-5060.rs +++ b/src/test/run-pass/issue-5060.rs @@ -24,4 +24,3 @@ macro_rules! print_hd_tl { pub fn main() { print_hd_tl!(x, y, z, w) } - diff --git a/src/test/run-pass/issue-5192.rs b/src/test/run-pass/issue-5192.rs index a6f3771bf6..d8f7f25508 100644 --- a/src/test/run-pass/issue-5192.rs +++ b/src/test/run-pass/issue-5192.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,7 +18,7 @@ pub trait EventLoop { } pub struct UvEventLoop { - uvio: int + uvio: isize } impl UvEventLoop { diff --git a/src/test/run-pass/issue-5239-2.rs b/src/test/run-pass/issue-5239-2.rs index dd9a6fb354..d8491070bd 100644 --- a/src/test/run-pass/issue-5239-2.rs +++ b/src/test/run-pass/issue-5239-2.rs @@ -10,8 +10,10 @@ // Regression test for issue #5239 +// pretty-expanded FIXME #23616 + pub fn main() { - let _f = |ref x: int| { *x }; + let _f = |ref x: isize| { *x }; let foo = 10; assert!(_f(foo) == 10); } diff --git a/src/test/run-pass/issue-5243.rs b/src/test/run-pass/issue-5243.rs index f5d2c38147..eda0eea707 100644 --- a/src/test/run-pass/issue-5243.rs +++ b/src/test/run-pass/issue-5243.rs @@ -12,8 +12,10 @@ // enough for trans to consider this as non-monomorphic, // which led to various assertions and failures in turn. +// pretty-expanded FIXME #23616 + struct S<'a> { - v: &'a int + v: &'a isize } fn f<'lt>(_s: &'lt S<'lt>) {} diff --git a/src/test/run-pass/issue-5315.rs b/src/test/run-pass/issue-5315.rs index 1d2e7b7993..b8532c55c4 100644 --- a/src/test/run-pass/issue-5315.rs +++ b/src/test/run-pass/issue-5315.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct A(bool); pub fn main() { diff --git a/src/test/run-pass/issue-5321-immediates-with-bare-self.rs b/src/test/run-pass/issue-5321-immediates-with-bare-self.rs index 2ab41f7783..d0bc396c36 100644 --- a/src/test/run-pass/issue-5321-immediates-with-bare-self.rs +++ b/src/test/run-pass/issue-5321-immediates-with-bare-self.rs @@ -14,7 +14,7 @@ trait Fooable { fn yes(self); } -impl Fooable for uint { +impl Fooable for usize { fn yes(self) { for _ in 0..self { println!("yes"); } } diff --git a/src/test/run-pass/issue-5353.rs b/src/test/run-pass/issue-5353.rs index 1f6493d961..34ef63572a 100644 --- a/src/test/run-pass/issue-5353.rs +++ b/src/test/run-pass/issue-5353.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + const INVALID_ENUM : u32 = 0; const INVALID_VALUE : u32 = 1; diff --git a/src/test/run-pass/issue-5518.rs b/src/test/run-pass/issue-5518.rs index a28bc9f825..5981a0148a 100644 --- a/src/test/run-pass/issue-5518.rs +++ b/src/test/run-pass/issue-5518.rs @@ -10,6 +10,8 @@ // aux-build:issue-5518.rs -extern crate "issue-5518" as other; +// pretty-expanded FIXME #23616 + +extern crate issue_5518 as other; fn main() {} diff --git a/src/test/run-pass/issue-5521.rs b/src/test/run-pass/issue-5521.rs index fb0e8e599e..4ad729f1bc 100644 --- a/src/test/run-pass/issue-5521.rs +++ b/src/test/run-pass/issue-5521.rs @@ -11,13 +11,15 @@ // aux-build:issue-5521.rs -extern crate "issue-5521" as foo; +// pretty-expanded FIXME #23616 + +extern crate issue_5521 as foo; fn bar(a: foo::map) { if false { panic!(); } else { - let _b = &(*a)[2]; + let _b = &(*a)[&2]; } } diff --git a/src/test/run-pass/issue-5530.rs b/src/test/run-pass/issue-5530.rs index a9e1ffcb34..50b9ca6e79 100644 --- a/src/test/run-pass/issue-5530.rs +++ b/src/test/run-pass/issue-5530.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Enum { - Foo { foo: uint }, - Bar { bar: uint } + Foo { foo: usize }, + Bar { bar: usize } } -fn fun1(e1: &Enum, e2: &Enum) -> uint { +fn fun1(e1: &Enum, e2: &Enum) -> usize { match (e1, e2) { (&Enum::Foo { foo: _ }, &Enum::Foo { foo: _ }) => 0, (&Enum::Foo { foo: _ }, &Enum::Bar { bar: _ }) => 1, @@ -22,7 +24,7 @@ fn fun1(e1: &Enum, e2: &Enum) -> uint { } } -fn fun2(e1: &Enum, e2: &Enum) -> uint { +fn fun2(e1: &Enum, e2: &Enum) -> usize { match (e1, e2) { (&Enum::Foo { foo: _ }, &Enum::Foo { foo: _ }) => 0, (&Enum::Foo { foo: _ }, _ ) => 1, diff --git a/src/test/run-pass/issue-5550.rs b/src/test/run-pass/issue-5550.rs index f87f1d8af7..91741f938a 100644 --- a/src/test/run-pass/issue-5550.rs +++ b/src/test/run-pass/issue-5550.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] pub fn main() { diff --git a/src/test/run-pass/issue-5554.rs b/src/test/run-pass/issue-5554.rs index 32fca7a182..e8190a7245 100644 --- a/src/test/run-pass/issue-5554.rs +++ b/src/test/run-pass/issue-5554.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::default::Default; pub struct X { @@ -26,7 +28,7 @@ impl Default for X { macro_rules! constants { () => { - let _ : X = Default::default(); + let _ : X = Default::default(); } } diff --git a/src/test/run-pass/issue-5572.rs b/src/test/run-pass/issue-5572.rs index 4e57ed9499..6ae9dc68a5 100644 --- a/src/test/run-pass/issue-5572.rs +++ b/src/test/run-pass/issue-5572.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(_t: T) { } pub fn main() { } diff --git a/src/test/run-pass/issue-5666.rs b/src/test/run-pass/issue-5666.rs index 4f304e3b43..e28a929d52 100644 --- a/src/test/run-pass/issue-5666.rs +++ b/src/test/run-pass/issue-5666.rs @@ -35,4 +35,3 @@ pub fn main() { println!("{}", pup.bark()); } } - diff --git a/src/test/run-pass/issue-5688.rs b/src/test/run-pass/issue-5688.rs index 9612c4bf18..88ff103723 100644 --- a/src/test/run-pass/issue-5688.rs +++ b/src/test/run-pass/issue-5688.rs @@ -13,12 +13,12 @@ ...should print &[1, 2, 3] but instead prints something like &[4492532864, 24]. It is pretty evident that the compiler messed up -with the representation of [int; n] and [int] somehow, or at least +with the representation of [isize; n] and [isize] somehow, or at least failed to typecheck correctly. */ -#[derive(Copy)] -struct X { vec: &'static [int] } +#[derive(Copy, Clone)] +struct X { vec: &'static [isize] } static V: &'static [X] = &[X { vec: &[1, 2, 3] }]; diff --git a/src/test/run-pass/issue-5708.rs b/src/test/run-pass/issue-5708.rs index 59bca87bed..dfb560db10 100644 --- a/src/test/run-pass/issue-5708.rs +++ b/src/test/run-pass/issue-5708.rs @@ -24,7 +24,7 @@ trait Inner { fn print(&self); } -impl Inner for int { +impl Inner for isize { fn print(&self) { print!("Inner: {}\n", *self); } } @@ -41,7 +41,7 @@ impl<'a> Outer<'a> { } pub fn main() { - let inner = 5; + let inner: isize = 5; let outer = Outer::new(&inner as &Inner); outer.inner.print(); } diff --git a/src/test/run-pass/issue-5718.rs b/src/test/run-pass/issue-5718.rs index 36aa8a9cbc..964809631d 100644 --- a/src/test/run-pass/issue-5718.rs +++ b/src/test/run-pass/issue-5718.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,15 +18,15 @@ struct Element; macro_rules! foo { ($tag: expr, $string: expr) => { if $tag == $string { - let element = box Element; + let element: Box<_> = box Element; unsafe { - return std::mem::transmute::<_, uint>(element); + return std::mem::transmute::<_, usize>(element); } } } } -fn bar() -> uint { +fn bar() -> usize { foo!("a", "b"); 0 } diff --git a/src/test/run-pass/issue-5741.rs b/src/test/run-pass/issue-5741.rs index 0aaa0c8624..5190bd95ad 100644 --- a/src/test/run-pass/issue-5741.rs +++ b/src/test/run-pass/issue-5741.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unreachable_code)] pub fn main() { diff --git a/src/test/run-pass/issue-5754.rs b/src/test/run-pass/issue-5754.rs index b2eeedfbdc..e6bc516acc 100644 --- a/src/test/run-pass/issue-5754.rs +++ b/src/test/run-pass/issue-5754.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct TwoDoubles { r: f64, i: f64 diff --git a/src/test/run-pass/issue-5791.rs b/src/test/run-pass/issue-5791.rs index 468f420624..aad90bd418 100644 --- a/src/test/run-pass/issue-5791.rs +++ b/src/test/run-pass/issue-5791.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; extern { diff --git a/src/test/run-pass/issue-5884.rs b/src/test/run-pass/issue-5884.rs index 6502c66d85..2096bebd2b 100644 --- a/src/test/run-pass/issue-5884.rs +++ b/src/test/run-pass/issue-5884.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub struct Foo { - a: int, + a: isize, } struct Bar<'a> { - a: Box>, + a: Box>, b: &'a Foo, } diff --git a/src/test/run-pass/issue-5900.rs b/src/test/run-pass/issue-5900.rs index 4518b503c0..d3a43b51dc 100644 --- a/src/test/run-pass/issue-5900.rs +++ b/src/test/run-pass/issue-5900.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub mod foo { use super::Bar; @@ -15,7 +17,7 @@ pub mod foo { } pub enum Bar { - Bar0 = 0 as int + Bar0 = 0 as isize } pub fn main() {} diff --git a/src/test/run-pass/issue-5917.rs b/src/test/run-pass/issue-5917.rs index 5b60126735..7f741182f4 100644 --- a/src/test/run-pass/issue-5917.rs +++ b/src/test/run-pass/issue-5917.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct T (&'static [int]); +// pretty-expanded FIXME #23616 + +struct T (&'static [isize]); static t : T = T (&[5, 4, 3]); pub fn main () { let T(ref v) = t; diff --git a/src/test/run-pass/issue-5950.rs b/src/test/run-pass/issue-5950.rs index c9413258e0..b0e01db14d 100644 --- a/src/test/run-pass/issue-5950.rs +++ b/src/test/run-pass/issue-5950.rs @@ -9,8 +9,10 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub use local as local_alias; -mod local { } +pub mod local { } pub fn main() {} diff --git a/src/test/run-pass/issue-5988.rs b/src/test/run-pass/issue-5988.rs index 1ad48d326e..8ec88d5572 100644 --- a/src/test/run-pass/issue-5988.rs +++ b/src/test/run-pass/issue-5988.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io)] + use std::old_io; trait B { fn f(&self); diff --git a/src/test/run-pass/issue-5997.rs b/src/test/run-pass/issue-5997.rs index 0ce8823bc9..48923bc82b 100644 --- a/src/test/run-pass/issue-5997.rs +++ b/src/test/run-pass/issue-5997.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn f() -> bool { enum E { V(T) } @@ -17,6 +19,6 @@ fn f() -> bool { } fn main() { - let b = f::(); + let b = f::(); assert!(b); } diff --git a/src/test/run-pass/issue-6117.rs b/src/test/run-pass/issue-6117.rs index 93edffdcb4..5552729740 100644 --- a/src/test/run-pass/issue-6117.rs +++ b/src/test/run-pass/issue-6117.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 enum Either { Left(T), Right(U) } pub fn main() { - match Either::Left(box 17) { + match Either::Left(Box::new(17)) { Either::Right(()) => {} _ => {} } diff --git a/src/test/run-pass/issue-6128.rs b/src/test/run-pass/issue-6128.rs index 1746a6281d..baf829bc26 100644 --- a/src/test/run-pass/issue-6128.rs +++ b/src/test/run-pass/issue-6128.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, collections)] extern crate collections; @@ -21,16 +23,16 @@ trait Graph { } -impl Graph for HashMap { +impl Graph for HashMap { fn f(&self, _e: E) { panic!(); } - fn g(&self, _e: int) { + fn g(&self, _e: isize) { panic!(); } } pub fn main() { - let g : Box> = box HashMap::new(); - let _g2 : Box> = g as Box>; + let g : Box> = box HashMap::new(); + let _g2 : Box> = g as Box>; } diff --git a/src/test/run-pass/issue-6130.rs b/src/test/run-pass/issue-6130.rs index 93429ff10d..6f15833916 100644 --- a/src/test/run-pass/issue-6130.rs +++ b/src/test/run-pass/issue-6130.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![deny(type_limits)] pub fn main() { - let i: uint = 0; - assert!(i <= 0xFFFF_FFFF_usize); + let i: usize = 0; + assert!(i <= 0xFFFF_FFFF); - let i: int = 0; - assert!(i >= -0x8000_0000__isize); - assert!(i <= 0x7FFF_FFFF__isize); + let i: isize = 0; + assert!(i >= -0x8000_0000); + assert!(i <= 0x7FFF_FFFF); } diff --git a/src/test/run-pass/issue-6153.rs b/src/test/run-pass/issue-6153.rs index b2b64e62c3..c280ea31eb 100644 --- a/src/test/run-pass/issue-6153.rs +++ b/src/test/run-pass/issue-6153.rs @@ -9,7 +9,9 @@ // except according to those terms. -fn swap(f: F) -> Vec where F: FnOnce(Vec) -> Vec { +// pretty-expanded FIXME #23616 + +fn swap(f: F) -> Vec where F: FnOnce(Vec) -> Vec { let x = vec!(1, 2, 3); f(x) } diff --git a/src/test/run-pass/issue-6157.rs b/src/test/run-pass/issue-6157.rs index 39f387afab..c7832ae41e 100644 --- a/src/test/run-pass/issue-6157.rs +++ b/src/test/run-pass/issue-6157.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait OpInt { fn call(&mut self, int, int) -> int; } +// pretty-expanded FIXME #23616 -impl OpInt for F where F: FnMut(int, int) -> int { - fn call(&mut self, a:int, b:int) -> int { +pub trait OpInt { fn call(&mut self, isize, isize) -> isize; } + +impl OpInt for F where F: FnMut(isize, isize) -> isize { + fn call(&mut self, a:isize, b:isize) -> isize { (*self)(a, b) } } -fn squarei<'a>(x: int, op: &'a mut OpInt) -> int { op.call(x, x) } +fn squarei<'a>(x: isize, op: &'a mut OpInt) -> isize { op.call(x, x) } -fn muli(x:int, y:int) -> int { x * y } +fn muli(x:isize, y:isize) -> isize { x * y } pub fn main() { let mut f = |x, y| muli(x, y); diff --git a/src/test/run-pass/issue-6318.rs b/src/test/run-pass/issue-6318.rs index 6e608d34bd..12b71f519b 100644 --- a/src/test/run-pass/issue-6318.rs +++ b/src/test/run-pass/issue-6318.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -28,4 +30,3 @@ pub fn main() { Thing::A(_a) => 0, }; } - diff --git a/src/test/run-pass/issue-6334.rs b/src/test/run-pass/issue-6334.rs index 67440b6ec1..2f2dca8fe2 100644 --- a/src/test/run-pass/issue-6334.rs +++ b/src/test/run-pass/issue-6334.rs @@ -11,38 +11,40 @@ // Tests that everything still compiles and runs fine even when // we reorder the bounds. +// pretty-expanded FIXME #23616 + trait A { - fn a(&self) -> uint; + fn a(&self) -> usize; } trait B { - fn b(&self) -> uint; + fn b(&self) -> usize; } trait C { - fn combine(&self, t: &T) -> uint; + fn combine(&self, t: &T) -> usize; } struct Foo; impl A for Foo { - fn a(&self) -> uint { 1 } + fn a(&self) -> usize { 1 } } impl B for Foo { - fn b(&self) -> uint { 2 } + fn b(&self) -> usize { 2 } } struct Bar; impl C for Bar { // Note below: bounds in impl decl are in reverse order. - fn combine(&self, t: &T) -> uint { + fn combine(&self, t: &T) -> usize { (t.a() * 100) + t.b() } } -fn use_c(s: &S, t: &T) -> uint { +fn use_c(s: &S, t: &T) -> usize { s.combine(t) } diff --git a/src/test/run-pass/issue-6341.rs b/src/test/run-pass/issue-6341.rs index 6e49c04356..41abaa2c8b 100644 --- a/src/test/run-pass/issue-6341.rs +++ b/src/test/run-pass/issue-6341.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(PartialEq)] -struct A { x: uint } +struct A { x: usize } impl Drop for A { fn drop(&mut self) {} diff --git a/src/test/run-pass/issue-6344-let.rs b/src/test/run-pass/issue-6344-let.rs index 65ee062a03..8449d9f572 100644 --- a/src/test/run-pass/issue-6344-let.rs +++ b/src/test/run-pass/issue-6344-let.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct A { x: uint } +struct A { x: usize } impl Drop for A { fn drop(&mut self) {} diff --git a/src/test/run-pass/issue-6344-match.rs b/src/test/run-pass/issue-6344-match.rs index ee99ec957b..4bb23295c8 100644 --- a/src/test/run-pass/issue-6344-match.rs +++ b/src/test/run-pass/issue-6344-match.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct A { x: uint } +struct A { x: usize } impl Drop for A { fn drop(&mut self) {} diff --git a/src/test/run-pass/issue-6449.rs b/src/test/run-pass/issue-6449.rs index 9a5fc7763f..3b33a0ac86 100644 --- a/src/test/run-pass/issue-6449.rs +++ b/src/test/run-pass/issue-6449.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { - Bar(int), + Bar(isize), Baz, } diff --git a/src/test/run-pass/issue-6470.rs b/src/test/run-pass/issue-6470.rs index ef16415080..9b5f78a145 100644 --- a/src/test/run-pass/issue-6470.rs +++ b/src/test/run-pass/issue-6470.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub mod Bar { pub struct Foo { - v: int, + v: isize, } extern { diff --git a/src/test/run-pass/issue-6557.rs b/src/test/run-pass/issue-6557.rs index b9f4f1cf3b..eba87f418e 100644 --- a/src/test/run-pass/issue-6557.rs +++ b/src/test/run-pass/issue-6557.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] -fn foo(box (_x, _y): Box<(int, int)>) {} +fn foo(box (_x, _y): Box<(isize, isize)>) {} pub fn main() {} diff --git a/src/test/run-pass/issue-6892.rs b/src/test/run-pass/issue-6892.rs index 557ec82233..4469dcc0ce 100644 --- a/src/test/run-pass/issue-6892.rs +++ b/src/test/run-pass/issue-6892.rs @@ -11,12 +11,14 @@ // Ensures that destructors are run for expressions of the form "let _ = e;" // where `e` is a type which requires a destructor. +// pretty-expanded FIXME #23616 + struct Foo; -struct Bar { x: int } -struct Baz(int); -enum FooBar { _Foo(Foo), _Bar(uint) } +struct Bar { x: isize } +struct Baz(isize); +enum FooBar { _Foo(Foo), _Bar(usize) } -static mut NUM_DROPS: uint = 0; +static mut NUM_DROPS: usize = 0; impl Drop for Foo { fn drop(&mut self) { @@ -49,7 +51,7 @@ fn main() { assert_eq!(unsafe { NUM_DROPS }, 3); { let _x = FooBar::_Foo(Foo); } assert_eq!(unsafe { NUM_DROPS }, 5); - { let _x = FooBar::_Bar(42_usize); } + { let _x = FooBar::_Bar(42); } assert_eq!(unsafe { NUM_DROPS }, 6); { let _ = Foo; } @@ -60,6 +62,6 @@ fn main() { assert_eq!(unsafe { NUM_DROPS }, 9); { let _ = FooBar::_Foo(Foo); } assert_eq!(unsafe { NUM_DROPS }, 11); - { let _ = FooBar::_Bar(42_usize); } + { let _ = FooBar::_Bar(42); } assert_eq!(unsafe { NUM_DROPS }, 12); } diff --git a/src/test/run-pass/issue-6898.rs b/src/test/run-pass/issue-6898.rs index 9e6293216b..3138aad2c8 100644 --- a/src/test/run-pass/issue-6898.rs +++ b/src/test/run-pass/issue-6898.rs @@ -8,31 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::intrinsics; /// Returns the size of a type -pub fn size_of() -> uint { +pub fn size_of() -> usize { TypeInfo::size_of(None::) } /// Returns the size of the type that `val` points to -pub fn size_of_val(val: &T) -> uint { +pub fn size_of_val(val: &T) -> usize { val.size_of_val() } pub trait TypeInfo { - fn size_of(_lame_type_hint: Option) -> uint; - fn size_of_val(&self) -> uint; + fn size_of(_lame_type_hint: Option) -> usize; + fn size_of_val(&self) -> usize; } impl TypeInfo for T { /// The size of the type in bytes. - fn size_of(_lame_type_hint: Option) -> uint { + fn size_of(_lame_type_hint: Option) -> usize { unsafe { intrinsics::size_of::() } } /// Returns the size of the type of `self` in bytes. - fn size_of_val(&self) -> uint { + fn size_of_val(&self) -> usize { TypeInfo::size_of(None::) } } diff --git a/src/test/run-pass/issue-6919.rs b/src/test/run-pass/issue-6919.rs index c684c4d897..3495c0eb1a 100644 --- a/src/test/run-pass/issue-6919.rs +++ b/src/test/run-pass/issue-6919.rs @@ -10,10 +10,11 @@ // aux-build:iss.rs +// pretty-expanded FIXME #23616 + #![crate_id="issue-6919"] extern crate issue6919_3; pub fn main() { let _ = issue6919_3::D.k; } - diff --git a/src/test/run-pass/issue-7012.rs b/src/test/run-pass/issue-7012.rs index 96db28f4a1..3a9864f3a7 100644 --- a/src/test/run-pass/issue-7012.rs +++ b/src/test/run-pass/issue-7012.rs @@ -18,11 +18,11 @@ would be printed, however the below prints false. struct signature<'a> { pattern : &'a [u32] } static test1: signature<'static> = signature { - pattern: &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32,0x03707344u32,0xa4093822u32,0x299f31d0u32] + pattern: &[0x243f6a88,0x85a308d3,0x13198a2e,0x03707344,0xa4093822,0x299f31d0] }; pub fn main() { - let test: &[u32] = &[0x243f6a88u32,0x85a308d3u32,0x13198a2eu32, - 0x03707344u32,0xa4093822u32,0x299f31d0u32]; + let test: &[u32] = &[0x243f6a88,0x85a308d3,0x13198a2e, + 0x03707344,0xa4093822,0x299f31d0]; println!("{}",test==test1.pattern); } diff --git a/src/test/run-pass/issue-7178.rs b/src/test/run-pass/issue-7178.rs index 6ef740b2a5..0882203cb1 100644 --- a/src/test/run-pass/issue-7178.rs +++ b/src/test/run-pass/issue-7178.rs @@ -10,7 +10,9 @@ // aux-build:issue-7178.rs -extern crate "issue-7178" as cross_crate_self; +// pretty-expanded FIXME #23616 + +extern crate issue_7178 as cross_crate_self; pub fn main() { let _ = cross_crate_self::Foo::new(&1); diff --git a/src/test/run-pass/issue-7222.rs b/src/test/run-pass/issue-7222.rs index 65ea895c2c..1bf343e23f 100644 --- a/src/test/run-pass/issue-7222.rs +++ b/src/test/run-pass/issue-7222.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { const FOO: f64 = 10.0; @@ -16,4 +18,3 @@ pub fn main() { _ => () } } - diff --git a/src/test/run-pass/issue-7268.rs b/src/test/run-pass/issue-7268.rs index 8aa9592731..626adfe292 100644 --- a/src/test/run-pass/issue-7268.rs +++ b/src/test/run-pass/issue-7268.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn foo(_: T) {} fn bar(x: &'static T) { diff --git a/src/test/run-pass/issue-7344.rs b/src/test/run-pass/issue-7344.rs index 6e2ed27725..fb348fb453 100644 --- a/src/test/run-pass/issue-7344.rs +++ b/src/test/run-pass/issue-7344.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unreachable_code)] fn foo() -> bool { false } diff --git a/src/test/run-pass/issue-7519-match-unit-in-arg.rs b/src/test/run-pass/issue-7519-match-unit-in-arg.rs index 75123243f4..c5c59407ab 100644 --- a/src/test/run-pass/issue-7519-match-unit-in-arg.rs +++ b/src/test/run-pass/issue-7519-match-unit-in-arg.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* #7519 ICE pattern matching unit in function argument */ diff --git a/src/test/run-pass/issue-7563.rs b/src/test/run-pass/issue-7563.rs index eda2057f6d..6d2a602fc8 100644 --- a/src/test/run-pass/issue-7563.rs +++ b/src/test/run-pass/issue-7563.rs @@ -13,9 +13,9 @@ trait IDummy { } #[derive(Debug)] -struct A { a: int } +struct A { a: isize } #[derive(Debug)] -struct B<'a> { b: int, pa: &'a A } +struct B<'a> { b: isize, pa: &'a A } impl IDummy for A { fn do_nothing(&self) { diff --git a/src/test/run-pass/issue-7575.rs b/src/test/run-pass/issue-7575.rs index 77cfc7f0cf..727ed91ead 100644 --- a/src/test/run-pass/issue-7575.rs +++ b/src/test/run-pass/issue-7575.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn new() -> bool { false } fn dummy(&self) { } @@ -17,8 +19,8 @@ trait Bar { fn new(&self) -> bool { true } } -impl Bar for int {} -impl Foo for int {} +impl Bar for isize {} +impl Foo for isize {} fn main() { assert!(1.new()); diff --git a/src/test/compile-fail/issue-7607-2.rs b/src/test/run-pass/issue-7607-2.rs similarity index 81% rename from src/test/compile-fail/issue-7607-2.rs rename to src/test/run-pass/issue-7607-2.rs index 9541899b46..799513e6e4 100644 --- a/src/test/compile-fail/issue-7607-2.rs +++ b/src/test/run-pass/issue-7607-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength +// pretty-expanded FIXME #23616 pub mod a { pub struct Foo { a: usize } @@ -16,11 +16,9 @@ pub mod a { pub mod b { use a::Foo; - impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module + impl Foo { fn bar(&self) { } } } pub fn main() { } - - diff --git a/src/test/run-pass/issue-7660.rs b/src/test/run-pass/issue-7660.rs index 9e36b1f508..b0ebc6c9cc 100644 --- a/src/test/run-pass/issue-7660.rs +++ b/src/test/run-pass/issue-7660.rs @@ -11,16 +11,20 @@ // Regression test for issue 7660 // rvalue lifetime too short when equivalent `match` works +// pretty-expanded FIXME #23616 + +#![feature(collections)] + extern crate collections; use std::collections::HashMap; -struct A(int, int); +struct A(isize, isize); pub fn main() { - let mut m: HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); m.insert(1, A(0, 0)); - let A(ref _a, ref _b) = m[1]; - let (a, b) = match m[1] { A(ref _a, ref _b) => (_a, _b) }; + let A(ref _a, ref _b) = m[&1]; + let (a, b) = match m[&1] { A(ref _a, ref _b) => (_a, _b) }; } diff --git a/src/test/run-pass/issue-7663.rs b/src/test/run-pass/issue-7663.rs index 0ff265e483..007127aeae 100644 --- a/src/test/run-pass/issue-7663.rs +++ b/src/test/run-pass/issue-7663.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_imports, dead_code)] mod test1 { - mod foo { pub fn p() -> int { 1 } } - mod bar { pub fn p() -> int { 2 } } + mod foo { pub fn p() -> isize { 1 } } + mod bar { pub fn p() -> isize { 2 } } pub mod baz { use test1::bar::p; @@ -24,8 +26,8 @@ mod test1 { mod test2 { - mod foo { pub fn p() -> int { 1 } } - mod bar { pub fn p() -> int { 2 } } + mod foo { pub fn p() -> isize { 1 } } + mod bar { pub fn p() -> isize { 2 } } pub mod baz { use test2::bar::p; diff --git a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs index 736860947f..43b5a997c1 100644 --- a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs +++ b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* #7673 Polymorphically creating traits barely works diff --git a/src/test/run-pass/issue-7784.rs b/src/test/run-pass/issue-7784.rs index a61ee8c2a0..e2016feeb0 100644 --- a/src/test/run-pass/issue-7784.rs +++ b/src/test/run-pass/issue-7784.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] use std::ops::Add; diff --git a/src/test/run-pass/issue-7899.rs b/src/test/run-pass/issue-7899.rs index 4b3d46f483..a17565fa0a 100644 --- a/src/test/run-pass/issue-7899.rs +++ b/src/test/run-pass/issue-7899.rs @@ -10,7 +10,9 @@ // aux-build:issue-7899.rs -extern crate "issue-7899" as testcrate; +// pretty-expanded FIXME #23616 + +extern crate issue_7899 as testcrate; fn main() { let f = testcrate::V2(1.0f32, 2.0f32); diff --git a/src/test/run-pass/issue-8044.rs b/src/test/run-pass/issue-8044.rs index 504441e3ba..4f72409c36 100644 --- a/src/test/run-pass/issue-8044.rs +++ b/src/test/run-pass/issue-8044.rs @@ -10,9 +10,11 @@ // aux-build:issue-8044.rs -extern crate "issue-8044" as minimal; +// pretty-expanded FIXME #23616 + +extern crate issue_8044 as minimal; use minimal::{BTree, leaf}; pub fn main() { - BTree:: { node: leaf(1) }; + BTree:: { node: leaf(1) }; } diff --git a/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs b/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs index 3238c24163..92d1c7c5a1 100644 --- a/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs +++ b/src/test/run-pass/issue-8171-default-method-self-inherit-builtin-trait.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* #8171 Self is not recognised as implementing kinds in default method implementations diff --git a/src/test/run-pass/issue-8248.rs b/src/test/run-pass/issue-8248.rs index 7bc8dbe616..b58be361f1 100644 --- a/src/test/run-pass/issue-8248.rs +++ b/src/test/run-pass/issue-8248.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn dummy(&self) { } } @@ -20,4 +22,3 @@ pub fn main() { let mut b = B; foo(&mut b as &mut A); } - diff --git a/src/test/run-pass/issue-8249.rs b/src/test/run-pass/issue-8249.rs index 83c9e9bf45..3e65bc000f 100644 --- a/src/test/run-pass/issue-8249.rs +++ b/src/test/run-pass/issue-8249.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn dummy(&self) { } } @@ -24,4 +26,3 @@ fn foo(a: &mut A) { pub fn main() { } - diff --git a/src/test/run-pass/issue-8259.rs b/src/test/run-pass/issue-8259.rs index fb893873bc..e7f09789c5 100644 --- a/src/test/run-pass/issue-8259.rs +++ b/src/test/run-pass/issue-8259.rs @@ -10,7 +10,9 @@ // aux-build:issue-8259.rs -extern crate "issue-8259" as other; +// pretty-expanded FIXME #23616 + +extern crate issue_8259 as other; static a: other::Foo<'static> = other::Foo::A; pub fn main() {} diff --git a/src/test/run-pass/issue-8351-1.rs b/src/test/run-pass/issue-8351-1.rs index b7e6facc58..a11e14fb33 100644 --- a/src/test/run-pass/issue-8351-1.rs +++ b/src/test/run-pass/issue-8351-1.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { - Foo{f: int}, + Foo{f: isize}, Bar, } diff --git a/src/test/run-pass/issue-8351-2.rs b/src/test/run-pass/issue-8351-2.rs index 40e0b3a8ee..7cf221926a 100644 --- a/src/test/run-pass/issue-8351-2.rs +++ b/src/test/run-pass/issue-8351-2.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { - Foo{f: int, b: bool}, + Foo{f: isize, b: bool}, Bar, } diff --git a/src/test/run-pass/issue-8391.rs b/src/test/run-pass/issue-8391.rs index 86c9b8c696..bd2e2871bd 100644 --- a/src/test/run-pass/issue-8391.rs +++ b/src/test/run-pass/issue-8391.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let x = match Some(1) { ref _y @ Some(_) => 1, diff --git a/src/test/run-pass/issue-8398.rs b/src/test/run-pass/issue-8398.rs index e52e3295c6..8eb10a199e 100644 --- a/src/test/run-pass/issue-8398.rs +++ b/src/test/run-pass/issue-8398.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io, io)] + use std::old_io; fn foo(a: &mut old_io::Writer) { @@ -15,4 +19,3 @@ fn foo(a: &mut old_io::Writer) { } pub fn main(){} - diff --git a/src/test/run-pass/issue-8401.rs b/src/test/run-pass/issue-8401.rs index 1ca91366f3..afdd572b12 100644 --- a/src/test/run-pass/issue-8401.rs +++ b/src/test/run-pass/issue-8401.rs @@ -10,6 +10,8 @@ // aux-build:issue_8401.rs +// pretty-expanded FIXME #23616 + extern crate issue_8401; pub fn main() {} diff --git a/src/test/run-pass/issue-8460.rs b/src/test/run-pass/issue-8460.rs index 00339a4e84..7d8c4ab210 100644 --- a/src/test/run-pass/issue-8460.rs +++ b/src/test/run-pass/issue-8460.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::num::Int; use std::thread; @@ -21,19 +25,19 @@ fn main() { assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); - assert!(thread::spawn(move|| { 1isize / zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i8 / zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i16 / zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i32 / zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i64 / zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1isize / zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i8 / zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i16 / zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i32 / zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i64 / zero::(); }).join().is_err()); assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); - assert!(thread::spawn(move|| { 1isize % zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i8 % zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i16 % zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i32 % zero(); }).join().is_err()); - assert!(thread::spawn(move|| { 1i64 % zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1isize % zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i8 % zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i16 % zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i32 % zero::(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i64 % zero::(); }).join().is_err()); } diff --git a/src/test/run-pass/issue-8498.rs b/src/test/run-pass/issue-8498.rs index 494b621785..825729b1e2 100644 --- a/src/test/run-pass/issue-8498.rs +++ b/src/test/run-pass/issue-8498.rs @@ -8,18 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 pub fn main() { - match &[(box 5,box 7)] { + match &[(Box::new(5),Box::new(7))] { ps => { let (ref y, _) = ps[0]; assert!(**y == 5); } } - match Some(&[(box 5,)]) { + match Some(&[(Box::new(5),)]) { Some(ps) => { let (ref y,) = ps[0]; assert!(**y == 5); @@ -27,7 +26,7 @@ pub fn main() { None => () } - match Some(&[(box 5,box 7)]) { + match Some(&[(Box::new(5),Box::new(7))]) { Some(ps) => { let (ref y, ref z) = ps[0]; assert!(**y == 5); diff --git a/src/test/run-pass/issue-8506.rs b/src/test/run-pass/issue-8506.rs index 54dfe2b9da..24632a0d13 100644 --- a/src/test/run-pass/issue-8506.rs +++ b/src/test/run-pass/issue-8506.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] enum Either { diff --git a/src/test/run-pass/issue-8578.rs b/src/test/run-pass/issue-8578.rs index 275fe740db..ce392f8d88 100644 --- a/src/test/run-pass/issue-8578.rs +++ b/src/test/run-pass/issue-8578.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub struct UninterpretedOption_NamePart { name_part: Option, } diff --git a/src/test/run-pass/issue-868.rs b/src/test/run-pass/issue-868.rs index e47999fc46..64b463ddf5 100644 --- a/src/test/run-pass/issue-868.rs +++ b/src/test/run-pass/issue-868.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn f(g: F) -> T where F: FnOnce() -> T { g() } pub fn main() { diff --git a/src/test/run-pass/issue-8709.rs b/src/test/run-pass/issue-8709.rs index 865905bf50..6467262929 100644 --- a/src/test/run-pass/issue-8709.rs +++ b/src/test/run-pass/issue-8709.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! sty { ($t:ty) => (stringify!($t)) } @@ -17,6 +19,6 @@ macro_rules! spath { } fn main() { - assert_eq!(sty!(int), "int"); + assert_eq!(sty!(isize), "isize"); assert_eq!(spath!(std::option), "std::option"); } diff --git a/src/test/run-pass/issue-8783.rs b/src/test/run-pass/issue-8783.rs index 815e00e129..485a76ff7e 100644 --- a/src/test/run-pass/issue-8783.rs +++ b/src/test/run-pass/issue-8783.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::default::Default; -struct X { pub x: uint } +struct X { pub x: usize } impl Default for X { fn default() -> X { - X { x: 42_usize } + X { x: 42 } } } diff --git a/src/test/run-pass/issue-8827.rs b/src/test/run-pass/issue-8827.rs index d7a8674954..280311af6f 100644 --- a/src/test/run-pass/issue-8827.rs +++ b/src/test/run-pass/issue-8827.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::{channel, Receiver}; -fn periodical(n: int) -> Receiver { +fn periodical(n: isize) -> Receiver { let (chan, port) = channel(); - Thread::spawn(move|| { + thread::spawn(move|| { loop { for _ in 1..n { match chan.send(false) { @@ -30,9 +32,9 @@ fn periodical(n: int) -> Receiver { return port; } -fn integers() -> Receiver { +fn integers() -> Receiver { let (chan, port) = channel(); - Thread::spawn(move|| { + thread::spawn(move|| { let mut i = 1; loop { match chan.send(i) { diff --git a/src/test/run-pass/issue-8851.rs b/src/test/run-pass/issue-8851.rs index b70711f9f3..2a0c02b23e 100644 --- a/src/test/run-pass/issue-8851.rs +++ b/src/test/run-pass/issue-8851.rs @@ -13,14 +13,16 @@ // doesn't cause capture. Making this macro hygienic (as I've done) // could very well make this test case completely pointless.... +// pretty-expanded FIXME #23616 + enum T { - A(int), - B(uint) + A(isize), + B(usize) } macro_rules! test { ($id:ident, $e:expr) => ( - fn foo(t: T) -> int { + fn foo(t: T) -> isize { match t { T::A($id) => $e, T::B($id) => $e @@ -29,7 +31,7 @@ macro_rules! test { ) } -test!(y, 10 + (y as int)); +test!(y, 10 + (y as isize)); pub fn main() { foo(T::A(20)); diff --git a/src/test/run-pass/issue-8860.rs b/src/test/run-pass/issue-8860.rs index 72e2a33b43..8024eaeda8 100644 --- a/src/test/run-pass/issue-8860.rs +++ b/src/test/run-pass/issue-8860.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static mut DROP: int = 0; -static mut DROP_S: int = 0; -static mut DROP_T: int = 0; +// pretty-expanded FIXME #23616 + +static mut DROP: isize = 0; +static mut DROP_S: isize = 0; +static mut DROP_T: isize = 0; struct S; impl Drop for S { @@ -23,7 +25,7 @@ impl Drop for S { } fn f(ref _s: S) {} -struct T { i: int } +struct T { i: isize } impl Drop for T { fn drop(&mut self) { unsafe { diff --git a/src/test/run-pass/issue-8898.rs b/src/test/run-pass/issue-8898.rs index b1c443dd0c..a4cad1b263 100644 --- a/src/test/run-pass/issue-8898.rs +++ b/src/test/run-pass/issue-8898.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn assert_repr_eq(obj : T, expected : String) { assert_eq!(expected, format!("{:?}", obj)); } diff --git a/src/test/run-pass/issue-9047.rs b/src/test/run-pass/issue-9047.rs index 9941381985..aa3e601c3a 100644 --- a/src/test/run-pass/issue-9047.rs +++ b/src/test/run-pass/issue-9047.rs @@ -10,7 +10,7 @@ fn decode() -> String { 'outer: loop { - let mut ch_start: uint; + let mut ch_start: usize; break 'outer; } "".to_string() diff --git a/src/test/run-pass/issue-9110.rs b/src/test/run-pass/issue-9110.rs index 09d0f20c96..298ae5e6aa 100644 --- a/src/test/run-pass/issue-9110.rs +++ b/src/test/run-pass/issue-9110.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! silly_macro { () => ( pub mod Qux { diff --git a/src/test/run-pass/issue-9123.rs b/src/test/run-pass/issue-9123.rs index f66215aa43..4da0c22a0b 100644 --- a/src/test/run-pass/issue-9123.rs +++ b/src/test/run-pass/issue-9123.rs @@ -10,6 +10,8 @@ // aux-build:issue_9123.rs +// pretty-expanded FIXME #23616 + extern crate issue_9123; pub fn main() {} diff --git a/src/test/run-pass/issue-9129.rs b/src/test/run-pass/issue-9129.rs index 6c84399304..99db47c172 100644 --- a/src/test/run-pass/issue-9129.rs +++ b/src/test/run-pass/issue-9129.rs @@ -17,7 +17,7 @@ pub trait bomb { fn boom(&self, Ident); } pub struct S; impl bomb for S { fn boom(&self, _: Ident) { } } -pub struct Ident { name: uint } +pub struct Ident { name: usize } // macro_rules! int3 { () => ( unsafe { asm!( "int3" ); } ) } macro_rules! int3 { () => ( { } ) } diff --git a/src/test/run-pass/issue-9188.rs b/src/test/run-pass/issue-9188.rs index 31797deccf..0bd8a8e0d9 100644 --- a/src/test/run-pass/issue-9188.rs +++ b/src/test/run-pass/issue-9188.rs @@ -10,11 +10,12 @@ // aux-build:issue_9188.rs +// pretty-expanded FIXME #23616 + extern crate issue_9188; pub fn main() { let a = issue_9188::bar(); - let b = issue_9188::foo::(); + let b = issue_9188::foo::(); assert_eq!(*a, *b); } - diff --git a/src/test/run-pass/issue-9249.rs b/src/test/run-pass/issue-9249.rs index 2795fd59c0..e4d848dbd7 100644 --- a/src/test/run-pass/issue-9249.rs +++ b/src/test/run-pass/issue-9249.rs @@ -8,5 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + static DATA:&'static [&'static str] = &["my string"]; fn main() { } diff --git a/src/test/run-pass/issue-9259.rs b/src/test/run-pass/issue-9259.rs index da5338b8c3..209c6b1396 100644 --- a/src/test/run-pass/issue-9259.rs +++ b/src/test/run-pass/issue-9259.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct A<'a> { a: &'a [String], b: Option<&'a [String]>, diff --git a/src/test/run-pass/issue-9382.rs b/src/test/run-pass/issue-9382.rs index c501420fa6..2c84e202b2 100644 --- a/src/test/run-pass/issue-9382.rs +++ b/src/test/run-pass/issue-9382.rs @@ -1,3 +1,5 @@ +// pretty-expanded FIXME #23616 + // 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. @@ -19,12 +21,12 @@ struct Thing1<'a> { - baz: &'a [Box], + baz: &'a [Box], bar: Box, } struct Thing2<'a> { - baz: &'a [Box], + baz: &'a [Box], bar: u64, } diff --git a/src/test/run-pass/issue-9394-inherited-trait-calls.rs b/src/test/run-pass/issue-9394-inherited-trait-calls.rs index 7273a45d89..148d0760e5 100644 --- a/src/test/run-pass/issue-9394-inherited-trait-calls.rs +++ b/src/test/run-pass/issue-9394-inherited-trait-calls.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Base: Base2 + Base3{ fn foo(&self) -> String; fn foo1(&self) -> String; diff --git a/src/test/run-pass/issue-9396.rs b/src/test/run-pass/issue-9396.rs index a98d1aba04..bfaf060e43 100644 --- a/src/test/run-pass/issue-9396.rs +++ b/src/test/run-pass/issue-9396.rs @@ -8,14 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io, std_misc)] + use std::sync::mpsc::{TryRecvError, channel}; use std::old_io::timer::Timer; -use std::thread::Thread; +use std::thread; use std::time::Duration; pub fn main() { let (tx, rx) = channel(); - let _t = Thread::scoped(move||{ + let _t = thread::scoped(move||{ let mut timer = Timer::new().unwrap(); timer.sleep(Duration::milliseconds(10)); tx.send(()).unwrap(); diff --git a/src/test/run-pass/issue-9719.rs b/src/test/run-pass/issue-9719.rs index aa1e65efaa..108f1a0d73 100644 --- a/src/test/run-pass/issue-9719.rs +++ b/src/test/run-pass/issue-9719.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod a { pub enum Enum { A(T), @@ -16,32 +18,32 @@ mod a { pub trait X { fn dummy(&self) { } } - impl X for int {} + impl X for isize {} pub struct Z<'a>(Enum<&'a (X+'a)>); - fn foo() { let x = 42; let z = Z(Enum::A(&x as &X)); let _ = z; } + fn foo() { let x: isize = 42; let z = Z(Enum::A(&x as &X)); let _ = z; } } mod b { trait X { fn dummy(&self) { } } - impl X for int {} + impl X for isize {} struct Y<'a>{ x:Option<&'a (X+'a)>, } fn bar() { - let x = 42; + let x: isize = 42; let _y = Y { x: Some(&x as &X) }; } } mod c { pub trait X { fn f(&self); } - impl X for int { fn f(&self) {} } + impl X for isize { fn f(&self) {} } pub struct Z<'a>(Option<&'a (X+'a)>); - fn main() { let x = 42; let z = Z(Some(&x as &X)); let _ = z; } + fn main() { let x: isize = 42; let z = Z(Some(&x as &X)); let _ = z; } } pub fn main() {} diff --git a/src/test/run-pass/issue-979.rs b/src/test/run-pass/issue-979.rs index 919f0aae38..3283dc44f3 100644 --- a/src/test/run-pass/issue-979.rs +++ b/src/test/run-pass/issue-979.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] use std::cell::Cell; struct r<'a> { - b: &'a Cell, + b: &'a Cell, } #[unsafe_destructor] @@ -23,7 +25,7 @@ impl<'a> Drop for r<'a> { } } -fn r(b: &Cell) -> r { +fn r(b: &Cell) -> r { r { b: b } diff --git a/src/test/run-pass/issue-9906.rs b/src/test/run-pass/issue-9906.rs index 921965b280..84f848fc9c 100644 --- a/src/test/run-pass/issue-9906.rs +++ b/src/test/run-pass/issue-9906.rs @@ -10,7 +10,9 @@ // aux-build:issue-9906.rs -extern crate "issue-9906" as testmod; +// pretty-expanded FIXME #23616 + +extern crate issue_9906 as testmod; pub fn main() { testmod::foo(); diff --git a/src/test/run-pass/issue-9918.rs b/src/test/run-pass/issue-9918.rs index 240a134221..e81a07fa68 100644 --- a/src/test/run-pass/issue-9918.rs +++ b/src/test/run-pass/issue-9918.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert_eq!((0 + 0u8) as char, '\0'); } diff --git a/src/test/run-pass/issue-9942.rs b/src/test/run-pass/issue-9942.rs index c7dea71998..222eb0c651 100644 --- a/src/test/run-pass/issue-9942.rs +++ b/src/test/run-pass/issue-9942.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - const S: uint = 23 as uint; [0; S]; () + const S: usize = 23 as usize; [0; S]; () } diff --git a/src/test/run-pass/issue-9951.rs b/src/test/run-pass/issue-9951.rs new file mode 100644 index 0000000000..63807395fb --- /dev/null +++ b/src/test/run-pass/issue-9951.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +trait Bar { + fn noop(&self); +} +impl Bar for u8 { + fn noop(&self) {} +} + +fn main() { + let (a, b) = (&5u8 as &Bar, &9u8 as &Bar); + let (c, d): (&Bar, &Bar) = (a, b); + + let (a, b) = (Box::new(5u8) as Box, Box::new(9u8) as Box); + let (c, d): (&Bar, &Bar) = (&*a, &*b); + + let (c, d): (&Bar, &Bar) = (&5, &9); +} diff --git a/src/test/run-pass/issue-9968.rs b/src/test/run-pass/issue-9968.rs index 2c9382be9b..c8af811d13 100644 --- a/src/test/run-pass/issue-9968.rs +++ b/src/test/run-pass/issue-9968.rs @@ -10,7 +10,9 @@ // aux-build:issue-9968.rs -extern crate "issue-9968" as lib; +// pretty-expanded FIXME #23616 + +extern crate issue_9968 as lib; use lib::{Trait, Struct}; diff --git a/src/test/run-pass/issue2170exe.rs b/src/test/run-pass/issue2170exe.rs index b4a41ef44f..d126d1f6ce 100644 --- a/src/test/run-pass/issue2170exe.rs +++ b/src/test/run-pass/issue2170exe.rs @@ -9,8 +9,10 @@ // except according to those terms. // aux-build:issue2170lib.rs +// pretty-expanded FIXME #23616 + extern crate issue2170lib; pub fn main() { - // let _ = issue2170lib::rsrc(2i32); + // let _ = issue2170lib::rsrc(2); } diff --git a/src/test/run-pass/issue22346.rs b/src/test/run-pass/issue22346.rs index 3193e5c5fc..8538950a89 100644 --- a/src/test/run-pass/issue22346.rs +++ b/src/test/run-pass/issue22346.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + // This used to cause an ICE because the retslot for the "return" had the wrong type fn testcase<'a>() -> Box + 'a> { - return Box::new(range(0, 3).map(|i| { return i; })); + return Box::new((0..3).map(|i| { return i; })); } fn main() { diff --git a/src/test/run-pass/issue_3136_b.rs b/src/test/run-pass/issue_3136_b.rs index a6fb993a96..cffe3f9572 100644 --- a/src/test/run-pass/issue_3136_b.rs +++ b/src/test/run-pass/issue_3136_b.rs @@ -10,5 +10,7 @@ // aux-build:issue_3136_a.rc +// pretty-expanded FIXME #23616 + extern crate issue_3136_a; pub fn main() {} diff --git a/src/test/run-pass/issue_9155.rs b/src/test/run-pass/issue_9155.rs index 951cde3264..9db556bf9a 100644 --- a/src/test/run-pass/issue_9155.rs +++ b/src/test/run-pass/issue_9155.rs @@ -10,6 +10,8 @@ // aux-build:issue_9155.rs +// pretty-expanded FIXME #23616 + extern crate issue_9155; struct Baz; diff --git a/src/test/run-pass/istr.rs b/src/test/run-pass/istr.rs index 15195482ed..0013cb292e 100644 --- a/src/test/run-pass/istr.rs +++ b/src/test/run-pass/istr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(collections)] + use std::string::String; fn test_stack_assign() { diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index 6036af5c62..c2ed68fc5d 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -12,7 +12,9 @@ // for completeness since .rs files linked from .rc files support this // notation to specify their module's attributes -#![feature(custom_attribute)] +// pretty-expanded FIXME #23616 + +#![feature(custom_attribute, libc)] #![allow(unused_attribute)] #![attr1 = "val"] #![attr2 = "val"] @@ -28,7 +30,7 @@ mod test_first_item_in_file_mod {} mod test_single_attr_outer { #[attr = "val"] - pub static x: int = 10; + pub static x: isize = 10; #[attr = "val"] pub fn f() { } @@ -45,7 +47,7 @@ mod test_single_attr_outer { mod test_multi_attr_outer { #[attr1 = "val"] #[attr2 = "val"] - pub static x: int = 10; + pub static x: isize = 10; #[attr1 = "val"] #[attr2 = "val"] @@ -63,13 +65,13 @@ mod test_multi_attr_outer { #[attr1 = "val"] #[attr2 = "val"] - struct t {x: int} + struct t {x: isize} } mod test_stmt_single_attr_outer { pub fn f() { #[attr = "val"] - static x: int = 10; + static x: isize = 10; #[attr = "val"] fn f() { } @@ -91,7 +93,7 @@ mod test_stmt_multi_attr_outer { #[attr1 = "val"] #[attr2 = "val"] - static x: int = 10; + static x: isize = 10; #[attr1 = "val"] #[attr2 = "val"] @@ -174,8 +176,8 @@ mod test_foreign_items { /*mod test_literals { #![str = "s"] #![char = 'c'] - #![int = 100] - #![uint = 100_usize] + #![isize = 100] + #![usize = 100_usize] #![mach_int = 100u32] #![float = 1.0] #![mach_float = 1.0f32] diff --git a/src/test/run-pass/item-name-overload.rs b/src/test/run-pass/item-name-overload.rs index 9aefda4bc7..2827a6df33 100644 --- a/src/test/run-pass/item-name-overload.rs +++ b/src/test/run-pass/item-name-overload.rs @@ -11,6 +11,8 @@ +// pretty-expanded FIXME #23616 + mod foo { pub fn baz() { } } diff --git a/src/test/run-pass/iter-cloned-type-inference.rs b/src/test/run-pass/iter-cloned-type-inference.rs new file mode 100644 index 0000000000..12f6a7caf6 --- /dev/null +++ b/src/test/run-pass/iter-cloned-type-inference.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test to see that the element type of .cloned() can be inferred +// properly. Previously this would fail to deduce the type of `sum`. + +// pretty-expanded FIXME #23616 + +#![feature(core)] + +use std::iter::AdditiveIterator; + +fn square_sum(v: &[i64]) -> i64 { + let sum = v.iter().cloned().sum(); + sum * sum +} + +fn main() { + assert_eq!(36, square_sum(&[1,2,3])); +} diff --git a/src/test/run-pass/iter-range.rs b/src/test/run-pass/iter-range.rs index 29ac563878..a6130841b5 100644 --- a/src/test/run-pass/iter-range.rs +++ b/src/test/run-pass/iter-range.rs @@ -10,14 +10,14 @@ -fn range_(a: int, b: int, mut it: F) where F: FnMut(int) { +fn range_(a: isize, b: isize, mut it: F) where F: FnMut(isize) { assert!((a < b)); - let mut i: int = a; + let mut i: isize = a; while i < b { it(i); i += 1; } } pub fn main() { - let mut sum: int = 0; + let mut sum: isize = 0; range_(0, 100, |x| sum += x ); println!("{}", sum); } diff --git a/src/test/run-pass/ivec-pass-by-value.rs b/src/test/run-pass/ivec-pass-by-value.rs index 36f0d3c1c5..62aa300578 100644 --- a/src/test/run-pass/ivec-pass-by-value.rs +++ b/src/test/run-pass/ivec-pass-by-value.rs @@ -9,5 +9,7 @@ // except according to those terms. -fn f(_a: Vec ) { } +// pretty-expanded FIXME #23616 + +fn f(_a: Vec ) { } pub fn main() { f(vec!(1, 2, 3, 4, 5)); } diff --git a/src/test/run-pass/ivec-tag.rs b/src/test/run-pass/ivec-tag.rs index dd38a5f8b3..8ae084dce8 100644 --- a/src/test/run-pass/ivec-tag.rs +++ b/src/test/run-pass/ivec-tag.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::{channel, Sender}; fn producer(tx: &Sender>) { tx.send( - vec!(1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8, - 13u8)).unwrap(); + vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13)).unwrap(); } pub fn main() { let (tx, rx) = channel::>(); - let _prod = Thread::spawn(move|| { + let _prod = thread::scoped(move|| { producer(&tx) }); diff --git a/src/test/run-pass/keyword-changes-2012-07-31.rs b/src/test/run-pass/keyword-changes-2012-07-31.rs index ff568b77f0..9838fe6239 100644 --- a/src/test/run-pass/keyword-changes-2012-07-31.rs +++ b/src/test/run-pass/keyword-changes-2012-07-31.rs @@ -12,13 +12,15 @@ // mod -> module // match -> match +// pretty-expanded FIXME #23616 + pub fn main() { } mod foo { } -fn bar() -> int { +fn bar() -> isize { match 0 { _ => { 0 } } diff --git a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs index f2d509ee61..11b1d70137 100644 --- a/src/test/run-pass/kindck-implicit-close-over-mut-var.rs +++ b/src/test/run-pass/kindck-implicit-close-over-mut-var.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] -fn user(_i: int) {} +use std::thread; + +fn user(_i: isize) {} fn foo() { // Here, i is *copied* into the proc (heap closure). // Requires allocation. The proc's copy is not mutable. let mut i = 0; - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { user(i); println!("spawned {}", i) }); @@ -29,7 +31,7 @@ fn bar() { // mutable outside of the proc. let mut i = 0; while i < 10 { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { user(i); }); i += 1; @@ -40,7 +42,7 @@ fn car() { // Here, i must be shadowed in the proc to be mutable. let mut i = 0; while i < 10 { - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let mut i = i; i += 1; user(i); @@ -50,4 +52,3 @@ fn car() { } pub fn main() {} - diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs index f05ac11d41..84156385ef 100644 --- a/src/test/run-pass/kindck-owned-trait-contains-1.rs +++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] diff --git a/src/test/run-pass/kinds-in-metadata.rs b/src/test/run-pass/kinds-in-metadata.rs index 233db83d28..84c5da1ad6 100644 --- a/src/test/run-pass/kinds-in-metadata.rs +++ b/src/test/run-pass/kinds-in-metadata.rs @@ -10,6 +10,8 @@ // aux-build:kinds_in_metadata.rs +// pretty-expanded FIXME #23616 + /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ @@ -20,6 +22,5 @@ extern crate kinds_in_metadata; use kinds_in_metadata::f; pub fn main() { - f::(); + f::(); } - diff --git a/src/test/run-pass/labeled-break.rs b/src/test/run-pass/labeled-break.rs index 30c2495d59..fe2f35c511 100644 --- a/src/test/run-pass/labeled-break.rs +++ b/src/test/run-pass/labeled-break.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { 'foo: loop { loop { diff --git a/src/test/run-pass/lambda-infer-unresolved.rs b/src/test/run-pass/lambda-infer-unresolved.rs index 3c2a3f355b..fca700f6e4 100644 --- a/src/test/run-pass/lambda-infer-unresolved.rs +++ b/src/test/run-pass/lambda-infer-unresolved.rs @@ -12,11 +12,11 @@ // resolved when we finish typechecking the ||. -struct Refs { refs: Vec , n: int } +struct Refs { refs: Vec , n: isize } pub fn main() { let mut e = Refs{refs: vec!(), n: 0}; let _f = || println!("{}", e.n); - let x: &[int] = &e.refs; + let x: &[isize] = &e.refs; assert_eq!(x.len(), 0); } diff --git a/src/test/run-pass/lambda-var-hygiene.rs b/src/test/run-pass/lambda-var-hygiene.rs index a6060bebbc..e5bdca1a06 100644 --- a/src/test/run-pass/lambda-var-hygiene.rs +++ b/src/test/run-pass/lambda-var-hygiene.rs @@ -15,7 +15,7 @@ macro_rules! bad_macro { ($ex:expr) => ({(|_x| { $ex }) (9) }) } -fn takes_x(_x : int) { +fn takes_x(_x : isize) { assert_eq!(bad_macro!(_x),8); } fn main() { diff --git a/src/test/run-pass/lang-item-public.rs b/src/test/run-pass/lang-item-public.rs index 350ec68a7d..f5b9bd4fba 100644 --- a/src/test/run-pass/lang-item-public.rs +++ b/src/test/run-pass/lang-item-public.rs @@ -10,12 +10,11 @@ // aux-build:lang-item-public.rs // ignore-android -// ignore-windows #13361 #![feature(lang_items, start, no_std)] #![no_std] -extern crate "lang-item-public" as lang_lib; +extern crate lang_item_public as lang_lib; #[cfg(target_os = "linux")] #[link(name = "c")] @@ -37,7 +36,7 @@ extern {} #[link(name = "c")] extern {} -#[cfg(target_os = "openbsd")] +#[cfg(any(target_os = "bitrig", target_os = "openbsd"))] #[link(name = "c")] extern {} @@ -46,6 +45,6 @@ extern {} extern {} #[start] -fn main(_: int, _: *const *const u8) -> int { - 1 % 1 +fn main(_: isize, _: *const *const u8) -> isize { + 1_isize % 1_isize } diff --git a/src/test/run-pass/large-records.rs b/src/test/run-pass/large-records.rs index 20ec058b9f..e9c66093fb 100644 --- a/src/test/run-pass/large-records.rs +++ b/src/test/run-pass/large-records.rs @@ -12,18 +12,20 @@ -struct Large {a: int, - b: int, - c: int, - d: int, - e: int, - f: int, - g: int, - h: int, - i: int, - j: int, - k: int, - l: int} +// pretty-expanded FIXME #23616 + +struct Large {a: isize, + b: isize, + c: isize, + d: isize, + e: isize, + f: isize, + g: isize, + h: isize, + i: isize, + j: isize, + k: isize, + l: isize} fn f() { let _foo: Large = Large {a: 0, diff --git a/src/test/run-pass/last-use-in-block.rs b/src/test/run-pass/last-use-in-block.rs index 8ef5df5d69..28fe3bf0bd 100644 --- a/src/test/run-pass/last-use-in-block.rs +++ b/src/test/run-pass/last-use-in-block.rs @@ -10,6 +10,8 @@ // Issue #1818 +// pretty-expanded FIXME #23616 + fn lp(s: String, mut f: F) -> T where F: FnMut(String) -> T { while false { let r = f(s); diff --git a/src/test/run-pass/last-use-in-cap-clause.rs b/src/test/run-pass/last-use-in-cap-clause.rs index 566d34e6d8..f9c8fe0f2d 100644 --- a/src/test/run-pass/last-use-in-cap-clause.rs +++ b/src/test/run-pass/last-use-in-cap-clause.rs @@ -10,18 +10,21 @@ // Make sure #1399 stays fixed +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] struct A { a: Box } fn foo() -> Box isize + 'static> { - let k = box 22; + let k: Box<_> = box 22; let _u = A {a: k.clone()}; - // FIXME(#16640) suffix in `22_isize` suffix shouldn't be necessary - let result = || 22_isize; - box result + // FIXME(#16640) suffix in `22` suffix shouldn't be necessary + let result = || 22; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Box::new(result) } pub fn main() { diff --git a/src/test/run-pass/last-use-is-capture.rs b/src/test/run-pass/last-use-is-capture.rs index 19a780d180..35a1715078 100644 --- a/src/test/run-pass/last-use-is-capture.rs +++ b/src/test/run-pass/last-use-is-capture.rs @@ -13,11 +13,11 @@ #![allow(unknown_features)] #![feature(box_syntax)] -struct A { a: Box } +struct A { a: Box } pub fn main() { fn invoke(f: F) where F: FnOnce() { f(); } - let k = box 22; + let k: Box<_> = box 22; let _u = A {a: k.clone()}; invoke(|| println!("{}", k.clone()) ) } diff --git a/src/test/run-pass/lazy-and-or.rs b/src/test/run-pass/lazy-and-or.rs index 559c9e7894..500de64ae8 100644 --- a/src/test/run-pass/lazy-and-or.rs +++ b/src/test/run-pass/lazy-and-or.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn incr(x: &mut int) -> bool { *x += 1; assert!((false)); return false; } +fn incr(x: &mut isize) -> bool { *x += 1; assert!((false)); return false; } pub fn main() { let x = 1 == 2 || 3 == 3; assert!((x)); - let mut y: int = 10; + let mut y: isize = 10; println!("{}", x || incr(&mut y)); assert_eq!(y, 10); if true && x { assert!((true)); } else { assert!((false)); } diff --git a/src/test/run-pass/lazy-init.rs b/src/test/run-pass/lazy-init.rs index 60f7689ecf..d71d7e751a 100644 --- a/src/test/run-pass/lazy-init.rs +++ b/src/test/run-pass/lazy-init.rs @@ -10,6 +10,6 @@ -fn foo(x: int) { println!("{}", x); } +fn foo(x: isize) { println!("{}", x); } -pub fn main() { let mut x: int; if 1 > 2 { x = 12; } else { x = 10; } foo(x); } +pub fn main() { let mut x: isize; if 1 > 2 { x = 12; } else { x = 10; } foo(x); } diff --git a/src/test/run-pass/leak-unique-as-tydesc.rs b/src/test/run-pass/leak-unique-as-tydesc.rs index 65808de3cf..30838b3121 100644 --- a/src/test/run-pass/leak-unique-as-tydesc.rs +++ b/src/test/run-pass/leak-unique-as-tydesc.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] fn leaky(_t: T) { } -pub fn main() { let x = box 10; leaky::>(x); } +pub fn main() { let x = box 10; leaky::>(x); } diff --git a/src/test/run-pass/let-assignability.rs b/src/test/run-pass/let-assignability.rs index 9ac016d534..c53bc83ef6 100644 --- a/src/test/run-pass/let-assignability.rs +++ b/src/test/run-pass/let-assignability.rs @@ -12,8 +12,8 @@ #![feature(box_syntax)] fn f() { - let a = box 1; - let b: &int = &*a; + let a: Box<_> = box 1; + let b: &isize = &*a; println!("{}", b); } diff --git a/src/test/run-pass/let-destruct-ref.rs b/src/test/run-pass/let-destruct-ref.rs index c0f674d037..0b38d16941 100644 --- a/src/test/run-pass/let-destruct-ref.rs +++ b/src/test/run-pass/let-destruct-ref.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = 3_usize; let ref y = x; diff --git a/src/test/run-pass/let-var-hygiene.rs b/src/test/run-pass/let-var-hygiene.rs index d6409267eb..c1e80aaf2d 100644 --- a/src/test/run-pass/let-var-hygiene.rs +++ b/src/test/run-pass/let-var-hygiene.rs @@ -9,6 +9,8 @@ // except according to those terms. // shouldn't affect evaluation of $ex: +// pretty-expanded FIXME #23616 + macro_rules! bad_macro { ($ex:expr) => ({let _x = 9; $ex}) } diff --git a/src/test/run-pass/linear-for-loop.rs b/src/test/run-pass/linear-for-loop.rs index 22a29279a6..80bd15578d 100644 --- a/src/test/run-pass/linear-for-loop.rs +++ b/src/test/run-pass/linear-for-loop.rs @@ -17,7 +17,7 @@ pub fn main() { println!("{}", y); assert_eq!(y, 6); let s = "hello there".to_string(); - let mut i: int = 0; + let mut i: isize = 0; for c in s.bytes() { if i == 0 { assert!((c == 'h' as u8)); } if i == 1 { assert!((c == 'e' as u8)); } diff --git a/src/test/run-pass/link-section.rs b/src/test/run-pass/link-section.rs index 38b5a858af..3336ce7e72 100644 --- a/src/test/run-pass/link-section.rs +++ b/src/test/run-pass/link-section.rs @@ -16,11 +16,11 @@ fn i_live_in_more_text() -> &'static str { #[cfg(not(target_os = "macos"))] #[link_section=".imm"] -static magic: uint = 42; +static magic: usize = 42; #[cfg(not(target_os = "macos"))] #[link_section=".mut"] -static mut frobulator: uint = 0xdeadbeef; +static mut frobulator: usize = 0xdeadbeef; #[cfg(target_os = "macos")] #[link_section="__TEXT,__moretext"] @@ -30,11 +30,11 @@ fn i_live_in_more_text() -> &'static str { #[cfg(target_os = "macos")] #[link_section="__RODATA,__imm"] -static magic: uint = 42; +static magic: usize = 42; #[cfg(target_os = "macos")] #[link_section="__DATA,__mut"] -static mut frobulator: uint = 0xdeadbeef; +static mut frobulator: usize = 0xdeadbeef; pub fn main() { unsafe { diff --git a/src/test/run-pass/linkage-visibility.rs b/src/test/run-pass/linkage-visibility.rs index 80a859c03b..945cf9370f 100644 --- a/src/test/run-pass/linkage-visibility.rs +++ b/src/test/run-pass/linkage-visibility.rs @@ -12,10 +12,12 @@ // ignore-android: FIXME(#10379) // ignore-windows: std::dynamic_lib does not work on Windows well -extern crate "linkage-visibility" as foo; +#![feature(std_misc, old_path)] + +extern crate linkage_visibility as foo; pub fn main() { foo::test(); - foo::foo2::(); + foo::foo2::(); foo::foo(); } diff --git a/src/test/run-pass/linkage1.rs b/src/test/run-pass/linkage1.rs index 5cd741350d..0794a5e0da 100644 --- a/src/test/run-pass/linkage1.rs +++ b/src/test/run-pass/linkage1.rs @@ -14,13 +14,13 @@ #![feature(linkage)] -extern crate "linkage1" as other; +extern crate linkage1 as other; extern { #[linkage = "extern_weak"] - static foo: *const int; + static foo: *const isize; #[linkage = "extern_weak"] - static something_that_should_never_exist: *mut int; + static something_that_should_never_exist: *mut isize; } fn main() { diff --git a/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs b/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs index 061f702552..6ddaee9c8b 100644 --- a/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs +++ b/src/test/run-pass/lint-non-camel-case-types-non-uppercase-statics-unicode.rs @@ -20,6 +20,6 @@ struct ヒ; -static ラ: uint = 0; +static ラ: usize = 0; pub fn main() {} diff --git a/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs b/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs index f51312bc25..3b4bd001e8 100644 --- a/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs +++ b/src/test/run-pass/lint-non-camel-case-with-trailing-underscores.rs @@ -10,7 +10,9 @@ // This is ok because we often use the trailing underscore to mean 'prime' +// pretty-expanded FIXME #23616 + #[forbid(non_camel_case_types)] -type Foo_ = int; +type Foo_ = isize; pub fn main() { } diff --git a/src/test/run-pass/lint-non-uppercase-statics-lowercase-mut-statics.rs b/src/test/run-pass/lint-non-uppercase-statics-lowercase-mut-statics.rs index ce3518618d..aa5b3834c0 100644 --- a/src/test/run-pass/lint-non-uppercase-statics-lowercase-mut-statics.rs +++ b/src/test/run-pass/lint-non-uppercase-statics-lowercase-mut-statics.rs @@ -9,9 +9,11 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #![forbid(non_camel_case_types)] #![forbid(non_upper_case_globals)] -static mut bar: int = 2; +static mut bar: isize = 2; pub fn main() {} diff --git a/src/test/run-pass/list.rs b/src/test/run-pass/list.rs index e55c1b36f3..8f0cbf96b6 100644 --- a/src/test/run-pass/list.rs +++ b/src/test/run-pass/list.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -enum list { cons(int, Box), nil, } +enum list { cons(isize, Box), nil, } pub fn main() { list::cons(10, box list::cons(11, box list::cons(12, box list::nil))); } diff --git a/src/test/run-pass/liveness-assign-imm-local-after-loop.rs b/src/test/run-pass/liveness-assign-imm-local-after-loop.rs index 143972fe29..df89809ef1 100644 --- a/src/test/run-pass/liveness-assign-imm-local-after-loop.rs +++ b/src/test/run-pass/liveness-assign-imm-local-after-loop.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unreachable_code)] #![allow(unused_variable)] fn test(_cond: bool) { - let v: int; + let v: isize; v = 1; loop { } // loop never terminates, so no error is reported v = 2; diff --git a/src/test/run-pass/liveness-assign-imm-local-after-ret.rs b/src/test/run-pass/liveness-assign-imm-local-after-ret.rs index f13e2826c8..6fc15478f7 100644 --- a/src/test/run-pass/liveness-assign-imm-local-after-ret.rs +++ b/src/test/run-pass/liveness-assign-imm-local-after-ret.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unreachable_code)] fn test() { - let _v: int; + let _v: isize; _v = 1; return; _v = 2; //~ WARNING: unreachable statement diff --git a/src/test/run-pass/liveness-move-in-loop.rs b/src/test/run-pass/liveness-move-in-loop.rs index 9120151051..f9bb45ee40 100644 --- a/src/test/run-pass/liveness-move-in-loop.rs +++ b/src/test/run-pass/liveness-move-in-loop.rs @@ -9,7 +9,9 @@ // except according to those terms. -fn take(x: int) -> int {x} +// pretty-expanded FIXME #23616 + +fn take(x: isize) -> isize {x} fn the_loop() { let mut list = Vec::new(); diff --git a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs index c4b45ae0f0..1991e2b178 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs @@ -10,7 +10,7 @@ #[derive(Clone, Debug)] enum foo { - a(uint), + a(usize), b(String), } diff --git a/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs b/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs index 95a5f1003b..4932831186 100644 --- a/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs +++ b/src/test/run-pass/log_syntax-trace_macros-macro-locations.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(trace_macros, log_syntax)] // make sure these macros can be used as in the various places that diff --git a/src/test/run-pass/logging-enabled-debug.rs b/src/test/run-pass/logging-enabled-debug.rs index 262d9b21eb..59f5b0af35 100644 --- a/src/test/run-pass/logging-enabled-debug.rs +++ b/src/test/run-pass/logging-enabled-debug.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:--cfg ndebug +// compile-flags:-C debug-assertions=no // exec-env:RUST_LOG=logging-enabled-debug=debug +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + #[macro_use] extern crate log; diff --git a/src/test/run-pass/logging-enabled.rs b/src/test/run-pass/logging-enabled.rs index 372cdc401b..294d4d1217 100644 --- a/src/test/run-pass/logging-enabled.rs +++ b/src/test/run-pass/logging-enabled.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// exec-env:RUST_LOG=logging-enabled=info +// exec-env:RUST_LOG=logging_enabled=info + +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] #[macro_use] extern crate log; diff --git a/src/test/run-pass/logging-only-prints-once.rs b/src/test/run-pass/logging-only-prints-once.rs index b03c4b5ff4..575f087d83 100644 --- a/src/test/run-pass/logging-only-prints-once.rs +++ b/src/test/run-pass/logging-only-prints-once.rs @@ -15,7 +15,7 @@ use std::cell::Cell; use std::fmt; use std::thread; -struct Foo(Cell); +struct Foo(Cell); impl fmt::Debug for Foo { fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/test/run-pass/logging-right-crate.rs b/src/test/run-pass/logging-right-crate.rs index ced1fdc445..7caeeb4012 100644 --- a/src/test/run-pass/logging-right-crate.rs +++ b/src/test/run-pass/logging-right-crate.rs @@ -21,9 +21,11 @@ // longer happens by enabling logging for *this* crate and then invoking a // function in an external crate which will panic when logging is enabled. +// pretty-expanded FIXME #23616 + extern crate logging_right_crate; pub fn main() { // this function panicks if logging is turned on - logging_right_crate::foo::(); + logging_right_crate::foo::(); } diff --git a/src/test/run-pass/logging-separate-lines.rs b/src/test/run-pass/logging-separate-lines.rs index 8526dfe72d..b27080b65b 100644 --- a/src/test/run-pass/logging-separate-lines.rs +++ b/src/test/run-pass/logging-separate-lines.rs @@ -10,6 +10,9 @@ // ignore-windows // exec-env:RUST_LOG=debug +// compile-flags:-C debug-assertions=y + +#![feature(old_io, rustc_private)] #[macro_use] extern crate log; diff --git a/src/test/run-pass/logging_before_rt_started.rs b/src/test/run-pass/logging_before_rt_started.rs index 8a21d60e46..820285188a 100644 --- a/src/test/run-pass/logging_before_rt_started.rs +++ b/src/test/run-pass/logging_before_rt_started.rs @@ -16,4 +16,6 @@ // this test will trigger "output during runtime initialization" to make sure // that the bug isn't re-introduced. +// pretty-expanded FIXME #23616 + pub fn main() {} diff --git a/src/test/run-pass/long-while.rs b/src/test/run-pass/long-while.rs index cbe2684470..6e0f1bb87a 100644 --- a/src/test/run-pass/long-while.rs +++ b/src/test/run-pass/long-while.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_variable)] pub fn main() { - let mut i: int = 0; + let mut i: isize = 0; while i < 1000000 { i += 1; let x = 3; diff --git a/src/test/run-pass/loop-break-cont-1.rs b/src/test/run-pass/loop-break-cont-1.rs index d58d2a7139..eaf69dbae0 100644 --- a/src/test/run-pass/loop-break-cont-1.rs +++ b/src/test/run-pass/loop-break-cont-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let _i = 0_usize; loop { diff --git a/src/test/run-pass/loop-diverges.rs b/src/test/run-pass/loop-diverges.rs index 9c46ba2cb9..c2ad9a6ef7 100644 --- a/src/test/run-pass/loop-diverges.rs +++ b/src/test/run-pass/loop-diverges.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* Make sure a loop{} can be the tailexpr in the body of a diverging function */ diff --git a/src/test/run-pass/loop-label-shadowing.rs b/src/test/run-pass/loop-label-shadowing.rs index d96ff869fa..399920a7e3 100644 --- a/src/test/run-pass/loop-label-shadowing.rs +++ b/src/test/run-pass/loop-label-shadowing.rs @@ -10,10 +10,11 @@ // Issue #12512. +// pretty-expanded FIXME #23616 + fn main() { let mut foo = Vec::new(); 'foo: for i in &[1, 2, 3] { foo.push(*i); } } - diff --git a/src/test/run-pass/loop-labeled-break-value.rs b/src/test/run-pass/loop-labeled-break-value.rs new file mode 100644 index 0000000000..4f03b45b11 --- /dev/null +++ b/src/test/run-pass/loop-labeled-break-value.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +fn main() { + 'outer: loop { + let _: i32 = loop { break 'outer }; + } + 'outer: loop { + let _: i32 = loop { loop { break 'outer } }; + } +} diff --git a/src/test/run-pass/loop-no-reinit-needed-post-bot.rs b/src/test/run-pass/loop-no-reinit-needed-post-bot.rs index 2582c2e614..689e17c170 100644 --- a/src/test/run-pass/loop-no-reinit-needed-post-bot.rs +++ b/src/test/run-pass/loop-no-reinit-needed-post-bot.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct S; // Ensure S is moved, not copied, on assignment. impl Drop for S { fn drop(&mut self) { } } diff --git a/src/test/run-pass/loop-scope.rs b/src/test/run-pass/loop-scope.rs index 88711a4605..70f2830555 100644 --- a/src/test/run-pass/loop-scope.rs +++ b/src/test/run-pass/loop-scope.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = vec!(10, 20, 30); let mut sum = 0; diff --git a/src/test/run-pass/macro-2.rs b/src/test/run-pass/macro-2.rs index 80b2f408c1..d582fc3b72 100644 --- a/src/test/run-pass/macro-2.rs +++ b/src/test/run-pass/macro-2.rs @@ -14,7 +14,7 @@ pub fn main() { macro_rules! mylambda_tt { ($x:ident, $body:expr) => ({ - fn f($x: int) -> int { return $body; }; + fn f($x: isize) -> isize { return $body; }; f }) } diff --git a/src/test/run-pass/macro-attributes.rs b/src/test/run-pass/macro-attributes.rs index 521aef4b5b..2752fc88b4 100644 --- a/src/test/run-pass/macro-attributes.rs +++ b/src/test/run-pass/macro-attributes.rs @@ -10,6 +10,8 @@ // ignore-pretty - token trees can't pretty print +#![feature(custom_attribute)] + macro_rules! compiles_fine { (#[$at:meta]) => { // test that the different types of attributes work diff --git a/src/test/run-pass/macro-block-nonterminal.rs b/src/test/run-pass/macro-block-nonterminal.rs index 6c568d6d49..496534a536 100644 --- a/src/test/run-pass/macro-block-nonterminal.rs +++ b/src/test/run-pass/macro-block-nonterminal.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! do_block{ ($val:block) => {$val} } diff --git a/src/test/run-pass/macro-crate-def-only.rs b/src/test/run-pass/macro-crate-def-only.rs index efee9ba963..58b09fa492 100644 --- a/src/test/run-pass/macro-crate-def-only.rs +++ b/src/test/run-pass/macro-crate-def-only.rs @@ -10,6 +10,8 @@ // aux-build:macro_crate_def_only.rs +// pretty-expanded FIXME #23616 + #[macro_use] #[no_link] extern crate macro_crate_def_only; diff --git a/src/test/run-pass/macro-crate-nonterminal-renamed.rs b/src/test/run-pass/macro-crate-nonterminal-renamed.rs index cb919297b0..ed7b1cbaca 100644 --- a/src/test/run-pass/macro-crate-nonterminal-renamed.rs +++ b/src/test/run-pass/macro-crate-nonterminal-renamed.rs @@ -12,7 +12,7 @@ // ignore-stage1 #[macro_use] -extern crate "macro_crate_nonterminal" as new_name; +extern crate macro_crate_nonterminal as new_name; pub fn main() { new_name::check_local(); diff --git a/src/test/run-pass/macro-crate-use.rs b/src/test/run-pass/macro-crate-use.rs index fbbe0105cf..557f982713 100644 --- a/src/test/run-pass/macro-crate-use.rs +++ b/src/test/run-pass/macro-crate-use.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn increment(x: uint) -> uint { +// pretty-expanded FIXME #23616 + +pub fn increment(x: usize) -> usize { x + 1 } diff --git a/src/test/run-pass/macro-deep_expansion.rs b/src/test/run-pass/macro-deep_expansion.rs index c4012e2cf3..fd21ed0150 100644 --- a/src/test/run-pass/macro-deep_expansion.rs +++ b/src/test/run-pass/macro-deep_expansion.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! foo2 { () => { "foo" diff --git a/src/test/run-pass/macro-delimiter-significance.rs b/src/test/run-pass/macro-delimiter-significance.rs index 01362f0f83..6a3a495f2f 100644 --- a/src/test/run-pass/macro-delimiter-significance.rs +++ b/src/test/run-pass/macro-delimiter-significance.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { vec![1_usize, 2, 3].len(); } - diff --git a/src/test/run-pass/macro-interpolation.rs b/src/test/run-pass/macro-interpolation.rs index 069aeb9220..e6b5d50b36 100644 --- a/src/test/run-pass/macro-interpolation.rs +++ b/src/test/run-pass/macro-interpolation.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! overly_complicated { ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) => ({ @@ -23,7 +25,7 @@ macro_rules! overly_complicated { } pub fn main() { - assert!(overly_complicated!(f, x, Option, { return Some(x); }, - Some(8_usize), Some(y), y) == 8_usize) + assert!(overly_complicated!(f, x, Option, { return Some(x); }, + Some(8), Some(y), y) == 8) } diff --git a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs index ce74896749..9fafeb6531 100644 --- a/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs +++ b/src/test/run-pass/macro-invocation-in-count-expr-fixed-array-type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! four { () => (4) } diff --git a/src/test/run-pass/macro-meta-items.rs b/src/test/run-pass/macro-meta-items.rs index 47e3a07239..605cade2b3 100644 --- a/src/test/run-pass/macro-meta-items.rs +++ b/src/test/run-pass/macro-meta-items.rs @@ -38,4 +38,3 @@ pub fn main() { emit!(baz); println!("{}", MISTYPED); } - diff --git a/src/test/run-pass/macro-method-issue-4621.rs b/src/test/run-pass/macro-method-issue-4621.rs index fd16958d89..cb15404597 100644 --- a/src/test/run-pass/macro-method-issue-4621.rs +++ b/src/test/run-pass/macro-method-issue-4621.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct A; -macro_rules! make_thirteen_method {() => (fn thirteen(&self)->int {13})} +macro_rules! make_thirteen_method {() => (fn thirteen(&self)->isize {13})} impl A { make_thirteen_method!(); } fn main() { assert_eq!(A.thirteen(),13); } - - - diff --git a/src/test/run-pass/macro-nt-list.rs b/src/test/run-pass/macro-nt-list.rs index c6efc2f2bc..f3367ff2b4 100644 --- a/src/test/run-pass/macro-nt-list.rs +++ b/src/test/run-pass/macro-nt-list.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! list { ( ($($id:ident),*) ) => (()); ( [$($id:ident),*] ) => (()); diff --git a/src/test/run-pass/macro-of-higher-order.rs b/src/test/run-pass/macro-of-higher-order.rs index 1a77eee824..ebd58f7722 100644 --- a/src/test/run-pass/macro-of-higher-order.rs +++ b/src/test/run-pass/macro-of-higher-order.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! higher_order { (subst $lhs:tt => $rhs:tt) => ({ macro_rules! anon { $lhs => $rhs } diff --git a/src/test/run-pass/macro-pat.rs b/src/test/run-pass/macro-pat.rs index 6f2626a5af..659113d4e0 100644 --- a/src/test/run-pass/macro-pat.rs +++ b/src/test/run-pass/macro-pat.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! mypat { () => ( Some('y') @@ -38,7 +40,7 @@ macro_rules! ident_pat { ) } -fn f(c: Option) -> uint { +fn f(c: Option) -> usize { match c { Some('x') => 1, mypat!() => 2, @@ -47,9 +49,9 @@ fn f(c: Option) -> uint { } pub fn main() { - assert_eq!(1_usize, f(Some('x'))); - assert_eq!(2_usize, f(Some('y'))); - assert_eq!(3_usize, f(None)); + assert_eq!(1, f(Some('x'))); + assert_eq!(2, f(Some('y'))); + assert_eq!(3, f(None)); assert_eq!(1, match Some('x') { Some(char_x!()) => 1, diff --git a/src/test/run-pass/macro-path.rs b/src/test/run-pass/macro-path.rs index 4aa1587943..2e88062297 100644 --- a/src/test/run-pass/macro-path.rs +++ b/src/test/run-pass/macro-path.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod m { - pub type t = int; + pub type t = isize; } macro_rules! foo { diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index 3aa0298709..0d8b86012d 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -12,7 +12,7 @@ macro_rules! myfn { ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( - fn $f( $( $x : int),* ) -> int $body + fn $f( $( $x : isize),* ) -> isize $body ) } diff --git a/src/test/run-pass/macro-with-attrs1.rs b/src/test/run-pass/macro-with-attrs1.rs index f180922a05..0938c16c30 100644 --- a/src/test/run-pass/macro-with-attrs1.rs +++ b/src/test/run-pass/macro-with-attrs1.rs @@ -10,6 +10,8 @@ // compile-flags: --cfg foo +// pretty-expanded FIXME #23616 + #[cfg(foo)] macro_rules! foo { () => (1) } diff --git a/src/test/run-pass/macro-with-attrs2.rs b/src/test/run-pass/macro-with-attrs2.rs index d683979462..cf48c325f1 100644 --- a/src/test/run-pass/macro-with-attrs2.rs +++ b/src/test/run-pass/macro-with-attrs2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[cfg(foo)] macro_rules! foo { () => (1) } @@ -17,4 +19,3 @@ macro_rules! foo { () => (2) } pub fn main() { assert_eq!(foo!(), 2); } - diff --git a/src/test/run-pass/macro-with-braces-in-expr-position.rs b/src/test/run-pass/macro-with-braces-in-expr-position.rs index cb52ba74bb..4881a5ab64 100644 --- a/src/test/run-pass/macro-with-braces-in-expr-position.rs +++ b/src/test/run-pass/macro-with-braces-in-expr-position.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; macro_rules! expr { ($e: expr) => { $e } } macro_rules! spawn { ($($code: tt)*) => { - expr!(Thread::spawn(move|| {$($code)*})) + expr!(thread::spawn(move|| {$($code)*})) } } diff --git a/src/test/run-pass/macro_with_super_2.rs b/src/test/run-pass/macro_with_super_2.rs index 5c681b8e6e..9ecf186d5b 100644 --- a/src/test/run-pass/macro_with_super_2.rs +++ b/src/test/run-pass/macro_with_super_2.rs @@ -10,6 +10,8 @@ // aux-build:macro_with_super_1.rs +// pretty-expanded FIXME #23616 + #[macro_use] extern crate macro_with_super_1; diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs index dfefe84518..1b4dfb869d 100644 --- a/src/test/run-pass/match-arm-statics.rs +++ b/src/test/run-pass/match-arm-statics.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct NewBool(bool); enum Direction { @@ -36,8 +38,8 @@ const VARIANT2_NORTH: EnumWithStructVariants = EnumWithStructVariants::Variant2 dir: Direction::North }; pub mod glfw { - #[derive(Copy)] - pub struct InputState(uint); + #[derive(Copy, Clone)] + pub struct InputState(usize); pub const RELEASE : InputState = InputState(0); pub const PRESS : InputState = InputState(1); @@ -99,7 +101,7 @@ fn issue_13731() { fn issue_15393() { #![allow(dead_code)] struct Flags { - bits: uint + bits: usize } const FOO: Flags = Flags { bits: 0x01 }; diff --git a/src/test/run-pass/match-borrowed_str.rs b/src/test/run-pass/match-borrowed_str.rs index b359614fa9..574c4b9f00 100644 --- a/src/test/run-pass/match-borrowed_str.rs +++ b/src/test/run-pass/match-borrowed_str.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unnecessary_allocation)] fn f1(ref_string: &str) -> String { diff --git a/src/test/run-pass/match-bot-2.rs b/src/test/run-pass/match-bot-2.rs index 949fad1134..4fa951b347 100644 --- a/src/test/run-pass/match-bot-2.rs +++ b/src/test/run-pass/match-bot-2.rs @@ -9,5 +9,7 @@ // except according to those terms. // n.b. This was only ever failing with optimization disabled. -fn a() -> int { match return 1 { 2 => 3, _ => panic!() } } +// pretty-expanded FIXME #23616 + +fn a() -> isize { match return 1 { 2 => 3, _ => panic!() } } pub fn main() { a(); } diff --git a/src/test/run-pass/match-bot.rs b/src/test/run-pass/match-bot.rs index 74cf3faea4..7745410fa4 100644 --- a/src/test/run-pass/match-bot.rs +++ b/src/test/run-pass/match-bot.rs @@ -10,7 +10,7 @@ pub fn main() { - let i: int = - match Some::(3) { None:: => { panic!() } Some::(_) => { 5 } }; + let i: isize = + match Some::(3) { None:: => { panic!() } Some::(_) => { 5 } }; println!("{}", i); } diff --git a/src/test/run-pass/match-enum-struct-0.rs b/src/test/run-pass/match-enum-struct-0.rs index 5cc512abfe..06d19cec18 100644 --- a/src/test/run-pass/match-enum-struct-0.rs +++ b/src/test/run-pass/match-enum-struct-0.rs @@ -10,8 +10,10 @@ // regression test for issue #5625 +// pretty-expanded FIXME #23616 + enum E { - Foo{f : int}, + Foo{f : isize}, Bar } diff --git a/src/test/run-pass/match-enum-struct-1.rs b/src/test/run-pass/match-enum-struct-1.rs index fdfadf8eb4..e4766f32a5 100644 --- a/src/test/run-pass/match-enum-struct-1.rs +++ b/src/test/run-pass/match-enum-struct-1.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum E { - Foo{f : int}, + Foo{f : isize}, Bar } diff --git a/src/test/run-pass/match-implicit-copy-unique.rs b/src/test/run-pass/match-implicit-copy-unique.rs index 6883187c40..d481c02eb4 100644 --- a/src/test/run-pass/match-implicit-copy-unique.rs +++ b/src/test/run-pass/match-implicit-copy-unique.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct Pair { a: Box, b: Box } +struct Pair { a: Box, b: Box } pub fn main() { - let mut x = box Pair {a: box 10, b: box 20}; + let mut x: Box<_> = box Pair {a: box 10, b: box 20}; let x_internal = &mut *x; match *x_internal { Pair {a: ref mut a, b: ref mut _b} => { diff --git a/src/test/run-pass/match-in-macro.rs b/src/test/run-pass/match-in-macro.rs index e4886ddaa0..27bbbc936a 100644 --- a/src/test/run-pass/match-in-macro.rs +++ b/src/test/run-pass/match-in-macro.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { - B { b1: int, bb1: int}, + B { b1: isize, bb1: isize}, } macro_rules! match_inside_expansion { diff --git a/src/test/run-pass/match-join.rs b/src/test/run-pass/match-join.rs index a903988529..b47732b325 100644 --- a/src/test/run-pass/match-join.rs +++ b/src/test/run-pass/match-join.rs @@ -9,8 +9,8 @@ // except according to those terms. fn foo(y: Option) { - let mut x: int; - let mut rs: Vec = Vec::new(); + let mut x: isize; + let mut rs: Vec = Vec::new(); /* tests that x doesn't get put in the precondition for the entire if expression */ @@ -25,4 +25,4 @@ fn foo(y: Option) { return; } -pub fn main() { println!("hello"); foo::(Some::(5)); } +pub fn main() { println!("hello"); foo::(Some::(5)); } diff --git a/src/test/run-pass/match-naked-record-expr.rs b/src/test/run-pass/match-naked-record-expr.rs index 433cf23626..e558e88e03 100644 --- a/src/test/run-pass/match-naked-record-expr.rs +++ b/src/test/run-pass/match-naked-record-expr.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct X { x: int } +// pretty-expanded FIXME #23616 + +struct X { x: isize } pub fn main() { let _x = match 0 { diff --git a/src/test/run-pass/match-naked-record.rs b/src/test/run-pass/match-naked-record.rs index fe12b7c158..a2b35e6558 100644 --- a/src/test/run-pass/match-naked-record.rs +++ b/src/test/run-pass/match-naked-record.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct X { x: int } +// pretty-expanded FIXME #23616 + +struct X { x: isize } pub fn main() { let _x = match 0 { diff --git a/src/test/run-pass/match-path.rs b/src/test/run-pass/match-path.rs index b3c7f3db51..1b3594a0a7 100644 --- a/src/test/run-pass/match-path.rs +++ b/src/test/run-pass/match-path.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + mod m1 { pub enum foo { foo1, foo2, } } diff --git a/src/test/run-pass/match-pattern-bindings.rs b/src/test/run-pass/match-pattern-bindings.rs index abb78fc831..d230f18f2b 100644 --- a/src/test/run-pass/match-pattern-bindings.rs +++ b/src/test/run-pass/match-pattern-bindings.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let value = Some(1); assert_eq!(match value { diff --git a/src/test/run-pass/match-pattern-lit.rs b/src/test/run-pass/match-pattern-lit.rs index 4265d0a540..33c77f33c4 100644 --- a/src/test/run-pass/match-pattern-lit.rs +++ b/src/test/run-pass/match-pattern-lit.rs @@ -10,7 +10,7 @@ -fn altlit(f: int) -> int { +fn altlit(f: isize) -> isize { match f { 10 => { println!("case 10"); return 20; } 11 => { println!("case 11"); return 22; } diff --git a/src/test/run-pass/match-pattern-no-type-params.rs b/src/test/run-pass/match-pattern-no-type-params.rs index d76c8faa5b..ccf23b87ea 100644 --- a/src/test/run-pass/match-pattern-no-type-params.rs +++ b/src/test/run-pass/match-pattern-no-type-params.rs @@ -10,7 +10,7 @@ enum maybe { nothing, just(T), } -fn foo(x: maybe) { +fn foo(x: maybe) { match x { maybe::nothing => { println!("A"); } maybe::just(_a) => { println!("B"); } diff --git a/src/test/run-pass/match-pattern-simple.rs b/src/test/run-pass/match-pattern-simple.rs index 92a7539022..8e729e2eab 100644 --- a/src/test/run-pass/match-pattern-simple.rs +++ b/src/test/run-pass/match-pattern-simple.rs @@ -10,6 +10,8 @@ -fn altsimple(f: int) { match f { _x => () } } +// pretty-expanded FIXME #23616 + +fn altsimple(f: isize) { match f { _x => () } } pub fn main() { } diff --git a/src/test/run-pass/match-phi.rs b/src/test/run-pass/match-phi.rs index 2a0a2b2088..ac070cb1f2 100644 --- a/src/test/run-pass/match-phi.rs +++ b/src/test/run-pass/match-phi.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] enum thing { a, b, c, } -fn foo(it: F) where F: FnOnce(int) { it(10); } +fn foo(it: F) where F: FnOnce(isize) { it(10); } pub fn main() { let mut x = true; diff --git a/src/test/run-pass/match-pipe-binding.rs b/src/test/run-pass/match-pipe-binding.rs index bdf12d22ed..70d3639a78 100644 --- a/src/test/run-pass/match-pipe-binding.rs +++ b/src/test/run-pass/match-pipe-binding.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn test1() { // from issue 6338 match ((1, "a".to_string()), (2, "b".to_string())) { diff --git a/src/test/run-pass/match-range-static.rs b/src/test/run-pass/match-range-static.rs index 0feeea7022..9aafcda1b0 100644 --- a/src/test/run-pass/match-range-static.rs +++ b/src/test/run-pass/match-range-static.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const s: int = 1; -const e: int = 42; +// pretty-expanded FIXME #23616 + +const s: isize = 1; +const e: isize = 42; pub fn main() { match 7 { diff --git a/src/test/run-pass/match-reassign.rs b/src/test/run-pass/match-reassign.rs new file mode 100644 index 0000000000..759296ad46 --- /dev/null +++ b/src/test/run-pass/match-reassign.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #23698: The reassignment checker only cared +// about the last assigment in a match arm body + +// Use an extra function to make sure no extra assignments +// are introduced by macros in the match statement +fn check_eq(x: i32, y: i32) { + assert_eq!(x, y); +} + +#[allow(unused_assignments)] +fn main() { + let mut x = Box::new(1); + match x { + y => { + x = Box::new(2); + let _tmp = 1; // This assignment used to throw off the reassignment checker + check_eq(*y, 1); + } + } +} diff --git a/src/test/run-pass/match-ref-binding-in-guard-3256.rs b/src/test/run-pass/match-ref-binding-in-guard-3256.rs index a83bc73457..1e2ebf42a9 100644 --- a/src/test/run-pass/match-ref-binding-in-guard-3256.rs +++ b/src/test/run-pass/match-ref-binding-in-guard-3256.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::Mutex; pub fn main() { diff --git a/src/test/run-pass/match-ref-binding-mut-option.rs b/src/test/run-pass/match-ref-binding-mut-option.rs index 8d1e483bcd..41f00e58ff 100644 --- a/src/test/run-pass/match-ref-binding-mut-option.rs +++ b/src/test/run-pass/match-ref-binding-mut-option.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut v = Some(22); match v { diff --git a/src/test/run-pass/match-ref-binding-mut.rs b/src/test/run-pass/match-ref-binding-mut.rs index 266f7cdde1..26c91e1703 100644 --- a/src/test/run-pass/match-ref-binding-mut.rs +++ b/src/test/run-pass/match-ref-binding-mut.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Rec { - f: int + f: isize } fn destructure(x: &mut Rec) { diff --git a/src/test/run-pass/match-ref-binding.rs b/src/test/run-pass/match-ref-binding.rs index 0b613df18e..826edb30b3 100644 --- a/src/test/run-pass/match-ref-binding.rs +++ b/src/test/run-pass/match-ref-binding.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn destructure(x: Option) -> int { +// pretty-expanded FIXME #23616 + +fn destructure(x: Option) -> isize { match x { None => 0, Some(ref v) => *v diff --git a/src/test/run-pass/lint-cstack.rs b/src/test/run-pass/match-ref-unsized.rs similarity index 64% rename from src/test/run-pass/lint-cstack.rs rename to src/test/run-pass/match-ref-unsized.rs index f180ffcd4e..4de028299d 100644 --- a/src/test/run-pass/lint-cstack.rs +++ b/src/test/run-pass/match-ref-unsized.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,19 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate libc; +// Binding unsized expressions to ref patterns -extern { - fn rust_get_test_int() -> libc::intptr_t; -} +pub fn main() { + let ref a = *"abcdef"; + assert_eq!(a, "abcdef"); -trait A { - fn foo(&self) { - unsafe { - rust_get_test_int(); - } + match *"12345" { + ref b => { assert_eq!(b, "12345") } } } - -pub fn main() { -} diff --git a/src/test/run-pass/match-static-const-rename.rs b/src/test/run-pass/match-static-const-rename.rs index 164cc99e18..21b806f80d 100644 --- a/src/test/run-pass/match-static-const-rename.rs +++ b/src/test/run-pass/match-static-const-rename.rs @@ -16,9 +16,11 @@ // around this problem locally by renaming the constant in the `use` // form to an uppercase identifier that placates the lint. +// pretty-expanded FIXME #23616 + #![deny(non_upper_case_globals)] -pub const A : int = 97; +pub const A : isize = 97; fn f() { let r = match (0,0) { @@ -35,7 +37,7 @@ fn f() { mod m { #[allow(non_upper_case_globals)] - pub const aha : int = 7; + pub const aha : isize = 7; } fn g() { diff --git a/src/test/run-pass/match-str.rs b/src/test/run-pass/match-str.rs index 301d99a7e2..5d8958c6b9 100644 --- a/src/test/run-pass/match-str.rs +++ b/src/test/run-pass/match-str.rs @@ -10,6 +10,8 @@ // Issue #53 +// pretty-expanded FIXME #23616 + pub fn main() { match "test" { "not-test" => panic!(), "test" => (), _ => panic!() } diff --git a/src/test/run-pass/match-struct-0.rs b/src/test/run-pass/match-struct-0.rs index 6d5658aa13..450b310b8f 100644 --- a/src/test/run-pass/match-struct-0.rs +++ b/src/test/run-pass/match-struct-0.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo{ - f : int, + f : isize, } pub fn main() { diff --git a/src/test/run-pass/match-tag.rs b/src/test/run-pass/match-tag.rs index cf940a6305..82d29f9050 100644 --- a/src/test/run-pass/match-tag.rs +++ b/src/test/run-pass/match-tag.rs @@ -11,14 +11,16 @@ +// pretty-expanded FIXME #23616 + enum color { - rgb(int, int, int), - rgba(int, int, int, int), - hsl(int, int, int), + rgb(isize, isize, isize), + rgba(isize, isize, isize, isize), + hsl(isize, isize, isize), } -fn process(c: color) -> int { - let mut x: int; +fn process(c: color) -> isize { + let mut x: isize; match c { color::rgb(r, _, _) => { x = r; } color::rgba(_, _, _, a) => { x = a; } diff --git a/src/test/run-pass/match-value-binding-in-guard-3291.rs b/src/test/run-pass/match-value-binding-in-guard-3291.rs index beb125492b..d4f4f3bb27 100644 --- a/src/test/run-pass/match-value-binding-in-guard-3291.rs +++ b/src/test/run-pass/match-value-binding-in-guard-3291.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn foo(x: Option>, b: bool) -> int { +fn foo(x: Option>, b: bool) -> isize { match x { None => { 1 } Some(ref x) if b => { *x.clone() } diff --git a/src/test/run-pass/match-vec-alternatives.rs b/src/test/run-pass/match-vec-alternatives.rs index eb6b2176e5..f9b49281ba 100644 --- a/src/test/run-pass/match-vec-alternatives.rs +++ b/src/test/run-pass/match-vec-alternatives.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { match (l1, l2) { @@ -57,22 +60,22 @@ fn match_nested_vecs_snoc<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) - fn main() { assert_eq!(match_vecs(&[1, 2], &[2, 3]), "both non-empty"); assert_eq!(match_vecs(&[], &[1, 2, 3, 4]), "one empty"); - assert_eq!(match_vecs::(&[], &[]), "both empty"); + assert_eq!(match_vecs::(&[], &[]), "both empty"); assert_eq!(match_vecs(&[1, 2, 3], &[]), "one empty"); assert_eq!(match_vecs_cons(&[1, 2], &[2, 3]), "both non-empty"); assert_eq!(match_vecs_cons(&[], &[1, 2, 3, 4]), "one empty"); - assert_eq!(match_vecs_cons::(&[], &[]), "both empty"); + assert_eq!(match_vecs_cons::(&[], &[]), "both empty"); assert_eq!(match_vecs_cons(&[1, 2, 3], &[]), "one empty"); assert_eq!(match_vecs_snoc(&[1, 2], &[2, 3]), "both non-empty"); assert_eq!(match_vecs_snoc(&[], &[1, 2, 3, 4]), "one empty"); - assert_eq!(match_vecs_snoc::(&[], &[]), "both empty"); + assert_eq!(match_vecs_snoc::(&[], &[]), "both empty"); assert_eq!(match_vecs_snoc(&[1, 2, 3], &[]), "one empty"); assert_eq!(match_nested_vecs_cons(None, Ok::<&[_], ()>(&[4_usize, 2_usize])), "None, Ok(at least two elements)"); - assert_eq!(match_nested_vecs_cons::(None, Err(())), "None, Ok(less than one element)"); + assert_eq!(match_nested_vecs_cons::(None, Err(())), "None, Ok(less than one element)"); assert_eq!(match_nested_vecs_cons::(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), "Some(empty), Ok(empty)"); assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[1]), Err(())), "Some(non-empty), any"); @@ -81,7 +84,7 @@ fn main() { assert_eq!(match_nested_vecs_snoc(None, Ok::<&[_], ()>(&[4_usize, 2_usize])), "None, Ok(at least two elements)"); - assert_eq!(match_nested_vecs_snoc::(None, Err(())), "None, Ok(less than one element)"); + assert_eq!(match_nested_vecs_snoc::(None, Err(())), "None, Ok(less than one element)"); assert_eq!(match_nested_vecs_snoc::(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), "Some(empty), Ok(empty)"); assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[1]), Err(())), "Some(non-empty), any"); diff --git a/src/test/run-pass/match-vec-rvalue.rs b/src/test/run-pass/match-vec-rvalue.rs index 04a0204d20..e368aeb976 100644 --- a/src/test/run-pass/match-vec-rvalue.rs +++ b/src/test/run-pass/match-vec-rvalue.rs @@ -11,6 +11,8 @@ // Tests that matching rvalues with drops does not crash. +// pretty-expanded FIXME #23616 + pub fn main() { match vec!(1, 2, 3) { x => { diff --git a/src/test/run-pass/match-with-ret-arm.rs b/src/test/run-pass/match-with-ret-arm.rs index 05c6aac90e..79b197f08e 100644 --- a/src/test/run-pass/match-with-ret-arm.rs +++ b/src/test/run-pass/match-with-ret-arm.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::uint; - pub fn main() { // sometimes we have had trouble finding // the right type for f, as we unified // bot and u32 here - let f = match "1234".parse::().ok() { + let f = match "1234".parse::().ok() { None => return (), Some(num) => num as u32 }; - assert_eq!(f, 1234u32); + assert_eq!(f, 1234); println!("{}", f) } diff --git a/src/test/run-pass/max-min-classes.rs b/src/test/run-pass/max-min-classes.rs index e3c375f8b0..f0844b8e1e 100644 --- a/src/test/run-pass/max-min-classes.rs +++ b/src/test/run-pass/max-min-classes.rs @@ -9,27 +9,27 @@ // except according to those terms. trait Product { - fn product(&self) -> int; + fn product(&self) -> isize; } struct Foo { - x: int, - y: int, + x: isize, + y: isize, } impl Foo { - pub fn sum(&self) -> int { + pub fn sum(&self) -> isize { self.x + self.y } } impl Product for Foo { - fn product(&self) -> int { + fn product(&self) -> isize { self.x * self.y } } -fn Foo(x: int, y: int) -> Foo { +fn Foo(x: isize, y: isize) -> Foo { Foo { x: x, y: y } } diff --git a/src/test/run-pass/method-attributes.rs b/src/test/run-pass/method-attributes.rs index 92af96e0d8..400ecda411 100644 --- a/src/test/run-pass/method-attributes.rs +++ b/src/test/run-pass/method-attributes.rs @@ -9,6 +9,8 @@ // except according to those terms. // pp-exact - Make sure we print all the attributes +// pretty-expanded FIXME #23616 + #![allow(unused_attribute)] #![feature(custom_attribute)] @@ -21,7 +23,7 @@ trait frobable { } #[int_frobable] -impl frobable for int { +impl frobable for isize { #[frob_attr1] fn frob(&self) { #![frob_attr2] diff --git a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs index cec9753a2f..3babb543bf 100644 --- a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs +++ b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs @@ -11,6 +11,8 @@ // Check that we successfully handle methods where the `self` type has // an early-bound lifetime. Issue #18208. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] use std::marker; diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index 0ad600dd85..7cc762c934 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -12,7 +12,10 @@ // type is `&mut [u8]`, passes in a pointer to the lvalue and not a // temporary. Issue #19147. -use std::raw; +// pretty-expanded FIXME #23616 + +#![feature(core, old_io)] + use std::mem; use std::slice; use std::old_io::IoResult; @@ -23,14 +26,14 @@ trait MyWriter { impl<'a> MyWriter for &'a mut [u8] { fn my_write(&mut self, buf: &[u8]) -> IoResult<()> { - slice::bytes::copy_memory(*self, buf); + slice::bytes::copy_memory(buf, *self); let write_len = buf.len(); unsafe { - *self = mem::transmute(raw::Slice { - data: self.as_ptr().offset(write_len as int), - len: self.len() - write_len, - }); + *self = slice::from_raw_parts_mut( + self.as_mut_ptr().offset(write_len as isize), + self.len() - write_len + ); } Ok(()) @@ -38,7 +41,7 @@ impl<'a> MyWriter for &'a mut [u8] { } fn main() { - let mut buf = [0_u8; 6]; + let mut buf = [0; 6]; { let mut writer: &mut [_] = &mut buf; diff --git a/src/test/run-pass/method-normalize-bounds-issue-20604.rs b/src/test/run-pass/method-normalize-bounds-issue-20604.rs index 73489948da..3a1ce74a64 100644 --- a/src/test/run-pass/method-normalize-bounds-issue-20604.rs +++ b/src/test/run-pass/method-normalize-bounds-issue-20604.rs @@ -14,6 +14,8 @@ // winnowing stage of method resolution failed to handle an associated // type projection. +// pretty-expanded FIXME #23616 + #![feature(associated_types)] trait Hasher { @@ -36,7 +38,7 @@ impl Hasher for SipHasher { fn finish(&self) -> u64 { 4 } } -impl Hash for int { +impl Hash for isize { fn hash(&self, h: &mut SipHasher) {} } @@ -62,4 +64,3 @@ fn foo>(map: &Map) { } fn main() {} - diff --git a/src/test/run-pass/method-projection.rs b/src/test/run-pass/method-projection.rs index 6f72a16398..3db7268207 100644 --- a/src/test/run-pass/method-projection.rs +++ b/src/test/run-pass/method-projection.rs @@ -13,17 +13,19 @@ /////////////////////////////////////////////////////////////////////////// +// pretty-expanded FIXME #23616 + trait MakeString { fn make_string(&self) -> String; } -impl MakeString for int { +impl MakeString for isize { fn make_string(&self) -> String { format!("{}", *self) } } -impl MakeString for uint { +impl MakeString for usize { fn make_string(&self) -> String { format!("{}", *self) } @@ -44,13 +46,13 @@ fn foo(f: &F) -> String { /////////////////////////////////////////////////////////////////////////// struct SomeStruct { - field: int, + field: isize, } impl Foo for SomeStruct { - type F = int; + type F = isize; - fn get(&self) -> &int { + fn get(&self) -> &isize { &self.field } } @@ -58,13 +60,13 @@ impl Foo for SomeStruct { /////////////////////////////////////////////////////////////////////////// struct SomeOtherStruct { - field: uint, + field: usize, } impl Foo for SomeOtherStruct { - type F = uint; + type F = usize; - fn get(&self) -> &uint { + fn get(&self) -> &usize { &self.field } } diff --git a/src/test/run-pass/method-recursive-blanket-impl.rs b/src/test/run-pass/method-recursive-blanket-impl.rs index 15eb2ae2e4..6877bf376a 100644 --- a/src/test/run-pass/method-recursive-blanket-impl.rs +++ b/src/test/run-pass/method-recursive-blanket-impl.rs @@ -13,6 +13,8 @@ // know not to stop at the blanket, we have to recursively evaluate // the `T:Foo` bound. +// pretty-expanded FIXME #23616 + use std::marker::Sized; // Note: this must be generic for the problem to show up diff --git a/src/test/run-pass/method-self-arg-aux1.rs b/src/test/run-pass/method-self-arg-aux1.rs index e9a1e19d4b..768e7f9486 100644 --- a/src/test/run-pass/method-self-arg-aux1.rs +++ b/src/test/run-pass/method-self-arg-aux1.rs @@ -10,6 +10,8 @@ // Test method calls with self as an argument (cross-crate) +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -26,5 +28,5 @@ fn main() { x.foo(&x); - assert!(method_self_arg1::get_count() == 2u64*3*3*3*5*5*5*7*7*7); + assert!(method_self_arg1::get_count() == 2*3*3*3*5*5*5*7*7*7); } diff --git a/src/test/run-pass/method-self-arg-aux2.rs b/src/test/run-pass/method-self-arg-aux2.rs index 7fa810ce15..b40333c67c 100644 --- a/src/test/run-pass/method-self-arg-aux2.rs +++ b/src/test/run-pass/method-self-arg-aux2.rs @@ -10,6 +10,8 @@ // Test method calls with self as an argument (cross-crate) +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -30,5 +32,5 @@ fn main() { x.run_trait(); - assert!(method_self_arg2::get_count() == 2u64*2*3*3*5*5*7*7*11*11*13*13*17); + assert!(method_self_arg2::get_count() == 2*2*3*3*5*5*7*7*11*11*13*13*17); } diff --git a/src/test/run-pass/method-self-arg-trait.rs b/src/test/run-pass/method-self-arg-trait.rs index c79141d979..f0ca0a70ac 100644 --- a/src/test/run-pass/method-self-arg-trait.rs +++ b/src/test/run-pass/method-self-arg-trait.rs @@ -10,12 +10,14 @@ // Test method calls with self as an argument +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] static mut COUNT: u64 = 1; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Foo; trait Bar : Sized { @@ -75,5 +77,5 @@ fn main() { x.baz(); - unsafe { assert!(COUNT == 2u64*2*3*3*5*5*7*7*11*11*13*13*17); } + unsafe { assert!(COUNT == 2*2*3*3*5*5*7*7*11*11*13*13*17); } } diff --git a/src/test/run-pass/method-self-arg.rs b/src/test/run-pass/method-self-arg.rs index de24297c7b..dfc1211922 100644 --- a/src/test/run-pass/method-self-arg.rs +++ b/src/test/run-pass/method-self-arg.rs @@ -10,12 +10,14 @@ // Test method calls with self as an argument +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -static mut COUNT: uint = 1; +static mut COUNT: usize = 1; -#[derive(Copy)] +#[derive(Copy, Clone)] struct Foo; impl Foo { @@ -54,5 +56,5 @@ fn main() { x.foo(&x); - unsafe { assert!(COUNT == 2_usize*3*3*3*5*5*5*7*7*7); } + unsafe { assert!(COUNT == 2*3*3*3*5*5*5*7*7*7); } } diff --git a/src/test/run-pass/method-two-trait-defer-resolution-1.rs b/src/test/run-pass/method-two-trait-defer-resolution-1.rs index 414b08b433..d0e0427f37 100644 --- a/src/test/run-pass/method-two-trait-defer-resolution-1.rs +++ b/src/test/run-pass/method-two-trait-defer-resolution-1.rs @@ -11,6 +11,8 @@ // Test that we pick which version of `foo` to run based on the // type that is (ultimately) inferred for `x`. +// pretty-expanded FIXME #23616 + trait foo { fn foo(&self) -> i32; } diff --git a/src/test/run-pass/method-two-trait-defer-resolution-2.rs b/src/test/run-pass/method-two-trait-defer-resolution-2.rs index 7463783be5..2ceff22adb 100644 --- a/src/test/run-pass/method-two-trait-defer-resolution-2.rs +++ b/src/test/run-pass/method-two-trait-defer-resolution-2.rs @@ -8,40 +8,49 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we pick which version of `Foo` to run based on whether -// the type we (ultimately) inferred for `x` is copyable or not. -// -// In this case, the two versions are both impls of same trait, and -// hence we we can resolve method even without knowing yet which -// version will run (note that the `push` occurs after the call to -// `foo()`). +// Test that when we write `x.foo()`, we do nothave to know the +// complete type of `x` in order to type-check the method call. In +// this case, we know that `x: Vec<_1>`, but we don't know what type +// `_1` is (because the call to `push` comes later). To pick between +// the impls, we would have to know `_1`, since we have to know +// whether `_1: MyCopy` or `_1 == Box`. However (and this is the +// point of the test), we don't have to pick between the two impls -- +// it is enough to know that `foo` comes from the `Foo` trait. We can +// translate the call as `Foo::foo(&x)` and let the specific impl get +// chosen later. + +// pretty-expanded FIXME #23616 #![allow(unknown_features)] #![feature(box_syntax)] trait Foo { - fn foo(&self) -> int; + fn foo(&self) -> isize; } -impl Foo for Vec { - fn foo(&self) -> int {1} +trait MyCopy { fn foo(&self) { } } +impl MyCopy for i32 { } + +impl Foo for Vec { + fn foo(&self) -> isize {1} } -impl Foo for Vec> { - fn foo(&self) -> int {2} +impl Foo for Vec> { + fn foo(&self) -> isize {2} } -fn call_foo_copy() -> int { +fn call_foo_copy() -> isize { let mut x = Vec::new(); let y = x.foo(); - x.push(0_usize); + x.push(0_i32); y } -fn call_foo_other() -> int { - let mut x = Vec::new(); +fn call_foo_other() -> isize { + let mut x: Vec<_> = Vec::new(); let y = x.foo(); - x.push(box 0); + let z: Box = box 0; + x.push(z); y } diff --git a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs index fbecb6851b..77072bdec9 100644 --- a/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs +++ b/src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs @@ -11,6 +11,10 @@ // Test that we select between traits A and B. To do that, we must // consider the `Sized` bound. +// pretty-expanded FIXME #23616 + +#![feature(core)] + trait A { fn foo(self); } @@ -28,7 +32,7 @@ impl B for *const [T] { } fn main() { - let x: [int; 4] = [1,2,3,4]; - let xptr = x.as_slice() as *const _; + let x: [isize; 4] = [1,2,3,4]; + let xptr = &x[..] as *const [isize]; xptr.foo(); } diff --git a/src/test/run-pass/method-where-clause.rs b/src/test/run-pass/method-where-clause.rs index 6337538a33..f2ff0abfad 100644 --- a/src/test/run-pass/method-where-clause.rs +++ b/src/test/run-pass/method-where-clause.rs @@ -11,6 +11,8 @@ // Test that we can use method notation to call methods based on a // where clause type, and not only type parameters. +// pretty-expanded FIXME #23616 + trait Foo { fn foo(&self) -> i32; } diff --git a/src/test/run-pass/mid-path-type-params.rs b/src/test/run-pass/mid-path-type-params.rs index 4a04a71f9a..3055f90ee2 100644 --- a/src/test/run-pass/mid-path-type-params.rs +++ b/src/test/run-pass/mid-path-type-params.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct S { contents: T, } @@ -25,11 +27,11 @@ trait Trait { } struct S2 { - contents: int, + contents: isize, } -impl Trait for S2 { - fn new(x: int, _: U) -> S2 { +impl Trait for S2 { + fn new(x: isize, _: U) -> S2 { S2 { contents: x, } @@ -37,7 +39,6 @@ impl Trait for S2 { } pub fn main() { - let _ = S::::new::(1, 1.0); - let _: S2 = Trait::::new::(1, 1.0); + let _ = S::::new::(1, 1.0); + let _: S2 = Trait::::new::(1, 1.0); } - diff --git a/src/test/run-pass/minmax-stability-issue-23687.rs b/src/test/run-pass/minmax-stability-issue-23687.rs new file mode 100644 index 0000000000..86dd1a0453 --- /dev/null +++ b/src/test/run-pass/minmax-stability-issue-23687.rs @@ -0,0 +1,83 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(core)] +use std::fmt::Debug; +use std::cmp::{self, PartialOrd, Ordering}; +use std::iter::MinMaxResult::MinMax; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct Foo { + n: u8, + name: &'static str +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Foo) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Foo { + fn cmp(&self, other: &Foo) -> Ordering { + self.n.cmp(&other.n) + } +} + +fn main() { + let a = Foo { n: 4, name: "a" }; + let b = Foo { n: 4, name: "b" }; + let c = Foo { n: 8, name: "c" }; + let d = Foo { n: 8, name: "d" }; + let e = Foo { n: 22, name: "e" }; + let f = Foo { n: 22, name: "f" }; + + let data = [a, b, c, d, e, f]; + + // `min` should return the left when the values are equal + assert_eq!(data.iter().min(), Some(&a)); + assert_eq!(data.iter().min_by(|a| a.n), Some(&a)); + assert_eq!(cmp::min(a, b), a); + assert_eq!(cmp::min(b, a), b); + assert_eq!(cmp::partial_min(a, b), Some(a)); + assert_eq!(cmp::partial_min(b, a), Some(b)); + + // `max` should return the right when the values are equal + assert_eq!(data.iter().max(), Some(&f)); + assert_eq!(data.iter().max_by(|a| a.n), Some(&f)); + assert_eq!(cmp::max(e, f), f); + assert_eq!(cmp::max(f, e), e); + assert_eq!(cmp::partial_max(e, f), Some(f)); + assert_eq!(cmp::partial_max(f, e), Some(e)); + + // Similar for `min_max` + assert_eq!(data.iter().min_max(), MinMax(&a, &f)); + assert_eq!(data[1..5].iter().min_max(), MinMax(&b, &e)); + assert_eq!(data[2..4].iter().min_max(), MinMax(&c, &d)); + + let mut presorted = data.to_vec(); + presorted.sort(); + assert_stable(&presorted); + + let mut presorted = data.to_vec(); + presorted.sort_by(|a, b| a.cmp(b)); + assert_stable(&presorted); + + // Assert that sorted and min/max are the same + fn assert_stable(presorted: &[T]) { + for slice in presorted.windows(2) { + let a = &slice[0]; + let b = &slice[1]; + + assert_eq!(a, cmp::min(a, b)); + assert_eq!(b, cmp::max(a, b)); + } + } +} diff --git a/src/test/run-pass/mod-inside-fn.rs b/src/test/run-pass/mod-inside-fn.rs index 388d2e4905..836f2960d7 100644 --- a/src/test/run-pass/mod-inside-fn.rs +++ b/src/test/run-pass/mod-inside-fn.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f() -> int { +// pretty-expanded FIXME #23616 + +fn f() -> isize { mod m { - pub fn g() -> int { 720 } + pub fn g() -> isize { 720 } } m::g() diff --git a/src/test/run-pass/mod-view-items.rs b/src/test/run-pass/mod-view-items.rs index f03ec7b6f3..ba23197b83 100644 --- a/src/test/run-pass/mod-view-items.rs +++ b/src/test/run-pass/mod-view-items.rs @@ -1,4 +1,3 @@ - // 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. @@ -15,8 +14,10 @@ // pretty-print such view items. If that happens again, this should // begin failing. +// pretty-expanded FIXME #23616 + mod m { - pub fn f() -> Vec { Vec::new() } + pub fn f() -> Vec { Vec::new() } } pub fn main() { let _x = m::f(); } diff --git a/src/test/run-pass/mod_dir_implicit_aux/mod.rs b/src/test/run-pass/mod_dir_implicit_aux/mod.rs index a3c1628725..58c1beee3b 100644 --- a/src/test/run-pass/mod_dir_implicit_aux/mod.rs +++ b/src/test/run-pass/mod_dir_implicit_aux/mod.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo() -> int { 10 } +pub fn foo() -> isize { 10 } diff --git a/src/test/run-pass/mod_dir_simple/test.rs b/src/test/run-pass/mod_dir_simple/test.rs index a3c1628725..58c1beee3b 100644 --- a/src/test/run-pass/mod_dir_simple/test.rs +++ b/src/test/run-pass/mod_dir_simple/test.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo() -> int { 10 } +pub fn foo() -> isize { 10 } diff --git a/src/test/run-pass/mod_file_aux.rs b/src/test/run-pass/mod_file_aux.rs index 4d18decdc1..b7470811f6 100644 --- a/src/test/run-pass/mod_file_aux.rs +++ b/src/test/run-pass/mod_file_aux.rs @@ -10,4 +10,4 @@ // ignore-test Not a test. Used by other tests -pub fn foo() -> int { 10 } +pub fn foo() -> isize { 10 } diff --git a/src/test/run-pass/module-qualified-struct-destructure.rs b/src/test/run-pass/module-qualified-struct-destructure.rs index b1c1b64ba4..d6844f0f4a 100644 --- a/src/test/run-pass/module-qualified-struct-destructure.rs +++ b/src/test/run-pass/module-qualified-struct-destructure.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod m { pub struct S { - pub x: int, - pub y: int + pub x: isize, + pub y: isize } } diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs index 457c0a35fd..9ccb8f2e6f 100644 --- a/src/test/run-pass/monad.rs +++ b/src/test/run-pass/monad.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + trait vec_monad { fn bind(&self, f: F ) -> Vec where F: FnMut(&A) -> Vec ; } @@ -37,18 +39,18 @@ impl option_monad for Option { } } -fn transform(x: Option) -> Option { +fn transform(x: Option) -> Option { x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_string()) ) } pub fn main() { assert_eq!(transform(Some(10)), Some("11".to_string())); assert_eq!(transform(None), None); - assert!((vec!("hi".to_string())) + assert_eq!((vec!("hi".to_string())) .bind(|x| vec!(x.clone(), format!("{}!", x)) ) - .bind(|x| vec!(x.clone(), format!("{}?", x)) ) == - vec!("hi".to_string(), - "hi?".to_string(), - "hi!".to_string(), - "hi!?".to_string())); + .bind(|x| vec!(x.clone(), format!("{}?", x)) ), + ["hi".to_string(), + "hi?".to_string(), + "hi!".to_string(), + "hi!?".to_string()]); } diff --git a/src/test/run-pass/monomorphize-abi-alignment.rs b/src/test/run-pass/monomorphize-abi-alignment.rs index 726f205f5c..00e97ebc24 100644 --- a/src/test/run-pass/monomorphize-abi-alignment.rs +++ b/src/test/run-pass/monomorphize-abi-alignment.rs @@ -18,7 +18,7 @@ * and apply the wrong instance of the method `unwrap`. */ -#[derive(Copy)] +#[derive(Copy, Clone)] struct S { i:u8, t:T } impl S { @@ -27,10 +27,10 @@ impl S { } } -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] struct A((u32, u32)); -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] struct B(u64); pub fn main() { diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index 1164ef1a3c..12162ba902 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::marker::MarkerTrait; trait Serializer : MarkerTrait { @@ -17,7 +21,7 @@ trait Serializable { fn serialize(&self, s: S); } -impl Serializable for int { +impl Serializable for isize { fn serialize(&self, _s: S) { } } @@ -29,7 +33,7 @@ impl Serializable for F { } } -impl Serializer for int { +impl Serializer for isize { } pub fn main() { diff --git a/src/test/run-pass/move-1-unique.rs b/src/test/run-pass/move-1-unique.rs index 018cd440ca..ab9770b13d 100644 --- a/src/test/run-pass/move-1-unique.rs +++ b/src/test/run-pass/move-1-unique.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #[derive(Clone)] struct Triple { - x: int, - y: int, - z: int, + x: isize, + y: isize, + z: isize, } -fn test(x: bool, foo: Box) -> int { +fn test(x: bool, foo: Box) -> isize { let bar = foo; let mut y: Box; if x { y = bar; } else { y = box Triple{x: 4, y: 5, z: 6}; } @@ -26,7 +28,7 @@ fn test(x: bool, foo: Box) -> int { } pub fn main() { - let x = box Triple{x: 1, y: 2, z: 3}; + let x: Box<_> = box Triple{x: 1, y: 2, z: 3}; assert_eq!(test(true, x.clone()), 2); assert_eq!(test(true, x.clone()), 2); assert_eq!(test(true, x.clone()), 2); diff --git a/src/test/run-pass/move-2-unique.rs b/src/test/run-pass/move-2-unique.rs index 50187ef8ba..c65e58a7b6 100644 --- a/src/test/run-pass/move-2-unique.rs +++ b/src/test/run-pass/move-2-unique.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct X { x: int, y: int, z: int } +struct X { x: isize, y: isize, z: isize } pub fn main() { - let x = box X{x: 1, y: 2, z: 3}; + let x: Box<_> = box X{x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); } diff --git a/src/test/run-pass/move-2.rs b/src/test/run-pass/move-2.rs index 6561a9b2d5..054b57b2f4 100644 --- a/src/test/run-pass/move-2.rs +++ b/src/test/run-pass/move-2.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct X { x: int, y: int, z: int } +struct X { x: isize, y: isize, z: isize } -pub fn main() { let x = box X {x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); } +pub fn main() { let x: Box<_> = box X {x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); } diff --git a/src/test/run-pass/move-3-unique.rs b/src/test/run-pass/move-3-unique.rs index 07d0594b49..6036fa26cc 100644 --- a/src/test/run-pass/move-3-unique.rs +++ b/src/test/run-pass/move-3-unique.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] #[derive(Clone)] struct Triple { - x: int, - y: int, - z: int, + x: isize, + y: isize, + z: isize, } -fn test(x: bool, foo: Box) -> int { +fn test(x: bool, foo: Box) -> isize { let bar = foo; let mut y: Box; if x { y = bar; } else { y = box Triple {x: 4, y: 5, z: 6}; } @@ -26,7 +28,7 @@ fn test(x: bool, foo: Box) -> int { } pub fn main() { - let x = box Triple{x: 1, y: 2, z: 3}; + let x: Box<_> = box Triple{x: 1, y: 2, z: 3}; for _ in 0_usize..10000_usize { assert_eq!(test(true, x.clone()), 2); } diff --git a/src/test/run-pass/move-4-unique.rs b/src/test/run-pass/move-4-unique.rs index 9e5eeef755..79a1b294da 100644 --- a/src/test/run-pass/move-4-unique.rs +++ b/src/test/run-pass/move-4-unique.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct Triple {a: int, b: int, c: int} +struct Triple {a: isize, b: isize, c: isize} fn test(foo: Box) -> Box { let foo = foo; diff --git a/src/test/run-pass/move-4.rs b/src/test/run-pass/move-4.rs index c902677c64..16ef950235 100644 --- a/src/test/run-pass/move-4.rs +++ b/src/test/run-pass/move-4.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct Triple { a: int, b: int, c: int } +struct Triple { a: isize, b: isize, c: isize } fn test(foo: Box) -> Box { let foo = foo; diff --git a/src/test/run-pass/move-arg-2-unique.rs b/src/test/run-pass/move-arg-2-unique.rs index e496e9e210..7aec948c8d 100644 --- a/src/test/run-pass/move-arg-2-unique.rs +++ b/src/test/run-pass/move-arg-2-unique.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn test(foo: Box> ) { assert!(((*foo)[0] == 10)); } +fn test(foo: Box> ) { assert!(((*foo)[0] == 10)); } pub fn main() { let x = box vec!(10); diff --git a/src/test/run-pass/move-arg-2.rs b/src/test/run-pass/move-arg-2.rs index fdb6799b90..69b66d81e4 100644 --- a/src/test/run-pass/move-arg-2.rs +++ b/src/test/run-pass/move-arg-2.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn test(foo: Box>) { assert!(((*foo)[0] == 10)); } +fn test(foo: Box>) { assert!(((*foo)[0] == 10)); } pub fn main() { let x = box vec!(10); diff --git a/src/test/run-pass/move-arg.rs b/src/test/run-pass/move-arg.rs index 87db5cbe2f..3d9eba8c09 100644 --- a/src/test/run-pass/move-arg.rs +++ b/src/test/run-pass/move-arg.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn test(foo: int) { assert!((foo == 10)); } +// pretty-expanded FIXME #23616 + +fn test(foo: isize) { assert!((foo == 10)); } pub fn main() { let x = 10; test(x); } diff --git a/src/test/run-pass/move-guard-const.rs b/src/test/run-pass/move-guard-const.rs new file mode 100644 index 0000000000..6e49538e98 --- /dev/null +++ b/src/test/run-pass/move-guard-const.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![feature(box_syntax)] + +fn main() { + let x: Box<_> = box 1; + + let v = (1, 2); + + match v { + (2, 1) if take(x) => (), + (1, 2) if take(x) => (), + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/src/test/run-pass/move-nullary-fn.rs b/src/test/run-pass/move-nullary-fn.rs index b7cd3003e7..cec1e43997 100644 --- a/src/test/run-pass/move-nullary-fn.rs +++ b/src/test/run-pass/move-nullary-fn.rs @@ -9,6 +9,8 @@ // except according to those terms. // Issue #922 +// pretty-expanded FIXME #23616 + fn f2(_thing: F) where F: FnOnce() { } fn f(thing: F) where F: FnOnce() { diff --git a/src/test/run-pass/move-out-of-field.rs b/src/test/run-pass/move-out-of-field.rs index cb487a34f3..a0eba4685b 100644 --- a/src/test/run-pass/move-out-of-field.rs +++ b/src/test/run-pass/move-out-of-field.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::string::String; struct StringBuffer { diff --git a/src/test/run-pass/move-scalar.rs b/src/test/run-pass/move-scalar.rs index 845cb8ab60..a5b0a8b9bf 100644 --- a/src/test/run-pass/move-scalar.rs +++ b/src/test/run-pass/move-scalar.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let y: int = 42; - let mut x: int; + let y: isize = 42; + let mut x: isize; x = y; assert_eq!(x, 42); } diff --git a/src/test/run-pass/moves-based-on-type-capture-clause.rs b/src/test/run-pass/moves-based-on-type-capture-clause.rs index 3596fa1a00..b6509d2803 100644 --- a/src/test/run-pass/moves-based-on-type-capture-clause.rs +++ b/src/test/run-pass/moves-based-on-type-capture-clause.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; pub fn main() { let x = "Hello world!".to_string(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { println!("{}", x); }); } diff --git a/src/test/run-pass/moves-based-on-type-cross-crate.rs b/src/test/run-pass/moves-based-on-type-cross-crate.rs index 16f15804e0..a313ec998f 100644 --- a/src/test/run-pass/moves-based-on-type-cross-crate.rs +++ b/src/test/run-pass/moves-based-on-type-cross-crate.rs @@ -10,6 +10,8 @@ // aux-build:moves_based_on_type_lib.rs +// pretty-expanded FIXME #23616 + extern crate moves_based_on_type_lib; use moves_based_on_type_lib::f; diff --git a/src/test/run-pass/multi-let.rs b/src/test/run-pass/multi-let.rs index eb1444be37..658b34e13f 100644 --- a/src/test/run-pass/multi-let.rs +++ b/src/test/run-pass/multi-let.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = 10; let y = x; diff --git a/src/test/run-pass/multidispatch1.rs b/src/test/run-pass/multidispatch1.rs index b9435afdc7..fdf9f95b27 100644 --- a/src/test/run-pass/multidispatch1.rs +++ b/src/test/run-pass/multidispatch1.rs @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::fmt::Debug; trait MyTrait { fn get(&self) -> T; } -#[derive(Copy)] +#[derive(Copy, Clone)] struct MyType { - dummy: uint + dummy: usize } -impl MyTrait for MyType { - fn get(&self) -> uint { self.dummy } +impl MyTrait for MyType { + fn get(&self) -> usize { self.dummy } } impl MyTrait for MyType { @@ -36,6 +38,6 @@ where T : Eq + Debug, pub fn main() { let value = MyType { dummy: 256 + 22 }; - test_eq::(value, value.dummy); + test_eq::(value, value.dummy); test_eq::(value, value.dummy as u8); } diff --git a/src/test/run-pass/multidispatch2.rs b/src/test/run-pass/multidispatch2.rs index 6b52ea9dfa..75c6c5ac7d 100644 --- a/src/test/run-pass/multidispatch2.rs +++ b/src/test/run-pass/multidispatch2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::fmt::Debug; use std::default::Default; @@ -23,13 +25,13 @@ impl MyTrait for T } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct MyType { - dummy: uint + dummy: usize } -impl MyTrait for MyType { - fn get(&self) -> uint { self.dummy } +impl MyTrait for MyType { + fn get(&self) -> usize { self.dummy } } fn test_eq(m: M, v: T) diff --git a/src/test/run-pass/multiline-comment.rs b/src/test/run-pass/multiline-comment.rs index 6203d47be5..8c74326d1c 100644 --- a/src/test/run-pass/multiline-comment.rs +++ b/src/test/run-pass/multiline-comment.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + /* * This is a multi-line oldcomment. */ diff --git a/src/test/run-pass/multiple-trait-bounds.rs b/src/test/run-pass/multiple-trait-bounds.rs index 7ce1afb52a..2746205b63 100644 --- a/src/test/run-pass/multiple-trait-bounds.rs +++ b/src/test/run-pass/multiple-trait-bounds.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn f(_: T) { } diff --git a/src/test/run-pass/mut-function-arguments.rs b/src/test/run-pass/mut-function-arguments.rs index b1f7da17c8..644e455755 100644 --- a/src/test/run-pass/mut-function-arguments.rs +++ b/src/test/run-pass/mut-function-arguments.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn f(mut y: Box) { +fn f(mut y: Box) { *y = 5; assert_eq!(*y, 5); } fn g() { - let frob = |mut q: Box| { *q = 2; assert!(*q == 2); }; + let frob = |mut q: Box| { *q = 2; assert!(*q == 2); }; let w = box 37; frob(w); diff --git a/src/test/run-pass/mut-in-ident-patterns.rs b/src/test/run-pass/mut-in-ident-patterns.rs index d3ae80861f..2a8f6f1fc3 100644 --- a/src/test/run-pass/mut-in-ident-patterns.rs +++ b/src/test/run-pass/mut-in-ident-patterns.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { - fn foo(&self, mut x: int) -> int { + fn foo(&self, mut x: isize) -> isize { let val = x; x = 37 * x; val + x @@ -30,7 +32,7 @@ pub fn main() { assert_eq!(X.foo(2), 76); enum Bar { - Foo(int), + Foo(isize), Baz(f32, u8) } @@ -61,14 +63,14 @@ pub fn main() { } } - fn foo1((x, mut y): (f64, int), mut z: int) -> int { + fn foo1((x, mut y): (f64, isize), mut z: isize) -> isize { y = 2 * 6; - z = y + (x as int); + z = y + (x as isize); y - z } struct A { - x: int + x: isize } let A { x: mut x } = A { x: 10 }; assert_eq!(x, 10); diff --git a/src/test/run-pass/mut-vstore-expr.rs b/src/test/run-pass/mut-vstore-expr.rs index a276e902fb..503f3ce5f9 100644 --- a/src/test/run-pass/mut-vstore-expr.rs +++ b/src/test/run-pass/mut-vstore-expr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let _x: &mut [int] = &mut [ 1, 2, 3 ]; + let _x: &mut [isize] = &mut [ 1, 2, 3 ]; } diff --git a/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs b/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs index e074c3fb3d..bed3b87def 100644 --- a/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs +++ b/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn test1() { let mut ints = [0; 32]; ints[0] += 1; diff --git a/src/test/run-pass/mutable-alias-vec.rs b/src/test/run-pass/mutable-alias-vec.rs index 28dd89edd6..3f90cedca9 100644 --- a/src/test/run-pass/mutable-alias-vec.rs +++ b/src/test/run-pass/mutable-alias-vec.rs @@ -8,16 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn grow(v: &mut Vec ) { +fn grow(v: &mut Vec ) { v.push(1); } pub fn main() { - let mut v: Vec = Vec::new(); + let mut v: Vec = Vec::new(); grow(&mut v); grow(&mut v); grow(&mut v); let len = v.len(); println!("{}", len); - assert_eq!(len, 3 as uint); + assert_eq!(len, 3 as usize); } diff --git a/src/test/run-pass/mutual-recursion-group.rs b/src/test/run-pass/mutual-recursion-group.rs index 8444a632fe..72a8847094 100644 --- a/src/test/run-pass/mutual-recursion-group.rs +++ b/src/test/run-pass/mutual-recursion-group.rs @@ -9,12 +9,14 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + enum colour { red, green, blue, } enum tree { children(Box), leaf(colour), } enum list { cons(Box, Box), nil, } -enum small_list { kons(int, Box), neel, } +enum small_list { kons(isize, Box), neel, } pub fn main() { } diff --git a/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs b/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs index 680cdf14e8..f275e9b742 100644 --- a/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs +++ b/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs @@ -10,6 +10,8 @@ // aux-build:namespaced_enum_emulate_flat.rs +// pretty-expanded FIXME #23616 + extern crate namespaced_enum_emulate_flat; use namespaced_enum_emulate_flat::{Foo, A, B, C}; @@ -28,4 +30,3 @@ fn _f2(f: Bar) { } pub fn main() {} - diff --git a/src/test/run-pass/namespaced-enum-emulate-flat.rs b/src/test/run-pass/namespaced-enum-emulate-flat.rs index e4a8ec19eb..0f85c20d31 100644 --- a/src/test/run-pass/namespaced-enum-emulate-flat.rs +++ b/src/test/run-pass/namespaced-enum-emulate-flat.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub use Foo::*; use nest::{Bar, D, E, F}; pub enum Foo { A, - B(int), - C { a: int }, + B(isize), + C { a: isize }, } impl Foo { @@ -32,8 +34,8 @@ mod nest { pub enum Bar { D, - E(int), - F { a: int }, + E(isize), + F { a: isize }, } impl Bar { diff --git a/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs b/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs index e5317c2f57..7bfe90bad7 100644 --- a/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs +++ b/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs @@ -10,6 +10,8 @@ // aux-build:namespaced_enums.rs +// pretty-expanded FIXME #23616 + extern crate namespaced_enums; fn _f(f: namespaced_enums::Foo) { diff --git a/src/test/run-pass/namespaced-enum-glob-import.rs b/src/test/run-pass/namespaced-enum-glob-import.rs index c48be3af24..f506ea11f8 100644 --- a/src/test/run-pass/namespaced-enum-glob-import.rs +++ b/src/test/run-pass/namespaced-enum-glob-import.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod m2 { pub enum Foo { A, - B(int), - C { a: int }, + B(isize), + C { a: isize }, } impl Foo { diff --git a/src/test/run-pass/namespaced-enums-xcrate.rs b/src/test/run-pass/namespaced-enums-xcrate.rs index 7545908dcb..0046d80e08 100644 --- a/src/test/run-pass/namespaced-enums-xcrate.rs +++ b/src/test/run-pass/namespaced-enums-xcrate.rs @@ -10,6 +10,8 @@ // aux-build:namespaced_enums.rs +// pretty-expanded FIXME #23616 + extern crate namespaced_enums; use namespaced_enums::Foo; @@ -21,4 +23,3 @@ fn _foo (f: Foo) { } pub fn main() {} - diff --git a/src/test/run-pass/namespaced-enums.rs b/src/test/run-pass/namespaced-enums.rs index 13f70f6a74..3e72f73bc4 100644 --- a/src/test/run-pass/namespaced-enums.rs +++ b/src/test/run-pass/namespaced-enums.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { A, - B(int), - C { a: int }, + B(isize), + C { a: isize }, } fn _foo (f: Foo) { diff --git a/src/test/run-pass/native-print-no-runtime.rs b/src/test/run-pass/native-print-no-runtime.rs index b151eddb94..deb0b50306 100644 --- a/src/test/run-pass/native-print-no-runtime.rs +++ b/src/test/run-pass/native-print-no-runtime.rs @@ -11,7 +11,7 @@ #![feature(start)] #[start] -pub fn main(_: int, _: *const *const u8) -> int { +pub fn main(_: isize, _: *const *const u8) -> isize { println!("hello"); 0 } diff --git a/src/test/run-pass/negative.rs b/src/test/run-pass/negative.rs index 435382666f..c5b6a6a035 100644 --- a/src/test/run-pass/negative.rs +++ b/src/test/run-pass/negative.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { match -5 { -5 => {} diff --git a/src/test/run-pass/nested-block-comment.rs b/src/test/run-pass/nested-block-comment.rs index a6d932935a..650e28548c 100644 --- a/src/test/run-pass/nested-block-comment.rs +++ b/src/test/run-pass/nested-block-comment.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* This test checks that nested comments are supported /* diff --git a/src/test/run-pass/nested-class.rs b/src/test/run-pass/nested-class.rs index 19eba0808c..86197d44a6 100644 --- a/src/test/run-pass/nested-class.rs +++ b/src/test/run-pass/nested-class.rs @@ -8,22 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { struct b { - i: int, + i: isize, } impl b { - fn do_stuff(&self) -> int { return 37; } + fn do_stuff(&self) -> isize { return 37; } } - fn b(i:int) -> b { + fn b(i:isize) -> b { b { i: i } } - // fn b(x:int) -> int { panic!(); } + // fn b(x:isize) -> isize { panic!(); } let z = b(42); assert_eq!(z.i, 42); diff --git a/src/test/run-pass/nested-enum-same-names.rs b/src/test/run-pass/nested-enum-same-names.rs index 33c4ed6234..c0baab66c5 100644 --- a/src/test/run-pass/nested-enum-same-names.rs +++ b/src/test/run-pass/nested-enum-same-names.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* #7770 ICE with sibling methods containing same-name-enum containing diff --git a/src/test/run-pass/nested-exhaustive-match.rs b/src/test/run-pass/nested-exhaustive-match.rs index b2a47e0ccb..e0a3b1adfe 100644 --- a/src/test/run-pass/nested-exhaustive-match.rs +++ b/src/test/run-pass/nested-exhaustive-match.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo { foo: bool, bar: Option, baz: int } +// pretty-expanded FIXME #23616 + +struct Foo { foo: bool, bar: Option, baz: isize } pub fn main() { match (Foo{foo: true, bar: Some(10), baz: 20}) { diff --git a/src/test/run-pass/nested-function-names-issue-8587.rs b/src/test/run-pass/nested-function-names-issue-8587.rs index f697f0b59d..28f3438f98 100644 --- a/src/test/run-pass/nested-function-names-issue-8587.rs +++ b/src/test/run-pass/nested-function-names-issue-8587.rs @@ -13,28 +13,30 @@ // // Issue #8587 +// pretty-expanded FIXME #23616 + pub struct X; impl X { - fn f(&self) -> int { + fn f(&self) -> isize { #[inline(never)] - fn inner() -> int { + fn inner() -> isize { 0 } inner() } - fn g(&self) -> int { + fn g(&self) -> isize { #[inline(never)] - fn inner_2() -> int { + fn inner_2() -> isize { 1 } inner_2() } - fn h(&self) -> int { + fn h(&self) -> isize { #[inline(never)] - fn inner() -> int { + fn inner() -> isize { 2 } inner() diff --git a/src/test/run-pass/nested-matchs.rs b/src/test/run-pass/nested-matchs.rs index b0ac9fb597..46d30b68f7 100644 --- a/src/test/run-pass/nested-matchs.rs +++ b/src/test/run-pass/nested-matchs.rs @@ -11,13 +11,13 @@ fn baz() -> ! { panic!(); } fn foo() { - match Some::(5) { - Some::(_x) => { + match Some::(5) { + Some::(_x) => { let mut bar; - match None:: { None:: => { bar = 5; } _ => { baz(); } } + match None:: { None:: => { bar = 5; } _ => { baz(); } } println!("{}", bar); } - None:: => { println!("hello"); } + None:: => { println!("hello"); } } } diff --git a/src/test/run-pass/nested-pattern.rs b/src/test/run-pass/nested-pattern.rs index 14a84484f6..f9abdd56fa 100644 --- a/src/test/run-pass/nested-pattern.rs +++ b/src/test/run-pass/nested-pattern.rs @@ -12,13 +12,13 @@ // a bug was causing this to complain about leaked memory on exit -enum t { foo(int, uint), bar(int, Option), } +enum t { foo(isize, usize), bar(isize, Option), } fn nested(o: t) { match o { - t::bar(_i, Some::(_)) => { println!("wrong pattern matched"); panic!(); } + t::bar(_i, Some::(_)) => { println!("wrong pattern matched"); panic!(); } _ => { println!("succeeded"); } } } -pub fn main() { nested(t::bar(1, None::)); } +pub fn main() { nested(t::bar(1, None::)); } diff --git a/src/test/run-pass/nested-vec-1.rs b/src/test/run-pass/nested-vec-1.rs new file mode 100644 index 0000000000..2b92ed38ea --- /dev/null +++ b/src/test/run-pass/nested-vec-1.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that using the `vec!` macro nested within itself works + +fn main() { + let nested = vec![vec![1u32, 2u32, 3u32]]; + assert_eq!(nested[0][1], 2); +} diff --git a/src/test/run-pass/nested-vec-2.rs b/src/test/run-pass/nested-vec-2.rs new file mode 100644 index 0000000000..669f9e4f4b --- /dev/null +++ b/src/test/run-pass/nested-vec-2.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that using the `vec!` macro nested within itself works +// when the contents implement Drop + +struct D(u32); + +impl Drop for D { + fn drop(&mut self) { println!("Dropping {}", self.0); } +} + +fn main() { + let nested = vec![vec![D(1u32), D(2u32), D(3u32)]]; + assert_eq!(nested[0][1].0, 2); +} diff --git a/src/test/run-pass/nested-vec-3.rs b/src/test/run-pass/nested-vec-3.rs new file mode 100644 index 0000000000..60cf795c91 --- /dev/null +++ b/src/test/run-pass/nested-vec-3.rs @@ -0,0 +1,60 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that using the `vec!` macro nested within itself works when +// the contents implement Drop and we hit a panic in the middle of +// construction. + + +use std::thread; +use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; + +static LOG: AtomicUsize = ATOMIC_USIZE_INIT; + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _nested = vec![vec![D( 1), D( 2), D( 3), D( 4)], + vec![D( 5), D( 6), D( 7), D( 8)], + vec![D( 9), D(10), die(), D(12)], + vec![D(13), D(14), D(15), D(16)]]; + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing the + // second inner vector. Therefore, we drop the elements of the + // partially filled vector first, before we get around to dropping + // the elements of the filled vector. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky: as noted above, we'll drop the 9+10 + // first, but due to #23222, they get dropped in reverse + // order. Likewise, again due to #23222, we will drop the second + // filled vec before the first filled vec. + // + // If Issue 23222 is "fixed", then presumably the corrected + // expected order of events will be 0x__9_A__1_2_3_4__5_6_7_8; + // that is, we would still drop 9+10 first, since they belong to + // the more deeply nested expression when the panic occurs. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/src/test/run-pass/nested_item_main.rs b/src/test/run-pass/nested_item_main.rs index d73fba5614..f7adfe3669 100644 --- a/src/test/run-pass/nested_item_main.rs +++ b/src/test/run-pass/nested_item_main.rs @@ -10,9 +10,11 @@ // aux-build:nested_item.rs +// pretty-expanded FIXME #23616 + extern crate nested_item; pub fn main() { assert_eq!(2, nested_item::foo::<()>()); - assert_eq!(2, nested_item::foo::()); + assert_eq!(2, nested_item::foo::()); } diff --git a/src/test/run-pass/new-box-syntax.rs b/src/test/run-pass/new-box-syntax.rs index 3d4847a119..95168b1bff 100644 --- a/src/test/run-pass/new-box-syntax.rs +++ b/src/test/run-pass/new-box-syntax.rs @@ -8,24 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, alloc)] // Tests that the new `box` syntax works with unique pointers. use std::boxed::{Box, HEAP}; struct Structure { - x: int, - y: int, + x: isize, + y: isize, } pub fn main() { - let x: Box = box(HEAP) 2; - let y: Box = box 2; - let b: Box = box()(1 + 2); + let x: Box = box(HEAP) 2; + let y: Box = box 2; + let b: Box = box()(1 + 2); let c = box()(3 + 4); } diff --git a/src/test/run-pass/new-box.rs b/src/test/run-pass/new-box.rs index 1f2207ad87..17f71c3de4 100644 --- a/src/test/run-pass/new-box.rs +++ b/src/test/run-pass/new-box.rs @@ -11,8 +11,8 @@ #![allow(unknown_features)] #![feature(box_syntax)] -fn f(x: Box) { - let y: &int = &*x; +fn f(x: Box) { + let y: &isize = &*x; println!("{}", *x); println!("{}", *y); } @@ -39,4 +39,3 @@ fn main() { f(box 1234); g(box Struct as Box); } - diff --git a/src/test/run-pass/new-impl-syntax.rs b/src/test/run-pass/new-impl-syntax.rs index bd0a53b620..554fab53e4 100644 --- a/src/test/run-pass/new-impl-syntax.rs +++ b/src/test/run-pass/new-impl-syntax.rs @@ -11,8 +11,8 @@ use std::fmt; struct Thingy { - x: int, - y: int + x: isize, + y: isize } impl fmt::Debug for Thingy { diff --git a/src/test/run-pass/new-style-constants.rs b/src/test/run-pass/new-style-constants.rs index fa681c8139..36d66d1e12 100644 --- a/src/test/run-pass/new-style-constants.rs +++ b/src/test/run-pass/new-style-constants.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static FOO: int = 3; +static FOO: isize = 3; pub fn main() { println!("{}", FOO); diff --git a/src/test/run-pass/new-style-fixed-length-vec.rs b/src/test/run-pass/new-style-fixed-length-vec.rs index e06461daed..4d9f0394eb 100644 --- a/src/test/run-pass/new-style-fixed-length-vec.rs +++ b/src/test/run-pass/new-style-fixed-length-vec.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static FOO: [int; 3] = [1, 2, 3]; +static FOO: [isize; 3] = [1, 2, 3]; pub fn main() { println!("{} {} {}", FOO[0], FOO[1], FOO[2]); diff --git a/src/test/run-pass/new-unicode-escapes.rs b/src/test/run-pass/new-unicode-escapes.rs index 7430f730f3..8c2d5e09ad 100644 --- a/src/test/run-pass/new-unicode-escapes.rs +++ b/src/test/run-pass/new-unicode-escapes.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + pub fn main() { let s = "\u{2603}"; assert_eq!(s, "☃"); diff --git a/src/test/run-pass/new-unsafe-pointers.rs b/src/test/run-pass/new-unsafe-pointers.rs index 96ccb1a37a..a0d631046a 100644 --- a/src/test/run-pass/new-unsafe-pointers.rs +++ b/src/test/run-pass/new-unsafe-pointers.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { - let _a: *const int = 3 as *const int; - let _a: *mut int = 3 as *mut int; + let _a: *const isize = 3 as *const isize; + let _a: *mut isize = 3 as *mut isize; } diff --git a/src/test/run-pass/newlambdas-ret-infer.rs b/src/test/run-pass/newlambdas-ret-infer.rs index 130cdc85b0..543dbb36b2 100644 --- a/src/test/run-pass/newlambdas-ret-infer.rs +++ b/src/test/run-pass/newlambdas-ret-infer.rs @@ -11,10 +11,10 @@ // Test that the lambda kind is inferred correctly as a return // expression -#![allow(unknown_features)] -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. +// pretty-expanded FIXME #23616 -fn unique() -> Box { return box || (); } +fn unique() -> Box { return Box::new(|| ()); } pub fn main() { } diff --git a/src/test/run-pass/newlambdas-ret-infer2.rs b/src/test/run-pass/newlambdas-ret-infer2.rs index 0952bedd6e..e8297173a5 100644 --- a/src/test/run-pass/newlambdas-ret-infer2.rs +++ b/src/test/run-pass/newlambdas-ret-infer2.rs @@ -11,10 +11,10 @@ // Test that the lambda kind is inferred correctly as a return // expression -#![allow(unknown_features)] -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. +// pretty-expanded FIXME #23616 -fn unique() -> Box { box || () } +fn unique() -> Box { Box::new(|| ()) } pub fn main() { } diff --git a/src/test/run-pass/newlambdas.rs b/src/test/run-pass/newlambdas.rs index 01875288ae..c6fa7cc35f 100644 --- a/src/test/run-pass/newlambdas.rs +++ b/src/test/run-pass/newlambdas.rs @@ -10,7 +10,9 @@ // Tests for the new |args| expr lambda syntax -fn f(i: int, f: F) -> int where F: FnOnce(int) -> int { f(i) } +// pretty-expanded FIXME #23616 + +fn f(i: isize, f: F) -> isize where F: FnOnce(isize) -> isize { f(i) } fn g(_g: G) where G: FnOnce() { } diff --git a/src/test/run-pass/newtype-polymorphic.rs b/src/test/run-pass/newtype-polymorphic.rs index 4b7dbdc9e5..424d518895 100644 --- a/src/test/run-pass/newtype-polymorphic.rs +++ b/src/test/run-pass/newtype-polymorphic.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #[derive(Clone)] struct myvec(Vec ); diff --git a/src/test/run-pass/newtype-struct-drop-run.rs b/src/test/run-pass/newtype-struct-drop-run.rs index 8c35abad7f..2d162ba7e3 100644 --- a/src/test/run-pass/newtype-struct-drop-run.rs +++ b/src/test/run-pass/newtype-struct-drop-run.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] // Make sure the destructor is run for newtype structs. use std::cell::Cell; -struct Foo<'a>(&'a Cell); +struct Foo<'a>(&'a Cell); #[unsafe_destructor] impl<'a> Drop for Foo<'a> { diff --git a/src/test/run-pass/newtype-struct-with-dtor.rs b/src/test/run-pass/newtype-struct-with-dtor.rs index 8631755f37..d1ad5614e3 100644 --- a/src/test/run-pass/newtype-struct-with-dtor.rs +++ b/src/test/run-pass/newtype-struct-with-dtor.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-fast doesn't like extern crate + +// pretty-expanded FIXME #23616 + +#![feature(libc)] extern crate libc; use libc::c_int; diff --git a/src/test/run-pass/newtype-struct-xc-2.rs b/src/test/run-pass/newtype-struct-xc-2.rs index 0302a0588e..ac03f65750 100644 --- a/src/test/run-pass/newtype-struct-xc-2.rs +++ b/src/test/run-pass/newtype-struct-xc-2.rs @@ -10,6 +10,8 @@ // aux-build:newtype_struct_xc.rs +// pretty-expanded FIXME #23616 + extern crate newtype_struct_xc; use newtype_struct_xc::Au; diff --git a/src/test/run-pass/newtype-struct-xc.rs b/src/test/run-pass/newtype-struct-xc.rs index 3e375c4831..0cac4530fa 100644 --- a/src/test/run-pass/newtype-struct-xc.rs +++ b/src/test/run-pass/newtype-struct-xc.rs @@ -10,6 +10,8 @@ // aux-build:newtype_struct_xc.rs +// pretty-expanded FIXME #23616 + extern crate newtype_struct_xc; pub fn main() { diff --git a/src/test/run-pass/newtype-temporary.rs b/src/test/run-pass/newtype-temporary.rs index 5952258e46..19790a488b 100644 --- a/src/test/run-pass/newtype-temporary.rs +++ b/src/test/run-pass/newtype-temporary.rs @@ -9,7 +9,7 @@ // except according to those terms. #[derive(PartialEq, Debug)] -struct Foo(uint); +struct Foo(usize); fn foo() -> Foo { Foo(42) diff --git a/src/test/run-pass/newtype.rs b/src/test/run-pass/newtype.rs index 869ae4a37d..818ea4c9f2 100644 --- a/src/test/run-pass/newtype.rs +++ b/src/test/run-pass/newtype.rs @@ -8,16 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +#[derive(Copy, Clone)] struct mytype(Mytype); -#[derive(Copy)] +#[derive(Copy, Clone)] struct Mytype { - compute: fn(mytype) -> int, - val: int, + compute: fn(mytype) -> isize, + val: isize, } -fn compute(i: mytype) -> int { +fn compute(i: mytype) -> isize { let mytype(m) = i; return m.val + 20; } diff --git a/src/test/run-pass/nil-decl-in-foreign.rs b/src/test/run-pass/nil-decl-in-foreign.rs index e23c970e29..97ee237771 100644 --- a/src/test/run-pass/nil-decl-in-foreign.rs +++ b/src/test/run-pass/nil-decl-in-foreign.rs @@ -9,6 +9,8 @@ // except according to those terms. // Issue #901 +// pretty-expanded FIXME #23616 + mod libc { extern { pub fn printf(x: ()); diff --git a/src/test/run-pass/nil-pattern.rs b/src/test/run-pass/nil-pattern.rs index 329590b547..342644e038 100644 --- a/src/test/run-pass/nil-pattern.rs +++ b/src/test/run-pass/nil-pattern.rs @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let x = (); match x { () => { } } } diff --git a/src/test/run-pass/no-landing-pads.rs b/src/test/run-pass/no-landing-pads.rs index 5ce32e4fe2..da57c81a66 100644 --- a/src/test/run-pass/no-landing-pads.rs +++ b/src/test/run-pass/no-landing-pads.rs @@ -10,6 +10,8 @@ // compile-flags: -Z no-landing-pads +// pretty-expanded FIXME #23616 + use std::thread; static mut HIT: bool = false; diff --git a/src/test/run-pass/no-std-xcrate2.rs b/src/test/run-pass/no-std-xcrate2.rs index f5f34607af..43f6b27d64 100644 --- a/src/test/run-pass/no-std-xcrate2.rs +++ b/src/test/run-pass/no-std-xcrate2.rs @@ -30,7 +30,7 @@ pub mod linkhack { } #[start] -pub fn main(_: int, _: **u8, _: *u8) -> int { +pub fn main(_: isize, _: **u8, _: *u8) -> isize { no_std_crate::foo(); 0 } diff --git a/src/test/run-pass/non-built-in-quote.rs b/src/test/run-pass/non-built-in-quote.rs index 8b41670734..6c0df5f4c1 100644 --- a/src/test/run-pass/non-built-in-quote.rs +++ b/src/test/run-pass/non-built-in-quote.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! quote_tokens { () => (()) } pub fn main() { diff --git a/src/test/run-pass/non-legacy-modes.rs b/src/test/run-pass/non-legacy-modes.rs index e422cb8032..5f1c69bb4b 100644 --- a/src/test/run-pass/non-legacy-modes.rs +++ b/src/test/run-pass/non-legacy-modes.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct X { - repr: int + repr: isize } fn apply(x: T, f: F) where F: FnOnce(T) { f(x); } -fn check_int(x: int) { +fn check_int(x: isize) { assert_eq!(x, 22); } diff --git a/src/test/run-pass/nondrop-cycle.rs b/src/test/run-pass/nondrop-cycle.rs index bbce9a8f4a..a28f2b15b9 100644 --- a/src/test/run-pass/nondrop-cycle.rs +++ b/src/test/run-pass/nondrop-cycle.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cell::Cell; struct C<'a> { diff --git a/src/test/run-pass/nul-characters.rs b/src/test/run-pass/nul-characters.rs index 22786c0abc..25c111daad 100644 --- a/src/test/run-pass/nul-characters.rs +++ b/src/test/run-pass/nul-characters.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let all_nuls1 = "\0\x00\u0000\U00000000"; - let all_nuls2 = "\U00000000\u0000\x00\0"; - let all_nuls3 = "\u0000\U00000000\x00\0"; - let all_nuls4 = "\x00\u0000\0\U00000000"; + let all_nuls1 = "\0\x00\u{0}\u{0}"; + let all_nuls2 = "\u{0}\u{0}\x00\0"; + let all_nuls3 = "\u{0}\u{0}\x00\0"; + let all_nuls4 = "\x00\u{0}\0\u{0}"; // sizes for two should suffice assert_eq!(all_nuls1.len(), 4); @@ -35,8 +37,8 @@ pub fn main() // testing equality between explicit character literals assert_eq!('\0', '\x00'); - assert_eq!('\u0000', '\x00'); - assert_eq!('\u0000', '\U00000000'); + assert_eq!('\u{0}', '\x00'); + assert_eq!('\u{0}', '\u{0}'); // NUL characters should make a difference assert!("Hello World" != "Hello \0World"); diff --git a/src/test/run-pass/nullable-pointer-ffi-compat.rs b/src/test/run-pass/nullable-pointer-ffi-compat.rs index 32432c07dc..22aa09c718 100644 --- a/src/test/run-pass/nullable-pointer-ffi-compat.rs +++ b/src/test/run-pass/nullable-pointer-ffi-compat.rs @@ -20,16 +20,18 @@ // then we simply express the enum as just a pointer and not wrap it // in a struct. +// pretty-expanded FIXME #23616 + use std::mem; #[inline(never)] -extern "C" fn foo<'a>(x: &'a int) -> Option<&'a int> { Some(x) } +extern "C" fn foo<'a>(x: &'a isize) -> Option<&'a isize> { Some(x) } -static FOO: int = 0xDEADBEE; +static FOO: isize = 0xDEADBEE; pub fn main() { unsafe { - let f: for<'a> extern "C" fn(&'a int) -> &'a int = mem::transmute(foo); + let f: for<'a> extern "C" fn(&'a isize) -> &'a isize = mem::transmute(foo); assert_eq!(*f(&FOO), FOO); } } diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs index bb62b1599a..ad2716e00d 100644 --- a/src/test/run-pass/nullable-pointer-iotareduction.rs +++ b/src/test/run-pass/nullable-pointer-iotareduction.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -21,7 +23,7 @@ use std::{option, mem}; // trying to get assert failure messages that at least identify which case // failed. -enum E { Thing(int, T), Nothing((), ((), ()), [i8; 0]) } +enum E { Thing(isize, T), Nothing((), ((), ()), [i8; 0]) } impl E { fn is_none(&self) -> bool { match *self { @@ -29,7 +31,7 @@ impl E { E::Nothing(..) => true } } - fn get_ref(&self) -> (int, &T) { + fn get_ref(&self) -> (isize, &T) { match *self { E::Nothing(..) => panic!("E::get_ref(Nothing::<{}>)", stringify!(T)), E::Thing(x, ref y) => (x, y) @@ -55,7 +57,7 @@ macro_rules! check_fancy { check_fancy!($e, $T, |ptr| assert!(*ptr == $e)); }}; ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{ - assert!(E::Nothing::<$T>((), ((), ()), [23i8; 0]).is_none()); + assert!(E::Nothing::<$T>((), ((), ()), [23; 0]).is_none()); let e = $e; let t_ = E::Thing::<$T>(23, e); match t_.get_ref() { @@ -74,11 +76,11 @@ macro_rules! check_type { } pub fn main() { - check_type!(&17, &int); - check_type!(box 18, Box); + check_type!(&17, &isize); + check_type!(box 18, Box); check_type!("foo".to_string(), String); - check_type!(vec!(20, 22), Vec ); - let mint: uint = unsafe { mem::transmute(main) }; + check_type!(vec!(20, 22), Vec ); + let mint: usize = unsafe { mem::transmute(main) }; check_type!(main, fn(), |pthing| { assert!(mint == unsafe { mem::transmute(*pthing) }) }); diff --git a/src/test/run-pass/nullable-pointer-size.rs b/src/test/run-pass/nullable-pointer-size.rs index 02fc0cf029..6e3f438575 100644 --- a/src/test/run-pass/nullable-pointer-size.rs +++ b/src/test/run-pass/nullable-pointer-size.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; -enum E { Thing(int, T), Nothing((), ((), ()), [i8; 0]) } -struct S(int, T); +enum E { Thing(isize, T), Nothing((), ((), ()), [i8; 0]) } +struct S(isize, T); // These are macros so we get useful assert messages. @@ -35,7 +37,7 @@ macro_rules! check_type { } pub fn main() { - check_type!(&'static int); - check_type!(Box); + check_type!(&'static isize); + check_type!(Box); check_type!(extern fn()); } diff --git a/src/test/run-pass/nullary-or-pattern.rs b/src/test/run-pass/nullary-or-pattern.rs index 565ef278d5..f4cfc80827 100644 --- a/src/test/run-pass/nullary-or-pattern.rs +++ b/src/test/run-pass/nullary-or-pattern.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum blah { a, b, } -fn or_alt(q: blah) -> int { +fn or_alt(q: blah) -> isize { match q { blah::a | blah::b => { 42 } } } diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index eccc2a41a8..cb41949a72 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -15,6 +15,10 @@ // necessary. Testing the methods of the impls is done within the source // file for each numeric type. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::ops::Add; use std::num::ToPrimitive; diff --git a/src/test/run-pass/object-lifetime-default-default-to-static.rs b/src/test/run-pass/object-lifetime-default-default-to-static.rs index c385a0195b..1b631f171e 100644 --- a/src/test/run-pass/object-lifetime-default-default-to-static.rs +++ b/src/test/run-pass/object-lifetime-default-default-to-static.rs @@ -11,6 +11,8 @@ // Test that `Box` is equivalent to `Box`, both in // fields and fn arguments. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Test { diff --git a/src/test/run-pass/object-lifetime-default-from-ref-struct.rs b/src/test/run-pass/object-lifetime-default-from-ref-struct.rs index 24da960367..910d933d46 100644 --- a/src/test/run-pass/object-lifetime-default-from-ref-struct.rs +++ b/src/test/run-pass/object-lifetime-default-from-ref-struct.rs @@ -11,6 +11,8 @@ // Test that the lifetime of the enclosing `&` is used for the object // lifetime bound. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Test { diff --git a/src/test/run-pass/object-lifetime-default-from-rptr-box.rs b/src/test/run-pass/object-lifetime-default-from-rptr-box.rs index 825800e1d4..e2047ee325 100644 --- a/src/test/run-pass/object-lifetime-default-from-rptr-box.rs +++ b/src/test/run-pass/object-lifetime-default-from-rptr-box.rs @@ -11,6 +11,8 @@ // Test that the lifetime from the enclosing `&` is "inherited" // through the `Box` struct. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Test { diff --git a/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs b/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs index 0f34d945c8..edd0bdb32c 100644 --- a/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs +++ b/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs @@ -11,6 +11,8 @@ // Test that the lifetime of the enclosing `&` is used for the object // lifetime bound. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Test { diff --git a/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs b/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs index 9d5dac536f..3c2419e420 100644 --- a/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs +++ b/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs @@ -11,6 +11,8 @@ // Test that the lifetime from the enclosing `&` is "inherited" // through the `MyBox` struct. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Test { diff --git a/src/test/run-pass/object-lifetime-default-from-rptr.rs b/src/test/run-pass/object-lifetime-default-from-rptr.rs index b7a28a5c52..d9e0b22fbf 100644 --- a/src/test/run-pass/object-lifetime-default-from-rptr.rs +++ b/src/test/run-pass/object-lifetime-default-from-rptr.rs @@ -11,6 +11,8 @@ // Test that the lifetime of the enclosing `&` is used for the object // lifetime bound. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Test { diff --git a/src/test/run-pass/object-method-numbering.rs b/src/test/run-pass/object-method-numbering.rs index 8da753acb9..8b8c56aee8 100644 --- a/src/test/run-pass/object-method-numbering.rs +++ b/src/test/run-pass/object-method-numbering.rs @@ -11,6 +11,8 @@ // Test for using an object with an associated type binding as the // instantiation for a generic type with a bound. +// pretty-expanded FIXME #23616 + trait SomeTrait { type SomeType; @@ -29,7 +31,7 @@ impl SomeTrait for i32 { } fn main() { - let x = 22_i32; + let x = 22; let x1: &SomeTrait = &x; let y = get_int(x1); assert_eq!(x, y); diff --git a/src/test/run-pass/object-one-type-two-traits.rs b/src/test/run-pass/object-one-type-two-traits.rs index f8a3ce7cda..aa2dbf03bb 100644 --- a/src/test/run-pass/object-one-type-two-traits.rs +++ b/src/test/run-pass/object-one-type-two-traits.rs @@ -17,25 +17,25 @@ use std::any::Any; trait Wrap { - fn get(&self) -> int; + fn get(&self) -> isize; fn wrap(self: Box) -> Box; } -impl Wrap for int { - fn get(&self) -> int { +impl Wrap for isize { + fn get(&self) -> isize { *self } - fn wrap(self: Box) -> Box { + fn wrap(self: Box) -> Box { self as Box } } -fn is(x: &Any) -> bool { +fn is(x: &Any) -> bool { x.is::() } fn main() { - let x = box 22 as Box; + let x = box 22isize as Box; println!("x={}", x.get()); let y = x.wrap(); } diff --git a/src/test/run-pass/object-safety-sized-self-by-value-self.rs b/src/test/run-pass/object-safety-sized-self-by-value-self.rs new file mode 100644 index 0000000000..b735743927 --- /dev/null +++ b/src/test/run-pass/object-safety-sized-self-by-value-self.rs @@ -0,0 +1,48 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that a trait is still object-safe (and usable) if it has +// methods with by-value self so long as they require `Self : Sized`. + +// pretty-expanded FIXME #23616 + +trait Counter { + fn tick(&mut self) -> u32; + fn get(self) -> u32 where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn get(self) -> u32 where Self : Sized { self.c } +} + +fn tick1(mut c: C) -> u32 { + tick2(&mut c); + c.get() +} + +fn tick2(c: &mut Counter) { + tick3(c); +} + +fn tick3(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + let value = tick1(c); + assert_eq!(value, 2); +} diff --git a/src/test/run-pass/object-safety-sized-self-generic-method.rs b/src/test/run-pass/object-safety-sized-self-generic-method.rs new file mode 100644 index 0000000000..696c5a0970 --- /dev/null +++ b/src/test/run-pass/object-safety-sized-self-generic-method.rs @@ -0,0 +1,48 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that a trait is still object-safe (and usable) if it has +// generic methods so long as they require `Self : Sized`. + +// pretty-expanded FIXME #23616 + +trait Counter { + fn tick(&mut self) -> u32; + fn with(&self, f: F) where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn with(&self, f: F) { f(self.c); } +} + +fn tick1(c: &mut C) { + tick2(c); + c.with(|i| ()); +} + +fn tick2(c: &mut Counter) { + tick3(c); +} + +fn tick3(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + tick1(&mut c); + assert_eq!(c.tick(), 3); +} diff --git a/src/test/run-pass/object-safety-sized-self-return-Self.rs b/src/test/run-pass/object-safety-sized-self-return-Self.rs new file mode 100644 index 0000000000..17c41f2194 --- /dev/null +++ b/src/test/run-pass/object-safety-sized-self-return-Self.rs @@ -0,0 +1,49 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that a trait is still object-safe (and usable) if it has +// methods that return `Self` so long as they require `Self : Sized`. + +// pretty-expanded FIXME #23616 + +trait Counter { + fn new() -> Self where Self : Sized; + fn tick(&mut self) -> u32; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn new() -> CCounter { CCounter { c: 0 } } + fn tick(&mut self) -> u32 { self.c += 1; self.c } +} + +fn preticked() -> C { + let mut c: C = Counter::new(); + tick(&mut c); + c +} + +fn tick(c: &mut Counter) { + tick_generic(c); +} + +fn tick_generic(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = preticked::(); + tick(&mut c); + assert_eq!(c.tick(), 5); +} diff --git a/src/test/run-pass/objects-coerce-freeze-borrored.rs b/src/test/run-pass/objects-coerce-freeze-borrored.rs index 998af27c33..686924a314 100644 --- a/src/test/run-pass/objects-coerce-freeze-borrored.rs +++ b/src/test/run-pass/objects-coerce-freeze-borrored.rs @@ -10,17 +10,19 @@ // Test that we can coerce an `@Object` to an `&Object` +// pretty-expanded FIXME #23616 + trait Foo { - fn foo(&self) -> uint; - fn bar(&mut self) -> uint; + fn foo(&self) -> usize; + fn bar(&mut self) -> usize; } -impl Foo for uint { - fn foo(&self) -> uint { +impl Foo for usize { + fn foo(&self) -> usize { *self } - fn bar(&mut self) -> uint { + fn bar(&mut self) -> usize { *self += 1; *self } @@ -34,15 +36,15 @@ fn do_it_mut(obj: &mut Foo) { do_it_imm(obj, y); } -fn do_it_imm(obj: &Foo, v: uint) { +fn do_it_imm(obj: &Foo, v: usize) { let y = obj.foo(); assert_eq!(v, y); } pub fn main() { - let mut x = 22_usize; + let mut x: usize = 22; let obj = &mut x as &mut Foo; do_it_mut(obj); - do_it_imm(obj, 23_usize); + do_it_imm(obj, 23); do_it_mut(obj); } diff --git a/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs index 30a8c270bd..9a1cdd2922 100644 --- a/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs +++ b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs @@ -12,20 +12,22 @@ // closed over do not contain managed values, and thus the boxes do // not have headers. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait FooTrait { - fn foo(&self) -> uint; + fn foo(&self) -> usize; } struct BarStruct { - x: uint + x: usize } impl FooTrait for BarStruct { - fn foo(&self) -> uint { + fn foo(&self) -> usize { self.x } } @@ -37,7 +39,7 @@ pub fn main() { box BarStruct{ x: 2 } as Box ); - for i in 0_usize..foos.len() { + for i in 0..foos.len() { assert_eq!(i, foos[i].foo()); } } diff --git a/src/test/run-pass/objects-owned-object-owned-method.rs b/src/test/run-pass/objects-owned-object-owned-method.rs index d355999c50..4357adbf65 100644 --- a/src/test/run-pass/objects-owned-object-owned-method.rs +++ b/src/test/run-pass/objects-owned-object-owned-method.rs @@ -12,19 +12,21 @@ // closed over contain managed values. This implies that the boxes // will have headers that must be skipped over. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait FooTrait { - fn foo(self: Box) -> uint; + fn foo(self: Box) -> usize; } struct BarStruct { - x: uint + x: usize } impl FooTrait for BarStruct { - fn foo(self: Box) -> uint { + fn foo(self: Box) -> usize { self.x } } diff --git a/src/test/run-pass/once-move-out-on-heap.rs b/src/test/run-pass/once-move-out-on-heap.rs index 8fe57a655a..7bf8b693d9 100644 --- a/src/test/run-pass/once-move-out-on-heap.rs +++ b/src/test/run-pass/once-move-out-on-heap.rs @@ -11,6 +11,8 @@ // Testing guarantees provided by once functions. +// pretty-expanded FIXME #23616 + use std::sync::Arc; fn foo(blk: F) { diff --git a/src/test/run-pass/one-tuple.rs b/src/test/run-pass/one-tuple.rs index 8377a45a1d..6520e42dbe 100644 --- a/src/test/run-pass/one-tuple.rs +++ b/src/test/run-pass/one-tuple.rs @@ -10,6 +10,8 @@ // Why one-tuples? Because macros. +// pretty-expanded FIXME #23616 + pub fn main() { match ('c',) { (x,) => { diff --git a/src/test/run-pass/opeq.rs b/src/test/run-pass/opeq.rs index 3f00cf7d18..f5f0928ff1 100644 --- a/src/test/run-pass/opeq.rs +++ b/src/test/run-pass/opeq.rs @@ -12,7 +12,7 @@ pub fn main() { - let mut x: int = 1; + let mut x: isize = 1; x *= 2; println!("{}", x); assert_eq!(x, 2); diff --git a/src/test/run-pass/operator-associativity.rs b/src/test/run-pass/operator-associativity.rs index bee6d23a27..ccfdb83ab8 100644 --- a/src/test/run-pass/operator-associativity.rs +++ b/src/test/run-pass/operator-associativity.rs @@ -12,4 +12,6 @@ // Testcase for issue #130, operator associativity. +// pretty-expanded FIXME #23616 + pub fn main() { assert!((3 * 5 / 2 == 7)); } diff --git a/src/test/run-pass/operator-multidispatch.rs b/src/test/run-pass/operator-multidispatch.rs index 4ce6fcee8c..af7deef11b 100644 --- a/src/test/run-pass/operator-multidispatch.rs +++ b/src/test/run-pass/operator-multidispatch.rs @@ -15,8 +15,8 @@ use std::ops; #[derive(Debug,PartialEq,Eq)] struct Point { - x: int, - y: int + x: isize, + y: isize } impl ops::Add for Point { @@ -27,10 +27,10 @@ impl ops::Add for Point { } } -impl ops::Add for Point { +impl ops::Add for Point { type Output = Point; - fn add(self, other: int) -> Point { + fn add(self, other: isize) -> Point { Point {x: self.x + other, y: self.y + other} } diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index 3ddc666cd3..045af79189 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + use std::cmp; use std::ops; -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] struct Point { - x: int, - y: int + x: isize, + y: isize } impl ops::Add for Point { @@ -50,10 +52,10 @@ impl ops::Not for Point { } impl ops::Index for Point { - type Output = int; + type Output = isize; - fn index(&self, x: &bool) -> &int { - if *x { + fn index(&self, x: bool) -> &isize { + if x { &self.x } else { &self.y @@ -85,4 +87,4 @@ pub fn main() { result(p[true]); } -fn result(i: int) { } +fn result(i: isize) { } diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 7a816f9133..03ba6097cd 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(collections)] + pub fn main() { let thing = "{{ f }}"; - let f = thing.find_str("{{"); + let f = thing.find("{{"); if f.is_none() { println!("None!"); diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs index 71323016e8..4902038667 100644 --- a/src/test/run-pass/option-unwrap.rs +++ b/src/test/run-pass/option-unwrap.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] use std::cell::Cell; struct dtor<'a> { - x: &'a Cell, + x: &'a Cell, } #[unsafe_destructor] diff --git a/src/test/run-pass/or-pattern.rs b/src/test/run-pass/or-pattern.rs index 654d2429a0..3ab78e8d05 100644 --- a/src/test/run-pass/or-pattern.rs +++ b/src/test/run-pass/or-pattern.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum blah { a(int, int, uint), b(int, int), c, } +// pretty-expanded FIXME #23616 -fn or_alt(q: blah) -> int { +enum blah { a(isize, isize, usize), b(isize, isize), c, } + +fn or_alt(q: blah) -> isize { match q { blah::a(x, y, _) | blah::b(x, y) => { return x + y; } blah::c => { return 0; } } } pub fn main() { assert_eq!(or_alt(blah::c), 0); - assert_eq!(or_alt(blah::a(10, 100, 0_usize)), 110); + assert_eq!(or_alt(blah::a(10, 100, 0)), 110); assert_eq!(or_alt(blah::b(20, 200)), 220); } diff --git a/src/test/run-pass/order-drop-with-match.rs b/src/test/run-pass/order-drop-with-match.rs index 3710f1b9d3..c8a2ba0af4 100644 --- a/src/test/run-pass/order-drop-with-match.rs +++ b/src/test/run-pass/order-drop-with-match.rs @@ -14,8 +14,10 @@ // in ORDER matching up to when it ran. // Correct order is: matched, inner, outer -static mut ORDER: [uint; 3] = [0, 0, 0]; -static mut INDEX: uint = 0; +// pretty-expanded FIXME #23616 + +static mut ORDER: [usize; 3] = [0, 0, 0]; +static mut INDEX: usize = 0; struct A; impl Drop for A { diff --git a/src/test/run-pass/osx-frameworks.rs b/src/test/run-pass/osx-frameworks.rs index aa4e91320f..41b34dc79b 100644 --- a/src/test/run-pass/osx-frameworks.rs +++ b/src/test/run-pass/osx-frameworks.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; #[cfg(target_os = "macos")] diff --git a/src/test/run-pass/out-of-stack-new-thread-no-split.rs b/src/test/run-pass/out-of-stack-new-thread-no-split.rs index f574259c37..f08ed6e7f9 100644 --- a/src/test/run-pass/out-of-stack-new-thread-no-split.rs +++ b/src/test/run-pass/out-of-stack-new-thread-no-split.rs @@ -12,12 +12,13 @@ //ignore-freebsd //ignore-ios //ignore-dragonfly +//ignore-bitrig -#![feature(asm)] +#![feature(asm, old_io, std_misc)] use std::old_io::process::Command; use std::env; -use std::thread::Thread; +use std::thread; // lifted from the test module // Inlining to avoid llvm turning the recursive functions into tail calls, @@ -36,7 +37,7 @@ fn recurse() { fn main() { let args: Vec = env::args().collect(); if args.len() > 1 && args[1] == "recurse" { - let _t = Thread::scoped(recurse); + let _t = thread::scoped(recurse); } else { let recurse = Command::new(&args[0]).arg("recurse").output().unwrap(); assert!(!recurse.status.success()); diff --git a/src/test/run-pass/out-of-stack-no-split.rs b/src/test/run-pass/out-of-stack-no-split.rs index 948c4d064d..8887e1937c 100644 --- a/src/test/run-pass/out-of-stack-no-split.rs +++ b/src/test/run-pass/out-of-stack-no-split.rs @@ -13,8 +13,9 @@ //ignore-freebsd //ignore-ios //ignore-dragonfly +//ignore-bitrig -#![feature(asm)] +#![feature(asm, old_io)] use std::old_io::process::Command; use std::env; diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index cc5eb69bb8..47f83eab4c 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -10,7 +10,7 @@ // ignore-android: FIXME (#20004) -#![feature(asm)] +#![feature(asm, old_io)] use std::old_io::process::Command; use std::env; diff --git a/src/test/run-pass/out-pointer-aliasing.rs b/src/test/run-pass/out-pointer-aliasing.rs index eee9838da2..0a58411041 100644 --- a/src/test/run-pass/out-pointer-aliasing.rs +++ b/src/test/run-pass/out-pointer-aliasing.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] pub struct Foo { - f1: int, - _f2: int, + f1: isize, + _f2: isize, } #[inline(never)] diff --git a/src/test/run-pass/output-slot-variants.rs b/src/test/run-pass/output-slot-variants.rs index fb87cd5eb6..33489688d4 100644 --- a/src/test/run-pass/output-slot-variants.rs +++ b/src/test/run-pass/output-slot-variants.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] #![allow(unknown_features)] #![feature(box_syntax)] -struct A { a: int, b: int } -struct Abox { a: Box, b: Box } +struct A { a: isize, b: isize } +struct Abox { a: Box, b: Box } -fn ret_int_i() -> int { 10 } +fn ret_int_i() -> isize { 10 } -fn ret_ext_i() -> Box { box 10 } +fn ret_ext_i() -> Box { box 10 } fn ret_int_rec() -> A { A {a: 10, b: 10} } @@ -29,8 +31,8 @@ fn ret_ext_mem() -> Abox { Abox {a: box 10, b: box 10} } fn ret_ext_ext_mem() -> Box { box Abox{a: box 10, b: box 10} } pub fn main() { - let mut int_i: int; - let mut ext_i: Box; + let mut int_i: isize; + let mut ext_i: Box; let mut int_rec: A; let mut ext_rec: Box; let mut ext_mem: Abox; diff --git a/src/test/run-pass/over-constrained-vregs.rs b/src/test/run-pass/over-constrained-vregs.rs index 1118638fe0..e4e0794147 100644 --- a/src/test/run-pass/over-constrained-vregs.rs +++ b/src/test/run-pass/over-constrained-vregs.rs @@ -10,8 +10,8 @@ // Regression test for issue #152. pub fn main() { - let mut b: uint = 1_usize; - while b <= 32_usize { + let mut b: usize = 1_usize; + while b < std::mem::size_of::() { 0_usize << b; b <<= 1_usize; println!("{}", b); diff --git a/src/test/run-pass/overloaded-autoderef-count.rs b/src/test/run-pass/overloaded-autoderef-count.rs index cc36b625c3..14a9cc4c24 100644 --- a/src/test/run-pass/overloaded-autoderef-count.rs +++ b/src/test/run-pass/overloaded-autoderef-count.rs @@ -13,8 +13,8 @@ use std::ops::{Deref, DerefMut}; #[derive(PartialEq)] struct DerefCounter { - count_imm: Cell, - count_mut: uint, + count_imm: Cell, + count_mut: usize, value: T } @@ -27,7 +27,7 @@ impl DerefCounter { } } - fn counts(&self) -> (uint, uint) { + fn counts(&self) -> (usize, usize) { (self.count_imm.get(), self.count_mut) } } @@ -50,12 +50,12 @@ impl DerefMut for DerefCounter { #[derive(PartialEq, Debug)] struct Point { - x: int, - y: int + x: isize, + y: isize } impl Point { - fn get(&self) -> (int, int) { + fn get(&self) -> (isize, isize) { (self.x, self.y) } } diff --git a/src/test/run-pass/overloaded-autoderef-indexing.rs b/src/test/run-pass/overloaded-autoderef-indexing.rs index 4cb7ece4ab..fdf42423b6 100644 --- a/src/test/run-pass/overloaded-autoderef-indexing.rs +++ b/src/test/run-pass/overloaded-autoderef-indexing.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ops::Deref; struct DerefArray<'a, T:'a> { diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs index d023a01f4b..6880032e69 100644 --- a/src/test/run-pass/overloaded-autoderef-order.rs +++ b/src/test/run-pass/overloaded-autoderef-order.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::rc::Rc; use std::ops::Deref; -#[derive(Copy)] +#[derive(Copy, Clone)] struct DerefWrapper { x: X, y: Y @@ -34,7 +36,7 @@ impl Deref for DerefWrapper { mod priv_test { use std::ops::Deref; - #[derive(Copy)] + #[derive(Copy, Clone)] pub struct DerefWrapperHideX { x: X, pub y: Y diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs index d50f2efe0e..38bf68b746 100644 --- a/src/test/run-pass/overloaded-autoderef-vtable.rs +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ops::Deref; struct DerefWithHelper { @@ -33,10 +35,10 @@ impl> Deref for DerefWithHelper { } } -struct Foo {x: int} +struct Foo {x: isize} impl Foo { - fn foo(&self) -> int {self.x} + fn foo(&self) -> isize {self.x} } pub fn main() { diff --git a/src/test/run-pass/overloaded-autoderef-xcrate.rs b/src/test/run-pass/overloaded-autoderef-xcrate.rs index f8dd729ec6..b97fb49112 100644 --- a/src/test/run-pass/overloaded-autoderef-xcrate.rs +++ b/src/test/run-pass/overloaded-autoderef-xcrate.rs @@ -10,6 +10,8 @@ // aux-build:overloaded_autoderef_xc.rs +// pretty-expanded FIXME #23616 + extern crate overloaded_autoderef_xc; fn main() { diff --git a/src/test/run-pass/overloaded-autoderef.rs b/src/test/run-pass/overloaded-autoderef.rs index f40c9dc45c..ddd6ae4d0a 100644 --- a/src/test/run-pass/overloaded-autoderef.rs +++ b/src/test/run-pass/overloaded-autoderef.rs @@ -9,7 +9,7 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, collections, core)] use std::cell::RefCell; use std::rc::Rc; @@ -17,14 +17,15 @@ use std::num::ToPrimitive; #[derive(PartialEq, Debug)] struct Point { - x: int, - y: int + x: isize, + y: isize } pub fn main() { - let box_5 = box 5_usize; + let box_5: Box<_> = box 5_usize; assert_eq!(Rc::new(5_usize).to_uint(), Some(5)); - assert_eq!((box &box &Rc::new(box box &box_5)).to_uint(), Some(5)); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + assert_eq!((Box::new(&Box::new(&Rc::new(Box::new(Box::new(&box_5)))))).to_uint(), Some(5)); let point = Rc::new(Point {x: 2, y: 4}); assert_eq!(point.x, 2); assert_eq!(point.y, 4); diff --git a/src/test/run-pass/overloaded-calls-object-one-arg.rs b/src/test/run-pass/overloaded-calls-object-one-arg.rs index 25b63cd14c..291d2c6498 100644 --- a/src/test/run-pass/overloaded-calls-object-one-arg.rs +++ b/src/test/run-pass/overloaded-calls-object-one-arg.rs @@ -11,7 +11,9 @@ // 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 { +// pretty-expanded FIXME #23616 + +fn foo(f: &mut FnMut(isize) -> isize) -> isize { f(22) } diff --git a/src/test/run-pass/overloaded-calls-object-two-args.rs b/src/test/run-pass/overloaded-calls-object-two-args.rs index 026ebc3084..42c71572a3 100644 --- a/src/test/run-pass/overloaded-calls-object-two-args.rs +++ b/src/test/run-pass/overloaded-calls-object-two-args.rs @@ -11,7 +11,9 @@ // 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 { +// pretty-expanded FIXME #23616 + +fn foo(f: &mut FnMut(isize, isize) -> isize) -> isize { f(1, 2) } diff --git a/src/test/run-pass/overloaded-calls-object-zero-args.rs b/src/test/run-pass/overloaded-calls-object-zero-args.rs index b38f8213b4..9bc6c9f042 100644 --- a/src/test/run-pass/overloaded-calls-object-zero-args.rs +++ b/src/test/run-pass/overloaded-calls-object-zero-args.rs @@ -11,7 +11,9 @@ // 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 { +// pretty-expanded FIXME #23616 + +fn foo(f: &mut FnMut() -> isize) -> isize { f() } diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index 2ef9e08134..597075c550 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -10,7 +10,9 @@ // Tests that nested vtables work with overloaded calls. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::marker::PhantomData; use std::ops::Fn; @@ -19,14 +21,21 @@ use std::ops::Add; struct G(PhantomData); impl<'a, A: Add> Fn<(A,)> for G { - type Output = i32; - extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 { arg.add(1) } } +impl<'a, A: Add> FnMut<(A,)> for G { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { self.call(args) } +} + +impl<'a, A: Add> FnOnce<(A,)> for G { + type Output = i32; + extern "rust-call" fn call_once(self, args: (A,)) -> i32 { self.call(args) } +} + fn main() { // ICE trigger - (G(PhantomData))(1_i32); + (G(PhantomData))(1); } diff --git a/src/test/run-pass/overloaded-calls-simple.rs b/src/test/run-pass/overloaded-calls-simple.rs index f9e838d9b3..eeb705a2e3 100644 --- a/src/test/run-pass/overloaded-calls-simple.rs +++ b/src/test/run-pass/overloaded-calls-simple.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(lang_items, unboxed_closures, core)] use std::ops::{Fn, FnMut, FnOnce}; @@ -18,24 +20,38 @@ struct S1 { } impl FnMut<(i32,)> for S1 { - type Output = i32; extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 { self.x * self.y * z } } +impl FnOnce<(i32,)> for S1 { + type Output = i32; + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { + self.call_mut(args) + } +} + struct S2 { x: i32, y: i32, } impl Fn<(i32,)> for S2 { - type Output = i32; extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 { self.x * self.y * z } } +impl FnMut<(i32,)> for S2 { + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } +} + +impl FnOnce<(i32,)> for S2 { + type Output = i32; + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } +} + struct S3 { x: i32, y: i32, @@ -70,4 +86,3 @@ fn main() { let ans = s(3, 1); assert_eq!(ans, 27); } - diff --git a/src/test/run-pass/overloaded-calls-zero-args.rs b/src/test/run-pass/overloaded-calls-zero-args.rs index ce7395673b..8df4adf671 100644 --- a/src/test/run-pass/overloaded-calls-zero-args.rs +++ b/src/test/run-pass/overloaded-calls-zero-args.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 -use std::ops::{FnMut}; +#![feature(unboxed_closures, core)] + +use std::ops::FnMut; struct S { x: i32, @@ -18,12 +20,16 @@ struct S { } impl FnMut<()> for S { - type Output = i32; extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 { self.x * self.y } } +impl FnOnce<()> for S { + type Output = i32; + extern "rust-call" fn call_once(mut self, args: ()) -> i32 { self.call_mut(args) } +} + fn main() { let mut s = S { x: 3, @@ -32,5 +38,3 @@ fn main() { let ans = s(); assert_eq!(ans, 9); } - - diff --git a/src/test/run-pass/overloaded-deref-count.rs b/src/test/run-pass/overloaded-deref-count.rs index f3091b53e8..5f6eb87ae1 100644 --- a/src/test/run-pass/overloaded-deref-count.rs +++ b/src/test/run-pass/overloaded-deref-count.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::cell::Cell; use std::ops::{Deref, DerefMut}; use std::vec::Vec; struct DerefCounter { - count_imm: Cell, - count_mut: uint, + count_imm: Cell, + count_mut: usize, value: T } @@ -27,7 +29,7 @@ impl DerefCounter { } } - fn counts(&self) -> (uint, uint) { + fn counts(&self) -> (usize, usize) { (self.count_imm.get(), self.count_mut) } } diff --git a/src/test/run-pass/overloaded-deref.rs b/src/test/run-pass/overloaded-deref.rs index f56e7d56fe..6d8bb30c83 100644 --- a/src/test/run-pass/overloaded-deref.rs +++ b/src/test/run-pass/overloaded-deref.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(collections)] use std::cell::RefCell; use std::rc::Rc; @@ -17,13 +16,13 @@ use std::string::String; #[derive(PartialEq, Debug)] struct Point { - x: int, - y: int + x: isize, + y: isize } pub fn main() { assert_eq!(*Rc::new(5), 5); - assert_eq!(***Rc::new(box box 5), 5); + assert_eq!(***Rc::new(Box::new(Box::new(5))), 5); assert_eq!(*Rc::new(Point {x: 2, y: 4}), Point {x: 2, y: 4}); let i = Rc::new(RefCell::new(2)); diff --git a/src/test/run-pass/overloaded-index-assoc-list.rs b/src/test/run-pass/overloaded-index-assoc-list.rs index 0064748e88..131098d7c9 100644 --- a/src/test/run-pass/overloaded-index-assoc-list.rs +++ b/src/test/run-pass/overloaded-index-assoc-list.rs @@ -11,6 +11,10 @@ // Test overloading of the `[]` operator. In particular test that it // takes its argument *by reference*. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::ops::Index; struct AssociationList { @@ -28,7 +32,7 @@ impl AssociationList { } } -impl Index for AssociationList { +impl<'a, K: PartialEq + std::fmt::Debug, V:Clone> Index<&'a K> for AssociationList { type Output = V; fn index<'a>(&'a self, index: &K) -> &'a V { @@ -49,9 +53,9 @@ pub fn main() { list.push(foo.clone(), 22); list.push(bar.clone(), 44); - assert!(list[foo] == 22); - assert!(list[bar] == 44); + assert!(list[&foo] == 22); + assert!(list[&bar] == 44); - assert!(list[foo] == 22); - assert!(list[bar] == 44); + assert!(list[&foo] == 22); + assert!(list[&bar] == 44); } diff --git a/src/test/run-pass/overloaded-index-autoderef.rs b/src/test/run-pass/overloaded-index-autoderef.rs index d5ccf8cd2b..56d71edd56 100644 --- a/src/test/run-pass/overloaded-index-autoderef.rs +++ b/src/test/run-pass/overloaded-index-autoderef.rs @@ -10,21 +10,23 @@ // Test overloaded indexing combined with autoderef. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, core)] use std::ops::{Index, IndexMut}; struct Foo { - x: int, - y: int, + x: isize, + y: isize, } -impl Index for Foo { - type Output = int; +impl Index for Foo { + type Output = isize; - fn index(&self, z: &int) -> &int { - if *z == 0 { + fn index(&self, z: isize) -> &isize { + if z == 0 { &self.x } else { &self.y @@ -32,9 +34,9 @@ impl Index for Foo { } } -impl IndexMut for Foo { - fn index_mut(&mut self, z: &int) -> &mut int { - if *z == 0 { +impl IndexMut for Foo { + fn index_mut(&mut self, z: isize) -> &mut isize { + if z == 0 { &mut self.x } else { &mut self.y @@ -43,19 +45,19 @@ impl IndexMut for Foo { } trait Int { - fn get(self) -> int; - fn get_from_ref(&self) -> int; + fn get(self) -> isize; + fn get_from_ref(&self) -> isize; fn inc(&mut self); } -impl Int for int { - fn get(self) -> int { self } - fn get_from_ref(&self) -> int { *self } +impl Int for isize { + fn get(self) -> isize { self } + fn get_from_ref(&self) -> isize { *self } fn inc(&mut self) { *self += 1; } } fn main() { - let mut f = box Foo { + let mut f: Box<_> = box Foo { x: 1, y: 2, }; diff --git a/src/test/run-pass/overloaded-index-in-field.rs b/src/test/run-pass/overloaded-index-in-field.rs index 487fb93c9f..bc53836aca 100644 --- a/src/test/run-pass/overloaded-index-in-field.rs +++ b/src/test/run-pass/overloaded-index-in-field.rs @@ -11,22 +11,26 @@ // Test using overloaded indexing when the "map" is stored in a // field. This caused problems at some point. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::ops::Index; struct Foo { - x: int, - y: int, + x: isize, + y: isize, } struct Bar { foo: Foo } -impl Index for Foo { - type Output = int; +impl Index for Foo { + type Output = isize; - fn index(&self, z: &int) -> &int { - if *z == 0 { + fn index(&self, z: isize) -> &isize { + if z == 0 { &self.x } else { &self.y @@ -35,14 +39,14 @@ impl Index for Foo { } trait Int { - fn get(self) -> int; - fn get_from_ref(&self) -> int; + fn get(self) -> isize; + fn get_from_ref(&self) -> isize; fn inc(&mut self); } -impl Int for int { - fn get(self) -> int { self } - fn get_from_ref(&self) -> int { *self } +impl Int for isize { + fn get(self) -> isize { self } + fn get_from_ref(&self) -> isize { *self } fn inc(&mut self) { *self += 1; } } diff --git a/src/test/run-pass/overloaded-index.rs b/src/test/run-pass/overloaded-index.rs index 10ca3804ea..4f8cf0e9e3 100644 --- a/src/test/run-pass/overloaded-index.rs +++ b/src/test/run-pass/overloaded-index.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::ops::{Index, IndexMut}; struct Foo { - x: int, - y: int, + x: isize, + y: isize, } -impl Index for Foo { - type Output = int; +impl Index for Foo { + type Output = isize; - fn index(&self, z: &int) -> &int { - if *z == 0 { + fn index(&self, z: isize) -> &isize { + if z == 0 { &self.x } else { &self.y @@ -27,9 +31,9 @@ impl Index for Foo { } } -impl IndexMut for Foo { - fn index_mut(&mut self, z: &int) -> &mut int { - if *z == 0 { +impl IndexMut for Foo { + fn index_mut(&mut self, z: isize) -> &mut isize { + if z == 0 { &mut self.x } else { &mut self.y @@ -38,14 +42,14 @@ impl IndexMut for Foo { } trait Int { - fn get(self) -> int; - fn get_from_ref(&self) -> int; + fn get(self) -> isize; + fn get_from_ref(&self) -> isize; fn inc(&mut self); } -impl Int for int { - fn get(self) -> int { self } - fn get_from_ref(&self) -> int { *self } +impl Int for isize { + fn get(self) -> isize { self } + fn get_from_ref(&self) -> isize { *self } fn inc(&mut self) { *self += 1; } } diff --git a/src/test/run-pass/owned-implies-static.rs b/src/test/run-pass/owned-implies-static.rs index 2db6f7ffaa..f698b66075 100644 --- a/src/test/run-pass/owned-implies-static.rs +++ b/src/test/run-pass/owned-implies-static.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 fn f(_x: T) {} pub fn main() { - f(box 5); + f(Box::new(5)); } diff --git a/src/test/run-pass/packed-struct-borrow-element.rs b/src/test/run-pass/packed-struct-borrow-element.rs index c6c74fe3fd..8819b20136 100644 --- a/src/test/run-pass/packed-struct-borrow-element.rs +++ b/src/test/run-pass/packed-struct-borrow-element.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[repr(packed)] struct Foo { bar: u8, - baz: uint + baz: usize } pub fn main() { diff --git a/src/test/run-pass/packed-struct-generic-layout.rs b/src/test/run-pass/packed-struct-generic-layout.rs index 004a302201..5d518749d9 100644 --- a/src/test/run-pass/packed-struct-generic-layout.rs +++ b/src/test/run-pass/packed-struct-generic-layout.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed-struct-generic-size.rs b/src/test/run-pass/packed-struct-generic-size.rs index 45791332bb..6c24b71971 100644 --- a/src/test/run-pass/packed-struct-generic-size.rs +++ b/src/test/run-pass/packed-struct-generic-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs index 9e94502a92..5d2454be2f 100644 --- a/src/test/run-pass/packed-struct-layout.rs +++ b/src/test/run-pass/packed-struct-layout.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed-struct-match.rs b/src/test/run-pass/packed-struct-match.rs index 46ffed0cba..3c3d632222 100644 --- a/src/test/run-pass/packed-struct-match.rs +++ b/src/test/run-pass/packed-struct-match.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #[repr(packed)] struct Foo { bar: u8, - baz: uint + baz: usize } pub fn main() { diff --git a/src/test/run-pass/packed-struct-size-xc.rs b/src/test/run-pass/packed-struct-size-xc.rs index c296895678..b7ea720caf 100644 --- a/src/test/run-pass/packed-struct-size-xc.rs +++ b/src/test/run-pass/packed-struct-size-xc.rs @@ -10,6 +10,8 @@ // aux-build:packed.rs +// pretty-expanded FIXME #23616 + extern crate packed; use std::mem; diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs index 846d51e2e7..3d748c4042 100644 --- a/src/test/run-pass/packed-struct-size.rs +++ b/src/test/run-pass/packed-struct-size.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs index cfe49c38c5..9a327eb567 100644 --- a/src/test/run-pass/packed-struct-vec.rs +++ b/src/test/run-pass/packed-struct-vec.rs @@ -13,7 +13,7 @@ use std::mem; #[repr(packed)] -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] struct Foo { bar: u8, baz: u64 @@ -24,7 +24,7 @@ pub fn main() { assert_eq!(mem::size_of::<[Foo; 10]>(), 90); - for i in 0_usize..10 { + for i in 0..10 { assert_eq!(foos[i], Foo { bar: 1, baz: 2}); } diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs index c41d678b0f..9d96adc29d 100644 --- a/src/test/run-pass/packed-tuple-struct-layout.rs +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs index a0b88ea53c..7b7cd59298 100644 --- a/src/test/run-pass/packed-tuple-struct-size.rs +++ b/src/test/run-pass/packed-tuple-struct-size.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/panic-in-dtor-drops-fields.rs b/src/test/run-pass/panic-in-dtor-drops-fields.rs index 6da15b97ac..4226fba9d3 100644 --- a/src/test/run-pass/panic-in-dtor-drops-fields.rs +++ b/src/test/run-pass/panic-in-dtor-drops-fields.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::thread; static mut dropped: bool = false; @@ -17,7 +19,7 @@ struct A { } struct B { - foo: int, + foo: isize, } impl Drop for A { diff --git a/src/test/run-pass/parameterized-trait-with-bounds.rs b/src/test/run-pass/parameterized-trait-with-bounds.rs index 061c916895..3e74341d81 100644 --- a/src/test/run-pass/parameterized-trait-with-bounds.rs +++ b/src/test/run-pass/parameterized-trait-with-bounds.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] @@ -21,7 +23,7 @@ mod foo { fn foo1(_: &(A + Send)) {} fn foo2(_: Box + Send + Sync>) {} -fn foo3(_: Box + 'static>) {} +fn foo3(_: Box + 'static>) {} fn foo4<'a, T>(_: Box + 'static + Send>) {} fn foo5<'a, T>(_: Box + 'static + Send>) {} diff --git a/src/test/run-pass/parse-assoc-type-lt.rs b/src/test/run-pass/parse-assoc-type-lt.rs index 5649c4c784..c816772205 100644 --- a/src/test/run-pass/parse-assoc-type-lt.rs +++ b/src/test/run-pass/parse-assoc-type-lt.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { type T; fn foo() -> Box<::T>; diff --git a/src/test/run-pass/parse-complex-macro-invoc-op.rs b/src/test/run-pass/parse-complex-macro-invoc-op.rs index 0995910fd4..e4c9fd9d8e 100644 --- a/src/test/run-pass/parse-complex-macro-invoc-op.rs +++ b/src/test/run-pass/parse-complex-macro-invoc-op.rs @@ -10,6 +10,8 @@ // Test parsing binary operators after macro invocations. +// pretty-expanded FIXME #23616 + #![feature(macro_rules)] macro_rules! id { diff --git a/src/test/run-pass/path.rs b/src/test/run-pass/path.rs index 02d8602d59..fddc2744eb 100644 --- a/src/test/run-pass/path.rs +++ b/src/test/run-pass/path.rs @@ -10,8 +10,10 @@ +// pretty-expanded FIXME #23616 + mod foo { - pub fn bar(_offset: uint) { } + pub fn bar(_offset: usize) { } } -pub fn main() { foo::bar(0_usize); } +pub fn main() { foo::bar(0); } diff --git a/src/test/run-pass/pattern-bound-var-in-for-each.rs b/src/test/run-pass/pattern-bound-var-in-for-each.rs index 7d9c3d324f..1ab578b933 100644 --- a/src/test/run-pass/pattern-bound-var-in-for-each.rs +++ b/src/test/run-pass/pattern-bound-var-in-for-each.rs @@ -12,7 +12,9 @@ // pattern-bound var is an upvar (when translating // the for-each body) -fn foo(src: uint) { +// pretty-expanded FIXME #23616 + +fn foo(src: usize) { match Some(src) { Some(src_id) => { diff --git a/src/test/run-pass/pattern-in-closure.rs b/src/test/run-pass/pattern-in-closure.rs index e4f1df2d63..909ed985d7 100644 --- a/src/test/run-pass/pattern-in-closure.rs +++ b/src/test/run-pass/pattern-in-closure.rs @@ -9,12 +9,12 @@ // except according to those terms. struct Foo { - x: int, - y: int + x: isize, + y: isize } pub fn main() { - let f = |(x, _): (int, int)| println!("{}", x + 1); + let f = |(x, _): (isize, isize)| println!("{}", x + 1); let g = |Foo { x: x, y: _y }: Foo| println!("{}", x + 1); f((2, 3)); g(Foo { x: 1, y: 2 }); diff --git a/src/test/run-pass/placement-new-arena.rs b/src/test/run-pass/placement-new-arena.rs index 7ad93d271a..7ac624e681 100644 --- a/src/test/run-pass/placement-new-arena.rs +++ b/src/test/run-pass/placement-new-arena.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_private)] + extern crate arena; use arena::Arena; diff --git a/src/test/run-pass/pred-not-bool.rs b/src/test/run-pass/pred-not-bool.rs index 15bf05fc0c..f0f3d3d7bd 100644 --- a/src/test/run-pass/pred-not-bool.rs +++ b/src/test/run-pass/pred-not-bool.rs @@ -11,6 +11,8 @@ // this checks that a pred with a non-bool return // type is rejected, even if the pred is never used -fn bad(_a: int) -> int { return 37; } //~ ERROR Non-boolean return type +// pretty-expanded FIXME #23616 + +fn bad(_a: isize) -> isize { return 37; } //~ ERROR Non-boolean return type pub fn main() { } diff --git a/src/test/run-pass/preempt.rs b/src/test/run-pass/preempt.rs index bcfc39ee7e..7e5e41820e 100644 --- a/src/test/run-pass/preempt.rs +++ b/src/test/run-pass/preempt.rs @@ -14,11 +14,11 @@ // note: halfway done porting to modern rust use std::comm; -fn starve_main(alive: Receiver) { +fn starve_main(alive: Receiver) { println!("signalling main"); alive.recv(); println!("starving main"); - let mut i: int = 0; + let mut i: isize = 0; loop { i += 1; } } @@ -29,7 +29,7 @@ pub fn main() { spawn(move|| { starve_main(port); }); - let mut i: int = 0; + let mut i: isize = 0; println!("main waiting for alive signal"); chan.send(i); println!("main got alive signal"); diff --git a/src/test/run-pass/priv-impl-prim-ty.rs b/src/test/run-pass/priv-impl-prim-ty.rs index 679aa3d668..aa2db260dd 100644 --- a/src/test/run-pass/priv-impl-prim-ty.rs +++ b/src/test/run-pass/priv-impl-prim-ty.rs @@ -10,7 +10,9 @@ // aux-build:priv-impl-prim-ty.rs -extern crate "priv-impl-prim-ty" as bar; +// pretty-expanded FIXME #23616 + +extern crate priv_impl_prim_ty as bar; pub fn main() { bar::frob(1); diff --git a/src/test/run-pass/privacy-ns.rs b/src/test/run-pass/privacy-ns.rs index e9b8e694d6..8082816c43 100644 --- a/src/test/run-pass/privacy-ns.rs +++ b/src/test/run-pass/privacy-ns.rs @@ -12,6 +12,8 @@ // Check we do the correct privacy checks when we import a name and there is an // item with that name in both the value and type namespaces. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] #![allow(unused_imports)] diff --git a/src/test/run-pass/privacy-reexport.rs b/src/test/run-pass/privacy-reexport.rs index b40aacdafc..d9d107d900 100644 --- a/src/test/run-pass/privacy-reexport.rs +++ b/src/test/run-pass/privacy-reexport.rs @@ -10,6 +10,8 @@ // aux-build:privacy_reexport.rs +// pretty-expanded FIXME #23616 + extern crate privacy_reexport; pub fn main() { diff --git a/src/test/run-pass/privacy1.rs b/src/test/run-pass/privacy1.rs index 7a07c97090..329c4aaa87 100644 --- a/src/test/run-pass/privacy1.rs +++ b/src/test/run-pass/privacy1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub mod test2 { // This used to generate an ICE (make sure that default functions are // parented to their trait to find the first private thing as the trait). diff --git a/src/test/run-pass/private-class-field.rs b/src/test/run-pass/private-class-field.rs index c7380b362f..d32ac4b908 100644 --- a/src/test/run-pass/private-class-field.rs +++ b/src/test/run-pass/private-class-field.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, } impl cat { - pub fn meow_count(&mut self) -> uint { self.meows } + pub fn meow_count(&mut self) -> usize { self.meows } } -fn cat(in_x : uint, in_y : int) -> cat { +fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y @@ -26,6 +28,6 @@ fn cat(in_x : uint, in_y : int) -> cat { } pub fn main() { - let mut nyan : cat = cat(52_usize, 99); - assert_eq!(nyan.meow_count(), 52_usize); + let mut nyan : cat = cat(52, 99); + assert_eq!(nyan.meow_count(), 52); } diff --git a/src/test/run-pass/private-method.rs b/src/test/run-pass/private-method.rs index 498bd04e37..0d6e6010c5 100644 --- a/src/test/run-pass/private-method.rs +++ b/src/test/run-pass/private-method.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct cat { - meows : uint, + meows : usize, - how_hungry : int, + how_hungry : isize, } impl cat { @@ -25,7 +27,7 @@ impl cat { fn nap(&mut self) { for _ in 1_usize..10_usize { } } } -fn cat(in_x : uint, in_y : int) -> cat { +fn cat(in_x : usize, in_y : isize) -> cat { cat { meows: in_x, how_hungry: in_y diff --git a/src/test/run-pass/process-exit.rs b/src/test/run-pass/process-exit.rs new file mode 100644 index 0000000000..9ef66ff2d7 --- /dev/null +++ b/src/test/run-pass/process-exit.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::process::{self, Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + child(); + } else { + parent(); + } +} + +fn parent() { + let args: Vec = env::args().collect(); + let status = Command::new(&args[0]).arg("child").status().unwrap(); + assert_eq!(status.code(), Some(2)); +} + +fn child() -> i32 { + process::exit(2); +} diff --git a/src/test/run-pass/process-remove-from-env.rs b/src/test/run-pass/process-remove-from-env.rs index 9eb7d624c9..6429352f44 100644 --- a/src/test/run-pass/process-remove-from-env.rs +++ b/src/test/run-pass/process-remove-from-env.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io)] + use std::old_io::Command; use std::env; diff --git a/src/test/run-pass/process-spawn-with-unicode-params.rs b/src/test/run-pass/process-spawn-with-unicode-params.rs index 017784990f..32448d100f 100644 --- a/src/test/run-pass/process-spawn-with-unicode-params.rs +++ b/src/test/run-pass/process-spawn-with-unicode-params.rs @@ -16,30 +16,34 @@ // non-ASCII characters. The child process ensures all the strings are // intact. -use std::old_io; -use std::old_io::fs; -use std::old_io::Command; +// ignore-aarch64 +#![feature(path, fs, os, io, old_path)] + +use std::io::prelude::*; +use std::io; +use std::fs; +use std::process::Command; use std::os; use std::env; -use std::old_path::Path; +use std::path::{Path, PathBuf}; fn main() { let my_args = env::args().collect::>(); - let my_cwd = os::getcwd().unwrap(); + let my_cwd = env::current_dir().unwrap(); let my_env = env::vars().collect::>(); - let my_path = Path::new(os::self_exe_name().unwrap()); - let my_dir = my_path.dir_path(); - let my_ext = my_path.extension_str().unwrap_or(""); + let my_path = env::current_exe().unwrap(); + let my_dir = my_path.parent().unwrap(); + let my_ext = my_path.extension().and_then(|s| s.to_str()).unwrap_or(""); // some non-ASCII characters - let blah = "\u03c0\u042f\u97f3\u00e6\u221e"; + let blah = "\u{3c0}\u{42f}\u{97f3}\u{e6}\u{221e}"; let child_name = "child"; let child_dir = format!("process-spawn-with-unicode-params-{}", blah); // parameters sent to child / expected to be received from parent let arg = blah; - let cwd = my_dir.join(Path::new(child_dir.clone())); + let cwd = my_dir.join(&child_dir); let env = ("RUST_TEST_PROC_SPAWN_UNICODE".to_string(), blah.to_string()); // am I the parent or the child? @@ -47,24 +51,22 @@ fn main() { let child_filestem = Path::new(child_name); let child_filename = child_filestem.with_extension(my_ext); - let child_path = cwd.join(child_filename); + let child_path = cwd.join(&child_filename); // make a separate directory for the child - drop(fs::mkdir(&cwd, old_io::USER_RWX).is_ok()); - assert!(fs::copy(&my_path, &child_path).is_ok()); - let mut my_env = my_env; - my_env.push(env); + let _ = fs::create_dir(&cwd); + fs::copy(&my_path, &child_path).unwrap(); // run child let p = Command::new(&child_path) .arg(arg) - .cwd(&cwd) - .env_set_all(&my_env) + .current_dir(&cwd) + .env(&env.0, &env.1) .spawn().unwrap().wait_with_output().unwrap(); // display the output - assert!(old_io::stdout().write(&p.output).is_ok()); - assert!(old_io::stderr().write(&p.error).is_ok()); + io::stdout().write_all(&p.stdout).unwrap(); + io::stderr().write_all(&p.stderr).unwrap(); // make sure the child succeeded assert!(p.status.success()); @@ -72,7 +74,7 @@ fn main() { } else { // child // check working directory (don't try to compare with `cwd` here!) - assert!(my_cwd.ends_with_path(&Path::new(child_dir))); + assert!(my_cwd.ends_with(&child_dir)); // check arguments assert_eq!(&*my_args[1], arg); diff --git a/src/test/run-pass/ptr-coercion.rs b/src/test/run-pass/ptr-coercion.rs index a6a8890101..ac1b6aebec 100644 --- a/src/test/run-pass/ptr-coercion.rs +++ b/src/test/run-pass/ptr-coercion.rs @@ -10,26 +10,28 @@ // Test coercions between pointers which don't do anything fancy like unsizing. +// pretty-expanded FIXME #23616 + pub fn main() { // &mut -> & - let x: &mut int = &mut 42; - let x: &int = x; + let x: &mut isize = &mut 42; + let x: &isize = x; - let x: &int = &mut 42; + let x: &isize = &mut 42; // & -> *const - let x: &int = &42; - let x: *const int = x; + let x: &isize = &42; + let x: *const isize = x; - let x: *const int = &42; + let x: *const isize = &42; // &mut -> *const - let x: &mut int = &mut 42; - let x: *const int = x; + let x: &mut isize = &mut 42; + let x: *const isize = x; - let x: *const int = &mut 42; + let x: *const isize = &mut 42; // *mut -> *const - let x: *mut int = &mut 42; - let x: *const int = x; + let x: *mut isize = &mut 42; + let x: *const isize = x; } diff --git a/src/test/run-pass/pub-extern-privacy.rs b/src/test/run-pass/pub-extern-privacy.rs index 7428377b59..b9a3f788f9 100644 --- a/src/test/run-pass/pub-extern-privacy.rs +++ b/src/test/run-pass/pub-extern-privacy.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::transmute; mod a { diff --git a/src/test/run-pass/pub-item-inside-macro.rs b/src/test/run-pass/pub-item-inside-macro.rs index 442eea13d6..d082ca624e 100644 --- a/src/test/run-pass/pub-item-inside-macro.rs +++ b/src/test/run-pass/pub-item-inside-macro.rs @@ -10,6 +10,8 @@ // Issue #14660 +// pretty-expanded FIXME #23616 + mod bleh { macro_rules! foo { () => { diff --git a/src/test/run-pass/pub-method-inside-macro.rs b/src/test/run-pass/pub-method-inside-macro.rs index af2f217c1f..2e2e261b6d 100644 --- a/src/test/run-pass/pub-method-inside-macro.rs +++ b/src/test/run-pass/pub-method-inside-macro.rs @@ -10,6 +10,8 @@ // Issue #17436 +// pretty-expanded FIXME #23616 + mod bleh { macro_rules! foo { () => { diff --git a/src/test/run-pass/pub-use-xcrate.rs b/src/test/run-pass/pub-use-xcrate.rs index cdc184898f..3318c0380b 100644 --- a/src/test/run-pass/pub-use-xcrate.rs +++ b/src/test/run-pass/pub-use-xcrate.rs @@ -11,6 +11,8 @@ // aux-build:pub_use_xcrate1.rs // aux-build:pub_use_xcrate2.rs +// pretty-expanded FIXME #23616 + extern crate pub_use_xcrate2; use pub_use_xcrate2::Foo; diff --git a/src/test/run-pass/pub_use_mods_xcrate_exe.rs b/src/test/run-pass/pub_use_mods_xcrate_exe.rs index ceba89523b..9373b7945d 100644 --- a/src/test/run-pass/pub_use_mods_xcrate_exe.rs +++ b/src/test/run-pass/pub_use_mods_xcrate_exe.rs @@ -10,6 +10,8 @@ // aux-build:pub_use_mods_xcrate.rs +// pretty-expanded FIXME #23616 + #![allow(unused_imports)] extern crate pub_use_mods_xcrate; diff --git a/src/test/run-pass/pure-sum.rs b/src/test/run-pass/pure-sum.rs index f7adb0f6e4..c27b95e1f1 100644 --- a/src/test/run-pass/pure-sum.rs +++ b/src/test/run-pass/pure-sum.rs @@ -10,47 +10,49 @@ // Check that functions can modify local state. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn sums_to(v: Vec , sum: int) -> bool { - let mut i = 0_usize; +fn sums_to(v: Vec , sum: isize) -> bool { + let mut i = 0; let mut sum0 = 0; while i < v.len() { sum0 += v[i]; - i += 1_usize; + i += 1; } return sum0 == sum; } -fn sums_to_using_uniq(v: Vec , sum: int) -> bool { - let mut i = 0_usize; - let mut sum0 = box 0; +fn sums_to_using_uniq(v: Vec , sum: isize) -> bool { + let mut i = 0; + let mut sum0: Box<_> = box 0; while i < v.len() { *sum0 += v[i]; - i += 1_usize; + i += 1; } return *sum0 == sum; } -fn sums_to_using_rec(v: Vec , sum: int) -> bool { - let mut i = 0_usize; +fn sums_to_using_rec(v: Vec , sum: isize) -> bool { + let mut i = 0; let mut sum0 = F {f: 0}; while i < v.len() { sum0.f += v[i]; - i += 1_usize; + i += 1; } return sum0.f == sum; } struct F { f: T } -fn sums_to_using_uniq_rec(v: Vec , sum: int) -> bool { - let mut i = 0_usize; - let mut sum0 = F {f: box 0}; +fn sums_to_using_uniq_rec(v: Vec , sum: isize) -> bool { + let mut i = 0; + let mut sum0 = F::> {f: box 0}; while i < v.len() { *sum0.f += v[i]; - i += 1_usize; + i += 1; } return *sum0.f == sum; } diff --git a/src/test/run-pass/range-type-infer.rs b/src/test/run-pass/range-type-infer.rs index 51945a4677..2d664c00ed 100644 --- a/src/test/run-pass/range-type-infer.rs +++ b/src/test/run-pass/range-type-infer.rs @@ -12,6 +12,8 @@ // good as the old one. Check out issue #21672, #21595 and #21649 for // more details. +// pretty-expanded FIXME #23616 + fn main() { let xs = (0..8).map(|i| i == 1u64).collect::>(); assert_eq!(xs[1], true); diff --git a/src/test/run-pass/range.rs b/src/test/run-pass/range.rs index 50b90b1a5e..4633f73b9a 100644 --- a/src/test/run-pass/range.rs +++ b/src/test/run-pass/range.rs @@ -10,7 +10,9 @@ // Test range syntax. -fn foo() -> int { 42 } +// pretty-expanded FIXME #23616 + +fn foo() -> isize { 42 } // Test that range syntax works in return statements fn return_range_to() -> ::std::ops::RangeTo { return ..1; } diff --git a/src/test/run-pass/ranges-precedence.rs b/src/test/run-pass/ranges-precedence.rs index db414abb7f..870d7a0bc0 100644 --- a/src/test/run-pass/ranges-precedence.rs +++ b/src/test/run-pass/ranges-precedence.rs @@ -11,12 +11,14 @@ // Test that the precedence of ranges is correct +// pretty-expanded FIXME #23616 + struct Foo { - foo: uint, + foo: usize, } impl Foo { - fn bar(&self) -> uint { 5 } + fn bar(&self) -> usize { 5 } } fn main() { @@ -38,7 +40,7 @@ fn main() { let x = ..1+3; assert!(x == (..4)); - let a = &[0i32, 1, 2, 3, 4, 5, 6]; + let a = &[0, 1, 2, 3, 4, 5, 6]; let x = &a[1+1..2+2]; assert!(x == &a[2..4]); let x = &a[..1+2]; @@ -58,4 +60,3 @@ fn main() { let y = ..; assert!(y == (..)); } - diff --git a/src/test/run-pass/raw-str.rs b/src/test/run-pass/raw-str.rs index 35e863d05a177dd06262b4d4302b5f40886ed0aa..298ac8f77eb11dd6f5a4a63ea68920e34a5e7d61 100644 GIT binary patch delta 32 ncmdnZwU=vyDyu}bk!f;Tt-6jvUTIE_m3oYUx{{_fS1lI+q<0Ab delta 30 lcmdnXwVP{$Dyx{0X>yvnjzV5(PL7p&jDfn6rZrbB7XXP+2nGNE diff --git a/src/test/run-pass/rcvr-borrowed-to-region.rs b/src/test/run-pass/rcvr-borrowed-to-region.rs index 84a230fd57..6e9769ea2b 100644 --- a/src/test/run-pass/rcvr-borrowed-to-region.rs +++ b/src/test/run-pass/rcvr-borrowed-to-region.rs @@ -12,20 +12,20 @@ #![feature(box_syntax)] trait get { - fn get(self) -> int; + fn get(self) -> isize; } // Note: impl on a slice; we're checking that the pointers below -// correctly get borrowed to `&`. (similar to impling for `int`, with +// correctly get borrowed to `&`. (similar to impling for `isize`, with // `&self` instead of `self`.) -impl<'a> get for &'a int { - fn get(self) -> int { +impl<'a> get for &'a isize { + fn get(self) -> isize { return *self; } } pub fn main() { - let x = box 6; + let x: Box<_> = box 6; let y = x.get(); println!("y={}", y); assert_eq!(y, 6); diff --git a/src/test/run-pass/rcvr-borrowed-to-slice.rs b/src/test/run-pass/rcvr-borrowed-to-slice.rs index 6a5da01499..1ec1674718 100644 --- a/src/test/run-pass/rcvr-borrowed-to-slice.rs +++ b/src/test/run-pass/rcvr-borrowed-to-slice.rs @@ -10,17 +10,17 @@ trait sum { - fn sum_(self) -> int; + fn sum_(self) -> isize; } // Note: impl on a slice -impl<'a> sum for &'a [int] { - fn sum_(self) -> int { +impl<'a> sum for &'a [isize] { + fn sum_(self) -> isize { self.iter().fold(0, |a, &b| a + b) } } -fn call_sum(x: &[int]) -> int { x.sum_() } +fn call_sum(x: &[isize]) -> isize { x.sum_() } pub fn main() { let x = vec!(1, 2, 3); diff --git a/src/test/run-pass/readalias.rs b/src/test/run-pass/readalias.rs index 51e955c476..d3b9e56f7d 100644 --- a/src/test/run-pass/readalias.rs +++ b/src/test/run-pass/readalias.rs @@ -11,7 +11,9 @@ -struct Point {x: int, y: int, z: int} +// pretty-expanded FIXME #23616 + +struct Point {x: isize, y: isize, z: isize} fn f(p: Point) { assert!((p.z == 12)); } diff --git a/src/test/run-pass/realloc-16687.rs b/src/test/run-pass/realloc-16687.rs index de5b14104c..cd9cc09012 100644 --- a/src/test/run-pass/realloc-16687.rs +++ b/src/test/run-pass/realloc-16687.rs @@ -13,6 +13,8 @@ // Ideally this would be revised to use no_std, but for now it serves // well enough to reproduce (and illustrate) the bug from #16687. +#![feature(alloc)] + extern crate alloc; use alloc::heap; @@ -26,49 +28,49 @@ fn main() { } unsafe fn test_triangle() -> bool { - static COUNT : uint = 16; + static COUNT : usize = 16; let mut ascend = repeat(ptr::null_mut()).take(COUNT).collect::>(); let ascend = &mut *ascend; - static ALIGN : uint = 1; + static ALIGN : usize = 1; // Checks that `ascend` forms triangle of ascending size formed // from pairs of rows (where each pair of rows is equally sized), // and the elements of the triangle match their row-pair index. unsafe fn sanity_check(ascend: &[*mut u8]) { - for i in 0_usize..COUNT / 2 { + for i in 0..COUNT / 2 { let (p0, p1, size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); - for j in 0_usize..size { - assert_eq!(*p0.offset(j as int), i as u8); - assert_eq!(*p1.offset(j as int), i as u8); + for j in 0..size { + assert_eq!(*p0.offset(j as isize), i as u8); + assert_eq!(*p1.offset(j as isize), i as u8); } } } static PRINT : bool = false; - unsafe fn allocate(size: uint, align: uint) -> *mut u8 { + unsafe fn allocate(size: usize, align: usize) -> *mut u8 { if PRINT { println!("allocate(size={} align={})", size, align); } let ret = heap::allocate(size, align); if ret.is_null() { alloc::oom() } if PRINT { println!("allocate(size={} align={}) ret: 0x{:010x}", - size, align, ret as uint); + size, align, ret as usize); } ret } - unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) { + unsafe fn deallocate(ptr: *mut u8, size: usize, align: usize) { if PRINT { println!("deallocate(ptr=0x{:010x} size={} align={})", - ptr as uint, size, align); + ptr as usize, size, align); } heap::deallocate(ptr, size, align); } - unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 { + unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { if PRINT { println!("reallocate(ptr=0x{:010x} old_size={} size={} align={})", - ptr as uint, old_size, size, align); + ptr as usize, old_size, size, align); } let ret = heap::reallocate(ptr, old_size, size, align); @@ -77,29 +79,29 @@ unsafe fn test_triangle() -> bool { if PRINT { println!("reallocate(ptr=0x{:010x} old_size={} size={} align={}) \ ret: 0x{:010x}", - ptr as uint, old_size, size, align, ret as uint); + ptr as usize, old_size, size, align, ret as usize); } ret } - fn idx_to_size(i: uint) -> uint { (i+1) * 10 } + fn idx_to_size(i: usize) -> usize { (i+1) * 10 } // Allocate pairs of rows that form a triangle shape. (Hope is // that at least two rows will be allocated near each other, so // that we trigger the bug (a buffer overrun) in an observable // way.) - for i in 0_usize..COUNT / 2 { + for i in 0..COUNT / 2 { let size = idx_to_size(i); ascend[2*i] = allocate(size, ALIGN); ascend[2*i+1] = allocate(size, ALIGN); } // Initialize each pair of rows to distinct value. - for i in 0_usize..COUNT / 2 { + for i in 0..COUNT / 2 { let (p0, p1, size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); for j in 0..size { - *p0.offset(j as int) = i as u8; - *p1.offset(j as int) = i as u8; + *p0.offset(j as isize) = i as u8; + *p1.offset(j as isize) = i as u8; } } @@ -109,7 +111,7 @@ unsafe fn test_triangle() -> bool { test_3(ascend); // triangle -> square test_4(ascend); // square -> triangle - for i in 0_usize..COUNT / 2 { + for i in 0..COUNT / 2 { let size = idx_to_size(i); deallocate(ascend[2*i], size, ALIGN); deallocate(ascend[2*i+1], size, ALIGN); @@ -123,7 +125,7 @@ unsafe fn test_triangle() -> bool { // rows as we go. unsafe fn test_1(ascend: &mut [*mut u8]) { let new_size = idx_to_size(COUNT-1); - for i in 0_usize..COUNT / 2 { + for i in 0..COUNT / 2 { let (p0, p1, old_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(old_size < new_size); @@ -138,7 +140,7 @@ unsafe fn test_triangle() -> bool { // Test 2: turn the square back into a triangle, top to bottom. unsafe fn test_2(ascend: &mut [*mut u8]) { let old_size = idx_to_size(COUNT-1); - for i in 0_usize..COUNT / 2 { + for i in 0..COUNT / 2 { let (p0, p1, new_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(new_size < old_size); @@ -153,7 +155,7 @@ unsafe fn test_triangle() -> bool { // Test 3: turn triangle into a square, bottom to top. unsafe fn test_3(ascend: &mut [*mut u8]) { let new_size = idx_to_size(COUNT-1); - for i in (0_usize..COUNT / 2).rev() { + for i in (0..COUNT / 2).rev() { let (p0, p1, old_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(old_size < new_size); @@ -168,7 +170,7 @@ unsafe fn test_triangle() -> bool { // Test 4: turn the square back into a triangle, bottom to top. unsafe fn test_4(ascend: &mut [*mut u8]) { let old_size = idx_to_size(COUNT-1); - for i in (0_usize..COUNT / 2).rev() { + for i in (0..COUNT / 2).rev() { let (p0, p1, new_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i)); assert!(new_size < old_size); diff --git a/src/test/run-pass/rec-align-u32.rs b/src/test/run-pass/rec-align-u32.rs index 51b800bc9f..e5d76c3e67 100644 --- a/src/test/run-pass/rec-align-u32.rs +++ b/src/test/run-pass/rec-align-u32.rs @@ -16,8 +16,8 @@ use std::mem; mod rusti { extern "rust-intrinsic" { - pub fn pref_align_of() -> uint; - pub fn min_align_of() -> uint; + pub fn pref_align_of() -> usize; + pub fn min_align_of() -> usize; } } @@ -38,19 +38,19 @@ struct Outer { #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))] mod m { - pub fn align() -> uint { 4_usize } - pub fn size() -> uint { 8_usize } + pub fn align() -> usize { 4 } + pub fn size() -> usize { 8 } } #[cfg(target_arch = "x86_64")] mod m { - pub fn align() -> uint { 4_usize } - pub fn size() -> uint { 8_usize } + pub fn align() -> usize { 4 } + pub fn size() -> usize { 8 } } pub fn main() { unsafe { - let x = Outer {c8: 22u8, t: Inner {c64: 44u32}}; + let x = Outer {c8: 22, t: Inner {c64: 44}}; // Send it through the shape code let y = format!("{:?}", x); diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index cf23a1a0f2..bae95bcb50 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -16,8 +16,8 @@ use std::mem; mod rusti { extern "rust-intrinsic" { - pub fn pref_align_of() -> uint; - pub fn min_align_of() -> uint; + pub fn pref_align_of() -> usize; + pub fn min_align_of() -> usize; } } @@ -44,14 +44,23 @@ struct Outer { mod m { #[cfg(target_arch = "x86")] pub mod m { - pub fn align() -> uint { 4_usize } - pub fn size() -> uint { 12_usize } + pub fn align() -> usize { 4 } + pub fn size() -> usize { 12 } } #[cfg(any(target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))] pub mod m { - pub fn align() -> uint { 8_usize } - pub fn size() -> uint { 16_usize } + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } + } +} + +#[cfg(target_os = "bitrig")] +mod m { + #[cfg(target_arch = "x86_64")] + pub mod m { + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } } } @@ -59,14 +68,14 @@ mod m { mod m { #[cfg(target_arch = "x86")] pub mod m { - pub fn align() -> uint { 8_usize } - pub fn size() -> uint { 16_usize } + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } } #[cfg(target_arch = "x86_64")] pub mod m { - pub fn align() -> uint { 8_usize } - pub fn size() -> uint { 16_usize } + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } } } @@ -74,14 +83,14 @@ mod m { mod m { #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] pub mod m { - pub fn align() -> uint { 8_usize } - pub fn size() -> uint { 16_usize } + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } } } pub fn main() { unsafe { - let x = Outer {c8: 22u8, t: Inner {c64: 44u64}}; + let x = Outer {c8: 22, t: Inner {c64: 44}}; let y = format!("{:?}", x); diff --git a/src/test/run-pass/rec-extend.rs b/src/test/run-pass/rec-extend.rs index de2e937ee8..1071df84cd 100644 --- a/src/test/run-pass/rec-extend.rs +++ b/src/test/run-pass/rec-extend.rs @@ -11,7 +11,9 @@ -struct Point {x: int, y: int} +// pretty-expanded FIXME #23616 + +struct Point {x: isize, y: isize} pub fn main() { let origin: Point = Point {x: 0, y: 0}; diff --git a/src/test/run-pass/rec-tup.rs b/src/test/run-pass/rec-tup.rs index dab7d26cc8..1644a16942 100644 --- a/src/test/run-pass/rec-tup.rs +++ b/src/test/run-pass/rec-tup.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] -struct Point {x: int, y: int} +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] +struct Point {x: isize, y: isize} type rect = (Point, Point); fn fst(r: rect) -> Point { let (fst, _) = r; return fst; } fn snd(r: rect) -> Point { let (_, snd) = r; return snd; } -fn f(r: rect, x1: int, y1: int, x2: int, y2: int) { +fn f(r: rect, x1: isize, y1: isize, x2: isize, y2: isize) { assert_eq!(fst(r).x, x1); assert_eq!(fst(r).y, y1); assert_eq!(snd(r).x, x2); @@ -30,7 +32,7 @@ pub fn main() { assert_eq!(snd(r).x, 11); assert_eq!(snd(r).y, 22); let r2 = r; - let x: int = fst(r2).x; + let x: isize = fst(r2).x; assert_eq!(x, 10); f(r, 10, 20, 11, 22); f(r2, 10, 20, 11, 22); diff --git a/src/test/run-pass/rec.rs b/src/test/run-pass/rec.rs index f59538c51a..a422aaba84 100644 --- a/src/test/run-pass/rec.rs +++ b/src/test/run-pass/rec.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(Copy)] -struct Rect {x: int, y: int, w: int, h: int} +// pretty-expanded FIXME #23616 -fn f(r: Rect, x: int, y: int, w: int, h: int) { +#[derive(Copy, Clone)] +struct Rect {x: isize, y: isize, w: isize, h: isize} + +fn f(r: Rect, x: isize, y: isize, w: isize, h: isize) { assert_eq!(r.x, x); assert_eq!(r.y, y); assert_eq!(r.w, w); @@ -25,7 +27,7 @@ pub fn main() { assert_eq!(r.w, 100); assert_eq!(r.h, 200); let r2: Rect = r; - let x: int = r2.x; + let x: isize = r2.x; assert_eq!(x, 10); f(r, 10, 20, 100, 200); f(r2, 10, 20, 100, 200); diff --git a/src/test/run-pass/record-pat.rs b/src/test/run-pass/record-pat.rs index 282a24a407..6b39cc196f 100644 --- a/src/test/run-pass/record-pat.rs +++ b/src/test/run-pass/record-pat.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum t1 { a(int), b(uint), } -struct T2 {x: t1, y: int} -enum t3 { c(T2, uint), } +// pretty-expanded FIXME #23616 -fn m(input: t3) -> int { +enum t1 { a(isize), b(usize), } +struct T2 {x: t1, y: isize} +enum t3 { c(T2, usize), } + +fn m(input: t3) -> isize { match input { t3::c(T2 {x: t1::a(m), ..}, _) => { return m; } - t3::c(T2 {x: t1::b(m), y: y}, z) => { return ((m + z) as int) + y; } + t3::c(T2 {x: t1::b(m), y: y}, z) => { return ((m + z) as isize) + y; } } } pub fn main() { - assert_eq!(m(t3::c(T2 {x: t1::a(10), y: 5}, 4_usize)), 10); - assert_eq!(m(t3::c(T2 {x: t1::b(10_usize), y: 5}, 4_usize)), 19); + assert_eq!(m(t3::c(T2 {x: t1::a(10), y: 5}, 4)), 10); + assert_eq!(m(t3::c(T2 {x: t1::b(10), y: 5}, 4)), 19); } diff --git a/src/test/run-pass/reexport-should-still-link.rs b/src/test/run-pass/reexport-should-still-link.rs index ba74386f97..1243d72af5 100644 --- a/src/test/run-pass/reexport-should-still-link.rs +++ b/src/test/run-pass/reexport-should-still-link.rs @@ -10,7 +10,9 @@ // aux-build:reexport-should-still-link.rs -extern crate "reexport-should-still-link" as foo; +// pretty-expanded FIXME #23616 + +extern crate reexport_should_still_link as foo; pub fn main() { foo::bar(); diff --git a/src/test/run-pass/reexport-star.rs b/src/test/run-pass/reexport-star.rs index 22ca737d42..a8d052f407 100644 --- a/src/test/run-pass/reexport-star.rs +++ b/src/test/run-pass/reexport-star.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + mod a { pub fn f() {} pub fn g() {} diff --git a/src/test/run-pass/reexported-static-methods-cross-crate.rs b/src/test/run-pass/reexported-static-methods-cross-crate.rs index 5399f3cfd3..3efd913cf5 100644 --- a/src/test/run-pass/reexported-static-methods-cross-crate.rs +++ b/src/test/run-pass/reexported-static-methods-cross-crate.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:reexported_static_methods.rs +// pretty-expanded FIXME #23616 + extern crate reexported_static_methods; use reexported_static_methods::Foo; @@ -17,8 +19,8 @@ use reexported_static_methods::Boz; use reexported_static_methods::Bort; pub fn main() { - assert_eq!(42, Foo::foo()); - assert_eq!(84, Baz::bar()); + assert_eq!(42_isize, Foo::foo()); + assert_eq!(84_isize, Baz::bar()); assert!(Boz::boz(1)); assert_eq!("bort()".to_string(), Bort::bort()); } diff --git a/src/test/run-pass/regions-addr-of-interior-of-unique-box.rs b/src/test/run-pass/regions-addr-of-interior-of-unique-box.rs index bb2885a217..4839067e53 100644 --- a/src/test/run-pass/regions-addr-of-interior-of-unique-box.rs +++ b/src/test/run-pass/regions-addr-of-interior-of-unique-box.rs @@ -9,16 +9,18 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct Point { - x: int, - y: int + x: isize, + y: isize } struct Character { pos: Box, } -fn get_x(x: &Character) -> &int { +fn get_x(x: &Character) -> &isize { // interesting case because the scope of this // borrow of the unique pointer is in fact // larger than the fn itself diff --git a/src/test/run-pass/regions-addr-of-ret.rs b/src/test/run-pass/regions-addr-of-ret.rs index a046ba456a..3baf2fa2de 100644 --- a/src/test/run-pass/regions-addr-of-ret.rs +++ b/src/test/run-pass/regions-addr-of-ret.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(x: &int) -> &int { +fn f(x: &isize) -> &isize { return &*x; } diff --git a/src/test/run-pass/regions-assoc-type-region-bound.rs b/src/test/run-pass/regions-assoc-type-region-bound.rs index 77e1a21476..b51d62f490 100644 --- a/src/test/run-pass/regions-assoc-type-region-bound.rs +++ b/src/test/run-pass/regions-assoc-type-region-bound.rs @@ -11,6 +11,8 @@ // Test that the compiler considers the 'a bound declared in the // trait. Issue #20890. +// pretty-expanded FIXME #23616 + trait Foo<'a> { type Value: 'a; diff --git a/src/test/run-pass/regions-assoc-type-static-bound.rs b/src/test/run-pass/regions-assoc-type-static-bound.rs index 80ae371e50..344f707aef 100644 --- a/src/test/run-pass/regions-assoc-type-static-bound.rs +++ b/src/test/run-pass/regions-assoc-type-static-bound.rs @@ -11,6 +11,8 @@ // Test that the compiler considers the 'static bound declared in the // trait. Issue #20890. +// pretty-expanded FIXME #23616 + trait Foo { type Value: 'static; fn dummy(&self) { } diff --git a/src/test/run-pass/regions-borrow-at.rs b/src/test/run-pass/regions-borrow-at.rs index 89779fa4d2..83a82041af 100644 --- a/src/test/run-pass/regions-borrow-at.rs +++ b/src/test/run-pass/regions-borrow-at.rs @@ -11,13 +11,13 @@ #![allow(unknown_features)] #![feature(box_syntax)] -fn foo(x: &uint) -> uint { +fn foo(x: &usize) -> usize { *x } pub fn main() { - let p = box 22_usize; + let p: Box<_> = box 22; let r = foo(&*p); println!("r={}", r); - assert_eq!(r, 22_usize); + assert_eq!(r, 22); } diff --git a/src/test/run-pass/regions-borrow-evec-fixed.rs b/src/test/run-pass/regions-borrow-evec-fixed.rs index 0264e64f70..7f3db86783 100644 --- a/src/test/run-pass/regions-borrow-evec-fixed.rs +++ b/src/test/run-pass/regions-borrow-evec-fixed.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(x: &[int]) -> int { +// pretty-expanded FIXME #23616 + +fn foo(x: &[isize]) -> isize { x[0] } diff --git a/src/test/run-pass/regions-borrow-evec-uniq.rs b/src/test/run-pass/regions-borrow-evec-uniq.rs index 16eeb99982..adf88037d2 100644 --- a/src/test/run-pass/regions-borrow-evec-uniq.rs +++ b/src/test/run-pass/regions-borrow-evec-uniq.rs @@ -9,7 +9,9 @@ // except according to those terms. -fn foo(x: &[int]) -> int { +// pretty-expanded FIXME #23616 + +fn foo(x: &[isize]) -> isize { x[0] } diff --git a/src/test/run-pass/regions-borrow-uniq.rs b/src/test/run-pass/regions-borrow-uniq.rs index a1af7159a9..01a4e9c20c 100644 --- a/src/test/run-pass/regions-borrow-uniq.rs +++ b/src/test/run-pass/regions-borrow-uniq.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn foo(x: &uint) -> uint { +fn foo(x: &usize) -> usize { *x } pub fn main() { - let p = box 3_usize; + let p: Box<_> = box 3; let r = foo(&*p); - assert_eq!(r, 3_usize); + assert_eq!(r, 3); } diff --git a/src/test/run-pass/regions-bot.rs b/src/test/run-pass/regions-bot.rs index 75c52f6304..269e30741f 100644 --- a/src/test/run-pass/regions-bot.rs +++ b/src/test/run-pass/regions-bot.rs @@ -10,9 +10,11 @@ // A very limited test of the "bottom" region +// pretty-expanded FIXME #23616 + fn produce_static() -> &'static T { panic!(); } -fn foo(_x: &T) -> &uint { produce_static() } +fn foo(_x: &T) -> &usize { produce_static() } pub fn main() { } diff --git a/src/test/run-pass/regions-close-over-type-parameter-successfully.rs b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs index 3922cb1219..cc417219ee 100644 --- a/src/test/run-pass/regions-close-over-type-parameter-successfully.rs +++ b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs @@ -11,13 +11,15 @@ // A test where we (successfully) close over a reference into // an object. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -trait SomeTrait { fn get(&self) -> int; } +trait SomeTrait { fn get(&self) -> isize; } -impl<'a> SomeTrait for &'a int { - fn get(&self) -> int { +impl<'a> SomeTrait for &'a isize { + fn get(&self) -> isize { **self } } @@ -27,7 +29,7 @@ fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box { } fn main() { - let i: int = 22; + let i: isize = 22; let obj = make_object(&i); assert_eq!(22, obj.get()); } diff --git a/src/test/run-pass/regions-copy-closure.rs b/src/test/run-pass/regions-copy-closure.rs index 6ebef9f34a..9e3fe79197 100644 --- a/src/test/run-pass/regions-copy-closure.rs +++ b/src/test/run-pass/regions-copy-closure.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] struct closure_box<'a> { cl: Box, @@ -21,11 +22,12 @@ fn box_it<'a>(x: Box) -> closure_box<'a> { } pub fn main() { - let mut i = 3i32; + let mut i = 3; assert_eq!(i, 3); { let cl = || i += 1; - let mut cl_box = box_it(box cl); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let mut cl_box = box_it(Box::new(cl)); cl_box.cl.call_mut(()); } assert_eq!(i, 4); diff --git a/src/test/run-pass/regions-creating-enums2.rs b/src/test/run-pass/regions-creating-enums2.rs index f23626643e..66d28f5afa 100644 --- a/src/test/run-pass/regions-creating-enums2.rs +++ b/src/test/run-pass/regions-creating-enums2.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum ast<'a> { - num(uint), + num(usize), add(&'a ast<'a>, &'a ast<'a>) } diff --git a/src/test/run-pass/regions-creating-enums5.rs b/src/test/run-pass/regions-creating-enums5.rs index c7d26e2d92..4bd12863e2 100644 --- a/src/test/run-pass/regions-creating-enums5.rs +++ b/src/test/run-pass/regions-creating-enums5.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum ast<'a> { - num(uint), + num(usize), add(&'a ast<'a>, &'a ast<'a>) } diff --git a/src/test/run-pass/regions-debruijn-of-object.rs b/src/test/run-pass/regions-debruijn-of-object.rs index b9d3ed49c6..9f2d27f024 100644 --- a/src/test/run-pass/regions-debruijn-of-object.rs +++ b/src/test/run-pass/regions-debruijn-of-object.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct ctxt<'tcx> { x: &'tcx i32 } diff --git a/src/test/run-pass/regions-dependent-addr-of.rs b/src/test/run-pass/regions-dependent-addr-of.rs index b51be0f0f7..123806a4d9 100644 --- a/src/test/run-pass/regions-dependent-addr-of.rs +++ b/src/test/run-pass/regions-dependent-addr-of.rs @@ -11,6 +11,8 @@ // Test lifetimes are linked properly when we create dependent region pointers. // Issue #3148. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] @@ -20,67 +22,67 @@ struct A { } struct B { - v1: int, - v2: [int; 3], - v3: Vec , + v1: isize, + v2: [isize; 3], + v3: Vec , v4: C, v5: Box, v6: Option } -#[derive(Copy)] +#[derive(Copy, Clone)] struct C { - f: int + f: isize } -fn get_v1(a: &A) -> &int { +fn get_v1(a: &A) -> &isize { // Region inferencer must deduce that &v < L2 < L1 let foo = &a.value; // L1 &foo.v1 // L2 } -fn get_v2(a: &A, i: uint) -> &int { +fn get_v2(a: &A, i: usize) -> &isize { let foo = &a.value; &foo.v2[i] } -fn get_v3(a: &A, i: uint) -> &int { +fn get_v3(a: &A, i: usize) -> &isize { let foo = &a.value; &foo.v3[i] } -fn get_v4(a: &A, _i: uint) -> &int { +fn get_v4(a: &A, _i: usize) -> &isize { let foo = &a.value; &foo.v4.f } -fn get_v5(a: &A, _i: uint) -> &int { +fn get_v5(a: &A, _i: usize) -> &isize { let foo = &a.value; &foo.v5.f } -fn get_v6_a(a: &A, _i: uint) -> &int { +fn get_v6_a(a: &A, _i: usize) -> &isize { match a.value.v6 { Some(ref v) => &v.f, None => panic!() } } -fn get_v6_b(a: &A, _i: uint) -> &int { +fn get_v6_b(a: &A, _i: usize) -> &isize { match *a { A { value: B { v6: Some(ref v), .. } } => &v.f, _ => panic!() } } -fn get_v6_c(a: &A, _i: uint) -> &int { +fn get_v6_c(a: &A, _i: usize) -> &isize { match a { &A { value: B { v6: Some(ref v), .. } } => &v.f, _ => panic!() } } -fn get_v5_ref(a: &A, _i: uint) -> &int { +fn get_v5_ref(a: &A, _i: usize) -> &isize { match &a.value { &B {v5: box C {f: ref v}, ..} => v } diff --git a/src/test/run-pass/regions-dependent-autofn.rs b/src/test/run-pass/regions-dependent-autofn.rs index e7dc5e99c2..ef05fc595d 100644 --- a/src/test/run-pass/regions-dependent-autofn.rs +++ b/src/test/run-pass/regions-dependent-autofn.rs @@ -11,6 +11,8 @@ // Test lifetimes are linked properly when we autoslice a vector. // Issue #3148. +// pretty-expanded FIXME #23616 + fn subslice(v: F) -> F where F: FnOnce() { v } fn both(v: F) -> F where F: FnOnce() { diff --git a/src/test/run-pass/regions-dependent-autoslice.rs b/src/test/run-pass/regions-dependent-autoslice.rs index bcf74729fd..fd0d8121f5 100644 --- a/src/test/run-pass/regions-dependent-autoslice.rs +++ b/src/test/run-pass/regions-dependent-autoslice.rs @@ -12,9 +12,11 @@ // Issue #3148. -fn subslice1<'r>(v: &'r [uint]) -> &'r [uint] { v } +// pretty-expanded FIXME #23616 -fn both<'r>(v: &'r [uint]) -> &'r [uint] { +fn subslice1<'r>(v: &'r [usize]) -> &'r [usize] { v } + +fn both<'r>(v: &'r [usize]) -> &'r [usize] { subslice1(subslice1(v)) } diff --git a/src/test/run-pass/regions-dependent-let-ref.rs b/src/test/run-pass/regions-dependent-let-ref.rs index 980fcfb2e9..1b869e462b 100644 --- a/src/test/run-pass/regions-dependent-let-ref.rs +++ b/src/test/run-pass/regions-dependent-let-ref.rs @@ -11,7 +11,9 @@ // Test lifetimes are linked properly when we take reference // to interior. -struct Foo(int); +// pretty-expanded FIXME #23616 + +struct Foo(isize); pub fn main() { // Here the lifetime of the `&` should be at least the // block, since a ref binding is created to the interior. diff --git a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs index bdc0d41c94..9aed915512 100644 --- a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs +++ b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs @@ -14,6 +14,8 @@ // lifetime parameters must be early bound in the type of the // associated item. +// pretty-expanded FIXME #23616 + use std::marker; pub enum Value<'v> { @@ -26,7 +28,7 @@ pub trait Decoder<'v> { } pub trait Decodable<'v, D: Decoder<'v>> - : marker::PhantomFn<(), &'v int> + : marker::PhantomFn<(), &'v isize> { fn decode(d: &mut D) -> Self; } diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs index 3f434a4838..738f5dbb7b 100644 --- a/src/test/run-pass/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions-early-bound-trait-param.rs @@ -11,21 +11,23 @@ // Tests that you can use an early-bound lifetime parameter as // on of the generic parameters in a trait. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] trait Trait<'a> { - fn long(&'a self) -> int; - fn short<'b>(&'b self) -> int; + fn long(&'a self) -> isize; + fn short<'b>(&'b self) -> isize; } -fn poly_invoke<'c, T: Trait<'c>>(x: &'c T) -> (int, int) { +fn poly_invoke<'c, T: Trait<'c>>(x: &'c T) -> (isize, isize) { let l = x.long(); let s = x.short(); (l,s) } -fn object_invoke1<'d>(x: &'d Trait<'d>) -> (int, int) { +fn object_invoke1<'d>(x: &'d Trait<'d>) -> (isize, isize) { let l = x.long(); let s = x.short(); (l,s) @@ -35,7 +37,7 @@ struct Struct1<'e> { f: &'e (Trait<'e>+'e) } -fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) { +fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (isize,isize) { let l = x.f.long(); let s = x.f.short(); (l,s) @@ -45,11 +47,11 @@ struct Struct2<'h, 'i> { f: &'h (Trait<'i>+'h) } -fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> int { +fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> isize { x.short() } -fn field_invoke2<'l, 'm, 'n>(x: &'n Struct2<'l,'m>) -> int { +fn field_invoke2<'l, 'm, 'n>(x: &'n Struct2<'l,'m>) -> isize { x.f.short() } @@ -69,28 +71,31 @@ fn make_ref<'r, T:RefMakerTrait<'r>>(t:T) -> &'r T { RefMakerTrait::mk(t) } -impl<'s> Trait<'s> for (int,int) { - fn long(&'s self) -> int { +impl<'s> Trait<'s> for (isize,isize) { + fn long(&'s self) -> isize { let &(x,_) = self; x } - fn short<'b>(&'b self) -> int { + fn short<'b>(&'b self) -> isize { let &(_,y) = self; y } } impl<'t> MakerTrait for Box+'static> { - fn mk() -> Box+'static> { box() (4,5) as Box } + fn mk() -> Box+'static> { + let tup: Box<(isize, isize)> = box() (4,5); + tup as Box + } } enum List<'l> { - Cons(int, &'l List<'l>), + Cons(isize, &'l List<'l>), Null } impl<'l> List<'l> { - fn car<'m>(&'m self) -> int { + fn car<'m>(&'m self) -> isize { match self { &List::Cons(car, _) => car, &List::Null => panic!(), diff --git a/src/test/run-pass/regions-early-bound-used-in-bound-method.rs b/src/test/run-pass/regions-early-bound-used-in-bound-method.rs index 410415e57a..6ad8995123 100644 --- a/src/test/run-pass/regions-early-bound-used-in-bound-method.rs +++ b/src/test/run-pass/regions-early-bound-used-in-bound-method.rs @@ -11,23 +11,25 @@ // Tests that you can use a fn lifetime parameter as part of // the value for a type parameter in a bound. +// pretty-expanded FIXME #23616 + trait GetRef<'a> { - fn get(&self) -> &'a int; + fn get(&self) -> &'a isize; } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Box<'a> { - t: &'a int + t: &'a isize } impl<'a> GetRef<'a> for Box<'a> { - fn get(&self) -> &'a int { + fn get(&self) -> &'a isize { self.t } } impl<'a> Box<'a> { - fn add<'b,G:GetRef<'b>>(&self, g2: G) -> int { + fn add<'b,G:GetRef<'b>>(&self, g2: G) -> isize { *self.t + *g2.get() } } diff --git a/src/test/run-pass/regions-early-bound-used-in-bound.rs b/src/test/run-pass/regions-early-bound-used-in-bound.rs index a3602c5fbe..6ab95d6e49 100644 --- a/src/test/run-pass/regions-early-bound-used-in-bound.rs +++ b/src/test/run-pass/regions-early-bound-used-in-bound.rs @@ -11,23 +11,24 @@ // Tests that you can use a fn lifetime parameter as part of // the value for a type parameter in a bound. +// pretty-expanded FIXME #23616 + trait GetRef<'a, T> { fn get(&self) -> &'a T; } +#[derive(Copy, Clone)] struct Box<'a, T:'a> { t: &'a T } -impl<'a,T:'a> Copy for Box<'a,T> {} - impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> { fn get(&self) -> &'a T { self.t } } -fn add<'a,G:GetRef<'a, int>>(g1: G, g2: G) -> int { +fn add<'a,G:GetRef<'a, isize>>(g1: G, g2: G) -> isize { *g1.get() + *g2.get() } diff --git a/src/test/run-pass/regions-early-bound-used-in-type-param.rs b/src/test/run-pass/regions-early-bound-used-in-type-param.rs index caef4e3fa9..dc991e9493 100644 --- a/src/test/run-pass/regions-early-bound-used-in-type-param.rs +++ b/src/test/run-pass/regions-early-bound-used-in-type-param.rs @@ -11,11 +11,13 @@ // Tests that you can use a fn lifetime parameter as part of // the value for a type parameter in a bound. +// pretty-expanded FIXME #23616 + trait Get { fn get(&self) -> T; } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Box { t: T } @@ -26,7 +28,7 @@ impl Get for Box { } } -fn add<'a,G:Get<&'a int>>(g1: G, g2: G) -> int { +fn add<'a,G:Get<&'a isize>>(g1: G, g2: G) -> isize { *g1.get() + *g2.get() } diff --git a/src/test/run-pass/regions-escape-into-other-fn.rs b/src/test/run-pass/regions-escape-into-other-fn.rs index b15f9d3485..3e2fec717f 100644 --- a/src/test/run-pass/regions-escape-into-other-fn.rs +++ b/src/test/run-pass/regions-escape-into-other-fn.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn foo(x: &uint) -> &uint { x } -fn bar(x: &uint) -> uint { *x } +fn foo(x: &usize) -> &usize { x } +fn bar(x: &usize) -> usize { *x } pub fn main() { - let p = box 3_usize; + let p: Box<_> = box 3; assert_eq!(bar(foo(&*p)), 3); } diff --git a/src/test/run-pass/regions-expl-self.rs b/src/test/run-pass/regions-expl-self.rs index 58c13885e0..7ad3c3f4e1 100644 --- a/src/test/run-pass/regions-expl-self.rs +++ b/src/test/run-pass/regions-expl-self.rs @@ -10,8 +10,10 @@ // Test that you can insert an explicit lifetime in explicit self. +// pretty-expanded FIXME #23616 + struct Foo { - f: uint + f: usize } impl Foo { diff --git a/src/test/run-pass/regions-fn-subtyping-2.rs b/src/test/run-pass/regions-fn-subtyping-2.rs index 70c90ee05b..7f2fc11cb8 100644 --- a/src/test/run-pass/regions-fn-subtyping-2.rs +++ b/src/test/run-pass/regions-fn-subtyping-2.rs @@ -13,13 +13,15 @@ // 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: Box FnMut(&'a int, Box)>) { +// pretty-expanded FIXME #23616 + +fn has_same_region(f: Box FnMut(&'a isize, Box)>) { // `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: Box FnMut(&'b int, Box)>) { +fn wants_same_region(_f: Box FnMut(&'b isize, Box)>) { } pub fn main() { diff --git a/src/test/run-pass/regions-fn-subtyping.rs b/src/test/run-pass/regions-fn-subtyping.rs index faa9b37bdc..e5b652c306 100644 --- a/src/test/run-pass/regions-fn-subtyping.rs +++ b/src/test/run-pass/regions-fn-subtyping.rs @@ -10,27 +10,30 @@ // Issue #2263. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] #![allow(unknown_features)] -#![feature(box_syntax)] + +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. // Should pass region checking. -fn ok(f: Box) { - // 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 +fn ok(f: Box) { + // Here, g is a function that can accept a usize pointer with + // lifetime r, and f is a function that can accept a usize 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: Box FnMut(&'r uint)> = box |x| { }; + let mut g: Box FnMut(&'r usize)> = Box::new(|x| { }); g = f; } // This version is the same as above, except that here, g's type is // inferred. -fn ok_inferred(f: Box) { - let mut g: Box FnMut(&'r uint)> = box |_| {}; +fn ok_inferred(f: Box) { + let mut g: Box FnMut(&'r usize)> = Box::new(|_| {}); g = f; } diff --git a/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs b/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs index 9f1a383fd6..5d17181173 100644 --- a/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs +++ b/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::swap; pub fn main() { diff --git a/src/test/run-pass/regions-infer-borrow-scope-view.rs b/src/test/run-pass/regions-infer-borrow-scope-view.rs index 1fdf3a92a3..9c200a370a 100644 --- a/src/test/run-pass/regions-infer-borrow-scope-view.rs +++ b/src/test/run-pass/regions-infer-borrow-scope-view.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + fn view(x: &[T]) -> &[T] {x} pub fn main() { diff --git a/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs b/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs index d07110fd72..59221afcef 100644 --- a/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs +++ b/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] fn borrow(x: &T) -> &T {x} pub fn main() { - let x = box 3; + let x: Box<_> = box 3; loop { let y = borrow(&*x); assert_eq!(*x, *y); diff --git a/src/test/run-pass/regions-infer-borrow-scope.rs b/src/test/run-pass/regions-infer-borrow-scope.rs index 708d031a68..3289da3cfd 100644 --- a/src/test/run-pass/regions-infer-borrow-scope.rs +++ b/src/test/run-pass/regions-infer-borrow-scope.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct Point {x: int, y: int} +struct Point {x: isize, y: isize} -fn x_coord(p: &Point) -> &int { +fn x_coord(p: &Point) -> &isize { return &p.x; } pub fn main() { - let p = box Point {x: 3, y: 4}; + let p: Box<_> = box Point {x: 3, y: 4}; let xc = x_coord(&*p); assert_eq!(*xc, 3); } diff --git a/src/test/run-pass/regions-infer-call-2.rs b/src/test/run-pass/regions-infer-call-2.rs index cfb6c85856..7e6767b0de 100644 --- a/src/test/run-pass/regions-infer-call-2.rs +++ b/src/test/run-pass/regions-infer-call-2.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn takes_two(x: &int, y: &int) -> int { *x + *y } +// pretty-expanded FIXME #23616 -fn with(f: F) -> T where F: FnOnce(&int) -> T { +fn takes_two(x: &isize, y: &isize) -> isize { *x + *y } + +fn with(f: F) -> T where F: FnOnce(&isize) -> T { f(&20) } -fn has_one<'a>(x: &'a int) -> int { +fn has_one<'a>(x: &'a isize) -> isize { with(|y| takes_two(x, y)) } diff --git a/src/test/run-pass/regions-infer-call.rs b/src/test/run-pass/regions-infer-call.rs index fdb7485efc..bc752a1d50 100644 --- a/src/test/run-pass/regions-infer-call.rs +++ b/src/test/run-pass/regions-infer-call.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn takes_two(x: &int, y: &int) -> int { *x + *y } +// pretty-expanded FIXME #23616 -fn has_two<'a,'b>(x: &'a int, y: &'b int) -> int { +fn takes_two(x: &isize, y: &isize) -> isize { *x + *y } + +fn has_two<'a,'b>(x: &'a isize, y: &'b isize) -> isize { takes_two(x, y) } diff --git a/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs b/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs index 7e328f3bb0..73cfbcddd9 100644 --- a/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs +++ b/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct boxed_int<'a> { - f: &'a int, + f: &'a isize, } -fn max<'r>(bi: &'r boxed_int, f: &'r int) -> int { +fn max<'r>(bi: &'r boxed_int, f: &'r isize) -> isize { if *bi.f > *f {*bi.f} else {*f} } -fn with(bi: &boxed_int) -> int { +fn with(bi: &boxed_int) -> isize { let i = 22; max(bi, &i) } diff --git a/src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs b/src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs index efe3994dbb..2349b6c3bc 100644 --- a/src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs +++ b/src/test/run-pass/regions-infer-reborrow-ref-mut-recurse.rs @@ -11,10 +11,12 @@ // Test an edge case in region inference: the lifetime of the borrow // of `*x` must be extended to at least 'a. -fn foo<'a,'b>(x: &'a &'b mut int) -> &'a int { - let y = &*x; // should be inferred to have type &'a &'b mut int... +// pretty-expanded FIXME #23616 - // ...because if we inferred, say, &'x &'b mut int where 'x <= 'a, +fn foo<'a,'b>(x: &'a &'b mut isize) -> &'a isize { + let y = &*x; // should be inferred to have type &'a &'b mut isize... + + // ...because if we inferred, say, &'x &'b mut isize where 'x <= 'a, // this reborrow would be illegal: &**y } diff --git a/src/test/run-pass/regions-infer-region-in-fn-but-not-type.rs b/src/test/run-pass/regions-infer-region-in-fn-but-not-type.rs index 9174b53be8..a8418f967f 100644 --- a/src/test/run-pass/regions-infer-region-in-fn-but-not-type.rs +++ b/src/test/run-pass/regions-infer-region-in-fn-but-not-type.rs @@ -9,9 +9,11 @@ // except according to those terms. -// check that the &int here does not cause us to think that `foo` +// check that the &isize here does not cause us to think that `foo` // contains region pointers -struct foo(Box); +// pretty-expanded FIXME #23616 + +struct foo(Box); fn take_foo(x: T) {} diff --git a/src/test/run-pass/regions-infer-static-from-proc.rs b/src/test/run-pass/regions-infer-static-from-proc.rs index cb45b8e131..403dfbf655 100644 --- a/src/test/run-pass/regions-infer-static-from-proc.rs +++ b/src/test/run-pass/regions-infer-static-from-proc.rs @@ -12,9 +12,11 @@ // region variables contained within (otherwise, region inference will // give `x` a very short lifetime). -static i: uint = 3; +// pretty-expanded FIXME #23616 + +static i: usize = 3; fn foo(_: F) {} -fn read(_: uint) { } +fn read(_: usize) { } pub fn main() { let x = &i; foo(move|| { diff --git a/src/test/run-pass/regions-issue-21422.rs b/src/test/run-pass/regions-issue-21422.rs index c59bf15afc..ecc170a146 100644 --- a/src/test/run-pass/regions-issue-21422.rs +++ b/src/test/run-pass/regions-issue-21422.rs @@ -12,6 +12,8 @@ // add inference constraints that the operands of a binary operator // should outlive the binary operation itself. +// pretty-expanded FIXME #23616 + pub struct P<'a> { _ptr: *const &'a u8, } diff --git a/src/test/run-pass/regions-issue-22246.rs b/src/test/run-pass/regions-issue-22246.rs index f5c34d6b34..16236f9465 100644 --- a/src/test/run-pass/regions-issue-22246.rs +++ b/src/test/run-pass/regions-issue-22246.rs @@ -11,6 +11,8 @@ // Regression test for issue #22246 -- we should be able to deduce // that `&'a B::Owned` implies that `B::Owned : 'a`. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] use std::ops::Deref; diff --git a/src/test/run-pass/regions-lifetime-nonfree-late-bound.rs b/src/test/run-pass/regions-lifetime-nonfree-late-bound.rs index a2b6d569ac..a2c07d2728 100644 --- a/src/test/run-pass/regions-lifetime-nonfree-late-bound.rs +++ b/src/test/run-pass/regions-lifetime-nonfree-late-bound.rs @@ -22,20 +22,22 @@ // doing region-folding, when really all clients of the region-folding // case only want to see FREE lifetime variables, not bound ones. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { fn explicit() { - fn test(_x: Option>) where F: FnMut(Box FnMut(&'a int)>) {} - test(Some(box |_f: Box FnMut(&'a int)>| {})); + fn test(_x: Option>) where F: FnMut(Box FnMut(&'a isize)>) {} + test(Some(box |_f: Box FnMut(&'a isize)>| {})); } // 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>) where F: FnMut(Box< FnMut(& int)>) {} - test(Some(box |_f: Box< FnMut(& int)>| {})); + fn test(_x: Option>) where F: FnMut(Box< FnMut(& isize)>) {} + test(Some(box |_f: Box< FnMut(& isize)>| {})); } explicit(); diff --git a/src/test/run-pass/regions-lifetime-static-items-enclosing-scopes.rs b/src/test/run-pass/regions-lifetime-static-items-enclosing-scopes.rs index b16b934d73..451c745358 100644 --- a/src/test/run-pass/regions-lifetime-static-items-enclosing-scopes.rs +++ b/src/test/run-pass/regions-lifetime-static-items-enclosing-scopes.rs @@ -11,6 +11,8 @@ // This test verifies that temporary lifetime is correctly computed // for static objects in enclosing scopes. +// pretty-expanded FIXME #23616 + use std::cmp::PartialEq; fn f(o: &mut Option) { @@ -23,5 +25,5 @@ pub fn main() { static C: E = E::V; } - f::(&mut None); + f::(&mut None); } diff --git a/src/test/run-pass/regions-link-fn-args.rs b/src/test/run-pass/regions-link-fn-args.rs index 8822d38803..9e8ce61604 100644 --- a/src/test/run-pass/regions-link-fn-args.rs +++ b/src/test/run-pass/regions-link-fn-args.rs @@ -11,9 +11,11 @@ // Test that region inference correctly links up the regions when a // `ref` borrow occurs inside a fn argument. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] -fn with<'a, F>(_: F) where F: FnOnce(&'a Vec) -> &'a Vec { } +fn with<'a, F>(_: F) where F: FnOnce(&'a Vec) -> &'a Vec { } fn foo() { with(|&ref ints| ints); diff --git a/src/test/run-pass/regions-mock-tcx.rs b/src/test/run-pass/regions-mock-tcx.rs index bf789d5364..ed3cec465e 100644 --- a/src/test/run-pass/regions-mock-tcx.rs +++ b/src/test/run-pass/regions-mock-tcx.rs @@ -15,6 +15,8 @@ // - Multiple lifetime parameters // - Arenas +#![feature(rustc_private, libc, collections)] + extern crate arena; extern crate collections; extern crate libc; @@ -27,7 +29,7 @@ use std::mem; type Type<'tcx> = &'tcx TypeStructure<'tcx>; -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum TypeStructure<'tcx> { TypeInt, TypeFunction(Type<'tcx>, Type<'tcx>), @@ -54,7 +56,7 @@ struct TypeContext<'tcx, 'ast> { type_table: HashMap>, ast_arena: &'ast AstArena<'ast>, - ast_counter: uint, + ast_counter: usize, } impl<'tcx,'ast> TypeContext<'tcx, 'ast> { @@ -92,23 +94,23 @@ impl<'tcx,'ast> TypeContext<'tcx, 'ast> { } } -#[derive(Copy, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] struct NodeId { - id: uint + id: usize } type Ast<'ast> = &'ast AstStructure<'ast>; -#[derive(Copy)] +#[derive(Copy, Clone)] struct AstStructure<'ast> { id: NodeId, kind: AstKind<'ast> } -#[derive(Copy)] +#[derive(Copy, Clone)] enum AstKind<'ast> { ExprInt, - ExprVar(uint), + ExprVar(usize), ExprLambda(Ast<'ast>), } diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs index e6b997f758..b67612c94b 100644 --- a/src/test/run-pass/regions-mock-trans.rs +++ b/src/test/run-pass/regions-mock-trans.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; use std::mem; @@ -23,7 +27,7 @@ struct Fcx<'a> { } struct Ccx { - x: int + x: isize } fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> { diff --git a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs index 5964ac65d5..6cc32301cc 100644 --- a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs +++ b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] use std::marker; diff --git a/src/test/run-pass/regions-no-variance-from-fn-generics.rs b/src/test/run-pass/regions-no-variance-from-fn-generics.rs index 80c478afa6..89bdbfaed9 100644 --- a/src/test/run-pass/regions-no-variance-from-fn-generics.rs +++ b/src/test/run-pass/regions-no-variance-from-fn-generics.rs @@ -12,6 +12,8 @@ // should not upset the variance inference for actual occurrences of // that lifetime in type expressions. +// pretty-expanded FIXME #23616 + pub trait HasLife<'a> { fn dummy(&'a self) { } // just to induce a variance on 'a } diff --git a/src/test/run-pass/regions-nullary-variant.rs b/src/test/run-pass/regions-nullary-variant.rs index e1359725f9..ae55b97dc9 100644 --- a/src/test/run-pass/regions-nullary-variant.rs +++ b/src/test/run-pass/regions-nullary-variant.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum roption<'a> { - a, b(&'a uint) + a, b(&'a usize) } -fn mk(cond: bool, ptr: &uint) -> roption { +fn mk(cond: bool, ptr: &usize) -> roption { if cond {roption::a} else {roption::b(ptr)} } diff --git a/src/test/run-pass/regions-params.rs b/src/test/run-pass/regions-params.rs index c71953e20f..5002fcce96 100644 --- a/src/test/run-pass/regions-params.rs +++ b/src/test/run-pass/regions-params.rs @@ -9,11 +9,13 @@ // except according to those terms. -fn region_identity(x: &uint) -> &uint { x } +// pretty-expanded FIXME #23616 + +fn region_identity(x: &usize) -> &usize { x } fn apply(t: T, f: F) -> T where F: FnOnce(T) -> T { f(t) } -fn parameterized(x: &uint) -> uint { +fn parameterized(x: &usize) -> usize { let z = apply(x, ({|y| region_identity(y) })); @@ -21,6 +23,6 @@ fn parameterized(x: &uint) -> uint { } pub fn main() { - let x = 3_usize; - assert_eq!(parameterized(&x), 3_usize); + let x = 3; + assert_eq!(parameterized(&x), 3); } diff --git a/src/test/run-pass/regions-reassign-let-bound-pointer.rs b/src/test/run-pass/regions-reassign-let-bound-pointer.rs index ecf79de622..b29cc8f903 100644 --- a/src/test/run-pass/regions-reassign-let-bound-pointer.rs +++ b/src/test/run-pass/regions-reassign-let-bound-pointer.rs @@ -12,7 +12,9 @@ // started out with a longer lifetime and was reassigned to a shorter // one (it should infer to be the intersection). -fn foo(x: &int) { +// pretty-expanded FIXME #23616 + +fn foo(x: &isize) { let a = 1; let mut z = x; z = &a; diff --git a/src/test/run-pass/regions-reassign-match-bound-pointer.rs b/src/test/run-pass/regions-reassign-match-bound-pointer.rs index 18312b1733..58d4f556a7 100644 --- a/src/test/run-pass/regions-reassign-match-bound-pointer.rs +++ b/src/test/run-pass/regions-reassign-match-bound-pointer.rs @@ -12,7 +12,9 @@ // started out with a longer lifetime and was reassigned to a shorter // one (it should infer to be the intersection). -fn foo(x: &int) { +// pretty-expanded FIXME #23616 + +fn foo(x: &isize) { let a = 1; match x { mut z => { diff --git a/src/test/run-pass/regions-refcell.rs b/src/test/run-pass/regions-refcell.rs index a224017780..63525b3620 100644 --- a/src/test/run-pass/regions-refcell.rs +++ b/src/test/run-pass/regions-refcell.rs @@ -12,13 +12,15 @@ // attempting to bootstrap librustc with new destructor lifetime // semantics. +// pretty-expanded FIXME #23616 + use std::collections::HashMap; use std::cell::RefCell; // This version does not yet work (associated type issues)... #[cfg(cannot_use_this_yet)] fn foo<'a>(map: RefCell>) { - let one = [1_usize]; + let one = [1]; assert_eq!(map.borrow().get("one"), Some(&one[..])); } @@ -26,8 +28,8 @@ fn foo<'a>(map: RefCell>) { // ... and this version does not work (the lifetime of `one` is // supposed to match the lifetime `'a`) ... fn foo<'a>(map: RefCell>) { - let one = [1_usize]; - assert_eq!(map.borrow().get("one"), Some(&one.as_slice())); + let one = [1]; + assert_eq!(map.borrow().get("one"), Some(&&one[..])); } #[cfg(all(not(cannot_use_this_yet),not(cannot_use_this_yet_either)))] @@ -41,9 +43,9 @@ fn foo<'a>(map: RefCell>) { } fn main() { - let zer = [0u8]; - let one = [1u8]; - let two = [2u8]; + let zer = [0]; + let one = [1]; + let two = [2]; let mut map = HashMap::new(); map.insert("zero", &zer[..]); map.insert("one", &one[..]); 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 index e779e002b2..a36c1b30ea 100644 --- 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 @@ -17,11 +17,13 @@ // changes were caught. However, those uses in the compiler could // easily get changed or refactored away in the future. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct Ctxt<'tcx> { - x: &'tcx Vec + x: &'tcx Vec } struct Foo<'a,'tcx:'a> { @@ -29,8 +31,9 @@ struct Foo<'a,'tcx:'a> { } impl<'a,'tcx> Foo<'a,'tcx> { - fn bother(&mut self) -> int { - self.elaborate_bounds(box |this| { + fn bother(&mut self) -> isize { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + self.elaborate_bounds(Box::new(|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` @@ -44,17 +47,17 @@ impl<'a,'tcx> Foo<'a,'tcx> { // `region_inference.rs` file (and the `givens` field, in // particular) for more details. this.foo() - }) + })) } - fn foo(&mut self) -> int { + fn foo(&mut self) -> isize { 22 } fn elaborate_bounds( &mut self, - mut mk_cand: Box FnMut(&mut Foo<'b, 'tcx>) -> int>) - -> int + mut mk_cand: Box FnMut(&mut Foo<'b, 'tcx>) -> isize>) + -> isize { mk_cand(self) } diff --git a/src/test/run-pass/regions-return-interior-of-option.rs b/src/test/run-pass/regions-return-interior-of-option.rs index ee1d668730..e6ab4a8142 100644 --- a/src/test/run-pass/regions-return-interior-of-option.rs +++ b/src/test/run-pass/regions-return-interior-of-option.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn get(opt: &Option) -> &T { match *opt { Some(ref v) => v, diff --git a/src/test/run-pass/regions-scope-chain-example.rs b/src/test/run-pass/regions-scope-chain-example.rs index e5ef88006c..185d5db1f5 100644 --- a/src/test/run-pass/regions-scope-chain-example.rs +++ b/src/test/run-pass/regions-scope-chain-example.rs @@ -16,6 +16,8 @@ // wrong path. The new algorithm avoids this problem and hence this // example typechecks correctly. +// pretty-expanded FIXME #23616 + enum ScopeChain<'a> { Link(Scope<'a>), End diff --git a/src/test/run-pass/regions-self-impls.rs b/src/test/run-pass/regions-self-impls.rs index b30b3cfa47..26e3fbfab9 100644 --- a/src/test/run-pass/regions-self-impls.rs +++ b/src/test/run-pass/regions-self-impls.rs @@ -9,15 +9,15 @@ // except according to those terms. struct Clam<'a> { - chowder: &'a int + chowder: &'a isize } trait get_chowder<'a> { - fn get_chowder(&self) -> &'a int; + fn get_chowder(&self) -> &'a isize; } impl<'a> get_chowder<'a> for Clam<'a> { - fn get_chowder(&self) -> &'a int { return self.chowder; } + fn get_chowder(&self) -> &'a isize { return self.chowder; } } pub fn main() { diff --git a/src/test/run-pass/regions-self-in-enums.rs b/src/test/run-pass/regions-self-in-enums.rs index ab0b4acc76..9ff20e93a0 100644 --- a/src/test/run-pass/regions-self-in-enums.rs +++ b/src/test/run-pass/regions-self-in-enums.rs @@ -9,13 +9,13 @@ // except according to those terms. enum int_wrapper<'a> { - int_wrapper_ctor(&'a int) + int_wrapper_ctor(&'a isize) } pub fn main() { let x = 3; let y = int_wrapper::int_wrapper_ctor(&x); - let mut z : ∫ + let mut z : &isize; match y { int_wrapper::int_wrapper_ctor(zz) => { z = zz; } } diff --git a/src/test/run-pass/regions-simple.rs b/src/test/run-pass/regions-simple.rs index d540605180..f4fe73131f 100644 --- a/src/test/run-pass/regions-simple.rs +++ b/src/test/run-pass/regions-simple.rs @@ -9,8 +9,8 @@ // except according to those terms. pub fn main() { - let mut x: int = 3; - let y: &mut int = &mut x; + let mut x: isize = 3; + let y: &mut isize = &mut x; *y = 5; println!("{}", *y); } diff --git a/src/test/run-pass/regions-static-closure.rs b/src/test/run-pass/regions-static-closure.rs index 7198c35944..ae39c26680 100644 --- a/src/test/run-pass/regions-static-closure.rs +++ b/src/test/run-pass/regions-static-closure.rs @@ -10,7 +10,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] struct closure_box<'a> { cl: Box, @@ -25,6 +25,7 @@ fn call_static_closure(mut cl: closure_box<'static>) { } pub fn main() { - let cl_box = box_it(box || println!("Hello, world!")); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let cl_box = box_it(Box::new(|| println!("Hello, world!"))); call_static_closure(cl_box); } diff --git a/src/test/run-pass/regions-trait-object-1.rs b/src/test/run-pass/regions-trait-object-1.rs index eb3bec7732..d235298857 100644 --- a/src/test/run-pass/regions-trait-object-1.rs +++ b/src/test/run-pass/regions-trait-object-1.rs @@ -12,6 +12,8 @@ // attempting to bootstrap libsyntax; it is adapted from // `syntax::ext::tt::generic_extension`. +// pretty-expanded FIXME #23616 + pub struct E<'a> { pub f: &'a u8, } @@ -37,7 +39,7 @@ fn extension<'e>(x: &'e E<'e>) -> Box { } fn main() { - let w = E { f: &10u8 }; + let w = E { f: &10 }; let o = extension(&w); - assert_eq!(o.n(), 10u8); + assert_eq!(o.n(), 10); } diff --git a/src/test/run-pass/regions-variance-contravariant-use-contravariant.rs b/src/test/run-pass/regions-variance-contravariant-use-contravariant.rs index ffc2f07a15..5e5be1c258 100644 --- a/src/test/run-pass/regions-variance-contravariant-use-contravariant.rs +++ b/src/test/run-pass/regions-variance-contravariant-use-contravariant.rs @@ -14,8 +14,10 @@ // Note: see compile-fail/variance-regions-*.rs for the tests that check that the // variance inference works in the first place. +// pretty-expanded FIXME #23616 + struct Contravariant<'a> { - f: &'a int + f: &'a isize } fn use_<'a>(c: Contravariant<'a>) { @@ -26,7 +28,7 @@ fn use_<'a>(c: Contravariant<'a>) { // if 'call <= 'a, which is true, so no error. collapse(&x, c); - fn collapse<'b>(x: &'b int, c: Contravariant<'b>) { } + fn collapse<'b>(x: &'b isize, c: Contravariant<'b>) { } } pub fn main() {} diff --git a/src/test/run-pass/regions-variance-covariant-use-covariant.rs b/src/test/run-pass/regions-variance-covariant-use-covariant.rs index 7e0ca41501..0256278137 100644 --- a/src/test/run-pass/regions-variance-covariant-use-covariant.rs +++ b/src/test/run-pass/regions-variance-covariant-use-covariant.rs @@ -17,8 +17,10 @@ // This is covariant with respect to 'a, meaning that // Covariant<'foo> <: Covariant<'static> because // 'foo <= 'static +// pretty-expanded FIXME #23616 + struct Covariant<'a> { - f: extern "Rust" fn(&'a int) + f: extern "Rust" fn(&'a isize) } fn use_<'a>(c: Covariant<'a>) { diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs deleted file mode 100644 index abe6ffe7d4..0000000000 --- a/src/test/run-pass/rename-directory.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test can't be a unit test in std, -// because it needs TempDir, which is in extra - -extern crate libc; - -use std::ffi::CString; -use std::old_io::TempDir; -use std::old_io::fs::PathExtensions; -use std::old_io::fs; -use std::old_io; -use std::os; - -fn rename_directory() { - unsafe { - static U_RWX: i32 = (libc::S_IRUSR | libc::S_IWUSR | libc::S_IXUSR) as i32; - - let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed"); - let tmpdir = tmpdir.path(); - let old_path = tmpdir.join_many(&["foo", "bar", "baz"]); - fs::mkdir_recursive(&old_path, old_io::USER_RWX); - let test_file = &old_path.join("temp.txt"); - - /* Write the temp input file */ - let fromp = CString::new(test_file.as_vec()).unwrap(); - let modebuf = CString::new(b"w+b").unwrap(); - let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr()); - assert!((ostream as uint != 0_usize)); - let s = "hello".to_string(); - let buf = CString::new(b"hello").unwrap(); - let write_len = libc::fwrite(buf.as_ptr() as *mut _, - 1_usize as libc::size_t, - (s.len() + 1_usize) as libc::size_t, - ostream); - assert_eq!(write_len, (s.len() + 1) as libc::size_t); - assert_eq!(libc::fclose(ostream), (0_usize as libc::c_int)); - - let new_path = tmpdir.join_many(&["quux", "blat"]); - fs::mkdir_recursive(&new_path, old_io::USER_RWX); - fs::rename(&old_path, &new_path.join("newdir")); - assert!(new_path.join("newdir").is_dir()); - assert!(new_path.join_many(&["newdir", "temp.txt"]).exists()); - } -} - -pub fn main() { rename_directory() } diff --git a/src/test/run-pass/repeat-expr-in-static.rs b/src/test/run-pass/repeat-expr-in-static.rs index a53f1da4ce..5a4475ae94 100644 --- a/src/test/run-pass/repeat-expr-in-static.rs +++ b/src/test/run-pass/repeat-expr-in-static.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static FOO: [int; 4] = [32; 4]; -static BAR: [int; 4] = [32, 32, 32, 32]; +// pretty-expanded FIXME #23616 + +static FOO: [isize; 4] = [32; 4]; +static BAR: [isize; 4] = [32, 32, 32, 32]; pub fn main() { assert!(FOO == BAR); diff --git a/src/test/run-pass/resolve-issue-2428.rs b/src/test/run-pass/resolve-issue-2428.rs index 016357b5df..bad5b83b54 100644 --- a/src/test/run-pass/resolve-issue-2428.rs +++ b/src/test/run-pass/resolve-issue-2428.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -const foo: int = 4 >> 1; +// pretty-expanded FIXME #23616 + +const foo: isize = 4 >> 1; enum bs { thing = foo } -pub fn main() { assert!((bs::thing as int == foo)); } +pub fn main() { assert!((bs::thing as isize == foo)); } diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs index abc33e9f2e..ba63c2db7c 100644 --- a/src/test/run-pass/resource-assign-is-not-copy.rs +++ b/src/test/run-pass/resource-assign-is-not-copy.rs @@ -14,7 +14,7 @@ use std::cell::Cell; #[derive(Debug)] struct r<'a> { - i: &'a Cell, + i: &'a Cell, } #[unsafe_destructor] @@ -24,7 +24,7 @@ impl<'a> Drop for r<'a> { } } -fn r(i: &Cell) -> r { +fn r(i: &Cell) -> r { r { i: i } diff --git a/src/test/run-pass/resource-destruct.rs b/src/test/run-pass/resource-destruct.rs index 71bf6cc626..229ceba08b 100644 --- a/src/test/run-pass/resource-destruct.rs +++ b/src/test/run-pass/resource-destruct.rs @@ -13,7 +13,7 @@ use std::cell::Cell; struct shrinky_pointer<'a> { - i: &'a Cell, + i: &'a Cell, } #[unsafe_destructor] @@ -24,10 +24,10 @@ impl<'a> Drop for shrinky_pointer<'a> { } impl<'a> shrinky_pointer<'a> { - pub fn look_at(&self) -> int { return self.i.get(); } + pub fn look_at(&self) -> isize { return self.i.get(); } } -fn shrinky_pointer(i: &Cell) -> shrinky_pointer { +fn shrinky_pointer(i: &Cell) -> shrinky_pointer { shrinky_pointer { i: i } diff --git a/src/test/run-pass/resource-in-struct.rs b/src/test/run-pass/resource-in-struct.rs index 33ae0af250..a8426f90cc 100644 --- a/src/test/run-pass/resource-in-struct.rs +++ b/src/test/run-pass/resource-in-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] // Ensures that class dtors run if the object is inside an enum diff --git a/src/test/run-pass/ret-bang.rs b/src/test/run-pass/ret-bang.rs index 74227192ca..7d4d021811 100644 --- a/src/test/run-pass/ret-bang.rs +++ b/src/test/run-pass/ret-bang.rs @@ -13,12 +13,12 @@ fn my_err(s: String) -> ! { println!("{}", s); panic!(); } -fn okay(i: uint) -> int { - if i == 3_usize { +fn okay(i: usize) -> isize { + if i == 3 { my_err("I don't like three".to_string()); } else { return 42; } } -pub fn main() { okay(4_usize); } +pub fn main() { okay(4); } diff --git a/src/test/run-pass/ret-none.rs b/src/test/run-pass/ret-none.rs index 8d7faffae7..032a4b662c 100644 --- a/src/test/run-pass/ret-none.rs +++ b/src/test/run-pass/ret-none.rs @@ -10,8 +10,10 @@ +// pretty-expanded FIXME #23616 + enum option { none, some(T), } fn f() -> option { return option::none; } -pub fn main() { f::(); } +pub fn main() { f::(); } diff --git a/src/test/run-pass/return-from-closure.rs b/src/test/run-pass/return-from-closure.rs index 60856ee604..4395f6fcb4 100644 --- a/src/test/run-pass/return-from-closure.rs +++ b/src/test/run-pass/return-from-closure.rs @@ -10,10 +10,12 @@ // just to make sure that `return` is only returning from the closure, // not the surrounding function. -static mut calls: uint = 0; +// pretty-expanded FIXME #23616 + +static mut calls: usize = 0; fn surrounding() { - let return_works = |n: int| { + let return_works = |n: isize| { unsafe { calls += 1 } if n >= 0 { return; } @@ -23,7 +25,7 @@ fn surrounding() { return_works(10); return_works(20); - let return_works_proc = |n: int| { + let return_works_proc = |n: isize| { unsafe { calls += 1 } if n >= 0 { return; } diff --git a/src/test/run-pass/return-nil.rs b/src/test/run-pass/return-nil.rs index b5a81268a2..fe4244084c 100644 --- a/src/test/run-pass/return-nil.rs +++ b/src/test/run-pass/return-nil.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + fn f() { let x: () = (); return x; } pub fn main() { let _x = f(); } diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs index ec033b74dd..abad08c7ac 100644 --- a/src/test/run-pass/running-with-no-runtime.rs +++ b/src/test/run-pass/running-with-no-runtime.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(start)] +#![feature(start, os, std_misc, old_io)] -use std::ffi; +use std::ffi::CStr; use std::old_io::process::{Command, ProcessOutput}; use std::os; use std::rt::unwind::try; @@ -20,7 +20,7 @@ use std::thread::Thread; use std::thunk::Thunk; #[start] -fn start(argc: int, argv: *const *const u8) -> int { +fn start(argc: isize, argv: *const *const u8) -> isize { if argc > 1 { unsafe { match **argv.offset(1) { @@ -36,22 +36,22 @@ fn start(argc: int, argv: *const *const u8) -> int { } let args = unsafe { - (0..argc as uint).map(|i| { - let ptr = *argv.offset(i as int) as *const _; - ffi::c_str_to_bytes(&ptr).to_vec() + (0..argc as usize).map(|i| { + let ptr = *argv.offset(i as isize) as *const _; + CStr::from_ptr(ptr).to_bytes().to_vec() }).collect::>() }; let me = &*args[0]; - let x: &[u8] = &[1u8]; + let x: &[u8] = &[1]; pass(Command::new(me).arg(x).output().unwrap()); - let x: &[u8] = &[2u8]; + let x: &[u8] = &[2]; pass(Command::new(me).arg(x).output().unwrap()); - let x: &[u8] = &[3u8]; + let x: &[u8] = &[3]; pass(Command::new(me).arg(x).output().unwrap()); - let x: &[u8] = &[4u8]; + let x: &[u8] = &[4]; pass(Command::new(me).arg(x).output().unwrap()); - let x: &[u8] = &[5u8]; + let x: &[u8] = &[5]; pass(Command::new(me).arg(x).output().unwrap()); 0 diff --git a/src/test/run-pass/rust-log-filter.rs b/src/test/run-pass/rust-log-filter.rs index 5d6657c7e1..660b1e2036 100644 --- a/src/test/run-pass/rust-log-filter.rs +++ b/src/test/run-pass/rust-log-filter.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// exec-env:RUST_LOG=rust-log-filter/foo +// exec-env:RUST_LOG=rust_log_filter/foo + +// pretty-expanded FIXME #23616 #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, std_misc, rustc_private)] #[macro_use] extern crate log; use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread::Thread; +use std::thread; pub struct ChannelLogger { tx: Sender @@ -39,7 +41,7 @@ impl log::Logger for ChannelLogger { pub fn main() { let (logger, rx) = ChannelLogger::new(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { log::set_logger(logger); info!("foo"); diff --git a/src/test/run-pass/segfault-no-out-of-stack.rs b/src/test/run-pass/segfault-no-out-of-stack.rs index 492736c225..6eb9600cf8 100644 --- a/src/test/run-pass/segfault-no-out-of-stack.rs +++ b/src/test/run-pass/segfault-no-out-of-stack.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(old_io)] + use std::old_io::process::Command; use std::env; fn main() { let args: Vec = env::args().collect(); if args.len() > 1 && args[1] == "segfault" { - unsafe { *(0 as *mut int) = 1 }; // trigger a segfault + unsafe { *(0 as *mut isize) = 1 }; // trigger a segfault } else { let segfault = Command::new(&args[0]).arg("segfault").output().unwrap(); assert!(!segfault.status.success()); diff --git a/src/test/run-pass/self-impl.rs b/src/test/run-pass/self-impl.rs index af2b2de8ab..c32773aa88 100644 --- a/src/test/run-pass/self-impl.rs +++ b/src/test/run-pass/self-impl.rs @@ -10,6 +10,8 @@ // Test that we can use `Self` types in impls in the expected way. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -32,7 +34,7 @@ trait Bar { fn dummy(&self, x: X) { } } -impl Bar for Box> { +impl Bar for Box> { fn bar(_x: Self, _y: &Self, _z: Box) -> Self { box Baz { f: 42 } } @@ -40,7 +42,7 @@ impl Bar for Box> { fn main() { let _: Foo = Foo::foo(Foo, &Foo, box Foo); - let _: Box> = Bar::bar(box Baz { f: 42 }, + let _: Box> = Bar::bar(box Baz { f: 42 }, &box Baz { f: 42 }, box box Baz { f: 42 }); } diff --git a/src/test/run-pass/self-in-mut-slot-default-method.rs b/src/test/run-pass/self-in-mut-slot-default-method.rs index e934498ea0..f8502137be 100644 --- a/src/test/run-pass/self-in-mut-slot-default-method.rs +++ b/src/test/run-pass/self-in-mut-slot-default-method.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct X { - a: int + a: isize } trait Changer : Sized { @@ -26,11 +28,11 @@ trait Changer : Sized { self } - fn set_to(&mut self, a: int); + fn set_to(&mut self, a: isize); } impl Changer for X { - fn set_to(&mut self, a: int) { + fn set_to(&mut self, a: isize) { self.a = a; } } @@ -40,7 +42,7 @@ pub fn main() { let new_x = x.change(); assert_eq!(new_x.a, 55); - let x = box new_x; + let x: Box<_> = box new_x; let new_x = x.change_again(); assert_eq!(new_x.a, 45); } diff --git a/src/test/run-pass/self-in-mut-slot-immediate-value.rs b/src/test/run-pass/self-in-mut-slot-immediate-value.rs index a4b5ea1d68..fa9ad9f651 100644 --- a/src/test/run-pass/self-in-mut-slot-immediate-value.rs +++ b/src/test/run-pass/self-in-mut-slot-immediate-value.rs @@ -11,9 +11,11 @@ // Assert that `mut self` on an immediate value doesn't // allow mutating the original - issue #10615. -#[derive(Copy)] +// pretty-expanded FIXME #23616 + +#[derive(Copy, Clone)] struct Value { - n: int + n: isize } impl Value { diff --git a/src/test/run-pass/self-re-assign.rs b/src/test/run-pass/self-re-assign.rs index cf09737e32..b3c81cab3c 100644 --- a/src/test/run-pass/self-re-assign.rs +++ b/src/test/run-pass/self-re-assign.rs @@ -11,13 +11,15 @@ // Ensure assigning an owned or managed variable to itself works. In particular, // that we do not glue_drop before we glue_take (#3290). +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] use std::rc::Rc; pub fn main() { - let mut x = box 3; + let mut x: Box<_> = box 3; x = x; assert!(*x == 3); diff --git a/src/test/run-pass/self-shadowing-import.rs b/src/test/run-pass/self-shadowing-import.rs index 19fdd04069..5de1686ef9 100644 --- a/src/test/run-pass/self-shadowing-import.rs +++ b/src/test/run-pass/self-shadowing-import.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod a { pub mod b { pub mod a { - pub fn foo() -> int { return 1; } + pub fn foo() -> isize { return 1; } } } } diff --git a/src/test/run-pass/self-type-param.rs b/src/test/run-pass/self-type-param.rs index 5c4e2f5ebd..ac810606a9 100644 --- a/src/test/run-pass/self-type-param.rs +++ b/src/test/run-pass/self-type-param.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait MyTrait { fn f(&self) -> Self; } struct S { - x: int + x: isize } impl MyTrait for S { diff --git a/src/test/run-pass/send-is-not-static-par-for.rs b/src/test/run-pass/send-is-not-static-par-for.rs old mode 100755 new mode 100644 index c6b64d97fb..99ae3b7c7d --- a/src/test/run-pass/send-is-not-static-par-for.rs +++ b/src/test/run-pass/send-is-not-static-par-for.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(core, std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::Mutex; fn par_for(iter: I, f: F) @@ -19,7 +21,7 @@ fn par_for(iter: I, f: F) { let f = &f; let _guards: Vec<_> = iter.map(|elem| { - Thread::scoped(move || { + thread::scoped(move || { f(elem) }) }).collect(); diff --git a/src/test/run-pass/send-resource.rs b/src/test/run-pass/send-resource.rs index a920d76e7c..3f64b2adb6 100644 --- a/src/test/run-pass/send-resource.rs +++ b/src/test/run-pass/send-resource.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::channel; struct test { - f: int, + f: isize, } impl Drop for test { fn drop(&mut self) {} } -fn test(f: int) -> test { +fn test(f: isize) -> test { test { f: f } @@ -28,7 +32,7 @@ fn test(f: int) -> test { pub fn main() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let (tx2, rx2) = channel(); tx.send(tx2).unwrap(); diff --git a/src/test/run-pass/send-type-inference.rs b/src/test/run-pass/send-type-inference.rs index 60093803f0..84d491d052 100644 --- a/src/test/run-pass/send-type-inference.rs +++ b/src/test/run-pass/send-type-inference.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::{channel, Sender}; // tests that ctrl's type gets inferred properly diff --git a/src/test/run-pass/send_str_hashmap.rs b/src/test/run-pass/send_str_hashmap.rs index 33e4fa85bc..16a695f08f 100644 --- a/src/test/run-pass/send_str_hashmap.rs +++ b/src/test/run-pass/send_str_hashmap.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections, into_cow)] + extern crate collections; use std::collections::HashMap; @@ -16,7 +20,7 @@ use std::borrow::{Cow, IntoCow}; type SendStr = Cow<'static, str>; pub fn main() { - let mut map: HashMap = HashMap::new(); + let mut map: HashMap = HashMap::new(); assert!(map.insert("foo".into_cow(), 42).is_none()); assert!(map.insert("foo".to_string().into_cow(), 42).is_some()); assert!(map.insert("foo".into_cow(), 42).is_some()); diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index 3390369242..d56657ee4d 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections, into_cow)] + extern crate collections; use self::collections::BTreeMap; @@ -16,7 +20,7 @@ use std::borrow::{Cow, IntoCow}; type SendStr = Cow<'static, str>; pub fn main() { - let mut map: BTreeMap = BTreeMap::new(); + let mut map: BTreeMap = BTreeMap::new(); assert!(map.insert("foo".into_cow(), 42).is_none()); assert!(map.insert("foo".to_string().into_cow(), 42).is_some()); assert!(map.insert("foo".into_cow(), 42).is_some()); diff --git a/src/test/run-pass/sendable-class.rs b/src/test/run-pass/sendable-class.rs index 8691d5e875..4fb1c32952 100644 --- a/src/test/run-pass/sendable-class.rs +++ b/src/test/run-pass/sendable-class.rs @@ -10,14 +10,16 @@ // Test that a class with only sendable fields can be sent +// pretty-expanded FIXME #23616 + use std::sync::mpsc::channel; struct foo { - i: int, + i: isize, j: char, } -fn foo(i:int, j: char) -> foo { +fn foo(i:isize, j: char) -> foo { foo { i: i, j: j diff --git a/src/test/run-pass/sendfn-is-a-block.rs b/src/test/run-pass/sendfn-is-a-block.rs index 18519573c2..59b92ec6a4 100644 --- a/src/test/run-pass/sendfn-is-a-block.rs +++ b/src/test/run-pass/sendfn-is-a-block.rs @@ -9,11 +9,13 @@ // except according to those terms. -fn test(f: F) -> uint where F: FnOnce(uint) -> uint { - return f(22_usize); +// pretty-expanded FIXME #23616 + +fn test(f: F) -> usize where F: FnOnce(usize) -> usize { + return f(22); } pub fn main() { - let y = test(|x| 4_usize * x); - assert_eq!(y, 88_usize); + let y = test(|x| 4 * x); + assert_eq!(y, 88); } diff --git a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs index 523b752810..63ffa55240 100644 --- a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs +++ b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs @@ -15,13 +15,13 @@ use std::thread; pub fn main() { test05(); } -fn test05_start(f: F) { +fn test05_start(f: F) { f(22); } fn test05() { - let three = box 3; - let fn_to_send = move|n:int| { + let three: Box<_> = box 3; + let fn_to_send = move|n:isize| { println!("{}", *three + n); // will copy x into the closure assert_eq!(*three, 3); }; diff --git a/src/test/run-pass/sepcomp-cci.rs b/src/test/run-pass/sepcomp-cci.rs index 0178b5e786..6a92f32c0b 100644 --- a/src/test/run-pass/sepcomp-cci.rs +++ b/src/test/run-pass/sepcomp-cci.rs @@ -13,23 +13,25 @@ // Test accessing cross-crate inlined items from multiple compilation units. +// pretty-expanded FIXME #23616 + extern crate sepcomp_cci_lib; use sepcomp_cci_lib::{cci_fn, CCI_STATIC}; -fn call1() -> uint { +fn call1() -> usize { cci_fn() + CCI_STATIC } mod a { use sepcomp_cci_lib::{cci_fn, CCI_STATIC}; - pub fn call2() -> uint { + pub fn call2() -> usize { cci_fn() + CCI_STATIC } } mod b { use sepcomp_cci_lib::{cci_fn, CCI_STATIC}; - pub fn call3() -> uint { + pub fn call3() -> usize { cci_fn() + CCI_STATIC } } diff --git a/src/test/run-pass/sepcomp-extern.rs b/src/test/run-pass/sepcomp-extern.rs index a5506e3fc7..f91c3d1ff3 100644 --- a/src/test/run-pass/sepcomp-extern.rs +++ b/src/test/run-pass/sepcomp-extern.rs @@ -13,24 +13,26 @@ // Test accessing external items from multiple compilation units. -#[link(name = "sepcomp-extern-lib")] +// pretty-expanded FIXME #23616 + +#[link(name = "sepcomp_extern_lib")] extern { #[allow(ctypes)] - fn foo() -> uint; + fn foo() -> usize; } -fn call1() -> uint { +fn call1() -> usize { unsafe { foo() } } mod a { - pub fn call2() -> uint { + pub fn call2() -> usize { unsafe { ::foo() } } } mod b { - pub fn call3() -> uint { + pub fn call3() -> usize { unsafe { ::foo() } } } diff --git a/src/test/run-pass/sepcomp-fns-backwards.rs b/src/test/run-pass/sepcomp-fns-backwards.rs index 61f008ad85..2e510082e2 100644 --- a/src/test/run-pass/sepcomp-fns-backwards.rs +++ b/src/test/run-pass/sepcomp-fns-backwards.rs @@ -15,21 +15,23 @@ // Generate some code in the first compilation unit before declaring any // modules. This ensures that the first module doesn't go into the same // compilation unit as the top-level module. -fn pad() -> uint { 0 } +// pretty-expanded FIXME #23616 + +fn pad() -> usize { 0 } mod b { - pub fn three() -> uint { + pub fn three() -> usize { ::one() + ::a::two() } } mod a { - pub fn two() -> uint { + pub fn two() -> usize { ::one() + ::one() } } -fn one() -> uint { +fn one() -> usize { 1 } @@ -38,4 +40,3 @@ fn main() { assert_eq!(a::two(), 2); assert_eq!(b::three(), 3); } - diff --git a/src/test/run-pass/sepcomp-fns.rs b/src/test/run-pass/sepcomp-fns.rs index 09f2a4281b..f4fa0ed569 100644 --- a/src/test/run-pass/sepcomp-fns.rs +++ b/src/test/run-pass/sepcomp-fns.rs @@ -17,16 +17,18 @@ // Generate some code in the first compilation unit before declaring any // modules. This ensures that the first module doesn't go into the same // compilation unit as the top-level module. -fn one() -> uint { 1 } +// pretty-expanded FIXME #23616 + +fn one() -> usize { 1 } mod a { - pub fn two() -> uint { + pub fn two() -> usize { ::one() + ::one() } } mod b { - pub fn three() -> uint { + pub fn three() -> usize { ::one() + ::a::two() } } diff --git a/src/test/run-pass/sepcomp-lib-lto.rs b/src/test/run-pass/sepcomp-lib-lto.rs index f0b6a50592..b159b12833 100644 --- a/src/test/run-pass/sepcomp-lib-lto.rs +++ b/src/test/run-pass/sepcomp-lib-lto.rs @@ -14,6 +14,7 @@ // aux-build:sepcomp_lib.rs // compile-flags: -C lto // no-prefer-dynamic +// ignore-android FIXME #18800 extern crate sepcomp_lib; use sepcomp_lib::a::one; diff --git a/src/test/run-pass/sepcomp-lib.rs b/src/test/run-pass/sepcomp-lib.rs index 28adb55399..00e83a5705 100644 --- a/src/test/run-pass/sepcomp-lib.rs +++ b/src/test/run-pass/sepcomp-lib.rs @@ -12,6 +12,8 @@ // Test linking against a library built with -C codegen-units > 1 +// pretty-expanded FIXME #23616 + extern crate sepcomp_lib; use sepcomp_lib::a::one; use sepcomp_lib::b::two; diff --git a/src/test/run-pass/sepcomp-statics.rs b/src/test/run-pass/sepcomp-statics.rs index 26a5c4d1c5..e926114e21 100644 --- a/src/test/run-pass/sepcomp-statics.rs +++ b/src/test/run-pass/sepcomp-statics.rs @@ -12,23 +12,25 @@ // Test references to static items across compilation units. -fn pad() -> uint { 0 } +// pretty-expanded FIXME #23616 -const ONE: uint = 1; +fn pad() -> usize { 0 } + +const ONE: usize = 1; mod b { // Separate compilation always switches to the LLVM module with the fewest // instructions. Make sure we have some instructions in this module so // that `a` and `b` don't go into the same compilation unit. - fn pad() -> uint { 0 } + fn pad() -> usize { 0 } - pub static THREE: uint = ::ONE + ::a::TWO; + pub static THREE: usize = ::ONE + ::a::TWO; } mod a { - fn pad() -> uint { 0 } + fn pad() -> usize { 0 } - pub const TWO: uint = ::ONE + ::ONE; + pub const TWO: usize = ::ONE + ::ONE; } fn main() { @@ -36,4 +38,3 @@ fn main() { assert_eq!(a::TWO, 2); assert_eq!(b::THREE, 3); } - diff --git a/src/test/run-pass/sepcomp-unwind.rs b/src/test/run-pass/sepcomp-unwind.rs index 21c5a6fc83..71d3d91e84 100644 --- a/src/test/run-pass/sepcomp-unwind.rs +++ b/src/test/run-pass/sepcomp-unwind.rs @@ -19,9 +19,11 @@ // In any case, this test should let us know if enabling parallel codegen ever // breaks unwinding. +// pretty-expanded FIXME #23616 + use std::thread; -fn pad() -> uint { 0 } +fn pad() -> usize { 0 } mod a { pub fn f() { diff --git a/src/test/run-pass/seq-compare.rs b/src/test/run-pass/seq-compare.rs index ef14e0ba93..743f54abcf 100644 --- a/src/test/run-pass/seq-compare.rs +++ b/src/test/run-pass/seq-compare.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert!(("hello".to_string() < "hellr".to_string())); assert!(("hello ".to_string() > "hello".to_string())); diff --git a/src/test/run-pass/shadow.rs b/src/test/run-pass/shadow.rs index 6e03c1e4a8..3b719d1806 100644 --- a/src/test/run-pass/shadow.rs +++ b/src/test/run-pass/shadow.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(c: Vec ) { - let a: int = 5; - let mut b: Vec = Vec::new(); +fn foo(c: Vec ) { + let a: isize = 5; + let mut b: Vec = Vec::new(); - match t::none:: { - t::some::(_) => { + match t::none:: { + t::some::(_) => { for _i in &c { println!("{}", a); let a = 17; diff --git a/src/test/run-pass/shift-near-oflo.rs b/src/test/run-pass/shift-near-oflo.rs new file mode 100644 index 0000000000..4ff058f336 --- /dev/null +++ b/src/test/run-pass/shift-near-oflo.rs @@ -0,0 +1,100 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C debug-assertions + +// Check that we do *not* overflow on a number of edge cases. +// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs) + +// (Work around constant-evaluation) +fn id(x: T) -> T { x } + +fn main() { + test_left_shift(); + test_right_shift(); +} + +fn test_left_shift() { + // negative rhs can panic, but values in [0,N-1] are okay for iN + + macro_rules! tests { + ($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { { + let x = (1 as $iN) << id(0); + assert_eq!(x, 1); + let x = (1 as $uN) << id(0); + assert_eq!(x, 1); + let x = (1 as $iN) << id($max_rhs); + assert_eq!(x, $expect_i); + let x = (1 as $uN) << id($max_rhs); + assert_eq!(x, $expect_u); + // high-order bits on LHS are silently discarded without panic. + let x = (3 as $iN) << id($max_rhs); + assert_eq!(x, $expect_i); + let x = (3 as $uN) << id($max_rhs); + assert_eq!(x, $expect_u); + } } + } + + let x = 1_i8 << id(0); + assert_eq!(x, 1); + let x = 1_u8 << id(0); + assert_eq!(x, 1); + let x = 1_i8 << id(7); + assert_eq!(x, std::i8::MIN); + let x = 1_u8 << id(7); + assert_eq!(x, 0x80); + // high-order bits on LHS are silently discarded without panic. + let x = 3_i8 << id(7); + assert_eq!(x, std::i8::MIN); + let x = 3_u8 << id(7); + assert_eq!(x, 0x80); + + // above is (approximately) expanded from: + tests!(i8, u8, 7, std::i8::MIN, 0x80_u8); + + tests!(i16, u16, 15, std::i16::MIN, 0x8000_u16); + tests!(i32, u32, 31, std::i32::MIN, 0x8000_0000_u32); + tests!(i64, u64, 63, std::i64::MIN, 0x8000_0000_0000_0000_u64); +} + +fn test_right_shift() { + // negative rhs can panic, but values in [0,N-1] are okay for iN + + macro_rules! tests { + ($iN:ty, $uN:ty, $max_rhs:expr, + $signbit_i:expr, $highbit_i:expr, $highbit_u:expr) => + { { + let x = (1 as $iN) >> id(0); + assert_eq!(x, 1); + let x = (1 as $uN) >> id(0); + assert_eq!(x, 1); + let x = ($highbit_i) >> id($max_rhs-1); + assert_eq!(x, 1); + let x = ($highbit_u) >> id($max_rhs); + assert_eq!(x, 1); + // sign-bit is carried by arithmetic right shift + let x = ($signbit_i) >> id($max_rhs); + assert_eq!(x, -1); + // low-order bits on LHS are silently discarded without panic. + let x = ($highbit_i + 1) >> id($max_rhs-1); + assert_eq!(x, 1); + let x = ($highbit_u + 1) >> id($max_rhs); + assert_eq!(x, 1); + let x = ($signbit_i + 1) >> id($max_rhs); + assert_eq!(x, -1); + } } + } + + tests!(i8, u8, 7, std::i8::MIN, 0x40_i8, 0x80_u8); + tests!(i16, u16, 15, std::i16::MIN, 0x4000_u16, 0x8000_u16); + tests!(i32, u32, 31, std::i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32); + tests!(i64, u64, 63, std::i64::MIN, + 0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64); +} diff --git a/src/test/run-pass/shift-various-types.rs b/src/test/run-pass/shift-various-types.rs index 2f56e09b2d..b0ab72c650 100644 --- a/src/test/run-pass/shift-various-types.rs +++ b/src/test/run-pass/shift-various-types.rs @@ -10,6 +10,8 @@ // Test that we can do shifts by any integral type. +// pretty-expanded FIXME #23616 + struct Panolpy { i8: i8, i16: i16, @@ -25,17 +27,17 @@ struct Panolpy { } fn foo(p: &Panolpy) { - assert_eq!(22_i32 >> p.i8, 11_i32); - assert_eq!(22_i32 >> p.i16, 11_i32); - assert_eq!(22_i32 >> p.i32, 11_i32); - assert_eq!(22_i32 >> p.i64, 11_i32); - assert_eq!(22_i32 >> p.isize, 11_i32); - - assert_eq!(22_i32 >> p.u8, 11_i32); - assert_eq!(22_i32 >> p.u16, 11_i32); - assert_eq!(22_i32 >> p.u32, 11_i32); - assert_eq!(22_i32 >> p.u64, 11_i32); - assert_eq!(22_i32 >> p.usize, 11_i32); + assert_eq!(22 >> p.i8, 11); + assert_eq!(22 >> p.i16, 11); + assert_eq!(22 >> p.i32, 11); + assert_eq!(22 >> p.i64, 11); + assert_eq!(22 >> p.isize, 11); + + assert_eq!(22 >> p.u8, 11); + assert_eq!(22 >> p.u16, 11); + assert_eq!(22 >> p.u32, 11); + assert_eq!(22 >> p.u64, 11); + assert_eq!(22 >> p.usize, 11); } fn main() { diff --git a/src/test/run-pass/shift.rs b/src/test/run-pass/shift.rs index 918da53509..f1637fe1e0 100644 --- a/src/test/run-pass/shift.rs +++ b/src/test/run-pass/shift.rs @@ -11,6 +11,8 @@ // Testing shifts for various combinations of integers // Issue #1570 +// pretty-expanded FIXME #23616 + pub fn main() { test_misc(); test_expr(); @@ -22,60 +24,60 @@ fn test_misc() { } fn test_expr() { - let v10 = 10 as uint; + let v10 = 10 as usize; let v4 = 4 as u8; let v2 = 2 as u8; - assert_eq!(v10 >> v2 as uint, v2 as uint); - assert_eq!(v10 << v4 as uint, 160 as uint); + assert_eq!(v10 >> v2 as usize, v2 as usize); + assert_eq!(v10 << v4 as usize, 160 as usize); let v10 = 10 as u8; - let v4 = 4 as uint; - let v2 = 2 as uint; - assert_eq!(v10 >> v2 as uint, v2 as u8); - assert_eq!(v10 << v4 as uint, 160 as u8); + let v4 = 4 as usize; + let v2 = 2 as usize; + assert_eq!(v10 >> v2 as usize, v2 as u8); + assert_eq!(v10 << v4 as usize, 160 as u8); - let v10 = 10 as int; + let v10 = 10 as isize; let v4 = 4 as i8; let v2 = 2 as i8; - assert_eq!(v10 >> v2 as uint, v2 as int); - assert_eq!(v10 << v4 as uint, 160 as int); + assert_eq!(v10 >> v2 as usize, v2 as isize); + assert_eq!(v10 << v4 as usize, 160 as isize); let v10 = 10 as i8; - let v4 = 4 as int; - let v2 = 2 as int; - assert_eq!(v10 >> v2 as uint, v2 as i8); - assert_eq!(v10 << v4 as uint, 160 as i8); + let v4 = 4 as isize; + let v2 = 2 as isize; + assert_eq!(v10 >> v2 as usize, v2 as i8); + assert_eq!(v10 << v4 as usize, 160 as i8); - let v10 = 10 as uint; - let v4 = 4 as int; - let v2 = 2 as int; - assert_eq!(v10 >> v2 as uint, v2 as uint); - assert_eq!(v10 << v4 as uint, 160 as uint); + let v10 = 10 as usize; + let v4 = 4 as isize; + let v2 = 2 as isize; + assert_eq!(v10 >> v2 as usize, v2 as usize); + assert_eq!(v10 << v4 as usize, 160 as usize); } fn test_const() { - static r1_1: uint = 10_usize >> 2_usize; - static r2_1: uint = 10_usize << 4_usize; - assert_eq!(r1_1, 2 as uint); - assert_eq!(r2_1, 160 as uint); + static r1_1: usize = 10_usize >> 2_usize; + static r2_1: usize = 10_usize << 4_usize; + assert_eq!(r1_1, 2 as usize); + assert_eq!(r2_1, 160 as usize); static r1_2: u8 = 10u8 >> 2_usize; static r2_2: u8 = 10u8 << 4_usize; assert_eq!(r1_2, 2 as u8); assert_eq!(r2_2, 160 as u8); - static r1_3: int = 10 >> 2_usize; - static r2_3: int = 10 << 4_usize; - assert_eq!(r1_3, 2 as int); - assert_eq!(r2_3, 160 as int); + static r1_3: isize = 10 >> 2_usize; + static r2_3: isize = 10 << 4_usize; + assert_eq!(r1_3, 2 as isize); + assert_eq!(r2_3, 160 as isize); static r1_4: i8 = 10i8 >> 2_usize; static r2_4: i8 = 10i8 << 4_usize; assert_eq!(r1_4, 2 as i8); assert_eq!(r2_4, 160 as i8); - static r1_5: uint = 10_usize >> 2_usize; - static r2_5: uint = 10_usize << 4_usize; - assert_eq!(r1_5, 2 as uint); - assert_eq!(r2_5, 160 as uint); + static r1_5: usize = 10_usize >> 2_usize; + static r2_5: usize = 10_usize << 4_usize; + assert_eq!(r1_5, 2 as usize); + assert_eq!(r2_5, 160 as usize); } diff --git a/src/test/run-pass/show-boxed-slice.rs b/src/test/run-pass/show-boxed-slice.rs index f496765edc..0397166818 100644 --- a/src/test/run-pass/show-boxed-slice.rs +++ b/src/test/run-pass/show-boxed-slice.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] - #[derive(Debug)] struct Foo(Box<[u8]>); pub fn main() { - println!("{:?}", Foo(box [0, 1, 2])); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + println!("{:?}", Foo(Box::new([0, 1, 2]))); } diff --git a/src/test/run-pass/signal-exit-status.rs b/src/test/run-pass/signal-exit-status.rs index 776d897938..bfc4aee775 100644 --- a/src/test/run-pass/signal-exit-status.rs +++ b/src/test/run-pass/signal-exit-status.rs @@ -10,6 +10,9 @@ // ignore-windows +#![feature(old_io)] +#![feature(os)] + use std::env; use std::old_io::process::{Command, ExitSignal, ExitStatus}; @@ -17,7 +20,7 @@ pub fn main() { let args: Vec = env::args().collect(); if args.len() >= 2 && args[1] == "signal" { // Raise a segfault. - unsafe { *(0 as *mut int) = 0; } + unsafe { *(0 as *mut isize) = 0; } } else { let status = Command::new(&args[0]).arg("signal").status().unwrap(); // Windows does not have signal, so we get exit status 0xC0000028 (STATUS_BAD_STACK). diff --git a/src/test/run-pass/signed-shift-const-eval.rs b/src/test/run-pass/signed-shift-const-eval.rs index 2acb93f48f..7167236438 100644 --- a/src/test/run-pass/signed-shift-const-eval.rs +++ b/src/test/run-pass/signed-shift-const-eval.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum test { thing = -5 >> 1_usize } pub fn main() { - assert_eq!(test::thing as int, -3); + assert_eq!(test::thing as isize, -3); } diff --git a/src/test/run-pass/sigpipe-should-be-ignored.rs b/src/test/run-pass/sigpipe-should-be-ignored.rs index d1428c6be1..4a05b487ae 100644 --- a/src/test/run-pass/sigpipe-should-be-ignored.rs +++ b/src/test/run-pass/sigpipe-should-be-ignored.rs @@ -11,18 +11,18 @@ // Be sure that when a SIGPIPE would have been received that the entire process // doesn't die in a ball of fire, but rather it's gracefully handled. -use std::os; +// ignore-aarch64 +// pretty-expanded FIXME #23616 + use std::env; -use std::old_io::PipeStream; -use std::old_io::Command; +use std::io::prelude::*; +use std::io; +use std::process::{Command, Stdio}; fn test() { - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - let reader = PipeStream::open(reader); - let mut writer = PipeStream::open(writer); - drop(reader); - - let _ = writer.write(&[1]); + let _ = io::stdin().read_line(&mut String::new()); + io::stdout().write(&[1]); + assert!(io::stdout().flush().is_err()); } fn main() { @@ -32,6 +32,9 @@ fn main() { } let mut p = Command::new(&args[0]) + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) .arg("test").spawn().unwrap(); + drop(p.stdout.take()); assert!(p.wait().unwrap().success()); } diff --git a/src/test/run-pass/simd-binop.rs b/src/test/run-pass/simd-binop.rs index 779e507f43..9f7b78e4e3 100644 --- a/src/test/run-pass/simd-binop.rs +++ b/src/test/run-pass/simd-binop.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] use std::simd::{i32x4, f32x4, u32x4}; @@ -29,6 +32,7 @@ pub fn main() { assert!(eq_u32x4(u32x4(1, 2, 3, 4) + u32x4(4, 3, 2, 1), u32x4(5, 5, 5, 5))); assert!(eq_u32x4(u32x4(4, 5, 6, 7) - u32x4(4, 3, 2, 1), u32x4(0, 2, 4, 6))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) * u32x4(4, 3, 2, 1), u32x4(4, 6, 6, 4))); + assert!(eq_u32x4(u32x4(1, 2, 3, 4) / u32x4(4, 3, 2, 1), u32x4(0, 0, 1, 4))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) & u32x4(4, 3, 2, 1), u32x4(0, 2, 2, 0))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) | u32x4(4, 3, 2, 1), u32x4(5, 3, 3, 5))); assert!(eq_u32x4(u32x4(1, 2, 3, 4) ^ u32x4(4, 3, 2, 1), u32x4(5, 1, 1, 5))); @@ -38,6 +42,7 @@ pub fn main() { assert!(eq_i32x4(i32x4(1, 2, 3, 4) + i32x4(4, 3, 2, 1), i32x4(5, 5, 5, 5))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) - i32x4(4, 3, 2, 1), i32x4(-3, -1, 1, 3))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) * i32x4(4, 3, 2, 1), i32x4(4, 6, 6, 4))); + assert!(eq_i32x4(i32x4(1, 2, 3, 4) / i32x4(4, 3, 2, 1), i32x4(0, 0, 1, 4))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) & i32x4(4, 3, 2, 1), i32x4(0, 2, 2, 0))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) | i32x4(4, 3, 2, 1), i32x4(5, 3, 3, 5))); assert!(eq_i32x4(i32x4(1, 2, 3, 4) ^ i32x4(4, 3, 2, 1), i32x4(5, 1, 1, 5))); diff --git a/src/test/run-pass/simd-generics.rs b/src/test/run-pass/simd-generics.rs index 1371c4cc5f..867f028a3f 100644 --- a/src/test/run-pass/simd-generics.rs +++ b/src/test/run-pass/simd-generics.rs @@ -9,12 +9,14 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(simd)] use std::ops; #[simd] -#[derive(Copy)] +#[derive(Copy, Clone)] struct f32x4(f32, f32, f32, f32); fn add>(lhs: T, rhs: T) -> T { diff --git a/src/test/run-pass/simd-issue-10604.rs b/src/test/run-pass/simd-issue-10604.rs index 7f1be4b7d7..8dca78b28e 100644 --- a/src/test/run-pass/simd-issue-10604.rs +++ b/src/test/run-pass/simd-issue-10604.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 +#![feature(core)] #![feature(simd)] pub fn main() { diff --git a/src/test/run-pass/simd-size-align.rs b/src/test/run-pass/simd-size-align.rs index 582810f0de..8324efc641 100644 --- a/src/test/run-pass/simd-size-align.rs +++ b/src/test/run-pass/simd-size-align.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(simd)] #![allow(non_camel_case_types)] diff --git a/src/test/run-pass/simd-type.rs b/src/test/run-pass/simd-type.rs index a1a7457811..540666f41a 100644 --- a/src/test/run-pass/simd-type.rs +++ b/src/test/run-pass/simd-type.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(simd)] #[simd] diff --git a/src/test/run-pass/simple-generic-match.rs b/src/test/run-pass/simple-generic-match.rs index 27d4f105f3..02fc2a61d0 100644 --- a/src/test/run-pass/simple-generic-match.rs +++ b/src/test/run-pass/simple-generic-match.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + enum clam { a(T), } -pub fn main() { let c = clam::a(2); match c { clam::a::(_) => { } } } +pub fn main() { let c = clam::a(2); match c { clam::a::(_) => { } } } diff --git a/src/test/run-pass/simple-generic-tag.rs b/src/test/run-pass/simple-generic-tag.rs index 8a36f9e17f..2e8d8f61bc 100644 --- a/src/test/run-pass/simple-generic-tag.rs +++ b/src/test/run-pass/simple-generic-tag.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + enum clam { a(T), } pub fn main() { } diff --git a/src/test/run-pass/simple-match-generic-tag.rs b/src/test/run-pass/simple-match-generic-tag.rs index 2217dddbd2..52989b3666 100644 --- a/src/test/run-pass/simple-match-generic-tag.rs +++ b/src/test/run-pass/simple-match-generic-tag.rs @@ -11,9 +11,9 @@ enum opt { none, some(T) } pub fn main() { - let x = opt::none::; + let x = opt::none::; match x { - opt::none:: => { println!("hello world"); } + opt::none:: => { println!("hello world"); } opt::some(_) => { } } } diff --git a/src/test/run-pass/single-derive-attr-with-gate.rs b/src/test/run-pass/single-derive-attr-with-gate.rs new file mode 100644 index 0000000000..addc56e9c4 --- /dev/null +++ b/src/test/run-pass/single-derive-attr-with-gate.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![feature(custom_derive)] + +#[derive_Clone] +struct Test; + +pub fn main() { + Test.clone(); +} diff --git a/src/test/run-pass/size-and-align.rs b/src/test/run-pass/size-and-align.rs index 4b587ae70a..007ce52d7c 100644 --- a/src/test/run-pass/size-and-align.rs +++ b/src/test/run-pass/size-and-align.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -enum clam { a(T, int), b, } +enum clam { a(T, isize), b, } fn uhoh(v: Vec> ) { match v[1] { @@ -22,6 +22,6 @@ fn uhoh(v: Vec> ) { } pub fn main() { - let v: Vec> = vec!(clam::b::, clam::b::, clam::a::(42, 17)); - uhoh::(v); + let v: Vec> = vec!(clam::b::, clam::b::, clam::a::(42, 17)); + uhoh::(v); } diff --git a/src/test/run-pass/sized-borrowed-pointer.rs b/src/test/run-pass/sized-borrowed-pointer.rs index 348b7562f8..76c06d560d 100644 --- a/src/test/run-pass/sized-borrowed-pointer.rs +++ b/src/test/run-pass/sized-borrowed-pointer.rs @@ -10,6 +10,8 @@ // Possibly-dynamic size of typaram should be cleared at pointer boundary. +// pretty-expanded FIXME #23616 + fn bar() { } fn foo() { bar::<&T>() } pub fn main() { } diff --git a/src/test/run-pass/sized-owned-pointer.rs b/src/test/run-pass/sized-owned-pointer.rs index e64917a97a..d3a6b104db 100644 --- a/src/test/run-pass/sized-owned-pointer.rs +++ b/src/test/run-pass/sized-owned-pointer.rs @@ -11,6 +11,8 @@ // Possibly-dynamic size of typaram should be cleared at pointer boundary. +// pretty-expanded FIXME #23616 + fn bar() { } fn foo() { bar::>() } pub fn main() { } diff --git a/src/test/run-pass/slice-2.rs b/src/test/run-pass/slice-2.rs index 6e256be69d..7f34b94ad0 100644 --- a/src/test/run-pass/slice-2.rs +++ b/src/test/run-pass/slice-2.rs @@ -10,60 +10,62 @@ // Test slicing expressions on slices and Vecs. +// pretty-expanded FIXME #23616 + fn main() { - let x: &[int] = &[1, 2, 3, 4, 5]; - let cmp: &[int] = &[1, 2, 3, 4, 5]; + let x: &[isize] = &[1, 2, 3, 4, 5]; + let cmp: &[isize] = &[1, 2, 3, 4, 5]; assert!(&x[..] == cmp); - let cmp: &[int] = &[3, 4, 5]; + let cmp: &[isize] = &[3, 4, 5]; assert!(&x[2..] == cmp); - let cmp: &[int] = &[1, 2, 3]; + let cmp: &[isize] = &[1, 2, 3]; assert!(&x[..3] == cmp); - let cmp: &[int] = &[2, 3, 4]; + let cmp: &[isize] = &[2, 3, 4]; assert!(&x[1..4] == cmp); - let x: Vec = vec![1, 2, 3, 4, 5]; - let cmp: &[int] = &[1, 2, 3, 4, 5]; + let x: Vec = vec![1, 2, 3, 4, 5]; + let cmp: &[isize] = &[1, 2, 3, 4, 5]; assert!(&x[..] == cmp); - let cmp: &[int] = &[3, 4, 5]; + let cmp: &[isize] = &[3, 4, 5]; assert!(&x[2..] == cmp); - let cmp: &[int] = &[1, 2, 3]; + let cmp: &[isize] = &[1, 2, 3]; assert!(&x[..3] == cmp); - let cmp: &[int] = &[2, 3, 4]; + let cmp: &[isize] = &[2, 3, 4]; assert!(&x[1..4] == cmp); - let x: &mut [int] = &mut [1, 2, 3, 4, 5]; + let x: &mut [isize] = &mut [1, 2, 3, 4, 5]; { - let cmp: &mut [int] = &mut [1, 2, 3, 4, 5]; + let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5]; assert!(&mut x[..] == cmp); } { - let cmp: &mut [int] = &mut [3, 4, 5]; + let cmp: &mut [isize] = &mut [3, 4, 5]; assert!(&mut x[2..] == cmp); } { - let cmp: &mut [int] = &mut [1, 2, 3]; + let cmp: &mut [isize] = &mut [1, 2, 3]; assert!(&mut x[..3] == cmp); } { - let cmp: &mut [int] = &mut [2, 3, 4]; + let cmp: &mut [isize] = &mut [2, 3, 4]; assert!(&mut x[1..4] == cmp); } - let mut x: Vec = vec![1, 2, 3, 4, 5]; + let mut x: Vec = vec![1, 2, 3, 4, 5]; { - let cmp: &mut [int] = &mut [1, 2, 3, 4, 5]; + let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5]; assert!(&mut x[..] == cmp); } { - let cmp: &mut [int] = &mut [3, 4, 5]; + let cmp: &mut [isize] = &mut [3, 4, 5]; assert!(&mut x[2..] == cmp); } { - let cmp: &mut [int] = &mut [1, 2, 3]; + let cmp: &mut [isize] = &mut [1, 2, 3]; assert!(&mut x[..3] == cmp); } { - let cmp: &mut [int] = &mut [2, 3, 4]; + let cmp: &mut [isize] = &mut [2, 3, 4]; assert!(&mut x[1..4] == cmp); } } diff --git a/src/test/run-pass/slice-panic-1.rs b/src/test/run-pass/slice-panic-1.rs index 639ffd5600..a4f737f746 100644 --- a/src/test/run-pass/slice-panic-1.rs +++ b/src/test/run-pass/slice-panic-1.rs @@ -10,11 +10,13 @@ // Test that if a slicing expr[..] fails, the correct cleanups happen. +// pretty-expanded FIXME #23616 + use std::thread; struct Foo; -static mut DTOR_COUNT: int = 0; +static mut DTOR_COUNT: isize = 0; impl Drop for Foo { fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } diff --git a/src/test/run-pass/slice-panic-2.rs b/src/test/run-pass/slice-panic-2.rs index 4a2038175d..f02a84b907 100644 --- a/src/test/run-pass/slice-panic-2.rs +++ b/src/test/run-pass/slice-panic-2.rs @@ -10,17 +10,19 @@ // Test that if a slicing expr[..] fails, the correct cleanups happen. +// pretty-expanded FIXME #23616 + use std::thread; struct Foo; -static mut DTOR_COUNT: int = 0; +static mut DTOR_COUNT: isize = 0; impl Drop for Foo { fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } } -fn bar() -> uint { +fn bar() -> usize { panic!(); } diff --git a/src/test/run-pass/slice.rs b/src/test/run-pass/slice.rs index 30b53dbb0a..edc5f6b184 100644 --- a/src/test/run-pass/slice.rs +++ b/src/test/run-pass/slice.rs @@ -10,64 +10,66 @@ // Test slicing sugar. -#![feature(associated_types)] +// pretty-expanded FIXME #23616 + +#![feature(core)] extern crate core; use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull}; -static mut COUNT: uint = 0; +static mut COUNT: usize = 0; struct Foo; impl Index> for Foo { type Output = Foo; - fn index(&self, index: &Range) -> &Foo { + fn index(&self, index: Range) -> &Foo { unsafe { COUNT += 1; } self } } impl Index> for Foo { type Output = Foo; - fn index(&self, index: &RangeTo) -> &Foo { + fn index(&self, index: RangeTo) -> &Foo { unsafe { COUNT += 1; } self } } impl Index> for Foo { type Output = Foo; - fn index(&self, index: &RangeFrom) -> &Foo { + fn index(&self, index: RangeFrom) -> &Foo { unsafe { COUNT += 1; } self } } impl Index for Foo { type Output = Foo; - fn index(&self, _index: &RangeFull) -> &Foo { + fn index(&self, _index: RangeFull) -> &Foo { unsafe { COUNT += 1; } self } } impl IndexMut> for Foo { - fn index_mut(&mut self, index: &Range) -> &mut Foo { + fn index_mut(&mut self, index: Range) -> &mut Foo { unsafe { COUNT += 1; } self } } impl IndexMut> for Foo { - fn index_mut(&mut self, index: &RangeTo) -> &mut Foo { + fn index_mut(&mut self, index: RangeTo) -> &mut Foo { unsafe { COUNT += 1; } self } } impl IndexMut> for Foo { - fn index_mut(&mut self, index: &RangeFrom) -> &mut Foo { + fn index_mut(&mut self, index: RangeFrom) -> &mut Foo { unsafe { COUNT += 1; } self } } impl IndexMut for Foo { - fn index_mut(&mut self, _index: &RangeFull) -> &mut Foo { + fn index_mut(&mut self, _index: RangeFull) -> &mut Foo { unsafe { COUNT += 1; } self } diff --git a/src/test/run-pass/small-enum-range-edge.rs b/src/test/run-pass/small-enum-range-edge.rs index 35283e466c..9515da6fcb 100644 --- a/src/test/run-pass/small-enum-range-edge.rs +++ b/src/test/run-pass/small-enum-range-edge.rs @@ -8,27 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +// this is for the wrapping_add call below. +#![feature(core)] + /*! * Tests the range assertion wraparound case in trans::middle::adt::load_discr. */ #[repr(u8)] -#[derive(Copy)] +#[derive(Copy, Clone)] enum Eu { Lu = 0, Hu = 255 } static CLu: Eu = Eu::Lu; static CHu: Eu = Eu::Hu; #[repr(i8)] -#[derive(Copy)] +#[derive(Copy, Clone)] enum Es { Ls = -128, Hs = 127 } static CLs: Es = Es::Ls; static CHs: Es = Es::Hs; pub fn main() { - assert_eq!((Eu::Hu as u8) + 1, Eu::Lu as u8); - assert_eq!((Es::Hs as i8) + 1, Es::Ls as i8); + assert_eq!((Eu::Hu as u8).wrapping_add(1), Eu::Lu as u8); + assert_eq!((Es::Hs as i8).wrapping_add(1), Es::Ls as i8); assert_eq!(CLu as u8, Eu::Lu as u8); assert_eq!(CHu as u8, Eu::Hu as u8); assert_eq!(CLs as i8, Es::Ls as i8); diff --git a/src/test/run-pass/small-enums-with-fields.rs b/src/test/run-pass/small-enums-with-fields.rs index 475af8f2b8..86eed715f3 100644 --- a/src/test/run-pass/small-enums-with-fields.rs +++ b/src/test/run-pass/small-enums-with-fields.rs @@ -29,14 +29,14 @@ macro_rules! check { pub fn main() { check!(Option, 2, None, "None", - Some(129u8), "Some(129)"); + Some(129), "Some(129)"); check!(Option, 4, None, "None", - Some(-20000i16), "Some(-20000)"); + Some(-20000), "Some(-20000)"); check!(Either, 2, - Either::Left(132u8), "Left(132)", - Either::Right(-32i8), "Right(-32)"); + Either::Left(132), "Left(132)", + Either::Right(-32), "Right(-32)"); check!(Either, 4, - Either::Left(132u8), "Left(132)", - Either::Right(-20000i16), "Right(-20000)"); + Either::Left(132), "Left(132)", + Either::Right(-20000), "Right(-20000)"); } diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs index 61b2fc8b50..5e84ce19de 100644 --- a/src/test/run-pass/smallest-hello-world.rs +++ b/src/test/run-pass/smallest-hello-world.rs @@ -10,7 +10,9 @@ // Smallest "hello world" with a libc runtime -#![feature(intrinsics, lang_items, start, no_std)] +// pretty-expanded FIXME #23616 + +#![feature(intrinsics, lang_items, start, no_std, libc)] #![no_std] extern crate libc; @@ -24,9 +26,9 @@ extern "rust-intrinsic" { fn transmute(t: T) -> U; } #[start] #[no_stack_check] -fn main(_: int, _: *const *const u8) -> int { +fn main(_: isize, _: *const *const u8) -> isize { unsafe { - let (ptr, _): (*const u8, uint) = transmute("Hello!\0"); + let (ptr, _): (*const u8, usize) = transmute("Hello!\0"); puts(ptr); } return 0; diff --git a/src/test/run-pass/snake-case-no-lowercase-equivalent.rs b/src/test/run-pass/snake-case-no-lowercase-equivalent.rs index 2220761a02..90ea7537c6 100644 --- a/src/test/run-pass/snake-case-no-lowercase-equivalent.rs +++ b/src/test/run-pass/snake-case-no-lowercase-equivalent.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(non_ascii_idents)] #![deny(non_snake_case)] diff --git a/src/test/run-pass/spawn-fn.rs b/src/test/run-pass/spawn-fn.rs index c8fe400c4c..efddf0455c 100644 --- a/src/test/run-pass/spawn-fn.rs +++ b/src/test/run-pass/spawn-fn.rs @@ -8,21 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +use std::thread; -fn x(s: String, n: int) { +fn x(s: String, n: isize) { println!("{}", s); println!("{}", n); } pub fn main() { - let _t = Thread::spawn(|| x("hello from first spawned fn".to_string(), 65) ); - let _t = Thread::spawn(|| x("hello from second spawned fn".to_string(), 66) ); - let _t = Thread::spawn(|| x("hello from third spawned fn".to_string(), 67) ); - let mut i: int = 30; + let _t = thread::scoped(|| x("hello from first spawned fn".to_string(), 65) ); + let _t = thread::scoped(|| x("hello from second spawned fn".to_string(), 66) ); + let _t = thread::scoped(|| x("hello from third spawned fn".to_string(), 67) ); + let mut i = 30; while i > 0 { i = i - 1; println!("parent sleeping"); - Thread::yield_now(); + thread::yield_now(); } } diff --git a/src/test/run-pass/spawn-types.rs b/src/test/run-pass/spawn-types.rs index bf2f03b3e6..aab292a940 100644 --- a/src/test/run-pass/spawn-types.rs +++ b/src/test/run-pass/spawn-types.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + /* Make sure we can spawn tasks that take different types of parameters. This is based on a test case for #520 provided by Rob @@ -17,14 +19,14 @@ use std::thread; use std::sync::mpsc::{channel, Sender}; -type ctx = Sender; +type ctx = Sender; fn iotask(_tx: &ctx, ip: String) { assert_eq!(ip, "localhost".to_string()); } pub fn main() { - let (tx, _rx) = channel::(); + let (tx, _rx) = channel::(); let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); t.join().ok().unwrap(); } diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index 90b47f4986..1c34634c73 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -14,4 +14,4 @@ pub fn main() { thread::spawn(move|| child(10)).join().ok().unwrap(); } -fn child(i: int) { println!("{}", i); assert!((i == 10)); } +fn child(i: isize) { println!("{}", i); assert!((i == 10)); } diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs index 91edb5fd9c..93dc3faaa2 100644 --- a/src/test/run-pass/spawn2.rs +++ b/src/test/run-pass/spawn2.rs @@ -12,10 +12,10 @@ use std::thread; pub fn main() { let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); - t.join().ok().unwrap(); + t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug } -fn child(args: (int, int, int, int, int, int, int, int, int)) { +fn child(args: (isize, isize, isize, isize, isize, isize, isize, isize, isize)) { let (i1, i2, i3, i4, i5, i6, i7, i8, i9) = args; println!("{}", i1); println!("{}", i2); diff --git a/src/test/run-pass/stable-addr-of.rs b/src/test/run-pass/stable-addr-of.rs index 515198f7a7..f93600195d 100644 --- a/src/test/run-pass/stable-addr-of.rs +++ b/src/test/run-pass/stable-addr-of.rs @@ -10,7 +10,9 @@ // Issue #2040 +// pretty-expanded FIXME #23616 + pub fn main() { - let foo = 1; - assert_eq!(&foo as *const int, &foo as *const int); + let foo: isize = 1; + assert_eq!(&foo as *const isize, &foo as *const isize); } diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs deleted file mode 100644 index 87d7376c24..0000000000 --- a/src/test/run-pass/stat.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::old_io::fs::PathExtensions; -use std::old_io::{File, TempDir}; - -pub fn main() { - let dir = TempDir::new_in(&Path::new("."), "").unwrap(); - let path = dir.path().join("file"); - - { - match File::create(&path) { - Err(..) => unreachable!(), - Ok(f) => { - let mut f = f; - for _ in 0_usize..1000 { - f.write(&[0]); - } - } - } - } - - assert!(path.exists()); - assert_eq!(path.stat().unwrap().size, 1000); -} diff --git a/src/test/run-pass/static-assert.rs b/src/test/run-pass/static-assert.rs index f8fd81b936..e5583a3c69 100644 --- a/src/test/run-pass/static-assert.rs +++ b/src/test/run-pass/static-assert.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(static_assert)] + #[static_assert] static b: bool = true; diff --git a/src/test/run-pass/static-fn-inline-xc.rs b/src/test/run-pass/static-fn-inline-xc.rs index efc374e25b..80de65c0e9 100644 --- a/src/test/run-pass/static-fn-inline-xc.rs +++ b/src/test/run-pass/static-fn-inline-xc.rs @@ -10,7 +10,9 @@ // aux-build:static_fn_inline_xc_aux.rs -extern crate "static_fn_inline_xc_aux" as mycore; +// pretty-expanded FIXME #23616 + +extern crate static_fn_inline_xc_aux as mycore; use mycore::num; diff --git a/src/test/run-pass/static-fn-trait-xc.rs b/src/test/run-pass/static-fn-trait-xc.rs index cb9f7c3da0..550e03c8b1 100644 --- a/src/test/run-pass/static-fn-trait-xc.rs +++ b/src/test/run-pass/static-fn-trait-xc.rs @@ -10,7 +10,9 @@ // aux-build:static_fn_trait_xc_aux.rs -extern crate "static_fn_trait_xc_aux" as mycore; +// pretty-expanded FIXME #23616 + +extern crate static_fn_trait_xc_aux as mycore; use mycore::num; diff --git a/src/test/run-pass/static-function-pointer-xc.rs b/src/test/run-pass/static-function-pointer-xc.rs index 6e12c5fa73..55f3b0883b 100644 --- a/src/test/run-pass/static-function-pointer-xc.rs +++ b/src/test/run-pass/static-function-pointer-xc.rs @@ -9,9 +9,11 @@ // except according to those terms. // aux-build:static-function-pointer-aux.rs -extern crate "static-function-pointer-aux" as aux; +// pretty-expanded FIXME #23616 -fn f(x: int) -> int { x } +extern crate static_function_pointer_aux as aux; + +fn f(x: isize) -> isize { x } pub fn main() { assert_eq!(aux::F(42), -42); diff --git a/src/test/run-pass/static-function-pointer.rs b/src/test/run-pass/static-function-pointer.rs index ff1091e07e..67cc033f7c 100644 --- a/src/test/run-pass/static-function-pointer.rs +++ b/src/test/run-pass/static-function-pointer.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(x: int) -> int { x } -fn g(x: int) -> int { 2 * x } +// pretty-expanded FIXME #23616 -static F: fn(int) -> int = f; -static mut G: fn(int) -> int = f; +fn f(x: isize) -> isize { x } +fn g(x: isize) -> isize { 2 * x } + +static F: fn(isize) -> isize = f; +static mut G: fn(isize) -> isize = f; pub fn main() { assert_eq!(F(42), 42); diff --git a/src/test/run-pass/static-impl.rs b/src/test/run-pass/static-impl.rs index b66999c8e6..aff2797c1a 100644 --- a/src/test/run-pass/static-impl.rs +++ b/src/test/run-pass/static-impl.rs @@ -10,43 +10,45 @@ +// pretty-expanded FIXME #23616 + pub trait plus { - fn plus(&self) -> int; + fn plus(&self) -> isize; } mod a { use plus; - impl plus for uint { fn plus(&self) -> int { *self as int + 20 } } + impl plus for usize { fn plus(&self) -> isize { *self as isize + 20 } } } mod b { use plus; - impl plus for String { fn plus(&self) -> int { 200 } } + impl plus for String { fn plus(&self) -> isize { 200 } } } trait uint_utils { fn str(&self) -> String; - fn multi(&self, f: F) where F: FnMut(uint); + fn multi(&self, f: F) where F: FnMut(usize); } -impl uint_utils for uint { +impl uint_utils for usize { fn str(&self) -> String { self.to_string() } - fn multi(&self, mut f: F) where F: FnMut(uint) { + fn multi(&self, mut f: F) where F: FnMut(usize) { let mut c = 0_usize; while c < *self { f(c); c += 1_usize; } } } trait vec_utils { - fn length_(&self, ) -> uint; + fn length_(&self, ) -> usize; fn iter_(&self, f: F) where F: FnMut(&T); fn map_(&self, f: F) -> Vec where F: FnMut(&T) -> U; } impl vec_utils for Vec { - fn length_(&self) -> uint { self.len() } + fn length_(&self) -> usize { self.len() } fn iter_(&self, mut f: F) where F: FnMut(&T) { for x in self { f(x); } } fn map_(&self, mut f: F) -> Vec where F: FnMut(&T) -> U { let mut r = Vec::new(); @@ -64,7 +66,7 @@ pub fn main() { assert_eq!((vec!(1)).length_().str(), "1".to_string()); let vect = vec!(3, 4).map_(|a| *a + 4); assert_eq!(vect[0], 7); - let vect = (vec!(3, 4)).map_::(|a| *a as uint + 4_usize); + let vect = (vec!(3, 4)).map_::(|a| *a as usize + 4_usize); assert_eq!(vect[0], 7_usize); let mut x = 0_usize; 10_usize.multi(|_n| x += 2_usize ); diff --git a/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs index d1fcc4659b..4ccb044bbd 100644 --- a/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs +++ b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Deserializer { - fn read_int(&self) -> int; + fn read_int(&self) -> isize; } trait Deserializable { fn deserialize(d: &D) -> Self; } -impl Deserializable for int { - fn deserialize(d: &D) -> int { +impl Deserializable for isize { + fn deserialize(d: &D) -> isize { return d.read_int(); } } @@ -25,11 +27,11 @@ impl Deserializable for int { struct FromThinAir { dummy: () } impl Deserializer for FromThinAir { - fn read_int(&self) -> int { 22 } + fn read_int(&self) -> isize { 22 } } pub fn main() { let d = FromThinAir { dummy: () }; - let i: int = Deserializable::deserialize(&d); + let i: isize = Deserializable::deserialize(&d); assert_eq!(i, 22); } diff --git a/src/test/run-pass/static-method-xcrate.rs b/src/test/run-pass/static-method-xcrate.rs index 076c56bcc4..d0b69b430a 100644 --- a/src/test/run-pass/static-method-xcrate.rs +++ b/src/test/run-pass/static-method-xcrate.rs @@ -10,12 +10,14 @@ // aux-build:static-methods-crate.rs +// pretty-expanded FIXME #23616 + extern crate static_methods_crate; use static_methods_crate::read; pub fn main() { - let result: int = read("5".to_string()); + let result: isize = read("5".to_string()); assert_eq!(result, 5); assert_eq!(read::readMaybe("false".to_string()), Some(false)); assert_eq!(read::readMaybe("foo".to_string()), None::); diff --git a/src/test/run-pass/static-methods-in-traits.rs b/src/test/run-pass/static-methods-in-traits.rs index 5f6dc4f2a5..cb23feb05a 100644 --- a/src/test/run-pass/static-methods-in-traits.rs +++ b/src/test/run-pass/static-methods-in-traits.rs @@ -8,27 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod a { pub trait Foo { fn foo() -> Self; } - impl Foo for int { - fn foo() -> int { + impl Foo for isize { + fn foo() -> isize { 3 } } - impl Foo for uint { - fn foo() -> uint { - 5_usize + impl Foo for usize { + fn foo() -> usize { + 5 } } } pub fn main() { - let x: int = a::Foo::foo(); - let y: uint = a::Foo::foo(); + let x: isize = a::Foo::foo(); + let y: usize = a::Foo::foo(); assert_eq!(x, 3); assert_eq!(y, 5); } diff --git a/src/test/run-pass/static-methods-in-traits2.rs b/src/test/run-pass/static-methods-in-traits2.rs index d0448de2c4..cd8406983f 100644 --- a/src/test/run-pass/static-methods-in-traits2.rs +++ b/src/test/run-pass/static-methods-in-traits2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub trait Number: NumConv { fn from(n: T) -> Self; } diff --git a/src/test/run-pass/static-mut-foreign.rs b/src/test/run-pass/static-mut-foreign.rs index e5d4591361..c6b919c973 100644 --- a/src/test/run-pass/static-mut-foreign.rs +++ b/src/test/run-pass/static-mut-foreign.rs @@ -12,6 +12,10 @@ // statics cannot. This ensures that there's some form of error if this is // attempted. +// pretty-expanded FIXME #23616 + +#![feature(libc)] + extern crate libc; #[link(name = "rust_test_helpers")] diff --git a/src/test/run-pass/static-mut-xc.rs b/src/test/run-pass/static-mut-xc.rs index 5aa28ad80f..0456d17bdc 100644 --- a/src/test/run-pass/static-mut-xc.rs +++ b/src/test/run-pass/static-mut-xc.rs @@ -14,11 +14,13 @@ // aux-build:static_mut_xc.rs +// pretty-expanded FIXME #23616 + extern crate static_mut_xc; -unsafe fn static_bound(_: &'static int) {} +unsafe fn static_bound(_: &'static isize) {} -fn static_bound_set(a: &'static mut int) { +fn static_bound_set(a: &'static mut isize) { *a = 3; } @@ -41,5 +43,5 @@ pub fn main() { } pub mod inner { - pub static mut a: int = 4; + pub static mut a: isize = 4; } diff --git a/src/test/run-pass/std-sync-right-kind-impls.rs b/src/test/run-pass/std-sync-right-kind-impls.rs new file mode 100644 index 0000000000..058777bb05 --- /dev/null +++ b/src/test/run-pass/std-sync-right-kind-impls.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![feature(std_misc, alloc)] + +use std::sync; + +fn assert_both() {} + +fn main() { + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::>(); + assert_both::(); + assert_both::>(); + assert_both::(); + assert_both::(); + assert_both::>(); + assert_both::>(); + assert_both::(); +} diff --git a/src/test/run-pass/str-multiline.rs b/src/test/run-pass/str-multiline.rs index 918715f81e..0d0d56fcaf 100644 --- a/src/test/run-pass/str-multiline.rs +++ b/src/test/run-pass/str-multiline.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let a: String = "this \ is a test".to_string(); diff --git a/src/test/run-pass/string-escapes.rs b/src/test/run-pass/string-escapes.rs index 7abe8276a9..e0fc1c4ce4 100644 --- a/src/test/run-pass/string-escapes.rs +++ b/src/test/run-pass/string-escapes.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn main() { let x = "\\\\\ "; diff --git a/src/test/run-pass/string-self-append.rs b/src/test/run-pass/string-self-append.rs index 359c14ea7b..cef7a93aee 100644 --- a/src/test/run-pass/string-self-append.rs +++ b/src/test/run-pass/string-self-append.rs @@ -12,12 +12,12 @@ pub fn main() { // Make sure we properly handle repeated self-appends. let mut a: String = "A".to_string(); let mut i = 20; - let mut expected_len = 1_usize; + let mut expected_len = 1; while i > 0 { println!("{}", a.len()); assert_eq!(a.len(), expected_len); a = format!("{}{}", a, a); i -= 1; - expected_len *= 2_usize; + expected_len *= 2; } } diff --git a/src/test/run-pass/struct-aliases-xcrate.rs b/src/test/run-pass/struct-aliases-xcrate.rs index 9046cafe75..17cb8acea6 100644 --- a/src/test/run-pass/struct-aliases-xcrate.rs +++ b/src/test/run-pass/struct-aliases-xcrate.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:xcrate_struct_aliases.rs +// pretty-expanded FIXME #23616 + extern crate xcrate_struct_aliases; use xcrate_struct_aliases::{S, S2}; @@ -28,4 +30,3 @@ fn main() { } } } - diff --git a/src/test/run-pass/struct-aliases.rs b/src/test/run-pass/struct-aliases.rs index 2cf961a5c0..79e7960cfb 100644 --- a/src/test/run-pass/struct-aliases.rs +++ b/src/test/run-pass/struct-aliases.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct S { - x: int, - y: int, + x: isize, + y: isize, } type S2 = S; @@ -30,4 +32,3 @@ fn main() { } } } - diff --git a/src/test/run-pass/struct-destructuring-cross-crate.rs b/src/test/run-pass/struct-destructuring-cross-crate.rs index 2de2bcc958..5fed712bd6 100644 --- a/src/test/run-pass/struct-destructuring-cross-crate.rs +++ b/src/test/run-pass/struct-destructuring-cross-crate.rs @@ -10,6 +10,8 @@ // aux-build:struct_destructuring_cross_crate.rs +// pretty-expanded FIXME #23616 + extern crate struct_destructuring_cross_crate; pub fn main() { diff --git a/src/test/run-pass/struct-like-variant-construct.rs b/src/test/run-pass/struct-like-variant-construct.rs index 364c6da980..a55e5143a0 100644 --- a/src/test/run-pass/struct-like-variant-construct.rs +++ b/src/test/run-pass/struct-like-variant-construct.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { Bar { - a: int, - b: int + a: isize, + b: isize }, Baz { c: f64, diff --git a/src/test/run-pass/struct-like-variant-match.rs b/src/test/run-pass/struct-like-variant-match.rs index 3afa44a314..f072d315d7 100644 --- a/src/test/run-pass/struct-like-variant-match.rs +++ b/src/test/run-pass/struct-like-variant-match.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { Bar { - x: int, - y: int + x: isize, + y: isize }, Baz { x: f64, diff --git a/src/test/run-pass/struct-new-as-field-name.rs b/src/test/run-pass/struct-new-as-field-name.rs index 21eb0ae99b..73f27448f8 100644 --- a/src/test/run-pass/struct-new-as-field-name.rs +++ b/src/test/run-pass/struct-new-as-field-name.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct Foo { - new: int, + new: isize, } pub fn main() { diff --git a/src/test/run-pass/struct-order-of-eval-1.rs b/src/test/run-pass/struct-order-of-eval-1.rs index 6cebd17496..49ec695a12 100644 --- a/src/test/run-pass/struct-order-of-eval-1.rs +++ b/src/test/run-pass/struct-order-of-eval-1.rs @@ -8,15 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct S { f0: String, f1: int } +// pretty-expanded FIXME #23616 + +struct S { f0: String, f1: isize } pub fn main() { let s = "Hello, world!".to_string(); - let _s = S { + let s = S { f0: s.to_string(), ..S { f0: s, f1: 23 } }; + assert_eq!(s.f0, "Hello, world!"); } diff --git a/src/test/run-pass/struct-order-of-eval-2.rs b/src/test/run-pass/struct-order-of-eval-2.rs index 786f080bb9..45755608ff 100644 --- a/src/test/run-pass/struct-order-of-eval-2.rs +++ b/src/test/run-pass/struct-order-of-eval-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + struct S { f0: String, f1: String, @@ -15,8 +17,9 @@ struct S { pub fn main() { let s = "Hello, world!".to_string(); - let _s = S { + let s = S { f1: s.to_string(), f0: s }; + assert_eq!(s.f0, "Hello, world!"); } diff --git a/src/test/run-pass/struct-order-of-eval-3.rs b/src/test/run-pass/struct-order-of-eval-3.rs new file mode 100644 index 0000000000..37b6de8e17 --- /dev/null +++ b/src/test/run-pass/struct-order-of-eval-3.rs @@ -0,0 +1,48 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks that functional-record-update order-of-eval is as expected +// even when no Drop-implementations are involved. + +// pretty-expanded FIXME #23616 + +use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT}; + +struct W { wrapped: u32 } +struct S { f0: W, _f1: i32 } + +pub fn main() { + const VAL: u32 = 0x89AB_CDEF; + let w = W { wrapped: VAL }; + let s = S { + f0: { event(0x01); W { wrapped: w.wrapped + 1 } }, + ..S { + f0: { event(0x02); w}, + _f1: 23 + } + }; + assert_eq!(s.f0.wrapped, VAL + 1); + let actual = event_log(); + let expect = 0x01_02; + assert!(expect == actual, + "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} + +static LOG: AtomicUsize = ATOMIC_USIZE_INIT; + +fn event_log() -> usize { + LOG.load(Ordering::SeqCst) +} + +fn event(tag: u8) { + let old_log = LOG.load(Ordering::SeqCst); + let new_log = (old_log << 8) + tag as usize; + LOG.store(new_log, Ordering::SeqCst); +} diff --git a/src/test/run-pass/struct-order-of-eval-4.rs b/src/test/run-pass/struct-order-of-eval-4.rs new file mode 100644 index 0000000000..1b53895f7d --- /dev/null +++ b/src/test/run-pass/struct-order-of-eval-4.rs @@ -0,0 +1,45 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks that struct-literal expression order-of-eval is as expected +// even when no Drop-implementations are involved. + +// pretty-expanded FIXME #23616 + +use std::sync::atomic::{Ordering, AtomicUsize, ATOMIC_USIZE_INIT}; + +struct W { wrapped: u32 } +struct S { f0: W, _f1: i32 } + +pub fn main() { + const VAL: u32 = 0x89AB_CDEF; + let w = W { wrapped: VAL }; + let s = S { + _f1: { event(0x01); 23 }, + f0: { event(0x02); w }, + }; + assert_eq!(s.f0.wrapped, VAL); + let actual = event_log(); + let expect = 0x01_02; + assert!(expect == actual, + "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} + +static LOG: AtomicUsize = ATOMIC_USIZE_INIT; + +fn event_log() -> usize { + LOG.load(Ordering::SeqCst) +} + +fn event(tag: u8) { + let old_log = LOG.load(Ordering::SeqCst); + let new_log = (old_log << 8) + tag as usize; + LOG.store(new_log, Ordering::SeqCst); +} diff --git a/src/test/run-pass/struct-partial-move-1.rs b/src/test/run-pass/struct-partial-move-1.rs index 8f75b763d9..3b04bfc1ac 100644 --- a/src/test/run-pass/struct-partial-move-1.rs +++ b/src/test/run-pass/struct-partial-move-1.rs @@ -12,8 +12,8 @@ pub struct Partial { x: T, y: T } #[derive(PartialEq, Debug)] -struct S { val: int } -impl S { fn new(v: int) -> S { S { val: v } } } +struct S { val: isize } +impl S { fn new(v: isize) -> S { S { val: v } } } impl Drop for S { fn drop(&mut self) { } } pub fn f((b1, b2): (T, T), mut f: F) -> Partial where F: FnMut(T) -> T { diff --git a/src/test/run-pass/struct-partial-move-2.rs b/src/test/run-pass/struct-partial-move-2.rs index 377e9e6b89..b9c697c71e 100644 --- a/src/test/run-pass/struct-partial-move-2.rs +++ b/src/test/run-pass/struct-partial-move-2.rs @@ -12,8 +12,8 @@ pub struct Partial { x: T, y: T } #[derive(PartialEq, Debug)] -struct S { val: int } -impl S { fn new(v: int) -> S { S { val: v } } } +struct S { val: isize } +impl S { fn new(v: isize) -> S { S { val: v } } } impl Drop for S { fn drop(&mut self) { } } pub type Two = (Partial, Partial); diff --git a/src/test/run-pass/struct-pattern-matching.rs b/src/test/run-pass/struct-pattern-matching.rs index 6033554d0c..9c3ce54f36 100644 --- a/src/test/run-pass/struct-pattern-matching.rs +++ b/src/test/run-pass/struct-pattern-matching.rs @@ -9,8 +9,8 @@ // except according to those terms. struct Foo { - x: int, - y: int, + x: isize, + y: isize, } pub fn main() { diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs index c8768731e2..1ff13d4eae 100644 --- a/src/test/run-pass/struct-return.rs +++ b/src/test/run-pass/struct-return.rs @@ -10,10 +10,10 @@ // // ignore-lexer-test FIXME #15883 -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Quad { a: u64, b: u64, c: u64, d: u64 } -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Floats { a: f64, b: u8, c: f64 } mod rustrt { @@ -28,19 +28,19 @@ mod rustrt { fn test1() { unsafe { - let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa_u64, - b: 0xbbbb_bbbb_bbbb_bbbb_u64, - c: 0xcccc_cccc_cccc_cccc_u64, - d: 0xdddd_dddd_dddd_dddd_u64 }; + let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa, + b: 0xbbbb_bbbb_bbbb_bbbb, + c: 0xcccc_cccc_cccc_cccc, + d: 0xdddd_dddd_dddd_dddd }; let qq = rustrt::rust_dbg_abi_1(q); - println!("a: {:x}", qq.a as uint); - println!("b: {:x}", qq.b as uint); - println!("c: {:x}", qq.c as uint); - println!("d: {:x}", qq.d as uint); - assert_eq!(qq.a, q.c + 1u64); - assert_eq!(qq.b, q.d - 1u64); - assert_eq!(qq.c, q.a + 1u64); - assert_eq!(qq.d, q.b - 1u64); + println!("a: {:x}", qq.a as usize); + println!("b: {:x}", qq.b as usize); + println!("c: {:x}", qq.c as usize); + println!("d: {:x}", qq.d as usize); + assert_eq!(qq.a, q.c + 1); + assert_eq!(qq.b, q.d - 1); + assert_eq!(qq.c, q.a + 1); + assert_eq!(qq.d, q.b - 1); } } @@ -48,14 +48,14 @@ fn test1() { fn test2() { unsafe { let f = Floats { a: 1.234567890e-15_f64, - b: 0b_1010_1010_u8, + b: 0b_1010_1010, c: 1.0987654321e-15_f64 }; let ff = rustrt::rust_dbg_abi_2(f); println!("a: {}", ff.a as f64); - println!("b: {}", ff.b as uint); + println!("b: {}", ff.b as usize); println!("c: {}", ff.c as f64); assert_eq!(ff.a, f.c + 1.0f64); - assert_eq!(ff.b, 0xff_u8); + assert_eq!(ff.b, 0xff); assert_eq!(ff.c, f.a - 1.0f64); } } diff --git a/src/test/run-pass/struct-variant-field-visibility.rs b/src/test/run-pass/struct-variant-field-visibility.rs index aad3ba01a4..b6e7846e96 100644 --- a/src/test/run-pass/struct-variant-field-visibility.rs +++ b/src/test/run-pass/struct-variant-field-visibility.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod foo { pub enum Foo { - Bar { a: int } + Bar { a: isize } } } diff --git a/src/test/run-pass/struct_variant_xc.rs b/src/test/run-pass/struct_variant_xc.rs index 923a142786..602650e4e0 100644 --- a/src/test/run-pass/struct_variant_xc.rs +++ b/src/test/run-pass/struct_variant_xc.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:struct_variant_xc_aux.rs +// pretty-expanded FIXME #23616 + extern crate struct_variant_xc_aux; use struct_variant_xc_aux::Enum::StructVariant; diff --git a/src/test/run-pass/struct_variant_xc_match.rs b/src/test/run-pass/struct_variant_xc_match.rs index 41dcb7ddbc..f43dd2332a 100644 --- a/src/test/run-pass/struct_variant_xc_match.rs +++ b/src/test/run-pass/struct_variant_xc_match.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:struct_variant_xc_aux.rs +// pretty-expanded FIXME #23616 + extern crate struct_variant_xc_aux; use struct_variant_xc_aux::Enum::{StructVariant, Variant}; diff --git a/src/test/run-pass/structured-compare.rs b/src/test/run-pass/structured-compare.rs index 12d8fe8f4c..7974366c39 100644 --- a/src/test/run-pass/structured-compare.rs +++ b/src/test/run-pass/structured-compare.rs @@ -10,12 +10,12 @@ -#[derive(Copy, Debug)] +#[derive(Copy, Clone, Debug)] enum foo { large, small, } impl PartialEq for foo { fn eq(&self, other: &foo) -> bool { - ((*self) as uint) == ((*other) as uint) + ((*self) as usize) == ((*other) as usize) } fn ne(&self, other: &foo) -> bool { !(*self).eq(other) } } diff --git a/src/test/run-pass/super-fast-paren-parsing.rs b/src/test/run-pass/super-fast-paren-parsing.rs index f00ba36a00..69ec0a2222 100644 --- a/src/test/run-pass/super-fast-paren-parsing.rs +++ b/src/test/run-pass/super-fast-paren-parsing.rs @@ -14,7 +14,7 @@ // // Big stack is needed for pretty printing, a little sad... -static a: int = +static a: isize = ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( diff --git a/src/test/run-pass/super.rs b/src/test/run-pass/super.rs index 95aeff425e..51520c7775 100644 --- a/src/test/run-pass/super.rs +++ b/src/test/run-pass/super.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub mod a { pub fn f() {} pub mod b { diff --git a/src/test/run-pass/supertrait-default-generics.rs b/src/test/run-pass/supertrait-default-generics.rs index e158ae672a..351c4259b5 100644 --- a/src/test/run-pass/supertrait-default-generics.rs +++ b/src/test/run-pass/supertrait-default-generics.rs @@ -10,6 +10,8 @@ // There is some other borrowck bug, so we make the stuff not mut. +// pretty-expanded FIXME #23616 + use std::ops::Add; trait Positioned { diff --git a/src/test/run-pass/supported-cast.rs b/src/test/run-pass/supported-cast.rs index 3fffef060a..811b9dce4b 100644 --- a/src/test/run-pass/supported-cast.rs +++ b/src/test/run-pass/supported-cast.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(libc)] + extern crate libc; pub fn main() { let f = 1_usize as *const libc::FILE; - println!("{:?}", f as int); - println!("{:?}", f as uint); + println!("{:?}", f as isize); + println!("{:?}", f as usize); println!("{:?}", f as i8); println!("{:?}", f as i16); println!("{:?}", f as i32); @@ -23,8 +25,8 @@ pub fn main() { println!("{:?}", f as u32); println!("{:?}", f as u64); - println!("{:?}", 1 as int); - println!("{:?}", 1 as uint); + println!("{:?}", 1 as isize); + println!("{:?}", 1 as usize); println!("{:?}", 1 as *const libc::FILE); println!("{:?}", 1 as i8); println!("{:?}", 1 as i16); @@ -37,8 +39,8 @@ pub fn main() { println!("{:?}", 1 as f32); println!("{:?}", 1 as f64); - println!("{:?}", 1_usize as int); - println!("{:?}", 1_usize as uint); + println!("{:?}", 1_usize as isize); + println!("{:?}", 1_usize as usize); println!("{:?}", 1_usize as *const libc::FILE); println!("{:?}", 1_usize as i8); println!("{:?}", 1_usize as i16); @@ -51,8 +53,8 @@ pub fn main() { println!("{:?}", 1_usize as f32); println!("{:?}", 1_usize as f64); - println!("{:?}", 1i8 as int); - println!("{:?}", 1i8 as uint); + println!("{:?}", 1i8 as isize); + println!("{:?}", 1i8 as usize); println!("{:?}", 1i8 as *const libc::FILE); println!("{:?}", 1i8 as i8); println!("{:?}", 1i8 as i16); @@ -65,8 +67,8 @@ pub fn main() { println!("{:?}", 1i8 as f32); println!("{:?}", 1i8 as f64); - println!("{:?}", 1u8 as int); - println!("{:?}", 1u8 as uint); + println!("{:?}", 1u8 as isize); + println!("{:?}", 1u8 as usize); println!("{:?}", 1u8 as *const libc::FILE); println!("{:?}", 1u8 as i8); println!("{:?}", 1u8 as i16); @@ -79,8 +81,8 @@ pub fn main() { println!("{:?}", 1u8 as f32); println!("{:?}", 1u8 as f64); - println!("{:?}", 1i16 as int); - println!("{:?}", 1i16 as uint); + println!("{:?}", 1i16 as isize); + println!("{:?}", 1i16 as usize); println!("{:?}", 1i16 as *const libc::FILE); println!("{:?}", 1i16 as i8); println!("{:?}", 1i16 as i16); @@ -93,8 +95,8 @@ pub fn main() { println!("{:?}", 1i16 as f32); println!("{:?}", 1i16 as f64); - println!("{:?}", 1u16 as int); - println!("{:?}", 1u16 as uint); + println!("{:?}", 1u16 as isize); + println!("{:?}", 1u16 as usize); println!("{:?}", 1u16 as *const libc::FILE); println!("{:?}", 1u16 as i8); println!("{:?}", 1u16 as i16); @@ -107,8 +109,8 @@ pub fn main() { println!("{:?}", 1u16 as f32); println!("{:?}", 1u16 as f64); - println!("{:?}", 1i32 as int); - println!("{:?}", 1i32 as uint); + println!("{:?}", 1i32 as isize); + println!("{:?}", 1i32 as usize); println!("{:?}", 1i32 as *const libc::FILE); println!("{:?}", 1i32 as i8); println!("{:?}", 1i32 as i16); @@ -121,8 +123,8 @@ pub fn main() { println!("{:?}", 1i32 as f32); println!("{:?}", 1i32 as f64); - println!("{:?}", 1u32 as int); - println!("{:?}", 1u32 as uint); + println!("{:?}", 1u32 as isize); + println!("{:?}", 1u32 as usize); println!("{:?}", 1u32 as *const libc::FILE); println!("{:?}", 1u32 as i8); println!("{:?}", 1u32 as i16); @@ -135,8 +137,8 @@ pub fn main() { println!("{:?}", 1u32 as f32); println!("{:?}", 1u32 as f64); - println!("{:?}", 1i64 as int); - println!("{:?}", 1i64 as uint); + println!("{:?}", 1i64 as isize); + println!("{:?}", 1i64 as usize); println!("{:?}", 1i64 as *const libc::FILE); println!("{:?}", 1i64 as i8); println!("{:?}", 1i64 as i16); @@ -149,8 +151,8 @@ pub fn main() { println!("{:?}", 1i64 as f32); println!("{:?}", 1i64 as f64); - println!("{:?}", 1u64 as int); - println!("{:?}", 1u64 as uint); + println!("{:?}", 1u64 as isize); + println!("{:?}", 1u64 as usize); println!("{:?}", 1u64 as *const libc::FILE); println!("{:?}", 1u64 as i8); println!("{:?}", 1u64 as i16); @@ -163,8 +165,8 @@ pub fn main() { println!("{:?}", 1u64 as f32); println!("{:?}", 1u64 as f64); - println!("{:?}", 1u64 as int); - println!("{:?}", 1u64 as uint); + println!("{:?}", 1u64 as isize); + println!("{:?}", 1u64 as usize); println!("{:?}", 1u64 as *const libc::FILE); println!("{:?}", 1u64 as i8); println!("{:?}", 1u64 as i16); @@ -177,8 +179,8 @@ pub fn main() { println!("{:?}", 1u64 as f32); println!("{:?}", 1u64 as f64); - println!("{:?}", true as int); - println!("{:?}", true as uint); + println!("{:?}", true as isize); + println!("{:?}", true as usize); println!("{:?}", true as *const libc::FILE); println!("{:?}", true as i8); println!("{:?}", true as i16); @@ -191,8 +193,8 @@ pub fn main() { println!("{:?}", true as f32); println!("{:?}", true as f64); - println!("{:?}", 1f32 as int); - println!("{:?}", 1f32 as uint); + println!("{:?}", 1f32 as isize); + println!("{:?}", 1f32 as usize); println!("{:?}", 1f32 as i8); println!("{:?}", 1f32 as i16); println!("{:?}", 1f32 as i32); @@ -204,8 +206,8 @@ pub fn main() { println!("{:?}", 1f32 as f32); println!("{:?}", 1f32 as f64); - println!("{:?}", 1f64 as int); - println!("{:?}", 1f64 as uint); + println!("{:?}", 1f64 as isize); + println!("{:?}", 1f64 as usize); println!("{:?}", 1f64 as i8); println!("{:?}", 1f64 as i16); println!("{:?}", 1f64 as i32); diff --git a/src/test/run-pass/svh-add-comment.rs b/src/test/run-pass/svh-add-comment.rs index 235c4e74d0..4d7b61e08f 100644 --- a/src/test/run-pass/svh-add-comment.rs +++ b/src/test/run-pass/svh-add-comment.rs @@ -13,6 +13,8 @@ // aux-build:svh-b.rs // aux-build:svh-a-comment.rs +// pretty-expanded FIXME #23616 + extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-doc.rs b/src/test/run-pass/svh-add-doc.rs index 365960b96e..ea07ebe364 100644 --- a/src/test/run-pass/svh-add-doc.rs +++ b/src/test/run-pass/svh-add-doc.rs @@ -13,6 +13,8 @@ // aux-build:svh-b.rs // aux-build:svh-a-doc.rs +// pretty-expanded FIXME #23616 + extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-macro.rs b/src/test/run-pass/svh-add-macro.rs index a0dbc96cdb..4e0192c40c 100644 --- a/src/test/run-pass/svh-add-macro.rs +++ b/src/test/run-pass/svh-add-macro.rs @@ -13,6 +13,8 @@ // aux-build:svh-b.rs // aux-build:svh-a-macro.rs +// pretty-expanded FIXME #23616 + extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-nothing.rs b/src/test/run-pass/svh-add-nothing.rs index 98b7663c58..9aa56ed2a7 100644 --- a/src/test/run-pass/svh-add-nothing.rs +++ b/src/test/run-pass/svh-add-nothing.rs @@ -13,6 +13,8 @@ // aux-build:svh-b.rs // aux-build:svh-a-no-change.rs +// pretty-expanded FIXME #23616 + extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-redundant-cfg.rs b/src/test/run-pass/svh-add-redundant-cfg.rs index 650f76d729..2da3004aaf 100644 --- a/src/test/run-pass/svh-add-redundant-cfg.rs +++ b/src/test/run-pass/svh-add-redundant-cfg.rs @@ -13,6 +13,8 @@ // aux-build:svh-b.rs // aux-build:svh-a-redundant-cfg.rs +// pretty-expanded FIXME #23616 + extern crate a; extern crate b; diff --git a/src/test/run-pass/svh-add-whitespace.rs b/src/test/run-pass/svh-add-whitespace.rs index 6612c93e90..bfc676bde2 100644 --- a/src/test/run-pass/svh-add-whitespace.rs +++ b/src/test/run-pass/svh-add-whitespace.rs @@ -13,6 +13,8 @@ // aux-build:svh-b.rs // aux-build:svh-a-whitespace.rs +// pretty-expanded FIXME #23616 + extern crate a; extern crate b; diff --git a/src/test/run-pass/swap-1.rs b/src/test/run-pass/swap-1.rs index 82a76512e0..e60c672f00 100644 --- a/src/test/run-pass/swap-1.rs +++ b/src/test/run-pass/swap-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::swap; pub fn main() { diff --git a/src/test/run-pass/swap-2.rs b/src/test/run-pass/swap-2.rs index 1dbd29a781..3891376e46 100644 --- a/src/test/run-pass/swap-2.rs +++ b/src/test/run-pass/swap-2.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::swap; pub fn main() { - let mut a: Vec = vec!(0, 1, 2, 3, 4, 5, 6); + let mut a: Vec = vec!(0, 1, 2, 3, 4, 5, 6); a.swap(2, 4); assert_eq!(a[2], 4); assert_eq!(a[4], 2); diff --git a/src/test/run-pass/swap-overlapping.rs b/src/test/run-pass/swap-overlapping.rs index b25b350aa4..2e5386d686 100644 --- a/src/test/run-pass/swap-overlapping.rs +++ b/src/test/run-pass/swap-overlapping.rs @@ -10,6 +10,8 @@ // Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same +// pretty-expanded FIXME #23616 + use std::ptr; pub fn main() { @@ -34,8 +36,8 @@ pub enum TestName { } pub enum TestFn { - DynTestFn(int), - DynBenchFn(int), + DynTestFn(isize), + DynBenchFn(isize), } pub struct TestDesc { diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs new file mode 100644 index 0000000000..447b4de450 --- /dev/null +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -0,0 +1,100 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// pretty-expanded FIXME #23616 + +#![allow(unused_mut)] +#![feature(collections)] + +extern crate collections; + +use collections::BinaryHeap; +use collections::{BitSet, BitVec}; +use collections::{BTreeMap, BTreeSet}; +use collections::EnumSet; +use collections::LinkedList; +use collections::Vec; +use collections::VecDeque; +use collections::VecMap; + +use collections::Bound::Included; +use collections::enum_set::CLike; +use std::mem; + +fn is_sync(_: T) where T: Sync {} +fn is_send(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + )+ + }) +} + +macro_rules! is_sync_send { + ($ctor:expr, $iter:ident($($param:expr),+)) => ({ + let mut x = $ctor; + is_sync(x.$iter($( $param ),+)); + let mut y = $ctor; + is_send(y.$iter($( $param ),+)); + }) +} + +fn main() { + // The iterator "generator" list should exhaust what corresponding + // implementations have where `Sync` and `Send` semantics apply. + all_sync_send!(BinaryHeap::::new(), iter, drain, into_iter); + + all_sync_send!(BitVec::new(), iter); + + all_sync_send!(BitSet::new(), iter); + is_sync_send!(BitSet::new(), union(&BitSet::new())); + is_sync_send!(BitSet::new(), intersection(&BitSet::new())); + is_sync_send!(BitSet::new(), difference(&BitSet::new())); + is_sync_send!(BitSet::new(), symmetric_difference(&BitSet::new())); + + all_sync_send!(BTreeMap::::new(), iter, iter_mut, into_iter, keys, values); + is_sync_send!(BTreeMap::::new(), range(Included(&0), Included(&9))); + is_sync_send!(BTreeMap::::new(), range_mut(Included(&0), Included(&9))); + + all_sync_send!(BTreeSet::::new(), iter, into_iter); + is_sync_send!(BTreeSet::::new(), range(Included(&0), Included(&9))); + is_sync_send!(BTreeSet::::new(), difference(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), symmetric_difference(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), intersection(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), union(&BTreeSet::::new())); + + all_sync_send!(LinkedList::::new(), iter, iter_mut, into_iter); + + #[derive(Copy, Clone)] + #[repr(usize)] + #[allow(dead_code)] + enum Foo { A, B, C } + impl CLike for Foo { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Foo { + unsafe { mem::transmute(v) } + } + } + all_sync_send!(EnumSet::::new(), iter); + + all_sync_send!(VecDeque::::new(), iter, iter_mut, drain, into_iter); + + all_sync_send!(VecMap::::new(), iter, iter_mut, drain, into_iter, keys, values); + + all_sync_send!(Vec::::new(), into_iter, drain); +} diff --git a/src/test/run-pass/syntax-extension-cfg.rs b/src/test/run-pass/syntax-extension-cfg.rs index 8c888ff036..8766cba5db 100644 --- a/src/test/run-pass/syntax-extension-cfg.rs +++ b/src/test/run-pass/syntax-extension-cfg.rs @@ -10,6 +10,8 @@ // compile-flags: --cfg foo --cfg qux="foo" +// pretty-expanded FIXME #23616 + pub fn main() { // check if ! cfg!(foo) { panic!() } diff --git a/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment b/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment index dea7f99fcb..61d6d3fdd3 100644 --- a/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment +++ b/src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment @@ -2,6 +2,6 @@ { assert!(file!().ends_with("includeme.fragment")); - assert!(line!() == 5_usize); + assert!(line!() == 5u32); format!("victory robot {}", line!()) } diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index 349a676a43..8834fd39d1 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + // This test is brittle! // ignore-pretty - the pretty tests lose path information, breaking include! @@ -22,9 +24,9 @@ pub mod m1 { macro_rules! indirect_line { () => ( line!() ) } pub fn main() { - assert_eq!(line!(), 25); - //assert!((column!() == 11)); - assert_eq!(indirect_line!(), 27); + assert_eq!(line!(), 27); + assert!((column!() == 4)); + assert_eq!(indirect_line!(), 29); assert!((file!().ends_with("syntax-extension-source-utils.rs"))); assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string()); assert!(include!("syntax-extension-source-utils-files/includeme.\ @@ -34,7 +36,6 @@ pub fn main() { assert!( include_str!("syntax-extension-source-utils-files/includeme.\ fragment").to_string() - .as_slice() .starts_with("/* this is for ")); assert!( include_bytes!("syntax-extension-source-utils-files/includeme.fragment") @@ -42,8 +43,5 @@ pub fn main() { // The Windows tests are wrapped in an extra module for some reason assert!((m1::m2::where_am_i().ends_with("m1::m2"))); - assert!(match (45, "( 2 * 3 ) + 5") { - (line!(), stringify!((2*3) + 5)) => true, - _ => false - }) + assert_eq!((46, "( 2 * 3 ) + 5"), (line!(), stringify!((2*3) + 5))); } diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs index 340ad2a531..ba8a3f77aa 100644 --- a/src/test/run-pass/syntax-trait-polarity.rs +++ b/src/test/run-pass/syntax-trait-polarity.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(optin_builtin_traits)] +// pretty-expanded FIXME #23616 + +#![feature(optin_builtin_traits, core)] use std::marker::{MarkerTrait, Send}; diff --git a/src/test/run-pass/tag-align-dyn-u64.rs b/src/test/run-pass/tag-align-dyn-u64.rs index b7fe4983b0..a9f5875023 100644 --- a/src/test/run-pass/tag-align-dyn-u64.rs +++ b/src/test/run-pass/tag-align-dyn-u64.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-linux #7340 fails on 32-bit Linux -// ignore-macos #7340 fails on 32-bit macos +// pretty-expanded FIXME #23616 use std::mem; @@ -23,15 +22,16 @@ struct Rec { } fn mk_rec() -> Rec { - return Rec { c8:0u8, t:Tag::Tag2(0u64) }; + return Rec { c8:0, t:Tag::Tag2(0) }; } -fn is_8_byte_aligned(u: &Tag) -> bool { - let p: uint = unsafe { mem::transmute(u) }; - return (p & 7_usize) == 0_usize; +fn is_u64_aligned(u: &Tag) -> bool { + let p: usize = unsafe { mem::transmute(u) }; + let u64_align = std::mem::min_align_of::(); + return (p & (u64_align - 1)) == 0; } pub fn main() { let x = mk_rec(); - assert!(is_8_byte_aligned(&x.t)); + assert!(is_u64_aligned(&x.t)); } diff --git a/src/test/run-pass/tag-align-dyn-variants.rs b/src/test/run-pass/tag-align-dyn-variants.rs index cb298e720e..90b583e2e5 100644 --- a/src/test/run-pass/tag-align-dyn-variants.rs +++ b/src/test/run-pass/tag-align-dyn-variants.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-linux #7340 fails on 32-bit Linux -// ignore-macos #7340 fails on 32-bit macos +// pretty-expanded FIXME #23616 use std::mem; @@ -26,15 +25,15 @@ struct Rec { } fn mk_rec(a: A, b: B) -> Rec { - Rec { chA:0u8, tA:Tag::VarA(a), chB:1u8, tB:Tag::VarB(b) } + Rec { chA:0, tA:Tag::VarA(a), chB:1, tB:Tag::VarB(b) } } -fn is_aligned(amnt: uint, u: &A) -> bool { - let p: uint = unsafe { mem::transmute(u) }; - return (p & (amnt-1_usize)) == 0_usize; +fn is_aligned(amnt: usize, u: &A) -> bool { + let p: usize = unsafe { mem::transmute(u) }; + return (p & (amnt-1)) == 0; } -fn variant_data_is_aligned(amnt: uint, u: &Tag) -> bool { +fn variant_data_is_aligned(amnt: usize, u: &Tag) -> bool { match u { &Tag::VarA(ref a) => is_aligned(amnt, a), &Tag::VarB(ref b) => is_aligned(amnt, b) @@ -42,33 +41,34 @@ fn variant_data_is_aligned(amnt: uint, u: &Tag) -> bool { } pub fn main() { + let u64_align = std::mem::min_align_of::(); let x = mk_rec(22u64, 23u64); - assert!(is_aligned(8_usize, &x.tA)); - assert!(variant_data_is_aligned(8_usize, &x.tA)); - assert!(is_aligned(8_usize, &x.tB)); - assert!(variant_data_is_aligned(8_usize, &x.tB)); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(u64_align, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(u64_align, &x.tB)); let x = mk_rec(22u64, 23u32); - assert!(is_aligned(8_usize, &x.tA)); - assert!(variant_data_is_aligned(8_usize, &x.tA)); - assert!(is_aligned(8_usize, &x.tB)); - assert!(variant_data_is_aligned(4_usize, &x.tB)); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(u64_align, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(4, &x.tB)); let x = mk_rec(22u32, 23u64); - assert!(is_aligned(8_usize, &x.tA)); - assert!(variant_data_is_aligned(4_usize, &x.tA)); - assert!(is_aligned(8_usize, &x.tB)); - assert!(variant_data_is_aligned(8_usize, &x.tB)); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(4, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(u64_align, &x.tB)); let x = mk_rec(22u32, 23u32); - assert!(is_aligned(4_usize, &x.tA)); - assert!(variant_data_is_aligned(4_usize, &x.tA)); - assert!(is_aligned(4_usize, &x.tB)); - assert!(variant_data_is_aligned(4_usize, &x.tB)); + assert!(is_aligned(4, &x.tA)); + assert!(variant_data_is_aligned(4, &x.tA)); + assert!(is_aligned(4, &x.tB)); + assert!(variant_data_is_aligned(4, &x.tB)); let x = mk_rec(22f64, 23f64); - assert!(is_aligned(8_usize, &x.tA)); - assert!(variant_data_is_aligned(8_usize, &x.tA)); - assert!(is_aligned(8_usize, &x.tB)); - assert!(variant_data_is_aligned(8_usize, &x.tB)); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(u64_align, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(u64_align, &x.tB)); } diff --git a/src/test/run-pass/tag-align-shape.rs b/src/test/run-pass/tag-align-shape.rs index cc0a75181d..5db886c815 100644 --- a/src/test/run-pass/tag-align-shape.rs +++ b/src/test/run-pass/tag-align-shape.rs @@ -20,7 +20,7 @@ struct t_rec { } pub fn main() { - let x = t_rec {c8: 22u8, t: a_tag::a_tag_var(44u64)}; + let x = t_rec {c8: 22, t: a_tag::a_tag_var(44)}; let y = format!("{:?}", x); println!("y = {:?}", y); assert_eq!(y, "t_rec { c8: 22, t: a_tag_var(44) }".to_string()); diff --git a/src/test/run-pass/tag-align-u64.rs b/src/test/run-pass/tag-align-u64.rs index 713f55cc10..e922ac3b46 100644 --- a/src/test/run-pass/tag-align-u64.rs +++ b/src/test/run-pass/tag-align-u64.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-linux #7340 fails on 32-bit Linux -// ignore-macos #7340 fails on 32-bit macos +// pretty-expanded FIXME #23616 use std::mem; @@ -23,15 +22,16 @@ struct Rec { } fn mk_rec() -> Rec { - return Rec { c8:0u8, t:Tag::TagInner(0u64) }; + return Rec { c8:0, t:Tag::TagInner(0) }; } -fn is_8_byte_aligned(u: &Tag) -> bool { - let p: uint = unsafe { mem::transmute(u) }; - return (p & 7_usize) == 0_usize; +fn is_u64_aligned(u: &Tag) -> bool { + let p: usize = unsafe { mem::transmute(u) }; + let u64_align = std::mem::min_align_of::(); + return (p & (u64_align - 1)) == 0; } pub fn main() { let x = mk_rec(); - assert!(is_8_byte_aligned(&x.t)); + assert!(is_u64_aligned(&x.t)); } diff --git a/src/test/run-pass/tag-exports.rs b/src/test/run-pass/tag-exports.rs index 2eff97d31b..d797fd2e54 100644 --- a/src/test/run-pass/tag-exports.rs +++ b/src/test/run-pass/tag-exports.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + use alder::*; mod alder { diff --git a/src/test/run-pass/tag-in-block.rs b/src/test/run-pass/tag-in-block.rs index 4cb189ee43..f1a820c8d8 100644 --- a/src/test/run-pass/tag-in-block.rs +++ b/src/test/run-pass/tag-in-block.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + fn foo() { fn zed(_z: bar) { } enum bar { nil, } diff --git a/src/test/run-pass/tag-variant-disr-type-mismatch.rs b/src/test/run-pass/tag-variant-disr-type-mismatch.rs index 7e4bd9ab27..d31eacc997 100644 --- a/src/test/run-pass/tag-variant-disr-type-mismatch.rs +++ b/src/test/run-pass/tag-variant-disr-type-mismatch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum color { red = 1, blue = 2, diff --git a/src/test/run-pass/tag-variant-disr-val.rs b/src/test/run-pass/tag-variant-disr-val.rs index 915a0b5b7e..a063801032 100644 --- a/src/test/run-pass/tag-variant-disr-val.rs +++ b/src/test/run-pass/tag-variant-disr-val.rs @@ -7,9 +7,11 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use color::{red, green, blue, black, white, imaginary, purple, orange}; -#[derive(Copy)] +#[derive(Copy, Clone)] enum color { red = 0xff0000, green = 0x00ff00, @@ -23,7 +25,7 @@ enum color { impl PartialEq for color { fn eq(&self, other: &color) -> bool { - ((*self) as uint) == ((*other) as uint) + ((*self) as usize) == ((*other) as usize) } fn ne(&self, other: &color) -> bool { !(*self).eq(other) } } @@ -39,9 +41,9 @@ pub fn main() { test_color(orange, 4, "orange".to_string()); } -fn test_color(color: color, val: int, name: String) { +fn test_color(color: color, val: isize, name: String) { //assert!(unsafe::transmute(color) == val); - assert_eq!(color as int, val); + assert_eq!(color as isize, val); assert!(get_color_alt(color) == name); assert!(get_color_if(color) == name); } diff --git a/src/test/run-pass/tag.rs b/src/test/run-pass/tag.rs index 45b6871e40..dbd65ee6bd 100644 --- a/src/test/run-pass/tag.rs +++ b/src/test/run-pass/tag.rs @@ -9,7 +9,9 @@ // except according to those terms. -enum colour { red(int, int), green, } +// pretty-expanded FIXME #23616 + +enum colour { red(isize, isize), green, } impl PartialEq for colour { fn eq(&self, other: &colour) -> bool { diff --git a/src/test/run-pass/tail-call-arg-leak.rs b/src/test/run-pass/tail-call-arg-leak.rs index a5447606d8..8842e1b859 100644 --- a/src/test/run-pass/tail-call-arg-leak.rs +++ b/src/test/run-pass/tail-call-arg-leak.rs @@ -12,6 +12,8 @@ // use of tail calls causes arg slot leaks, issue #160. +// pretty-expanded FIXME #23616 + fn inner(dummy: String, b: bool) { if b { return inner(dummy, false); } } pub fn main() { diff --git a/src/test/run-pass/tail-cps.rs b/src/test/run-pass/tail-cps.rs index 6f03f385a8..b631390592 100644 --- a/src/test/run-pass/tail-cps.rs +++ b/src/test/run-pass/tail-cps.rs @@ -12,13 +12,13 @@ fn checktrue(rs: bool) -> bool { assert!((rs)); return true; } pub fn main() { let k = checktrue; evenk(42, k); oddk(45, k); } -fn evenk(n: int, k: fn(bool) -> bool) -> bool { +fn evenk(n: isize, k: fn(bool) -> bool) -> bool { println!("evenk"); println!("{}", n); if n == 0 { return k(true); } else { return oddk(n - 1, k); } } -fn oddk(n: int, k: fn(bool) -> bool) -> bool { +fn oddk(n: isize, k: fn(bool) -> bool) -> bool { println!("oddk"); println!("{}", n); if n == 0 { return k(false); } else { return evenk(n - 1, k); } diff --git a/src/test/run-pass/tail-direct.rs b/src/test/run-pass/tail-direct.rs index fd03d28050..01fc18af34 100644 --- a/src/test/run-pass/tail-direct.rs +++ b/src/test/run-pass/tail-direct.rs @@ -11,8 +11,10 @@ +// pretty-expanded FIXME #23616 + pub fn main() { assert!((even(42))); assert!((odd(45))); } -fn even(n: int) -> bool { if n == 0 { return true; } else { return odd(n - 1); } } +fn even(n: isize) -> bool { if n == 0 { return true; } else { return odd(n - 1); } } -fn odd(n: int) -> bool { if n == 0 { return false; } else { return even(n - 1); } } +fn odd(n: isize) -> bool { if n == 0 { return false; } else { return even(n - 1); } } diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index 78826666f5..786dd2c761 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { test05(); } -fn test05_start(tx : &Sender) { +fn test05_start(tx : &Sender) { tx.send(10).unwrap(); println!("sent 10"); tx.send(20).unwrap(); @@ -24,8 +26,8 @@ fn test05_start(tx : &Sender) { fn test05() { let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { test05_start(&tx) }); - let mut value: int = rx.recv().unwrap(); + let _t = thread::scoped(move|| { test05_start(&tx) }); + let mut value: isize = rx.recv().unwrap(); println!("{}", value); value = rx.recv().unwrap(); println!("{}", value); diff --git a/src/test/run-pass/task-comm-1.rs b/src/test/run-pass/task-comm-1.rs index 180f6e09ba..9c3466f162 100644 --- a/src/test/run-pass/task-comm-1.rs +++ b/src/test/run-pass/task-comm-1.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; pub fn main() { test00(); } fn start() { println!("Started / Finished task."); } fn test00() { - let _ = Thread::scoped(move|| start() ).join(); + let _ = thread::scoped(move|| start() ).join(); println!("Completing."); } diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index 60af3afec2..f25bb3ff71 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::{channel, Sender}; fn start(tx: &Sender>) { @@ -27,10 +29,10 @@ fn start(tx: &Sender>) { pub fn main() { let (tx, rx) = channel(); - let _child = Thread::spawn(move|| { start(&tx) }); + let _child = thread::scoped(move|| { start(&tx) }); let mut c = rx.recv().unwrap(); c.send("A".to_string()).unwrap(); c.send("B".to_string()).unwrap(); - Thread::yield_now(); + thread::yield_now(); } diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index 1740c49c77..ec9ed53c1d 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -8,17 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; -fn start(tx: &Sender>) { +fn start(tx: &Sender>) { let (tx2, _rx) = channel(); tx.send(tx2).unwrap(); } pub fn main() { let (tx, rx) = channel(); - let _child = Thread::spawn(move|| { + let _child = thread::scoped(move|| { start(&tx) }); let _tx = rx.recv().unwrap(); diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index 08dce2a764..03305091a2 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -8,22 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; pub fn main() { test00(); } -fn start(_task_number: int) { println!("Started / Finished task."); } +fn start(_task_number: isize) { println!("Started / Finished task."); } fn test00() { - let i: int = 0; - let mut result = Thread::scoped(move|| { + let i: isize = 0; + let mut result = thread::scoped(move|| { start(i) }); // Sleep long enough for the task to finish. let mut i = 0_usize; while i < 10000 { - Thread::yield_now(); + thread::yield_now(); i += 1; } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index 429c6ce9fb..15ceacd672 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; -fn start(tx: &Sender, start: int, number_of_messages: int) { - let mut i: int = 0; +fn start(tx: &Sender, start: isize, number_of_messages: isize) { + let mut i: isize = 0; while i< number_of_messages { tx.send(start + i).unwrap(); i += 1; } } pub fn main() { println!("Check that we don't deadlock."); let (tx, rx) = channel(); - let _ = Thread::scoped(move|| { start(&tx, 0, 10) }).join(); + let _t = thread::scoped(move|| { start(&tx, 0, 10) }).join(); println!("Joined task"); } diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 0735e3996e..1e2d9fe52d 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -8,18 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; pub fn main() { let (tx, rx) = channel(); - // Spawn 10 tasks each sending us back one int. + // Spawn 10 tasks each sending us back one isize. let mut i = 10; while (i > 0) { println!("{}", i); let tx = tx.clone(); - Thread::spawn({let i = i; move|| { child(i, &tx) }}); + thread::scoped({let i = i; move|| { child(i, &tx) }}); i = i - 1; } @@ -36,7 +38,7 @@ pub fn main() { println!("main thread exiting"); } -fn child(x: int, tx: &Sender) { +fn child(x: isize, tx: &Sender) { println!("{}", x); tx.send(x).unwrap(); } diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 28eea784f3..2663595aec 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; -fn start(tx: &Sender, i0: int) { +fn start(tx: &Sender, i0: isize) { let mut i = i0; while i > 0 { tx.send(0).unwrap(); @@ -25,7 +29,7 @@ pub fn main() { // the child's point of view the receiver may die. We should // drop messages on the floor in this case, and not crash! let (tx, rx) = channel(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { start(&tx, 10) }); rx.recv(); diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index 1d297c04c8..c6d8f3c0d9 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -13,21 +13,21 @@ use std::cmp; // Tests of ports and channels on various types fn test_rec() { - struct R {val0: int, val1: u8, val2: char} + struct R {val0: isize, val1: u8, val2: char} let (tx, rx) = channel(); - let r0: R = R {val0: 0, val1: 1u8, val2: '2'}; + let r0: R = R {val0: 0, val1: 1, val2: '2'}; tx.send(r0).unwrap(); let mut r1: R; r1 = rx.recv().unwrap(); assert_eq!(r1.val0, 0); - assert_eq!(r1.val1, 1u8); + assert_eq!(r1.val1, 1); assert_eq!(r1.val2, '2'); } fn test_vec() { let (tx, rx) = channel(); - let v0: Vec = vec!(0, 1, 2); + let v0: Vec = vec!(0, 1, 2); tx.send(v0).unwrap(); let v1 = rx.recv().unwrap(); assert_eq!(v1[0], 0); @@ -49,8 +49,8 @@ fn test_str() { #[derive(Debug)] enum t { tag1, - tag2(int), - tag3(int, u8, char) + tag2(isize), + tag3(isize, u8, char) } impl cmp::PartialEq for t { @@ -84,14 +84,14 @@ fn test_tag() { let (tx, rx) = channel(); tx.send(t::tag1).unwrap(); tx.send(t::tag2(10)).unwrap(); - tx.send(t::tag3(10, 11u8, 'A')).unwrap(); + tx.send(t::tag3(10, 11, 'A')).unwrap(); let mut t1: t; t1 = rx.recv().unwrap(); assert_eq!(t1, t::tag1); t1 = rx.recv().unwrap(); assert_eq!(t1, t::tag2(10)); t1 = rx.recv().unwrap(); - assert_eq!(t1, t::tag3(10, 11u8, 'A')); + assert_eq!(t1, t::tag3(10, 11, 'A')); } fn test_chan() { @@ -102,7 +102,7 @@ fn test_chan() { // Does the transmitted channel still work? tx2.send(10).unwrap(); - let mut i: int; + let mut i: isize; i = rx2.recv().unwrap(); assert_eq!(i, 10); } diff --git a/src/test/run-pass/task-comm-17.rs b/src/test/run-pass/task-comm-17.rs index 9db5465f7e..de334c77aa 100644 --- a/src/test/run-pass/task-comm-17.rs +++ b/src/test/run-pass/task-comm-17.rs @@ -8,15 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + // Issue #922 // This test is specifically about spawning temporary closures. -use std::thread::Thread; +use std::thread; fn f() { } pub fn main() { - let _t = Thread::scoped(move|| f() ).join(); + let _t = thread::scoped(move|| f() ).join(); } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index 9028294683..254ad653c4 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(std_misc)] + // no-pretty-expanded FIXME #15189 -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } -fn test00_start(ch: &Sender, message: int, count: int) { +fn test00_start(ch: &Sender, message: isize, count: isize) { println!("Starting test00_start"); - let mut i: int = 0; + let mut i: isize = 0; while i < count { println!("Sending Message"); ch.send(message + 0).unwrap(); @@ -27,20 +29,20 @@ fn test00_start(ch: &Sender, message: int, count: int) { } fn test00() { - let number_of_tasks: int = 16; - let number_of_messages: int = 4; + let number_of_tasks: isize = 16; + let number_of_messages: isize = 4; println!("Creating tasks"); let (tx, rx) = channel(); - let mut i: int = 0; + let mut i: isize = 0; // Create and spawn tasks... let mut results = Vec::new(); while i < number_of_tasks { let tx = tx.clone(); - results.push(Thread::scoped({ + results.push(thread::scoped({ let i = i; move|| { test00_start(&tx, i, number_of_messages) diff --git a/src/test/run-pass/task-comm-4.rs b/src/test/run-pass/task-comm-4.rs index 1f1b750aa5..e70a00591d 100644 --- a/src/test/run-pass/task-comm-4.rs +++ b/src/test/run-pass/task-comm-4.rs @@ -15,8 +15,8 @@ use std::sync::mpsc::channel; pub fn main() { test00(); } fn test00() { - let mut r: int = 0; - let mut sum: int = 0; + let mut r: isize = 0; + let mut sum: isize = 0; let (tx, rx) = channel(); tx.send(1).unwrap(); tx.send(2).unwrap(); diff --git a/src/test/run-pass/task-comm-5.rs b/src/test/run-pass/task-comm-5.rs index 039308d5cf..cd3d97b88b 100644 --- a/src/test/run-pass/task-comm-5.rs +++ b/src/test/run-pass/task-comm-5.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::channel; pub fn main() { test00(); } fn test00() { - let _r: int = 0; - let mut sum: int = 0; + let _r: isize = 0; + let mut sum: isize = 0; let (tx, rx) = channel(); - let number_of_messages: int = 1000; - let mut i: int = 0; + let number_of_messages: isize = 1000; + let mut i: isize = 0; while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } i = 0; while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs index 7cdfddcdeb..80e777d242 100644 --- a/src/test/run-pass/task-comm-6.rs +++ b/src/test/run-pass/task-comm-6.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] use std::sync::mpsc::channel; @@ -15,15 +17,15 @@ use std::sync::mpsc::channel; pub fn main() { test00(); } fn test00() { - let mut r: int = 0; - let mut sum: int = 0; + let mut r: isize = 0; + let mut sum: isize = 0; let (tx, rx) = channel(); let mut tx0 = tx.clone(); let mut tx1 = tx.clone(); let mut tx2 = tx.clone(); let mut tx3 = tx.clone(); - let number_of_messages: int = 1000; - let mut i: int = 0; + let number_of_messages: isize = 1000; + let mut i: isize = 0; while i < number_of_messages { tx0.send(i + 0).unwrap(); tx1.send(i + 0).unwrap(); diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index 6f3b47b8bf..b05e36552a 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -8,43 +8,46 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] #![allow(dead_assignment)] use std::sync::mpsc::{channel, Sender}; -use std::thread::Thread; +use std::thread; pub fn main() { test00(); } -fn test00_start(c: &Sender, start: int, - number_of_messages: int) { - let mut i: int = 0; +fn test00_start(c: &Sender, start: isize, + number_of_messages: isize) { + let mut i: isize = 0; while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } } fn test00() { - let mut r: int = 0; - let mut sum: int = 0; + let mut r: isize = 0; + let mut sum: isize = 0; let (tx, rx) = channel(); - let number_of_messages: int = 10; + let number_of_messages: isize = 10; let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 0, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 1, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 2, number_of_messages); }); let tx2 = tx.clone(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { test00_start(&tx2, number_of_messages * 3, number_of_messages); }); - let mut i: int = 0; + let mut i: isize = 0; while i < number_of_messages { r = rx.recv().unwrap(); sum += r; diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 6d8de4a6a5..758764aa9f 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -8,27 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; use std::sync::mpsc::{channel, Sender}; pub fn main() { test00(); } -fn test00_start(c: &Sender, number_of_messages: int) { - let mut i: int = 0; +fn test00_start(c: &Sender, number_of_messages: isize) { + let mut i: isize = 0; while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } } fn test00() { - let r: int = 0; - let mut sum: int = 0; + let r: isize = 0; + let mut sum: isize = 0; let (tx, rx) = channel(); - let number_of_messages: int = 10; + let number_of_messages: isize = 10; - let result = Thread::scoped(move|| { + let result = thread::scoped(move|| { test00_start(&tx, number_of_messages); }); - let mut i: int = 0; + let mut i: isize = 0; while i < number_of_messages { sum += rx.recv().unwrap(); println!("{}", r); diff --git a/src/test/run-pass/task-comm-chan-nil.rs b/src/test/run-pass/task-comm-chan-nil.rs index 78a4263200..77571504fe 100644 --- a/src/test/run-pass/task-comm-chan-nil.rs +++ b/src/test/run-pass/task-comm-chan-nil.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::mpsc::channel; // rustboot can't transmit nils across channels because they don't have diff --git a/src/test/run-pass/task-life-0.rs b/src/test/run-pass/task-life-0.rs index 3f22992648..b97f4355b3 100644 --- a/src/test/run-pass/task-life-0.rs +++ b/src/test/run-pass/task-life-0.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +// pretty-expanded FIXME #23616 + +#![feature(std_misc)] + +use std::thread; pub fn main() { - let _t = Thread::spawn(move|| child("Hello".to_string()) ); + let _t = thread::scoped(move|| child("Hello".to_string()) ); } fn child(_s: String) { diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs index ca2a8cf550..aa7b61bf11 100644 --- a/src/test/run-pass/task-spawn-move-and-copy.rs +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, std_misc)] -use std::thread::Thread; +use std::thread; use std::sync::mpsc::channel; pub fn main() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); - let x = box 1; - let x_in_parent = &(*x) as *const int as uint; + let x: Box = box 1; + let x_in_parent = &(*x) as *const isize as usize; - let _t = Thread::spawn(move || { - let x_in_child = &(*x) as *const int as uint; + let _t = thread::scoped(move || { + let x_in_child = &(*x) as *const isize as usize; tx.send(x_in_child).unwrap(); }); diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index 1c263b19dd..7bcde7b83c 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -8,24 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, old_io, std_misc, io, set_panic, set_stdio)] -use std::sync::mpsc::channel; -use std::old_io::{ChanReader, ChanWriter}; +use std::io::prelude::*; +use std::io; +use std::str; +use std::sync::{Arc, Mutex}; use std::thread; -fn main() { - let (tx, rx) = channel(); - let mut reader = ChanReader::new(rx); - let stderr = ChanWriter::new(tx); +struct Sink(Arc>>); +impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} - let res = thread::Builder::new().stderr(box stderr as Box) - .spawn(move|| -> () { +fn main() { + let data = Arc::new(Mutex::new(Vec::new())); + let sink = Sink(data.clone()); + let res = thread::Builder::new().spawn(move|| -> () { + io::set_panic(Box::new(sink)); panic!("Hello, world!") }).unwrap().join(); assert!(res.is_err()); - let output = reader.read_to_string().unwrap(); + let output = data.lock().unwrap(); + let output = str::from_utf8(&output).unwrap(); assert!(output.contains("Hello, world!")); } diff --git a/src/test/run-pass/tcp-accept-stress.rs b/src/test/run-pass/tcp-accept-stress.rs index b87718ba46..00467e5633 100644 --- a/src/test/run-pass/tcp-accept-stress.rs +++ b/src/test/run-pass/tcp-accept-stress.rs @@ -13,14 +13,16 @@ // quite quickly and it takes a few seconds for the sockets to get // recycled. +#![feature(old_io, io, std_misc)] + use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream}; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; -static N: uint = 8; -static M: uint = 20; +static N: usize = 8; +static M: usize = 20; fn main() { test(); @@ -38,7 +40,7 @@ fn test() { let a = a.clone(); let cnt = cnt.clone(); let srv_tx = srv_tx.clone(); - Thread::scoped(move|| { + thread::scoped(move|| { let mut a = a; loop { match a.accept() { @@ -57,7 +59,7 @@ fn test() { let _t = (0..N).map(|_| { let cli_tx = cli_tx.clone(); - Thread::scoped(move|| { + thread::scoped(move|| { for _ in 0..M { let _s = TcpStream::connect(addr).unwrap(); } diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs index d1a3edcfbc..64f07a60b3 100644 --- a/src/test/run-pass/tcp-connect-timeouts.rs +++ b/src/test/run-pass/tcp-connect-timeouts.rs @@ -10,7 +10,7 @@ // ignore-pretty // compile-flags:--test -// exec-env:RUST_TEST_TASKS=1 +// exec-env:RUST_TEST_THREADS=1 // Tests for the connect_timeout() function on a TcpStream. This runs with only // one test task to ensure that errors are timeouts, not file descriptor @@ -19,13 +19,14 @@ #![reexport_test_harness_main = "test_main"] #![allow(unused_imports)] +#![feature(old_io, std_misc, io)] use std::old_io::*; use std::old_io::test::*; use std::old_io; use std::time::Duration; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; #[cfg_attr(target_os = "freebsd", ignore)] fn eventual_timeout() { @@ -33,7 +34,7 @@ fn eventual_timeout() { let (tx1, rx1) = channel(); let (_tx2, rx2) = channel::<()>(); - let _t = Thread::spawn(move|| { + let _t = thread::scoped(move|| { let _l = TcpListener::bind(addr).unwrap().listen(); tx1.send(()).unwrap(); let _ = rx2.recv(); diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs index 82584c83de..4209d5986b 100644 --- a/src/test/run-pass/tcp-stress.rs +++ b/src/test/run-pass/tcp-stress.rs @@ -13,19 +13,22 @@ // ignore-openbsd system ulimit (Too many open files) // exec-env:RUST_LOG=debug +#![feature(rustc_private, libc, old_io, io, std_misc)] +#![allow(deprecated, unused_must_use)] + #[macro_use] extern crate log; extern crate libc; use std::sync::mpsc::channel; use std::old_io::net::tcp::{TcpListener, TcpStream}; -use std::old_io::{Acceptor, Listener}; -use std::thread::{Builder, Thread}; +use std::old_io::{Acceptor, Listener, Reader, Writer}; +use std::thread::{self, Builder}; use std::time::Duration; fn main() { // This test has a chance to time out, try to not let it time out - Thread::spawn(move|| -> () { + thread::spawn(move|| -> () { use std::old_io::timer; timer::sleep(Duration::milliseconds(30 * 1000)); println!("timed out!"); @@ -33,7 +36,7 @@ fn main() { }); let (tx, rx) = channel(); - Thread::spawn(move || -> () { + thread::spawn(move || -> () { let mut listener = TcpListener::bind("127.0.0.1:0").unwrap(); tx.send(listener.socket_name().unwrap()).unwrap(); let mut acceptor = listener.listen(); @@ -52,7 +55,7 @@ fn main() { let addr = rx.recv().unwrap(); let (tx, rx) = channel(); - for _ in 0_usize..1000 { + for _ in 0..1000 { let tx = tx.clone(); Builder::new().stack_size(64 * 1024).spawn(move|| { match TcpStream::connect(addr) { @@ -71,7 +74,7 @@ fn main() { // Wait for all clients to exit, but don't wait for the server to exit. The // server just runs infinitely. drop(tx); - for _ in 0_usize..1000 { + for _ in 0..1000 { rx.recv().unwrap(); } unsafe { libc::exit(0) } diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 053df3a57f..49fac24d0b 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -18,10 +18,13 @@ // they're in a different location than before. Hence, these tests are all run // serially here. +#![feature(old_io, old_path, os, old_fs)] + +use std::old_path::{Path, GenericPath}; use std::old_io::fs::PathExtensions; use std::old_io::{fs, TempDir}; use std::old_io; -use std::os; +use std::env; use std::sync::mpsc::channel; use std::thread; @@ -126,7 +129,7 @@ fn test_rm_tempdir_close() { // to depend on std fn recursive_mkdir_rel() { let path = Path::new("frob"); - let cwd = os::getcwd().unwrap(); + let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap()); println!("recursive_mkdir_rel: Making: {} in cwd {} [{}]", path.display(), cwd.display(), path.exists()); fs::mkdir_recursive(&path, old_io::USER_RWX); @@ -144,7 +147,7 @@ fn recursive_mkdir_dot() { fn recursive_mkdir_rel_2() { let path = Path::new("./frob/baz"); - let cwd = os::getcwd().unwrap(); + let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap()); println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{}]", path.display(), cwd.display(), path.exists()); fs::mkdir_recursive(&path, old_io::USER_RWX); @@ -193,7 +196,7 @@ pub fn dont_double_panic() { fn in_tmpdir(f: F) where F: FnOnce() { let tmpdir = TempDir::new("test").ok().expect("can't make tmpdir"); - assert!(os::change_dir(tmpdir.path()).is_ok()); + assert!(env::set_current_dir(tmpdir.path().as_str().unwrap()).is_ok()); f(); } diff --git a/src/test/run-pass/terminate-in-initializer.rs b/src/test/run-pass/terminate-in-initializer.rs index bef9efa9eb..ec9e7de40d 100644 --- a/src/test/run-pass/terminate-in-initializer.rs +++ b/src/test/run-pass/terminate-in-initializer.rs @@ -12,22 +12,24 @@ // Issue #787 // Don't try to clean up uninitialized locals +// pretty-expanded FIXME #23616 + use std::thread; -fn test_break() { loop { let _x: Box = break; } } +fn test_break() { loop { let _x: Box = break; } } -fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box = continue; } } +fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box = continue; } } -fn test_ret() { let _x: Box = return; } +fn test_ret() { let _x: Box = return; } fn test_panic() { - fn f() { let _x: Box = panic!(); } + fn f() { let _x: Box = panic!(); } thread::spawn(move|| f() ).join().err().unwrap(); } fn test_panic_indirect() { fn f() -> ! { panic!(); } - fn g() { let _x: Box = f(); } + fn g() { let _x: Box = f(); } thread::spawn(move|| g() ).join().err().unwrap(); } diff --git a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs index 7c99c968e3..d58b5d3a00 100644 --- a/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs +++ b/src/test/run-pass/test-fn-signature-verification-for-explicit-return-type.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(test)] + // compile-flags: --test // no-pretty-expanded extern crate test; #[bench] -fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {} +pub fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {} #[test] -fn test_explicit_return_type() -> () {} - +pub fn test_explicit_return_type() -> () {} diff --git a/src/test/run-pass/test-should-fail-good-message.rs b/src/test/run-pass/test-should-fail-good-message.rs index dcb2fe6dfc..2869849930 100644 --- a/src/test/run-pass/test-should-fail-good-message.rs +++ b/src/test/run-pass/test-should-fail-good-message.rs @@ -12,15 +12,13 @@ // ignore-pretty: does not work well with `--test` #[test] -#[should_fail(expected = "foo")] -fn test_foo() { +#[should_panic(expected = "foo")] +pub fn test_foo() { panic!("foo bar") } #[test] -#[should_fail(expected = "foo")] -fn test_foo_dynamic() { +#[should_panic(expected = "foo")] +pub fn test_foo_dynamic() { panic!("{} bar", "foo") } - - diff --git a/src/test/run-pass/threads.rs b/src/test/run-pass/threads.rs index abc2938df0..969a42a6f8 100644 --- a/src/test/run-pass/threads.rs +++ b/src/test/run-pass/threads.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +#![feature(std_misc)] + +use std::thread; pub fn main() { let mut i = 10; while i > 0 { - Thread::scoped({let i = i; move|| child(i)}); + thread::scoped({let i = i; move|| child(i)}); i = i - 1; } println!("main thread exiting"); } -fn child(x: int) { println!("{}", x); } +fn child(x: isize) { println!("{}", x); } diff --git a/src/test/run-pass/trailing-comma.rs b/src/test/run-pass/trailing-comma.rs index 76c62a83e7..b9eda08465 100644 --- a/src/test/run-pass/trailing-comma.rs +++ b/src/test/run-pass/trailing-comma.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns,)] +#![feature(slice_patterns)] fn f(_: T,) {} @@ -17,24 +20,24 @@ struct Foo(T); struct Bar; impl Bar { - fn f(_: int,) {} - fn g(self, _: int,) {} + fn f(_: isize,) {} + fn g(self, _: isize,) {} fn h(self,) {} } enum Baz { - Qux(int,), + Qux(isize,), } #[allow(unused,)] pub fn main() { - f::(0,); + f::(0,); let (_, _,) = (1, 1,); let [_, _,] = [1, 1,]; let [_, _, .., _,] = [1, 1, 1, 1,]; let [_, _, _.., _,] = [1, 1, 1, 1,]; - let x: Foo = Foo::(1); + let x: Foo = Foo::(1); Bar::f(0,); Bar.g(0,); diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs index ed25bf8b02..50c9c43ba2 100644 --- a/src/test/run-pass/trait-bounds-basic.rs +++ b/src/test/run-pass/trait-bounds-basic.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] trait Foo : ::std::marker::MarkerTrait { } diff --git a/src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs b/src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs index 5b744a4413..33bfbc3960 100644 --- a/src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs +++ b/src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs @@ -12,14 +12,14 @@ // trait exactly, as long as the implementation doesn't demand *more* bounds // than the trait. +// pretty-expanded FIXME #23616 + trait A { fn foo(&self); } -impl A for int { +impl A for isize { fn foo(&self) {} // Ord implies Eq, so this is ok. } fn main() {} - - diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 26772a5b22..02ea703705 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -14,50 +14,50 @@ // ignore-pretty #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, std_misc)] #![feature(unboxed_closures)] use std::sync::Arc; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; trait Pet { fn name(&self, blk: Box); - fn num_legs(&self) -> uint; + fn num_legs(&self) -> usize; fn of_good_pedigree(&self) -> bool; } struct Catte { - num_whiskers: uint, + num_whiskers: usize, name: String, } struct Dogge { - bark_decibels: uint, - tricks_known: uint, + bark_decibels: usize, + tricks_known: usize, name: String, } struct Goldfyshe { - swim_speed: uint, + swim_speed: usize, name: String, } impl Pet for Catte { fn name(&self, mut blk: Box) { blk(&self.name) } - fn num_legs(&self) -> uint { 4 } + fn num_legs(&self) -> usize { 4 } fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 } } impl Pet for Dogge { fn name(&self, mut blk: Box) { blk(&self.name) } - fn num_legs(&self) -> uint { 4 } + fn num_legs(&self) -> usize { 4 } fn of_good_pedigree(&self) -> bool { self.bark_decibels < 70 || self.tricks_known > 20 } } impl Pet for Goldfyshe { fn name(&self, mut blk: Box) { blk(&self.name) } - fn num_legs(&self) -> uint { 0 } + fn num_legs(&self) -> usize { 0 } fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 } } @@ -83,13 +83,13 @@ pub fn main() { box dogge2 as Box)); let (tx1, rx1) = channel(); let arc1 = arc.clone(); - let _t1 = Thread::spawn(move|| { check_legs(arc1); tx1.send(()); }); + let _t1 = thread::scoped(move|| { check_legs(arc1); tx1.send(()); }); let (tx2, rx2) = channel(); let arc2 = arc.clone(); - let _t2 = Thread::spawn(move|| { check_names(arc2); tx2.send(()); }); + let _t2 = thread::scoped(move|| { check_names(arc2); tx2.send(()); }); let (tx3, rx3) = channel(); let arc3 = arc.clone(); - let _t3 = Thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); }); + let _t3 = thread::scoped(move|| { check_pedigree(arc3); tx3.send(()); }); rx1.recv(); rx2.recv(); rx3.recv(); @@ -104,9 +104,10 @@ fn check_legs(arc: Arc>>) { } fn check_names(arc: Arc>>) { for pet in &*arc { - pet.name(box |name| { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + pet.name(Box::new(|name| { assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8); - }) + })) } } fn check_pedigree(arc: Arc>>) { diff --git a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs index 976120908b..60c1816b16 100644 --- a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs +++ b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + trait U : ::std::marker::MarkerTrait {} trait T { fn get(self) -> X; } diff --git a/src/test/run-pass/trait-bounds-recursion.rs b/src/test/run-pass/trait-bounds-recursion.rs index 7135dad7d1..250390f70b 100644 --- a/src/test/run-pass/trait-bounds-recursion.rs +++ b/src/test/run-pass/trait-bounds-recursion.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + trait I { fn i(&self) -> Self; } trait A : ::std::marker::MarkerTrait { diff --git a/src/test/run-pass/trait-bounds.rs b/src/test/run-pass/trait-bounds.rs index 7ec6ffbd46..642119df15 100644 --- a/src/test/run-pass/trait-bounds.rs +++ b/src/test/run-pass/trait-bounds.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait connection { - fn read(&self) -> int; + fn read(&self) -> isize; } trait connection_factory { @@ -20,7 +22,7 @@ type my_connection = (); type my_connection_factory = (); impl connection for () { - fn read(&self) -> int { 43 } + fn read(&self) -> isize { 43 } } impl connection_factory for my_connection_factory { diff --git a/src/test/run-pass/trait-cache-issue-18209.rs b/src/test/run-pass/trait-cache-issue-18209.rs index a5efb32079..9cc2b2fadc 100644 --- a/src/test/run-pass/trait-cache-issue-18209.rs +++ b/src/test/run-pass/trait-cache-issue-18209.rs @@ -13,6 +13,8 @@ // // See issue #18209. +// pretty-expanded FIXME #23616 + pub trait Foo { fn load_from() -> Box; fn load() -> Box { diff --git a/src/test/run-pass/trait-coercion-generic.rs b/src/test/run-pass/trait-coercion-generic.rs index fa02dabb37..f9a22d5cce 100644 --- a/src/test/run-pass/trait-coercion-generic.rs +++ b/src/test/run-pass/trait-coercion-generic.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] -#![feature(box_syntax)] - trait Trait { fn f(&self, x: T); } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { - x: int, - y: int, + x: isize, + y: isize, } impl Trait<&'static str> for Struct { @@ -29,9 +26,9 @@ impl Trait<&'static str> for Struct { pub fn main() { let a = Struct { x: 1, y: 2 }; - let b: Box> = box a; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let b: Box> = Box::new(a); b.f("Mary"); let c: &Trait<&'static str> = &a; c.f("Joe"); } - diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs index 1ae9b3f0e9..fa31d9891a 100644 --- a/src/test/run-pass/trait-coercion.rs +++ b/src/test/run-pass/trait-coercion.rs @@ -9,18 +9,18 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, old_io, io)] -use std::old_io; +use std::io::{self, Write}; trait Trait { fn f(&self); } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { - x: int, - y: int, + x: isize, + y: isize, } impl Trait for Struct { @@ -29,18 +29,17 @@ impl Trait for Struct { } } -fn foo(mut a: Box) { - a.write(b"Hello\n"); -} +fn foo(mut a: Box) {} + +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. pub fn main() { let a = Struct { x: 1, y: 2 }; - let b: Box = box a; + let b: Box = Box::new(a); b.f(); let c: &Trait = &a; c.f(); - let out = old_io::stdout(); - foo(box out); + let out = io::stdout(); + foo(Box::new(out)); } - diff --git a/src/test/run-pass/trait-composition-trivial.rs b/src/test/run-pass/trait-composition-trivial.rs index de130bf1b4..4138413c5b 100644 --- a/src/test/run-pass/trait-composition-trivial.rs +++ b/src/test/run-pass/trait-composition-trivial.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn foo(&self); } diff --git a/src/test/run-pass/trait-contravariant-self.rs b/src/test/run-pass/trait-contravariant-self.rs index 19d76b8890..17c68d6494 100644 --- a/src/test/run-pass/trait-contravariant-self.rs +++ b/src/test/run-pass/trait-contravariant-self.rs @@ -38,5 +38,3 @@ fn main() { let x: Box = (box SFoo); wants_bar(&x); } - - diff --git a/src/test/run-pass/trait-default-method-bound-subst.rs b/src/test/run-pass/trait-default-method-bound-subst.rs index 5f0e149eb2..e936989537 100644 --- a/src/test/run-pass/trait-default-method-bound-subst.rs +++ b/src/test/run-pass/trait-default-method-bound-subst.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn g(&self, x: T, y: U) -> (T, U) { (x, y) } } diff --git a/src/test/run-pass/trait-default-method-bound-subst2.rs b/src/test/run-pass/trait-default-method-bound-subst2.rs index 1ea3879e7f..4fedbba81f 100644 --- a/src/test/run-pass/trait-default-method-bound-subst2.rs +++ b/src/test/run-pass/trait-default-method-bound-subst2.rs @@ -9,11 +9,13 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn g(&self, x: T) -> T { x } } -impl A for int { } +impl A for isize { } fn f>(i: V, j: T) -> T { i.g(j) diff --git a/src/test/run-pass/trait-default-method-bound-subst3.rs b/src/test/run-pass/trait-default-method-bound-subst3.rs index aff20ffe96..4f749cbd3f 100644 --- a/src/test/run-pass/trait-default-method-bound-subst3.rs +++ b/src/test/run-pass/trait-default-method-bound-subst3.rs @@ -9,11 +9,13 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { fn g(&self, x: T, y: T) -> (T, T) { (x, y) } } -impl A for int { } +impl A for isize { } fn f(i: V, j: T, k: T) -> (T, T) { i.g(j, k) diff --git a/src/test/run-pass/trait-default-method-bound-subst4.rs b/src/test/run-pass/trait-default-method-bound-subst4.rs index 383849ca51..6774569cd2 100644 --- a/src/test/run-pass/trait-default-method-bound-subst4.rs +++ b/src/test/run-pass/trait-default-method-bound-subst4.rs @@ -9,18 +9,20 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { - fn g(&self, x: uint) -> uint { x } + fn g(&self, x: usize) -> usize { x } fn h(&self, x: T) { } } -impl A for int { } +impl A for isize { } -fn f>(i: V, j: uint) -> uint { +fn f>(i: V, j: usize) -> usize { i.g(j) } pub fn main () { - assert_eq!(f::(0, 2_usize), 2_usize); - assert_eq!(f::(0, 2_usize), 2_usize); + assert_eq!(f::(0, 2), 2); + assert_eq!(f::(0, 2), 2); } diff --git a/src/test/run-pass/trait-default-method-bound.rs b/src/test/run-pass/trait-default-method-bound.rs index 8a2f1b1743..4107540a47 100644 --- a/src/test/run-pass/trait-default-method-bound.rs +++ b/src/test/run-pass/trait-default-method-bound.rs @@ -9,11 +9,13 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait A { - fn g(&self) -> int { 10 } + fn g(&self) -> isize { 10 } } -impl A for int { } +impl A for isize { } fn f(i: T) { assert_eq!(i.g(), 10); diff --git a/src/test/run-pass/trait-default-method-xc-2.rs b/src/test/run-pass/trait-default-method-xc-2.rs index b28e8bd24a..d4ed727040 100644 --- a/src/test/run-pass/trait-default-method-xc-2.rs +++ b/src/test/run-pass/trait-default-method-xc-2.rs @@ -12,8 +12,10 @@ // aux-build:trait_default_method_xc_aux_2.rs -extern crate "trait_default_method_xc_aux" as aux; -extern crate "trait_default_method_xc_aux_2" as aux2; +// pretty-expanded FIXME #23616 + +extern crate trait_default_method_xc_aux as aux; +extern crate trait_default_method_xc_aux_2 as aux2; use aux::A; use aux2::{a_struct, welp}; diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs index 4745d05795..65e8c53a25 100644 --- a/src/test/run-pass/trait-default-method-xc.rs +++ b/src/test/run-pass/trait-default-method-xc.rs @@ -10,7 +10,9 @@ // aux-build:trait_default_method_xc_aux.rs -extern crate "trait_default_method_xc_aux" as aux; +// pretty-expanded FIXME #23616 + +extern crate trait_default_method_xc_aux as aux; use aux::{A, TestEquality, Something}; use aux::B; @@ -18,16 +20,16 @@ fn f(i: T) { assert_eq!(i.g(), 10); } -fn welp(i: int, _x: &T) -> int { +fn welp(i: isize, _x: &T) -> isize { i.g() } mod stuff { - pub struct thing { pub x: int } + pub struct thing { pub x: isize } } impl A for stuff::thing { - fn f(&self) -> int { 10 } + fn f(&self) -> isize { 10 } } fn g>(i: V, j: T, k: U) -> (T, U) { @@ -67,7 +69,7 @@ pub fn main() { assert_eq!(0.thing(3.14f64, 1), (3.14f64, 1)); assert_eq!(B::staticthing(&0, 3.14f64, 1), (3.14f64, 1)); - assert_eq!(B::::staticthing::(&0, 3.14, 1), (3.14, 1)); + assert_eq!(B::::staticthing::(&0, 3.14, 1), (3.14, 1)); assert_eq!(g(0, 3.14f64, 1), (3.14f64, 1)); assert_eq!(g(false, 3.14f64, 1), (3.14, 1)); diff --git a/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs b/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs index ca66a106c4..b9ca8971d3 100644 --- a/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs +++ b/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs @@ -12,6 +12,8 @@ // between the builtin rules for Sized and the where clause. Issue // #20959. +// pretty-expanded FIXME #23616 + fn foo(x: Option) where Option : Sized { diff --git a/src/test/run-pass/trait-generic.rs b/src/test/run-pass/trait-generic.rs index 5f4b18df6e..6ef0dacee7 100644 --- a/src/test/run-pass/trait-generic.rs +++ b/src/test/run-pass/trait-generic.rs @@ -10,10 +10,12 @@ +// pretty-expanded FIXME #23616 + trait to_str { fn to_string_(&self) -> String; } -impl to_str for int { +impl to_str for isize { fn to_string_(&self) -> String { self.to_string() } } impl to_str for String { @@ -44,9 +46,9 @@ fn bar>(x: T) -> Vec { } pub fn main() { - assert_eq!(foo(vec!(1)), vec!("hi".to_string())); - assert_eq!(bar:: >(vec!(4, 5)), vec!("4".to_string(), "5".to_string())); + assert_eq!(foo(vec!(1)), ["hi".to_string()]); + assert_eq!(bar:: >(vec!(4, 5)), ["4".to_string(), "5".to_string()]); assert_eq!(bar:: >(vec!("x".to_string(), "y".to_string())), - vec!("x".to_string(), "y".to_string())); - assert_eq!(bar::<(), Vec<()>>(vec!(())), vec!("()".to_string())); + ["x".to_string(), "y".to_string()]); + assert_eq!(bar::<(), Vec<()>>(vec!(())), ["()".to_string()]); } diff --git a/src/test/compile-fail/impl-not-adjacent-to-type.rs b/src/test/run-pass/trait-impl-2.rs similarity index 64% rename from src/test/compile-fail/impl-not-adjacent-to-type.rs rename to src/test/run-pass/trait-impl-2.rs index 7a7673d871..c94b517f6a 100644 --- a/src/test/compile-fail/impl-not-adjacent-to-type.rs +++ b/src/test/run-pass/trait-impl-2.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,17 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod foo { - pub struct Foo { - x: isize, - y: isize, +// pretty-expanded FIXME #23616 + +pub mod Foo { + pub trait Trait { + fn foo(&self); } } -impl foo::Foo { -//~^ ERROR implementations may only be implemented in the same module - fn bar() {} +mod Bar { + impl<'a> ::Foo::Trait+'a { + fn bar(&self) { self.foo() } + } } fn main() {} - diff --git a/src/test/run-pass/trait-impl.rs b/src/test/run-pass/trait-impl.rs index 325fba8a0e..95fd7bda47 100644 --- a/src/test/run-pass/trait-impl.rs +++ b/src/test/run-pass/trait-impl.rs @@ -11,10 +11,12 @@ // Test calling methods on an impl for a bare trait. // aux-build:traitimpl.rs +// pretty-expanded FIXME #23616 + extern crate traitimpl; use traitimpl::Bar; -static mut COUNT: uint = 1; +static mut COUNT: usize = 1; trait T { fn t(&self) {} @@ -29,7 +31,7 @@ impl<'a> T+'a { } } -impl T for int {} +impl T for isize {} struct Foo; impl<'a> Bar<'a> for Foo {} diff --git a/src/test/run-pass/trait-inheritance-auto-xc-2.rs b/src/test/run-pass/trait-inheritance-auto-xc-2.rs index d45d7ebe90..128be2993e 100644 --- a/src/test/run-pass/trait-inheritance-auto-xc-2.rs +++ b/src/test/run-pass/trait-inheritance-auto-xc-2.rs @@ -10,7 +10,9 @@ // aux-build:trait_inheritance_auto_xc_2_aux.rs -extern crate "trait_inheritance_auto_xc_2_aux" as aux; +// pretty-expanded FIXME #23616 + +extern crate trait_inheritance_auto_xc_2_aux as aux; // aux defines impls of Foo, Bar and Baz for A use aux::{Foo, Bar, Baz, A}; diff --git a/src/test/run-pass/trait-inheritance-auto-xc.rs b/src/test/run-pass/trait-inheritance-auto-xc.rs index f4e1908aae..827674c81a 100644 --- a/src/test/run-pass/trait-inheritance-auto-xc.rs +++ b/src/test/run-pass/trait-inheritance-auto-xc.rs @@ -10,15 +10,17 @@ // aux-build:trait_inheritance_auto_xc_aux.rs -extern crate "trait_inheritance_auto_xc_aux" as aux; +// pretty-expanded FIXME #23616 + +extern crate trait_inheritance_auto_xc_aux as aux; use aux::{Foo, Bar, Baz, Quux}; -struct A { x: int } +struct A { x: isize } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } fn f(a: &T) { assert_eq!(a.f(), 10); diff --git a/src/test/run-pass/trait-inheritance-auto.rs b/src/test/run-pass/trait-inheritance-auto.rs index c5a7720e3c..1b72736cde 100644 --- a/src/test/run-pass/trait-inheritance-auto.rs +++ b/src/test/run-pass/trait-inheritance-auto.rs @@ -10,19 +10,21 @@ // Testing that this impl turns A into a Quux, because // A is already a Foo Bar Baz +// pretty-expanded FIXME #23616 + impl Quux for T { } -trait Foo { fn f(&self) -> int; } -trait Bar { fn g(&self) -> int; } -trait Baz { fn h(&self) -> int; } +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } trait Quux: Foo + Bar + Baz { } -struct A { x: int } +struct A { x: isize } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } fn f(a: &T) { assert_eq!(a.f(), 10); diff --git a/src/test/run-pass/trait-inheritance-call-bound-inherited.rs b/src/test/run-pass/trait-inheritance-call-bound-inherited.rs index 46258902f9..c8df12392f 100644 --- a/src/test/run-pass/trait-inheritance-call-bound-inherited.rs +++ b/src/test/run-pass/trait-inheritance-call-bound-inherited.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } +// pretty-expanded FIXME #23616 -struct A { x: int } +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } // Call a function on Foo, given a T: Bar -fn gg(a: &T) -> int { +fn gg(a: &T) -> isize { a.f() } diff --git a/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs b/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs index 7b79ad42ed..fcd6143579 100644 --- a/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs +++ b/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } -trait Baz : Bar { fn h(&self) -> int; } +// pretty-expanded FIXME #23616 -struct A { x: int } +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } +trait Baz : Bar { fn h(&self) -> isize; } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } // Call a function on Foo, given a T: Baz, // which is inherited via Bar -fn gg(a: &T) -> int { +fn gg(a: &T) -> isize { a.f() } diff --git a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs index 68a31ba9db..3996ae850e 100644 --- a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs +++ b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs @@ -11,24 +11,26 @@ // Testing that we can cast to a subtrait and call subtrait // methods. Not testing supertrait methods +// pretty-expanded FIXME #23616 + trait Foo { - fn f(&self) -> int; + fn f(&self) -> isize; } trait Bar : Foo { - fn g(&self) -> int; + fn g(&self) -> isize; } struct A { - x: int + x: isize } impl Foo for A { - fn f(&self) -> int { 10 } + fn f(&self) -> isize { 10 } } impl Bar for A { - fn g(&self) -> int { 20 } + fn g(&self) -> isize { 20 } } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-cast.rs b/src/test/run-pass/trait-inheritance-cast.rs index 51bc275187..7784ed2f26 100644 --- a/src/test/run-pass/trait-inheritance-cast.rs +++ b/src/test/run-pass/trait-inheritance-cast.rs @@ -10,24 +10,26 @@ // Testing that supertrait methods can be called on subtrait object types +// pretty-expanded FIXME #23616 + trait Foo { - fn f(&self) -> int; + fn f(&self) -> isize; } trait Bar : Foo { - fn g(&self) -> int; + fn g(&self) -> isize; } struct A { - x: int + x: isize } impl Foo for A { - fn f(&self) -> int { 10 } + fn f(&self) -> isize { 10 } } impl Bar for A { - fn g(&self) -> int { 20 } + fn g(&self) -> isize { 20 } } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs b/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs index 3ee046e8bf..c665c35b41 100644 --- a/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs +++ b/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs @@ -10,16 +10,18 @@ // aux-build:trait_inheritance_cross_trait_call_xc_aux.rs -extern crate "trait_inheritance_cross_trait_call_xc_aux" as aux; +// pretty-expanded FIXME #23616 + +extern crate trait_inheritance_cross_trait_call_xc_aux as aux; use aux::Foo; trait Bar : Foo { - fn g(&self) -> int; + fn g(&self) -> isize; } impl Bar for aux::A { - fn g(&self) -> int { self.f() } + fn g(&self) -> isize { self.f() } } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-cross-trait-call.rs b/src/test/run-pass/trait-inheritance-cross-trait-call.rs index 7b047b5cc8..418986f961 100644 --- a/src/test/run-pass/trait-inheritance-cross-trait-call.rs +++ b/src/test/run-pass/trait-inheritance-cross-trait-call.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } +// pretty-expanded FIXME #23616 -struct A { x: int } +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } -impl Foo for A { fn f(&self) -> int { 10 } } +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } impl Bar for A { // Testing that this impl can call the impl of Foo - fn g(&self) -> int { self.f() } + fn g(&self) -> isize { self.f() } } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-diamond.rs b/src/test/run-pass/trait-inheritance-diamond.rs index 253c10ac6f..07b1a79110 100644 --- a/src/test/run-pass/trait-inheritance-diamond.rs +++ b/src/test/run-pass/trait-inheritance-diamond.rs @@ -10,17 +10,19 @@ // B and C both require A, so D does as well, twice, but that's just fine -trait A { fn a(&self) -> int; } -trait B: A { fn b(&self) -> int; } -trait C: A { fn c(&self) -> int; } -trait D: B + C { fn d(&self) -> int; } +// pretty-expanded FIXME #23616 + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } +trait D: B + C { fn d(&self) -> isize; } struct S { bogus: () } -impl A for S { fn a(&self) -> int { 10 } } -impl B for S { fn b(&self) -> int { 20 } } -impl C for S { fn c(&self) -> int { 30 } } -impl D for S { fn d(&self) -> int { 40 } } +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } +impl D for S { fn d(&self) -> isize { 40 } } fn f(x: &T) { assert_eq!(x.a(), 10); diff --git a/src/test/run-pass/trait-inheritance-multiple-inheritors.rs b/src/test/run-pass/trait-inheritance-multiple-inheritors.rs index 6cd3d62473..b892462695 100644 --- a/src/test/run-pass/trait-inheritance-multiple-inheritors.rs +++ b/src/test/run-pass/trait-inheritance-multiple-inheritors.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A { fn a(&self) -> int; } -trait B: A { fn b(&self) -> int; } -trait C: A { fn c(&self) -> int; } +// pretty-expanded FIXME #23616 + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } struct S { bogus: () } -impl A for S { fn a(&self) -> int { 10 } } -impl B for S { fn b(&self) -> int { 20 } } -impl C for S { fn c(&self) -> int { 30 } } +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } // Both B and C inherit from A fn f(x: &T) { diff --git a/src/test/run-pass/trait-inheritance-multiple-params.rs b/src/test/run-pass/trait-inheritance-multiple-params.rs index b5524c6dda..37803edb75 100644 --- a/src/test/run-pass/trait-inheritance-multiple-params.rs +++ b/src/test/run-pass/trait-inheritance-multiple-params.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A { fn a(&self) -> int; } -trait B: A { fn b(&self) -> int; } -trait C: A { fn c(&self) -> int; } +// pretty-expanded FIXME #23616 + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } struct S { bogus: () } -impl A for S { fn a(&self) -> int { 10 } } -impl B for S { fn b(&self) -> int { 20 } } -impl C for S { fn c(&self) -> int { 30 } } +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } // Multiple type params, multiple levels of inheritance fn f(x: &X, y: &Y, z: &Z) { diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs index 9a30d51f4c..4af049fc0c 100644 --- a/src/test/run-pass/trait-inheritance-num.rs +++ b/src/test/run-pass/trait-inheritance-num.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::cmp::{PartialEq, PartialOrd}; use std::num::NumCast; diff --git a/src/test/run-pass/trait-inheritance-num0.rs b/src/test/run-pass/trait-inheritance-num0.rs index d68b6a54f7..b7f9534935 100644 --- a/src/test/run-pass/trait-inheritance-num0.rs +++ b/src/test/run-pass/trait-inheritance-num0.rs @@ -1,4 +1,3 @@ - // 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. @@ -11,11 +10,15 @@ // Extending Num and using inherited static methods +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::cmp::PartialOrd; use std::num::NumCast; pub trait Num { - fn from_int(i: int) -> Self; + fn from_int(i: isize) -> Self; fn gt(&self, other: &Self) -> bool; } diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs index 15fb5df462..02ebf6bfa5 100644 --- a/src/test/run-pass/trait-inheritance-num1.rs +++ b/src/test/run-pass/trait-inheritance-num1.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::cmp::PartialOrd; use std::num::NumCast; diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index f89eea4609..773fc387a2 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -1,4 +1,3 @@ - // 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. @@ -11,6 +10,8 @@ // A more complex example of numeric extensions +#![feature(core)] + use std::cmp::{PartialEq, PartialOrd}; use std::num::NumCast; @@ -20,13 +21,13 @@ impl TypeExt for u8 {} impl TypeExt for u16 {} impl TypeExt for u32 {} impl TypeExt for u64 {} -impl TypeExt for uint {} +impl TypeExt for usize {} impl TypeExt for i8 {} impl TypeExt for i16 {} impl TypeExt for i32 {} impl TypeExt for i64 {} -impl TypeExt for int {} +impl TypeExt for isize {} impl TypeExt for f32 {} impl TypeExt for f64 {} @@ -38,13 +39,13 @@ impl NumExt for u8 {} impl NumExt for u16 {} impl NumExt for u32 {} impl NumExt for u64 {} -impl NumExt for uint {} +impl NumExt for usize {} impl NumExt for i8 {} impl NumExt for i16 {} impl NumExt for i32 {} impl NumExt for i64 {} -impl NumExt for int {} +impl NumExt for isize {} impl NumExt for f32 {} impl NumExt for f64 {} @@ -56,7 +57,7 @@ impl UnSignedExt for u8 {} impl UnSignedExt for u16 {} impl UnSignedExt for u32 {} impl UnSignedExt for u64 {} -impl UnSignedExt for uint {} +impl UnSignedExt for usize {} pub trait SignedExt: NumExt {} @@ -65,7 +66,7 @@ impl SignedExt for i8 {} impl SignedExt for i16 {} impl SignedExt for i32 {} impl SignedExt for i64 {} -impl SignedExt for int {} +impl SignedExt for isize {} impl SignedExt for f32 {} impl SignedExt for f64 {} @@ -77,13 +78,13 @@ impl IntegerExt for u8 {} impl IntegerExt for u16 {} impl IntegerExt for u32 {} impl IntegerExt for u64 {} -impl IntegerExt for uint {} +impl IntegerExt for usize {} impl IntegerExt for i8 {} impl IntegerExt for i16 {} impl IntegerExt for i32 {} impl IntegerExt for i64 {} -impl IntegerExt for int {} +impl IntegerExt for isize {} pub trait FloatExt: NumExt {} diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs index 09015d983e..b5cf25bc5a 100644 --- a/src/test/run-pass/trait-inheritance-num3.rs +++ b/src/test/run-pass/trait-inheritance-num3.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(core)] + use std::cmp::{PartialEq, PartialOrd}; use std::num::NumCast; diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs index a21026839a..b2c3900bc0 100644 --- a/src/test/run-pass/trait-inheritance-num5.rs +++ b/src/test/run-pass/trait-inheritance-num5.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::cmp::PartialEq; use std::num::NumCast; pub trait NumExt: PartialEq + NumCast {} impl NumExt for f32 {} -impl NumExt for int {} +impl NumExt for isize {} fn num_eq_one() -> T { NumCast::from(1).unwrap() } pub fn main() { - num_eq_one::(); // you need to actually use the function to trigger the ICE + num_eq_one::(); // you need to actually use the function to trigger the ICE } diff --git a/src/test/run-pass/trait-inheritance-overloading-simple.rs b/src/test/run-pass/trait-inheritance-overloading-simple.rs index 4cd9fbeba9..9c1f585fe4 100644 --- a/src/test/run-pass/trait-inheritance-overloading-simple.rs +++ b/src/test/run-pass/trait-inheritance-overloading-simple.rs @@ -13,7 +13,7 @@ use std::cmp::PartialEq; trait MyNum : PartialEq { } #[derive(Debug)] -struct MyInt { val: int } +struct MyInt { val: isize } impl PartialEq for MyInt { fn eq(&self, other: &MyInt) -> bool { self.val == other.val } @@ -26,7 +26,7 @@ fn f(x: T, y: T) -> bool { return x == y; } -fn mi(v: int) -> MyInt { MyInt { val: v } } +fn mi(v: isize) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y, z) = (mi(3), mi(5), mi(3)); diff --git a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs index 2a087e5e42..f44c6927c8 100644 --- a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs +++ b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs @@ -10,6 +10,8 @@ // aux-build:trait_inheritance_overloading_xc.rs +// pretty-expanded FIXME #23616 + extern crate trait_inheritance_overloading_xc; use trait_inheritance_overloading_xc::{MyNum, MyInt}; @@ -17,7 +19,7 @@ fn f(x: T, y: T) -> (T, T, T) { return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); } -fn mi(v: int) -> MyInt { MyInt { val: v } } +fn mi(v: isize) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); diff --git a/src/test/run-pass/trait-inheritance-overloading.rs b/src/test/run-pass/trait-inheritance-overloading.rs index 893f782cba..b7d0400dd8 100644 --- a/src/test/run-pass/trait-inheritance-overloading.rs +++ b/src/test/run-pass/trait-inheritance-overloading.rs @@ -14,7 +14,7 @@ use std::ops::{Add, Sub, Mul}; trait MyNum : Add + Sub + Mul + PartialEq + Clone { } #[derive(Clone, Debug)] -struct MyInt { val: int } +struct MyInt { val: isize } impl Add for MyInt { type Output = MyInt; @@ -45,7 +45,7 @@ fn f(x: T, y: T) -> (T, T, T) { return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); } -fn mi(v: int) -> MyInt { MyInt { val: v } } +fn mi(v: isize) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); diff --git a/src/test/run-pass/trait-inheritance-self-in-supertype.rs b/src/test/run-pass/trait-inheritance-self-in-supertype.rs index 96f1c940dc..87a36ba7b9 100644 --- a/src/test/run-pass/trait-inheritance-self-in-supertype.rs +++ b/src/test/run-pass/trait-inheritance-self-in-supertype.rs @@ -10,6 +10,8 @@ // Test for issue #4183: use of Self in supertraits. +// pretty-expanded FIXME #23616 + use std::num::Float as StdFloat; pub static FUZZY_EPSILON: f64 = 0.1; diff --git a/src/test/run-pass/trait-inheritance-self.rs b/src/test/run-pass/trait-inheritance-self.rs index 07b0929968..7d975da4a2 100644 --- a/src/test/run-pass/trait-inheritance-self.rs +++ b/src/test/run-pass/trait-inheritance-self.rs @@ -17,7 +17,7 @@ trait Bar : Foo { } struct S { - x: int + x: isize } impl Foo for S { diff --git a/src/test/run-pass/trait-inheritance-simple.rs b/src/test/run-pass/trait-inheritance-simple.rs index 113efa663a..ff89b1ee5d 100644 --- a/src/test/run-pass/trait-inheritance-simple.rs +++ b/src/test/run-pass/trait-inheritance-simple.rs @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { fn f(&self) -> int; } -trait Bar : Foo { fn g(&self) -> int; } +// pretty-expanded FIXME #23616 -struct A { x: int } +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } +struct A { x: isize } -fn ff(a: &T) -> int { +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +fn ff(a: &T) -> isize { a.f() } -fn gg(a: &T) -> int { +fn gg(a: &T) -> isize { a.g() } diff --git a/src/test/run-pass/trait-inheritance-static.rs b/src/test/run-pass/trait-inheritance-static.rs index 611c3e006e..9ed5fd0aaa 100644 --- a/src/test/run-pass/trait-inheritance-static.rs +++ b/src/test/run-pass/trait-inheritance-static.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub trait MyNum { - fn from_int(int) -> Self; + fn from_int(isize) -> Self; } pub trait NumExt: MyNum { } -struct S { v: int } +struct S { v: isize } impl MyNum for S { - fn from_int(i: int) -> S { + fn from_int(i: isize) -> S { S { v: i } diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs index 8f3b325a51..9fe9d7fce7 100644 --- a/src/test/run-pass/trait-inheritance-static2.rs +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -8,20 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(core)] + pub trait MyEq : ::std::marker::MarkerTrait { } pub trait MyNum : ::std::marker::MarkerTrait { - fn from_int(int) -> Self; + fn from_int(isize) -> Self; } pub trait NumExt: MyEq + MyNum { } -struct S { v: int } +struct S { v: isize } impl MyEq for S { } impl MyNum for S { - fn from_int(i: int) -> S { + fn from_int(i: isize) -> S { S { v: i } diff --git a/src/test/run-pass/trait-inheritance-subst.rs b/src/test/run-pass/trait-inheritance-subst.rs index cd57e6a7dd..d35a937a57 100644 --- a/src/test/run-pass/trait-inheritance-subst.rs +++ b/src/test/run-pass/trait-inheritance-subst.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub trait Add { fn add(&self, rhs: &RHS) -> Result; } trait MyNum : Add { } -struct MyInt { val: int } +struct MyInt { val: isize } impl Add for MyInt { fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) } @@ -26,7 +28,7 @@ fn f(x: T, y: T) -> T { return x.add(&y); } -fn mi(v: int) -> MyInt { MyInt { val: v } } +fn mi(v: isize) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); diff --git a/src/test/run-pass/trait-inheritance-subst2.rs b/src/test/run-pass/trait-inheritance-subst2.rs index ebddfafc3b..e0be575950 100644 --- a/src/test/run-pass/trait-inheritance-subst2.rs +++ b/src/test/run-pass/trait-inheritance-subst2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Panda { fn chomp(&self, bamboo: &T) -> T; } @@ -18,7 +20,7 @@ trait Add: Panda { trait MyNum : Add { } -struct MyInt { val: int } +struct MyInt { val: isize } impl Panda for MyInt { fn chomp(&self, bamboo: &MyInt) -> MyInt { @@ -36,7 +38,7 @@ fn f(x: T, y: T) -> T { return x.add(&y).chomp(&y); } -fn mi(v: int) -> MyInt { MyInt { val: v } } +fn mi(v: isize) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); diff --git a/src/test/run-pass/trait-inheritance-visibility.rs b/src/test/run-pass/trait-inheritance-visibility.rs index 3cdedd884a..8c8b9232de 100644 --- a/src/test/run-pass/trait-inheritance-visibility.rs +++ b/src/test/run-pass/trait-inheritance-visibility.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + mod traits { - pub trait Foo { fn f(&self) -> int; } + pub trait Foo { fn f(&self) -> isize; } - impl Foo for int { fn f(&self) -> int { 10 } } + impl Foo for isize { fn f(&self) -> isize { 10 } } } trait Quux: traits::Foo { } diff --git a/src/test/run-pass/trait-inheritance2.rs b/src/test/run-pass/trait-inheritance2.rs index 7fa895ddf9..9e721836d6 100644 --- a/src/test/run-pass/trait-inheritance2.rs +++ b/src/test/run-pass/trait-inheritance2.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { fn f(&self) -> int; } -trait Bar { fn g(&self) -> int; } -trait Baz { fn h(&self) -> int; } +// pretty-expanded FIXME #23616 + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } trait Quux: Foo + Bar + Baz { } -struct A { x: int } +struct A { x: isize } -impl Foo for A { fn f(&self) -> int { 10 } } -impl Bar for A { fn g(&self) -> int { 20 } } -impl Baz for A { fn h(&self) -> int { 30 } } +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } impl Quux for A {} fn f(a: &T) { diff --git a/src/test/run-pass/trait-object-generics.rs b/src/test/run-pass/trait-object-generics.rs index 6f89490716..63246b870c 100644 --- a/src/test/run-pass/trait-object-generics.rs +++ b/src/test/run-pass/trait-object-generics.rs @@ -10,6 +10,8 @@ // test for #8664 +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -40,14 +42,14 @@ impl Impl { enum Type { Constant(T) } trait Trait { - fn method(&self,Type<(K,V)>) -> int; + fn method(&self,Type<(K,V)>) -> isize; } impl Trait for () { - fn method(&self, _x: Type<(u8,V)>) -> int { 0 } + fn method(&self, _x: Type<(u8,V)>) -> isize { 0 } } pub fn main() { let a = box() () as Box>; - assert_eq!(a.method(Type::Constant((1u8, 2u8))), 0); + assert_eq!(a.method(Type::Constant((1, 2))), 0); } diff --git a/src/test/run-pass/trait-object-with-lifetime-bound.rs b/src/test/run-pass/trait-object-with-lifetime-bound.rs index 4e481910aa..30a05ee1c5 100644 --- a/src/test/run-pass/trait-object-with-lifetime-bound.rs +++ b/src/test/run-pass/trait-object-with-lifetime-bound.rs @@ -11,6 +11,8 @@ // Uncovered during work on new scoping rules for safe destructors // as an important use case to support properly. +// pretty-expanded FIXME #23616 + pub struct E<'a> { pub f: &'a u8, } @@ -36,7 +38,7 @@ fn extension<'e>(x: &'e E<'e>) -> Box { } fn main() { - let w = E { f: &10u8 }; + let w = E { f: &10 }; let o = extension(&w); - assert_eq!(o.n(), 10u8); + assert_eq!(o.n(), 10); } diff --git a/src/test/run-pass/trait-region-pointer-simple.rs b/src/test/run-pass/trait-region-pointer-simple.rs index 412fb6625e..95311e62e6 100644 --- a/src/test/run-pass/trait-region-pointer-simple.rs +++ b/src/test/run-pass/trait-region-pointer-simple.rs @@ -9,15 +9,15 @@ // except according to those terms. trait Foo { - fn f(&self) -> int; + fn f(&self) -> isize; } struct A { - x: int + x: isize } impl Foo for A { - fn f(&self) -> int { + fn f(&self) -> isize { println!("Today's number is {}", self.x); return self.x; } diff --git a/src/test/run-pass/trait-safety-ok-cc.rs b/src/test/run-pass/trait-safety-ok-cc.rs index 99203d3e24..ada7939956 100644 --- a/src/test/run-pass/trait-safety-ok-cc.rs +++ b/src/test/run-pass/trait-safety-ok-cc.rs @@ -8,23 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:trait-safety-lib.rs +// aux-build:trait_safety_lib.rs // Simple smoke test that unsafe traits can be compiled across crates. -extern crate "trait-safety-lib" as lib; +// pretty-expanded FIXME #23616 + +extern crate trait_safety_lib as lib; use lib::Foo; -struct Bar { x: int } +struct Bar { x: isize } unsafe impl Foo for Bar { - fn foo(&self) -> int { self.x } + fn foo(&self) -> isize { self.x } } -fn take_foo(f: &F) -> int { f.foo() } +fn take_foo(f: &F) -> isize { f.foo() } fn main() { - let x: int = 22; + let x: isize = 22; assert_eq!(22, take_foo(&x)); let x: Bar = Bar { x: 23 }; diff --git a/src/test/run-pass/trait-safety-ok.rs b/src/test/run-pass/trait-safety-ok.rs index a24796a7d0..3cd23aeaf2 100644 --- a/src/test/run-pass/trait-safety-ok.rs +++ b/src/test/run-pass/trait-safety-ok.rs @@ -10,17 +10,19 @@ // Simple smoke test that unsafe traits can be compiled etc. +// pretty-expanded FIXME #23616 + unsafe trait Foo { - fn foo(&self) -> int; + fn foo(&self) -> isize; } -unsafe impl Foo for int { - fn foo(&self) -> int { *self } +unsafe impl Foo for isize { + fn foo(&self) -> isize { *self } } -fn take_foo(f: &F) -> int { f.foo() } +fn take_foo(f: &F) -> isize { f.foo() } fn main() { - let x: int = 22; + let x: isize = 22; assert_eq!(22, take_foo(&x)); } diff --git a/src/test/run-pass/trait-static-method-overwriting.rs b/src/test/run-pass/trait-static-method-overwriting.rs index 10439d5c86..31968da6ee 100644 --- a/src/test/run-pass/trait-static-method-overwriting.rs +++ b/src/test/run-pass/trait-static-method-overwriting.rs @@ -1,4 +1,3 @@ - // 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. diff --git a/src/test/run-pass/trait-to-str.rs b/src/test/run-pass/trait-to-str.rs index ea8a5a28c3..3d84092c06 100644 --- a/src/test/run-pass/trait-to-str.rs +++ b/src/test/run-pass/trait-to-str.rs @@ -15,7 +15,7 @@ trait to_str { fn to_string_(&self) -> String; } -impl to_str for int { +impl to_str for isize { fn to_string_(&self) -> String { self.to_string() } } diff --git a/src/test/run-pass/trait-where-clause-vs-impl.rs b/src/test/run-pass/trait-where-clause-vs-impl.rs index 772310d473..f3dcb51f97 100644 --- a/src/test/run-pass/trait-where-clause-vs-impl.rs +++ b/src/test/run-pass/trait-where-clause-vs-impl.rs @@ -13,6 +13,8 @@ // // Issue #18453. +// pretty-expanded FIXME #23616 + use std::rc::Rc; pub trait Foo { diff --git a/src/test/run-pass/trait-with-bounds-default.rs b/src/test/run-pass/trait-with-bounds-default.rs index 6b2c5093c8..34a79c4cf3 100644 --- a/src/test/run-pass/trait-with-bounds-default.rs +++ b/src/test/run-pass/trait-with-bounds-default.rs @@ -27,8 +27,8 @@ trait Getter { } -impl Getter for int { - fn do_get(&self) -> int { *self } +impl Getter for isize { + fn do_get(&self) -> isize { *self } } impl Getter for Option { diff --git a/src/test/run-pass/traits-assoc-type-in-supertrait.rs b/src/test/run-pass/traits-assoc-type-in-supertrait.rs new file mode 100644 index 0000000000..751cd50441 --- /dev/null +++ b/src/test/run-pass/traits-assoc-type-in-supertrait.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test case where an associated type is referenced from within the +// supertrait definition. Issue #20220. + +// pretty-expanded FIXME #23616 + +use std::vec::IntoIter; + +pub trait Foo: Iterator::Key> { + type Key; +} + +impl Foo for IntoIter { + type Key = i32; +} + +fn sum_foo>(f: F) -> i32 { + f.fold(0, |a,b| a + b) +} + +fn main() { + let x = sum_foo(vec![11, 10, 1].into_iter()); + assert_eq!(x, 22); +} diff --git a/src/test/run-pass/traits-conditional-dispatch.rs b/src/test/run-pass/traits-conditional-dispatch.rs index 5af2d4ee80..0190b7b7b9 100644 --- a/src/test/run-pass/traits-conditional-dispatch.rs +++ b/src/test/run-pass/traits-conditional-dispatch.rs @@ -12,19 +12,29 @@ // blanket impl for T:Copy coexists with an impl for Box, because // Box does not impl Copy. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] +use std::marker::MarkerTrait; + trait Get { fn get(&self) -> Self; } -impl Get for T { - fn get(&self) -> T { *self } +trait MyCopy : MarkerTrait { fn copy(&self) -> Self; } +impl MyCopy for u16 { fn copy(&self) -> Self { *self } } +impl MyCopy for u32 { fn copy(&self) -> Self { *self } } +impl MyCopy for i32 { fn copy(&self) -> Self { *self } } +impl MyCopy for Option { fn copy(&self) -> Self { *self } } + +impl Get for T { + fn get(&self) -> T { self.copy() } } -impl Get for Box { - fn get(&self) -> Box { box get_it(&**self) } +impl Get for Box { + fn get(&self) -> Box { box get_it(&**self) } } fn get_it(t: &T) -> T { @@ -35,5 +45,5 @@ fn main() { assert_eq!(get_it(&1_u32), 1_u32); assert_eq!(get_it(&1_u16), 1_u16); assert_eq!(get_it(&Some(1_u16)), Some(1_u16)); - assert_eq!(get_it(&box 1), box 1); + assert_eq!(get_it(&Box::new(1)), Box::new(1)); } diff --git a/src/test/run-pass/traits-conditional-model-fn.rs b/src/test/run-pass/traits-conditional-model-fn.rs index 92ba5aad05..65a4884462 100644 --- a/src/test/run-pass/traits-conditional-model-fn.rs +++ b/src/test/run-pass/traits-conditional-model-fn.rs @@ -14,6 +14,8 @@ // aux-build:go_trait.rs +// pretty-expanded FIXME #23616 + extern crate go_trait; use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; @@ -24,11 +26,11 @@ use std::cell::Cell; /////////////////////////////////////////////////////////////////////////// struct SomeGoableThing { - counter: Rc> + counter: Rc> } impl Go for SomeGoableThing { - fn go(&self, arg: int) { + fn go(&self, arg: isize) { self.counter.set(self.counter.get() + arg); } } @@ -36,11 +38,11 @@ impl Go for SomeGoableThing { /////////////////////////////////////////////////////////////////////////// struct SomeGoOnceableThing { - counter: Rc> + counter: Rc> } impl GoOnce for SomeGoOnceableThing { - fn go_once(self, arg: int) { + fn go_once(self, arg: isize) { self.counter.set(self.counter.get() + arg); } } diff --git a/src/test/run-pass/traits-default-method-macro.rs b/src/test/run-pass/traits-default-method-macro.rs index 245ae540ee..1ec58eac58 100644 --- a/src/test/run-pass/traits-default-method-macro.rs +++ b/src/test/run-pass/traits-default-method-macro.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn bar(&self) -> String { format!("test") diff --git a/src/test/run-pass/traits-default-method-mut.rs b/src/test/run-pass/traits-default-method-mut.rs index a3a1076ecb..3f61eb4723 100644 --- a/src/test/run-pass/traits-default-method-mut.rs +++ b/src/test/run-pass/traits-default-method-mut.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] trait Foo { - fn foo(&self, mut v: int) { v = 1; } + fn foo(&self, mut v: isize) { v = 1; } } pub fn main() {} diff --git a/src/test/run-pass/traits-default-method-self.rs b/src/test/run-pass/traits-default-method-self.rs index 270b954521..d9536108f4 100644 --- a/src/test/run-pass/traits-default-method-self.rs +++ b/src/test/run-pass/traits-default-method-self.rs @@ -17,7 +17,7 @@ trait Cat { fn purr(&self) -> bool { true } } -impl Cat for int { +impl Cat for isize { fn meow(&self) -> bool { self.scratch() } diff --git a/src/test/run-pass/traits-default-method-trivial.rs b/src/test/run-pass/traits-default-method-trivial.rs index 474632a7ff..0e71fcab9d 100644 --- a/src/test/run-pass/traits-default-method-trivial.rs +++ b/src/test/run-pass/traits-default-method-trivial.rs @@ -17,7 +17,7 @@ trait Cat { fn purr(&self) -> bool { true } } -impl Cat for int { +impl Cat for isize { fn meow(&self) -> bool { self.scratch() } diff --git a/src/test/run-pass/traits-issue-22019.rs b/src/test/run-pass/traits-issue-22019.rs index 7e0f60d55a..2f3e0c64f6 100644 --- a/src/test/run-pass/traits-issue-22019.rs +++ b/src/test/run-pass/traits-issue-22019.rs @@ -12,6 +12,8 @@ // distinct scopes to be compared (`'g` and `'h`). The only important // thing is that compilation succeeds here. +// pretty-expanded FIXME #23616 + #![allow(missing_copy_implementations)] #![allow(unused_variables)] diff --git a/src/test/run-pass/traits-issue-22110.rs b/src/test/run-pass/traits-issue-22110.rs index 9cdcf4945d..3da8c25397 100644 --- a/src/test/run-pass/traits-issue-22110.rs +++ b/src/test/run-pass/traits-issue-22110.rs @@ -12,6 +12,8 @@ // and the blanket impl. The only important thing is that compilation // succeeds here. Issue #22110. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] trait Foo { diff --git a/src/test/run-pass/traits-issue-22655.rs b/src/test/run-pass/traits-issue-22655.rs new file mode 100644 index 0000000000..ded17422c4 --- /dev/null +++ b/src/test/run-pass/traits-issue-22655.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for issue #22655: This test should not lead to +// infinite recursion. + +// pretty-expanded FIXME #23616 + +unsafe impl Send for Unique { } + +pub struct Unique { + pointer: *const T, +} + +pub struct Node { + vals: V, + edges: Unique>, +} + +fn is_send() {} + +fn main() { + is_send::>(); +} diff --git a/src/test/run-pass/traits-issue-23003.rs b/src/test/run-pass/traits-issue-23003.rs new file mode 100644 index 0000000000..46cd22f22b --- /dev/null +++ b/src/test/run-pass/traits-issue-23003.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test stack overflow triggered by evaluating the implications. To be +// WF, the type `Receipt` would require that `::Cancel` be WF. This normalizes to `Receipt` +// again, leading to an infinite cycle. Issue #23003. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] +#![allow(unused_variables)] + +use std::marker::PhantomData; + +trait Async { + type Cancel; +} + +struct Receipt { + marker: PhantomData, +} + +struct Complete { + core: Option<()>, +} + +impl Async for Complete { + type Cancel = Receipt; +} + +fn foo(r: Receipt) { } + +fn main() { } diff --git a/src/test/run-pass/traits-multidispatch-infer-convert-target.rs b/src/test/run-pass/traits-multidispatch-infer-convert-target.rs index 532ef7cbec..1f1d1a46cf 100644 --- a/src/test/run-pass/traits-multidispatch-infer-convert-target.rs +++ b/src/test/run-pass/traits-multidispatch-infer-convert-target.rs @@ -10,6 +10,8 @@ // Test that we can infer the Target based on the Self or vice versa. +// pretty-expanded FIXME #23616 + use std::mem; trait Convert { @@ -28,7 +30,7 @@ impl Convert for u32 { } } -fn test(_: T, _: U, t_size: uint, u_size: uint) +fn test(_: T, _: U, t_size: usize, u_size: usize) where T : Convert { assert_eq!(mem::size_of::(), t_size); diff --git a/src/test/run-pass/traits-repeated-supertrait.rs b/src/test/run-pass/traits-repeated-supertrait.rs new file mode 100644 index 0000000000..509a6e36af --- /dev/null +++ b/src/test/run-pass/traits-repeated-supertrait.rs @@ -0,0 +1,58 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test that we can invoke the +// various methods in various ways successfully. +// See also `compile-fail/trait-repeated-supertrait-ambig.rs`. + +// pretty-expanded FIXME #23616 + +trait CompareTo { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo + CompareTo { +} + +impl CompareTo for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &CompareToInts) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_trait(c: &C) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_ufcs1(c: &C) -> bool { + CompareToInts::same_as(c, 22_i64) && CompareToInts::same_as(c, 22_u64) +} + +fn with_ufcs2(c: &C) -> bool { + CompareTo::same_as(c, 22_i64) && CompareTo::same_as(c, 22_u64) +} + +fn main() { + assert_eq!(22_i64.same_as(22_i64), true); + assert_eq!(22_i64.same_as(22_u64), true); + assert_eq!(with_trait(&22), true); + assert_eq!(with_obj(&22), true); + assert_eq!(with_ufcs1(&22), true); + assert_eq!(with_ufcs2(&22), true); +} diff --git a/src/test/run-pass/trans-tag-static-padding.rs b/src/test/run-pass/trans-tag-static-padding.rs index 6d0ae8f67c..3e2297f008 100644 --- a/src/test/run-pass/trans-tag-static-padding.rs +++ b/src/test/run-pass/trans-tag-static-padding.rs @@ -21,6 +21,8 @@ // Last 7 bytes of Request struct are not occupied by any fields. +// pretty-expanded FIXME #23616 + enum TestOption { TestNone, TestSome(T), diff --git a/src/test/run-pass/transmute-non-immediate-to-immediate.rs b/src/test/run-pass/transmute-non-immediate-to-immediate.rs index 70a41f773a..bd705a909b 100644 --- a/src/test/run-pass/transmute-non-immediate-to-immediate.rs +++ b/src/test/run-pass/transmute-non-immediate-to-immediate.rs @@ -11,8 +11,10 @@ // Issue #7988 // Transmuting non-immediate type to immediate type +// pretty-expanded FIXME #23616 + pub fn main() { unsafe { - ::std::mem::transmute::<[int; 1],int>([1]) + ::std::mem::transmute::<[isize; 1],isize>([1]) }; } diff --git a/src/test/run-pass/trivial_casts.rs b/src/test/run-pass/trivial_casts.rs new file mode 100644 index 0000000000..3da1ba0f04 --- /dev/null +++ b/src/test/run-pass/trivial_casts.rs @@ -0,0 +1,71 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that all coercions can actually be done using casts (modulo the lints). + +#![allow(trivial_casts, trivial_numeric_casts)] + +trait Foo { + fn foo(&self) {} +} + +pub struct Bar; + +impl Foo for Bar {} + +pub fn main() { + // Numeric + let _ = 42_i32 as i32; + let _ = 42_u8 as u8; + + // & to * pointers + let x: &u32 = &42; + let _ = x as *const u32; + + let x: &mut u32 = &mut 42; + let _ = x as *mut u32; + + // unsize array + let x: &[u32; 3] = &[42, 43, 44]; + let _ = x as &[u32]; + let _ = x as *const [u32]; + + let x: &mut [u32; 3] = &mut [42, 43, 44]; + let _ = x as &mut [u32]; + let _ = x as *mut [u32]; + + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _ = x as Box<[u32]>; + + // unsize trait + let x: &Bar = &Bar; + let _ = x as &Foo; + let _ = x as *const Foo; + + let x: &mut Bar = &mut Bar; + let _ = x as &mut Foo; + let _ = x as *mut Foo; + + let x: Box = Box::new(Bar); + let _ = x as Box; + + // functions + fn baz(_x: i32) {} + let _ = &baz as &Fn(i32); + let x = |_x: i32| {}; + let _ = &x as &Fn(i32); +} + +// subtyping +pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) { + let _ = a as &'a Bar; + let _ = b as &'a Bar; + let _ = b as &'b Bar; +} diff --git a/src/test/run-pass/tup.rs b/src/test/run-pass/tup.rs index dd508d6e90..50687756e2 100644 --- a/src/test/run-pass/tup.rs +++ b/src/test/run-pass/tup.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type point = (int, int); +// pretty-expanded FIXME #23616 -fn f(p: point, x: int, y: int) { +type point = (isize, isize); + +fn f(p: point, x: isize, y: isize) { let (a, b) = p; assert_eq!(a, x); assert_eq!(b, y); diff --git a/src/test/run-pass/tuple-index-fat-types.rs b/src/test/run-pass/tuple-index-fat-types.rs index 924b861a91..395531d157 100644 --- a/src/test/run-pass/tuple-index-fat-types.rs +++ b/src/test/run-pass/tuple-index-fat-types.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo<'a>(&'a [int]); +// pretty-expanded FIXME #23616 + +struct Foo<'a>(&'a [isize]); fn main() { - let x: &[int] = &[1, 2, 3]; + let x: &[isize] = &[1, 2, 3]; let y = (x,); assert_eq!(y.0, x); - let x: &[int] = &[1, 2, 3]; + let x: &[isize] = &[1, 2, 3]; let y = Foo(x); assert_eq!(y.0, x); } diff --git a/src/test/run-pass/tuple-index.rs b/src/test/run-pass/tuple-index.rs index abdf617277..a70b49296f 100644 --- a/src/test/run-pass/tuple-index.rs +++ b/src/test/run-pass/tuple-index.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Point(int, int); +// pretty-expanded FIXME #23616 + +struct Point(isize, isize); fn main() { let mut x = Point(3, 2); diff --git a/src/test/run-pass/tuple-struct-construct.rs b/src/test/run-pass/tuple-struct-construct.rs index 7773bf647f..c40adf2260 100644 --- a/src/test/run-pass/tuple-struct-construct.rs +++ b/src/test/run-pass/tuple-struct-construct.rs @@ -9,7 +9,7 @@ // except according to those terms. #[derive(Debug)] -struct Foo(int, int); +struct Foo(isize, isize); pub fn main() { let x = Foo(1, 2); diff --git a/src/test/run-pass/tuple-struct-constructor-pointer.rs b/src/test/run-pass/tuple-struct-constructor-pointer.rs index bcd62e92b4..90cf94666d 100644 --- a/src/test/run-pass/tuple-struct-constructor-pointer.rs +++ b/src/test/run-pass/tuple-struct-constructor-pointer.rs @@ -9,13 +9,13 @@ // except according to those terms. #[derive(PartialEq, Debug)] -struct Foo(int); +struct Foo(isize); #[derive(PartialEq, Debug)] -struct Bar(int, int); +struct Bar(isize, isize); pub fn main() { - let f: fn(int) -> Foo = Foo; - let g: fn(int, int) -> Bar = Bar; + let f: fn(isize) -> Foo = Foo; + let g: fn(isize, isize) -> Bar = Bar; assert_eq!(f(42), Foo(42)); assert_eq!(g(4, 7), Bar(4, 7)); } diff --git a/src/test/run-pass/tuple-struct-destructuring.rs b/src/test/run-pass/tuple-struct-destructuring.rs index ec7675abf8..4b0eb26cf9 100644 --- a/src/test/run-pass/tuple-struct-destructuring.rs +++ b/src/test/run-pass/tuple-struct-destructuring.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo(int, int); +struct Foo(isize, isize); pub fn main() { let x = Foo(1, 2); diff --git a/src/test/run-pass/tuple-struct-matching.rs b/src/test/run-pass/tuple-struct-matching.rs index f50b040595..b37302fce0 100644 --- a/src/test/run-pass/tuple-struct-matching.rs +++ b/src/test/run-pass/tuple-struct-matching.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo(int, int); +struct Foo(isize, isize); pub fn main() { let x = Foo(1, 2); diff --git a/src/test/run-pass/tuple-struct-trivial.rs b/src/test/run-pass/tuple-struct-trivial.rs index c22c812760..fa2c9768fc 100644 --- a/src/test/run-pass/tuple-struct-trivial.rs +++ b/src/test/run-pass/tuple-struct-trivial.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo(int, int, int); +// pretty-expanded FIXME #23616 + +struct Foo(isize, isize, isize); pub fn main() { } diff --git a/src/test/run-pass/tydesc-name.rs b/src/test/run-pass/tydesc-name.rs index e3b148ac92..4ba7e786ec 100644 --- a/src/test/run-pass/tydesc-name.rs +++ b/src/test/run-pass/tydesc-name.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 -use std::intrinsics::get_tydesc; +#![feature(core)] + +use std::intrinsics::type_name; struct Foo { x: T @@ -17,7 +20,7 @@ struct Foo { pub fn main() { unsafe { - assert_eq!((*get_tydesc::()).name, "isize"); - assert_eq!((*get_tydesc::>()).name, "Foo"); + assert_eq!(type_name::(), "isize"); + assert_eq!(type_name::>(), "Foo"); } } diff --git a/src/test/run-pass/type-id-higher-rank.rs b/src/test/run-pass/type-id-higher-rank.rs index d33ebeadba..ec5aa2863a 100644 --- a/src/test/run-pass/type-id-higher-rank.rs +++ b/src/test/run-pass/type-id-higher-rank.rs @@ -11,17 +11,19 @@ // Test that type IDs correctly account for higher-rank lifetimes // Also acts as a regression test for an ICE (issue #19791) -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 -use std::any::TypeId; +#![feature(unboxed_closures, core)] + +use std::any::{Any, TypeId}; fn main() { // Bare fns { - let a = TypeId::of::(); - let b = TypeId::of:: fn(&'static int, &'a int)>(); - let c = TypeId::of:: fn(&'a int, &'b int)>(); - let d = TypeId::of:: fn(&'b int, &'a int)>(); + let a = TypeId::of::(); + let b = TypeId::of:: fn(&'static isize, &'a isize)>(); + let c = TypeId::of:: fn(&'a isize, &'b isize)>(); + let d = TypeId::of:: fn(&'b isize, &'a isize)>(); assert!(a != b); assert!(a != c); assert!(a != d); @@ -30,16 +32,16 @@ fn main() { assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly - let e = TypeId::of:: fn(fn(&'a int) -> &'a int)>(); - let f = TypeId::of:: fn(&'a int) -> &'a int)>(); + let e = TypeId::of:: fn(fn(&'a isize) -> &'a isize)>(); + let f = TypeId::of:: fn(&'a isize) -> &'a isize)>(); assert!(e != f); } // Boxed unboxed closures { - let a = TypeId::of::>(); - let b = TypeId::of:: Fn(&'static int, &'a int)>>(); - let c = TypeId::of:: Fn(&'a int, &'b int)>>(); - let d = TypeId::of:: Fn(&'b int, &'a int)>>(); + let a = TypeId::of::>(); + let b = TypeId::of:: Fn(&'static isize, &'a isize)>>(); + let c = TypeId::of:: Fn(&'a isize, &'b isize)>>(); + let d = TypeId::of:: Fn(&'b isize, &'a isize)>>(); assert!(a != b); assert!(a != c); assert!(a != d); @@ -48,20 +50,20 @@ fn main() { assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly - let e = TypeId::of:: Fn(Box &'a int>)>>(); - let f = TypeId::of:: Fn(&'a int) -> &'a int>)>>(); + let e = TypeId::of:: Fn(Box &'a isize>)>>(); + let f = TypeId::of:: Fn(&'a isize) -> &'a isize>)>>(); assert!(e != f); } // Raw unboxed closures // Note that every unboxed closure has its own anonymous type, // so no two IDs should equal each other, even when compatible { - let a = id(|_: &int, _: &int| {}); - let b = id(|_: &int, _: &int| {}); + let a = id(|_: &isize, _: &isize| {}); + let b = id(|_: &isize, _: &isize| {}); assert!(a != b); } - fn id(_: T) -> TypeId { + fn id(_: T) -> TypeId { TypeId::of::() } } diff --git a/src/test/run-pass/type-in-nested-module.rs b/src/test/run-pass/type-in-nested-module.rs index f0b7ee072e..7e2360caa9 100644 --- a/src/test/run-pass/type-in-nested-module.rs +++ b/src/test/run-pass/type-in-nested-module.rs @@ -10,9 +10,11 @@ +// pretty-expanded FIXME #23616 + mod a { pub mod b { - pub type t = int; + pub type t = isize; pub fn foo() { let _x: t = 10; } } diff --git a/src/test/run-pass/type-namespace.rs b/src/test/run-pass/type-namespace.rs index e9b0324456..c03ddd0c64 100644 --- a/src/test/run-pass/type-namespace.rs +++ b/src/test/run-pass/type-namespace.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct A { a: int } +// pretty-expanded FIXME #23616 -fn a(a: A) -> int { return a.a; } +struct A { a: isize } + +fn a(a: A) -> isize { return a.a; } pub fn main() { let x: A = A {a: 1}; assert!((a(x) == 1)); } diff --git a/src/test/run-pass/type-param-constraints.rs b/src/test/run-pass/type-param-constraints.rs index 7d1fad5d28..381f1b6825 100644 --- a/src/test/run-pass/type-param-constraints.rs +++ b/src/test/run-pass/type-param-constraints.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -16,14 +18,14 @@ fn s_foo(_shared: T) { } fn u_foo(_unique: T) { } struct r { - i: int, + i: isize, } impl Drop for r { fn drop(&mut self) {} } -fn r(i:int) -> r { +fn r(i:isize) -> r { r { i: i } @@ -32,13 +34,13 @@ fn r(i:int) -> r { pub fn main() { p_foo(r(10)); - p_foo(box r(10)); - p_foo(box 10); + p_foo::>(box r(10)); + p_foo::>(box 10); p_foo(10); - s_foo(box 10); + s_foo::>(box 10); s_foo(10); - u_foo(box 10); + u_foo::>(box 10); u_foo(10); } diff --git a/src/test/run-pass/type-param.rs b/src/test/run-pass/type-param.rs index 209dade8d0..c59e40934f 100644 --- a/src/test/run-pass/type-param.rs +++ b/src/test/run-pass/type-param.rs @@ -10,6 +10,8 @@ +// pretty-expanded FIXME #23616 + type lteq = extern fn(T) -> bool; pub fn main() { } diff --git a/src/test/run-pass/type-params-in-for-each.rs b/src/test/run-pass/type-params-in-for-each.rs index cf8a09998d..fea2bd978e 100644 --- a/src/test/run-pass/type-params-in-for-each.rs +++ b/src/test/run-pass/type-params-in-for-each.rs @@ -9,18 +9,20 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + struct S { a: T, - b: uint, + b: usize, } -fn range_(lo: uint, hi: uint, mut it: F) where F: FnMut(uint) { +fn range_(lo: usize, hi: usize, mut it: F) where F: FnMut(usize) { let mut lo_ = lo; - while lo_ < hi { it(lo_); lo_ += 1_usize; } + while lo_ < hi { it(lo_); lo_ += 1; } } -fn create_index(_index: Vec> , _hash_fn: extern fn(T) -> uint) { - range_(0_usize, 256_usize, |_i| { +fn create_index(_index: Vec> , _hash_fn: extern fn(T) -> usize) { + range_(0, 256, |_i| { let _bucket: Vec = Vec::new(); }) } diff --git a/src/test/run-pass/type-ptr.rs b/src/test/run-pass/type-ptr.rs index 410e3df9e2..67ead80c89 100644 --- a/src/test/run-pass/type-ptr.rs +++ b/src/test/run-pass/type-ptr.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(a: *const int) -> *const int { return a; } +// pretty-expanded FIXME #23616 -fn g(a: *const int) -> *const int { let b = f(a); return b; } +fn f(a: *const isize) -> *const isize { return a; } + +fn g(a: *const isize) -> *const isize { let b = f(a); return b; } pub fn main() { return; } diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index 961a4472bd..8c1251feea 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::size_of; struct t {a: u8, b: i8} struct u {a: u8, b: i8, c: u8} struct v {a: u8, b: i8, c: v2, d: u32} struct v2 {u: char, v: u8} -struct w {a: int, b: ()} -struct x {a: int, b: (), c: ()} -struct y {x: int} +struct w {a: isize, b: ()} +struct x {a: isize, b: (), c: ()} +struct y {x: isize} enum e1 { a(u8, u32), b(u32), c @@ -30,26 +32,26 @@ enum e3 { } pub fn main() { - assert_eq!(size_of::(), 1 as uint); - assert_eq!(size_of::(), 4 as uint); - assert_eq!(size_of::(), 4 as uint); - assert_eq!(size_of::(), 1 as uint); - assert_eq!(size_of::(), 4 as uint); - assert_eq!(size_of::(), 2 as uint); - assert_eq!(size_of::(), 3 as uint); + assert_eq!(size_of::(), 1 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 1 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 2 as usize); + assert_eq!(size_of::(), 3 as usize); // Alignment causes padding before the char and the u32. assert!(size_of::() == - 16 as uint); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); + 16 as usize); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); // Make sure enum types are the appropriate size, mostly // around ensuring alignment is handled properly - assert_eq!(size_of::(), 8 as uint); - assert_eq!(size_of::(), 8 as uint); - assert_eq!(size_of::(), 4 as uint); + assert_eq!(size_of::(), 8 as usize); + assert_eq!(size_of::(), 8 as usize); + assert_eq!(size_of::(), 4 as usize); } diff --git a/src/test/run-pass/type-use-i1-versus-i8.rs b/src/test/run-pass/type-use-i1-versus-i8.rs index 99c68ac810..6cef9c3be1 100644 --- a/src/test/run-pass/type-use-i1-versus-i8.rs +++ b/src/test/run-pass/type-use-i1-versus-i8.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::ptr; pub fn main() { diff --git a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs index 673e852356..2da8b0a508 100644 --- a/src/test/run-pass/typeck-macro-interaction-issue-8852.rs +++ b/src/test/run-pass/typeck-macro-interaction-issue-8852.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum T { - A(int), + A(isize), B(f64) } diff --git a/src/test/run-pass/typeck_type_placeholder_1.rs b/src/test/run-pass/typeck_type_placeholder_1.rs index 48dc944382..53e78db68b 100644 --- a/src/test/run-pass/typeck_type_placeholder_1.rs +++ b/src/test/run-pass/typeck_type_placeholder_1.rs @@ -11,28 +11,30 @@ // This test checks that the `_` type placeholder works // correctly for enabling type inference. +// pretty-expanded FIXME #23616 + struct TestStruct { - x: *const int + x: *const isize } unsafe impl Sync for TestStruct {} -static CONSTEXPR: TestStruct = TestStruct{x: &413 as *const _}; +static CONSTEXPR: TestStruct = TestStruct{ x: &413 }; pub fn main() { - let x: Vec<_> = (0_usize..5).collect(); - let expected: &[uint] = &[0,1,2,3,4]; + let x: Vec<_> = (0..5).collect(); + let expected: &[usize] = &[0,1,2,3,4]; assert_eq!(x, expected); - let x = (0_usize..5).collect::>(); + let x = (0..5).collect::>(); assert_eq!(x, expected); let y: _ = "hello"; assert_eq!(y.len(), 5); - let ptr = &5_usize; + let ptr: &usize = &5; let ptr2 = ptr as *const _; - assert_eq!(ptr as *const uint as uint, ptr2 as uint); + assert_eq!(ptr as *const usize as usize, ptr2 as usize); } diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs index a251fcc732..7a143ce588 100644 --- a/src/test/run-pass/typeid-intrinsic.rs +++ b/src/test/run-pass/typeid-intrinsic.rs @@ -11,8 +11,12 @@ // aux-build:typeid-intrinsic.rs // aux-build:typeid-intrinsic2.rs -extern crate "typeid-intrinsic" as other1; -extern crate "typeid-intrinsic2" as other2; +// pretty-expanded FIXME #23616 + +#![feature(hash, core)] + +extern crate typeid_intrinsic as other1; +extern crate typeid_intrinsic2 as other2; use std::hash::{self, SipHasher}; use std::any::TypeId; @@ -44,18 +48,18 @@ pub fn main() { assert_eq!(other1::id_G(), other2::id_G()); assert_eq!(other1::id_H(), other2::id_H()); - assert_eq!(TypeId::of::(), other2::foo::()); - assert_eq!(TypeId::of::(), other1::foo::()); - assert_eq!(other2::foo::(), other1::foo::()); + assert_eq!(TypeId::of::(), other2::foo::()); + assert_eq!(TypeId::of::(), other1::foo::()); + assert_eq!(other2::foo::(), other1::foo::()); assert_eq!(TypeId::of::(), other2::foo::()); assert_eq!(TypeId::of::(), other1::foo::()); assert_eq!(other2::foo::(), other1::foo::()); } // sanity test of TypeId - let (a, b, c) = (TypeId::of::(), TypeId::of::<&'static str>(), + let (a, b, c) = (TypeId::of::(), TypeId::of::<&'static str>(), TypeId::of::()); - let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), + let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), TypeId::of::()); assert!(a != b); @@ -67,7 +71,7 @@ pub fn main() { assert_eq!(c, f); // check it has a hash - let (a, b) = (TypeId::of::(), TypeId::of::()); + let (a, b) = (TypeId::of::(), TypeId::of::()); assert_eq!(hash::hash::(&a), hash::hash::(&b)); diff --git a/src/test/run-pass/typestate-cfg-nesting.rs b/src/test/run-pass/typestate-cfg-nesting.rs index 37d06bf4f8..86184f6cf0 100644 --- a/src/test/run-pass/typestate-cfg-nesting.rs +++ b/src/test/run-pass/typestate-cfg-nesting.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unused_variable)] diff --git a/src/test/run-pass/typestate-multi-decl.rs b/src/test/run-pass/typestate-multi-decl.rs index 42910c4700..c7762a8464 100644 --- a/src/test/run-pass/typestate-multi-decl.rs +++ b/src/test/run-pass/typestate-multi-decl.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let (x, y) = (10, 20); let z = x + y; diff --git a/src/test/run-pass/u32-decr.rs b/src/test/run-pass/u32-decr.rs index 6ad320580d..4955ac8a4b 100644 --- a/src/test/run-pass/u32-decr.rs +++ b/src/test/run-pass/u32-decr.rs @@ -11,8 +11,10 @@ +// pretty-expanded FIXME #23616 + pub fn main() { - let mut word: u32 = 200000u32; - word = word - 1u32; - assert_eq!(word, 199999u32); + let mut word: u32 = 200000; + word = word - 1; + assert_eq!(word, 199999); } diff --git a/src/test/run-pass/u8-incr-decr.rs b/src/test/run-pass/u8-incr-decr.rs index 0a178b250a..7c67d304ed 100644 --- a/src/test/run-pass/u8-incr-decr.rs +++ b/src/test/run-pass/u8-incr-decr.rs @@ -14,14 +14,16 @@ // These constants were chosen because they aren't used anywhere // in the rest of the generated code so they're easily grep-able. +// pretty-expanded FIXME #23616 + pub fn main() { - let mut x: u8 = 19u8; // 0x13 + let mut x: u8 = 19; // 0x13 - let mut y: u8 = 35u8; // 0x23 + let mut y: u8 = 35; // 0x23 - x = x + 7u8; // 0x7 + x = x + 7; // 0x7 - y = y - 9u8; // 0x9 + y = y - 9; // 0x9 assert_eq!(x, y); } diff --git a/src/test/run-pass/u8-incr.rs b/src/test/run-pass/u8-incr.rs index 90ed3a5eec..e15576c3fa 100644 --- a/src/test/run-pass/u8-incr.rs +++ b/src/test/run-pass/u8-incr.rs @@ -11,13 +11,15 @@ +// pretty-expanded FIXME #23616 + pub fn main() { - let mut x: u8 = 12u8; - let y: u8 = 12u8; - x = x + 1u8; - x = x - 1u8; + let mut x: u8 = 12; + let y: u8 = 12; + x = x + 1; + x = x - 1; assert_eq!(x, y); - // x = 14u8; - // x = x + 1u8; + // x = 14; + // x = x + 1; } diff --git a/src/test/run-pass/ufcs-explicit-self.rs b/src/test/run-pass/ufcs-explicit-self.rs index 2be9f75dae..bd09a311b7 100644 --- a/src/test/run-pass/ufcs-explicit-self.rs +++ b/src/test/run-pass/ufcs-explicit-self.rs @@ -11,50 +11,49 @@ #![allow(unknown_features)] #![feature(box_syntax)] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Foo { - f: int, + f: isize, } impl Foo { - fn foo(self: Foo, x: int) -> int { + fn foo(self: Foo, x: isize) -> isize { self.f + x } - fn bar(self: &Foo, x: int) -> int { + fn bar(self: &Foo, x: isize) -> isize { self.f + x } - fn baz(self: Box, x: int) -> int { + fn baz(self: Box, x: isize) -> isize { self.f + x } } -#[derive(Copy)] +#[derive(Copy, Clone)] struct Bar { f: T, } impl Bar { - fn foo(self: Bar, x: int) -> int { + fn foo(self: Bar, x: isize) -> isize { x } - fn bar<'a>(self: &'a Bar, x: int) -> int { + fn bar<'a>(self: &'a Bar, x: isize) -> isize { x } - fn baz(self: Bar, x: int) -> int { + fn baz(self: Bar, x: isize) -> isize { x } } fn main() { - let foo = box Foo { + let foo: Box<_> = box Foo { f: 1, }; println!("{} {} {}", foo.foo(2), foo.bar(2), foo.baz(2)); - let bar = box Bar { + let bar: Box<_> = box Bar { f: 1, }; println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); - let bar: Box> = bar; + let bar: Box> = bar; println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); } - diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/ufcs-polymorphic-paths.rs similarity index 52% rename from src/test/run-pass/const-polymorphic-paths.rs rename to src/test/run-pass/ufcs-polymorphic-paths.rs index dce12030f7..a6ea0f76dc 100644 --- a/src/test/run-pass/const-polymorphic-paths.rs +++ b/src/test/run-pass/ufcs-polymorphic-paths.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(macro_rules)] +// pretty-expanded FIXME #23616 + +#![feature(collections, rand, into_cow)] use std::borrow::{Cow, IntoCow}; use std::collections::BitVec; @@ -27,11 +29,11 @@ struct Newt(T); fn id(x: T) -> T { x } fn 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 odd(x: usize) -> bool { x % 2 == 1 } fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() } trait Size: Sized { - fn size() -> uint { std::mem::size_of::() } + fn size() -> usize { std::mem::size_of::() } } impl Size for T {} @@ -47,24 +49,26 @@ macro_rules! tests { tests! { // Free function. - id, fn(int) -> int, (5); - id::, fn(int) -> int, (5); + id, fn(i32) -> i32, (5); + id::, fn(i32) -> i32, (5); // Enum variant constructor. - Some, fn(int) -> Option, (5); - Some::, fn(int) -> Option, (5); + Some, fn(i32) -> Option, (5); + Some::, fn(i32) -> Option, (5); // Tuple struct constructor. - Newt, fn(int) -> Newt, (5); - Newt::, fn(int) -> Newt, (5); + Newt, fn(i32) -> Newt, (5); + Newt::, fn(i32) -> Newt, (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); - BitVec::from_fn, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd); - BitVec::from_fn:: bool>, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd); + >::new, fn() -> Vec<()>, (); + Vec::with_capacity, fn(usize) -> Vec<()>, (5); + Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5); + >::with_capacity, fn(usize) -> Vec<()>, (5); + BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); + BitVec::from_fn:: bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); // Inherent non-static method. Vec::map_in_place, fn(Vec, fn(u8) -> i8) -> Vec, (vec![b'f', b'o', b'o'], u8_as_i8); @@ -77,29 +81,52 @@ tests! { // , (vec![b'f', b'o', b'o'], u8_as_i8); // Trait static methods. - ::size, fn() -> uint, (); - Default::default, fn() -> int, (); - ::default, fn() -> int, (); - Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - ::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - Rand::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); - ::rand::, fn(&mut DummyRng) -> int, (&mut dummy_rng()); + bool::size, fn() -> usize, (); + ::size, fn() -> usize, (); + ::size, fn() -> usize, (); + + Default::default, fn() -> i32, (); + i32::default, fn() -> i32, (); + ::default, fn() -> i32, (); + ::default, fn() -> i32, (); + + Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + Rand::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + i32::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); // Trait non-static methods. - Clone::clone, fn(&int) -> int, (&5); - ::clone, fn(&int) -> int, (&5); - FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, + Clone::clone, fn(&i32) -> i32, (&5); + i32::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); + + FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + >::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, + as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); - FromIterator::from_iter::>, fn(OptionIter) -> Vec, + FromIterator::from_iter::>, fn(OptionIter) -> Vec, (Some(5).into_iter()); - as FromIterator<_>>::from_iter::>, fn(OptionIter) -> Vec, + as FromIterator<_>>::from_iter::>, fn(OptionIter) -> Vec, (Some(5).into_iter()); + Add::add, fn(i32, i32) -> i32, (5, 6); + i32::add, fn(i32, i32) -> i32, (5, 6); + ::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); + + String::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); + ::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); >::into_cow, fn(String) -> Cow<'static, str>, diff --git a/src/test/run-pass/ufcs-trait-object.rs b/src/test/run-pass/ufcs-trait-object.rs index 2ae63040d1..b242018458 100644 --- a/src/test/run-pass/ufcs-trait-object.rs +++ b/src/test/run-pass/ufcs-trait-object.rs @@ -11,6 +11,8 @@ // Test that when you use ufcs form to invoke a trait method (on a // trait object) everything works fine. +// pretty-expanded FIXME #23616 + trait Foo { fn test(&self) -> i32; } @@ -20,6 +22,6 @@ impl Foo for i32 { } fn main() { - let a: &Foo = &22_i32; + let a: &Foo = &22; assert_eq!(Foo::test(a), 22); } diff --git a/src/test/run-pass/ufcs-type-params.rs b/src/test/run-pass/ufcs-type-params.rs index ccd5a22522..d72fde1a33 100644 --- a/src/test/run-pass/ufcs-type-params.rs +++ b/src/test/run-pass/ufcs-type-params.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn get(&self) -> T; } diff --git a/src/test/run-pass/uint.rs b/src/test/run-pass/uint.rs index 876e37c535..a894d76297 100644 --- a/src/test/run-pass/uint.rs +++ b/src/test/run-pass/uint.rs @@ -11,4 +11,6 @@ -pub fn main() { let _x: uint = 10 as uint; } +// pretty-expanded FIXME #23616 + +pub fn main() { let _x: usize = 10 as usize; } diff --git a/src/test/run-pass/unary-minus-suffix-inference.rs b/src/test/run-pass/unary-minus-suffix-inference.rs index adbbf1aec9..9d685e0263 100644 --- a/src/test/run-pass/unary-minus-suffix-inference.rs +++ b/src/test/run-pass/unary-minus-suffix-inference.rs @@ -26,7 +26,7 @@ pub fn main() { println!("{}", d_neg); let e = 1; - let e_neg: int = -e; + let e_neg: isize = -e; println!("{}", e_neg); // intentional overflows @@ -48,6 +48,6 @@ pub fn main() { println!("{}", i_neg); let j = 1; - let j_neg: uint = -j; + let j_neg: usize = -j; println!("{}", j_neg); } diff --git a/src/test/run-pass/unboxed-closures-all-traits.rs b/src/test/run-pass/unboxed-closures-all-traits.rs index 7e71e1da46..9ca8e5403a 100644 --- a/src/test/run-pass/unboxed-closures-all-traits.rs +++ b/src/test/run-pass/unboxed-closures-all-traits.rs @@ -8,24 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(lang_items, unboxed_closures)] -fn a int>(f: F) -> int { +fn a isize>(f: F) -> isize { f(1, 2) } -fn b int>(mut f: F) -> int { +fn b isize>(mut f: F) -> isize { f(3, 4) } -fn c int>(f: F) -> int { +fn c isize>(f: F) -> isize { f(5, 6) } fn main() { - let z: int = 7; - assert_eq!(a(move |x: int, y| x + y + z), 10); - assert_eq!(b(move |x: int, y| x + y + z), 14); - assert_eq!(c(move |x: int, y| x + y + z), 18); + let z: isize = 7; + assert_eq!(a(move |x: isize, y| x + y + z), 10); + assert_eq!(b(move |x: isize, y| x + y + z), 14); + assert_eq!(c(move |x: isize, y| x + y + z), 18); } - diff --git a/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs new file mode 100644 index 0000000000..37dccca1e2 --- /dev/null +++ b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs @@ -0,0 +1,37 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that you can supply `&F` where `F: FnMut()`. + +// pretty-expanded FIXME #23616 + +#![feature(lang_items, unboxed_closures)] + +fn a i32>(mut f: F) -> i32 { + f() +} + +fn b(f: &mut FnMut() -> i32) -> i32 { + a(f) +} + +fn c i32>(f: &mut F) -> i32 { + a(f) +} + +fn main() { + let z: isize = 7; + + let x = b(&mut || 22); + assert_eq!(x, 22); + + let x = c(&mut || 22); + assert_eq!(x, 22); +} diff --git a/src/test/run-pass/unboxed-closures-blanket-fn.rs b/src/test/run-pass/unboxed-closures-blanket-fn.rs new file mode 100644 index 0000000000..0f93966077 --- /dev/null +++ b/src/test/run-pass/unboxed-closures-blanket-fn.rs @@ -0,0 +1,37 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that you can supply `&F` where `F: Fn()`. + +// pretty-expanded FIXME #23616 + +#![feature(lang_items, unboxed_closures)] + +fn a i32>(f: F) -> i32 { + f() +} + +fn b(f: &Fn() -> i32) -> i32 { + a(f) +} + +fn c i32>(f: &F) -> i32 { + a(f) +} + +fn main() { + let z: isize = 7; + + let x = b(&|| 22); + assert_eq!(x, 22); + + let x = c(&|| 22); + assert_eq!(x, 22); +} diff --git a/src/test/run-pass/unboxed-closures-boxed.rs b/src/test/run-pass/unboxed-closures-boxed.rs index d515ccf2ec..5dea6a7c6d 100644 --- a/src/test/run-pass/unboxed-closures-boxed.rs +++ b/src/test/run-pass/unboxed-closures-boxed.rs @@ -25,4 +25,3 @@ pub fn main() { println!("{}", z); assert_eq!(z, 5); } - diff --git a/src/test/run-pass/unboxed-closures-by-ref.rs b/src/test/run-pass/unboxed-closures-by-ref.rs index 178865897e..7855cf6ba0 100644 --- a/src/test/run-pass/unboxed-closures-by-ref.rs +++ b/src/test/run-pass/unboxed-closures-by-ref.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] // Test by-ref capture of environment in unboxed closure types diff --git a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs index 0303954ce2..6e92850ac2 100644 --- a/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs +++ b/src/test/run-pass/unboxed-closures-call-fn-autoderef.rs @@ -10,19 +10,21 @@ // Test that the call operator autoderefs when calling a bounded type parameter. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::ops::FnMut; -fn call_with_2(x: &fn(int) -> int) -> int +fn call_with_2(x: &fn(isize) -> isize) -> isize { x(2) // look ma, no `*` } -fn subtract_22(x: int) -> int { x - 22 } +fn subtract_22(x: isize) -> isize { x - 22 } pub fn main() { - let subtract_22: fn(int) -> int = subtract_22; + let subtract_22: fn(isize) -> isize = 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 index 305f496e66..402b4b0b85 100644 --- a/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs +++ b/src/test/run-pass/unboxed-closures-call-sugar-autoderef.rs @@ -10,12 +10,14 @@ // Test that the call operator autoderefs when calling a bounded type parameter. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::ops::FnMut; -fn call_with_2(x: &mut F) -> int - where F : FnMut(int) -> int +fn call_with_2(x: &mut F) -> isize + where F : FnMut(isize) -> isize { x(2) // look ma, no `*` } 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 index da647e90c0..c82026235c 100644 --- a/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs +++ b/src/test/run-pass/unboxed-closures-call-sugar-object-autoderef.rs @@ -11,13 +11,13 @@ // Test that the call operator autoderefs when calling to an object type. #![allow(unknown_features)] -#![feature(box_syntax)] #![feature(unboxed_closures)] use std::ops::FnMut; -fn make_adder(x: int) -> Boxint + 'static> { - box move |y| { x + y } +fn make_adder(x: isize) -> Boxisize + 'static> { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Box::new(move |y| { x + y }) } pub fn main() { @@ -26,4 +26,3 @@ pub fn main() { println!("{}", z); assert_eq!(z, 5); } - diff --git a/src/test/run-pass/unboxed-closures-call-sugar-object.rs b/src/test/run-pass/unboxed-closures-call-sugar-object.rs index 8ee3c96f58..629da1091a 100644 --- a/src/test/run-pass/unboxed-closures-call-sugar-object.rs +++ b/src/test/run-pass/unboxed-closures-call-sugar-object.rs @@ -9,13 +9,13 @@ // except according to those terms. #![allow(unknown_features)] -#![feature(box_syntax)] #![feature(unboxed_closures)] use std::ops::FnMut; -fn make_adder(x: int) -> Boxint + 'static> { - box move |y| { x + y } +fn make_adder(x: isize) -> Boxisize + 'static> { + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Box::new(move |y| { x + y }) } pub fn main() { @@ -24,4 +24,3 @@ pub fn main() { println!("{}", z); assert_eq!(z, 5); } - diff --git a/src/test/run-pass/unboxed-closures-counter-not-moved.rs b/src/test/run-pass/unboxed-closures-counter-not-moved.rs index 0b85916d22..792d172277 100644 --- a/src/test/run-pass/unboxed-closures-counter-not-moved.rs +++ b/src/test/run-pass/unboxed-closures-counter-not-moved.rs @@ -10,6 +10,8 @@ // Test that we mutate a counter on the stack only when we expect to. +// pretty-expanded FIXME #23616 + fn call(f: F) where F : FnOnce() { f(); } diff --git a/src/test/run-pass/unboxed-closures-cross-crate.rs b/src/test/run-pass/unboxed-closures-cross-crate.rs index 96d7559262..0c255c6bd6 100644 --- a/src/test/run-pass/unboxed-closures-cross-crate.rs +++ b/src/test/run-pass/unboxed-closures-cross-crate.rs @@ -12,7 +12,9 @@ // Acts as a regression test for #16790, #18378 and #18543 // aux-build:unboxed-closures-cross-crate.rs -extern crate "unboxed-closures-cross-crate" as ubcc; +// pretty-expanded FIXME #23616 + +extern crate unboxed_closures_cross_crate as ubcc; fn main() { assert_eq!(ubcc::has_closures(), 2_usize); diff --git a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs index 0c49c81517..c91aa6ed0d 100644 --- a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs +++ b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn main() { let mut unboxed = || {}; unboxed(); } - diff --git a/src/test/run-pass/unboxed-closures-drop.rs b/src/test/run-pass/unboxed-closures-drop.rs index f4a24c17e6..f0c6c0ff45 100644 --- a/src/test/run-pass/unboxed-closures-drop.rs +++ b/src/test/run-pass/unboxed-closures-drop.rs @@ -11,18 +11,20 @@ // A battery of tests to ensure destructors of unboxed closure environments // run at the right times. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] -static mut DROP_COUNT: uint = 0; +static mut DROP_COUNT: usize = 0; -fn drop_count() -> uint { +fn drop_count() -> usize { unsafe { DROP_COUNT } } struct Droppable { - x: int, + x: isize, } impl Droppable { @@ -41,27 +43,27 @@ impl Drop for Droppable { } } -fn a int>(f: F) -> int { +fn a isize>(f: F) -> isize { f(1, 2) } -fn b int>(mut f: F) -> int { +fn b isize>(mut f: F) -> isize { f(3, 4) } -fn c int>(f: F) -> int { +fn c isize>(f: F) -> isize { f(5, 6) } fn test_fn() { { - a(move |a: int, b| { a + b }); + a(move |a: isize, b| { a + b }); } assert_eq!(drop_count(), 0); { let z = &Droppable::new(); - a(move |a: int, b| { z; a + b }); + a(move |a: isize, b| { z; a + b }); assert_eq!(drop_count(), 0); } assert_eq!(drop_count(), 1); @@ -69,7 +71,7 @@ fn test_fn() { { let z = &Droppable::new(); let zz = &Droppable::new(); - a(move |a: int, b| { z; zz; a + b }); + a(move |a: isize, b| { z; zz; a + b }); assert_eq!(drop_count(), 1); } assert_eq!(drop_count(), 3); @@ -77,13 +79,13 @@ fn test_fn() { fn test_fn_mut() { { - b(move |a: int, b| { a + b }); + b(move |a: isize, b| { a + b }); } assert_eq!(drop_count(), 3); { let z = &Droppable::new(); - b(move |a: int, b| { z; a + b }); + b(move |a: isize, b| { z; a + b }); assert_eq!(drop_count(), 3); } assert_eq!(drop_count(), 4); @@ -91,7 +93,7 @@ fn test_fn_mut() { { let z = &Droppable::new(); let zz = &Droppable::new(); - b(move |a: int, b| { z; zz; a + b }); + b(move |a: isize, b| { z; zz; a + b }); assert_eq!(drop_count(), 4); } assert_eq!(drop_count(), 6); @@ -99,13 +101,13 @@ fn test_fn_mut() { fn test_fn_once() { { - c(move |a: int, b| { a + b }); + c(move |a: isize, b| { a + b }); } assert_eq!(drop_count(), 6); { let z = Droppable::new(); - c(move |a: int, b| { z; a + b }); + c(move |a: isize, b| { z; a + b }); assert_eq!(drop_count(), 7); } assert_eq!(drop_count(), 7); @@ -113,7 +115,7 @@ fn test_fn_once() { { let z = Droppable::new(); let zz = Droppable::new(); - c(move |a: int, b| { z; zz; a + b }); + c(move |a: isize, b| { z; zz; a + b }); assert_eq!(drop_count(), 9); } assert_eq!(drop_count(), 9); @@ -124,4 +126,3 @@ fn main() { test_fn_mut(); test_fn_once(); } - diff --git a/src/test/run-pass/unboxed-closures-extern-fn-hr.rs b/src/test/run-pass/unboxed-closures-extern-fn-hr.rs index df753f0f33..4af4b320d0 100644 --- a/src/test/run-pass/unboxed-closures-extern-fn-hr.rs +++ b/src/test/run-pass/unboxed-closures-extern-fn-hr.rs @@ -10,25 +10,27 @@ // Checks that higher-ranked extern fn pointers implement the full range of Fn traits. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::ops::{Fn,FnMut,FnOnce}; -fn square(x: &int) -> int { (*x) * (*x) } +fn square(x: &isize) -> isize { (*x) * (*x) } -fn call_itint>(f: &F, x: int) -> int { +fn call_itisize>(f: &F, x: isize) -> isize { (*f)(&x) } -fn call_it_boxed(f: &Fn(&int) -> int, x: int) -> int { +fn call_it_boxed(f: &Fn(&isize) -> isize, x: isize) -> isize { f.call((&x,)) } -fn call_it_mutint>(f: &mut F, x: int) -> int { +fn call_it_mutisize>(f: &mut F, x: isize) -> isize { (*f)(&x) } -fn call_it_onceint>(f: F, x: int) -> int { +fn call_it_onceisize>(f: F, x: isize) -> isize { f(&x) } @@ -42,4 +44,3 @@ fn main() { assert_eq!(y, square(&22)); assert_eq!(z, square(&22)); } - diff --git a/src/test/run-pass/unboxed-closures-extern-fn.rs b/src/test/run-pass/unboxed-closures-extern-fn.rs index a25f5e265e..d711ebbe4b 100644 --- a/src/test/run-pass/unboxed-closures-extern-fn.rs +++ b/src/test/run-pass/unboxed-closures-extern-fn.rs @@ -10,22 +10,24 @@ // Checks that extern fn pointers implement the full range of Fn traits. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] #![feature(unboxed_closures)] use std::ops::{Fn,FnMut,FnOnce}; -fn square(x: int) -> int { x * x } +fn square(x: isize) -> isize { x * x } -fn call_itint>(f: &F, x: int) -> int { +fn call_itisize>(f: &F, x: isize) -> isize { f(x) } -fn call_it_mutint>(f: &mut F, x: int) -> int { +fn call_it_mutisize>(f: &mut F, x: isize) -> isize { f(x) } -fn call_it_onceint>(f: F, x: int) -> int { +fn call_it_onceisize>(f: F, x: isize) -> isize { f(x) } @@ -37,4 +39,3 @@ fn main() { assert_eq!(y, square(22)); assert_eq!(z, square(22)); } - diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs index 5d6029e703..9b71abf365 100644 --- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs @@ -11,20 +11,29 @@ // Checks that the Fn trait hierarchy rules permit // any Fn trait to be used where Fn is implemented. -#![feature(unboxed_closures)] -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::ops::{Fn,FnMut,FnOnce}; struct S; impl Fn<(i32,)> for S { - type Output = i32; extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 { x * x } } +impl FnMut<(i32,)> for S { + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } +} + +impl FnOnce<(i32,)> for S { + type Output = i32; + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } +} + fn call_iti32>(f: &F, x: i32) -> i32 { f(x) } @@ -44,4 +53,3 @@ fn main() { assert_eq!(x, y); assert_eq!(y, z); } - diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs index 95dae41c68..6261058b86 100644 --- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs @@ -11,21 +11,26 @@ // Checks that the Fn trait hierarchy rules permit // FnMut or FnOnce to be used where FnMut is implemented. -#![feature(unboxed_closures)] -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::ops::{FnMut,FnOnce}; struct S; impl FnMut<(i32,)> for S { - type Output = i32; - extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { x * x } } +impl FnOnce<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } +} + fn call_it_muti32>(f: &mut F, x: i32) -> i32 { f(x) } @@ -39,4 +44,3 @@ fn main() { let z = call_it_once(S, 22); assert_eq!(y, z); } - diff --git a/src/test/run-pass/unboxed-closures-generic.rs b/src/test/run-pass/unboxed-closures-generic.rs index f4af42a866..47936ba938 100644 --- a/src/test/run-pass/unboxed-closures-generic.rs +++ b/src/test/run-pass/unboxed-closures-generic.rs @@ -22,4 +22,3 @@ pub fn main() { println!("{}", z); assert_eq!(z, 5); } - diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs index 56de159611..d408612f9b 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-bound.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we are able to infer that the type of `x` is `int` based +// Test that we are able to infer that the type of `x` is `isize` based // on the expected type from the object. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::num::ToPrimitive; @@ -22,5 +24,5 @@ fn doit(val: T, f: &F) } pub fn main() { - doit(0, &|x /*: int*/ | { x.to_int(); }); + doit(0, &|x /*: isize*/ | { x.to_int(); }); } diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs index c74ed665e7..c1e1ff3cd8 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-from-expected-object-type.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we are able to infer that the type of `x` is `int` based +// Test that we are able to infer that the type of `x` is `isize` based // on the expected type from the object. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::num::ToPrimitive; fn doit(val: T, f: &Fn(T)) { f.call((val,)) } pub fn main() { - doit(0, &|x /*: int*/ | { x.to_int(); }); + doit(0, &|x /*: isize*/ | { x.to_int(); }); } diff --git a/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs b/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs index a61dd095a0..99e2149de9 100644 --- a/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs +++ b/src/test/run-pass/unboxed-closures-infer-argument-types-with-bound-regions-from-expected-bound.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we are able to infer that the type of `x` is `int` based +// Test that we are able to infer that the type of `x` is `isize` based // on the expected type from the object. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::num::ToPrimitive; @@ -22,5 +24,5 @@ fn doit(val: T, f: &F) } pub fn main() { - doit(0, &|x /*: int*/ | { x.to_int(); }); + doit(0, &|x /*: isize*/ | { x.to_int(); }); } diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs b/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs index 09b8c8f445..798959f69d 100644 --- a/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs +++ b/src/test/run-pass/unboxed-closures-infer-fnmut-calling-fnmut.rs @@ -11,6 +11,8 @@ // Test that we are able to infer a suitable kind for this closure // that is just called (`FnMut`). +// pretty-expanded FIXME #23616 + fn main() { let mut counter = 0; @@ -26,4 +28,3 @@ fn main() { assert_eq!(counter, 2); } - diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs b/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs index 794527249b..5b1e35a3e5 100644 --- a/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs +++ b/src/test/run-pass/unboxed-closures-infer-fnmut-move.rs @@ -11,6 +11,8 @@ // Test that we are able to infer a suitable kind for this `move` // closure that is just called (`FnMut`). +// pretty-expanded FIXME #23616 + fn main() { let mut counter = 0; diff --git a/src/test/run-pass/unboxed-closures-infer-fnmut.rs b/src/test/run-pass/unboxed-closures-infer-fnmut.rs index 67f36b9a92..cd7f26bba2 100644 --- a/src/test/run-pass/unboxed-closures-infer-fnmut.rs +++ b/src/test/run-pass/unboxed-closures-infer-fnmut.rs @@ -11,6 +11,8 @@ // Test that we are able to infer a suitable kind for this closure // that is just called (`FnMut`). +// pretty-expanded FIXME #23616 + fn main() { let mut counter = 0; diff --git a/src/test/run-pass/unboxed-closures-infer-fnonce-move.rs b/src/test/run-pass/unboxed-closures-infer-fnonce-move.rs index 9f8fc80819..dc106614b5 100644 --- a/src/test/run-pass/unboxed-closures-infer-fnonce-move.rs +++ b/src/test/run-pass/unboxed-closures-infer-fnonce-move.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] // Test that we are able to infer a suitable kind for this `move` diff --git a/src/test/run-pass/unboxed-closures-infer-fnonce.rs b/src/test/run-pass/unboxed-closures-infer-fnonce.rs index f0f10139c5..036b32a44d 100644 --- a/src/test/run-pass/unboxed-closures-infer-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-infer-fnonce.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] // Test that we are able to infer a suitable kind for this closure diff --git a/src/test/run-pass/unboxed-closures-infer-kind.rs b/src/test/run-pass/unboxed-closures-infer-kind.rs index 36c8400be7..edc01d91f5 100644 --- a/src/test/run-pass/unboxed-closures-infer-kind.rs +++ b/src/test/run-pass/unboxed-closures-infer-kind.rs @@ -11,6 +11,8 @@ // Test that we can infer the "kind" of an unboxed closure based on // the expected type. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] // Test by-ref capture of environment in unboxed closure types diff --git a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs index 2d1ba7f39b..e02784f917 100644 --- a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs +++ b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(core,unboxed_closures)] use std::marker::PhantomData; @@ -30,13 +32,20 @@ impl YCombinator { } impl R, A) -> R> Fn<(A,)> for YCombinator { - type Output = R; - extern "rust-call" fn call(&self, (arg,): (A,)) -> R { (self.func)(self, arg) } } +impl R, A) -> R> FnMut<(A,)> for YCombinator { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) } +} + +impl R, A) -> R> FnOnce<(A,)> for YCombinator { + type Output = R; + extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) } +} + fn main() { let factorial = |recur: &Fn(u32) -> u32, arg: u32| -> u32 { if arg == 0 {1} else {arg * recur(arg-1)} diff --git a/src/test/run-pass/unboxed-closures-infer-upvar.rs b/src/test/run-pass/unboxed-closures-infer-upvar.rs index 087ef5dcf0..e29632b007 100644 --- a/src/test/run-pass/unboxed-closures-infer-upvar.rs +++ b/src/test/run-pass/unboxed-closures-infer-upvar.rs @@ -11,6 +11,8 @@ // Test that the type variable in the type(`Vec<_>`) of a closed over // variable does not interfere with type inference. +// pretty-expanded FIXME #23616 + fn f(mut f: F) { f(); } @@ -18,5 +20,5 @@ fn f(mut f: F) { fn main() { let mut v: Vec<_> = vec![]; f(|| v.push(0)); - assert_eq!(v, vec![0]); + assert_eq!(v, [0]); } diff --git a/src/test/run-pass/unboxed-closures-manual-impl.rs b/src/test/run-pass/unboxed-closures-manual-impl.rs index 37075de040..38f15d6e44 100644 --- a/src/test/run-pass/unboxed-closures-manual-impl.rs +++ b/src/test/run-pass/unboxed-closures-manual-impl.rs @@ -1,4 +1,3 @@ - // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -9,20 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures)] +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, core)] use std::ops::FnMut; struct S; impl FnMut<(i32,)> for S { - type Output = i32; - extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { x * x } } +impl FnOnce<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } +} + fn call_iti32>(mut f: F, x: i32) -> i32 { f(x) + 3 } @@ -37,4 +42,3 @@ fn main() { assert!(x == 4); assert!(y == 4); } - diff --git a/src/test/run-pass/unboxed-closures-monomorphization.rs b/src/test/run-pass/unboxed-closures-monomorphization.rs index 535c456236..f16f757c64 100644 --- a/src/test/run-pass/unboxed-closures-monomorphization.rs +++ b/src/test/run-pass/unboxed-closures-monomorphization.rs @@ -13,11 +13,12 @@ #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] fn main(){ fn bar<'a, T:Clone+'a> (t: T) -> BoxT + 'a> { - box move || t.clone() + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + Box::new(move || t.clone()) } let mut f = bar(42_u32); @@ -31,7 +32,7 @@ fn main(){ assert_eq!(f.call_mut(()), &x); #[derive(Clone, Copy, Debug, PartialEq)] - struct Foo(uint, &'static str); + struct Foo(usize, &'static str); let x = Foo(42, "forty-two"); let mut f = bar(x); diff --git a/src/test/run-pass/unboxed-closures-move-mutable.rs b/src/test/run-pass/unboxed-closures-move-mutable.rs index 069e93b86b..1aca3174e1 100644 --- a/src/test/run-pass/unboxed-closures-move-mutable.rs +++ b/src/test/run-pass/unboxed-closures-move-mutable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] #![deny(unused_mut)] @@ -16,7 +18,7 @@ // mutably so we do not get a spurious warning about it not needing to // be declared mutable (issue #18336 and #18769) -fn set(x: &mut uint) { *x = 42; } +fn set(x: &mut usize) { *x = 42; } fn main() { { diff --git a/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs b/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs index 9966364625..b69153b73a 100644 --- a/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs +++ b/src/test/run-pass/unboxed-closures-move-some-upvars-in-by-ref-closure.rs @@ -11,6 +11,8 @@ // Test that in a by-ref once closure we move some variables even as // we capture others by mutable reference. +// pretty-expanded FIXME #23616 + fn call(f: F) where F : FnOnce() { f(); } diff --git a/src/test/run-pass/unboxed-closures-prelude.rs b/src/test/run-pass/unboxed-closures-prelude.rs index c8f0d5fde4..313fb67637 100644 --- a/src/test/run-pass/unboxed-closures-prelude.rs +++ b/src/test/run-pass/unboxed-closures-prelude.rs @@ -10,21 +10,23 @@ // Tests that the reexports of `FnOnce` et al from the prelude work. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -#![feature(unboxed_closures)] +#![feature(unboxed_closures, core)] fn main() { - let task: Box int> = box |x| x; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let task: Box isize> = Box::new(|x| x); task.call((0, )); - let mut task: Box int> = box |x| x; + let mut task: Box isize> = Box::new(|x| x); task(0); call(|x| x, 22); } -fn call int>(f: F, x: int) -> int { +fn call isize>(f: F, x: isize) -> isize { f(x) } - diff --git a/src/test/run-pass/unboxed-closures-simple.rs b/src/test/run-pass/unboxed-closures-simple.rs index 9f29e75be7..1443d305bc 100644 --- a/src/test/run-pass/unboxed-closures-simple.rs +++ b/src/test/run-pass/unboxed-closures-simple.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::ops::FnMut; pub fn main() { - let mut f = |x: int, y: int| -> int { x + y }; + let mut f = |x: isize, y: isize| -> isize { x + y }; let z = f(1, 2); assert_eq!(z, 3); } diff --git a/src/test/run-pass/unboxed-closures-single-word-env.rs b/src/test/run-pass/unboxed-closures-single-word-env.rs index 9e543f925f..65a26d14e1 100644 --- a/src/test/run-pass/unboxed-closures-single-word-env.rs +++ b/src/test/run-pass/unboxed-closures-single-word-env.rs @@ -11,24 +11,25 @@ // Ensures that single-word environments work right in unboxed closures. // These take a different path in codegen. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] -fn a int>(f: F) -> int { +fn a isize>(f: F) -> isize { f(1, 2) } -fn b int>(mut f: F) -> int { +fn b isize>(mut f: F) -> isize { f(3, 4) } -fn c int>(f: F) -> int { +fn c isize>(f: F) -> isize { f(5, 6) } fn main() { let z = 10; - assert_eq!(a(move |x: int, y| x + y + z), 13); - assert_eq!(b(move |x: int, y| x + y + z), 17); - assert_eq!(c(move |x: int, y| x + y + z), 21); + assert_eq!(a(move |x: isize, y| x + y + z), 13); + assert_eq!(b(move |x: isize, y| x + y + z), 17); + assert_eq!(c(move |x: isize, y| x + y + z), 21); } - diff --git a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs index 7a6b68a5e0..e90a344361 100644 --- a/src/test/run-pass/unboxed-closures-static-call-fn-once.rs +++ b/src/test/run-pass/unboxed-closures-static-call-fn-once.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn main() { let onetime = |x| x; onetime(0); } - diff --git a/src/test/run-pass/unboxed-closures-sugar-object.rs b/src/test/run-pass/unboxed-closures-sugar-object.rs index fff841a2f0..77beeb13fb 100644 --- a/src/test/run-pass/unboxed-closures-sugar-object.rs +++ b/src/test/run-pass/unboxed-closures-sugar-object.rs @@ -10,6 +10,8 @@ // Test unboxed closure sugar used in object types. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] #![feature(unboxed_closures)] diff --git a/src/test/run-pass/unboxed-closures-unique-type-id.rs b/src/test/run-pass/unboxed-closures-unique-type-id.rs index 5c36832d9f..403b2ca9aa 100644 --- a/src/test/run-pass/unboxed-closures-unique-type-id.rs +++ b/src/test/run-pass/unboxed-closures-unique-type-id.rs @@ -12,13 +12,15 @@ // // error: internal compiler error: get_unique_type_id_of_type() - // unexpected type: closure, -// ty_closure(syntax::ast::DefId{krate: 0u32, node: 66u32}, -// ReScope(63u32)) +// ty_closure(syntax::ast::DefId{krate: 0, node: 66}, +// ReScope(63)) // // This is a regression test for issue #17021. // // compile-flags: -g +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] use std::ptr; @@ -28,8 +30,8 @@ pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T { } pub fn main() { - let mut a = 7_usize; + let mut a = 7; let b = &mut a; - replace_map(b, |x: uint| x * 2); - assert_eq!(*b, 14_usize); + replace_map(b, |x: usize| x * 2); + assert_eq!(*b, 14); } diff --git a/src/test/run-pass/unboxed-closures-zero-args.rs b/src/test/run-pass/unboxed-closures-zero-args.rs index 8e3d44df79..cb3a18a18c 100644 --- a/src/test/run-pass/unboxed-closures-zero-args.rs +++ b/src/test/run-pass/unboxed-closures-zero-args.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] fn main() { let mut zero = || {}; let () = zero(); } - diff --git a/src/test/run-pass/unfold-cross-crate.rs b/src/test/run-pass/unfold-cross-crate.rs index 2af3804726..fceccb499c 100644 --- a/src/test/run-pass/unfold-cross-crate.rs +++ b/src/test/run-pass/unfold-cross-crate.rs @@ -10,13 +10,17 @@ // no-pretty-expanded FIXME #15189 +// pretty-expanded FIXME #23616 + +#![feature(core)] + use std::iter::Unfold; // Unfold had a bug with 'a that mean it didn't work // cross-crate pub fn main() { - fn count(st: &mut uint) -> Option { + fn count(st: &mut usize) -> Option { if *st < 10 { let ret = Some(*st); *st += 1; diff --git a/src/test/run-pass/unify-return-ty.rs b/src/test/run-pass/unify-return-ty.rs index 1a65f685a5..01b55ebb8e 100644 --- a/src/test/run-pass/unify-return-ty.rs +++ b/src/test/run-pass/unify-return-ty.rs @@ -12,6 +12,8 @@ // unified with the type *T, and so the type variable // in that type gets resolved. +// pretty-expanded FIXME #23616 + use std::mem; fn null() -> *const T { @@ -20,4 +22,4 @@ fn null() -> *const T { } } -pub fn main() { null::(); } +pub fn main() { null::(); } diff --git a/src/test/run-pass/uninit-empty-types.rs b/src/test/run-pass/uninit-empty-types.rs index a0cf984cbb..8c69704b3b 100644 --- a/src/test/run-pass/uninit-empty-types.rs +++ b/src/test/run-pass/uninit-empty-types.rs @@ -10,6 +10,8 @@ // Test the uninit() construct returning various empty types. +// pretty-expanded FIXME #23616 + use std::mem; #[derive(Clone)] diff --git a/src/test/run-pass/uniq-self-in-mut-slot.rs b/src/test/run-pass/uniq-self-in-mut-slot.rs index b7980ed902..a6408128c3 100644 --- a/src/test/run-pass/uniq-self-in-mut-slot.rs +++ b/src/test/run-pass/uniq-self-in-mut-slot.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] struct X { - a: int + a: isize } trait Changer { @@ -27,7 +29,7 @@ impl Changer for X { } pub fn main() { - let x = box X { a: 32 }; + let x: Box<_> = box X { a: 32 }; let new_x = x.change(); assert_eq!(new_x.a, 55); } diff --git a/src/test/run-pass/unique-assign-copy.rs b/src/test/run-pass/unique-assign-copy.rs index c19063fe46..32a0713ca9 100644 --- a/src/test/run-pass/unique-assign-copy.rs +++ b/src/test/run-pass/unique-assign-copy.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut i = box 1; + let mut i: Box<_> = box 1; // Should be a copy let mut j; j = i.clone(); diff --git a/src/test/run-pass/unique-assign-drop.rs b/src/test/run-pass/unique-assign-drop.rs index 241258f089..715fa548a7 100644 --- a/src/test/run-pass/unique-assign-drop.rs +++ b/src/test/run-pass/unique-assign-drop.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_assignment)] #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 1; - let mut j = box 2; + let i: Box<_> = box 1; + let mut j: Box<_> = box 2; // Should drop the previous value of j j = i; assert_eq!(*j, 1); diff --git a/src/test/run-pass/unique-assign-generic.rs b/src/test/run-pass/unique-assign-generic.rs index c8abb08084..ca145479a3 100644 --- a/src/test/run-pass/unique-assign-generic.rs +++ b/src/test/run-pass/unique-assign-generic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -18,6 +20,6 @@ fn f(t: T) -> T { } pub fn main() { - let t = f(box 100); + let t = f::>(box 100); assert_eq!(t, box 100); } diff --git a/src/test/run-pass/unique-assign.rs b/src/test/run-pass/unique-assign.rs index cbcb6afb4c..e4e7b69671 100644 --- a/src/test/run-pass/unique-assign.rs +++ b/src/test/run-pass/unique-assign.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut i; + let mut i: Box<_>; i = box 1; assert_eq!(*i, 1); } diff --git a/src/test/run-pass/unique-autoderef-field.rs b/src/test/run-pass/unique-autoderef-field.rs index aab7f4108f..8ee1b28ea2 100644 --- a/src/test/run-pass/unique-autoderef-field.rs +++ b/src/test/run-pass/unique-autoderef-field.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct J { j: int } +struct J { j: isize } pub fn main() { - let i = box J { + let i: Box<_> = box J { j: 100 }; assert_eq!(i.j, 100); diff --git a/src/test/run-pass/unique-autoderef-index.rs b/src/test/run-pass/unique-autoderef-index.rs index 30c4b2d7b5..9dc98cf2e3 100644 --- a/src/test/run-pass/unique-autoderef-index.rs +++ b/src/test/run-pass/unique-autoderef-index.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box vec!(100); + let i: Box<_> = box vec!(100); assert_eq!((*i)[0], 100); } diff --git a/src/test/run-pass/unique-cmp.rs b/src/test/run-pass/unique-cmp.rs index a2962dc00d..be7e46c869 100644 --- a/src/test/run-pass/unique-cmp.rs +++ b/src/test/run-pass/unique-cmp.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 100; + let i: Box<_> = box 100; assert!(i == box 100); assert!(i < box 101); assert!(i <= box 100); diff --git a/src/test/run-pass/unique-containing-tag.rs b/src/test/run-pass/unique-containing-tag.rs index e4099c94c2..ce5a2bed48 100644 --- a/src/test/run-pass/unique-containing-tag.rs +++ b/src/test/run-pass/unique-containing-tag.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - enum t { t1(int), t2(int), } + enum t { t1(isize), t2(isize), } - let _x = box t::t1(10); + let _x: Box<_> = box t::t1(10); /*alt *x { t1(a) { diff --git a/src/test/run-pass/unique-create.rs b/src/test/run-pass/unique-create.rs index 975f1e9da8..8469ae7020 100644 --- a/src/test/run-pass/unique-create.rs +++ b/src/test/run-pass/unique-create.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - box 100; + let _: Box<_> = box 100; } fn vec() { diff --git a/src/test/run-pass/unique-decl-init-copy.rs b/src/test/run-pass/unique-decl-init-copy.rs index 3af38784ad..0840f1308c 100644 --- a/src/test/run-pass/unique-decl-init-copy.rs +++ b/src/test/run-pass/unique-decl-init-copy.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut i = box 1; + let mut i: Box<_> = box 1; // Should be a copy let mut j = i.clone(); *i = 2; diff --git a/src/test/run-pass/unique-decl-init.rs b/src/test/run-pass/unique-decl-init.rs index c919274880..1d5a44f45a 100644 --- a/src/test/run-pass/unique-decl-init.rs +++ b/src/test/run-pass/unique-decl-init.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 1; + let i: Box<_> = box 1; let j = i; assert_eq!(*j, 1); } diff --git a/src/test/run-pass/unique-decl-move.rs b/src/test/run-pass/unique-decl-move.rs index 96dd9f51fb..203a30e76b 100644 --- a/src/test/run-pass/unique-decl-move.rs +++ b/src/test/run-pass/unique-decl-move.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 100; + let i: Box<_> = box 100; let j = i; assert_eq!(*j, 100); } diff --git a/src/test/run-pass/unique-decl.rs b/src/test/run-pass/unique-decl.rs index a902fef288..7404e8887e 100644 --- a/src/test/run-pass/unique-decl.rs +++ b/src/test/run-pass/unique-decl.rs @@ -9,10 +9,12 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let _: Box; + let _: Box; } -fn f(_i: Box) -> Box { +fn f(_i: Box) -> Box { panic!(); } diff --git a/src/test/run-pass/unique-deref.rs b/src/test/run-pass/unique-deref.rs index 41d3b87a00..44681742a7 100644 --- a/src/test/run-pass/unique-deref.rs +++ b/src/test/run-pass/unique-deref.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 100; + let i: Box<_> = box 100; assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-destructure.rs b/src/test/run-pass/unique-destructure.rs index 9e71e850b3..87bc6f6639 100644 --- a/src/test/run-pass/unique-destructure.rs +++ b/src/test/run-pass/unique-destructure.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] -struct Foo { a: int, b: int } +struct Foo { a: isize, b: isize } pub fn main() { let box Foo{a, b} = box Foo{a: 100, b: 200}; diff --git a/src/test/run-pass/unique-drop-complex.rs b/src/test/run-pass/unique-drop-complex.rs index c5a0a4df27..056acd1620 100644 --- a/src/test/run-pass/unique-drop-complex.rs +++ b/src/test/run-pass/unique-drop-complex.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let _x = box vec!(0,0,0,0,0); + let _x: Box<_> = box vec!(0,0,0,0,0); } diff --git a/src/test/run-pass/unique-fn-arg-move.rs b/src/test/run-pass/unique-fn-arg-move.rs index 1b3f7e72a4..e608ab9b63 100644 --- a/src/test/run-pass/unique-fn-arg-move.rs +++ b/src/test/run-pass/unique-fn-arg-move.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn f(i: Box) { +fn f(i: Box) { assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-fn-arg-mut.rs b/src/test/run-pass/unique-fn-arg-mut.rs index e1d148cc9a..f0d2abfe27 100644 --- a/src/test/run-pass/unique-fn-arg-mut.rs +++ b/src/test/run-pass/unique-fn-arg-mut.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn f(i: &mut Box) { +fn f(i: &mut Box) { *i = box 200; } diff --git a/src/test/run-pass/unique-fn-arg.rs b/src/test/run-pass/unique-fn-arg.rs index 301994a74a..3d7ef31d02 100644 --- a/src/test/run-pass/unique-fn-arg.rs +++ b/src/test/run-pass/unique-fn-arg.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn f(i: Box) { +fn f(i: Box) { assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-fn-ret.rs b/src/test/run-pass/unique-fn-ret.rs index de2c265089..bb1948bf3c 100644 --- a/src/test/run-pass/unique-fn-ret.rs +++ b/src/test/run-pass/unique-fn-ret.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -fn f() -> Box { +fn f() -> Box { box 100 } diff --git a/src/test/run-pass/unique-generic-assign.rs b/src/test/run-pass/unique-generic-assign.rs index 58470637a1..2da3b9f05f 100644 --- a/src/test/run-pass/unique-generic-assign.rs +++ b/src/test/run-pass/unique-generic-assign.rs @@ -11,6 +11,8 @@ // Issue #976 +// pretty-expanded FIXME #23616 + fn f(x: Box) { let _x2 = x; } diff --git a/src/test/run-pass/unique-in-tag.rs b/src/test/run-pass/unique-in-tag.rs index 4f02018346..0762b37ff8 100644 --- a/src/test/run-pass/unique-in-tag.rs +++ b/src/test/run-pass/unique-in-tag.rs @@ -12,7 +12,7 @@ #![feature(box_syntax)] fn test1() { - enum bar { u(Box), w(int), } + enum bar { u(Box), w(isize), } let x = bar::u(box 10); assert!(match x { diff --git a/src/test/run-pass/unique-in-vec-copy.rs b/src/test/run-pass/unique-in-vec-copy.rs index 3bde79fdce..129c0784cc 100644 --- a/src/test/run-pass/unique-in-vec-copy.rs +++ b/src/test/run-pass/unique-in-vec-copy.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut a = vec!(box 10); + let mut a: Vec> = vec!(box 10); let b = a.clone(); assert_eq!(*a[0], 10); diff --git a/src/test/run-pass/unique-in-vec.rs b/src/test/run-pass/unique-in-vec.rs index 05b0c7244d..dc94fa6ca4 100644 --- a/src/test/run-pass/unique-in-vec.rs +++ b/src/test/run-pass/unique-in-vec.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let vect = vec!(box 100); + let vect : Vec> = vec!(box 100); assert!(vect[0] == box 100); } diff --git a/src/test/run-pass/unique-init.rs b/src/test/run-pass/unique-init.rs index d3f13f1609..bd7a649526 100644 --- a/src/test/run-pass/unique-init.rs +++ b/src/test/run-pass/unique-init.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let _i = box 100; + let _i: Box<_> = box 100; } diff --git a/src/test/run-pass/unique-kinds.rs b/src/test/run-pass/unique-kinds.rs index 4c93c379b4..96d54193ac 100644 --- a/src/test/run-pass/unique-kinds.rs +++ b/src/test/run-pass/unique-kinds.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] @@ -23,11 +25,11 @@ fn sendable() { assert!(i != j); } - let i = box 100; - let j = box 100; + let i: Box<_> = box 100; + let j: Box<_> = box 100; f(i, j); - let i = box 100; - let j = box 101; + let i: Box<_> = box 100; + let j: Box<_> = box 101; g(i, j); } @@ -41,11 +43,11 @@ fn copyable() { assert!(i != j); } - let i = box 100; - let j = box 100; + let i: Box<_> = box 100; + let j: Box<_> = box 100; f(i, j); - let i = box 100; - let j = box 101; + let i: Box<_> = box 100; + let j: Box<_> = box 101; g(i, j); } @@ -59,11 +61,11 @@ fn noncopyable() { assert!(i != j); } - let i = box 100; - let j = box 100; + let i: Box<_> = box 100; + let j: Box<_> = box 100; f(i, j); - let i = box 100; - let j = box 101; + let i: Box<_> = box 100; + let j: Box<_> = box 101; g(i, j); } diff --git a/src/test/run-pass/unique-log.rs b/src/test/run-pass/unique-log.rs index 4b21b949f8..148ca4757a 100644 --- a/src/test/run-pass/unique-log.rs +++ b/src/test/run-pass/unique-log.rs @@ -12,6 +12,6 @@ #![feature(box_syntax)] pub fn main() { - let i = box 100; + let i: Box<_> = box 100; println!("{}", i); } diff --git a/src/test/run-pass/unique-match-discrim.rs b/src/test/run-pass/unique-match-discrim.rs index a1502c2eb8..1b0392341e 100644 --- a/src/test/run-pass/unique-match-discrim.rs +++ b/src/test/run-pass/unique-match-discrim.rs @@ -10,11 +10,10 @@ // Issue #961 -#![allow(unknown_features)] -#![feature(box_syntax)] +// pretty-expanded FIXME #23616 fn altsimple() { - match box true { + match Box::new(true) { _ => { } } } diff --git a/src/test/run-pass/unique-move-drop.rs b/src/test/run-pass/unique-move-drop.rs index 705b9d6e92..e81095d548 100644 --- a/src/test/run-pass/unique-move-drop.rs +++ b/src/test/run-pass/unique-move-drop.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_variable)] #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 100; - let j = box 200; + let i: Box<_> = box 100; + let j: Box<_> = box 200; let j = i; assert_eq!(*j, 100); } diff --git a/src/test/run-pass/unique-move-temp.rs b/src/test/run-pass/unique-move-temp.rs index b6c24f5be2..634a1569ac 100644 --- a/src/test/run-pass/unique-move-temp.rs +++ b/src/test/run-pass/unique-move-temp.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut i; + let mut i: Box<_>; i = box 100; assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-move.rs b/src/test/run-pass/unique-move.rs index ed13bf6a5c..29bf113926 100644 --- a/src/test/run-pass/unique-move.rs +++ b/src/test/run-pass/unique-move.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let i = box 100; + let i: Box<_> = box 100; let mut j; j = i; assert_eq!(*j, 100); diff --git a/src/test/run-pass/unique-mutable.rs b/src/test/run-pass/unique-mutable.rs index 403b8bf18b..106481e318 100644 --- a/src/test/run-pass/unique-mutable.rs +++ b/src/test/run-pass/unique-mutable.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let mut i = box 0; + let mut i: Box<_> = box 0; *i = 1; assert_eq!(*i, 1); } diff --git a/src/test/run-pass/unique-object-move.rs b/src/test/run-pass/unique-object-move.rs index f01a56142e..4d120e7caf 100644 --- a/src/test/run-pass/unique-object-move.rs +++ b/src/test/run-pass/unique-object-move.rs @@ -10,13 +10,15 @@ // Issue #5192 +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub trait EventLoop { fn foo(&self) {} } pub struct UvEventLoop { - uvio: int + uvio: isize } impl EventLoop for UvEventLoop { } diff --git a/src/test/run-pass/unique-pat-2.rs b/src/test/run-pass/unique-pat-2.rs index 5db96bc356..d16355af99 100644 --- a/src/test/run-pass/unique-pat-2.rs +++ b/src/test/run-pass/unique-pat-2.rs @@ -8,17 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] -struct Foo {a: int, b: uint} +struct Foo {a: isize, b: usize} -enum bar { u(Box), w(int), } +enum bar { u(Box), w(isize), } pub fn main() { - assert!(match bar::u(box Foo{a: 10, b: 40_usize}) { - bar::u(box Foo{a: a, b: b}) => { a + (b as int) } + assert!(match bar::u(box Foo{a: 10, b: 40}) { + bar::u(box Foo{a: a, b: b}) => { a + (b as isize) } _ => { 66 } } == 50); } diff --git a/src/test/run-pass/unique-pat-3.rs b/src/test/run-pass/unique-pat-3.rs index 42a4b1a9c0..648e9599a9 100644 --- a/src/test/run-pass/unique-pat-3.rs +++ b/src/test/run-pass/unique-pat-3.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -enum bar { u(Box), w(int), } +enum bar { u(Box), w(isize), } pub fn main() { assert!(match bar::u(box 10) { diff --git a/src/test/run-pass/unique-pat.rs b/src/test/run-pass/unique-pat.rs index bff2d4e917..ae76179b5e 100644 --- a/src/test/run-pass/unique-pat.rs +++ b/src/test/run-pass/unique-pat.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/test/run-pass/unique-rec.rs b/src/test/run-pass/unique-rec.rs index 756911d29f..7a09e241ca 100644 --- a/src/test/run-pass/unique-rec.rs +++ b/src/test/run-pass/unique-rec.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -struct X { x: int } +struct X { x: isize } pub fn main() { - let x = box X {x: 1}; + let x: Box<_> = box X {x: 1}; let bar = x; assert_eq!(bar.x, 1); } diff --git a/src/test/run-pass/unique-send-2.rs b/src/test/run-pass/unique-send-2.rs index 43824812ec..99a3b64105 100644 --- a/src/test/run-pass/unique-send-2.rs +++ b/src/test/run-pass/unique-send-2.rs @@ -8,30 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] use std::sync::mpsc::{channel, Sender}; use std::thread; -fn child(tx: &Sender>, i: uint) { +fn child(tx: &Sender>, i: usize) { tx.send(box i).unwrap(); } pub fn main() { let (tx, rx) = channel(); - let n = 100_usize; - let mut expected = 0_usize; - let _t = (0_usize..n).map(|i| { + let n = 100; + let mut expected = 0; + let _t = (0..n).map(|i| { expected += i; let tx = tx.clone(); - thread::spawn(move|| { + thread::scoped(move|| { child(&tx, i) }) }).collect::>(); - let mut actual = 0_usize; - for _ in 0_usize..n { + let mut actual = 0; + for _ in 0..n { let j = rx.recv().unwrap(); actual += *j; } diff --git a/src/test/run-pass/unique-send.rs b/src/test/run-pass/unique-send.rs index 2a462e9cdd..c9649ef60d 100644 --- a/src/test/run-pass/unique-send.rs +++ b/src/test/run-pass/unique-send.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] use std::sync::mpsc::channel; pub fn main() { - let (tx, rx) = channel(); + let (tx, rx) = channel::>(); tx.send(box 100).unwrap(); let v = rx.recv().unwrap(); assert_eq!(v, box 100); diff --git a/src/test/run-pass/unique-swap.rs b/src/test/run-pass/unique-swap.rs index 2adb9c22f6..454011a9ec 100644 --- a/src/test/run-pass/unique-swap.rs +++ b/src/test/run-pass/unique-swap.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] use std::mem::swap; pub fn main() { - let mut i = box 100; - let mut j = box 200; + let mut i: Box<_> = box 100; + let mut j: Box<_> = box 200; swap(&mut i, &mut j); assert_eq!(i, box 200); assert_eq!(j, box 100); diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs index ac46187f03..c2db63ed25 100644 --- a/src/test/run-pass/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -10,7 +10,10 @@ // Make sure the destructor is run for unit-like structs. -use std::boxed::BoxAny; +// pretty-expanded FIXME #23616 + +#![feature(alloc)] + use std::thread; struct Foo; @@ -26,6 +29,6 @@ pub fn main() { let _b = Foo; }).join(); - let s = x.err().unwrap().downcast::<&'static str>().ok().unwrap(); + let s = x.err().unwrap().downcast::<&'static str>().unwrap(); assert_eq!(&**s, "This panic should happen."); } diff --git a/src/test/run-pass/unit.rs b/src/test/run-pass/unit.rs index 3b52dcce4b..2679c4c033 100644 --- a/src/test/run-pass/unit.rs +++ b/src/test/run-pass/unit.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_variable)] #![allow(dead_assignment)] diff --git a/src/test/run-pass/unnamed_argument_mode.rs b/src/test/run-pass/unnamed_argument_mode.rs index d22a6652e1..d498a70be4 100644 --- a/src/test/run-pass/unnamed_argument_mode.rs +++ b/src/test/run-pass/unnamed_argument_mode.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn good(_a: &int) { +// pretty-expanded FIXME #23616 + +fn good(_a: &isize) { } -// unnamed argument &int is now parse x: &int +// unnamed argument &isize is now parse x: &isize -fn called(_f: F) where F: FnOnce(&int) { +fn called(_f: F) where F: FnOnce(&isize) { } pub fn main() { diff --git a/src/test/run-pass/unreachable-code-1.rs b/src/test/run-pass/unreachable-code-1.rs index d8a8913e58..612beabb03 100644 --- a/src/test/run-pass/unreachable-code-1.rs +++ b/src/test/run-pass/unreachable-code-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unreachable_code)] #![allow(unused_variable)] diff --git a/src/test/run-pass/unreachable-code.rs b/src/test/run-pass/unreachable-code.rs index a28dc2c1f1..4f58df6625 100644 --- a/src/test/run-pass/unreachable-code.rs +++ b/src/test/run-pass/unreachable-code.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(path_statement)] #![allow(unreachable_code)] #![allow(unused_variable)] diff --git a/src/test/run-pass/unsafe-coercion.rs b/src/test/run-pass/unsafe-coercion.rs new file mode 100644 index 0000000000..d0c633e827 --- /dev/null +++ b/src/test/run-pass/unsafe-coercion.rs @@ -0,0 +1,27 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that safe fns are not a subtype of unsafe fns. + +// pretty-expanded FIXME #23616 + +fn foo(x: i32) -> i32 { + x * 22 +} + +fn bar(x: fn(i32) -> i32) -> unsafe fn(i32) -> i32 { + x // OK, coercion! +} + +fn main() { + let f = bar(foo); + let x = unsafe { f(2) }; + assert_eq!(x, 44); +} diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs index 4ce3f2c53b..f3a2ad749a 100644 --- a/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-blk.rs @@ -11,6 +11,8 @@ // // See also: compile-fail/unsafe-fn-called-from-safe.rs +// pretty-expanded FIXME #23616 + unsafe fn f() { return; } fn g() { diff --git a/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs index e68b868a24..37c72ba8ab 100644 --- a/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs +++ b/src/test/run-pass/unsafe-fn-called-from-unsafe-fn.rs @@ -11,6 +11,8 @@ // // See also: compile-fail/unsafe-fn-called-from-safe.rs +// pretty-expanded FIXME #23616 + unsafe fn f() { return; } unsafe fn g() { diff --git a/src/test/run-pass/unsafe-pointer-assignability.rs b/src/test/run-pass/unsafe-pointer-assignability.rs index 7a624109a5..75c7cabfcb 100644 --- a/src/test/run-pass/unsafe-pointer-assignability.rs +++ b/src/test/run-pass/unsafe-pointer-assignability.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(x: *const int) { +// pretty-expanded FIXME #23616 + +fn f(x: *const isize) { unsafe { assert_eq!(*x, 3); } diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index ae175d27b0..8ff8169ef4 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -7,11 +7,11 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// -// ignore-lexer-test FIXME #15879 // Test syntax checks for `?Sized` syntax. +// pretty-expanded FIXME #23616 + use std::marker::{PhantomData, PhantomFn}; trait T1 : PhantomFn { } diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs index 10b2f2fb70..965ce6bad1 100644 --- a/src/test/run-pass/unsized2.rs +++ b/src/test/run-pass/unsized2.rs @@ -7,8 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// -// ignore-lexer-test FIXME #15879 + +// pretty-expanded FIXME #23616 #![allow(unknown_features)] #![feature(box_syntax)] @@ -96,14 +96,14 @@ struct S2 { f: X, } struct S3 { - f1: int, + f1: isize, f2: X, } enum E { V1(X), V2{x: X}, - V3(int, X), - V4{u: int, x: X}, + V3(isize, X), + V4{u: isize, x: X}, } pub fn main() { diff --git a/src/test/run-pass/unsized3.rs b/src/test/run-pass/unsized3.rs index 983152cd05..8db294bdcc 100644 --- a/src/test/run-pass/unsized3.rs +++ b/src/test/run-pass/unsized3.rs @@ -10,36 +10,39 @@ // Test structs with always-unsized fields. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] -#![feature(box_syntax)] +#![feature(box_syntax, core)] use std::mem; use std::raw; +use std::slice; struct Foo { f: [T], } struct Bar { - f1: uint, - f2: [uint], + f1: usize, + f2: [usize], } struct Baz { - f1: uint, + f1: usize, f2: str, } trait Tr { - fn foo(&self) -> uint; + fn foo(&self) -> usize; } struct St { - f: uint + f: usize } impl Tr for St { - fn foo(&self) -> uint { + fn foo(&self) -> usize { self.f } } @@ -66,20 +69,19 @@ pub fn main() { f: [T; 3] } - let data = box Foo_{f: [1i32, 2, 3] }; - let x: &Foo = mem::transmute(raw::Slice { len: 3, data: &*data }); + let data: Box> = box Foo_{f: [1, 2, 3] }; + let x: &Foo = mem::transmute(slice::from_raw_parts(&*data, 3)); assert!(x.f.len() == 3); assert!(x.f[0] == 1); - assert!(x.f[1] == 2); - assert!(x.f[2] == 3); struct Baz_ { - f1: uint, + f1: usize, f2: [u8; 5], } - let data = box Baz_{ f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; - let x: &Baz = mem::transmute( raw::Slice { len: 5, data: &*data } ); + let data: Box<_> = box Baz_ { + f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; + let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5)); assert!(x.f1 == 42); let chs: Vec = x.f2.chars().collect(); assert!(chs.len() == 5); @@ -96,7 +98,7 @@ pub fn main() { let obj: Box = box St { f: 42 }; let obj: &Tr = &*obj; let obj: raw::TraitObject = mem::transmute(&*obj); - let data = box Qux_{ f: St { f: 234 } }; + let data: Box<_> = box Qux_{ f: St { f: 234 } }; let x: &Qux = mem::transmute(raw::TraitObject { vtable: obj.vtable, data: mem::transmute(&*data) }); assert!(x.f.foo() == 234); diff --git a/src/test/run-pass/unused-move-capture.rs b/src/test/run-pass/unused-move-capture.rs index 4e8fdda956..b155620e51 100644 --- a/src/test/run-pass/unused-move-capture.rs +++ b/src/test/run-pass/unused-move-capture.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let _x = box 1; + let _x: Box<_> = box 1; let lam_move = || {}; lam_move(); } diff --git a/src/test/run-pass/unused-move.rs b/src/test/run-pass/unused-move.rs index d053b03a2c..015b6f8094 100644 --- a/src/test/run-pass/unused-move.rs +++ b/src/test/run-pass/unused-move.rs @@ -12,12 +12,14 @@ // Issue Name: Unused move causes a crash // Abstract: zero-fill to block after drop +// pretty-expanded FIXME #23616 + #![allow(path_statement)] #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { - let y = box 1; + let y: Box<_> = box 1; y; } diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs index 52c09aadfb..449e500edb 100644 --- a/src/test/run-pass/unwind-resource.rs +++ b/src/test/run-pass/unwind-resource.rs @@ -37,7 +37,8 @@ fn f(tx: Sender) { pub fn main() { let (tx, rx) = channel(); - let _t = thread::spawn(move|| f(tx.clone())); + let t = thread::spawn(move|| f(tx.clone())); println!("hiiiiiiiii"); assert!(rx.recv().unwrap()); + drop(t.join()); } diff --git a/src/test/run-pass/unwind-unique.rs b/src/test/run-pass/unwind-unique.rs index d38b6e79eb..1d6ce626c2 100644 --- a/src/test/run-pass/unwind-unique.rs +++ b/src/test/run-pass/unwind-unique.rs @@ -8,16 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] use std::thread; fn f() { - let _a = box 0; + let _a: Box<_> = box 0; panic!(); } pub fn main() { - let _t = thread::spawn(f); + let t = thread::spawn(f); + drop(t.join()); } diff --git a/src/test/run-pass/use-crate-name-alias.rs b/src/test/run-pass/use-crate-name-alias.rs index 4751b4666f..98594183a0 100644 --- a/src/test/run-pass/use-crate-name-alias.rs +++ b/src/test/run-pass/use-crate-name-alias.rs @@ -9,6 +9,8 @@ // except according to those terms. // Issue #1706 -extern crate "std" as stdlib; +// pretty-expanded FIXME #23616 + +extern crate std as stdlib; pub fn main() {} diff --git a/src/test/run-pass/use-import-export.rs b/src/test/run-pass/use-import-export.rs index ec8033ff3b..044472606a 100644 --- a/src/test/run-pass/use-import-export.rs +++ b/src/test/run-pass/use-import-export.rs @@ -10,12 +10,14 @@ +// pretty-expanded FIXME #23616 + mod foo { - pub fn x() -> int { return 1; } + pub fn x() -> isize { return 1; } } mod bar { - pub fn y() -> int { return 1; } + pub fn y() -> isize { return 1; } } pub fn main() { foo::x(); bar::y(); } diff --git a/src/test/run-pass/use-mod.rs b/src/test/run-pass/use-mod.rs index cca9c8f2df..49ad171eaa 100644 --- a/src/test/run-pass/use-mod.rs +++ b/src/test/run-pass/use-mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub use foo::bar::{self, First}; use self::bar::Second; diff --git a/src/test/run-pass/use-trait-before-def.rs b/src/test/run-pass/use-trait-before-def.rs index 0b59ced98c..38952334e4 100644 --- a/src/test/run-pass/use-trait-before-def.rs +++ b/src/test/run-pass/use-trait-before-def.rs @@ -10,6 +10,8 @@ // Issue #1761 -impl foo for int { fn foo(&self) -> int { 10 } } -trait foo { fn foo(&self) -> int; } +// pretty-expanded FIXME #23616 + +impl foo for isize { fn foo(&self) -> isize { 10 } } +trait foo { fn foo(&self) -> isize; } pub fn main() {} diff --git a/src/test/run-pass/use-uninit-match.rs b/src/test/run-pass/use-uninit-match.rs index efa6a2c583..9e606384f3 100644 --- a/src/test/run-pass/use-uninit-match.rs +++ b/src/test/run-pass/use-uninit-match.rs @@ -10,8 +10,8 @@ -fn foo(o: myoption) -> int { - let mut x: int = 5; +fn foo(o: myoption) -> isize { + let mut x: isize = 5; match o { myoption::none:: => { } myoption::some::(_t) => { x += 1; } diff --git a/src/test/run-pass/use-uninit-match2.rs b/src/test/run-pass/use-uninit-match2.rs index f2b487b703..dc0a6a26bc 100644 --- a/src/test/run-pass/use-uninit-match2.rs +++ b/src/test/run-pass/use-uninit-match2.rs @@ -10,8 +10,8 @@ -fn foo(o: myoption) -> int { - let mut x: int; +fn foo(o: myoption) -> isize { + let mut x: isize; match o { myoption::none:: => { panic!(); } myoption::some::(_t) => { x = 5; } diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 65a392e63c..40ab4c86c6 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -1,4 +1,3 @@ - // 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. @@ -9,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unused_imports)] #![feature(start, no_std)] #![no_std] extern crate std; -extern crate "std" as zed; +extern crate std as zed; use std::str; use zed::str as x; @@ -23,4 +24,4 @@ mod baz { } #[start] -pub fn start(_: int, _: *const *const u8) -> int { 0 } +pub fn start(_: isize, _: *const *const u8) -> isize { 0 } diff --git a/src/test/run-pass/use_inline_dtor.rs b/src/test/run-pass/use_inline_dtor.rs index 18cb478be3..0f55a357a0 100644 --- a/src/test/run-pass/use_inline_dtor.rs +++ b/src/test/run-pass/use_inline_dtor.rs @@ -10,6 +10,8 @@ // aux-build:inline_dtor.rs +// pretty-expanded FIXME #23616 + extern crate inline_dtor; pub fn main() { diff --git a/src/test/run-pass/utf8.rs b/src/test/run-pass/utf8.rs index 96bba01068..07fd7b297b 100644 --- a/src/test/run-pass/utf8.rs +++ b/src/test/run-pass/utf8.rs @@ -18,14 +18,14 @@ pub fn main() { let y_diaeresis: char = 'ÿ'; // 0xff let pi: char = 'Π'; // 0x3a0 - assert_eq!(yen as int, 0xa5); - assert_eq!(c_cedilla as int, 0xe7); - assert_eq!(thorn as int, 0xfe); - assert_eq!(y_diaeresis as int, 0xff); - assert_eq!(pi as int, 0x3a0); + assert_eq!(yen as isize, 0xa5); + assert_eq!(c_cedilla as isize, 0xe7); + assert_eq!(thorn as isize, 0xfe); + assert_eq!(y_diaeresis as isize, 0xff); + assert_eq!(pi as isize, 0x3a0); - assert_eq!(pi as int, '\u03a0' as int); - assert_eq!('\x0a' as int, '\n' as int); + assert_eq!(pi as isize, '\u{3a0}' as isize); + assert_eq!('\x0a' as isize, '\n' as isize); let bhutan: String = "འབྲུག་ཡུལ།".to_string(); let japan: String = "日本".to_string(); @@ -33,21 +33,21 @@ pub fn main() { let austria: String = "Österreich".to_string(); let bhutan_e: String = - "\u0f60\u0f56\u0fb2\u0f74\u0f42\u0f0b\u0f61\u0f74\u0f63\u0f0d".to_string(); - let japan_e: String = "\u65e5\u672c".to_string(); + "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string(); + let japan_e: String = "\u{65e5}\u{672c}".to_string(); let uzbekistan_e: String = - "\u040e\u0437\u0431\u0435\u043a\u0438\u0441\u0442\u043e\u043d".to_string(); - let austria_e: String = "\u00d6sterreich".to_string(); + "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string(); + let austria_e: String = "\u{d6}sterreich".to_string(); let oo: char = 'Ö'; - assert_eq!(oo as int, 0xd6); + assert_eq!(oo as isize, 0xd6); fn check_str_eq(a: String, b: String) { - let mut i: int = 0; + let mut i: isize = 0; for ab in a.bytes() { println!("{}", i); println!("{}", ab); - let bb: u8 = b.as_bytes()[i as uint]; + let bb: u8 = b.as_bytes()[i as usize]; println!("{}", bb); assert_eq!(ab, bb); i += 1; diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 84f605eef5..45a3f2327a 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -10,34 +10,36 @@ // // ignore-lexer-test FIXME #15679 +#![feature(collections, core, str_char)] + use std::str; pub fn main() { // Chars of 1, 2, 3, and 4 bytes - let chs: Vec = vec!('e', 'é', '€', '\U00010000'); + let chs: Vec = vec!('e', 'é', '€', '\u{10000}'); let s: String = chs.iter().cloned().collect(); let schs: Vec = s.chars().collect(); - assert!(s.len() == 10_usize); - assert!(s.chars().count() == 4_usize); - assert!(schs.len() == 4_usize); + assert!(s.len() == 10); + assert!(s.chars().count() == 4); + assert!(schs.len() == 4); assert!(schs.iter().cloned().collect::() == s); - assert!(s.char_at(0_usize) == 'e'); - assert!(s.char_at(1_usize) == 'é'); + assert!(s.char_at(0) == 'e'); + assert!(s.char_at(1) == 'é'); assert!((str::from_utf8(s.as_bytes()).is_ok())); // invalid prefix - assert!((!str::from_utf8(&[0x80_u8]).is_ok())); + assert!((!str::from_utf8(&[0x80]).is_ok())); // invalid 2 byte prefix - assert!((!str::from_utf8(&[0xc0_u8]).is_ok())); - assert!((!str::from_utf8(&[0xc0_u8, 0x10_u8]).is_ok())); + assert!((!str::from_utf8(&[0xc0]).is_ok())); + assert!((!str::from_utf8(&[0xc0, 0x10]).is_ok())); // invalid 3 byte prefix - assert!((!str::from_utf8(&[0xe0_u8]).is_ok())); - assert!((!str::from_utf8(&[0xe0_u8, 0x10_u8]).is_ok())); - assert!((!str::from_utf8(&[0xe0_u8, 0xff_u8, 0x10_u8]).is_ok())); + assert!((!str::from_utf8(&[0xe0]).is_ok())); + assert!((!str::from_utf8(&[0xe0, 0x10]).is_ok())); + assert!((!str::from_utf8(&[0xe0, 0xff, 0x10]).is_ok())); // invalid 4 byte prefix - assert!((!str::from_utf8(&[0xf0_u8]).is_ok())); - assert!((!str::from_utf8(&[0xf0_u8, 0x10_u8]).is_ok())); - assert!((!str::from_utf8(&[0xf0_u8, 0xff_u8, 0x10_u8]).is_ok())); - assert!((!str::from_utf8(&[0xf0_u8, 0xff_u8, 0xff_u8, 0x10_u8]).is_ok())); + assert!((!str::from_utf8(&[0xf0]).is_ok())); + assert!((!str::from_utf8(&[0xf0, 0x10]).is_ok())); + assert!((!str::from_utf8(&[0xf0, 0xff, 0x10]).is_ok())); + assert!((!str::from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok())); } diff --git a/src/test/run-pass/utf8_idents.rs b/src/test/run-pass/utf8_idents.rs index beb2f4d996..b11b7e83eb 100644 --- a/src/test/run-pass/utf8_idents.rs +++ b/src/test/run-pass/utf8_idents.rs @@ -22,7 +22,7 @@ pub fn main() { assert_eq!(საჭმელად_გემრიელი_სადილი(), 0); } -fn საჭმელად_გემრიელი_სადილი() -> int { +fn საჭმელად_გემრიელი_სადილი() -> isize { // Lunch in several languages. diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index 5a476ed9ee..d81dc3afcd 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc, std_misc)] + extern crate libc; -use std::ffi::{self, CString}; +use std::ffi::{CStr, CString}; use libc::{c_char, c_int}; -// ignore-fast doesn't like extern crate extern { fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; @@ -22,18 +25,18 @@ extern { unsafe fn check(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); - assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr())); + assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes()); } pub fn main() { unsafe { // Call with just the named parameter - let c = CString::new(b"Hello World\n").unwrap(); + let c = CString::new(&b"Hello World\n"[..]).unwrap(); check("Hello World\n", |s| sprintf(s, c.as_ptr())); // Call with variable number of arguments - let c = CString::new(b"%d %f %c %s\n").unwrap(); + let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap(); check("42 42.500000 a %d %f %c %s\n\n", |s| { sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); }); @@ -44,11 +47,11 @@ pub fn main() { // A function that takes a function pointer unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) { // Call with just the named parameter - let c = CString::new(b"Hello World\n").unwrap(); + let c = CString::new(&b"Hello World\n"[..]).unwrap(); check("Hello World\n", |s| sprintf(s, c.as_ptr())); // Call with variable number of arguments - let c = CString::new(b"%d %f %c %s\n").unwrap(); + let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap(); check("42 42.500000 a %d %f %c %s\n\n", |s| { sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); }); diff --git a/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs b/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs index 948d68e0cc..e21ea025d8 100644 --- a/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs +++ b/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs @@ -13,7 +13,10 @@ // us from approximating the lifetimes of `field1` and `field2` to a // common intersection. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] +#![feature(core)] struct List<'l> { field1: &'l i32, diff --git a/src/test/run-pass/variance-trait-matching.rs b/src/test/run-pass/variance-trait-matching.rs index 10441bee3c..5a179bfc7d 100644 --- a/src/test/run-pass/variance-trait-matching.rs +++ b/src/test/run-pass/variance-trait-matching.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] // Get is covariant in T @@ -45,5 +47,3 @@ fn main() { let y = get(&x); assert_eq!(y, 23); } - - diff --git a/src/test/run-pass/variance-vec-covariant.rs b/src/test/run-pass/variance-vec-covariant.rs index caec6df5a4..2f554c3c4f 100644 --- a/src/test/run-pass/variance-vec-covariant.rs +++ b/src/test/run-pass/variance-vec-covariant.rs @@ -10,7 +10,10 @@ // Test that vec is now covariant in its argument type. +// pretty-expanded FIXME #23616 + #![allow(dead_code)] +#![feature(core)] fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 { bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b diff --git a/src/test/run-pass/variant-attributes.rs b/src/test/run-pass/variant-attributes.rs index 16dca2db39..18987d1e01 100644 --- a/src/test/run-pass/variant-attributes.rs +++ b/src/test/run-pass/variant-attributes.rs @@ -9,6 +9,8 @@ // except according to those terms. // pp-exact - Make sure we actually print the attributes +// pretty-expanded FIXME #23616 + #![feature(custom_attribute)] enum crew_of_enterprise_d { diff --git a/src/test/run-pass/variant-structs-trivial.rs b/src/test/run-pass/variant-structs-trivial.rs index e078fa1485..6961cd4977 100644 --- a/src/test/run-pass/variant-structs-trivial.rs +++ b/src/test/run-pass/variant-structs-trivial.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + enum Foo { - Bar { x: int }, - Baz { y: int } + Bar { x: isize }, + Baz { y: isize } } pub fn main() { } diff --git a/src/test/run-pass/vec-concat.rs b/src/test/run-pass/vec-concat.rs index 64c4c17386..658c35ae8d 100644 --- a/src/test/run-pass/vec-concat.rs +++ b/src/test/run-pass/vec-concat.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(collections)] + use std::vec; pub fn main() { - let a: Vec = vec!(1, 2, 3, 4, 5); - let b: Vec = vec!(6, 7, 8, 9, 0); - let mut v: Vec = a; + let a: Vec = vec!(1, 2, 3, 4, 5); + let b: Vec = vec!(6, 7, 8, 9, 0); + let mut v: Vec = a; v.push_all(&b); println!("{}", v[9]); assert_eq!(v[0], 1); diff --git a/src/test/run-pass/vec-dst.rs b/src/test/run-pass/vec-dst.rs index 40073c2b74..e88acb3838 100644 --- a/src/test/run-pass/vec-dst.rs +++ b/src/test/run-pass/vec-dst.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] pub fn main() { // Tests for indexing into box/& [T; n] - let x: [int; 3] = [1, 2, 3]; - let mut x: Box<[int; 3]> = box x; + let x: [isize; 3] = [1, 2, 3]; + let mut x: Box<[isize; 3]> = box x; assert!(x[0] == 1); assert!(x[1] == 2); assert!(x[2] == 3); @@ -23,8 +25,8 @@ pub fn main() { assert!(x[1] == 45); assert!(x[2] == 3); - let mut x: [int; 3] = [1, 2, 3]; - let x: &mut [int; 3] = &mut x; + let mut x: [isize; 3] = [1, 2, 3]; + let x: &mut [isize; 3] = &mut x; assert!(x[0] == 1); assert!(x[1] == 2); assert!(x[2] == 3); diff --git a/src/test/run-pass/vec-fixed-length.rs b/src/test/run-pass/vec-fixed-length.rs index 015baea5fb..4dadf53c77 100644 --- a/src/test/run-pass/vec-fixed-length.rs +++ b/src/test/run-pass/vec-fixed-length.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::mem::size_of; pub fn main() { - let x: [int; 4] = [1, 2, 3, 4]; + let x: [isize; 4] = [1, 2, 3, 4]; assert_eq!(x[0], 1); assert_eq!(x[1], 2); assert_eq!(x[2], 3); assert_eq!(x[3], 4); - assert_eq!(size_of::<[u8; 4]>(), 4_usize); + assert_eq!(size_of::<[u8; 4]>(), 4); // FIXME #10183 // FIXME #18069 //if cfg!(target_pointer_width = "64") { - // assert_eq!(size_of::<[u8; (1 << 32)]>(), (1_usize << 32)); + // assert_eq!(size_of::<[u8; (1 << 32)]>(), (1 << 32)); //} } diff --git a/src/test/run-pass/vec-growth.rs b/src/test/run-pass/vec-growth.rs index b8626b9c8a..d5e6a9c424 100644 --- a/src/test/run-pass/vec-growth.rs +++ b/src/test/run-pass/vec-growth.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut v = vec!(1); v.push(2); diff --git a/src/test/run-pass/vec-late-init.rs b/src/test/run-pass/vec-late-init.rs index dec0b3eaa7..7a8c0739ef 100644 --- a/src/test/run-pass/vec-late-init.rs +++ b/src/test/run-pass/vec-late-init.rs @@ -10,7 +10,7 @@ pub fn main() { - let mut later: Vec ; + let mut later: Vec ; if true { later = vec!(1); } else { later = vec!(2); } println!("{}", later[0]); } diff --git a/src/test/run-pass/vec-macro-no-std.rs b/src/test/run-pass/vec-macro-no-std.rs index 47b87fce2a..948fe28cc6 100644 --- a/src/test/run-pass/vec-macro-no-std.rs +++ b/src/test/run-pass/vec-macro-no-std.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, start, no_std)] +// pretty-expanded FIXME #23616 + +#![feature(lang_items, start, no_std, core, libc, collections)] #![no_std] -extern crate "std" as other; +extern crate std as other; #[macro_use] extern crate core; @@ -27,7 +29,7 @@ use collections::vec::Vec; // Issue #16806 #[start] -fn start(_argc: int, _argv: *const *const u8) -> int { +fn start(_argc: isize, _argv: *const *const u8) -> isize { let x: Vec = vec![0, 1, 2]; match x.last() { Some(&2) => (), diff --git a/src/test/run-pass/vec-macro-repeat.rs b/src/test/run-pass/vec-macro-repeat.rs index 76e7b92ea0..2a83ccaba8 100644 --- a/src/test/run-pass/vec-macro-repeat.rs +++ b/src/test/run-pass/vec-macro-repeat.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert_eq!(vec![1; 3], vec![1, 1, 1]); assert_eq!(vec![1; 2], vec![1, 1]); diff --git a/src/test/run-pass/vec-macro-rvalue-scope.rs b/src/test/run-pass/vec-macro-rvalue-scope.rs index 68dedfc6a2..5869558eac 100644 --- a/src/test/run-pass/vec-macro-rvalue-scope.rs +++ b/src/test/run-pass/vec-macro-rvalue-scope.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + fn one() -> i32 { 1 } // Make sure the vec![...] macro doesn't introduce hidden rvalue diff --git a/src/test/run-pass/vec-macro-with-brackets.rs b/src/test/run-pass/vec-macro-with-brackets.rs index 5d1f43fb23..cccf807572 100644 --- a/src/test/run-pass/vec-macro-with-brackets.rs +++ b/src/test/run-pass/vec-macro-with-brackets.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + macro_rules! vec [ ($($e:expr),*) => ({ let mut _temp = ::std::vec::Vec::new(); diff --git a/src/test/run-pass/vec-macro-with-trailing-comma.rs b/src/test/run-pass/vec-macro-with-trailing-comma.rs index 07033d6049..3018a746b4 100644 --- a/src/test/run-pass/vec-macro-with-trailing-comma.rs +++ b/src/test/run-pass/vec-macro-with-trailing-comma.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert_eq!(vec!(1), vec!(1,)); assert_eq!(vec!(1, 2, 3), vec!(1, 2, 3,)); diff --git a/src/test/run-pass/vec-matching-autoslice.rs b/src/test/run-pass/vec-matching-autoslice.rs index 4ed73dc230..2b80ad8103 100644 --- a/src/test/run-pass/vec-matching-autoslice.rs +++ b/src/test/run-pass/vec-matching-autoslice.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + pub fn main() { let x = [1, 2, 3]; match x { diff --git a/src/test/run-pass/vec-matching-fixed.rs b/src/test/run-pass/vec-matching-fixed.rs index 6ef1dc4ea2..1278eaf96a 100644 --- a/src/test/run-pass/vec-matching-fixed.rs +++ b/src/test/run-pass/vec-matching-fixed.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] fn a() { let x = [1, 2, 3]; diff --git a/src/test/run-pass/vec-matching-fold.rs b/src/test/run-pass/vec-matching-fold.rs index e72170cb73..c375fc85bc 100644 --- a/src/test/run-pass/vec-matching-fold.rs +++ b/src/test/run-pass/vec-matching-fold.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] fn foldl(values: &[T], initial: U, diff --git a/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs b/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs index 6430990615..e7553c8e15 100644 --- a/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs +++ b/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + pub fn main() { let x = &[1, 2, 3, 4, 5]; - let x: &[int] = &[1, 2, 3, 4, 5]; + let x: &[isize] = &[1, 2, 3, 4, 5]; if !x.is_empty() { let el = match x { [1, ref tail..] => &tail[0], diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index 8dcf4612f4..b81bdda613 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] fn a() { let x = [1]; @@ -74,7 +77,7 @@ fn d() { } fn e() { - let x: &[int] = &[1, 2, 3]; + let x: &[isize] = &[1, 2, 3]; match x { [1, 2] => (), [..] => () diff --git a/src/test/run-pass/vec-push.rs b/src/test/run-pass/vec-push.rs index 33f01c5bd4..b69bd53cb8 100644 --- a/src/test/run-pass/vec-push.rs +++ b/src/test/run-pass/vec-push.rs @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut v = vec!(1, 2, 3); v.push(1); } diff --git a/src/test/run-pass/vec-repeat-with-cast.rs b/src/test/run-pass/vec-repeat-with-cast.rs index 22ca6c37a8..a6ca02d4fa 100644 --- a/src/test/run-pass/vec-repeat-with-cast.rs +++ b/src/test/run-pass/vec-repeat-with-cast.rs @@ -8,4 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn main() { let _a = [0; 1 as uint]; } +// pretty-expanded FIXME #23616 + +pub fn main() { let _a = [0; 1 as usize]; } diff --git a/src/test/run-pass/vec-slice-drop.rs b/src/test/run-pass/vec-slice-drop.rs index 498ec0e8fb..1d749d4963 100644 --- a/src/test/run-pass/vec-slice-drop.rs +++ b/src/test/run-pass/vec-slice-drop.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_destructor)] use std::cell::Cell; // Make sure that destructors get run on slice literals struct foo<'a> { - x: &'a Cell, + x: &'a Cell, } #[unsafe_destructor] @@ -24,7 +26,7 @@ impl<'a> Drop for foo<'a> { } } -fn foo(x: &Cell) -> foo { +fn foo(x: &Cell) -> foo { foo { x: x } diff --git a/src/test/run-pass/vec-slice.rs b/src/test/run-pass/vec-slice.rs index 5375e54e27..6baeb99df9 100644 --- a/src/test/run-pass/vec-slice.rs +++ b/src/test/run-pass/vec-slice.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let v = vec![1,2,3,4,5]; let v2 = &v[1..3]; diff --git a/src/test/run-pass/vec-tail-matching.rs b/src/test/run-pass/vec-tail-matching.rs index 401d629c38..091e3f03e7 100644 --- a/src/test/run-pass/vec-tail-matching.rs +++ b/src/test/run-pass/vec-tail-matching.rs @@ -9,6 +9,10 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + struct Foo { string: String } diff --git a/src/test/run-pass/vec-to_str.rs b/src/test/run-pass/vec-to_str.rs index 5d132b2a74..a9bb68395c 100644 --- a/src/test/run-pass/vec-to_str.rs +++ b/src/test/run-pass/vec-to_str.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { assert_eq!(format!("{:?}", vec!(0, 1)), "[0, 1]".to_string()); let foo = vec!(3, 4); - let bar: &[int] = &[4, 5]; + let bar: &[isize] = &[4, 5]; assert_eq!(format!("{:?}", foo), "[3, 4]"); assert_eq!(format!("{:?}", bar), "[4, 5]"); diff --git a/src/test/run-pass/vec.rs b/src/test/run-pass/vec.rs index 5e19868de1..ce20d452c4 100644 --- a/src/test/run-pass/vec.rs +++ b/src/test/run-pass/vec.rs @@ -9,11 +9,13 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { - let v: Vec = vec!(10, 20); + let v: Vec = vec!(10, 20); assert_eq!(v[0], 10); assert_eq!(v[1], 20); - let mut x: uint = 0; + let mut x: usize = 0; assert_eq!(v[x], 10); assert_eq!(v[x + 1], 20); x = x + 1; diff --git a/src/test/run-pass/vector-no-ann-2.rs b/src/test/run-pass/vector-no-ann-2.rs index 6391893b9a..10f71b3e12 100644 --- a/src/test/run-pass/vector-no-ann-2.rs +++ b/src/test/run-pass/vector-no-ann-2.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![allow(unknown_features)] #![feature(box_syntax)] -pub fn main() { let _quux: Box> = box Vec::new(); } +pub fn main() { let _quux: Box> = box Vec::new(); } diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 08d39e58b7..09ecdf45b9 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(rand, core)] + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use std::rand::{thread_rng, Rng, Rand}; use std::thread; @@ -53,7 +57,7 @@ impl Drop for DropCounter { } pub fn main() { - assert!(MAX_LEN <= std::usize::BITS); + assert!(MAX_LEN <= std::usize::BITS as usize); // len can't go above 64. for len in 2..MAX_LEN { for _ in 0..REPEATS { diff --git a/src/test/run-pass/visible-private-types-feature-gate.rs b/src/test/run-pass/visible-private-types-feature-gate.rs index 46e93b2569..4aa0867ae4 100644 --- a/src/test/run-pass/visible-private-types-feature-gate.rs +++ b/src/test/run-pass/visible-private-types-feature-gate.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(visible_private_types)] trait Foo { fn dummy(&self) { } } @@ -19,4 +21,3 @@ struct Baz; pub fn f(_: Baz) {} fn main() {} - diff --git a/src/test/run-pass/wait-forked-but-failed-child.rs b/src/test/run-pass/wait-forked-but-failed-child.rs index dcbecb859e..079c97013a 100644 --- a/src/test/run-pass/wait-forked-but-failed-child.rs +++ b/src/test/run-pass/wait-forked-but-failed-child.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(libc, old_io)] + extern crate libc; use std::old_io::process::Command; diff --git a/src/test/run-pass/warn-ctypes-inhibit.rs b/src/test/run-pass/warn-ctypes-inhibit.rs index 7312191825..81a3c94eec 100644 --- a/src/test/run-pass/warn-ctypes-inhibit.rs +++ b/src/test/run-pass/warn-ctypes-inhibit.rs @@ -10,11 +10,13 @@ // compile-flags:-D improper-ctypes +// pretty-expanded FIXME #23616 + #![allow(improper_ctypes)] mod libc { extern { - pub fn malloc(size: int) -> *const u8; + pub fn malloc(size: isize) -> *const u8; } } diff --git a/src/test/run-pass/weak-lang-item.rs b/src/test/run-pass/weak-lang-item.rs index 741e8be02f..5a567758bf 100644 --- a/src/test/run-pass/weak-lang-item.rs +++ b/src/test/run-pass/weak-lang-item.rs @@ -10,7 +10,9 @@ // aux-build:weak-lang-items.rs -extern crate "weak-lang-items" as other; +// pretty-expanded FIXME #23616 + +extern crate weak_lang_items as other; use std::thread; diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs index baea1b8826..b28760e6c9 100644 --- a/src/test/run-pass/weird-exprs.rs +++ b/src/test/run-pass/weird-exprs.rs @@ -54,18 +54,18 @@ fn zombiejesus() { } fn notsure() { - let mut _x: int; + let mut _x: isize; let mut _y = (_x = 0) == (_x = 0); let mut _z = (_x = 0) < (_x = 0); let _a = (_x += 0) == (_x = 0); let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z); } -fn canttouchthis() -> uint { +fn canttouchthis() -> usize { fn p() -> bool { true } let _a = (assert!((true)) == (assert!(p()))); let _c = (assert!((p())) == ()); - let _b: bool = (println!("{}", 0) == (return 0_usize)); + let _b: bool = (println!("{}", 0) == (return 0)); } fn angrydome() { 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 index 256b199d72..cdb5e3fe1d 100644 --- a/src/test/run-pass/wf-bound-region-in-object-type.rs +++ b/src/test/run-pass/wf-bound-region-in-object-type.rs @@ -11,14 +11,16 @@ // Test that the `wf` checker properly handles bound regions in object // types. Compiling this code used to trigger an ICE. +// pretty-expanded FIXME #23616 + pub struct Context<'tcx> { - vec: &'tcx Vec + vec: &'tcx Vec } -pub type Cmd<'a> = &'a int; +pub type Cmd<'a> = &'a isize; pub type DecodeInlinedItem<'a> = - Box FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx int, ()> + 'a>; + Box FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx isize, ()> + 'a>; fn foo(d: DecodeInlinedItem) { } diff --git a/src/test/run-pass/where-clause-bounds-inconsistency.rs b/src/test/run-pass/where-clause-bounds-inconsistency.rs index 3374f47ed5..d4823b8a33 100644 --- a/src/test/run-pass/where-clause-bounds-inconsistency.rs +++ b/src/test/run-pass/where-clause-bounds-inconsistency.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Bound { fn dummy(&self) { } } diff --git a/src/test/run-pass/where-clause-early-bound-lifetimes.rs b/src/test/run-pass/where-clause-early-bound-lifetimes.rs index 4a149d4d3d..b9f605ec54 100644 --- a/src/test/run-pass/where-clause-early-bound-lifetimes.rs +++ b/src/test/run-pass/where-clause-early-bound-lifetimes.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait TheTrait { fn dummy(&self) { } } -impl TheTrait for &'static int { } +impl TheTrait for &'static isize { } fn foo<'a,T>(_: &'a T) where &'a T : TheTrait { } fn bar(_: &'static T) where &'static T : TheTrait { } fn main() { - static x: int = 1; + static x: isize = 1; foo(&x); bar(&x); } diff --git a/src/test/run-pass/where-clause-method-substituion.rs b/src/test/run-pass/where-clause-method-substituion.rs index ecc210ea57..d7aaa0b2f9 100644 --- a/src/test/run-pass/where-clause-method-substituion.rs +++ b/src/test/run-pass/where-clause-method-substituion.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + trait Foo { fn dummy(&self, arg: T) { } } trait Bar { @@ -27,4 +29,3 @@ impl Bar for i32 { fn main() { 1.method::(); } - diff --git a/src/test/run-pass/where-clause-region-outlives.rs b/src/test/run-pass/where-clause-region-outlives.rs index aa39325277..60df52bfeb 100644 --- a/src/test/run-pass/where-clause-region-outlives.rs +++ b/src/test/run-pass/where-clause-region-outlives.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct A<'a, 'b> where 'a : 'b { x: &'a int, y: &'b int } +// pretty-expanded FIXME #23616 + +struct A<'a, 'b> where 'a : 'b { x: &'a isize, y: &'b isize } fn main() { let x = 1; diff --git a/src/test/run-pass/where-clauses-cross-crate.rs b/src/test/run-pass/where-clauses-cross-crate.rs index b822abd673..1b349b25ef 100644 --- a/src/test/run-pass/where-clauses-cross-crate.rs +++ b/src/test/run-pass/where-clauses-cross-crate.rs @@ -18,6 +18,5 @@ fn main() { println!("{}", equal(&1, &2)); println!("{}", equal(&1, &1)); println!("{}", "hello".equal(&"hello")); - println!("{}", "hello".equals::(&1, &1, &"foo", &"bar")); + println!("{}", "hello".equals::(&1, &1, &"foo", &"bar")); } - diff --git a/src/test/run-pass/where-clauses-lifetimes.rs b/src/test/run-pass/where-clauses-lifetimes.rs index e3ea7cd80e..bba20e8e92 100644 --- a/src/test/run-pass/where-clauses-lifetimes.rs +++ b/src/test/run-pass/where-clauses-lifetimes.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo<'a, I>(mut it: I) where I: Iterator {} +// pretty-expanded FIXME #23616 + +fn foo<'a, I>(mut it: I) where I: Iterator {} fn main() { foo([1, 2].iter()); diff --git a/src/test/run-pass/where-clauses-unboxed-closures.rs b/src/test/run-pass/where-clauses-unboxed-closures.rs index 7edcdf6429..c509cbe2a5 100644 --- a/src/test/run-pass/where-clauses-unboxed-closures.rs +++ b/src/test/run-pass/where-clauses-unboxed-closures.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unboxed_closures)] struct Bencher; @@ -23,4 +25,3 @@ fn main() { // OK warm_up(|b| () ); } - diff --git a/src/test/run-pass/where-clauses.rs b/src/test/run-pass/where-clauses.rs index 92bc7edf28..ab1f30c3d1 100644 --- a/src/test/run-pass/where-clauses.rs +++ b/src/test/run-pass/where-clauses.rs @@ -32,6 +32,5 @@ fn main() { println!("{}", equal(&1, &2)); println!("{}", equal(&1, &1)); println!("{}", "hello".equal(&"hello")); - println!("{}", "hello".equals::(&1, &1, &"foo", &"bar")); + println!("{}", "hello".equals::(&1, &1, &"foo", &"bar")); } - diff --git a/src/test/run-pass/where-for-self.rs b/src/test/run-pass/where-for-self.rs index 1fd223b0dd..8535d76d47 100644 --- a/src/test/run-pass/where-for-self.rs +++ b/src/test/run-pass/where-for-self.rs @@ -11,6 +11,8 @@ // Test that we can quantify lifetimes outside a constraint (i.e., including // the self type) in a where clause. +// pretty-expanded FIXME #23616 + use std::marker::PhantomFn; static mut COUNT: u32 = 1; @@ -55,11 +57,10 @@ fn foo2(x: &T) } fn main() { - let x = 42u32; + let x = 42; foo1(&x); foo2(&x); unsafe { assert!(COUNT == 12); } } - diff --git a/src/test/run-pass/while-flow-graph.rs b/src/test/run-pass/while-flow-graph.rs index 8239afb359..102a5a7558 100644 --- a/src/test/run-pass/while-flow-graph.rs +++ b/src/test/run-pass/while-flow-graph.rs @@ -10,4 +10,6 @@ -pub fn main() { let x: int = 10; while x == 10 && x == 11 { let _y = 0xf00_usize; } } +// pretty-expanded FIXME #23616 + +pub fn main() { let x: isize = 10; while x == 10 && x == 11 { let _y = 0xf00_usize; } } diff --git a/src/test/run-pass/while-label.rs b/src/test/run-pass/while-label.rs index 4a3cd115d2..076ba8f428 100644 --- a/src/test/run-pass/while-label.rs +++ b/src/test/run-pass/while-label.rs @@ -9,6 +9,8 @@ // except according to those terms. +// pretty-expanded FIXME #23616 + pub fn main() { let mut i = 100; 'w: while 1 + 1 == 2 { diff --git a/src/test/run-pass/while-let.rs b/src/test/run-pass/while-let.rs index 1780445fb3..b1e80c86ec 100644 --- a/src/test/run-pass/while-let.rs +++ b/src/test/run-pass/while-let.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + use std::collections::BinaryHeap; -fn make_pq() -> BinaryHeap { +fn make_pq() -> BinaryHeap { BinaryHeap::from_vec(vec![1,2,3]) } diff --git a/src/test/run-pass/while-loop-constraints-2.rs b/src/test/run-pass/while-loop-constraints-2.rs index 622b66d22a..6e33923247 100644 --- a/src/test/run-pass/while-loop-constraints-2.rs +++ b/src/test/run-pass/while-loop-constraints-2.rs @@ -12,9 +12,9 @@ #![allow(unused_variable)] pub fn main() { - let mut y: int = 42; - let mut z: int = 42; - let mut x: int; + let mut y: isize = 42; + let mut z: isize = 42; + let mut x: isize; while z < 50 { z += 1; while false { x = y; y = z; } diff --git a/src/test/run-pass/while-prelude-drop.rs b/src/test/run-pass/while-prelude-drop.rs index bfabcb4d87..88d5314a96 100644 --- a/src/test/run-pass/while-prelude-drop.rs +++ b/src/test/run-pass/while-prelude-drop.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(collections)] + use std::string::String; #[derive(PartialEq)] enum t { a, b(String), } -fn make(i: int) -> t { +fn make(i: isize) -> t { if i > 10 { return t::a; } let mut s = String::from_str("hello"); // Ensure s is non-const. diff --git a/src/test/run-pass/while-with-break.rs b/src/test/run-pass/while-with-break.rs index a732826754..ed149ad510 100644 --- a/src/test/run-pass/while-with-break.rs +++ b/src/test/run-pass/while-with-break.rs @@ -10,12 +10,12 @@ pub fn main() { - let mut i: int = 90; + let mut i: isize = 90; while i < 100 { println!("{}", i); i = i + 1; if i == 95 { - let _v: Vec = + let _v: Vec = vec!(1, 2, 3, 4, 5); // we check that it is freed by break println!("breaking"); diff --git a/src/test/run-pass/while.rs b/src/test/run-pass/while.rs index bd8b1f0f08..bf56e76687 100644 --- a/src/test/run-pass/while.rs +++ b/src/test/run-pass/while.rs @@ -11,8 +11,8 @@ pub fn main() { - let mut x: int = 10; - let mut y: int = 0; + let mut x: isize = 10; + let mut y: isize = 0; while y < x { println!("{}", y); println!("hello"); y = y + 1; } while x > 0 { println!("goodbye"); diff --git a/src/test/run-pass/writealias.rs b/src/test/run-pass/writealias.rs index dacfeb0081..10718e981f 100644 --- a/src/test/run-pass/writealias.rs +++ b/src/test/run-pass/writealias.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + use std::sync::Mutex; -struct Point {x: int, y: int, z: int} +struct Point {x: isize, y: isize, z: isize} fn f(p: &mut Point) { p.z = 13; } diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs index 5dd0a5522c..b0bfb5c29c 100644 --- a/src/test/run-pass/x86stdcall.rs +++ b/src/test/run-pass/x86stdcall.rs @@ -13,8 +13,8 @@ #[cfg(windows)] mod kernel32 { extern "system" { - pub fn SetLastError(err: uint); - pub fn GetLastError() -> uint; + pub fn SetLastError(err: usize); + pub fn GetLastError() -> usize; } } @@ -22,7 +22,7 @@ mod kernel32 { #[cfg(windows)] pub fn main() { unsafe { - let expected = 1234_usize; + let expected = 1234; kernel32::SetLastError(expected); let actual = kernel32::GetLastError(); println!("actual = {}", actual); @@ -34,6 +34,7 @@ pub fn main() { target_os = "linux", target_os = "freebsd", target_os = "dragonfly", + target_os = "bitrig", target_os = "openbsd", target_os = "android"))] pub fn main() { } diff --git a/src/test/run-pass/x86stdcall2.rs b/src/test/run-pass/x86stdcall2.rs index 86c1ae0f51..7b15531dac 100644 --- a/src/test/run-pass/x86stdcall2.rs +++ b/src/test/run-pass/x86stdcall2.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + pub type HANDLE = u32; pub type DWORD = u32; pub type SIZE_T = u32; -pub type LPVOID = uint; +pub type LPVOID = usize; pub type BOOL = u8; #[cfg(windows)] @@ -30,10 +32,10 @@ mod kernel32 { #[cfg(windows)] pub fn main() { let heap = unsafe { kernel32::GetProcessHeap() }; - let mem = unsafe { kernel32::HeapAlloc(heap, 0u32, 100u32) }; - assert!(mem != 0_usize); - let res = unsafe { kernel32::HeapFree(heap, 0u32, mem) }; - assert!(res != 0u8); + let mem = unsafe { kernel32::HeapAlloc(heap, 0, 100) }; + assert!(mem != 0); + let res = unsafe { kernel32::HeapFree(heap, 0, mem) }; + assert!(res != 0); } #[cfg(not(windows))] diff --git a/src/test/run-pass/xcrate-address-insignificant.rs b/src/test/run-pass/xcrate-address-insignificant.rs index 236ff0838e..ac8b15d7bf 100644 --- a/src/test/run-pass/xcrate-address-insignificant.rs +++ b/src/test/run-pass/xcrate-address-insignificant.rs @@ -10,7 +10,9 @@ // aux-build:xcrate_address_insignificant.rs -extern crate "xcrate_address_insignificant" as foo; +// pretty-expanded FIXME #23616 + +extern crate xcrate_address_insignificant as foo; pub fn main() { assert_eq!(foo::foo::(), foo::bar()); diff --git a/src/test/run-pass/xcrate-static-addresses.rs b/src/test/run-pass/xcrate-static-addresses.rs index 6afa02fce5..43bae9c7ce 100644 --- a/src/test/run-pass/xcrate-static-addresses.rs +++ b/src/test/run-pass/xcrate-static-addresses.rs @@ -10,6 +10,8 @@ // aux-build:xcrate_static_addresses.rs +// pretty-expanded FIXME #23616 + extern crate xcrate_static_addresses; use xcrate_static_addresses as other; diff --git a/src/test/run-pass/xcrate-trait-lifetime-param.rs b/src/test/run-pass/xcrate-trait-lifetime-param.rs index aa61237417..62d62839ba 100644 --- a/src/test/run-pass/xcrate-trait-lifetime-param.rs +++ b/src/test/run-pass/xcrate-trait-lifetime-param.rs @@ -10,7 +10,9 @@ // aux-build:xcrate-trait-lifetime-param.rs -extern crate "xcrate-trait-lifetime-param" as other; +// pretty-expanded FIXME #23616 + +extern crate xcrate_trait_lifetime_param as other; struct Reader<'a> { b : &'a [u8] diff --git a/src/test/run-pass/xcrate-unit-struct.rs b/src/test/run-pass/xcrate-unit-struct.rs index 30b5f47b2a..78e92053a1 100644 --- a/src/test/run-pass/xcrate-unit-struct.rs +++ b/src/test/run-pass/xcrate-unit-struct.rs @@ -9,6 +9,8 @@ // except according to those terms. // aux-build:xcrate_unit_struct.rs +// pretty-expanded FIXME #23616 + extern crate xcrate_unit_struct; const s1: xcrate_unit_struct::Struct = xcrate_unit_struct::Struct; diff --git a/src/test/run-pass/yield2.rs b/src/test/run-pass/yield2.rs index 56dc02c6d2..acc5583313 100644 --- a/src/test/run-pass/yield2.rs +++ b/src/test/run-pass/yield2.rs @@ -11,6 +11,6 @@ use std::thread; pub fn main() { - let mut i: int = 0; + let mut i: isize = 0; while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); } } diff --git a/src/test/run-pass/zero-size-type-destructors.rs b/src/test/run-pass/zero-size-type-destructors.rs index f4d03a5cda..dea9edf058 100644 --- a/src/test/run-pass/zero-size-type-destructors.rs +++ b/src/test/run-pass/zero-size-type-destructors.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + #![feature(unsafe_no_drop_flag)] -static mut destructions : int = 3; +static mut destructions : isize = 3; pub fn foo() { #[unsafe_no_drop_flag] diff --git a/src/test/run-pass/zero_sized_subslice_match.rs b/src/test/run-pass/zero_sized_subslice_match.rs index 65882d3937..b98f907774 100644 --- a/src/test/run-pass/zero_sized_subslice_match.rs +++ b/src/test/run-pass/zero_sized_subslice_match.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// pretty-expanded FIXME #23616 + +#![feature(slice_patterns)] + fn main() { let x = [(), ()]; // The subslice used to go out of bounds for zero-sized array items, check that this doesn't // happen anymore match x { - [_, y..] => assert_eq!(&x[1] as *const _, &y[0] as *const _) + [_, y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ()) } } -- 2.39.5

    = self.child.get(); //~^ ERROR attempt to use a non-constant value in a constant + //~| ERROR unresolved name `self` panic!(); } } diff --git a/src/test/compile-fail/issue-3763.rs b/src/test/compile-fail/issue-3763.rs index 6e6c19a5bf..085b4e76af 100644 --- a/src/test/compile-fail/issue-3763.rs +++ b/src/test/compile-fail/issue-3763.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - mod my_mod { pub struct MyStruct { priv_field: isize @@ -26,10 +24,15 @@ fn main() { let my_struct = my_mod::MyStruct(); let _woohoo = (&my_struct).priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private - let _woohoo = (box my_struct).priv_field; + + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let _woohoo = (Box::new(my_struct)).priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private + (&my_struct).happyfun(); //~ ERROR method `happyfun` is private - (box my_struct).happyfun(); //~ ERROR method `happyfun` is private + + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + (Box::new(my_struct)).happyfun(); //~ ERROR method `happyfun` is private let nope = my_struct.priv_field; //~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private } diff --git a/src/test/compile-fail/issue-3907.rs b/src/test/compile-fail/issue-3907.rs index 001de796b4..a3d90a00d0 100644 --- a/src/test/compile-fail/issue-3907.rs +++ b/src/test/compile-fail/issue-3907.rs @@ -28,4 +28,3 @@ fn main() { }; s.bar(); } - diff --git a/src/test/compile-fail/issue-3953.rs b/src/test/compile-fail/issue-3953.rs deleted file mode 100644 index 0f1dd2d7fd..0000000000 --- a/src/test/compile-fail/issue-3953.rs +++ /dev/null @@ -1,34 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-tidy-linelength - -use std::cmp::PartialEq; - -trait Hahaha: PartialEq + PartialEq { - //~^ ERROR trait `PartialEq` already appears in the list of bounds -} - -struct Lol(isize); - -impl Hahaha for Lol { } - -impl PartialEq for Lol { - fn eq(&self, other: &Lol) -> bool { **self != **other } - fn ne(&self, other: &Lol) -> bool { **self == **other } -} - -fn main() { - if Lol(2) == Lol(4) { - println!("2 == 4"); - } else { - println!("2 != 4"); - } -} diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs index e4f7521c33..2652fb5dfc 100644 --- a/src/test/compile-fail/issue-3973.rs +++ b/src/test/compile-fail/issue-3973.rs @@ -30,7 +30,5 @@ impl ToString_ for Point { fn main() { let p = Point::new(0.0, 0.0); - //~^ ERROR unresolved name `Point::new` - //~^^ ERROR failed to resolve. Use of undeclared type or module `Point` println!("{}", p.to_string()); } diff --git a/src/test/compile-fail/issue-4265.rs b/src/test/compile-fail/issue-4265.rs index b4bc7ecdc5..553436607d 100644 --- a/src/test/compile-fail/issue-4265.rs +++ b/src/test/compile-fail/issue-4265.rs @@ -17,7 +17,7 @@ impl Foo { Foo { baz: 0 }.bar(); } - fn bar() { //~ ERROR duplicate definition of value `bar` + fn bar() { //~ ERROR duplicate method } } diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs index d0da51373d..55a793f748 100644 --- a/src/test/compile-fail/issue-4335.rs +++ b/src/test/compile-fail/issue-4335.rs @@ -9,12 +9,14 @@ // except according to those terms. #![feature(unboxed_closures)] -#![feature(box_syntax)] fn id(t: T) -> T { t } fn f<'r, T>(v: &'r T) -> Box T + 'r> { - id(box || *v) //~ ERROR cannot infer + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + id(Box::new(|| *v)) + //~^ ERROR `v` does not live long enough + //~| ERROR cannot move out of borrowed content } fn main() { diff --git a/src/test/compile-fail/issue-4517.rs b/src/test/compile-fail/issue-4517.rs index 6d4777be40..a1804b5a26 100644 --- a/src/test/compile-fail/issue-4517.rs +++ b/src/test/compile-fail/issue-4517.rs @@ -11,7 +11,7 @@ fn bar(int_param: usize) {} fn main() { - let foo: [u8; 4] = [1u8; 4_usize]; + let foo: [u8; 4] = [1; 4]; bar(foo); //~^ ERROR mismatched types //~| expected `usize` diff --git a/src/test/compile-fail/issue-5239-1.rs b/src/test/compile-fail/issue-5239-1.rs index 49a43ee37a..1ebef06008 100644 --- a/src/test/compile-fail/issue-5239-1.rs +++ b/src/test/compile-fail/issue-5239-1.rs @@ -12,5 +12,5 @@ fn main() { let x = |ref x: isize| -> isize { x += 1; }; - //~^ ERROR binary assignment operation `+=` cannot be applied to type `&isize` + //~^ ERROR E0368 } diff --git a/src/test/compile-fail/issue-5844.rs b/src/test/compile-fail/issue-5844.rs index 6c85a97f7f..02e5b9b092 100644 --- a/src/test/compile-fail/issue-5844.rs +++ b/src/test/compile-fail/issue-5844.rs @@ -15,4 +15,3 @@ extern crate issue_5844_aux; fn main () { issue_5844_aux::rand(); //~ ERROR: requires unsafe } - diff --git a/src/test/compile-fail/issue-6804.rs b/src/test/compile-fail/issue-6804.rs index 30d3ab17a4..ffab194149 100644 --- a/src/test/compile-fail/issue-6804.rs +++ b/src/test/compile-fail/issue-6804.rs @@ -8,13 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_attrs)] +#![feature(slice_patterns)] #![allow(dead_code)] // Matching against NaN should result in a warning use std::f64::NAN; -fn main() { +#[rustc_error] +fn main() { //~ ERROR compilation successful let x = NAN; match x { NAN => {}, @@ -27,7 +30,3 @@ fn main() { }; //~^^^ WARNING unmatchable NaN in pattern, use the is_nan method in a guard instead } - -// At least one error is needed so that compilation fails -#[static_assert] -static B: bool = false; //~ ERROR static assertion failed diff --git a/src/test/compile-fail/issue-7575.rs b/src/test/compile-fail/issue-7575.rs index b6643f4395..9c019f6ec4 100644 --- a/src/test/compile-fail/issue-7575.rs +++ b/src/test/compile-fail/issue-7575.rs @@ -32,17 +32,17 @@ trait UnusedTrait : MarkerTrait { impl CtxtFn for usize { fn f8(self, i: usize) -> usize { - i * 4_usize + i * 4 } fn f9(i: usize) -> usize { - i * 4_usize + i * 4 } } impl OtherTrait for usize { fn f9(i: usize) -> usize { - i * 8_usize + i * 8 } } diff --git a/src/test/compile-fail/issue-7607-1.rs b/src/test/compile-fail/issue-7607-1.rs index 48fc393d0d..40c3d96bc9 100644 --- a/src/test/compile-fail/issue-7607-1.rs +++ b/src/test/compile-fail/issue-7607-1.rs @@ -8,15 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - struct Foo { x: isize } -impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module +impl Fo { //~ ERROR use of undeclared type name `Fo` fn foo() {} } fn main() {} - diff --git a/src/test/compile-fail/issue-7867.rs b/src/test/compile-fail/issue-7867.rs index 7bb4aac23d..400806c3a5 100644 --- a/src/test/compile-fail/issue-7867.rs +++ b/src/test/compile-fail/issue-7867.rs @@ -23,16 +23,16 @@ fn main() { _ => () } - match &Some(42i32) { + match &Some(42) { Some(x) => (), //~^ ERROR mismatched types - //~| expected `&core::option::Option` + //~| expected `&core::option::Option<_>` //~| found `core::option::Option<_>` //~| expected &-ptr //~| found enum `core::option::Option` None => () //~^ ERROR mismatched types - //~| expected `&core::option::Option` + //~| expected `&core::option::Option<_>` //~| found `core::option::Option<_>` //~| expected &-ptr //~| found enum `core::option::Option` diff --git a/src/test/compile-fail/issue-7950.rs b/src/test/compile-fail/issue-7950.rs new file mode 100644 index 0000000000..01b90f5680 --- /dev/null +++ b/src/test/compile-fail/issue-7950.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// tests the good error message, not "missing module Foo" or something else unexpected + +struct Foo; + +fn main() { + Foo::bar(); //~ ERROR type `Foo` does not implement any method in scope named `bar` +} diff --git a/src/test/compile-fail/issue-8460-const.rs b/src/test/compile-fail/issue-8460-const.rs index 954ae8ebc4..9c2e8d278a 100644 --- a/src/test/compile-fail/issue-8460-const.rs +++ b/src/test/compile-fail/issue-8460-const.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{int, i8, i16, i32, i64}; +use std::{isize, i8, i16, i32, i64}; use std::thread; fn main() { - assert!(thread::spawn(move|| { int::MIN / -1; }).join().is_err()); + assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression @@ -32,7 +32,7 @@ fn main() { //~^ ERROR attempted to divide by zero in a constant expression assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| { int::MIN % -1; }).join().is_err()); + assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression diff --git a/src/test/compile-fail/issue-8767.rs b/src/test/compile-fail/issue-8767.rs index 6c5bac5e0c..9abd8c9e3f 100644 --- a/src/test/compile-fail/issue-8767.rs +++ b/src/test/compile-fail/issue-8767.rs @@ -10,9 +10,8 @@ // ignore-tidy-linelength -impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module +impl B { //~ ERROR use of undeclared type name `B` } fn main() { } - diff --git a/src/test/compile-fail/issue-9814.rs b/src/test/compile-fail/issue-9814.rs index 8aefc5919d..226734b84d 100644 --- a/src/test/compile-fail/issue-9814.rs +++ b/src/test/compile-fail/issue-9814.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Verify that single-variant enums cant be de-referenced +// Verify that single-variant enums can't be de-referenced // Regression test for issue #9814 enum Foo { Bar(isize) } diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index 74e372e41e..1925caf687 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -17,7 +17,7 @@ fn assert_copy() { } trait Dummy : MarkerTrait { } -#[derive(Copy)] +#[derive(Copy, Clone)] struct MyStruct { x: isize, y: isize, @@ -80,4 +80,3 @@ fn test<'a,T,U:Copy>(_: &'a isize) { pub fn main() { } - diff --git a/src/test/compile-fail/kindck-impl-type-params-2.rs b/src/test/compile-fail/kindck-impl-type-params-2.rs index b575144f63..fd0789421e 100644 --- a/src/test/compile-fail/kindck-impl-type-params-2.rs +++ b/src/test/compile-fail/kindck-impl-type-params-2.rs @@ -21,7 +21,7 @@ impl Foo for T { fn take_param(foo: &T) { } fn main() { - let x = box 3; + let x: Box<_> = box 3; take_param(&x); //~^ ERROR the trait `core::marker::Copy` is not implemented } diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs index dffc8fa2ab..71494fd5f3 100644 --- a/src/test/compile-fail/kindck-impl-type-params.rs +++ b/src/test/compile-fail/kindck-impl-type-params.rs @@ -28,6 +28,7 @@ fn f(val: T) { let a = &t as &Gettable; //~^ ERROR the trait `core::marker::Send` is not implemented //~^^ ERROR the trait `core::marker::Copy` is not implemented + //~^^^ ERROR the parameter type `T` may not live long enough } fn g(val: T) { diff --git a/src/test/compile-fail/kindck-inherited-copy-bound.rs b/src/test/compile-fail/kindck-inherited-copy-bound.rs index 0072b1228a..066590252a 100644 --- a/src/test/compile-fail/kindck-inherited-copy-bound.rs +++ b/src/test/compile-fail/kindck-inherited-copy-bound.rs @@ -24,14 +24,14 @@ impl Foo for T { fn take_param(foo: &T) { } fn a() { - let x = box 3; - take_param(&x); //~ ERROR `core::marker::Copy` is not implemented + let x: Box<_> = box 3; + take_param(&x); //~ ERROR E0277 } fn b() { - let x = box 3; + let x: Box<_> = box 3; let y = &x; - let z = &x as &Foo; //~ ERROR `core::marker::Copy` is not implemented + let z = &x as &Foo; //~ ERROR E0038 } fn main() { } diff --git a/src/test/compile-fail/kindck-nonsendable-1.rs b/src/test/compile-fail/kindck-nonsendable-1.rs index e6041cddea..bf2a209c4c 100644 --- a/src/test/compile-fail/kindck-nonsendable-1.rs +++ b/src/test/compile-fail/kindck-nonsendable-1.rs @@ -16,8 +16,7 @@ fn foo(_x: Rc) {} fn bar(_: F) { } fn main() { - let x = Rc::new(3_usize); + let x = Rc::new(3); bar(move|| foo(x)); //~^ ERROR `core::marker::Send` is not implemented } - diff --git a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs index 55cce01633..1fa7284f6b 100644 --- a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -37,4 +37,3 @@ fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier } fn main() {} - diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs index fac518c763..d2d0dbf3e9 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs @@ -10,21 +10,21 @@ // ignore-tidy-linelength -use std::iter::{Range,range}; +use std::ops::Range; trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } impl<'r> Itble<'r, usize, Range> for (usize, usize) { fn iter(&'r self) -> Range { let &(min, max) = self; - range(min, max) + min..max } } fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool { //~^ HELP: consider using an explicit lifetime parameter as shown: fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &'r T) let cont_iter = cont.iter(); //~ ERROR: cannot infer - let result = cont_iter.fold(Some(0u16), |state, val| { + let result = cont_iter.fold(Some(0), |state, val| { state.map_or(None, |mask| { let bit = 1 << val; if mask & bit == 0 {Some(mask|bit)} else {None} diff --git a/src/test/compile-fail/linkage1.rs b/src/test/compile-fail/linkage1.rs index 35f93c13fb..555cc2b9a7 100644 --- a/src/test/compile-fail/linkage1.rs +++ b/src/test/compile-fail/linkage1.rs @@ -11,5 +11,4 @@ extern { #[linkage = "extern_weak"] static foo: isize; //~^ ERROR: the `linkage` attribute is experimental and not portable - //~^^ ERROR: the `linkage` attribute is experimental and not portable } diff --git a/src/test/compile-fail/linkage3.rs b/src/test/compile-fail/linkage3.rs index c75c7002e5..8343f71890 100644 --- a/src/test/compile-fail/linkage3.rs +++ b/src/test/compile-fail/linkage3.rs @@ -18,4 +18,3 @@ extern { fn main() { println!("{:?}", foo); } - diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs index f60c39ba02..ba1b7f03b0 100644 --- a/src/test/compile-fail/lint-dead-code-3.rs +++ b/src/test/compile-fail/lint-dead-code-3.rs @@ -19,7 +19,7 @@ extern crate libc; pub use extern_foo as x; extern { - fn extern_foo(); + pub fn extern_foo(); } struct Foo; //~ ERROR: struct is never used @@ -86,6 +86,6 @@ mod inner { } pub fn foo() { - let a = &1 as &inner::Trait; + let a: &inner::Trait = &1_isize; a.f(); } diff --git a/src/test/compile-fail/lint-dead-code-4.rs b/src/test/compile-fail/lint-dead-code-4.rs index f304c26efb..3a9baecb9c 100644 --- a/src/test/compile-fail/lint-dead-code-4.rs +++ b/src/test/compile-fail/lint-dead-code-4.rs @@ -16,8 +16,6 @@ extern crate libc; -use std::num::Int; - struct Foo { x: usize, b: bool, //~ ERROR: struct field is never used @@ -63,6 +61,6 @@ fn field_match_in_let(f: Bar) -> bool { fn main() { field_read(Foo { x: 1, b: false, marker: std::marker::NoCopy }); field_match_in_patterns(XYZ::Z); - field_match_in_let(Bar { x: 42_usize, b: true, _guard: () }); + field_match_in_let(Bar { x: 42, b: true, _guard: () }); let _ = Baz { x: 0 }; } diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs index 345e56e2e5..1f70828e41 100644 --- a/src/test/compile-fail/lint-exceeding-bitshifts.rs +++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(negate_unsigned)] #![deny(exceeding_bitshifts)] #![allow(unused_variables)] #![allow(dead_code)] -#![feature(core)] +#![feature(core, negate_unsigned)] fn main() { let n = 1u8 << 7; @@ -60,4 +61,3 @@ fn main() { let n = 1_isize << std::isize::BITS; //~ ERROR: bitshift exceeds the type's number of bits let n = 1_usize << std::usize::BITS; //~ ERROR: bitshift exceeds the type's number of bits } - diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 73a58741bb..04db6c8c8f 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -17,15 +17,15 @@ #![doc="More garbage"] type Typedef = String; -pub type PubTypedef = String; //~ ERROR: missing documentation +pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias struct Foo { a: isize, b: isize, } -pub struct PubFoo { //~ ERROR: missing documentation - pub a: isize, //~ ERROR: missing documentation +pub struct PubFoo { //~ ERROR: missing documentation for a struct + pub a: isize, //~ ERROR: missing documentation for a struct field b: isize, } @@ -36,11 +36,11 @@ pub struct PubFoo2 { } mod module_no_dox {} -pub mod pub_module_no_dox {} //~ ERROR: missing documentation +pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module /// dox pub fn foo() {} -pub fn foo2() {} //~ ERROR: missing documentation +pub fn foo2() {} //~ ERROR: missing documentation for a function fn foo3() {} #[allow(missing_docs)] pub fn foo4() {} @@ -58,9 +58,9 @@ trait B { fn foo_with_impl(&self) {} } -pub trait C { //~ ERROR: missing documentation - fn foo(&self); //~ ERROR: missing documentation - fn foo_with_impl(&self) {} //~ ERROR: missing documentation +pub trait C { //~ ERROR: missing documentation for a trait + fn foo(&self); //~ ERROR: missing documentation for a trait method + fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a trait method } #[allow(missing_docs)] @@ -68,13 +68,26 @@ pub trait D { fn dummy(&self) { } } +/// dox +pub trait E { + type AssociatedType; //~ ERROR: missing documentation for an associated type + type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type + + /// dox + type DocumentedType; + /// dox + type DocumentedTypeDef = Self; + /// dox + fn dummy(&self) {} +} + impl Foo { pub fn foo() {} fn bar() {} } impl PubFoo { - pub fn foo() {} //~ ERROR: missing documentation + pub fn foo() {} //~ ERROR: missing documentation for a method /// dox pub fn foo1() {} fn foo2() {} @@ -111,9 +124,9 @@ enum Baz { BarB } -pub enum PubBaz { //~ ERROR: missing documentation - PubBazA { //~ ERROR: missing documentation - a: isize, //~ ERROR: missing documentation +pub enum PubBaz { //~ ERROR: missing documentation for an enum + PubBazA { //~ ERROR: missing documentation for a variant + a: isize, //~ ERROR: missing documentation for a struct field }, } @@ -139,14 +152,14 @@ pub fn baz() {} mod internal_impl { /// dox pub fn documented() {} - pub fn undocumented1() {} //~ ERROR: missing documentation - pub fn undocumented2() {} //~ ERROR: missing documentation + pub fn undocumented1() {} //~ ERROR: missing documentation for a function + pub fn undocumented2() {} //~ ERROR: missing documentation for a function fn undocumented3() {} /// dox pub mod globbed { /// dox pub fn also_documented() {} - pub fn also_undocumented1() {} //~ ERROR: missing documentation + pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function fn also_undocumented2() {} } } diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs index 9f58d5791c..f6d3d62d0b 100644 --- a/src/test/compile-fail/lint-non-camel-case-types.rs +++ b/src/test/compile-fail/lint-non-camel-case-types.rs @@ -11,6 +11,9 @@ #![forbid(non_camel_case_types)] #![allow(dead_code)] +struct ONE_TWO_THREE; +//~^ ERROR type `ONE_TWO_THREE` should have a camel case name such as `OneTwoThree` + struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo` bar: isize, } diff --git a/src/test/compile-fail/lint-output-format.rs b/src/test/compile-fail/lint-output-format.rs index ec4e3c774d..d95ed7f10b 100644 --- a/src/test/compile-fail/lint-output-format.rs +++ b/src/test/compile-fail/lint-output-format.rs @@ -13,10 +13,10 @@ #![feature(foo)] //~ ERROR unused or unknown feature -extern crate lint_output_format; //~ WARNING: use of unstable library feature +extern crate lint_output_format; //~ ERROR use of unstable library feature use lint_output_format::{foo, bar}; fn main() { let _x = foo(); //~ WARNING #[warn(deprecated)] on by default - let _y = bar(); //~ WARNING: use of unstable library feature + let _y = bar(); //~ ERROR use of unstable library feature } diff --git a/src/test/compile-fail/lint-stability-fields.rs b/src/test/compile-fail/lint-stability-fields.rs new file mode 100644 index 0000000000..716d7674b2 --- /dev/null +++ b/src/test/compile-fail/lint-stability-fields.rs @@ -0,0 +1,346 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:lint_stability_fields.rs +#![deny(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] +#![staged_api] + +mod cross_crate { + extern crate lint_stability_fields; + + use self::lint_stability_fields::*; + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, //~ ERROR use of unstable + override2: 3, + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + }; + + let _ = x.inherit; + let _ = x.override1; //~ ERROR use of unstable + let _ = x.override2; + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + + let Stable { + inherit: _, + override1: _, //~ ERROR use of unstable + override2: _ + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; //~ ERROR use of unstable + let _ = x.2; + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + + let Stable2(_, + _, //~ ERROR use of unstable + _) + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { //~ ERROR use of unstable + inherit: 1, //~ ERROR use of unstable + override1: 2, + override2: 3, + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + }; + + let _ = x.inherit; //~ ERROR use of unstable + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + + let Unstable { //~ ERROR use of unstable + inherit: _, //~ ERROR use of unstable + override1: _, + override2: _ + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + } = x; + + let Unstable //~ ERROR use of unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); //~ ERROR use of unstable + + let _ = x.0; //~ ERROR use of unstable + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + + let Unstable2 //~ ERROR use of unstable + (_, //~ ERROR use of unstable + _, + _) + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + = x; + let Unstable2 //~ ERROR use of unstable + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + inherit: 1, + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + override1: 2, + override2: 3, //~ ERROR use of unstable + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + let _ = x.override1; + let _ = x.override2; //~ ERROR use of unstable + + let Deprecated { + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + inherit: _, + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + override1: _, + override2: _ //~ ERROR use of unstable + } = x; + + let Deprecated + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + + let _ = x.0; + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + let _ = x.1; + let _ = x.2; //~ ERROR use of unstable + + let Deprecated2 + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + (_, + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + _, + _) //~ ERROR use of unstable + = x; + let Deprecated2 + //~^ ERROR use of deprecated item + //~^^ ERROR use of unstable + // the patterns are all fine: + (..) = x; + } +} + +mod this_crate { + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable { + inherit: u8, + #[unstable(feature = "test_feature")] + override1: u8, + #[deprecated(since = "1.0.0")] + #[unstable(feature = "test_feature")] + override2: u8, + } + + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] u8); + + #[unstable(feature = "test_feature")] + struct Unstable { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[deprecated(since = "1.0.0")] + #[unstable(feature = "test_feature")] + override2: u8, + } + + #[unstable(feature = "test_feature")] + struct Unstable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] u8); + + #[unstable(feature = "test_feature")] + #[deprecated(feature = "rust1", since = "1.0.0")] + struct Deprecated { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[unstable(feature = "test_feature")] + override2: u8, + } + + #[unstable(feature = "test_feature")] + #[deprecated(feature = "rust1", since = "1.0.0")] + struct Deprecated2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "test_feature")] u8); + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated item + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated item + + let Stable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated item + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated item + + let Stable2(_, + _, + _) + //~^ ERROR use of deprecated item + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated item + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated item + + let Unstable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated item + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated item + + let Unstable2 + (_, + _, + _) + //~^ ERROR use of deprecated item + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + //~^ ERROR use of deprecated item + inherit: 1, + //~^ ERROR use of deprecated item + override1: 2, + override2: 3, + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated item + let _ = x.override1; + let _ = x.override2; + + let Deprecated { + //~^ ERROR use of deprecated item + inherit: _, + //~^ ERROR use of deprecated item + override1: _, + override2: _ + } = x; + + let Deprecated + //~^ ERROR use of deprecated item + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated item + + let _ = x.0; + //~^ ERROR use of deprecated item + let _ = x.1; + let _ = x.2; + + let Deprecated2 + //~^ ERROR use of deprecated item + (_, + //~^ ERROR use of deprecated item + _, + _) + = x; + let Deprecated2 + //~^ ERROR use of deprecated item + // the patterns are all fine: + (..) = x; + } +} + +fn main() {} diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 88f2cbdea6..391b49e106 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -24,73 +24,132 @@ extern crate lint_stability; mod cross_crate { extern crate stability_cfg1; - extern crate stability_cfg2; //~ WARNING: use of unstable library feature + extern crate stability_cfg2; //~ ERROR use of unstable library feature use lint_stability::*; fn test() { + type Foo = MethodTester; let foo = MethodTester; deprecated(); //~ ERROR use of deprecated item foo.method_deprecated(); //~ ERROR use of deprecated item + Foo::method_deprecated(&foo); //~ ERROR use of deprecated item + ::method_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item deprecated_text(); //~ ERROR use of deprecated item: text foo.method_deprecated_text(); //~ ERROR use of deprecated item: text + Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text deprecated_unstable(); //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature foo.method_deprecated_unstable(); //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature + ::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature deprecated_unstable_text(); //~ ERROR use of deprecated item: text - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + ::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + + unstable(); //~ ERROR use of unstable library feature + foo.method_unstable(); //~ ERROR use of unstable library feature + Foo::method_unstable(&foo); //~ ERROR use of unstable library feature + ::method_unstable(&foo); //~ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature - unstable(); //~ WARNING use of unstable library feature - foo.method_unstable(); //~ WARNING use of unstable library feature - foo.trait_unstable(); //~ WARNING use of unstable library feature - - unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text - foo.method_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text - foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text + unstable_text(); + //~^ ERROR use of unstable library feature 'test_feature': text + foo.method_unstable_text(); + //~^ ERROR use of unstable library feature 'test_feature': text + Foo::method_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text + ::method_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'test_feature': text + Trait::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text stable(); foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); stable_text(); foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item let _ = DeprecatedUnstableStruct { i: 0 }; //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature - let _ = UnstableStruct { i: 0 }; //~ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable library feature let _ = StableStruct { i: 0 }; let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item let _ = DeprecatedUnstableUnitStruct; //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature - let _ = UnstableUnitStruct; //~ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + let _ = UnstableUnitStruct; //~ ERROR use of unstable library feature let _ = StableUnitStruct; let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item let _ = Enum::DeprecatedUnstableVariant; //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature - let _ = Enum::UnstableVariant; //~ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + let _ = Enum::UnstableVariant; //~ ERROR use of unstable library feature let _ = Enum::StableVariant; let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item let _ = DeprecatedUnstableTupleStruct (1); //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature - let _ = UnstableTupleStruct (1); //~ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + let _ = UnstableTupleStruct (1); //~ ERROR use of unstable library feature let _ = StableTupleStruct (1); // At the moment, the lint checker only checks stability in @@ -100,65 +159,97 @@ mod cross_crate { // on macros themselves are not yet linted. macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text macro_test_arg!(deprecated_unstable_text()); //~ ERROR use of deprecated item: text - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text } - fn test_method_param(foo: F) { + fn test_method_param(foo: Foo) { foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item + //~^ ERROR use of unstable library feature foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - //~^ WARNING use of unstable library feature - foo.trait_unstable(); //~ WARNING use of unstable library feature - foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text + //~^ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'test_feature': text + Trait::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'test_feature': text foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); } fn test_method_object(foo: &Trait) { foo.trait_deprecated(); //~ ERROR use of deprecated item foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item - //~^ WARNING use of unstable library feature + //~^ ERROR use of unstable library feature foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text - //~^ WARNING use of unstable library feature - foo.trait_unstable(); //~ WARNING use of unstable library feature - foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text + //~^ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'test_feature': text foo.trait_stable(); } struct S; - impl UnstableTrait for S { } //~ WARNING use of unstable library feature + impl UnstableTrait for S { } //~ ERROR use of unstable library feature - trait LocalTrait : UnstableTrait { } //~ WARNING use of unstable library feature + trait LocalTrait : UnstableTrait { } //~ ERROR use of unstable library feature impl Trait for S { fn trait_stable(&self) {} - fn trait_unstable(&self) {} //~ WARNING use of unstable library feature + fn trait_unstable(&self) {} //~ ERROR use of unstable library feature } } mod inheritance { - extern crate inherited_stability; //~ WARNING: use of unstable library feature - use self::inherited_stability::*; //~ WARNING: use of unstable library feature + extern crate inherited_stability; //~ ERROR use of unstable library feature + use self::inherited_stability::*; //~ ERROR use of unstable library feature fn test_inheritance() { - unstable(); //~ WARNING use of unstable library feature + unstable(); //~ ERROR use of unstable library feature stable(); - stable_mod::unstable(); //~ WARNING use of unstable library feature + stable_mod::unstable(); //~ ERROR use of unstable library feature stable_mod::stable(); unstable_mod::deprecated(); //~ ERROR use of deprecated item - unstable_mod::unstable(); //~ WARNING use of unstable library feature + unstable_mod::unstable(); //~ ERROR use of unstable library feature - let _ = Unstable::UnstableVariant; //~ WARNING use of unstable library feature + let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature let _ = Unstable::StableVariant; let x: usize = 0; - x.unstable(); //~ WARNING use of unstable library feature + x.unstable(); //~ ERROR use of unstable library feature x.stable(); } } @@ -226,11 +317,17 @@ mod this_crate { #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] - pub struct DeprecatedStruct { i: isize } + pub struct DeprecatedStruct { + #[stable(feature = "test_feature", since = "1.0.0")] i: isize + } #[unstable(feature = "test_feature")] - pub struct UnstableStruct { i: isize } + pub struct UnstableStruct { + #[stable(feature = "test_feature", since = "1.0.0")] i: isize + } #[stable(feature = "rust1", since = "1.0.0")] - pub struct StableStruct { i: isize } + pub struct StableStruct { + #[stable(feature = "test_feature", since = "1.0.0")] i: isize + } #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] @@ -264,31 +361,62 @@ mod this_crate { // errors, because other stability attributes now have meaning // only *across* crates, not within a single crate. + type Foo = MethodTester; let foo = MethodTester; deprecated(); //~ ERROR use of deprecated item foo.method_deprecated(); //~ ERROR use of deprecated item + Foo::method_deprecated(&foo); //~ ERROR use of deprecated item + ::method_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item deprecated_text(); //~ ERROR use of deprecated item: text foo.method_deprecated_text(); //~ ERROR use of deprecated item: text + Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text unstable(); foo.method_unstable(); + Foo::method_unstable(&foo); + ::method_unstable(&foo); foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); unstable_text(); foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + ::method_unstable_text(&foo); foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); stable(); foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); stable_text(); foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item let _ = UnstableStruct { i: 0 }; @@ -307,12 +435,27 @@ mod this_crate { let _ = StableTupleStruct (1); } - fn test_method_param(foo: F) { + fn test_method_param(foo: Foo) { foo.trait_deprecated(); //~ ERROR use of deprecated item + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item + ::trait_deprecated(&foo); //~ ERROR use of deprecated item foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); } fn test_method_object(foo: &Trait) { diff --git a/src/test/compile-fail/lint-stability3.rs b/src/test/compile-fail/lint-stability3.rs index 88a93134b4..44a36f215f 100644 --- a/src/test/compile-fail/lint-stability3.rs +++ b/src/test/compile-fail/lint-stability3.rs @@ -22,4 +22,3 @@ use lint_stability::*; fn main() { macro_test_arg_nested!(deprecated_text); } - diff --git a/src/test/compile-fail/lint-type-limits.rs b/src/test/compile-fail/lint-type-limits.rs index c00bd2adaa..798dc112b0 100644 --- a/src/test/compile-fail/lint-type-limits.rs +++ b/src/test/compile-fail/lint-type-limits.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(negate_unsigned)] #![allow(dead_code)] +#![feature(negate_unsigned)] // compile-flags: -D unused-comparisons fn main() { } @@ -50,12 +52,12 @@ fn qux() { } fn quy() { - let i = -23_usize; //~ WARNING negation of unsigned int literal may be unintentional + let i = -23_us; //~ WARNING negation of unsigned int literal may be unintentional //~^ WARNING unused variable } fn quz() { - let i = 23_usize; + let i = 23_us; let j = -i; //~ WARNING negation of unsigned int variable may be unintentional //~^ WARNING unused variable } diff --git a/src/test/compile-fail/lint-unsafe-code.rs b/src/test/compile-fail/lint-unsafe-code.rs new file mode 100644 index 0000000000..8440cf3a88 --- /dev/null +++ b/src/test/compile-fail/lint-unsafe-code.rs @@ -0,0 +1,102 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused_unsafe)] +#![allow(dead_code)] +#![deny(unsafe_code)] + +use std::marker::PhantomFn; + +struct Bar; +struct Bar2; +struct Bar3; + +#[allow(unsafe_code)] +mod allowed_unsafe { + use std::marker::PhantomFn; + fn allowed() { unsafe {} } + unsafe fn also_allowed() {} + unsafe trait AllowedUnsafe : PhantomFn {} + unsafe impl AllowedUnsafe for super::Bar {} +} + +macro_rules! unsafe_in_macro { + () => { + unsafe {} //~ ERROR: usage of an `unsafe` block + } +} + +unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function +unsafe trait Foo : PhantomFn {} //~ ERROR: declaration of an `unsafe` trait +unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait + +trait Baz { + unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl Baz for Bar { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + + +#[allow(unsafe_code)] +trait A { + unsafe fn allowed_unsafe(&self); + unsafe fn allowed_unsafe_provided(&self) {} +} + +#[allow(unsafe_code)] +impl Baz for Bar2 { + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} +} + +impl Baz for Bar3 { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +#[allow(unsafe_code)] +unsafe trait B { + fn dummy(&self) {} +} + +trait C { + #[allow(unsafe_code)] + unsafe fn baz(&self); + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar2 { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +trait D { + #[allow(unsafe_code)] + unsafe fn unsafe_provided(&self) {} +} + +impl D for Bar {} + +fn main() { + unsafe {} //~ ERROR: usage of an `unsafe` block + + unsafe_in_macro!() +} diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs index ada0cd2bc9..854c51d076 100644 --- a/src/test/compile-fail/lint-unused-extern-crate.rs +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:lint-unused-extern-crate.rs +// aux-build:lint_unused_extern_crate.rs #![deny(unused_extern_crates)] #![allow(unused_variables)] @@ -19,12 +19,12 @@ extern crate libc; //~ ERROR: unused extern crate -extern crate "collections" as collecs; // no error, it is used +extern crate collections as collecs; // no error, it is used extern crate rand; // no error, the use marks it as used // even if imported objects aren't used -extern crate "lint-unused-extern-crate" as other; // no error, the use * marks it as used +extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used #[allow(unused_imports)] use rand::isaac::IsaacRng; diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs index a4f46cbd18..517be0eb8a 100644 --- a/src/test/compile-fail/lint-uppercase-variables.rs +++ b/src/test/compile-fail/lint-uppercase-variables.rs @@ -40,4 +40,3 @@ fn main() { let _ = Something { X: 0 }; } - diff --git a/src/test/compile-fail/liveness-issue-2163.rs b/src/test/compile-fail/liveness-issue-2163.rs index 69bceec8c3..7c94e33b47 100644 --- a/src/test/compile-fail/liveness-issue-2163.rs +++ b/src/test/compile-fail/liveness-issue-2163.rs @@ -13,6 +13,6 @@ use std::vec::Vec; fn main() { let a: Vec = Vec::new(); a.iter().all(|_| -> bool { - //~^ ERROR mismatched types + //~^ ERROR not all control paths return a value }); } diff --git a/src/test/compile-fail/liveness-return-last-stmt-semi.rs b/src/test/compile-fail/liveness-return-last-stmt-semi.rs index 57252dd58d..a4eb1630af 100644 --- a/src/test/compile-fail/liveness-return-last-stmt-semi.rs +++ b/src/test/compile-fail/liveness-return-last-stmt-semi.rs @@ -10,7 +10,7 @@ // // regression test for #8005 -macro_rules! test { () => { fn foo() -> i32 { 1i32; } } } +macro_rules! test { () => { fn foo() -> i32 { 1; } } } //~^ ERROR not all control paths return a value //~^^ HELP consider removing this semicolon diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index ac4b8a5f30..0fee48a8c6 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -10,7 +10,7 @@ #![deny(unused_variables)] #![deny(unused_assignments)] -#![allow(dead_code, non_camel_case_types)] +#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)] fn f1(x: isize) { //~^ ERROR unused variable: `x` diff --git a/src/test/compile-fail/liveness-use-after-move.rs b/src/test/compile-fail/liveness-use-after-move.rs index 985eb1cd7b..6fcab38003 100644 --- a/src/test/compile-fail/liveness-use-after-move.rs +++ b/src/test/compile-fail/liveness-use-after-move.rs @@ -11,7 +11,7 @@ #![feature(box_syntax)] fn main() { - let x = box 5; + let x: Box<_> = box 5; let y = x; println!("{}", *x); //~ ERROR use of moved value: `*x` y.clone(); diff --git a/src/test/compile-fail/loop-labeled-break-value.rs b/src/test/compile-fail/loop-labeled-break-value.rs new file mode 100644 index 0000000000..e1ae3ae464 --- /dev/null +++ b/src/test/compile-fail/loop-labeled-break-value.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + loop { + let _: i32 = loop { break }; //~ ERROR mismatched types + } + loop { + let _: i32 = 'inner: loop { break 'inner }; //~ ERROR mismatched types + } + loop { + let _: i32 = 'inner: loop { loop { break 'inner } }; //~ ERROR mismatched types + } +} diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs index e76eaea365..abf0ed420e 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -29,4 +29,3 @@ fn main() { //~^^ ERROR unresolved name `a::bar` b::bar(); } - diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/compile-fail/macro-no-implicit-reexport.rs index 13dbab12b7..e8d9f444ce 100644 --- a/src/test/compile-fail/macro-no-implicit-reexport.rs +++ b/src/test/compile-fail/macro-no-implicit-reexport.rs @@ -16,5 +16,5 @@ extern crate macro_non_reexport_2; fn main() { - assert_eq!(reexported!(), 3_usize); //~ ERROR macro undefined + assert_eq!(reexported!(), 3); //~ ERROR macro undefined } diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs index cff01f36f3..0469a9d1cc 100644 --- a/src/test/compile-fail/macro-outer-attributes.rs +++ b/src/test/compile-fail/macro-outer-attributes.rs @@ -28,4 +28,3 @@ fn main() { a::bar(); //~ ERROR unresolved name `a::bar` b::bar(); } - diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs index dc8f4fadc7..26de51a7cf 100644 --- a/src/test/compile-fail/macro-reexport-not-locally-visible.rs +++ b/src/test/compile-fail/macro-reexport-not-locally-visible.rs @@ -18,5 +18,5 @@ extern crate macro_reexport_1; fn main() { - assert_eq!(reexported!(), 3_usize); //~ ERROR macro undefined + assert_eq!(reexported!(), 3); //~ ERROR macro undefined } diff --git a/src/test/compile-fail/malformed-derive-entry.rs b/src/test/compile-fail/malformed-derive-entry.rs new file mode 100644 index 0000000000..62dbc21495 --- /dev/null +++ b/src/test/compile-fail/malformed-derive-entry.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Copy(Bad))] +//~^ ERROR malformed `derive` entry +struct Test1; + +#[derive(Copy="bad")] +//~^ ERROR malformed `derive` entry +struct Test2; + +#[derive()] +//~^ WARNING empty trait list +struct Test3; + +#[derive] +//~^ WARNING empty trait list +struct Test4; diff --git a/src/test/compile-fail/malformed-plugin-1.rs b/src/test/compile-fail/malformed-plugin-1.rs index 254a797ef1..214a5e5e3e 100644 --- a/src/test/compile-fail/malformed-plugin-1.rs +++ b/src/test/compile-fail/malformed-plugin-1.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(plugin)] #![plugin] //~ ERROR malformed plugin attribute fn main() {} diff --git a/src/test/compile-fail/malformed-plugin-2.rs b/src/test/compile-fail/malformed-plugin-2.rs index 884087b7bc..1b112608be 100644 --- a/src/test/compile-fail/malformed-plugin-2.rs +++ b/src/test/compile-fail/malformed-plugin-2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(plugin)] #![plugin="bleh"] //~ ERROR malformed plugin attribute fn main() {} diff --git a/src/test/compile-fail/malformed-plugin-3.rs b/src/test/compile-fail/malformed-plugin-3.rs index 4885bb901d..0c948831de 100644 --- a/src/test/compile-fail/malformed-plugin-3.rs +++ b/src/test/compile-fail/malformed-plugin-3.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(plugin)] #![plugin(foo="bleh")] //~ ERROR malformed plugin attribute fn main() {} diff --git a/src/test/compile-fail/manual-link-bad-form.rs b/src/test/compile-fail/manual-link-bad-form.rs index bd2a3eba0b..fc4fa838a5 100644 --- a/src/test/compile-fail/manual-link-bad-form.rs +++ b/src/test/compile-fail/manual-link-bad-form.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-l :static +// compile-flags:-l static= // error-pattern: empty library name given via `-l` fn main() { } - - diff --git a/src/test/compile-fail/manual-link-bad-kind.rs b/src/test/compile-fail/manual-link-bad-kind.rs index 4614440dda..e9cbdb0994 100644 --- a/src/test/compile-fail/manual-link-bad-kind.rs +++ b/src/test/compile-fail/manual-link-bad-kind.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-l foo:bar +// compile-flags:-l bar=foo // error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static fn main() { } - diff --git a/src/test/compile-fail/manual-link-bad-search-path.rs b/src/test/compile-fail/manual-link-bad-search-path.rs new file mode 100644 index 0000000000..2bf61cbe24 --- /dev/null +++ b/src/test/compile-fail/manual-link-bad-search-path.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-L native= +// error-pattern: empty search path given via `-L` + +fn main() { +} diff --git a/src/test/compile-fail/manual-link-framework.rs b/src/test/compile-fail/manual-link-framework.rs index 96cc35049e..97176a533d 100644 --- a/src/test/compile-fail/manual-link-framework.rs +++ b/src/test/compile-fail/manual-link-framework.rs @@ -10,7 +10,7 @@ // ignore-macos // ignore-ios -// compile-flags:-l foo:framework +// compile-flags:-l framework=foo // error-pattern: native frameworks are only available on OSX targets fn main() { diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index 6e8719eeac..e298a0f62c 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -26,6 +26,7 @@ impl Map for HashMap {} fn main() { let x: Box> = box HashMap::new(); let x: Box> = x; - let y: Box> = box x; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let y: Box> = Box::new(x); //~^ ERROR the trait `Map` is not implemented } diff --git a/src/test/compile-fail/lint-unsafe-block.rs b/src/test/compile-fail/match-ref-ice.rs similarity index 50% rename from src/test/compile-fail/lint-unsafe-block.rs rename to src/test/compile-fail/match-ref-ice.rs index 56d2b2cd6c..042ec95f7e 100644 --- a/src/test/compile-fail/lint-unsafe-block.rs +++ b/src/test/compile-fail/match-ref-ice.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,21 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unused_unsafe)] -#![allow(dead_code)] -#![deny(unsafe_blocks)] -unsafe fn allowed() {} +#![feature(slice_patterns)] -#[allow(unsafe_blocks)] fn also_allowed() { unsafe {} } - -macro_rules! unsafe_in_macro { - () => { - unsafe {} //~ ERROR: usage of an `unsafe` block - } -} +// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose +// arity is always 0, an ICE occurs. +// +// Related issue: #23009 fn main() { - unsafe {} //~ ERROR: usage of an `unsafe` block + let homura = [1, 2, 3]; - unsafe_in_macro!() + match homura { + [1, ref madoka, 3] => (), + [1, 2, 3] => (), //~ ERROR unreachable pattern + [_, _, _] => (), + } } diff --git a/src/test/compile-fail/trait-impl-2.rs b/src/test/compile-fail/match-ref-mut-invariance.rs similarity index 53% rename from src/test/compile-fail/trait-impl-2.rs rename to src/test/compile-fail/match-ref-mut-invariance.rs index 303e3d9374..c2b54a972b 100644 --- a/src/test/compile-fail/trait-impl-2.rs +++ b/src/test/compile-fail/match-ref-mut-invariance.rs @@ -8,16 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test calling methods on an impl for a bare trait. This test checks trait impls -// must be in the same module as the trait. +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `match`. -mod Foo { - trait T {} -} - -mod Bar { - impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same - fn foo(&self) {} +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + match self.0 { ref mut x => x } //~ ERROR mismatched types } } diff --git a/src/test/compile-fail/match-ref-mut-let-invariance.rs b/src/test/compile-fail/match-ref-mut-let-invariance.rs new file mode 100644 index 0000000000..ea16c61dfd --- /dev/null +++ b/src/test/compile-fail/match-ref-mut-let-invariance.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `let`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + let ref mut x = self.0; + x //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/src/test/compile-fail/match-vec-fixed.rs b/src/test/compile-fail/match-vec-fixed.rs index e778dd18e6..60d0c24bb3 100644 --- a/src/test/compile-fail/match-vec-fixed.rs +++ b/src/test/compile-fail/match-vec-fixed.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn a() { let v = [1, 2, 3]; match v { diff --git a/src/test/compile-fail/match-vec-mismatch-2.rs b/src/test/compile-fail/match-vec-mismatch-2.rs index a4abdf3ddf..0bbba88612 100644 --- a/src/test/compile-fail/match-vec-mismatch-2.rs +++ b/src/test/compile-fail/match-vec-mismatch-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { match () { [()] => { } diff --git a/src/test/compile-fail/match-vec-mismatch.rs b/src/test/compile-fail/match-vec-mismatch.rs index edbdc77f03..ef75213d34 100644 --- a/src/test/compile-fail/match-vec-mismatch.rs +++ b/src/test/compile-fail/match-vec-mismatch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn main() { match "foo".to_string() { ['f', 'o', ..] => {} //~ ERROR mismatched types diff --git a/src/test/compile-fail/match-vec-unreachable.rs b/src/test/compile-fail/match-vec-unreachable.rs index 2c63438cbf..48b70b4bda 100644 --- a/src/test/compile-fail/match-vec-unreachable.rs +++ b/src/test/compile-fail/match-vec-unreachable.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] fn main() { let x: Vec<(isize, isize)> = Vec::new(); diff --git a/src/test/compile-fail/method-ambig-two-traits-cross-crate.rs b/src/test/compile-fail/method-ambig-two-traits-cross-crate.rs index 981c4c6f40..c1d4551fd9 100644 --- a/src/test/compile-fail/method-ambig-two-traits-cross-crate.rs +++ b/src/test/compile-fail/method-ambig-two-traits-cross-crate.rs @@ -19,4 +19,3 @@ trait me2 { } impl me2 for usize { fn me(&self) -> usize { *self } } fn main() { 1_usize.me(); } //~ ERROR E0034 - diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs index f474049265..c9ef2df8e1 100644 --- a/src/test/compile-fail/method-macro-backtrace.rs +++ b/src/test/compile-fail/method-macro-backtrace.rs @@ -29,7 +29,7 @@ impl S { // Cause an error. It shouldn't have any macro backtrace frames. fn bar(&self) { } - fn bar(&self) { } //~ ERROR duplicate definition + fn bar(&self) { } //~ ERROR duplicate method } fn main() { } diff --git a/src/test/compile-fail/method-missing-call.rs b/src/test/compile-fail/method-missing-call.rs index 6616dcc8e1..b13d4250ee 100644 --- a/src/test/compile-fail/method-missing-call.rs +++ b/src/test/compile-fail/method-missing-call.rs @@ -40,4 +40,3 @@ fn main() { .filter_map; //~ ERROR attempted to take value of method `filter_map` on type //~^ HELP maybe a `()` to call it is missing } - diff --git a/src/test/compile-fail/method-self-arg-1.rs b/src/test/compile-fail/method-self-arg-1.rs index 7b6868af80..57a96bb9a2 100644 --- a/src/test/compile-fail/method-self-arg-1.rs +++ b/src/test/compile-fail/method-self-arg-1.rs @@ -23,9 +23,9 @@ fn main() { //~| found `Foo` //~| expected &-ptr //~| found struct `Foo` - Foo::bar(&42i32); //~ ERROR mismatched types + Foo::bar(&42); //~ ERROR mismatched types //~| expected `&Foo` - //~| found `&i32` + //~| found `&_` //~| expected struct `Foo` - //~| found i32 + //~| found integral variable } diff --git a/src/test/compile-fail/method-suggestion-no-duplication.rs b/src/test/compile-fail/method-suggestion-no-duplication.rs index e807d2b944..1d0c4254ed 100644 --- a/src/test/compile-fail/method-suggestion-no-duplication.rs +++ b/src/test/compile-fail/method-suggestion-no-duplication.rs @@ -19,6 +19,4 @@ fn main() { //~^ ERROR does not implement any method //~^^ HELP #1: `core::slice::SliceExt` //~^^^ HELP #2: `core::str::StrExt` - //~^^^^ HELP #3: `collections::slice::SliceExt` - //~^^^^^ HELP #4: `collections::str::StrExt` } diff --git a/src/test/compile-fail/move-in-guard-1.rs b/src/test/compile-fail/move-in-guard-1.rs new file mode 100644 index 0000000000..068bfa3cd7 --- /dev/null +++ b/src/test/compile-fail/move-in-guard-1.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] + +pub fn main() { + let x: Box<_> = box 1; + + let v = (1, 2); + + match v { + (1, _) if take(x) => (), + (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/src/test/compile-fail/move-in-guard-2.rs b/src/test/compile-fail/move-in-guard-2.rs new file mode 100644 index 0000000000..984963b2f8 --- /dev/null +++ b/src/test/compile-fail/move-in-guard-2.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] + +pub fn main() { + let x: Box<_> = box 1; + + let v = (1, 2); + + match v { + (1, _) | + (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/src/test/compile-fail/move-out-of-tuple-field.rs b/src/test/compile-fail/move-out-of-tuple-field.rs index 7e3a85569d..b739366671 100644 --- a/src/test/compile-fail/move-out-of-tuple-field.rs +++ b/src/test/compile-fail/move-out-of-tuple-field.rs @@ -13,7 +13,7 @@ struct Foo(Box); fn main() { - let x = (box 1,); + let x: (Box<_>,) = (box 1,); let y = x.0; let z = x.0; //~ ERROR use of moved value: `x.0` diff --git a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs index f410541f0b..5af326b429 100644 --- a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs +++ b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs @@ -12,7 +12,6 @@ // bound must be noncopyable. For details see // http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/ -#![feature(box_syntax)] #![feature(unboxed_closures)] struct R<'a> { @@ -41,7 +40,8 @@ fn innocent_looking_victim() { } fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { - let mut r = R {c: box f}; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let mut r = R {c: Box::new(f)}; f(&mut r, false) //~ ERROR use of moved value } diff --git a/src/test/compile-fail/mut-cross-borrowing.rs b/src/test/compile-fail/mut-cross-borrowing.rs index 2cf6e67a90..73982fa281 100644 --- a/src/test/compile-fail/mut-cross-borrowing.rs +++ b/src/test/compile-fail/mut-cross-borrowing.rs @@ -13,7 +13,6 @@ fn f(_: &mut isize) {} fn main() { - let mut x = box 3; + let mut x: Box<_> = box 3; f(x) //~ ERROR mismatched types } - diff --git a/src/test/compile-fail/mut-pattern-mismatched.rs b/src/test/compile-fail/mut-pattern-mismatched.rs index 6de69a9adb..9eb24c8196 100644 --- a/src/test/compile-fail/mut-pattern-mismatched.rs +++ b/src/test/compile-fail/mut-pattern-mismatched.rs @@ -9,21 +9,21 @@ // except according to those terms. fn main() { - let foo = &mut 1i32; + let foo = &mut 1; // (separate lines to ensure the spans are accurate) let &_ //~ ERROR mismatched types - //~| expected `&mut i32` + //~| expected `&mut _` //~| found `&_` //~| values differ in mutability = foo; let &mut _ = foo; - let bar = &1i32; + let bar = &1; let &_ = bar; let &mut _ //~ ERROR mismatched types - //~| expected `&i32` + //~| expected `&_` //~| found `&mut _` //~| values differ in mutability = bar; diff --git a/src/test/compile-fail/mutable-class-fields-2.rs b/src/test/compile-fail/mutable-class-fields-2.rs index b6744d4b33..46af3a862c 100644 --- a/src/test/compile-fail/mutable-class-fields-2.rs +++ b/src/test/compile-fail/mutable-class-fields-2.rs @@ -29,6 +29,6 @@ fn cat(in_x : usize, in_y : isize) -> cat { } fn main() { - let nyan : cat = cat(52_usize, 99); + let nyan : cat = cat(52, 99); nyan.eat(); } diff --git a/src/test/compile-fail/mutable-class-fields.rs b/src/test/compile-fail/mutable-class-fields.rs index 94b1047f85..c163dc2b4d 100644 --- a/src/test/compile-fail/mutable-class-fields.rs +++ b/src/test/compile-fail/mutable-class-fields.rs @@ -21,6 +21,6 @@ fn cat(in_x : usize, in_y : isize) -> cat { } fn main() { - let nyan : cat = cat(52_usize, 99); + let nyan : cat = cat(52, 99); nyan.how_hungry = 0; //~ ERROR cannot assign } diff --git a/src/test/compile-fail/no-implicit-prelude-nested.rs b/src/test/compile-fail/no-implicit-prelude-nested.rs index 2fb097f111..526750257d 100644 --- a/src/test/compile-fail/no-implicit-prelude-nested.rs +++ b/src/test/compile-fail/no-implicit-prelude-nested.rs @@ -18,11 +18,11 @@ mod foo { mod baz { struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name @@ -30,11 +30,11 @@ mod foo { } struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name @@ -45,11 +45,11 @@ fn qux() { #[no_implicit_prelude] mod qux_inner { struct Test; - impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait - impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait + impl Add for Test {} //~ ERROR: use of undeclared trait + impl Clone for Test {} //~ ERROR: use of undeclared trait + impl Iterator for Test {} //~ ERROR: use of undeclared trait + impl ToString for Test {} //~ ERROR: use of undeclared trait + impl Writer for Test {} //~ ERROR: use of undeclared trait fn foo() { drop(2) //~ ERROR: unresolved name diff --git a/src/test/compile-fail/no-implicit-prelude.rs b/src/test/compile-fail/no-implicit-prelude.rs index c0f7bea25b..c4bcd33b93 100644 --- a/src/test/compile-fail/no-implicit-prelude.rs +++ b/src/test/compile-fail/no-implicit-prelude.rs @@ -17,11 +17,11 @@ // fail with the same error message). struct Test; -impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait -impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait +impl Add for Test {} //~ ERROR: use of undeclared trait +impl Clone for Test {} //~ ERROR: use of undeclared trait +impl Iterator for Test {} //~ ERROR: use of undeclared trait +impl ToString for Test {} //~ ERROR: use of undeclared trait +impl Writer for Test {} //~ ERROR: use of undeclared trait fn main() { drop(2) //~ ERROR: unresolved name diff --git a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs index 0212adff30..a7cabae16b 100644 --- a/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-enum-for-vec-repeat.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Note: This test is checking that we forbid a coding pattern that +// Issue #5873 explicitly wants to allow. + enum State { ST_NULL, ST_WHITESPACE } fn main() { [State::ST_NULL; (State::ST_WHITESPACE as usize)]; - //~^ ERROR expected constant integer for repeat count, found non-constant expression + //~^ ERROR expected constant integer for repeat count, but non-constant path } diff --git a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs index 14d2c8d032..59e910ec6a 100644 --- a/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs +++ b/src/test/compile-fail/non-constant-expr-for-fixed-len-vec.rs @@ -13,6 +13,7 @@ fn main() { fn bar(n: isize) { let _x: [isize; n]; - //~^ ERROR expected constant expr for array length: non-constant path in constant expr + //~^ ERROR no type for local variable + //~| ERROR array length constant evaluation error: non-constant path in constant expr } } diff --git a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs index 26528543b4..3ce206ff7f 100644 --- a/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs +++ b/src/test/compile-fail/non-constant-expr-for-vec-repeat.rs @@ -12,6 +12,7 @@ fn main() { fn bar(n: usize) { - let _x = [0; n]; //~ ERROR expected constant integer for repeat count, found variable + let _x = [0; n]; + //~^ ERROR expected constant integer for repeat count, found variable } } diff --git a/src/test/compile-fail/non-exhaustive-match-nested.rs b/src/test/compile-fail/non-exhaustive-match-nested.rs index 8f2cb61f95..ad2b8c400e 100644 --- a/src/test/compile-fail/non-exhaustive-match-nested.rs +++ b/src/test/compile-fail/non-exhaustive-match-nested.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + enum t { a(u), b } enum u { c, d } diff --git a/src/test/compile-fail/non-exhaustive-match.rs b/src/test/compile-fail/non-exhaustive-match.rs index 1dec049aed..b9749c2696 100644 --- a/src/test/compile-fail/non-exhaustive-match.rs +++ b/src/test/compile-fail/non-exhaustive-match.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + enum t { a, b, } fn main() { diff --git a/src/test/compile-fail/non-exhaustive-pattern-witness.rs b/src/test/compile-fail/non-exhaustive-pattern-witness.rs index 0eb91e0419..146265bf0e 100644 --- a/src/test/compile-fail/non-exhaustive-pattern-witness.rs +++ b/src/test/compile-fail/non-exhaustive-pattern-witness.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(advanced_slice_patterns)] +#![feature(slice_patterns)] struct Foo { first: bool, @@ -27,7 +28,7 @@ fn struct_with_a_nested_enum_and_vector() { Foo { first: true, second: None } => (), Foo { first: true, second: Some(_) } => (), Foo { first: false, second: None } => (), - Foo { first: false, second: Some([1_usize, 2_usize, 3_usize, 4_usize]) } => () + Foo { first: false, second: Some([1, 2, 3, 4]) } => () } } diff --git a/src/test/compile-fail/nonbool_static_assert.rs b/src/test/compile-fail/nonbool_static_assert.rs new file mode 100644 index 0000000000..7a7912b06f --- /dev/null +++ b/src/test/compile-fail/nonbool_static_assert.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(static_assert)] +#![allow(dead_code)] + +#[static_assert] +static E: i32 = 1; //~ ERROR can only have static_assert on a static with type `bool` + +fn main() {} diff --git a/src/test/compile-fail/object-lifetime-default-elision.rs b/src/test/compile-fail/object-lifetime-default-elision.rs index 0077d10e6c..4fba45e2a6 100644 --- a/src/test/compile-fail/object-lifetime-default-elision.rs +++ b/src/test/compile-fail/object-lifetime-default-elision.rs @@ -81,8 +81,8 @@ fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait { // which fails to type check. ss - //~^ ERROR cannot infer - //~| ERROR mismatched types + //~^ ERROR lifetime of the source pointer does not outlive lifetime bound + //~| ERROR cannot infer } fn main() { diff --git a/src/test/compile-fail/object-lifetime-default-from-box-error.rs b/src/test/compile-fail/object-lifetime-default-from-box-error.rs index 70752cbfda..7fae530984 100644 --- a/src/test/compile-fail/object-lifetime-default-from-box-error.rs +++ b/src/test/compile-fail/object-lifetime-default-from-box-error.rs @@ -25,7 +25,7 @@ fn load(ss: &mut SomeStruct) -> Box { // `Box` defaults to a `'static` bound, so this return // is illegal. - ss.r //~ ERROR mismatched types + ss.r //~ ERROR lifetime of the source pointer does not outlive lifetime bound } fn store(ss: &mut SomeStruct, b: Box) { @@ -38,7 +38,7 @@ fn store(ss: &mut SomeStruct, b: Box) { fn store1<'b>(ss: &mut SomeStruct, b: Box) { // Here we override the lifetimes explicitly, and so naturally we get an error. - ss.r = b; //~ ERROR mismatched types + ss.r = b; //~ ERROR lifetime of the source pointer does not outlive lifetime bound } fn main() { diff --git a/src/test/run-pass/coherence-cow-2.rs b/src/test/compile-fail/object-safety-by-value-self-use.rs similarity index 62% rename from src/test/run-pass/coherence-cow-2.rs rename to src/test/compile-fail/object-safety-by-value-self-use.rs index 93e507c0d6..36356cb7d5 100644 --- a/src/test/run-pass/coherence-cow-2.rs +++ b/src/test/compile-fail/object-safety-by-value-self-use.rs @@ -8,16 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// Check that while a trait with by-value self is object-safe, we +// can't actually invoke it from an object (yet...?). -// Test that it's ok for T to appear second in the self-type, as long -// as it's covered somewhere. +#![feature(rustc_attrs)] -extern crate "coherence-lib" as lib; -use lib::{Remote,Pair}; +trait Bar { + fn bar(self); +} -pub struct Cover(T); +trait Baz { + fn baz(self: Self); +} -impl Remote for Pair,T> { } +fn use_bar(t: Box) { + t.bar() //~ ERROR cannot move a value of type Bar +} fn main() { } diff --git a/src/test/compile-fail/object-safety-by-value-self.rs b/src/test/compile-fail/object-safety-by-value-self.rs index 5ebcc8516c..5a8772d614 100644 --- a/src/test/compile-fail/object-safety-by-value-self.rs +++ b/src/test/compile-fail/object-safety-by-value-self.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Check that we correctly prevent users from making trait objects -// from traits with a `fn(self)` method. +// Check that a trait with by-value self is considered object-safe. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(trivial_casts)] trait Bar { fn bar(self); @@ -19,29 +22,35 @@ trait Baz { fn baz(self: Self); } +trait Quux { + // Legal because of the where clause: + fn baz(self: Self) where Self : Sized; +} + fn make_bar(t: &T) -> &Bar { - t - //~^ ERROR `Bar` is not object-safe - //~| NOTE method `bar` has a receiver type of `Self` + t // legal } fn make_bar_explicit(t: &T) -> &Bar { - t as &Bar - //~^ ERROR `Bar` is not object-safe - //~| NOTE method `bar` has a receiver type of `Self` + t as &Bar // legal } fn make_baz(t: &T) -> &Baz { - t - //~^ ERROR `Baz` is not object-safe - //~| NOTE method `baz` has a receiver type of `Self` + t // legal } fn make_baz_explicit(t: &T) -> &Baz { - t as &Baz - //~^ ERROR `Baz` is not object-safe - //~| NOTE method `baz` has a receiver type of `Self` + t as &Baz // legal +} + +fn make_quux(t: &T) -> &Quux { + t +} + +fn make_quux_explicit(t: &T) -> &Quux { + t as &Quux } -fn main() { +#[rustc_error] +fn main() { //~ ERROR compilation successful } diff --git a/src/test/compile-fail/object-safety-generics.rs b/src/test/compile-fail/object-safety-generics.rs index 0ca706404c..fd20accfa1 100644 --- a/src/test/compile-fail/object-safety-generics.rs +++ b/src/test/compile-fail/object-safety-generics.rs @@ -9,12 +9,18 @@ // except according to those terms. // Check that we correctly prevent users from making trait objects -// from traits with generic methods. +// from traits with generic methods, unless `where Self : Sized` is +// present. trait Bar { fn bar(&self, t: T); } +trait Quux { + fn bar(&self, t: T) + where Self : Sized; +} + fn make_bar(t: &T) -> &Bar { t //~^ ERROR `Bar` is not object-safe @@ -27,5 +33,13 @@ fn make_bar_explicit(t: &T) -> &Bar { //~| NOTE method `bar` has generic type parameters } +fn make_quux(t: &T) -> &Quux { + t +} + +fn make_quux_explicit(t: &T) -> &Quux { + t as &Quux +} + fn main() { } diff --git a/src/test/compile-fail/object-safety-mentions-Self.rs b/src/test/compile-fail/object-safety-mentions-Self.rs index df0f44c139..b546774ccb 100644 --- a/src/test/compile-fail/object-safety-mentions-Self.rs +++ b/src/test/compile-fail/object-safety-mentions-Self.rs @@ -9,7 +9,8 @@ // except according to those terms. // Check that we correctly prevent users from making trait objects -// form traits that make use of `Self` in an argument or return position. +// form traits that make use of `Self` in an argument or return +// position, unless `where Self : Sized` is present.. trait Bar { fn bar(&self, x: &Self); @@ -19,6 +20,10 @@ trait Baz { fn bar(&self) -> Self; } +trait Quux { + fn get(&self, s: &Self) -> Self where Self : Sized; +} + fn make_bar(t: &T) -> &Bar { t //~^ ERROR `Bar` is not object-safe @@ -43,5 +48,13 @@ fn make_baz_explicit(t: &T) -> &Baz { //~| NOTE method `bar` references the `Self` type in its arguments or return type } +fn make_quux(t: &T) -> &Quux { + t +} + +fn make_quux_explicit(t: &T) -> &Quux { + t as &Quux +} + fn main() { } diff --git a/src/test/compile-fail/opt-in-copy.rs b/src/test/compile-fail/opt-in-copy.rs index 56f71c844a..be321b6290 100644 --- a/src/test/compile-fail/opt-in-copy.rs +++ b/src/test/compile-fail/opt-in-copy.rs @@ -16,6 +16,7 @@ struct IWantToCopyThis { impl Copy for IWantToCopyThis {} //~^ ERROR the trait `Copy` may not be implemented for this type +//~| ERROR E0277 enum CantCopyThisEither { A, @@ -28,6 +29,6 @@ enum IWantToCopyThisToo { impl Copy for IWantToCopyThisToo {} //~^ ERROR the trait `Copy` may not be implemented for this type +//~| ERROR E0277 fn main() {} - diff --git a/src/test/compile-fail/or-patter-mismatch.rs b/src/test/compile-fail/or-patter-mismatch.rs index 4b261d8988..59508d6ac9 100644 --- a/src/test/compile-fail/or-patter-mismatch.rs +++ b/src/test/compile-fail/or-patter-mismatch.rs @@ -12,4 +12,4 @@ enum blah { a(isize, isize, usize), b(isize, isize), } -fn main() { match blah::a(1, 1, 2_usize) { blah::a(_, x, y) | blah::b(x, y) => { } } } +fn main() { match blah::a(1, 1, 2) { blah::a(_, x, y) | blah::b(x, y) => { } } } diff --git a/src/test/compile-fail/overloaded-calls-bad.rs b/src/test/compile-fail/overloaded-calls-bad.rs index 61752e62ab..77ac97bc8b 100644 --- a/src/test/compile-fail/overloaded-calls-bad.rs +++ b/src/test/compile-fail/overloaded-calls-bad.rs @@ -18,13 +18,18 @@ struct S { } impl FnMut<(isize,)> for S { - type Output = isize; - extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { self.x * self.y * z } } +impl FnOnce<(isize,)> for S { + type Output = isize; + extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize { + self.call_mut((z,)) + } +} + fn main() { let mut s = S { x: 3, diff --git a/src/test/compile-fail/overloaded-calls-nontuple.rs b/src/test/compile-fail/overloaded-calls-nontuple.rs index 41ecf71461..ea47d67641 100644 --- a/src/test/compile-fail/overloaded-calls-nontuple.rs +++ b/src/test/compile-fail/overloaded-calls-nontuple.rs @@ -18,12 +18,16 @@ struct S { } impl FnMut for S { - type Output = isize; extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { self.x + self.y + z } } +impl FnOnce for S { + type Output = isize; + extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) } +} + fn main() { let mut s = S { x: 1, @@ -31,4 +35,3 @@ fn main() { }; drop(s(3)) //~ ERROR cannot use call notation } - diff --git a/src/test/compile-fail/pattern-bindings-after-at.rs b/src/test/compile-fail/pattern-bindings-after-at.rs index 8054409932..da2a97b0ca 100644 --- a/src/test/compile-fail/pattern-bindings-after-at.rs +++ b/src/test/compile-fail/pattern-bindings-after-at.rs @@ -23,4 +23,3 @@ fn main() { _ => () } } - diff --git a/src/test/compile-fail/pattern-ident-path-generics.rs b/src/test/compile-fail/pattern-ident-path-generics.rs index 58288fa484..0b7886842b 100644 --- a/src/test/compile-fail/pattern-ident-path-generics.rs +++ b/src/test/compile-fail/pattern-ident-path-generics.rs @@ -14,4 +14,3 @@ fn main() { Some(_) => {} } } - diff --git a/src/test/compile-fail/phantom-oibit.rs b/src/test/compile-fail/phantom-oibit.rs new file mode 100644 index 0000000000..c912d084da --- /dev/null +++ b/src/test/compile-fail/phantom-oibit.rs @@ -0,0 +1,41 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Ensure that OIBIT checks `T` when it encounters a `PhantomData` field, instead of checking +// the `PhantomData` type itself (which almost always implements a "default" trait +// (`impl Trait for ..`)) + +#![feature(optin_builtin_traits)] + +use std::marker::{MarkerTrait, PhantomData}; + +unsafe trait Zen: MarkerTrait {} + +unsafe impl Zen for .. {} + +unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + +struct Guard<'a, T: 'a> { + _marker: PhantomData<&'a T>, +} + +struct Nested(T); + +fn is_zen(_: T) {} + +fn not_sync(x: Guard) { + is_zen(x) //~ error: the trait `core::marker::Sync` is not implemented for the type `T` +} + +fn nested_not_sync(x: Nested>) { + is_zen(x) //~ error: the trait `core::marker::Sync` is not implemented for the type `T` +} + +fn main() {} diff --git a/src/test/compile-fail/priv_in_pub_sig_priv_mod.rs b/src/test/compile-fail/priv_in_pub_sig_priv_mod.rs new file mode 100644 index 0000000000..f589daf3f3 --- /dev/null +++ b/src/test/compile-fail/priv_in_pub_sig_priv_mod.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we properly check for private types in public signatures, even +// inside a private module (#22261). + +mod a { + struct Priv; + + pub fn expose_a() -> Priv { //~Error: private type in exported type signature + panic!(); + } + + mod b { + pub fn expose_b() -> super::Priv { //~Error: private type in exported type signature + panic!(); + } + } +} + +pub fn main() {} diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 1ae79adbad..67dccb4c93 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -27,10 +27,6 @@ mod bar { // can't publicly re-export private items pub use self::baz::{foo, bar}; - //~^ ERROR: function `bar` is private - - pub use self::private::ppriv; - //~^ ERROR: function `ppriv` is private pub struct A; impl A { @@ -61,10 +57,8 @@ mod bar { fn bar2(&self) {} } - // both of these are re-exported by `bar`, but only one should be - // validly re-exported pub fn foo() {} - fn bar() {} + pub fn bar() {} } extern { @@ -92,10 +86,6 @@ mod bar { pub fn gpub() {} fn gpriv() {} } - - mod private { - fn ppriv() {} - } } pub fn gpub() {} @@ -142,13 +132,13 @@ mod foo { ::bar::baz::foo(); //~ ERROR: function `foo` is inaccessible //~^ NOTE: module `baz` is private - ::bar::baz::bar(); //~ ERROR: function `bar` is private + ::bar::baz::bar(); //~ ERROR: function `bar` is inaccessible } fn test2() { use bar::baz::{foo, bar}; //~^ ERROR: function `foo` is inaccessible - //~^^ ERROR: function `bar` is private + //~^^ ERROR: function `bar` is inaccessible foo(); bar(); } diff --git a/src/test/compile-fail/privacy5.rs b/src/test/compile-fail/privacy5.rs index df570fd464..4ca37fc2ad 100644 --- a/src/test/compile-fail/privacy5.rs +++ b/src/test/compile-fail/privacy5.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:privacy-tuple-struct.rs -// ignore-fast +// aux-build:privacy_tuple_struct.rs -extern crate "privacy-tuple-struct" as other; +extern crate privacy_tuple_struct as other; mod a { pub struct A(()); @@ -102,30 +101,30 @@ fn xcrate() { let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor let d = other::D(4); - let other::A(()) = a; //~ ERROR: field #1 of struct `privacy-tuple-struct::A` is private + let other::A(()) = a; //~ ERROR: field #1 of struct `privacy_tuple_struct::A` is private let other::A(_) = a; match a { other::A(()) => {} } - //~^ ERROR: field #1 of struct `privacy-tuple-struct::A` is private + //~^ ERROR: field #1 of struct `privacy_tuple_struct::A` is private match a { other::A(_) => {} } let other::B(_) = b; - let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy-tuple-struct::B` is private + let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy_tuple_struct::B` is private match b { other::B(_) => {} } match b { other::B(_b) => {} } - //~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private + //~^ ERROR: field #1 of struct `privacy_tuple_struct::B` is private match b { other::B(1) => {} other::B(_) => {} } - //~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private + //~^ ERROR: field #1 of struct `privacy_tuple_struct::B` is private let other::C(_, _) = c; let other::C(_a, _) = c; - let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private - let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private + let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy_tuple_struct::C` is private + let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy_tuple_struct::C` is private match c { other::C(_, _) => {} } match c { other::C(_a, _) => {} } match c { other::C(_, _b) => {} } - //~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private + //~^ ERROR: field #2 of struct `privacy_tuple_struct::C` is private match c { other::C(_a, _b) => {} } - //~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private + //~^ ERROR: field #2 of struct `privacy_tuple_struct::C` is private let other::D(_) = d; let other::D(_d) = d; diff --git a/src/test/compile-fail/private-method.rs b/src/test/compile-fail/private-method.rs index ccbdd52a98..16510c2c8c 100644 --- a/src/test/compile-fail/private-method.rs +++ b/src/test/compile-fail/private-method.rs @@ -30,6 +30,6 @@ mod kitties { } fn main() { - let nyan : kitties::cat = kitties::cat(52_usize, 99); + let nyan : kitties::cat = kitties::cat(52, 99); nyan.nap(); } diff --git a/src/test/compile-fail/private-struct-field-cross-crate.rs b/src/test/compile-fail/private-struct-field-cross-crate.rs index 243d835d46..fb4491a637 100644 --- a/src/test/compile-fail/private-struct-field-cross-crate.rs +++ b/src/test/compile-fail/private-struct-field-cross-crate.rs @@ -13,7 +13,7 @@ extern crate cci_class; use cci_class::kitties::cat; fn main() { - let nyan : cat = cat(52_usize, 99); - assert!((nyan.meows == 52_usize)); + let nyan : cat = cat(52, 99); + assert!((nyan.meows == 52)); //~^ ERROR field `meows` of struct `cci_class::kitties::cat` is private } diff --git a/src/test/compile-fail/pub-method-macro.rs b/src/test/compile-fail/pub-method-macro.rs index aa890550f1..198fa5b9ac 100644 --- a/src/test/compile-fail/pub-method-macro.rs +++ b/src/test/compile-fail/pub-method-macro.rs @@ -20,7 +20,7 @@ mod bleh { ) } - #[derive(Copy)] + #[derive(Copy, Clone)] pub struct S; impl S { diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs index a8b6e39941..3ae61722bc 100644 --- a/src/test/compile-fail/range-1.rs +++ b/src/test/compile-fail/range-1.rs @@ -15,12 +15,13 @@ pub fn main() { let _ = 0u32..10i32; //~^ ERROR start and end of range have incompatible types - // Float => does not implement iterator. - for i in 0f32..42f32 {} - //~^ ERROR the trait `core::num::Int` is not implemented for the type `f32` + // Bool => does not implement iterator. + for i in false..true {} + //~^ ERROR the trait + //~^^ ERROR the trait // Unsized type. - let arr: &[_] = &[1u32, 2, 3]; + let arr: &[_] = &[1, 2, 3]; let range = *arr..; //~^ ERROR the trait `core::marker::Sized` is not implemented } diff --git a/src/test/compile-fail/recursion.rs b/src/test/compile-fail/recursion.rs index ffc21a5ce6..55f3b99533 100644 --- a/src/test/compile-fail/recursion.rs +++ b/src/test/compile-fail/recursion.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,10 +10,9 @@ //~^^^^^^^^^^ ERROR overflow // -// We also get a second error message at the top of file (dummy -// span). This is not helpful, but also kind of annoying to prevent, -// so for now just live with it, since we also get a second message -// that is more helpful. +// We get an error message at the top of file (dummy span). +// This is not helpful, but also kind of annoying to prevent, +// so for now just live with it. enum Nil {NilValue} struct Cons {head:isize, tail:T} @@ -28,9 +27,8 @@ impl Dot for Cons { } fn test (n:isize, i:isize, first:T, second:T) ->isize { match n { 0 => {first.dot(second)} - //~^ ERROR: reached the recursion limit during monomorphization - // Error message should be here. It should be a type error - // to instantiate `test` at a type other than T. (See #4287) + // FIXME(#4287) Error message should be here. It should be + // a type error to instantiate `test` at a type other than T. _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} } } diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs index 6cd984c071..368269999a 100644 --- a/src/test/compile-fail/recursion_limit.rs +++ b/src/test/compile-fail/recursion_limit.rs @@ -42,9 +42,5 @@ fn is_send() { } fn main() { is_send::(); //~^ ERROR overflow evaluating - //~^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate - //~^^^ NOTE required by `is_send` - //~^^^^ ERROR overflow evaluating - //~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate - //~^^^^^^ NOTE required by `is_send` + //~| NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate } diff --git a/src/test/compile-fail/reflect-assoc.rs b/src/test/compile-fail/reflect-assoc.rs new file mode 100644 index 0000000000..9cf0d252c2 --- /dev/null +++ b/src/test/compile-fail/reflect-assoc.rs @@ -0,0 +1,35 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that types that appear in assoc bindings in an object +// type are subject to the reflect check. + +use std::marker::Reflect; +use std::io::Write; + +trait Get { + type Output; + fn get(self) -> Self::Output; +} + +struct Struct(T); + +fn is_reflect() { } + +fn a() { + is_reflect::>>(); //~ ERROR not implemented +} + +fn ok_a() { + is_reflect::>>(); // OK +} + +fn main() { +} diff --git a/src/test/compile-fail/reflect-object-param.rs b/src/test/compile-fail/reflect-object-param.rs new file mode 100644 index 0000000000..9f074667fe --- /dev/null +++ b/src/test/compile-fail/reflect-object-param.rs @@ -0,0 +1,47 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that types that appear in input types in an object type are +// subject to the reflect check. + +use std::marker::Reflect; +use std::io::Write; + +trait Get { + fn get(self) -> T; +} + +struct Struct(T); + +fn is_reflect() { } + +fn a() { + is_reflect::(); //~ ERROR not implemented +} + +fn ok_a() { + is_reflect::(); // OK +} + +fn b() { + is_reflect::>>(); //~ ERROR not implemented +} + +fn ok_b() { + is_reflect::>>(); // OK +} + +fn c() { + is_reflect::>>>(); //~ ERROR not implemented +} + +fn main() { + is_reflect::>>>(); // OK +} diff --git a/src/test/compile-fail/reflect.rs b/src/test/compile-fail/reflect.rs new file mode 100644 index 0000000000..701aa5b40b --- /dev/null +++ b/src/test/compile-fail/reflect.rs @@ -0,0 +1,39 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that there is no way to get a generic type `T` to be +// considered as `Reflect` (or accessible via something that is +// considered `Reflect`) without a reflect bound, but that any +// concrete type works fine. Note that object types are tested +// separately. + +use std::marker::Reflect; +use std::io::Write; + +struct Struct(T); + +fn is_reflect() { } + +fn c() { + is_reflect::>(); //~ ERROR not implemented +} + +fn ok_c() { + is_reflect::>(); // OK +} + +fn d() { + is_reflect::<(i32, T)>(); //~ ERROR not implemented +} + +fn main() { + is_reflect::<&i32>(); // OK + is_reflect::>(); // OK +} diff --git a/src/test/compile-fail/region-bound-on-closure-outlives-call.rs b/src/test/compile-fail/region-bound-on-closure-outlives-call.rs index 9f35c636b4..b73c283fa5 100644 --- a/src/test/compile-fail/region-bound-on-closure-outlives-call.rs +++ b/src/test/compile-fail/region-bound-on-closure-outlives-call.rs @@ -13,4 +13,3 @@ fn call_rec(mut f: F) -> usize where F: FnMut(usize) -> usize { } fn main() {} - diff --git a/src/test/compile-fail/region-object-lifetime-1.rs b/src/test/compile-fail/region-object-lifetime-1.rs index 2095fb903b..1e615be9d6 100644 --- a/src/test/compile-fail/region-object-lifetime-1.rs +++ b/src/test/compile-fail/region-object-lifetime-1.rs @@ -26,4 +26,3 @@ fn borrowed_receiver_same_lifetime<'a>(x: &'a Foo) -> &'a () { #[rustc_error] fn main() {} //~ ERROR compilation successful - diff --git a/src/test/compile-fail/region-object-lifetime-2.rs b/src/test/compile-fail/region-object-lifetime-2.rs index f9bf4e257b..e011b8f569 100644 --- a/src/test/compile-fail/region-object-lifetime-2.rs +++ b/src/test/compile-fail/region-object-lifetime-2.rs @@ -21,4 +21,3 @@ fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () { } fn main() {} - diff --git a/src/test/compile-fail/region-object-lifetime-3.rs b/src/test/compile-fail/region-object-lifetime-3.rs index 097053276c..84dd97643a 100644 --- a/src/test/compile-fail/region-object-lifetime-3.rs +++ b/src/test/compile-fail/region-object-lifetime-3.rs @@ -26,4 +26,3 @@ fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () { #[rustc_error] fn main() {} //~ ERROR compilation successful - diff --git a/src/test/compile-fail/region-object-lifetime-4.rs b/src/test/compile-fail/region-object-lifetime-4.rs index fe0ff8dc3f..0a68e7f107 100644 --- a/src/test/compile-fail/region-object-lifetime-4.rs +++ b/src/test/compile-fail/region-object-lifetime-4.rs @@ -23,4 +23,3 @@ fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () { } fn main() {} - diff --git a/src/test/compile-fail/region-object-lifetime-5.rs b/src/test/compile-fail/region-object-lifetime-5.rs index f07f753d82..26aad0e33b 100644 --- a/src/test/compile-fail/region-object-lifetime-5.rs +++ b/src/test/compile-fail/region-object-lifetime-5.rs @@ -22,4 +22,3 @@ fn owned_receiver(x: Box) -> &'static () { } fn main() {} - diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs index 2da414befd..1bb2bb5a15 100644 --- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs +++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs @@ -11,32 +11,36 @@ // Test that attempts to implicitly coerce a value into an // object respect the lifetime bound on the object type. -#![feature(box_syntax)] - trait Foo : ::std::marker::MarkerTrait {} impl<'a> Foo for &'a [u8] {} +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + fn a(v: &[u8]) -> Box { - let x: Box = box v; //~ ERROR does not fulfill the required lifetime + let x: Box = Box::new(v); + //~^ ERROR cannot infer an appropriate lifetime due to conflicting x } fn b(v: &[u8]) -> Box { - box v //~ ERROR does not fulfill the required lifetime + Box::new(v) + //~^ ERROR cannot infer an appropriate lifetime due to conflicting } fn c(v: &[u8]) -> Box { // same as previous case due to RFC 599 - box v //~ ERROR does not fulfill the required lifetime + Box::new(v) + //~^ ERROR cannot infer an appropriate lifetime due to conflicting } fn d<'a,'b>(v: &'a [u8]) -> Box { - box v //~ ERROR does not fulfill the required lifetime + Box::new(v) + //~^ ERROR cannot infer an appropriate lifetime due to conflicting } fn e<'a:'b,'b>(v: &'a [u8]) -> Box { - box v // OK, thanks to 'a:'b + Box::new(v) // OK, thanks to 'a:'b } fn main() { } diff --git a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs index 9418156ffc..5db9a01c01 100644 --- a/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs +++ b/src/test/compile-fail/regionck-unboxed-closure-lifetimes.rs @@ -20,4 +20,3 @@ fn main() { f = move |a: isize, b: isize| { a + b + *c_ref }; } } - diff --git a/src/test/compile-fail/regions-addr-of-self.rs b/src/test/compile-fail/regions-addr-of-self.rs index 45e468b3ab..04ee052640 100644 --- a/src/test/compile-fail/regions-addr-of-self.rs +++ b/src/test/compile-fail/regions-addr-of-self.rs @@ -15,18 +15,18 @@ struct dog { impl dog { pub fn chase_cat(&mut self) { let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer - *p += 1_usize; + *p += 1; } pub fn chase_cat_2(&mut self) { let p: &mut usize = &mut self.cats_chased; - *p += 1_usize; + *p += 1; } } fn dog() -> dog { dog { - cats_chased: 0_usize + cats_chased: 0 } } diff --git a/src/test/compile-fail/regions-addr-of-upvar-self.rs b/src/test/compile-fail/regions-addr-of-upvar-self.rs index 8cc2dd6afc..28491f1155 100644 --- a/src/test/compile-fail/regions-addr-of-upvar-self.rs +++ b/src/test/compile-fail/regions-addr-of-upvar-self.rs @@ -18,7 +18,7 @@ impl dog { pub fn chase_cat(&mut self) { let _f = || { let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer - *p = 3_usize; + *p = 3; }; } } diff --git a/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs b/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs index 1705cfec6e..82d05c5d71 100644 --- a/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs +++ b/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:regions-bounded-method-type-parameters-cross-crate-lib.rs +// aux-build:regions_bounded_method_type_parameters_cross_crate_lib.rs // Check explicit region bounds on methods in the cross crate case. -extern crate "regions-bounded-method-type-parameters-cross-crate-lib" as lib; +extern crate regions_bounded_method_type_parameters_cross_crate_lib as lib; use lib::Inv; use lib::MaybeOwned; 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 index 979c1e997d..f80b0ffa5a 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -10,6 +10,8 @@ #![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + use std::marker::MarkerTrait; trait X : MarkerTrait {} @@ -24,48 +26,48 @@ trait Iter { fn bad1(v: T) -> Box { let item = v.into_item(); - box item //~ ERROR associated type `::Item` may not live long enough + Box::new(item) //~ ERROR associated type `::Item` may not live long enough } fn bad2(v: T) -> Box where Box : X { - let item = box v.into_item(); - box item //~ ERROR associated type `::Item` may not live long enough + let item: Box<_> = box v.into_item(); + Box::new(item) //~ ERROR associated type `::Item` may not live long enough } fn bad3<'a, T: Iter>(v: T) -> Box { let item = v.into_item(); - box item //~ ERROR associated type `::Item` may not live long enough + Box::new(item) //~ ERROR associated type `::Item` may not live long enough } fn bad4<'a, T: Iter>(v: T) -> Box where Box : X { - let item = box v.into_item(); - box item //~ ERROR associated type `::Item` may not live long enough + let item: Box<_> = box v.into_item(); + Box::new(item) //~ ERROR associated type `::Item` may not live long enough } fn ok1<'a, T: Iter>(v: T) -> Box where T::Item : 'a { let item = v.into_item(); - box item // OK, T::Item : 'a is declared + Box::new(item) // OK, T::Item : 'a is declared } fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box where T::Item : Clone { let item = Clone::clone(w); - box item // OK, T::Item : 'a is implied + Box::new(item) // OK, T::Item : 'a is implied } fn ok3<'a, T: Iter>(v: &'a T) -> Box where T::Item : Clone + 'a { let item = Clone::clone(v.as_item()); - box item // OK, T::Item : 'a was declared + Box::new(item) // OK, T::Item : 'a was declared } fn meh1<'a, T: Iter>(v: &'a T) -> Box @@ -78,8 +80,7 @@ fn meh1<'a, T: Iter>(v: &'a T) -> Box // T::Item`. But we're not that smart at present. let item = Clone::clone(v.as_item()); - box item //~ ERROR associated type `::Item` may not live + Box::new(item) //~ ERROR associated type `::Item` may not live } fn main() {} - diff --git a/src/test/compile-fail/regions-close-object-into-object-1.rs b/src/test/compile-fail/regions-close-object-into-object-1.rs index 7bbce7dad5..4c831a2b65 100644 --- a/src/test/compile-fail/regions-close-object-into-object-1.rs +++ b/src/test/compile-fail/regions-close-object-into-object-1.rs @@ -25,4 +25,3 @@ fn f<'a, T:'static, U>(v: Box+'static>) -> Box { } fn main() {} - diff --git a/src/test/compile-fail/regions-close-object-into-object-3.rs b/src/test/compile-fail/regions-close-object-into-object-3.rs index e22d0c7d0a..b723efff3c 100644 --- a/src/test/compile-fail/regions-close-object-into-object-3.rs +++ b/src/test/compile-fail/regions-close-object-into-object-3.rs @@ -24,4 +24,3 @@ fn h<'a, T, U>(v: Box+'static>) -> Box { } fn main() {} - diff --git a/src/test/compile-fail/regions-close-object-into-object-4.rs b/src/test/compile-fail/regions-close-object-into-object-4.rs index 147a575d38..9b311588bb 100644 --- a/src/test/compile-fail/regions-close-object-into-object-4.rs +++ b/src/test/compile-fail/regions-close-object-into-object-4.rs @@ -23,4 +23,3 @@ fn i<'a, T, U>(v: Box+'a>) -> Box { } fn main() {} - diff --git a/src/test/compile-fail/regions-close-object-into-object-5.rs b/src/test/compile-fail/regions-close-object-into-object-5.rs index bdc52eca2c..253132e5f0 100644 --- a/src/test/compile-fail/regions-close-object-into-object-5.rs +++ b/src/test/compile-fail/regions-close-object-into-object-5.rs @@ -24,7 +24,7 @@ impl<'a, T> X for B<'a, T> {} fn f<'a, T, U>(v: Box+'static>) -> Box { box B(&*v) as Box //~ ERROR the parameter type `T` may not live long enough + //~^ ERROR the parameter type `T` may not live long enough } fn main() {} - diff --git a/src/test/compile-fail/regions-close-over-type-parameter-1.rs b/src/test/compile-fail/regions-close-over-type-parameter-1.rs index fc18095fc8..924044647d 100644 --- a/src/test/compile-fail/regions-close-over-type-parameter-1.rs +++ b/src/test/compile-fail/regions-close-over-type-parameter-1.rs @@ -19,6 +19,7 @@ trait SomeTrait { fn get(&self) -> isize; } fn make_object1(v: A) -> Box { box v as Box //~^ ERROR the parameter type `A` may not live long enough + //~^^ ERROR the parameter type `A` may not live long enough } fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box { @@ -28,6 +29,7 @@ fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box { fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box { box v as Box //~^ ERROR the parameter type `A` may not live long enough + //~^^ ERROR the parameter type `A` may not live long enough } fn main() { } diff --git a/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs index 0f8bc6d684..10b883d4dc 100644 --- a/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs +++ b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs @@ -27,7 +27,7 @@ fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { // A outlives 'a AND 'b...but not 'c. - box v as Box //~ ERROR mismatched types + box v as Box //~ ERROR lifetime of the source pointer does not outlive } 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 index 655ac6f66c..7324d4a4a0 100644 --- a/src/test/compile-fail/regions-close-param-into-object.rs +++ b/src/test/compile-fail/regions-close-param-into-object.rs @@ -8,33 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. trait X { fn foo(&self) {} } fn p1(v: T) -> Box where T : X { - box v //~ ERROR parameter type `T` may not live long enough + Box::new(v) //~ ERROR parameter type `T` may not live long enough } fn p2(v: Box) -> Box where Box : X { - box v //~ ERROR parameter type `T` may not live long enough + Box::new(v) //~ ERROR parameter type `T` may not live long enough } fn p3<'a,T>(v: T) -> Box where T : X { - box v //~ ERROR parameter type `T` may not live long enough + Box::new(v) //~ ERROR parameter type `T` may not live long enough } fn p4<'a,T>(v: Box) -> Box where Box : X { - box v //~ ERROR parameter type `T` may not live long enough + Box::new(v) //~ ERROR parameter type `T` may not live long enough } fn main() {} - diff --git a/src/test/compile-fail/regions-creating-enums.rs b/src/test/compile-fail/regions-creating-enums.rs index 4c361427bf..ad2dc28afe 100644 --- a/src/test/compile-fail/regions-creating-enums.rs +++ b/src/test/compile-fail/regions-creating-enums.rs @@ -14,8 +14,8 @@ enum ast<'a> { } fn build() { - let x = ast::num(3_usize); - let y = ast::num(4_usize); + let x = ast::num(3); + let y = ast::num(4); let z = ast::add(&x, &y); compute(&z); } diff --git a/src/test/compile-fail/regions-nested-fns.rs b/src/test/compile-fail/regions-nested-fns.rs index 58386c319f..f114a8bc7c 100644 --- a/src/test/compile-fail/regions-nested-fns.rs +++ b/src/test/compile-fail/regions-nested-fns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. fn ignore(t: T) {} @@ -16,17 +16,17 @@ fn nested<'x>(x: &'x isize) { let y = 3; let mut ay = &y; - ignore:: FnMut(&'z isize)>>(box |z| { + ignore:: FnMut(&'z isize)>>(Box::new(|z| { ay = x; //~ ERROR cannot infer ay = &y; ay = z; - }); + })); - ignore::< Box FnMut(&'z isize) -> &'z isize>>(box |z| { + ignore::< Box FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { if false { return x; } //~ ERROR cannot infer an appropriate lifetime for automatic if false { return ay; } return z; - }); + })); } fn main() {} diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19552.rs b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs index 3401dd1bec..8e83177090 100644 --- a/src/test/compile-fail/regions-pattern-typing-issue-19552.rs +++ b/src/test/compile-fail/regions-pattern-typing-issue-19552.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(slice_patterns)] + fn assert_static(_t: T) {} fn main() { diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs index da839d7217..ae9ceb600d 100644 --- a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs +++ b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs @@ -9,8 +9,8 @@ // except according to those terms. fn main() { - let a0 = 0u8; - let f = 1u8; + let a0 = 0; + let f = 1; let mut a1 = &a0; match (&a1,) { (&ref b0,) => { diff --git a/src/test/compile-fail/regions-proc-bound-capture.rs b/src/test/compile-fail/regions-proc-bound-capture.rs index 7ea4d1c750..3c137133c9 100644 --- a/src/test/compile-fail/regions-proc-bound-capture.rs +++ b/src/test/compile-fail/regions-proc-bound-capture.rs @@ -8,17 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { // This is legal, because the region bound on `proc` // states that it captures `x`. - box move|| { *x } + Box::new(move|| { *x }) } fn static_proc(x: &isize) -> Box(isize) + 'static> { // This is illegal, because the region bound on `proc` is 'static. - box move|| { *x } //~ ERROR cannot infer + Box::new(move|| { *x }) //~ ERROR captured variable `x` does not outlive the enclosing closure } fn main() { } diff --git a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs index aa20efa5a1..1e2224eafa 100644 --- a/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs +++ b/src/test/compile-fail/regions-return-ref-to-upvar-issue-17403.rs @@ -15,7 +15,7 @@ fn main() { // Unboxed closure case { - let mut x = 0_usize; + let mut x = 0; let mut f = || &mut x; //~ ERROR cannot infer let x = f(); let y = f(); diff --git a/src/test/compile-fail/regions-steal-closure.rs b/src/test/compile-fail/regions-steal-closure.rs index 97b51fdb32..a30d8471a3 100644 --- a/src/test/compile-fail/regions-steal-closure.rs +++ b/src/test/compile-fail/regions-steal-closure.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] #![feature(unboxed_closures)] struct closure_box<'a> { @@ -20,9 +19,10 @@ fn box_it<'r>(x: Box) -> closure_box<'r> { } fn main() { - let cl_box = { + let mut cl_box = { let mut i = 3; - box_it(box || i += 1) //~ ERROR cannot infer + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough }; cl_box.cl.call_mut(()); } diff --git a/src/test/compile-fail/regions-trait-1.rs b/src/test/compile-fail/regions-trait-1.rs index b45a37d26e..01439ce5e6 100644 --- a/src/test/compile-fail/regions-trait-1.rs +++ b/src/test/compile-fail/regions-trait-1.rs @@ -34,7 +34,7 @@ fn get_v(gc: Box) -> usize { } fn main() { - let ctxt = ctxt { v: 22_usize }; + let ctxt = ctxt { v: 22 }; let hc = has_ctxt { c: &ctxt }; - assert_eq!(get_v(box hc as Box), 22_usize); + assert_eq!(get_v(box hc as Box), 22); } diff --git a/src/test/compile-fail/regions-trait-object-subtyping.rs b/src/test/compile-fail/regions-trait-object-subtyping.rs new file mode 100644 index 0000000000..f3722690ef --- /dev/null +++ b/src/test/compile-fail/regions-trait-object-subtyping.rs @@ -0,0 +1,35 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Dummy { fn dummy(&self); } + +fn foo1<'a:'b,'b>(x: &'a mut (Dummy+'a)) -> &'b mut (Dummy+'b) { + // Here, we are able to coerce + x +} + +fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) { + // Here, we are able to coerce + x +} + +fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy { + // Without knowing 'a:'b, we can't coerce + x //~ ERROR lifetime of the source pointer does not outlive + //~^ ERROR cannot infer +} + +struct Wrapper(T); +fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> { + // We can't coerce because it is packed in `Wrapper` + x //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/compile-fail/reject-specialized-drops-8142.rs b/src/test/compile-fail/reject-specialized-drops-8142.rs new file mode 100644 index 0000000000..30264c9f21 --- /dev/null +++ b/src/test/compile-fail/reject-specialized-drops-8142.rs @@ -0,0 +1,79 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue 8142: Test that Drop impls cannot be specialized beyond the +// predicates attached to the struct/enum definition itself. + +#![feature(unsafe_destructor)] + +trait Bound { fn foo(&self) { } } +struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } +struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } +struct M<'m> { x: &'m i8 } +struct N<'n> { x: &'n i8 } +struct O { x: *const To } +struct P { x: *const Tp } +struct Q { x: *const Tq } +struct R { x: *const Tr } +struct S { x: *const Ts } +struct T<'t,Ts:'t> { x: &'t Ts } +struct U; +struct V { x: *const Tva, y: *const Tvb } +struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } + +#[unsafe_destructor] +impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT + //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl. + fn drop(&mut self) { } } + +#[unsafe_destructor] +impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT + //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl. + fn drop(&mut self) { } } + +#[unsafe_destructor] +impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT + +#[unsafe_destructor] +impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT +//~^ ERROR Implementations of Drop cannot be specialized + +#[unsafe_destructor] +impl Drop for O { fn drop(&mut self) { } } // ACCEPT + +#[unsafe_destructor] +impl Drop for P { fn drop(&mut self) { } } // REJECT +//~^ ERROR Implementations of Drop cannot be specialized + +#[unsafe_destructor] +impl Drop for Q { fn drop(&mut self) { } } // REJECT +//~^ ERROR The requirement `Adds_bnd : Bound` is added only by the Drop impl. + +#[unsafe_destructor] +impl<'rbnd,Adds_rbnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT +//~^ ERROR The requirement `Adds_rbnd : 'rbnd` is added only by the Drop impl. + +#[unsafe_destructor] +impl Drop for S { fn drop(&mut self) { } } // ACCEPT + +#[unsafe_destructor] +impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT + +impl Drop for U { fn drop(&mut self) { } } // ACCEPT + +#[unsafe_destructor] +impl Drop for V { fn drop(&mut self) { } } // REJECT +//~^ERROR Implementations of Drop cannot be specialized + +#[unsafe_destructor] +impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT +//~^ERROR Implementations of Drop cannot be specialized + +pub fn main() { } diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs index 9b3e266804..1215814122 100644 --- a/src/test/compile-fail/repeat_count.rs +++ b/src/test/compile-fail/repeat_count.rs @@ -19,7 +19,7 @@ fn main() { //~| found `()` //~| expected usize //~| found () -//~| ERROR expected constant integer for repeat count, found non-constant expression +//~| ERROR expected positive integer for repeat count, found tuple let c = [0; true]; //~^ ERROR mismatched types //~| expected `usize` diff --git a/src/test/compile-fail/reserved-attr-on-macro.rs b/src/test/compile-fail/reserved-attr-on-macro.rs new file mode 100644 index 0000000000..db8f82a70e --- /dev/null +++ b/src/test/compile-fail/reserved-attr-on-macro.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[rustc_attribute_should_be_reserved] //~ ERROR attributes with the prefix `rustc_` are reserved +macro_rules! foo { + () => (()); +} + +fn main() { + foo!(); +} diff --git a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs index 8673d95de1..af3ee7f353 100644 --- a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs @@ -12,4 +12,3 @@ extern crate std; //~^ ERROR an external crate named `std` has already been imported fn main(){} - diff --git a/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs index f27b11d541..0c601a8117 100644 --- a/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-import-vs-extern-crate.rs @@ -12,4 +12,3 @@ use std::slice as std; //~ ERROR import `std` conflicts with imported crate fn main() { } - diff --git a/src/test/compile-fail/resolve-conflict-import-vs-import.rs b/src/test/compile-fail/resolve-conflict-import-vs-import.rs index beb4b74f32..10afe82f2e 100644 --- a/src/test/compile-fail/resolve-conflict-import-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-import-vs-import.rs @@ -14,4 +14,3 @@ use std::mem::transmute; fn main() { } - diff --git a/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs index 9d40196d4a..e685353592 100644 --- a/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-item-vs-extern-crate.rs @@ -12,4 +12,3 @@ fn std() {} //~ ERROR the name `std` conflicts with an external crate fn main() { } - diff --git a/src/test/compile-fail/resolve-conflict-item-vs-import.rs b/src/test/compile-fail/resolve-conflict-item-vs-import.rs index 9680091835..1edf815eca 100644 --- a/src/test/compile-fail/resolve-conflict-item-vs-import.rs +++ b/src/test/compile-fail/resolve-conflict-item-vs-import.rs @@ -15,4 +15,3 @@ fn transmute() {} fn main() { } - diff --git a/src/test/compile-fail/resolve-unknown-trait.rs b/src/test/compile-fail/resolve-unknown-trait.rs index 0d0dc0a05d..fd4dce51fc 100644 --- a/src/test/compile-fail/resolve-unknown-trait.rs +++ b/src/test/compile-fail/resolve-unknown-trait.rs @@ -10,11 +10,10 @@ trait NewTrait : SomeNonExistentTrait {} -//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` impl SomeNonExistentTrait for isize {} -//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait` +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` fn f() {} -//~^ ERROR attempt to bound type parameter with a nonexistent trait `SomeNonExistentTrait` - +//~^ ERROR use of undeclared trait name `SomeNonExistentTrait` diff --git a/src/test/compile-fail/retslot-cast.rs b/src/test/compile-fail/retslot-cast.rs new file mode 100644 index 0000000000..4ef07ecb43 --- /dev/null +++ b/src/test/compile-fail/retslot-cast.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +pub fn fail(x: Option<& (Iterator+Send)>) -> Option<&Iterator> { + // This call used to trigger an LLVM assertion because the return + // slot had type "Option<&Iterator>"* instead of + // "Option<&(Iterator+Send)>"* -- but this now yields a + // compilation error and I'm not sure how to create a comparable + // test. To ensure that this PARTICULAR failure doesn't occur + // again, though, I've left this test here, so if this ever starts + // to compile again, we can adjust the test appropriately (clearly + // it should never ICE...). -nmatsakis + inner(x) //~ ERROR mismatched types +} + +pub fn inner(x: Option<& (Iterator+Send)>) -> Option<&(Iterator+Send)> { + x +} + +#[rustc_error] +fn main() {} diff --git a/src/test/compile-fail/send-is-not-static-ensures-scoping.rs b/src/test/compile-fail/send-is-not-static-ensures-scoping.rs old mode 100755 new mode 100644 index abbcd7e459..fe03ca8353 --- a/src/test/compile-fail/send-is-not-static-ensures-scoping.rs +++ b/src/test/compile-fail/send-is-not-static-ensures-scoping.rs @@ -13,9 +13,10 @@ use std::thread; fn main() { let bad = { let x = 1; - let y = &x; + let y = &x; //~ ERROR `x` does not live long enough - thread::scoped(|| { //~ ERROR cannot infer an appropriate lifetime + thread::scoped(|| { + //~^ ERROR `y` does not live long enough let _z = y; }) }; diff --git a/src/test/compile-fail/send-is-not-static-std-sync-2.rs b/src/test/compile-fail/send-is-not-static-std-sync-2.rs new file mode 100644 index 0000000000..d9d3706586 --- /dev/null +++ b/src/test/compile-fail/send-is-not-static-std-sync-2.rs @@ -0,0 +1,46 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// basic tests to see that certain "obvious" errors are caught by +// these types no longer requiring `'static` (RFC 458) + +#![allow(dead_code)] + +use std::sync::{Mutex, RwLock, mpsc}; + +fn mutex() { + let lock = { + let x = 1; + Mutex::new(&x) //~ ERROR does not live long enough + }; + + let _dangling = *lock.lock().unwrap(); +} + +fn rwlock() { + let lock = { + let x = 1; + RwLock::new(&x) //~ ERROR does not live long enough + }; + let _dangling = *lock.read().unwrap(); +} + +fn channel() { + let (_tx, rx) = { + let x = 1; + let (tx, rx) = mpsc::channel(); + let _ = tx.send(&x); //~ ERROR does not live long enough + (tx, rx) + }; + + let _dangling = rx.recv(); +} + +fn main() {} diff --git a/src/test/compile-fail/send-is-not-static-std-sync.rs b/src/test/compile-fail/send-is-not-static-std-sync.rs new file mode 100644 index 0000000000..8ec2fe8a1e --- /dev/null +++ b/src/test/compile-fail/send-is-not-static-std-sync.rs @@ -0,0 +1,56 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// basic tests to see that certain "obvious" errors are caught by +// these types no longer requiring `'static` (RFC 458) + +#![allow(dead_code)] + +use std::sync::{Mutex, RwLock, mpsc}; + +fn mutex() { + let x = 1; + let y = Box::new(1); + let lock = Mutex::new(&x); + *lock.lock().unwrap() = &*y; + drop(y); //~ ERROR cannot move out + { + let z = 2; + *lock.lock().unwrap() = &z; //~ ERROR does not live long enough + } +} + +fn rwlock() { + let x = 1; + let y = Box::new(1); + let lock = RwLock::new(&x); + *lock.write().unwrap() = &*y; + drop(y); //~ ERROR cannot move out + { + let z = 2; + *lock.write().unwrap() = &z; //~ ERROR does not live long enough + } +} + +fn channel() { + let x = 1; + let y = Box::new(1); + let (tx, rx) = mpsc::channel(); + + tx.send(&x).unwrap(); + tx.send(&*y); + drop(y); //~ ERROR cannot move out + { + let z = 2; + tx.send(&z).unwrap(); //~ ERROR does not live long enough + } +} + +fn main() {} diff --git a/src/test/compile-fail/shadowing-in-the-same-pattern.rs b/src/test/compile-fail/shadowing-in-the-same-pattern.rs index c29534128a..e847d33241 100644 --- a/src/test/compile-fail/shadowing-in-the-same-pattern.rs +++ b/src/test/compile-fail/shadowing-in-the-same-pattern.rs @@ -15,4 +15,3 @@ fn f((a, a): (isize, isize)) {} //~ ERROR identifier `a` is bound more than once fn main() { let (a, a) = (1, 1); //~ ERROR identifier `a` is bound more than once } - diff --git a/src/test/compile-fail/shift-various-bad-types.rs b/src/test/compile-fail/shift-various-bad-types.rs index 901ae1d5e2..24b66213b3 100644 --- a/src/test/compile-fail/shift-various-bad-types.rs +++ b/src/test/compile-fail/shift-various-bad-types.rs @@ -17,19 +17,19 @@ struct Panolpy { fn foo(p: &Panolpy) { 22 >> p.char; - //~^ ERROR right-hand-side of a shift operation must have integral type + //~^ ERROR E0277 + //~| ERROR E0277 22 >> p.str; - //~^ ERROR right-hand-side of a shift operation must have integral type + //~^ ERROR E0277 + //~| ERROR E0277 22 >> p; - //~^ ERROR right-hand-side of a shift operation must have integral type + //~^ ERROR E0277 + //~| ERROR E0277 - // We could be more accepting in the case of a type not yet inferred, but not - // known to be an integer, but meh. let x; - 22 >> x; - //~^ ERROR the type of this value must be known in this context + 22 >> x; // ambiguity error winds up being suppressed 22 >> 1; // Integer literal types are OK diff --git a/src/test/compile-fail/simd-binop.rs b/src/test/compile-fail/simd-binop.rs index f028c9af46..feffe5c0b0 100644 --- a/src/test/compile-fail/simd-binop.rs +++ b/src/test/compile-fail/simd-binop.rs @@ -10,6 +10,7 @@ // ignore-tidy-linelength +#![feature(core)] use std::simd::f32x4; diff --git a/src/test/compile-fail/single-derive-attr.rs b/src/test/compile-fail/single-derive-attr.rs new file mode 100644 index 0000000000..0b1b3141f5 --- /dev/null +++ b/src/test/compile-fail/single-derive-attr.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive_Clone] +//~^ ERROR attributes of the form `#[derive_*]` are reserved +struct Test; + +pub fn main() {} diff --git a/src/test/compile-fail/single-primitive-inherent-impl.rs b/src/test/compile-fail/single-primitive-inherent-impl.rs new file mode 100644 index 0000000000..b2cfcfab78 --- /dev/null +++ b/src/test/compile-fail/single-primitive-inherent-impl.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_std)] +#![no_std] + +// OK +#[lang = "char"] +impl char {} + +impl char { +//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive +} diff --git a/src/test/compile-fail/static-array-across-crate.rs b/src/test/compile-fail/static-array-across-crate.rs new file mode 100644 index 0000000000..04a731e847 --- /dev/null +++ b/src/test/compile-fail/static-array-across-crate.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:pub_static_array.rs + +extern crate pub_static_array as array; + +use array::ARRAY; + +static X: &'static u8 = &ARRAY[0]; +//~^ ERROR: cannot refer to the interior of another static, use a constant + +pub fn main() {} diff --git a/src/test/compile-fail/static-assert.rs b/src/test/compile-fail/static-assert.rs index 349e5f4cb5..d0cfbfbbcc 100644 --- a/src/test/compile-fail/static-assert.rs +++ b/src/test/compile-fail/static-assert.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(static_assert)] #![allow(dead_code)] #[static_assert] diff --git a/src/test/compile-fail/static-assert2.rs b/src/test/compile-fail/static-assert2.rs index d5e70205e9..35f840dab0 100644 --- a/src/test/compile-fail/static-assert2.rs +++ b/src/test/compile-fail/static-assert2.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(static_assert)] #![allow(dead_code)] #[static_assert] diff --git a/src/test/compile-fail/static-region-bound.rs b/src/test/compile-fail/static-region-bound.rs index 200aa98919..eca22bfdda 100644 --- a/src/test/compile-fail/static-region-bound.rs +++ b/src/test/compile-fail/static-region-bound.rs @@ -13,7 +13,7 @@ fn f(_: T) {} fn main() { - let x = box 3; + let x: Box<_> = box 3; f(x); let x = &3; //~ ERROR borrowed value does not live long enough f(x); diff --git a/src/test/compile-fail/struct-field-privacy.rs b/src/test/compile-fail/struct-field-privacy.rs index 667e944f92..a1b6b9a744 100644 --- a/src/test/compile-fail/struct-field-privacy.rs +++ b/src/test/compile-fail/struct-field-privacy.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:struct-field-privacy.rs +// aux-build:struct_field_privacy.rs -extern crate "struct-field-privacy" as xc; +extern crate struct_field_privacy as xc; struct A { a: isize, @@ -37,11 +37,11 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B) { c.a; c.b; //~ ERROR: field `b` of struct `inner::B` is private - d.a; //~ ERROR: field `a` of struct `struct-field-privacy::A` is private + d.a; //~ ERROR: field `a` of struct `struct_field_privacy::A` is private d.b; e.a; - e.b; //~ ERROR: field `b` of struct `struct-field-privacy::B` is private + e.b; //~ ERROR: field `b` of struct `struct_field_privacy::B` is private } fn main() {} diff --git a/src/test/compile-fail/struct-variant-privacy-xc.rs b/src/test/compile-fail/struct-variant-privacy-xc.rs index c58273361a..b8be7d0cdc 100644 --- a/src/test/compile-fail/struct-variant-privacy-xc.rs +++ b/src/test/compile-fail/struct-variant-privacy-xc.rs @@ -18,4 +18,3 @@ fn f(b: struct_variant_privacy::Bar) { //~ ERROR enum `Bar` is private } fn main() {} - diff --git a/src/test/compile-fail/structure-constructor-type-mismatch.rs b/src/test/compile-fail/structure-constructor-type-mismatch.rs index c276228b18..02c4f3d5d5 100644 --- a/src/test/compile-fail/structure-constructor-type-mismatch.rs +++ b/src/test/compile-fail/structure-constructor-type-mismatch.rs @@ -26,40 +26,39 @@ fn main() { let pt = PointF { //~^ ERROR structure constructor specifies a structure of type //~| expected f32 - //~| found i32 - x: 1i32, - y: 2i32, + //~| found integral variable + x: 1, + y: 2, }; let pt2 = Point:: { //~^ ERROR structure constructor specifies a structure of type //~| expected f32 - //~| found i32 - x: 3i32, - y: 4i32, + //~| found integral variable + x: 3, + y: 4, }; let pair = PairF { //~^ ERROR structure constructor specifies a structure of type //~| expected f32 - //~| found i32 - x: 5i32, - y: 6i32, + //~| found integral variable + x: 5, + y: 6, }; let pair2 = PairF:: { //~^ ERROR structure constructor specifies a structure of type //~| expected f32 - //~| found i32 - x: 7i32, - y: 8i32, + //~| found integral variable + x: 7, + y: 8, }; let pt3 = PointF:: { //~^ ERROR wrong number of type arguments //~| ERROR structure constructor specifies a structure of type - x: 9i32, - y: 10i32, + x: 9, + y: 10, }; } - diff --git a/src/test/compile-fail/suggest-private-fields.rs b/src/test/compile-fail/suggest-private-fields.rs new file mode 100644 index 0000000000..f987257d4e --- /dev/null +++ b/src/test/compile-fail/suggest-private-fields.rs @@ -0,0 +1,36 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:struct_field_privacy.rs + +extern crate struct_field_privacy as xc; + +use xc::B; + +struct A { + pub a: u32, + b: u32, +} + +fn main () { + // external crate struct + let k = B { + aa: 20, //~ ERROR structure `struct_field_privacy::B` has no field named `aa` + //~^ HELP did you mean `a`? + bb: 20, //~ ERROR structure `struct_field_privacy::B` has no field named `bb` + }; + // local crate struct + let l = A { + aa: 20, //~ ERROR structure `A` has no field named `aa` + //~^ HELP did you mean `a`? + bb: 20, //~ ERROR structure `A` has no field named `bb` + //~^ HELP did you mean `b`? + }; +} diff --git a/src/test/compile-fail/syntaxt-default-trait-impls.rs b/src/test/compile-fail/syntaxt-default-trait-impls.rs new file mode 100644 index 0000000000..a33cd0edca --- /dev/null +++ b/src/test/compile-fail/syntaxt-default-trait-impls.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +trait MyDefaultImpl {} + +impl MyDefaultImpl for .. {} +//~^ ERROR default trait implementations are not allowed to have genercis + +fn main() {} diff --git a/src/test/compile-fail/tail-typeck.rs b/src/test/compile-fail/tail-typeck.rs index 9c1d318d58..5c1270aa0e 100644 --- a/src/test/compile-fail/tail-typeck.rs +++ b/src/test/compile-fail/tail-typeck.rs @@ -12,6 +12,6 @@ fn f() -> isize { return g(); } -fn g() -> usize { return 0_usize; } +fn g() -> usize { return 0; } fn main() { let y = f(); } diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs index fff1441409..1fd711ca4f 100644 --- a/src/test/compile-fail/trait-as-struct-constructor.rs +++ b/src/test/compile-fail/trait-as-struct-constructor.rs @@ -14,4 +14,3 @@ fn main() { TraitNotAStruct{ value: 0 }; //~^ ERROR: use of trait `TraitNotAStruct` as a struct constructor [E0159] } - diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs index 284c4fac95..217540415a 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs @@ -32,4 +32,3 @@ struct ZipIterator { } fn main() {} - diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index 448b186f6a..e126a3040e 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -15,7 +15,7 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ERROR the trait `core::marker::Sized` is not implemented + //~^ ERROR the trait `core::marker::Sized` is not implemented } fn main() { } diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs index df44e847c5..d39b7e15ed 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs @@ -25,4 +25,3 @@ fn main() { let baz: Foo = panic!(); //~^ ERROR not implemented } - diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs index 18871d0d38..d93c9bafae 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs @@ -23,4 +23,3 @@ static X: Foo = Foo { fn main() { } - diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc.rs index ded75aa1d8..5f95a7ca6e 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc.rs @@ -22,4 +22,3 @@ fn kaboom(y: Bar) {} fn main() { } - diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc1.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc1.rs index 8a9732de7f..840787022e 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc1.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-xc1.rs @@ -23,4 +23,3 @@ fn main() { //~^ ERROR not implemented let _ = bar; } - diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index 8dfdb2f205..ce0a7d3bb3 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -66,4 +66,3 @@ impl PolyTrait> for Struct { fn main() { } - diff --git a/src/test/compile-fail/trait-coercion-generic-bad.rs b/src/test/compile-fail/trait-coercion-generic-bad.rs index 1ddfc5b7cc..b25af522b2 100644 --- a/src/test/compile-fail/trait-coercion-generic-bad.rs +++ b/src/test/compile-fail/trait-coercion-generic-bad.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - struct Struct { person: &'static str } @@ -25,7 +23,8 @@ impl Trait<&'static str> for Struct { } fn main() { - let s: Box> = box Struct { person: "Fred" }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let s: Box> = Box::new(Struct { person: "Fred" }); //~^ ERROR the trait `Trait` is not implemented for the type `Struct` s.f(1); } diff --git a/src/test/compile-fail/trait-coercion-generic-regions.rs b/src/test/compile-fail/trait-coercion-generic-regions.rs index 7b426a4c03..9ba017e150 100644 --- a/src/test/compile-fail/trait-coercion-generic-regions.rs +++ b/src/test/compile-fail/trait-coercion-generic-regions.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - struct Struct { person: &'static str } @@ -27,6 +25,6 @@ impl Trait<&'static str> for Struct { fn main() { let person = "Fred".to_string(); let person: &str = &person; //~ ERROR `person` does not live long enough - let s: Box> = box Struct { person: person }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let s: Box> = Box::new(Struct { person: person }); } - diff --git a/src/test/compile-fail/trait-impl-for-module.rs b/src/test/compile-fail/trait-impl-for-module.rs index 28d20483c7..969b6398fd 100644 --- a/src/test/compile-fail/trait-impl-for-module.rs +++ b/src/test/compile-fail/trait-impl-for-module.rs @@ -14,7 +14,7 @@ mod a { trait A { } -impl A for a { //~ERROR found module name used as a type +impl A for a { //~ ERROR use of undeclared type name `a` } fn main() { diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index e621d77a65..3aec23a55b 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - -impl Option { //~ERROR inherent implementations are not allowed for types not defined in the current module +impl Option { +//~^ ERROR cannot associate methods with a type outside the crate the type is defined in pub fn foo(&self) { } } diff --git a/src/test/compile-fail/trait-safety-trait-impl-cc.rs b/src/test/compile-fail/trait-safety-trait-impl-cc.rs index 032deb2e01..6050b549b6 100644 --- a/src/test/compile-fail/trait-safety-trait-impl-cc.rs +++ b/src/test/compile-fail/trait-safety-trait-impl-cc.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:trait-safety-lib.rs +// aux-build:trait_safety_lib.rs // Check that unsafe traits require unsafe impls and that inherent // impls cannot be unsafe. -extern crate "trait-safety-lib" as lib; +extern crate trait_safety_lib as lib; struct Bar; impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration diff --git a/src/test/compile-fail/trait-test-2.rs b/src/test/compile-fail/trait-test-2.rs index d8b3176787..b09b10ffa0 100644 --- a/src/test/compile-fail/trait-test-2.rs +++ b/src/test/compile-fail/trait-test-2.rs @@ -18,4 +18,5 @@ fn main() { 10.dup::(); //~ ERROR does not take type parameters 10.blah::(); //~ ERROR incorrect number of type parameters (box 10 as Box).dup(); //~ ERROR cannot convert to a trait object + //~^ ERROR the trait `bar` is not implemented for the type `bar` } diff --git a/src/test/compile-fail/traits-assoc-type-in-supertrait-bad.rs b/src/test/compile-fail/traits-assoc-type-in-supertrait-bad.rs new file mode 100644 index 0000000000..971869ba85 --- /dev/null +++ b/src/test/compile-fail/traits-assoc-type-in-supertrait-bad.rs @@ -0,0 +1,26 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test case where an associated type is referenced from within the +// supertrait definition, and the impl makes the wrong +// associations. Issue #20220. + +use std::vec::IntoIter; + +pub trait Foo: Iterator::Key> { + type Key; +} + +impl Foo for IntoIter { //~ ERROR type mismatch + type Key = u32; +} + +fn main() { +} diff --git a/src/test/compile-fail/traits-issue-23003-overflow.rs b/src/test/compile-fail/traits-issue-23003-overflow.rs new file mode 100644 index 0000000000..ea41775f31 --- /dev/null +++ b/src/test/compile-fail/traits-issue-23003-overflow.rs @@ -0,0 +1,38 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// A variant of traits-issue-23003 in which an infinite series of +// types are required. This currently creates an overflow. This test +// is included to ensure that some controlled failure, at least, +// results -- but it might be that we should adjust the rules somewhat +// to make this legal. -nmatsakis + +use std::marker::PhantomData; + +trait Async { + type Cancel; +} + +struct Receipt { + marker: PhantomData, +} + +struct Complete { + core: Option, +} + +impl Async for Complete { + type Cancel = Receipt>>; +} + +fn foo(r: Receipt>) { } +//~^ ERROR overflow + +fn main() { } diff --git a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs index 0a5aa1b7bd..8fe1f4d237 100644 --- a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs +++ b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs @@ -33,7 +33,7 @@ where T : Convert } fn a() { - test(22_i32, std::default::Default::default()); //~ ERROR type annotations required + test(22, std::default::Default::default()); //~ ERROR type annotations required } fn main() {} diff --git a/src/test/compile-fail/traits-repeated-supertrait-ambig.rs b/src/test/compile-fail/traits-repeated-supertrait-ambig.rs new file mode 100644 index 0000000000..d61ac6f08d --- /dev/null +++ b/src/test/compile-fail/traits-repeated-supertrait-ambig.rs @@ -0,0 +1,53 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test then that when we don't give +// enough information to pick between these, no selection is made. In +// this particular case, the two choices are i64/u64 -- so when we use +// an integer literal, we wind up falling this literal back to i32. +// See also `run-pass/trait-repeated-supertrait.rs`. + +trait CompareTo { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo + CompareTo { +} + +impl CompareTo for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &CompareToInts) -> bool { + c.same_as(22) //~ ERROR `CompareTo` is not implemented +} + +fn with_trait(c: &C) -> bool { + c.same_as(22) //~ ERROR `CompareTo` is not implemented +} + +fn with_ufcs1(c: &C) -> bool { + CompareToInts::same_as(c, 22) //~ ERROR `CompareTo` is not implemented +} + +fn with_ufcs2(c: &C) -> bool { + CompareTo::same_as(c, 22) //~ ERROR `CompareTo` is not implemented +} + +fn main() { + assert_eq!(22_i64.same_as(22), true); //~ ERROR `CompareTo` is not implemented +} diff --git a/src/test/compile-fail/transmute-different-sizes.rs b/src/test/compile-fail/transmute-different-sizes.rs index 5c61212a7f..918589b8fd 100644 --- a/src/test/compile-fail/transmute-different-sizes.rs +++ b/src/test/compile-fail/transmute-different-sizes.rs @@ -25,5 +25,3 @@ unsafe fn g(x: &T) { } fn main() {} - - diff --git a/src/test/compile-fail/trivial_casts.rs b/src/test/compile-fail/trivial_casts.rs new file mode 100644 index 0000000000..3119b86548 --- /dev/null +++ b/src/test/compile-fail/trivial_casts.rs @@ -0,0 +1,94 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test the trivial_casts and trivial_numeric_casts lints. For each error we also +// check that the cast can be done using just coercion. + +#![deny(trivial_casts, trivial_numeric_casts)] + +trait Foo { + fn foo(&self) {} +} + +pub struct Bar; + +impl Foo for Bar {} + +pub fn main() { + // Numeric + let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32` + let _: i32 = 42_i32; + + let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8` + let _: u8 = 42_u8; + + // & to * pointers + let x: &u32 = &42; + let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32` + let _: *const u32 = x; + + let x: &mut u32 = &mut 42; + let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32` + let _: *mut u32 = x; + + // unsize array + let x: &[u32; 3] = &[42, 43, 44]; + let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]` + let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]` + let _: &[u32] = x; + let _: *const [u32] = x; + + let x: &mut [u32; 3] = &mut [42, 43, 44]; + let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]` + let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]` + let _: &mut [u32] = x; + let _: *mut [u32] = x; + + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _ = x as Box<[u32]>; //~ERROR trivial cast: `Box<[u32; 3]>` as `Box<[u32]>` + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _: Box<[u32]> = x; + + // unsize trait + let x: &Bar = &Bar; + let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&Foo` + let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const Foo` + let _: &Foo = x; + let _: *const Foo = x; + + let x: &mut Bar = &mut Bar; + let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut Foo` + let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut Foo` + let _: &mut Foo = x; + let _: *mut Foo = x; + + let x: Box = Box::new(Bar); + let _ = x as Box; //~ERROR trivial cast: `Box` as `Box` + let x: Box = Box::new(Bar); + let _: Box = x; + + // functions + fn baz(_x: i32) {} + let _ = &baz as &Fn(i32); //~ERROR trivial cast: `&fn(i32) {main::baz}` as `&core::ops::Fn(i32)` + let _: &Fn(i32) = &baz; + let x = |_x: i32| {}; + let _ = &x as &Fn(i32); //~ERROR trivial cast + let _: &Fn(i32) = &x; +} + +// subtyping +pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) { + let _ = a as &'a Bar; //~ERROR trivial cast + let _: &'a Bar = a; + let _ = b as &'a Bar; //~ERROR trivial cast + let _: &'a Bar = b; + let _ = b as &'b Bar; //~ERROR trivial cast + let _: &'b Bar = b; +} diff --git a/src/test/compile-fail/tuple-index-out-of-bounds.rs b/src/test/compile-fail/tuple-index-out-of-bounds.rs index 54b8d551f2..c2c41fbbb2 100644 --- a/src/test/compile-fail/tuple-index-out-of-bounds.rs +++ b/src/test/compile-fail/tuple-index-out-of-bounds.rs @@ -11,14 +11,14 @@ struct Point(i32, i32); fn main() { - let origin = Point(0i32, 0i32); + let origin = Point(0, 0); origin.0; origin.1; origin.2; //~^ ERROR attempted out-of-bounds tuple index `2` on type `Point` - let tuple = (0i32, 0i32); + let tuple = (0, 0); tuple.0; tuple.1; tuple.2; - //~^ ERROR attempted out-of-bounds tuple index `2` on type `(i32, i32)` + //~^ ERROR attempted out-of-bounds tuple index `2` on type `(_, _)` } diff --git a/src/test/compile-fail/type-mismatch-multiple.rs b/src/test/compile-fail/type-mismatch-multiple.rs index 3bf0896d99..627300a037 100644 --- a/src/test/compile-fail/type-mismatch-multiple.rs +++ b/src/test/compile-fail/type-mismatch-multiple.rs @@ -10,12 +10,12 @@ // Checking that the compiler reports multiple type errors at once -fn main() { let a: bool = 1i32; let b: i32 = true; } +fn main() { let a: bool = 1; let b: i32 = true; } //~^ ERROR mismatched types //~| expected `bool` -//~| found `i32` +//~| found `_` //~| expected bool -//~| found i32 +//~| found integral variable //~| ERROR mismatched types //~| expected `i32` //~| found `bool` diff --git a/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs b/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs index 8ff514e04e..8cc531625d 100644 --- a/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs +++ b/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs @@ -20,7 +20,7 @@ impl MyAdd for i32 { } fn main() { - let x = 5; + let x: i32 = 5; let y = x as MyAdd; //~^ ERROR as `MyAdd` } diff --git a/src/test/compile-fail/type-params-in-different-spaces-1.rs b/src/test/compile-fail/type-params-in-different-spaces-1.rs index de9623de7c..88d8788d63 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-1.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-1.rs @@ -23,7 +23,7 @@ trait BrokenAdd: Int { impl BrokenAdd for T {} pub fn main() { - let foo: u8 = 0u8; + let foo: u8 = 0; let x: u8 = foo.broken_add("hello darkness my old friend".to_string()); println!("{}", x); } diff --git a/src/test/compile-fail/type-params-in-different-spaces-2.rs b/src/test/compile-fail/type-params-in-different-spaces-2.rs index 3a4cc9e874..71e9113603 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-2.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-2.rs @@ -29,4 +29,3 @@ trait B: Tr { fn main() { } - diff --git a/src/test/compile-fail/type-params-in-different-spaces-3.rs b/src/test/compile-fail/type-params-in-different-spaces-3.rs index c113e1b781..3ad1e9ab53 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-3.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-3.rs @@ -15,4 +15,3 @@ trait Tr : Sized { } fn main() {} - diff --git a/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs b/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs new file mode 100644 index 0000000000..fb6c43a190 --- /dev/null +++ b/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo1, U>(x: T) {} +//~^ ERROR: wrong number of type arguments: expected 0, found 1 + +trait Trait: Copy {} +//~^ ERROR: wrong number of type arguments: expected 0, found 1 + +struct MyStruct1>; +//~^ ERROR wrong number of type arguments: expected 0, found 1 + +struct MyStruct2<'a, T: Copy<'a>>; +//~^ ERROR: wrong number of lifetime parameters: expected 0, found 1 + +fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} +//~^ ERROR: wrong number of type arguments: expected 0, found 1 +//~^^ ERROR: wrong number of lifetime parameters: expected 0, found 1 + +fn main() { +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs new file mode 100644 index 0000000000..8a9d53731c --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). + +trait Trait { + type AssocType; + fn dummy(&self) { } +} +fn bar() { + is_send::(); //~ ERROR not implemented +} + +fn is_send() { +} + +fn main() { } diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs new file mode 100644 index 0000000000..0f3453da43 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs @@ -0,0 +1,32 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} + +impl MyTrait for .. {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::<(MyS2, MyS)>(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs new file mode 100644 index 0000000000..524f467e01 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs @@ -0,0 +1,35 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} + +impl MyTrait for .. {} +impl !MyTrait for *mut T {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +struct MyS3; + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs new file mode 100644 index 0000000000..b1febae768 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs @@ -0,0 +1,34 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:typeck_default_trait_impl_cross_crate_coherence_lib.rs + +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). + +#![feature(optin_builtin_traits)] + +extern crate typeck_default_trait_impl_cross_crate_coherence_lib as lib; + +use lib::DefaultedTrait; + +struct A; +impl DefaultedTrait for (A,) { } //~ ERROR E0117 + +struct B; +impl !DefaultedTrait for (B,) { } //~ ERROR E0117 + +struct C; +struct D(T); +impl DefaultedTrait for Box { } //~ ERROR E0321 +impl DefaultedTrait for lib::Something { } //~ ERROR E0117 +impl DefaultedTrait for D { } // OK + +fn main() { } diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs new file mode 100644 index 0000000000..db4d1fe485 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +struct MySendable { + t: *mut u8 +} + +unsafe impl Send for MySendable {} + +struct MyNotSendable { + t: *mut u8 +} + +impl !Send for MyNotSendable {} + +fn is_send() {} + +fn main() { + is_send::(); + is_send::(); + //~^ ERROR the trait `core::marker::Send` is not implemented for the type `MyNotSendable` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs new file mode 100644 index 0000000000..d613589e7d --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs @@ -0,0 +1,50 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![feature(optin_builtin_traits)] + +use std::marker::Managed; +use std::cell::UnsafeCell; + +struct MySync { + t: *mut u8 +} + +unsafe impl Sync for MySync {} + +struct MyNotSync { + t: *mut u8 +} + +impl !Sync for MyNotSync {} + +struct MyTypeWUnsafe { + t: UnsafeCell +} + +struct MyTypeManaged { + t: Managed +} + +fn is_sync() {} + +fn main() { + is_sync::(); + is_sync::(); + //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `MyNotSync` + + is_sync::(); + //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell` + + is_sync::(); + //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::marker::Managed` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs new file mode 100644 index 0000000000..a1ca0e3e0f --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-negation.rs @@ -0,0 +1,44 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait MyTrait: MarkerTrait {} + +impl MyTrait for .. {} + +unsafe trait MyUnsafeTrait: MarkerTrait {} + +unsafe impl MyUnsafeTrait for .. {} + +struct ThisImplsTrait; + +impl !MyUnsafeTrait for ThisImplsTrait {} + + +struct ThisImplsUnsafeTrait; + +impl !MyTrait for ThisImplsUnsafeTrait {} + +fn is_my_trait() {} +fn is_my_unsafe_trait() {} + +fn main() { + is_my_trait::(); + is_my_trait::(); + //~^ ERROR the trait `MyTrait` is not implemented for the type `ThisImplsUnsafeTrait` + + is_my_unsafe_trait::(); + //~^ ERROR the trait `MyUnsafeTrait` is not implemented for the type `ThisImplsTrait` + + is_my_unsafe_trait::(); +} diff --git a/src/test/compile-fail/duplicate-trait-bounds.rs b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs similarity index 72% rename from src/test/compile-fail/duplicate-trait-bounds.rs rename to src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs index d9aa9d9dfc..a345bd1b65 100644 --- a/src/test/compile-fail/duplicate-trait-bounds.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +// ignore-tidy-linelength -fn foo() {} //~ ERROR `Foo` already appears in the list of bounds +#![feature(optin_builtin_traits)] + +impl Copy for .. {} +//~^ ERROR E0318 fn main() {} diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs new file mode 100644 index 0000000000..4006eb2e83 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies +// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In +// other words, the `..` impl only applies if there are no existing +// impls whose types unify. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait Defaulted : MarkerTrait { } +impl Defaulted for .. { } +impl<'a,T:Signed> Defaulted for &'a T { } +impl<'a,T:Signed> Defaulted for &'a mut T { } +fn is_defaulted() { } + +trait Signed : MarkerTrait { } +impl Signed for i32 { } + +fn main() { + is_defaulted::<&'static i32>(); + is_defaulted::<&'static u32>(); + //~^ ERROR the trait `Signed` is not implemented for the type `u32` +} diff --git a/src/test/parse-fail/obsolete-for-sized.rs b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs similarity index 70% rename from src/test/parse-fail/obsolete-for-sized.rs rename to src/test/compile-fail/typeck-default-trait-impl-send-param.rs index 1b86d08a50..185e9dcb3b 100644 --- a/src/test/parse-fail/obsolete-for-sized.rs +++ b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we generate obsolete syntax errors around usages of `for Sized?` +// Test that we do not consider parameter types to be sendable without +// an explicit trait bound. -trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized? +fn foo() { + is_send::() //~ ERROR not implemented +} -trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized? +fn is_send() { +} fn main() { } diff --git a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs new file mode 100644 index 0000000000..4a6a77ac7b --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that when a `..` impl applies, we also check that any +// supertrait conditions are met. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait MyTrait : 'static {} + +impl MyTrait for .. {} + +fn foo() { } + +fn bar<'a>() { + foo::<&'a ()>(); //~ ERROR does not fulfill the required lifetime +} + +fn main() { +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs new file mode 100644 index 0000000000..7f24058e47 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that when a `..` impl applies, we also check that any +// supertrait conditions are met. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait NotImplemented: MarkerTrait { } + +trait MyTrait : NotImplemented {} + +impl MyTrait for .. {} + +fn foo() { bar::() } + +fn bar() { } + +fn main() { + foo::(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i32` + bar::(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i64` +} diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs new file mode 100644 index 0000000000..c970aaaf5d --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs @@ -0,0 +1,47 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +// Test that when a `..` impl applies, we also check that any +// supertrait conditions are met. + +#![feature(optin_builtin_traits)] + +use std::marker::MarkerTrait; + +trait NotImplemented: MarkerTrait { } + +trait MyTrait: MarkerTrait + where Option : NotImplemented +{} + +impl NotImplemented for i32 {} + +impl MyTrait for .. {} + +fn foo() { + bar::>() + //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option` + // + // This should probably typecheck. This is #20671. +} + +fn bar() { } + +fn test() { + bar::>(); + //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option` +} + +fn main() { + foo::(); + //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option` +} diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs index 557fb2f4f8..57a394dc7f 100644 --- a/src/test/compile-fail/typeck-negative-impls-builtin.rs +++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs @@ -17,6 +17,6 @@ trait TestTrait { } impl !TestTrait for TestType {} -//~^ ERROR negative impls are currently allowed just for `Send` and `Sync` +//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`) fn main() {} diff --git a/src/test/compile-fail/typeck_type_placeholder_item.rs b/src/test/compile-fail/typeck_type_placeholder_item.rs index 5bfad94867..d4f3cdfd8b 100644 --- a/src/test/compile-fail/typeck_type_placeholder_item.rs +++ b/src/test/compile-fail/typeck_type_placeholder_item.rs @@ -21,7 +21,7 @@ fn test2() -> (_, _) { (5, 5) } static TEST3: _ = "test"; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -static TEST4: _ = 145u16; +static TEST4: _ = 145; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures static TEST5: (_, _) = (1, 2); @@ -74,7 +74,7 @@ pub fn main() { static FN_TEST3: _ = "test"; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - static FN_TEST4: _ = 145u16; + static FN_TEST4: _ = 145; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures static FN_TEST5: (_, _) = (1, 2); diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs index cbcf31b5b7..5d2b5fa52d 100644 --- a/src/test/compile-fail/ufcs-explicit-self-bad.rs +++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs @@ -63,4 +63,3 @@ fn main() { }; println!("{} {}", bar.foo(2), bar.bar(2)); } - diff --git a/src/test/compile-fail/ufcs-qpath-missing-params.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs index f4e18265fd..b3fe178dc4 100644 --- a/src/test/compile-fail/ufcs-qpath-missing-params.rs +++ b/src/test/compile-fail/ufcs-qpath-missing-params.rs @@ -12,5 +12,5 @@ use std::borrow::IntoCow; fn main() { ::into_cow("foo".to_string()); - //~^ ERROR wrong number of type arguments: expected 1, found 0 + //~^ ERROR too few type parameters provided: expected 1 parameter(s) } diff --git a/src/test/compile-fail/ufcs-qpath-self-mismatch.rs b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs index 868c1eae4a..8e60064bec 100644 --- a/src/test/compile-fail/ufcs-qpath-self-mismatch.rs +++ b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs @@ -18,4 +18,3 @@ fn main() { >::add(1, 2u32); //~^ ERROR mismatched types } - diff --git a/src/test/compile-fail/unboxed-closure-illegal-move.rs b/src/test/compile-fail/unboxed-closure-illegal-move.rs index 800126450c..564b1b4669 100644 --- a/src/test/compile-fail/unboxed-closure-illegal-move.rs +++ b/src/test/compile-fail/unboxed-closure-illegal-move.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] #![feature(unboxed_closures)] // Tests that we can't move out of an unboxed closure environment @@ -19,31 +18,33 @@ fn to_fn>(f: F) -> F { f } fn to_fn_mut>(f: F) -> F { f } fn to_fn_once>(f: F) -> F { f } +// FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + fn main() { // By-ref cases { - let x = box 0_usize; + let x = Box::new(0); let f = to_fn(|| drop(x)); //~ ERROR cannot move } { - let x = box 0_usize; + let x = Box::new(0); let f = to_fn_mut(|| drop(x)); //~ ERROR cannot move } { - let x = box 0_usize; + let x = Box::new(0); let f = to_fn_once(|| drop(x)); // OK -- FnOnce } // By-value cases { - let x = box 0_usize; + let x = Box::new(0); let f = to_fn(move || drop(x)); //~ ERROR cannot move } { - let x = box 0_usize; + let x = Box::new(0); let f = to_fn_mut(move || drop(x)); //~ ERROR cannot move } { - let x = box 0_usize; + let x = Box::new(0); let f = to_fn_once(move || drop(x)); // this one is ok } } diff --git a/src/test/compile-fail/unboxed-closure-immutable-capture.rs b/src/test/compile-fail/unboxed-closure-immutable-capture.rs index b40a91181a..5be2738b47 100644 --- a/src/test/compile-fail/unboxed-closure-immutable-capture.rs +++ b/src/test/compile-fail/unboxed-closure-immutable-capture.rs @@ -17,7 +17,7 @@ fn set(x: &mut usize) { *x = 0; } fn main() { - let x = 0_usize; + let x = 0; move || x = 1; //~ ERROR cannot assign move || set(&mut x); //~ ERROR cannot borrow move || x = 1; //~ ERROR cannot assign diff --git a/src/test/compile-fail/unboxed-closure-region.rs b/src/test/compile-fail/unboxed-closure-region.rs index 59c8495371..eee1b6ce30 100644 --- a/src/test/compile-fail/unboxed-closure-region.rs +++ b/src/test/compile-fail/unboxed-closure-region.rs @@ -14,7 +14,7 @@ // reference cannot escape the region of that variable. fn main() { let _f = { - let x = 0_usize; - || x //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements + let x = 0; + || x //~ ERROR `x` does not live long enough }; } diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs index 12f62d805e..b195a932ac 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs @@ -10,11 +10,10 @@ #![feature(unboxed_closures)] -fn f isize>(x: F) {} //~ ERROR nonexistent trait `Nonexist` +fn f isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist` type Typedef = isize; fn g isize>(x: F) {} //~ ERROR `Typedef` is not a trait fn main() {} - diff --git a/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs b/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs index 1f0d5aae36..55156e28cd 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs @@ -20,4 +20,3 @@ fn bar2(x: &T) where T: Fn<()> { } fn main() { } - diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs index a3991a87b7..1e36c47c09 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-1.rs @@ -22,4 +22,3 @@ fn bar() { } fn main() { } - diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs index ad85cdcaa0..f50d91a4dd 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs @@ -20,4 +20,3 @@ fn foo(b: Box) { } fn main() { } - diff --git a/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs index 5810ffcf21..e6e18d996b 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-wrong-trait.rs @@ -17,4 +17,3 @@ fn f isize>(x: F) {} //~| ERROR no associated type `Output` fn main() {} - diff --git a/src/test/compile-fail/unboxed-closures-borrow-conflict.rs b/src/test/compile-fail/unboxed-closures-borrow-conflict.rs index 1191cfa260..372f327793 100644 --- a/src/test/compile-fail/unboxed-closures-borrow-conflict.rs +++ b/src/test/compile-fail/unboxed-closures-borrow-conflict.rs @@ -14,7 +14,7 @@ // cause borrow conflicts. fn main() { - let mut x = 0_usize; + let mut x = 0; let f = || x += 1; let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed } diff --git a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs index bbafd5109e..93498ac7f8 100644 --- a/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs +++ b/src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs @@ -19,13 +19,17 @@ use std::ops::{Fn,FnMut,FnOnce}; struct S; impl FnMut<(isize,)> for S { - type Output = isize; - extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize { x * x } } +impl FnOnce<(isize,)> for S { + type Output = isize; + + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } +} + fn call_itisize>(f: &F, x: isize) -> isize { f.call((x,)) } @@ -33,6 +37,4 @@ fn call_itisize>(f: &F, x: isize) -> isize { fn main() { let x = call_it(&S, 22); //~^ ERROR not implemented - //~| ERROR not implemented } - diff --git a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs b/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs index f993b8fa8c..226b516e09 100644 --- a/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs +++ b/src/test/compile-fail/unboxed-closures-infer-explicit-call-too-early.rs @@ -15,4 +15,3 @@ fn main() { let () = zero.call_mut(()); //~^ ERROR we have not yet inferred what kind of closure it is } - diff --git a/src/test/compile-fail/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs b/src/test/compile-fail/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs index afbc141b5d..7c5ea03159 100644 --- a/src/test/compile-fail/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs +++ b/src/test/compile-fail/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs @@ -29,4 +29,3 @@ fn main() { tick2(); //~ ERROR cannot borrow } - diff --git a/src/test/compile-fail/unboxed-closures-mutate-upvar.rs b/src/test/compile-fail/unboxed-closures-mutate-upvar.rs index 650bb17bb7..35052ec0bd 100644 --- a/src/test/compile-fail/unboxed-closures-mutate-upvar.rs +++ b/src/test/compile-fail/unboxed-closures-mutate-upvar.rs @@ -20,21 +20,21 @@ fn to_fn>(f: F) -> F { f } fn to_fn_mut>(f: F) -> F { f } fn a() { - let n = 0u8; + let n = 0; let mut f = to_fn_mut(|| { //~ ERROR closure cannot assign n += 1; }); } fn b() { - let mut n = 0u8; + let mut n = 0; let mut f = to_fn_mut(|| { n += 1; // OK }); } fn c() { - let n = 0u8; + let n = 0; let mut f = to_fn_mut(move || { // If we just did a straight-forward desugaring, this would // compile, but we do something a bit more subtle, and hence @@ -44,21 +44,21 @@ fn c() { } fn d() { - let mut n = 0u8; + let mut n = 0; let mut f = to_fn_mut(move || { n += 1; // OK }); } fn e() { - let n = 0u8; + let n = 0; let mut f = to_fn(move || { n += 1; //~ ERROR cannot assign }); } fn f() { - let mut n = 0u8; + let mut n = 0; let mut f = to_fn(move || { n += 1; //~ ERROR cannot assign }); diff --git a/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs b/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs index 2345a86595..432c7fa5d1 100644 --- a/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs +++ b/src/test/compile-fail/unboxed-closures-mutated-upvar-from-fn-closure.rs @@ -16,7 +16,7 @@ fn call(f: F) where F : Fn() { } fn main() { - let mut counter = 0_u32; + let mut counter = 0; call(|| { counter += 1; //~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure diff --git a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs index 713b64b134..2dcd7a97d8 100644 --- a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs +++ b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs @@ -28,14 +28,19 @@ impl YCombinator { } impl R, A) -> R> FnMut<(A,)> for YCombinator { - type Output = R; - extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R { (self.func)(self, arg) //~^ ERROR cannot borrow `*self` as mutable more than once at a time } } +impl R, A) -> R> FnOnce<(A,)> for YCombinator { + type Output = R; + extern "rust-call" fn call_once(mut self, args: (A,)) -> R { + self.call_mut(args) + } +} + fn main() { let mut counter = 0; let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 { diff --git a/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs index f430e9fc75..1a52e22419 100644 --- a/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs +++ b/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs @@ -16,4 +16,3 @@ fn main() { let mut_ = to_fn_mut(|x| x); mut_.call((0, )); //~ ERROR does not implement any method in scope named `call` } - diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index 23f7ee2b01..dc7c70ba64 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -27,11 +27,15 @@ fn a() { } fn b() { - let y = call_it_mut(&mut square, 22); //~ ERROR not implemented + let y = call_it_mut(&mut square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn c() { - let z = call_it_once(square, 22); //~ ERROR not implemented + let z = call_it_once(square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs index c2a2e5162a..28e8b8db2a 100644 --- a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs +++ b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs @@ -25,4 +25,3 @@ pub fn main() { //~| ERROR type mismatch println!("{}", z); } - diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index 96619bef36..cdcb435b65 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -27,12 +27,15 @@ fn a() { } fn b() { - let y = call_it_mut(&mut square, 22); //~ ERROR not implemented + let y = call_it_mut(&mut square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn c() { - let z = call_it_once(square, 22); //~ ERROR not implemented + let z = call_it_once(square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn main() { } - diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index ebcbdbbc00..150bf36dcc 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -28,11 +28,15 @@ fn a() { } fn b() { - let y = call_it_mut(&mut square, 22); //~ ERROR not implemented + let y = call_it_mut(&mut square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn c() { - let z = call_it_once(square, 22); //~ ERROR not implemented + let z = call_it_once(square, 22); + //~^ ERROR not implemented + //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unique-pinned-nocopy.rs b/src/test/compile-fail/unique-pinned-nocopy.rs index 88535ee04f..2ec10d08bb 100644 --- a/src/test/compile-fail/unique-pinned-nocopy.rs +++ b/src/test/compile-fail/unique-pinned-nocopy.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - #[derive(Debug)] struct r { b: bool, @@ -20,7 +18,8 @@ impl Drop for r { } fn main() { - let i = box r { b: true }; + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let i = Box::new(r { b: true }); let _j = i.clone(); //~ ERROR not implement println!("{:?}", i); } diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs index 046337c33f..86fe4da342 100644 --- a/src/test/compile-fail/unique-unique-kind.rs +++ b/src/test/compile-fail/unique-unique-kind.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] - use std::rc::Rc; fn f(__isize: T) { } fn main() { - let i = box Rc::new(100); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let i = Box::new(Rc::new(100)); f(i); //~^ ERROR `core::marker::Send` is not implemented } diff --git a/src/test/compile-fail/unique-vec-res.rs b/src/test/compile-fail/unique-vec-res.rs index 91a41ad6a4..938abbf2c2 100644 --- a/src/test/compile-fail/unique-vec-res.rs +++ b/src/test/compile-fail/unique-vec-res.rs @@ -10,8 +10,6 @@ #![feature(unsafe_destructor)] -#![feature(box_syntax)] - use std::cell::Cell; #[derive(Debug)] @@ -36,8 +34,9 @@ fn clone(t: &T) -> T { t.clone() } fn main() { let i1 = &Cell::new(0); let i2 = &Cell::new(1); - let r1 = vec!(box r { i: i1 }); - let r2 = vec!(box r { i: i2 }); + // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. + let r1 = vec!(Box::new(r { i: i1 })); + let r2 = vec!(Box::new(r { i: i2 })); f(clone(&r1), clone(&r2)); //~^ ERROR the trait `core::clone::Clone` is not implemented for the type //~^^ ERROR the trait `core::clone::Clone` is not implemented for the type diff --git a/src/test/compile-fail/unnecessary-private.rs b/src/test/compile-fail/unnecessary-private.rs index 964db6e9a4..113393490c 100644 --- a/src/test/compile-fail/unnecessary-private.rs +++ b/src/test/compile-fail/unnecessary-private.rs @@ -9,11 +9,11 @@ // except according to those terms. fn main() { - pub use std::uint; //~ ERROR: visibility has no effect + pub use std::usize; //~ ERROR: visibility has no effect pub struct A; //~ ERROR: visibility has no effect pub enum B {} //~ ERROR: visibility has no effect pub trait C { //~ ERROR: visibility has no effect - pub fn foo(&self) {} //~ ERROR: visibility has no effect + fn foo(&self) {} } impl A { pub fn foo(&self) {} //~ ERROR: visibility has no effect diff --git a/src/test/compile-fail/unreachable-arm.rs b/src/test/compile-fail/unreachable-arm.rs index eb5ffeaf88..bc93b86a39 100644 --- a/src/test/compile-fail/unreachable-arm.rs +++ b/src/test/compile-fail/unreachable-arm.rs @@ -15,4 +15,4 @@ enum foo { a(Box, isize), b(usize), } -fn main() { match foo::b(1_usize) { foo::b(_) | foo::a(box _, 1) => { } foo::a(_, 1) => { } } } +fn main() { match foo::b(1) { foo::b(_) | foo::a(box _, 1) => { } foo::a(_, 1) => { } } } diff --git a/src/test/compile-fail/unreachable-variant.rs b/src/test/compile-fail/unreachable-variant.rs index ef991d8533..5983c83f8b 100644 --- a/src/test/compile-fail/unreachable-variant.rs +++ b/src/test/compile-fail/unreachable-variant.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:unreachable-variant.rs +// aux-build:unreachable_variant.rs -extern crate "unreachable-variant" as other; +extern crate unreachable_variant as other; fn main() { let _x = other::super_sekrit::sooper_sekrit::baz; //~ ERROR is private diff --git a/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs b/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs index 97908118e3..4ea7051775 100644 --- a/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs +++ b/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs @@ -10,7 +10,7 @@ fn f(p: *const u8) { - *p = 0u8; //~ ERROR dereference of unsafe pointer requires unsafe function or block + *p = 0; //~ ERROR dereference of unsafe pointer requires unsafe function or block return; } diff --git a/src/test/compile-fail/unsafe-subtyping.rs b/src/test/compile-fail/unsafe-subtyping.rs new file mode 100644 index 0000000000..f486763681 --- /dev/null +++ b/src/test/compile-fail/unsafe-subtyping.rs @@ -0,0 +1,21 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that safe fns are not a subtype of unsafe fns. + +fn foo(x: Option) -> Option { + x //~ ERROR mismatched types +} + +fn bar(x: fn(i32)) -> unsafe fn(i32) { + x // OK, coercion! +} + +fn main() { } diff --git a/src/test/compile-fail/unsafe-trait-impl.rs b/src/test/compile-fail/unsafe-trait-impl.rs new file mode 100644 index 0000000000..71da2f7633 --- /dev/null +++ b/src/test/compile-fail/unsafe-trait-impl.rs @@ -0,0 +1,22 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that safe fns are not a subtype of unsafe fns. + +trait Foo { + unsafe fn len(&self) -> u32; +} + +impl Foo for u32 { + fn len(&self) -> u32 { *self } + //~^ ERROR incompatible type for trait: expected unsafe fn, found normal fn +} + +fn main() { } diff --git a/src/test/compile-fail/unsafe_no_drop_flag-gate.rs b/src/test/compile-fail/unsafe_no_drop_flag-gate.rs new file mode 100644 index 0000000000..542698fd15 --- /dev/null +++ b/src/test/compile-fail/unsafe_no_drop_flag-gate.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct T; + +#[unsafe_no_drop_flag] +//~^ ERROR unsafe_no_drop_flag has unstable semantics and may be removed +pub struct S { + pub x: T, +} + +impl Drop for S { + fn drop(&mut self) {} +} + +pub fn main() {} diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs deleted file mode 100644 index f51eee3793..0000000000 --- a/src/test/compile-fail/unsendable-class.rs +++ /dev/null @@ -1,35 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::sync::mpsc::channel; - -// Test that a class with an unsendable field can't be -// sent - -use std::rc::Rc; - -struct foo { - i: isize, - j: Rc, -} - -fn foo(i:isize, j: Rc) -> foo { - foo { - i: i, - j: j - } -} - -fn main() { - let cat = "kitty".to_string(); - let (tx, _) = channel(); - //~^ ERROR `core::marker::Send` is not implemented - tx.send(foo(42, Rc::new(cat))); -} diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs deleted file mode 100644 index f8b8ad2bf2..0000000000 --- a/src/test/compile-fail/unsized4.rs +++ /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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that bounds are sized-compatible. - -trait T : Sized {} -fn f() { -//~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type -} - -pub fn main() { -} diff --git a/src/test/compile-fail/unused-macro-with-bad-frag-spec.rs b/src/test/compile-fail/unused-macro-with-bad-frag-spec.rs new file mode 100644 index 0000000000..b868b79365 --- /dev/null +++ b/src/test/compile-fail/unused-macro-with-bad-frag-spec.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #21370 + +macro_rules! test { + ($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty` +} + +fn main() { } diff --git a/src/test/compile-fail/unused-macro-with-follow-violation.rs b/src/test/compile-fail/unused-macro-with-follow-violation.rs new file mode 100644 index 0000000000..e9d09bb6ad --- /dev/null +++ b/src/test/compile-fail/unused-macro-with-follow-violation.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! test { + ($e:expr +) => () //~ ERROR not allowed for `expr` fragments +} + +fn main() { } diff --git a/src/test/compile-fail/use-after-move-implicity-coerced-object.rs b/src/test/compile-fail/use-after-move-implicity-coerced-object.rs index d8a82d8fbf..26d22b072e 100644 --- a/src/test/compile-fail/use-after-move-implicity-coerced-object.rs +++ b/src/test/compile-fail/use-after-move-implicity-coerced-object.rs @@ -18,7 +18,7 @@ struct Number { n: i64 } -impl fmt::String for Number { +impl fmt::Display for Number { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.n) } @@ -34,8 +34,8 @@ impl List { } fn main() { - let n = box Number { n: 42 }; - let mut l = box List { list: Vec::new() }; + let n: Box<_> = box Number { n: 42 }; + let mut l: Box<_> = box List { list: Vec::new() }; l.push(n); let x = n.to_string(); //~^ ERROR: use of moved value: `n` diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs index 2a97155dd2..49d8622976 100644 --- a/src/test/compile-fail/use-from-trait.rs +++ b/src/test/compile-fail/use-from-trait.rs @@ -11,7 +11,7 @@ use Trait::foo; //~^ ERROR `foo` is not directly importable use Foo::new; -//~^ ERROR `new` is not directly importable +//~^ ERROR unresolved import `Foo::new`. Not a module `Foo` pub trait Trait { fn foo(); diff --git a/src/test/compile-fail/use-meta-mismatch.rs b/src/test/compile-fail/use-meta-mismatch.rs index 808deea226..6b7b9c8914 100644 --- a/src/test/compile-fail/use-meta-mismatch.rs +++ b/src/test/compile-fail/use-meta-mismatch.rs @@ -10,6 +10,6 @@ // error-pattern:can't find crate for `extra` -extern crate "fake-crate" as extra; +extern crate fake_crate as extra; fn main() { } diff --git a/src/test/compile-fail/useless-priv.rs b/src/test/compile-fail/useless-priv.rs index b1120e5443..59964d0df9 100644 --- a/src/test/compile-fail/useless-priv.rs +++ b/src/test/compile-fail/useless-priv.rs @@ -12,10 +12,7 @@ struct A { pub i: isize } pub enum C { pub Variant } //~ ERROR: unnecessary `pub` pub trait E { - pub fn foo(&self) {} //~ ERROR: unnecessary visibility -} -trait F { - pub fn foo(&self) {} //~ ERROR: unnecessary visibility + fn foo(&self); } impl E for A { diff --git a/src/test/compile-fail/useless-priv2.rs b/src/test/compile-fail/useless-priv2.rs deleted file mode 100644 index a404d09248..0000000000 --- a/src/test/compile-fail/useless-priv2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub trait E { - pub fn foo(&self); //~ ERROR: unnecessary visibility -} -trait F { - pub fn foo(&self); //~ ERROR: unnecessary visibility -} - -fn main() {} diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs index 86271f670c..2a62ac2ac3 100644 --- a/src/test/compile-fail/variadic-ffi.rs +++ b/src/test/compile-fail/variadic-ffi.rs @@ -30,9 +30,9 @@ fn main() { //~| expected non-variadic fn //~| found variadic function - let y: unsafe extern "C" fn(f: isize, x: u8, ...) = bar; + let y: extern "C" fn(f: isize, x: u8, ...) = bar; //~^ ERROR: mismatched types - //~| expected `unsafe extern "C" fn(isize, u8, ...)` + //~| expected `extern "C" fn(isize, u8, ...)` //~| found `extern "C" fn(isize, u8) {bar}` //~| expected variadic fn //~| found non-variadic function diff --git a/src/test/compile-fail/variance-deprecated-markers.rs b/src/test/compile-fail/variance-deprecated-markers.rs deleted file mode 100644 index 8f9d24cb13..0000000000 --- a/src/test/compile-fail/variance-deprecated-markers.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that the deprecated markers still have their old effect. - -#![feature(rustc_attrs)] - -use std::marker; - -#[rustc_variance] -struct A(marker::CovariantType); //~ ERROR types=[[+];[];[]] - -#[rustc_variance] -struct B(marker::ContravariantType); //~ ERROR types=[[-];[];[]] - -#[rustc_variance] -struct C(marker::InvariantType); //~ ERROR types=[[o];[];[]] - -#[rustc_variance] -struct D<'a>(marker::CovariantLifetime<'a>); //~ ERROR regions=[[+];[];[]] - -#[rustc_variance] -struct E<'a>(marker::ContravariantLifetime<'a>); //~ ERROR regions=[[-];[];[]] - -#[rustc_variance] -struct F<'a>(marker::InvariantLifetime<'a>); //~ ERROR regions=[[o];[];[]] - -fn main() { } diff --git a/src/test/compile-fail/variance-issue-20533.rs b/src/test/compile-fail/variance-issue-20533.rs index 0254f56bd1..6069001248 100644 --- a/src/test/compile-fail/variance-issue-20533.rs +++ b/src/test/compile-fail/variance-issue-20533.rs @@ -33,22 +33,21 @@ struct AffineU32(u32); fn main() { { - let a = AffineU32(1_u32); + let a = AffineU32(1); let x = foo(&a); drop(a); //~ ERROR cannot move out of `a` drop(x); } { - let a = AffineU32(1_u32); + let a = AffineU32(1); let x = bar(&a); drop(a); //~ ERROR cannot move out of `a` drop(x); } { - let a = AffineU32(1_u32); + let a = AffineU32(1); let x = baz(&a); drop(a); //~ ERROR cannot move out of `a` drop(x); } } - diff --git a/src/test/run-pass/coherence-cow-1.rs b/src/test/compile-fail/variance-region-bounds.rs similarity index 65% rename from src/test/run-pass/coherence-cow-1.rs rename to src/test/compile-fail/variance-region-bounds.rs index b380372b40..96ae201f6a 100644 --- a/src/test/run-pass/coherence-cow-1.rs +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -8,16 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +// Check that `T:'a` is contravariant in T. -// Test that it's ok for T to appear first in the self-type, as long -// as it's covered somewhere. +#![feature(rustc_attrs)] -extern crate "coherence-lib" as lib; -use lib::{Remote,Pair}; +#[rustc_variance] +trait Foo: 'static { //~ ERROR types=[[];[-];[]] +} -pub struct Cover(T); - -impl Remote for Pair> { } +#[rustc_variance] +trait Bar { //~ ERROR types=[[+];[-];[]] + fn do_it(&self) + where T: 'static; +} fn main() { } diff --git a/src/test/compile-fail/variance-trait-matching.rs b/src/test/compile-fail/variance-trait-matching.rs index d4dab5f0ed..ec020f1881 100644 --- a/src/test/compile-fail/variance-trait-matching.rs +++ b/src/test/compile-fail/variance-trait-matching.rs @@ -27,4 +27,3 @@ fn f() -> &'static mut isize { } fn main() {} - diff --git a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs index 6aaf51278a..44a3f716e3 100644 --- a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs +++ b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs @@ -30,9 +30,9 @@ use id::Id; mod s { #![allow(unstable)] - use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; + use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - static S_COUNT: AtomicUint = ATOMIC_UINT_INIT; + static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; /// generates globally unique count (global across the current /// process, that is) diff --git a/src/test/compile-fail/vec_refs_data_with_early_death.rs b/src/test/compile-fail/vec_refs_data_with_early_death.rs index a191b3e56c..0025449a3d 100644 --- a/src/test/compile-fail/vec_refs_data_with_early_death.rs +++ b/src/test/compile-fail/vec_refs_data_with_early_death.rs @@ -27,5 +27,5 @@ fn main() { v.push(&x); //~ ERROR `x` does not live long enough v.push(&y); //~ ERROR `y` does not live long enough - assert_eq!(v.as_slice(), [&3, &4]); + assert_eq!(v, [&3, &4]); } diff --git a/src/test/compile-fail/vector-cast-weirdness.rs b/src/test/compile-fail/vector-cast-weirdness.rs index c5109ce473..cac52306d6 100644 --- a/src/test/compile-fail/vector-cast-weirdness.rs +++ b/src/test/compile-fail/vector-cast-weirdness.rs @@ -10,6 +10,8 @@ // Issue #14893. Tests that casts from vectors don't behave strangely in the // presence of the `_` type shorthand notation. +// Update: after a change to the way casts are done, we have more type information +// around and so the errors here are no longer exactly the same. struct X { y: [u8; 2], @@ -18,14 +20,15 @@ struct X { fn main() { let x1 = X { y: [0, 0] }; - let p1: *const u8 = &x1.y as *const _; //~ ERROR mismatched types + // No longer a type mismatch - the `_` can be fully resolved by type inference. + let p1: *const u8 = &x1.y as *const _; let t1: *const [u8; 2] = &x1.y as *const _; let h1: *const [u8; 2] = &x1.y as *const [u8; 2]; let mut x1 = X { y: [0, 0] }; + // This is still an error since we don't allow casts from &mut [T; n] to *mut T. let p1: *mut u8 = &mut x1.y as *mut _; //~ ERROR mismatched types let t1: *mut [u8; 2] = &mut x1.y as *mut _; let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2]; } - diff --git a/src/test/compile-fail/vtable-res-trait-param.rs b/src/test/compile-fail/vtable-res-trait-param.rs index cc6ff2d8eb..654272f5bc 100644 --- a/src/test/compile-fail/vtable-res-trait-param.rs +++ b/src/test/compile-fail/vtable-res-trait-param.rs @@ -23,7 +23,7 @@ impl TraitB for isize { } fn call_it(b: B) -> isize { - let y = 4_usize; + let y = 4; b.gimme_an_a(y) //~ ERROR the trait `TraitA` is not implemented } diff --git a/src/test/compile-fail/walk-struct-literal-with.rs b/src/test/compile-fail/walk-struct-literal-with.rs index 0f3754e09e..10503084b9 100644 --- a/src/test/compile-fail/walk-struct-literal-with.rs +++ b/src/test/compile-fail/walk-struct-literal-with.rs @@ -25,4 +25,3 @@ fn main(){ let end = Mine{other_val:1, ..start.make_string_bar()}; println!("{}", start.test); //~ ERROR use of moved value: `start.test` } - diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index 42df43934a..708d56442f 100644 --- a/src/test/compile-fail/weak-lang-item.rs +++ b/src/test/compile-fail/weak-lang-item.rs @@ -17,4 +17,4 @@ #![no_std] extern crate core; -extern crate "weak-lang-items" as other; +extern crate weak_lang_items; diff --git a/src/test/compile-fail/where-clauses-unsatisfied.rs b/src/test/compile-fail/where-clauses-unsatisfied.rs index 4a4a5f3193..269df21248 100644 --- a/src/test/compile-fail/where-clauses-unsatisfied.rs +++ b/src/test/compile-fail/where-clauses-unsatisfied.rs @@ -17,4 +17,3 @@ fn main() { drop(equal(&Struct, &Struct)) //~^ ERROR the trait `core::cmp::Eq` is not implemented } - diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index 26117e7a13..63132d9132 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -139,13 +139,13 @@ fn assoc_enum(arg: Enum) { } fn main() { - assoc_struct(Struct { b: -1i32, b1: 0i64 }); - assoc_local(1i32); - assoc_arg::(2i64); - assoc_return_value(3i32); - assoc_tuple((4i32, 5i64)); - assoc_enum(Enum::Variant1(6i32, 7i64)); - assoc_enum(Enum::Variant2(8i64, 9i32)); + assoc_struct(Struct { b: -1, b1: 0 }); + assoc_local(1); + assoc_arg::(2); + assoc_return_value(3); + assoc_tuple((4, 5)); + assoc_enum(Enum::Variant1(6, 7)); + assoc_enum(Enum::Variant2(8, 9)); } fn zzz() { () } diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs index 30a70fe0b3..1aabd549ca 100644 --- a/src/test/debuginfo/basic-types-globals-metadata.rs +++ b/src/test/debuginfo/basic-types-globals-metadata.rs @@ -12,33 +12,33 @@ // compile-flags:-g // gdb-command:run -// gdb-command:whatis 'basic-types-globals-metadata::B' +// gdb-command:whatis 'basic_types_globals_metadata::B' // gdb-check:type = bool -// gdb-command:whatis 'basic-types-globals-metadata::I' +// gdb-command:whatis 'basic_types_globals_metadata::I' // gdb-check:type = isize -// gdb-command:whatis 'basic-types-globals-metadata::C' +// gdb-command:whatis 'basic_types_globals_metadata::C' // gdb-check:type = char -// gdb-command:whatis 'basic-types-globals-metadata::I8' +// gdb-command:whatis 'basic_types_globals_metadata::I8' // gdb-check:type = i8 -// gdb-command:whatis 'basic-types-globals-metadata::I16' +// gdb-command:whatis 'basic_types_globals_metadata::I16' // gdb-check:type = i16 -// gdb-command:whatis 'basic-types-globals-metadata::I32' +// gdb-command:whatis 'basic_types_globals_metadata::I32' // gdb-check:type = i32 -// gdb-command:whatis 'basic-types-globals-metadata::I64' +// gdb-command:whatis 'basic_types_globals_metadata::I64' // gdb-check:type = i64 -// gdb-command:whatis 'basic-types-globals-metadata::U' +// gdb-command:whatis 'basic_types_globals_metadata::U' // gdb-check:type = usize -// gdb-command:whatis 'basic-types-globals-metadata::U8' +// gdb-command:whatis 'basic_types_globals_metadata::U8' // gdb-check:type = u8 -// gdb-command:whatis 'basic-types-globals-metadata::U16' +// gdb-command:whatis 'basic_types_globals_metadata::U16' // gdb-check:type = u16 -// gdb-command:whatis 'basic-types-globals-metadata::U32' +// gdb-command:whatis 'basic_types_globals_metadata::U32' // gdb-check:type = u32 -// gdb-command:whatis 'basic-types-globals-metadata::U64' +// gdb-command:whatis 'basic_types_globals_metadata::U64' // gdb-check:type = u64 -// gdb-command:whatis 'basic-types-globals-metadata::F32' +// gdb-command:whatis 'basic_types_globals_metadata::F32' // gdb-check:type = f32 -// gdb-command:whatis 'basic-types-globals-metadata::F64' +// gdb-command:whatis 'basic_types_globals_metadata::F64' // gdb-check:type = f64 // gdb-command:continue @@ -48,13 +48,13 @@ // N.B. These are `mut` only so they don't constant fold away. static mut B: bool = false; -static mut I: int = -1; +static mut I: isize = -1; static mut C: char = 'a'; static mut I8: i8 = 68; static mut I16: i16 = -16; static mut I32: i32 = -32; static mut I64: i64 = -64; -static mut U: uint = 1; +static mut U: usize = 1; static mut U8: u8 = 100; static mut U16: u16 = 16; static mut U32: u32 = 32; diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs index cb89879481..f0c187fd22 100644 --- a/src/test/debuginfo/basic-types-globals.rs +++ b/src/test/debuginfo/basic-types-globals.rs @@ -18,33 +18,33 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print 'basic-types-globals::B' +// gdb-command:print 'basic_types_globals::B' // gdb-check:$1 = false -// gdb-command:print 'basic-types-globals::I' +// gdb-command:print 'basic_types_globals::I' // gdb-check:$2 = -1 -// gdb-command:print 'basic-types-globals::C' +// gdb-command:print 'basic_types_globals::C' // gdb-check:$3 = 97 -// gdb-command:print/d 'basic-types-globals::I8' +// gdb-command:print/d 'basic_types_globals::I8' // gdb-check:$4 = 68 -// gdb-command:print 'basic-types-globals::I16' +// gdb-command:print 'basic_types_globals::I16' // gdb-check:$5 = -16 -// gdb-command:print 'basic-types-globals::I32' +// gdb-command:print 'basic_types_globals::I32' // gdb-check:$6 = -32 -// gdb-command:print 'basic-types-globals::I64' +// gdb-command:print 'basic_types_globals::I64' // gdb-check:$7 = -64 -// gdb-command:print 'basic-types-globals::U' +// gdb-command:print 'basic_types_globals::U' // gdb-check:$8 = 1 -// gdb-command:print/d 'basic-types-globals::U8' +// gdb-command:print/d 'basic_types_globals::U8' // gdb-check:$9 = 100 -// gdb-command:print 'basic-types-globals::U16' +// gdb-command:print 'basic_types_globals::U16' // gdb-check:$10 = 16 -// gdb-command:print 'basic-types-globals::U32' +// gdb-command:print 'basic_types_globals::U32' // gdb-check:$11 = 32 -// gdb-command:print 'basic-types-globals::U64' +// gdb-command:print 'basic_types_globals::U64' // gdb-check:$12 = 64 -// gdb-command:print 'basic-types-globals::F32' +// gdb-command:print 'basic_types_globals::F32' // gdb-check:$13 = 2.5 -// gdb-command:print 'basic-types-globals::F64' +// gdb-command:print 'basic_types_globals::F64' // gdb-check:$14 = 3.5 // gdb-command:continue @@ -53,13 +53,13 @@ // N.B. These are `mut` only so they don't constant fold away. static mut B: bool = false; -static mut I: int = -1; +static mut I: isize = -1; static mut C: char = 'a'; static mut I8: i8 = 68; static mut I16: i16 = -16; static mut I32: i32 = -32; static mut I64: i64 = -64; -static mut U: uint = 1; +static mut U: usize = 1; static mut U8: u8 = 100; static mut U16: u16 = 16; static mut U32: u32 = 32; diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs index 7f82878e08..4094c2e9b1 100644 --- a/src/test/debuginfo/basic-types-mut-globals.rs +++ b/src/test/debuginfo/basic-types-mut-globals.rs @@ -21,77 +21,77 @@ // gdb-command:run // Check initializers -// gdb-command:print 'basic-types-mut-globals::B' +// gdb-command:print 'basic_types_mut_globals::B' // gdb-check:$1 = false -// gdb-command:print 'basic-types-mut-globals::I' +// gdb-command:print 'basic_types_mut_globals::I' // gdb-check:$2 = -1 -// gdb-command:print 'basic-types-mut-globals::C' +// gdb-command:print 'basic_types_mut_globals::C' // gdb-check:$3 = 97 -// gdb-command:print/d 'basic-types-mut-globals::I8' +// gdb-command:print/d 'basic_types_mut_globals::I8' // gdb-check:$4 = 68 -// gdb-command:print 'basic-types-mut-globals::I16' +// gdb-command:print 'basic_types_mut_globals::I16' // gdb-check:$5 = -16 -// gdb-command:print 'basic-types-mut-globals::I32' +// gdb-command:print 'basic_types_mut_globals::I32' // gdb-check:$6 = -32 -// gdb-command:print 'basic-types-mut-globals::I64' +// gdb-command:print 'basic_types_mut_globals::I64' // gdb-check:$7 = -64 -// gdb-command:print 'basic-types-mut-globals::U' +// gdb-command:print 'basic_types_mut_globals::U' // gdb-check:$8 = 1 -// gdb-command:print/d 'basic-types-mut-globals::U8' +// gdb-command:print/d 'basic_types_mut_globals::U8' // gdb-check:$9 = 100 -// gdb-command:print 'basic-types-mut-globals::U16' +// gdb-command:print 'basic_types_mut_globals::U16' // gdb-check:$10 = 16 -// gdb-command:print 'basic-types-mut-globals::U32' +// gdb-command:print 'basic_types_mut_globals::U32' // gdb-check:$11 = 32 -// gdb-command:print 'basic-types-mut-globals::U64' +// gdb-command:print 'basic_types_mut_globals::U64' // gdb-check:$12 = 64 -// gdb-command:print 'basic-types-mut-globals::F32' +// gdb-command:print 'basic_types_mut_globals::F32' // gdb-check:$13 = 2.5 -// gdb-command:print 'basic-types-mut-globals::F64' +// gdb-command:print 'basic_types_mut_globals::F64' // gdb-check:$14 = 3.5 // gdb-command:continue // Check new values -// gdb-command:print 'basic-types-mut-globals'::B +// gdb-command:print 'basic_types_mut_globals'::B // gdb-check:$15 = true -// gdb-command:print 'basic-types-mut-globals'::I +// gdb-command:print 'basic_types_mut_globals'::I // gdb-check:$16 = 2 -// gdb-command:print 'basic-types-mut-globals'::C +// gdb-command:print 'basic_types_mut_globals'::C // gdb-check:$17 = 102 -// gdb-command:print/d 'basic-types-mut-globals'::I8 +// gdb-command:print/d 'basic_types_mut_globals'::I8 // gdb-check:$18 = 78 -// gdb-command:print 'basic-types-mut-globals'::I16 +// gdb-command:print 'basic_types_mut_globals'::I16 // gdb-check:$19 = -26 -// gdb-command:print 'basic-types-mut-globals'::I32 +// gdb-command:print 'basic_types_mut_globals'::I32 // gdb-check:$20 = -12 -// gdb-command:print 'basic-types-mut-globals'::I64 +// gdb-command:print 'basic_types_mut_globals'::I64 // gdb-check:$21 = -54 -// gdb-command:print 'basic-types-mut-globals'::U +// gdb-command:print 'basic_types_mut_globals'::U // gdb-check:$22 = 5 -// gdb-command:print/d 'basic-types-mut-globals'::U8 +// gdb-command:print/d 'basic_types_mut_globals'::U8 // gdb-check:$23 = 20 -// gdb-command:print 'basic-types-mut-globals'::U16 +// gdb-command:print 'basic_types_mut_globals'::U16 // gdb-check:$24 = 32 -// gdb-command:print 'basic-types-mut-globals'::U32 +// gdb-command:print 'basic_types_mut_globals'::U32 // gdb-check:$25 = 16 -// gdb-command:print 'basic-types-mut-globals'::U64 +// gdb-command:print 'basic_types_mut_globals'::U64 // gdb-check:$26 = 128 -// gdb-command:print 'basic-types-mut-globals'::F32 +// gdb-command:print 'basic_types_mut_globals'::F32 // gdb-check:$27 = 5.75 -// gdb-command:print 'basic-types-mut-globals'::F64 +// gdb-command:print 'basic_types_mut_globals'::F64 // gdb-check:$28 = 9.25 #![allow(unused_variables)] #![omit_gdb_pretty_printer_section] static mut B: bool = false; -static mut I: int = -1; +static mut I: isize = -1; static mut C: char = 'a'; static mut I8: i8 = 68; static mut I16: i16 = -16; static mut I32: i32 = -32; static mut I64: i64 = -64; -static mut U: uint = 1; +static mut U: usize = 1; static mut U8: u8 = 100; static mut U16: u16 = 16; static mut U32: u32 = 32; diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 95483c1678..c9144b18b2 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -60,7 +60,7 @@ // lldb-check:[...]$1 = -1 // NOTE: LLDB does not support 32bit chars -// d ebugger:print (uint)(c) +// d ebugger:print (usize)(c) // c heck:$3 = 97 // lldb-command:print i8 @@ -91,13 +91,13 @@ fn main() { let b: bool = false; - let i: int = -1; + let i: isize = -1; let c: char = 'a'; let i8: i8 = 68; let i16: i16 = -16; let i32: i32 = -32; let i64: i64 = -64; - let u: uint = 1; + let u: usize = 1; let u8: u8 = 100; let u16: u16 = 16; let u32: u32 = 32; diff --git a/src/test/debuginfo/borrowed-basic.rs b/src/test/debuginfo/borrowed-basic.rs index 52e81b7e04..b0f06bb8a7 100644 --- a/src/test/debuginfo/borrowed-basic.rs +++ b/src/test/debuginfo/borrowed-basic.rs @@ -114,8 +114,8 @@ fn main() { let bool_val: bool = true; let bool_ref: &bool = &bool_val; - let int_val: int = -1; - let int_ref: &int = &int_val; + let int_val: isize = -1; + let int_ref: &isize = &int_val; let char_val: char = 'a'; let char_ref: &char = &char_val; @@ -132,8 +132,8 @@ fn main() { let i64_val: i64 = -64; let i64_ref: &i64 = &i64_val; - let uint_val: uint = 1; - let uint_ref: &uint = &uint_val; + let uint_val: usize = 1; + let uint_ref: &usize = &uint_val; let u8_val: u8 = 100; let u8_ref: &u8 = &u8_val; diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs index 2cfc6855e5..70c24fc2ab 100644 --- a/src/test/debuginfo/borrowed-struct.rs +++ b/src/test/debuginfo/borrowed-struct.rs @@ -67,20 +67,20 @@ #![omit_gdb_pretty_printer_section] struct SomeStruct { - x: int, + x: isize, y: f64 } fn main() { let stack_val: SomeStruct = SomeStruct { x: 10, y: 23.5 }; let stack_val_ref: &SomeStruct = &stack_val; - let stack_val_interior_ref_1: &int = &stack_val.x; + let stack_val_interior_ref_1: &isize = &stack_val.x; let stack_val_interior_ref_2: &f64 = &stack_val.y; let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 }; - let unique_val = box SomeStruct { x: 13, y: 26.5 }; + let unique_val: Box<_> = box SomeStruct { x: 13, y: 26.5 }; let unique_val_ref: &SomeStruct = &*unique_val; - let unique_val_interior_ref_1: &int = &unique_val.x; + let unique_val_interior_ref_1: &isize = &unique_val.x; let unique_val_interior_ref_2: &f64 = &unique_val.y; zzz(); // #break diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs index 14a3d008f4..d8ce3af478 100644 --- a/src/test/debuginfo/borrowed-unique-basic.rs +++ b/src/test/debuginfo/borrowed-unique-basic.rs @@ -118,8 +118,8 @@ fn main() { let bool_box: Box = box true; let bool_ref: &bool = &*bool_box; - let int_box: Box = box -1; - let int_ref: &int = &*int_box; + let int_box: Box = box -1; + let int_ref: &isize = &*int_box; let char_box: Box = box 'a'; let char_ref: &char = &*char_box; @@ -136,8 +136,8 @@ fn main() { let i64_box: Box = box -64; let i64_ref: &i64 = &*i64_box; - let uint_box: Box = box 1; - let uint_ref: &uint = &*uint_box; + let uint_box: Box = box 1; + let uint_ref: &usize = &*uint_box; let u8_box: Box = box 100; let u8_ref: &u8 = &*u8_box; diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index 972d6ab12e..9c6e197e65 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -57,9 +57,9 @@ impl Drop for StructWithDestructor { fn main() { - let unique = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; + let unique: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; - let unique_dtor = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; + let unique_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; zzz(); // #break } diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs index 3efda1e2f6..bc1116b064 100644 --- a/src/test/debuginfo/by-value-non-immediate-argument.rs +++ b/src/test/debuginfo/by-value-non-immediate-argument.rs @@ -74,7 +74,7 @@ #[derive(Clone)] struct Struct { - a: int, + a: isize, b: f64 } @@ -92,11 +92,11 @@ fn fun_fun(StructStruct { a: x, b: Struct { a: y, b: z } }: StructStruct) { zzz(); // #break } -fn tup(a: (int, uint, f64, f64)) { +fn tup(a: (isize, usize, f64, f64)) { zzz(); // #break } -struct Newtype(f64, f64, int, uint); +struct Newtype(f64, f64, isize, usize); fn new_type(a: Newtype) { zzz(); // #break diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs index 2b2a9bf83f..5bd872f9fa 100644 --- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs +++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs @@ -51,16 +51,16 @@ trait Trait { fn method(self) -> Self; } -impl Trait for int { - fn method(self) -> int { +impl Trait for isize { + fn method(self) -> isize { zzz(); // #break self } } struct Struct { - x: uint, - y: uint, + x: usize, + y: usize, } impl Trait for Struct { @@ -70,15 +70,15 @@ impl Trait for Struct { } } -impl Trait for (f64, int, int, f64) { - fn method(self) -> (f64, int, int, f64) { +impl Trait for (f64, isize, isize, f64) { + fn method(self) -> (f64, isize, isize, f64) { zzz(); // #break self } } fn main() { - let _ = (1111 as int).method(); + let _ = (1111 as isize).method(); let _ = Struct { x: 2222, y: 3333 }.method(); let _ = (4444.5, 5555, 6666, 7777.5).method(); } diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index 2305d7bc5c..3024ca0fe6 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -8,31 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-aarch64 // min-lldb-version: 310 // compile-flags:-g // === GDB TESTS =================================================================================== -// gdb-command:print 'c-style-enum::SINGLE_VARIANT' +// gdb-command:print 'c_style_enum::SINGLE_VARIANT' // gdb-check:$1 = TheOnlyVariant -// gdb-command:print 'c-style-enum::AUTO_ONE' +// gdb-command:print 'c_style_enum::AUTO_ONE' // gdb-check:$2 = One -// gdb-command:print 'c-style-enum::AUTO_TWO' +// gdb-command:print 'c_style_enum::AUTO_TWO' // gdb-check:$3 = One -// gdb-command:print 'c-style-enum::AUTO_THREE' +// gdb-command:print 'c_style_enum::AUTO_THREE' // gdb-check:$4 = One -// gdb-command:print 'c-style-enum::MANUAL_ONE' +// gdb-command:print 'c_style_enum::MANUAL_ONE' // gdb-check:$5 = OneHundred -// gdb-command:print 'c-style-enum::MANUAL_TWO' +// gdb-command:print 'c_style_enum::MANUAL_TWO' // gdb-check:$6 = OneHundred -// gdb-command:print 'c-style-enum::MANUAL_THREE' +// gdb-command:print 'c_style_enum::MANUAL_THREE' // gdb-check:$7 = OneHundred // gdb-command:run @@ -58,16 +59,16 @@ // gdb-command:print single_variant // gdb-check:$14 = TheOnlyVariant -// gdb-command:print 'c-style-enum::AUTO_TWO' +// gdb-command:print 'c_style_enum::AUTO_TWO' // gdb-check:$15 = Two -// gdb-command:print 'c-style-enum::AUTO_THREE' +// gdb-command:print 'c_style_enum::AUTO_THREE' // gdb-check:$16 = Three -// gdb-command:print 'c-style-enum::MANUAL_TWO' +// gdb-command:print 'c_style_enum::MANUAL_TWO' // gdb-check:$17 = OneThousand -// gdb-command:print 'c-style-enum::MANUAL_THREE' +// gdb-command:print 'c_style_enum::MANUAL_THREE' // gdb-check:$18 = OneMillion @@ -104,21 +105,21 @@ use self::AutoDiscriminant::{One, Two, Three}; use self::ManualDiscriminant::{OneHundred, OneThousand, OneMillion}; use self::SingleVariant::TheOnlyVariant; -#[derive(Copy)] +#[derive(Copy, Clone)] enum AutoDiscriminant { One, Two, Three } -#[derive(Copy)] +#[derive(Copy, Clone)] enum ManualDiscriminant { OneHundred = 100, OneThousand = 1000, OneMillion = 1000000 } -#[derive(Copy)] +#[derive(Copy, Clone)] enum SingleVariant { TheOnlyVariant } diff --git a/src/test/debuginfo/closure-in-generic-function.rs b/src/test/debuginfo/closure-in-generic-function.rs index b92f5de21b..448e157a25 100644 --- a/src/test/debuginfo/closure-in-generic-function.rs +++ b/src/test/debuginfo/closure-in-generic-function.rs @@ -60,7 +60,7 @@ fn some_generic_fun(a: T1, b: T2) -> (T2, T1) { fn main() { some_generic_fun(0.5f64, 10); - some_generic_fun(&29, box 110); + some_generic_fun(&29, Box::new(110)); } fn zzz() { () } diff --git a/src/test/debuginfo/constant-debug-locs.rs b/src/test/debuginfo/constant-debug-locs.rs new file mode 100644 index 0000000000..f150e84b9f --- /dev/null +++ b/src/test/debuginfo/constant-debug-locs.rs @@ -0,0 +1,68 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-android: FIXME(#10381) +// min-lldb-version: 310 + +// compile-flags:-g + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] +#![feature(std_misc, core)] + +// This test makes sure that the compiler doesn't crash when trying to assign +// debug locations to const-expressions. + +use std::sync::MUTEX_INIT; +use std::cell::UnsafeCell; + +const CONSTANT: u64 = 3 + 4; + +struct Struct { + a: isize, + b: usize, +} +const STRUCT: Struct = Struct { a: 1, b: 2 }; + +struct TupleStruct(u32); +const TUPLE_STRUCT: TupleStruct = TupleStruct(4); + +enum Enum { + Variant1(char), + Variant2 { a: u8 }, + Variant3 +} + +const VARIANT1: Enum = Enum::Variant1('v'); +const VARIANT2: Enum = Enum::Variant2 { a: 2 }; +const VARIANT3: Enum = Enum::Variant3; + +const STRING: &'static str = "String"; + +const VEC: [u32; 8] = [0; 8]; + +const NESTED: (Struct, TupleStruct) = (STRUCT, TUPLE_STRUCT); + +const UNSAFE_CELL: UnsafeCell = UnsafeCell { value: false }; + +fn main() { + let mut _constant = CONSTANT; + let mut _struct = STRUCT; + let mut _tuple_struct = TUPLE_STRUCT; + let mut _variant1 = VARIANT1; + let mut _variant2 = VARIANT2; + let mut _variant3 = VARIANT3; + let mut _string = STRING; + let mut _vec = VEC; + let mut _nested = NESTED; + let mut _extern = MUTEX_INIT; + let mut _unsafe_cell = UNSAFE_CELL; +} diff --git a/src/test/debuginfo/cross-crate-spans.rs b/src/test/debuginfo/cross-crate-spans.rs new file mode 100644 index 0000000000..3aef9438a3 --- /dev/null +++ b/src/test/debuginfo/cross-crate-spans.rs @@ -0,0 +1,74 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![omit_gdb_pretty_printer_section] + +// ignore-android: FIXME(#10381) +// min-lldb-version: 310 + +// aux-build:cross_crate_spans.rs +extern crate cross_crate_spans; + +// compile-flags:-g + + +// === GDB TESTS =================================================================================== + +// gdb-command:break cross_crate_spans.rs:21 +// gdb-command:run + +// gdb-command:print result +// gdb-check:$1 = {17, 17} +// gdb-command:print a_variable +// gdb-check:$2 = 123456789 +// gdb-command:print another_variable +// gdb-check:$3 = 123456789.5 +// gdb-command:continue + +// gdb-command:print result +// gdb-check:$4 = {1212, 1212} +// gdb-command:print a_variable +// gdb-check:$5 = 123456789 +// gdb-command:print another_variable +// gdb-check:$6 = 123456789.5 +// gdb-command:continue + + + +// === LLDB TESTS ================================================================================== + +// lldb-command:b cross_crate_spans.rs:21 +// lldb-command:run + +// lldb-command:print result +// lldb-check:[...]$0 = (17, 17) +// lldb-command:print a_variable +// lldb-check:[...]$1 = 123456789 +// lldb-command:print another_variable +// lldb-check:[...]$2 = 123456789.5 +// lldb-command:continue + +// lldb-command:print result +// lldb-check:[...]$3 = (1212, 1212) +// lldb-command:print a_variable +// lldb-check:[...]$4 = 123456789 +// lldb-command:print another_variable +// lldb-check:[...]$5 = 123456789.5 +// lldb-command:continue + + +// This test makes sure that we can break in functions inlined from other crates. + +fn main() { + + let _ = cross_crate_spans::generic_function(17u32); + let _ = cross_crate_spans::generic_function(1212i16); + +} diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs index 51cced2043..d7ec567325 100644 --- a/src/test/debuginfo/destructured-fn-argument.rs +++ b/src/test/debuginfo/destructured-fn-argument.rs @@ -325,18 +325,18 @@ enum Univariant { Unit(i32) } -struct TupleStruct (f64, int); +struct TupleStruct (f64, isize); -fn simple_tuple((a, b): (int, bool)) { +fn simple_tuple((a, b): (isize, bool)) { zzz(); // #break } -fn nested_tuple((a, (b, c)): (int, (u16, u16))) { +fn nested_tuple((a, (b, c)): (isize, (u16, u16))) { zzz(); // #break } -fn destructure_only_first_level((a, b): (int, (u32, u32))) { +fn destructure_only_first_level((a, b): (isize, (u32, u32))) { zzz(); // #break } @@ -348,7 +348,7 @@ fn struct_pattern(Struct { a: k, b: l }: Struct) { zzz(); // #break } -fn ignored_tuple_element((m, _, n): (int, u16, i32)) { +fn ignored_tuple_element((m, _, n): (isize, u16, i32)) { zzz(); // #break } @@ -370,27 +370,27 @@ fn complex_nesting(((u, v ), ((w, (x, Struct { a: y, b: z})), Struct { a: zzz(); // #break } -fn managed_box(&aa: &(int, int)) { +fn managed_box(&aa: &(isize, isize)) { zzz(); // #break } -fn borrowed_pointer(&bb: &(int, int)) { +fn borrowed_pointer(&bb: &(isize, isize)) { zzz(); // #break } -fn contained_borrowed_pointer((&cc, _): (&int, int)) { +fn contained_borrowed_pointer((&cc, _): (&isize, isize)) { zzz(); // #break } -fn unique_pointer(box dd: Box<(int, int, int)>) { +fn unique_pointer(box dd: Box<(isize, isize, isize)>) { zzz(); // #break } -fn ref_binding(ref ee: (int, int, int)) { +fn ref_binding(ref ee: (isize, isize, isize)) { zzz(); // #break } -fn ref_binding_in_tuple((ref ff, gg): (int, (int, int))) { +fn ref_binding_in_tuple((ref ff, gg): (isize, (isize, isize))) { zzz(); // #break } @@ -414,7 +414,7 @@ fn tuple_struct_with_ref_binding(TupleStruct(mm, ref nn): TupleStruct) { zzz(); // #break } -fn multiple_arguments((oo, pp): (int, int), qq : int) { +fn multiple_arguments((oo, pp): (isize, isize), qq : isize) { zzz(); // #break } @@ -442,7 +442,7 @@ fn main() { tuple_struct_with_ref_binding(TupleStruct(55.0, 56)); multiple_arguments((57, 58), 59); - fn nested_function(rr: int, (ss, tt): (int, int)) { + fn nested_function(rr: isize, (ss, tt): (isize, isize)) { zzz(); // #break } diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs index cf0ca0b67a..4b1c57e0af 100644 --- a/src/test/debuginfo/destructured-local.rs +++ b/src/test/debuginfo/destructured-local.rs @@ -258,18 +258,18 @@ enum Univariant { Unit(i32) } -struct TupleStruct (f64, int); +struct TupleStruct (f64, isize); fn main() { // simple tuple - let (a, b) : (int, bool) = (1, false); + let (a, b) : (isize, bool) = (1, false); // nested tuple - let (c, (d, e)) : (int, (u16, u16)) = (2, (3, 4)); + let (c, (d, e)) : (isize, (u16, u16)) = (2, (3, 4)); // bind tuple-typed value to one name (destructure only first level) - let (f, g) : (int, (u32, u32)) = (5, (6, 7)); + let (f, g) : (isize, (u32, u32)) = (5, (6, 7)); // struct as tuple element let (h, i, j) : (i16, Struct, i16) = (8, Struct { a: 9, b: 10 }, 11); diff --git a/src/test/debuginfo/extern-c-fn.rs b/src/test/debuginfo/extern-c-fn.rs new file mode 100644 index 0000000000..9e73417e7d --- /dev/null +++ b/src/test/debuginfo/extern-c-fn.rs @@ -0,0 +1,68 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// min-lldb-version: 310 + +// compile-flags:-g + +// === GDB TESTS =================================================================================== +// gdb-command:run + +// gdb-command:print s +// gdb-check:$1 = [...]"abcd" +// gdb-command:print len +// gdb-check:$2 = 20 +// gdb-command:print local0 +// gdb-check:$3 = 19 +// gdb-command:print local1 +// gdb-check:$4 = true +// gdb-command:print local2 +// gdb-check:$5 = 20.5 + +// gdb-command:continue + +// === LLDB TESTS ================================================================================== +// lldb-command:run + +// lldb-command:print len +// lldb-check:[...]$0 = 20 +// lldb-command:print local0 +// lldb-check:[...]$1 = 19 +// lldb-command:print local1 +// lldb-check:[...]$2 = true +// lldb-command:print local2 +// lldb-check:[...]$3 = 20.5 + +// lldb-command:continue + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] + + +#[no_mangle] +pub unsafe extern "C" fn fn_with_c_abi(s: *const u8, len: i32) -> i32 { + let local0 = len - 1; + let local1 = len > 2; + let local2 = (len as f64) + 0.5; + + zzz(); // #break + + return 0; +} + +fn main() { + unsafe { + fn_with_c_abi(b"abcd\0".as_ptr(), 20); + } +} + +#[inline(never)] +fn zzz() {()} diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index 9eadf3cc19..d611e4a65a 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -17,6 +17,8 @@ // compile-flags:-g +#![feature(old_io)] + // === GDB TESTS =================================================================================== // gdb-command:run @@ -224,7 +226,7 @@ #![allow(unused_variables)] #![omit_gdb_pretty_printer_section] -fn immediate_args(a: int, b: bool, c: f64) { +fn immediate_args(a: isize, b: bool, c: f64) { ::std::old_io::print("") // #break } @@ -330,6 +332,3 @@ fn main() { while_expr(40, 41, 42); loop_expr(43, 44, 45); } - - - diff --git a/src/test/debuginfo/function-arguments.rs b/src/test/debuginfo/function-arguments.rs index 2ab3668abb..21c2cc09a9 100644 --- a/src/test/debuginfo/function-arguments.rs +++ b/src/test/debuginfo/function-arguments.rs @@ -58,7 +58,7 @@ fn main() { } } -fn fun(x: int, y: bool) -> (int, bool) { +fn fun(x: isize, y: bool) -> (isize, bool) { zzz(); // #break (x, y) diff --git a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs index 8d456f3343..0608e49b28 100644 --- a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs +++ b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs @@ -20,6 +20,8 @@ // compile-flags:-g +#![feature(old_io)] + // === GDB TESTS =================================================================================== // gdb-command:rbreak immediate_args @@ -248,7 +250,7 @@ #![omit_gdb_pretty_printer_section] #[no_stack_check] -fn immediate_args(a: int, b: bool, c: f64) { +fn immediate_args(a: isize, b: bool, c: f64) { ::std::old_io::print(""); } diff --git a/src/test/debuginfo/function-prologue-stepping-regular.rs b/src/test/debuginfo/function-prologue-stepping-regular.rs index 14433fbcd2..e1a77b34e7 100644 --- a/src/test/debuginfo/function-prologue-stepping-regular.rs +++ b/src/test/debuginfo/function-prologue-stepping-regular.rs @@ -126,9 +126,10 @@ // lldb-command:continue #![allow(unused_variables)] +#![feature(old_io)] #![omit_gdb_pretty_printer_section] -fn immediate_args(a: int, b: bool, c: f64) { +fn immediate_args(a: isize, b: bool, c: f64) { () } diff --git a/src/test/debuginfo/gdb-pretty-std.rs b/src/test/debuginfo/gdb-pretty-std.rs new file mode 100644 index 0000000000..dbf80a9bcc --- /dev/null +++ b/src/test/debuginfo/gdb-pretty-std.rs @@ -0,0 +1,60 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-windows failing on win32 bot +// ignore-freebsd: gdb package too new +// ignore-tidy-linelength +// ignore-lldb +// ignore-android: FIXME(#10381) +// compile-flags:-g +// min-gdb-version 7.7 + +// gdb-command: run + +// gdb-command: print slice +// gdb-check:$1 = &[i32](len: 4) = {0, 1, 2, 3} + +// gdb-command: print vec +// gdb-check:$2 = Vec(len: 4, cap: [...]) = {4, 5, 6, 7} + +// gdb-command: print str_slice +// gdb-check:$3 = "IAMA string slice!" + +// gdb-command: print string +// gdb-check:$4 = "IAMA string!" + +// gdb-command: print some +// gdb-check:$5 = Some = {8} + +// gdb-command: print none +// gdb-check:$6 = None + +fn main() { + + // &[] + let slice: &[i32] = &[0, 1, 2, 3]; + + // Vec + let vec = vec![4u64, 5, 6, 7]; + + // &str + let str_slice = "IAMA string slice!"; + + // String + let string = "IAMA string!".to_string(); + + // Option + let some = Some(8i16); + let none: Option = None; + + zzz(); // #break +} + +fn zzz() { () } diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs index aa902a9b2d..aa6051d792 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs @@ -37,7 +37,7 @@ // gdb-check:$5 = CStyleEnumVar3 struct RegularStruct { - the_first_field: int, + the_first_field: isize, the_second_field: f64, the_third_field: bool, } diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs index d47dee14f5..81af9c213a 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs @@ -81,7 +81,7 @@ use self::MixedEnum::{MixedEnumCStyleVar, MixedEnumTupleVar, MixedEnumStructVar} use self::NestedEnum::{NestedVariant1, NestedVariant2}; struct RegularStruct { - the_first_field: int, + the_first_field: isize, the_second_field: f64, the_third_field: bool, the_fourth_field: &'static str, @@ -140,7 +140,7 @@ fn main() { let mixed_enum_struct_var = MixedEnumStructVar { field1: 108.5, field2: 109 }; let some = Some(110_usize); - let none: Option = None; + let none: Option = None; let some_fat = Some("abc"); let none_fat: Option<&'static str> = None; @@ -177,7 +177,7 @@ fn main() { } }; - let none_check1: Option<(uint, Vec)> = None; + let none_check1: Option<(usize, Vec)> = None; let none_check2: Option = None; zzz(); // #break diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs index 76b7a3e729..1748083b2b 100644 --- a/src/test/debuginfo/generic-function.rs +++ b/src/test/debuginfo/generic-function.rs @@ -73,7 +73,7 @@ #[derive(Clone)] struct Struct { - a: int, + a: isize, b: f64 } diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 8c4eeb27c0..fc9ef8e3a9 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -114,24 +114,24 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { x: T } impl Struct { - fn self_by_ref(&self, arg1: int, arg2: T2) -> int { + fn self_by_ref(&self, arg1: isize, arg2: T2) -> isize { zzz(); // #break arg1 } - fn self_by_val(self, arg1: int, arg2: T2) -> int { + fn self_by_val(self, arg1: isize, arg2: T2) -> isize { zzz(); // #break arg1 } - fn self_owned(self: Box>, arg1: int, arg2: T2) -> int { + fn self_owned(self: Box>, arg1: isize, arg2: T2) -> isize { zzz(); // #break arg1 } @@ -142,11 +142,10 @@ fn main() { let _ = stack.self_by_ref(-1, 2_u16); let _ = stack.self_by_val(-3, -4_i16); - let owned = box Struct { x: 1234.5f64 }; + let owned: Box<_> = box Struct { x: 1234.5f64 }; let _ = owned.self_by_ref(-5, -6_i32); let _ = owned.self_by_val(-7, -8_i64); let _ = owned.self_owned(-9, -10.5_f32); } fn zzz() {()} - diff --git a/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs b/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs index eb1083f624..f24b221cce 100644 --- a/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs +++ b/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs @@ -34,26 +34,26 @@ #![omit_gdb_pretty_printer_section] struct Struct { - x: int + x: isize } impl Struct { - fn static_method(arg1: T1, arg2: T2) -> int { + fn static_method(arg1: T1, arg2: T2) -> isize { zzz(); // #break return 0; } } enum Enum { - Variant1 { x: int }, + Variant1 { x: isize }, Variant2, - Variant3(f64, int, char), + Variant3(f64, isize, char), } impl Enum { - fn static_method(arg1: T1, arg2: T2, arg3: T3) -> int { + fn static_method(arg1: T1, arg2: T2, arg3: T3) -> isize { zzz(); // #break return 1; } diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 455861b1ea..caed4bd181 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -53,7 +53,7 @@ enum Univariant { fn main() { - // In order to avoid endianess trouble all of the following test values consist of a single + // In order to avoid endianness trouble all of the following test values consist of a single // repeated byte. This way each interpretation of the union should look the same, no matter if // this is a big or little endian machine. diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 15982f309c..a459badfa8 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -38,7 +38,7 @@ // lldb-check:[...]$2 = AGenericStruct { key: 4.5, value: 5 } // lldb-command:print float_int_float -// lldb-check:[...]$3 = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } +// lldb-check:[...]$3 = AGenericStruct> { key: 6.5, value: AGenericStruct { key: 7, value: 8.5 } } #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/generic-trait-generic-static-default-method.rs b/src/test/debuginfo/generic-trait-generic-static-default-method.rs index 4382861fd2..45da87a567 100644 --- a/src/test/debuginfo/generic-trait-generic-static-default-method.rs +++ b/src/test/debuginfo/generic-trait-generic-static-default-method.rs @@ -28,11 +28,11 @@ #![omit_gdb_pretty_printer_section] struct Struct { - x: int + x: isize } trait Trait { - fn generic_static_default_method(arg1: int, arg2: &(T1, T2)) -> int { + fn generic_static_default_method(arg1: isize, arg2: &(T1, T2)) -> isize { zzz(); // #break arg1 } @@ -43,8 +43,9 @@ impl Trait for Struct {} fn main() { // Is this really how to use these? - Trait::generic_static_default_method::(1000, &(1, 2.5)); - Trait::generic_static_default_method::(2000, &(3.5, (4, 5, 6))); + Trait::generic_static_default_method::(1000, &(1, 2.5)); + Trait::generic_static_default_method::(2000, + &(3.5, (4, 5, 6))); } diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index da62e33555..b0f0852c69 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -71,7 +71,7 @@ enum Univariant { fn main() { - // In order to avoid endianess trouble all of the following test values consist of a single + // In order to avoid endianness trouble all of the following test values consist of a single // repeated byte. This way each interpretation of the union should look the same, no matter if // this is a big or little endian machine. diff --git a/src/test/debuginfo/issue12886.rs b/src/test/debuginfo/issue12886.rs index 424ba50e3c..b259efc9ca 100644 --- a/src/test/debuginfo/issue12886.rs +++ b/src/test/debuginfo/issue12886.rs @@ -10,12 +10,13 @@ // ignore-windows failing on 64-bit bots FIXME #17638 // ignore-lldb +// ignore-aarch64 // compile-flags:-g // gdb-command:run // gdb-command:next -// gdb-check:[...]33[...]s +// gdb-check:[...]34[...]s // gdb-command:continue #![omit_gdb_pretty_printer_section] @@ -28,7 +29,7 @@ // contained in the output, after calling `next` just once, we can be sure that we did not stop in // unwrap(). (The testing framework doesn't allow for checking that some text is *not* contained in // the output, which is why we have to make the test in this kind of roundabout way) -fn bar() -> int { +fn bar() -> isize { let s = Some(5).unwrap(); // #break s } diff --git a/src/test/debuginfo/issue13213.rs b/src/test/debuginfo/issue13213.rs index a079ddbd0f..38b149ef24 100644 --- a/src/test/debuginfo/issue13213.rs +++ b/src/test/debuginfo/issue13213.rs @@ -11,6 +11,9 @@ // min-lldb-version: 310 // aux-build:issue13213aux.rs + +#![feature(old_io)] + extern crate issue13213aux; // compile-flags:-g diff --git a/src/test/debuginfo/issue22656.rs b/src/test/debuginfo/issue22656.rs new file mode 100644 index 0000000000..af518797d1 --- /dev/null +++ b/src/test/debuginfo/issue22656.rs @@ -0,0 +1,57 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// This test makes sure that the LLDB pretty printer does not throw an exception +// when trying to handle a Vec<> or anything else that contains zero-sized +// fields. + +// min-lldb-version: 310 +// ignore-gdb +// ignore-tidy-linelength + +// compile-flags:-g + +// === LLDB TESTS ================================================================================== +// lldb-command:run + +// lldb-command:print v +// lldb-check:[...]$0 = vec![1, 2, 3] +// lldb-command:print zs +// lldb-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct, y: 123, z: ZeroSizedStruct, w: 456 } +// lldb-command:continue + +#![allow(unused_variables)] +#![allow(dead_code)] +#![omit_gdb_pretty_printer_section] + +struct ZeroSizedStruct; + +struct StructWithZeroSizedField { + x: ZeroSizedStruct, + y: u32, + z: ZeroSizedStruct, + w: u64 +} + +fn main() { + let v = vec![1,2,3]; + + let zs = StructWithZeroSizedField { + x: ZeroSizedStruct, + y: 123, + z: ZeroSizedStruct, + w: 456 + }; + + zzz(); // #break +} + +fn zzz() { () } diff --git a/src/test/debuginfo/lexical-scope-in-match.rs b/src/test/debuginfo/lexical-scope-in-match.rs index c2cddd2576..228799848c 100644 --- a/src/test/debuginfo/lexical-scope-in-match.rs +++ b/src/test/debuginfo/lexical-scope-in-match.rs @@ -128,8 +128,8 @@ #![omit_gdb_pretty_printer_section] struct Struct { - x: int, - y: int + x: isize, + y: isize } fn main() { diff --git a/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs b/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs index e097ec2adb..59935e55b3 100644 --- a/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs +++ b/src/test/debuginfo/lexical-scope-in-parameterless-closure.rs @@ -20,4 +20,3 @@ fn main() { let _ = ||(); let _ = (1_usize..3).map(|_| 5); } - diff --git a/src/test/debuginfo/lexical-scope-in-stack-closure.rs b/src/test/debuginfo/lexical-scope-in-stack-closure.rs index 6a909ced81..c0b65fbb22 100644 --- a/src/test/debuginfo/lexical-scope-in-stack-closure.rs +++ b/src/test/debuginfo/lexical-scope-in-stack-closure.rs @@ -78,7 +78,7 @@ fn main() { zzz(); // #break sentinel(); - let closure = |x: int| { + let closure = |x: isize| { zzz(); // #break sentinel(); diff --git a/src/test/debuginfo/lexical-scope-in-unique-closure.rs b/src/test/debuginfo/lexical-scope-in-unique-closure.rs index c0a5a31c9c..5bae2aa7ae 100644 --- a/src/test/debuginfo/lexical-scope-in-unique-closure.rs +++ b/src/test/debuginfo/lexical-scope-in-unique-closure.rs @@ -79,7 +79,7 @@ fn main() { zzz(); // #break sentinel(); - let unique_closure = |x:int| { + let unique_closure = |x:isize| { zzz(); // #break sentinel(); diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index c1ec837a4b..1d406af10a 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -16,7 +16,7 @@ // gdb-command:run -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$1 = 0 // STRUCT EXPRESSION @@ -28,7 +28,7 @@ // gdb-command:print val // gdb-check:$4 = 11 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$5 = 1 // gdb-command:print ten // gdb-check:$6 = 10 @@ -49,7 +49,7 @@ // gdb-command:print val // gdb-check:$11 = 12 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$12 = 2 // gdb-command:print ten // gdb-check:$13 = 10 @@ -70,7 +70,7 @@ // gdb-command:print val // gdb-check:$18 = 13 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$19 = 3 // gdb-command:print ten // gdb-check:$20 = 10 @@ -91,7 +91,7 @@ // gdb-command:print val // gdb-check:$25 = 14 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$26 = 4 // gdb-command:print ten // gdb-check:$27 = 10 @@ -112,7 +112,7 @@ // gdb-command:print val // gdb-check:$32 = 15 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$33 = 5 // gdb-command:print ten // gdb-check:$34 = 10 @@ -133,7 +133,7 @@ // gdb-command:print val // gdb-check:$39 = 16 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$40 = 6 // gdb-command:print ten // gdb-check:$41 = 10 @@ -155,7 +155,7 @@ // gdb-command:print val // gdb-check:$46 = 17 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$47 = 7 // gdb-command:print ten // gdb-check:$48 = 10 @@ -176,7 +176,7 @@ // gdb-command:print val // gdb-check:$53 = 18 -// gdb-command:print 'lexical-scopes-in-block-expression::MUT_INT' +// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' // gdb-check:$54 = 8 // gdb-command:print ten // gdb-check:$55 = 10 @@ -350,14 +350,14 @@ #![allow(unused_assignments)] #![omit_gdb_pretty_printer_section] -static mut MUT_INT: int = 0; +static mut MUT_INT: isize = 0; struct Point { - x: int, - y: int + x: isize, + y: isize } -fn a_function(x: int) -> int { +fn a_function(x: isize) -> isize { x + 1 } @@ -502,7 +502,7 @@ fn main() { zzz(); // #break sentinel(); - val as uint + val as usize }]; zzz(); // #break diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs index e51842992c..ea7d150164 100644 --- a/src/test/debuginfo/limited-debuginfo.rs +++ b/src/test/debuginfo/limited-debuginfo.rs @@ -44,7 +44,7 @@ fn main() { fn zzz() {()} -fn some_function(a: int, b: int) { +fn some_function(a: isize, b: isize) { let some_variable = Struct { a: 11, b: 22 }; let some_other_variable = 23; @@ -53,5 +53,4 @@ fn some_function(a: int, b: int) { } } -fn some_other_function(a: int, b: int) -> bool { true } - +fn some_other_function(a: isize, b: isize) -> bool { true } diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 7ad668791d..6468a36f8c 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -115,7 +115,7 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] enum Enum { Variant1 { x: u16, y: u16 }, Variant2 (u32) @@ -123,17 +123,17 @@ enum Enum { impl Enum { - fn self_by_ref(&self, arg1: int, arg2: int) -> int { + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_by_val(self, arg1: int, arg2: int) -> int { + fn self_by_val(self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_owned(self: Box, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } @@ -144,11 +144,10 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned = box Enum::Variant1{ x: 1799, y: 1799 }; + let owned: Box<_> = box Enum::Variant1{ x: 1799, y: 1799 }; let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); } fn zzz() {()} - diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 6b56a7998c..975668baa1 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -115,24 +115,24 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { x: T } impl Struct { - fn self_by_ref(&self, arg1: int, arg2: int) -> int { + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_by_val(self, arg1: int, arg2: int) -> int { + fn self_by_val(self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_owned(self: Box>, arg1: int, arg2: int) -> int { + fn self_owned(self: Box>, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } @@ -143,11 +143,10 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned = box Struct { x: 1234.5f64 }; + let owned: Box<_> = box Struct { x: 1234.5f64 }; let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); } fn zzz() {()} - diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index e32288a8e7..28885d0ad9 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -115,24 +115,24 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { - x: int + x: isize } impl Struct { - fn self_by_ref(&self, arg1: int, arg2: int) -> int { + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize { zzz(); // #break self.x + arg1 + arg2 } - fn self_by_val(self, arg1: int, arg2: int) -> int { + fn self_by_val(self, arg1: isize, arg2: isize) -> isize { zzz(); // #break self.x + arg1 + arg2 } - fn self_owned(self: Box, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: isize, arg2: isize) -> isize { zzz(); // #break self.x + arg1 + arg2 } @@ -143,11 +143,10 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned = box Struct { x: 200 }; + let owned: Box<_> = box Struct { x: 200 }; let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); } fn zzz() {()} - diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index 6e9a695720..b69a385673 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -115,30 +115,30 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { - x: int + x: isize } trait Trait { - fn self_by_ref(&self, arg1: int, arg2: int) -> int; - fn self_by_val(self, arg1: int, arg2: int) -> int; - fn self_owned(self: Box, arg1: int, arg2: int) -> int; + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize; + fn self_by_val(self, arg1: isize, arg2: isize) -> isize; + fn self_owned(self: Box, arg1: isize, arg2: isize) -> isize; } impl Trait for Struct { - fn self_by_ref(&self, arg1: int, arg2: int) -> int { + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize { zzz(); // #break self.x + arg1 + arg2 } - fn self_by_val(self, arg1: int, arg2: int) -> int { + fn self_by_val(self, arg1: isize, arg2: isize) -> isize { zzz(); // #break self.x + arg1 + arg2 } - fn self_owned(self: Box, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: isize, arg2: isize) -> isize { zzz(); // #break self.x + arg1 + arg2 } @@ -149,11 +149,10 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned = box Struct { x: 200 }; + let owned: Box<_> = box Struct { x: 200 }; let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); } fn zzz() {()} - diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index cee04e92c2..97d4496cce 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -115,22 +115,22 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] -struct TupleStruct(int, f64); +#[derive(Copy, Clone)] +struct TupleStruct(isize, f64); impl TupleStruct { - fn self_by_ref(&self, arg1: int, arg2: int) -> int { + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_by_val(self, arg1: int, arg2: int) -> int { + fn self_by_val(self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_owned(self: Box, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } @@ -141,11 +141,10 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned = box TupleStruct(200, -200.5); + let owned: Box<_> = box TupleStruct(200, -200.5); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); } fn zzz() {()} - diff --git a/src/test/debuginfo/no-debug-attribute.rs b/src/test/debuginfo/no-debug-attribute.rs index 5b2045d59d..f39e8ee222 100644 --- a/src/test/debuginfo/no-debug-attribute.rs +++ b/src/test/debuginfo/no-debug-attribute.rs @@ -40,4 +40,3 @@ fn main() { function_without_debuginfo(); function_with_debuginfo(); } - diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index 3b1979337d..4772ee10ff 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -105,7 +105,7 @@ struct LongCycle4 { struct LongCycleWithAnonymousTypes { next: Opt>>>>>, - value: uint, + value: usize, } // This test case makes sure that recursive structs are properly described. The Node structs are @@ -128,10 +128,10 @@ fn main() { next: Val { val: box UniqueNode { next: Empty, - value: 1_u16, + value: 1, } }, - value: 0_u16, + value: 0, }; let unique_unique: Box> = box UniqueNode { @@ -219,4 +219,3 @@ fn main() { } fn zzz() {()} - diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index cb2b04f4d8..f16f236a0c 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -114,23 +114,23 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { - x: int + x: isize } trait Trait : Sized { - fn self_by_ref(&self, arg1: int, arg2: int) -> int { + fn self_by_ref(&self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_by_val(self, arg1: int, arg2: int) -> int { + fn self_by_val(self, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } - fn self_owned(self: Box, arg1: int, arg2: int) -> int { + fn self_owned(self: Box, arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } @@ -143,11 +143,10 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned = box Struct { x: 200 }; + let owned: Box<_> = box Struct { x: 200 }; let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); } fn zzz() {()} - diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index b96ec3b7b8..56de877016 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -114,24 +114,24 @@ #![feature(box_syntax)] #![omit_gdb_pretty_printer_section] -#[derive(Copy)] +#[derive(Copy, Clone)] struct Struct { - x: int + x: isize } trait Trait : Sized { - fn self_by_ref(&self, arg1: int, arg2: T) -> int { + fn self_by_ref(&self, arg1: isize, arg2: T) -> isize { zzz(); // #break arg1 } - fn self_by_val(self, arg1: int, arg2: T) -> int { + fn self_by_val(self, arg1: isize, arg2: T) -> isize { zzz(); // #break arg1 } - fn self_owned(self: Box, arg1: int, arg2: T) -> int { + fn self_owned(self: Box, arg1: isize, arg2: T) -> isize { zzz(); // #break arg1 } @@ -144,11 +144,10 @@ fn main() { let _ = stack.self_by_ref(-1, 2_u16); let _ = stack.self_by_val(-3, -4_i16); - let owned = box Struct { x: 879 }; + let owned: Box<_> = box Struct { x: 879 }; let _ = owned.self_by_ref(-5, -6_i32); let _ = owned.self_by_val(-7, -8_i64); let _ = owned.self_owned(-9, -10.5_f32); } fn zzz() {()} - diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index 161392c94c..16ae83ee8d 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -42,23 +42,24 @@ #![allow(unused_variables)] #![omit_gdb_pretty_printer_section] +#![feature(core)] use std::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2}; fn main() { - let vi8x16 = i8x16(0i8, 1i8, 2i8, 3i8, 4i8, 5i8, 6i8, 7i8, - 8i8, 9i8, 10i8, 11i8, 12i8, 13i8, 14i8, 15i8); + let vi8x16 = i8x16(0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15); - let vi16x8 = i16x8(16i16, 17i16, 18i16, 19i16, 20i16, 21i16, 22i16, 23i16); - let vi32x4 = i32x4(24i32, 25i32, 26i32, 27i32); - let vi64x2 = i64x2(28i64, 29i64); + let vi16x8 = i16x8(16, 17, 18, 19, 20, 21, 22, 23); + let vi32x4 = i32x4(24, 25, 26, 27); + let vi64x2 = i64x2(28, 29); - let vu8x16 = u8x16(30u8, 31u8, 32u8, 33u8, 34u8, 35u8, 36u8, 37u8, - 38u8, 39u8, 40u8, 41u8, 42u8, 43u8, 44u8, 45u8); - let vu16x8 = u16x8(46u16, 47u16, 48u16, 49u16, 50u16, 51u16, 52u16, 53u16); - let vu32x4 = u32x4(54u32, 55u32, 56u32, 57u32); - let vu64x2 = u64x2(58u64, 59u64); + let vu8x16 = u8x16(30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45); + let vu16x8 = u16x8(46, 47, 48, 49, 50, 51, 52, 53); + let vu32x4 = u32x4(54, 55, 56, 57); + let vu64x2 = u64x2(58, 59); let vf32x4 = f32x4(60.5f32, 61.5f32, 62.5f32, 63.5f32); let vf64x2 = f64x2(64.5f64, 65.5f64); diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index eee3cf5505..36007c1093 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -14,22 +14,22 @@ // === GDB TESTS =================================================================================== -// gdb-command:print 'simple-struct::NO_PADDING_16' +// gdb-command:print 'simple_struct::NO_PADDING_16' // gdb-check:$1 = {x = 1000, y = -1001} -// gdb-command:print 'simple-struct::NO_PADDING_32' +// gdb-command:print 'simple_struct::NO_PADDING_32' // gdb-check:$2 = {x = 1, y = 2, z = 3} -// gdb-command:print 'simple-struct::NO_PADDING_64' +// gdb-command:print 'simple_struct::NO_PADDING_64' // gdb-check:$3 = {x = 4, y = 5, z = 6} -// gdb-command:print 'simple-struct::NO_PADDING_163264' +// gdb-command:print 'simple_struct::NO_PADDING_163264' // gdb-check:$4 = {a = 7, b = 8, c = 9, d = 10} -// gdb-command:print 'simple-struct::INTERNAL_PADDING' +// gdb-command:print 'simple_struct::INTERNAL_PADDING' // gdb-check:$5 = {x = 11, y = 12} -// gdb-command:print 'simple-struct::PADDING_AT_END' +// gdb-command:print 'simple_struct::PADDING_AT_END' // gdb-check:$6 = {x = 13, y = 14} // gdb-command:run @@ -52,22 +52,22 @@ // gdb-command:print padding_at_end // gdb-check:$12 = {x = -10014, y = 10015} -// gdb-command:print 'simple-struct::NO_PADDING_16' +// gdb-command:print 'simple_struct::NO_PADDING_16' // gdb-check:$13 = {x = 100, y = -101} -// gdb-command:print 'simple-struct::NO_PADDING_32' +// gdb-command:print 'simple_struct::NO_PADDING_32' // gdb-check:$14 = {x = -15, y = -16, z = 17} -// gdb-command:print 'simple-struct::NO_PADDING_64' +// gdb-command:print 'simple_struct::NO_PADDING_64' // gdb-check:$15 = {x = -18, y = 19, z = 20} -// gdb-command:print 'simple-struct::NO_PADDING_163264' +// gdb-command:print 'simple_struct::NO_PADDING_163264' // gdb-check:$16 = {a = -21, b = 22, c = 23, d = 24} -// gdb-command:print 'simple-struct::INTERNAL_PADDING' +// gdb-command:print 'simple_struct::INTERNAL_PADDING' // gdb-check:$17 = {x = 25, y = -26} -// gdb-command:print 'simple-struct::PADDING_AT_END' +// gdb-command:print 'simple_struct::PADDING_AT_END' // gdb-check:$18 = {x = -27, y = 28} // gdb-command:continue diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index 75db47af24..3c3a85a34c 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -14,21 +14,21 @@ // === GDB TESTS =================================================================================== -// gdb-command:print/d 'simple-tuple::NO_PADDING_8' +// gdb-command:print/d 'simple_tuple::NO_PADDING_8' // gdb-check:$1 = {-50, 50} -// gdb-command:print 'simple-tuple::NO_PADDING_16' +// gdb-command:print 'simple_tuple::NO_PADDING_16' // gdb-check:$2 = {-1, 2, 3} -// gdb-command:print 'simple-tuple::NO_PADDING_32' +// gdb-command:print 'simple_tuple::NO_PADDING_32' // gdb-check:$3 = {4, 5, 6} -// gdb-command:print 'simple-tuple::NO_PADDING_64' +// gdb-command:print 'simple_tuple::NO_PADDING_64' // gdb-check:$4 = {7, 8, 9} -// gdb-command:print 'simple-tuple::INTERNAL_PADDING_1' +// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' // gdb-check:$5 = {10, 11} -// gdb-command:print 'simple-tuple::INTERNAL_PADDING_2' +// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' // gdb-check:$6 = {12, 13, 14, 15} -// gdb-command:print 'simple-tuple::PADDING_AT_END' +// gdb-command:print 'simple_tuple::PADDING_AT_END' // gdb-check:$7 = {16, 17} // gdb-command:run @@ -50,21 +50,21 @@ // gdb-command:print paddingAtEnd // gdb-check:$14 = {15, 16} -// gdb-command:print/d 'simple-tuple::NO_PADDING_8' +// gdb-command:print/d 'simple_tuple::NO_PADDING_8' // gdb-check:$15 = {-127, 127} -// gdb-command:print 'simple-tuple::NO_PADDING_16' +// gdb-command:print 'simple_tuple::NO_PADDING_16' // gdb-check:$16 = {-10, 10, 9} -// gdb-command:print 'simple-tuple::NO_PADDING_32' +// gdb-command:print 'simple_tuple::NO_PADDING_32' // gdb-check:$17 = {14, 15, 16} -// gdb-command:print 'simple-tuple::NO_PADDING_64' +// gdb-command:print 'simple_tuple::NO_PADDING_64' // gdb-check:$18 = {17, 18, 19} -// gdb-command:print 'simple-tuple::INTERNAL_PADDING_1' +// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' // gdb-check:$19 = {110, 111} -// gdb-command:print 'simple-tuple::INTERNAL_PADDING_2' +// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' // gdb-check:$20 = {112, 113, 114, 115} -// gdb-command:print 'simple-tuple::PADDING_AT_END' +// gdb-command:print 'simple_tuple::PADDING_AT_END' // gdb-check:$21 = {116, 117} diff --git a/src/test/debuginfo/static-method-on-struct-and-enum.rs b/src/test/debuginfo/static-method-on-struct-and-enum.rs index 48db69289c..59fe96f995 100644 --- a/src/test/debuginfo/static-method-on-struct-and-enum.rs +++ b/src/test/debuginfo/static-method-on-struct-and-enum.rs @@ -56,26 +56,26 @@ #![omit_gdb_pretty_printer_section] struct Struct { - x: int + x: isize } impl Struct { - fn static_method(arg1: int, arg2: int) -> int { + fn static_method(arg1: isize, arg2: isize) -> isize { zzz(); // #break arg1 + arg2 } } enum Enum { - Variant1 { x: int }, + Variant1 { x: isize }, Variant2, - Variant3(f64, int, char), + Variant3(f64, isize, char), } impl Enum { - fn static_method(arg1: int, arg2: f64, arg3: uint) -> int { + fn static_method(arg1: isize, arg2: f64, arg3: usize) -> isize { zzz(); // #break arg1 } diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index b2971329cc..b7956c2212 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -66,7 +66,7 @@ enum Univariant { fn main() { - // In order to avoid endianess trouble all of the following test values consist of a single + // In order to avoid endianness trouble all of the following test values consist of a single // repeated byte. This way each interpretation of the union should look the same, no matter if // this is a big or little endian machine. diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index d522e9f891..43cb48d16b 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -68,7 +68,7 @@ enum Univariant { fn main() { - // In order to avoid endianess trouble all of the following test values consist of a single + // In order to avoid endianness trouble all of the following test values consist of a single // repeated byte. This way each interpretation of the union should look the same, no matter if // this is a big or little endian machine. diff --git a/src/test/debuginfo/trait-generic-static-default-method.rs b/src/test/debuginfo/trait-generic-static-default-method.rs index 2ecafb02ae..d066af53e3 100644 --- a/src/test/debuginfo/trait-generic-static-default-method.rs +++ b/src/test/debuginfo/trait-generic-static-default-method.rs @@ -48,11 +48,11 @@ #![omit_gdb_pretty_printer_section] struct Struct { - x: int + x: isize } trait Trait { - fn generic_static_default_method(arg1: int, arg2: T) -> int { + fn generic_static_default_method(arg1: isize, arg2: T) -> isize { zzz(); // #break arg1 } @@ -64,7 +64,7 @@ fn main() { // Is this really how to use these? Trait::generic_static_default_method::(1000, 0.5); - Trait::generic_static_default_method::(2000, &(1, 2, 3)); + Trait::generic_static_default_method::(2000, &(1, 2, 3)); } diff --git a/src/test/debuginfo/trait-pointers.rs b/src/test/debuginfo/trait-pointers.rs index f74c9953f7..3054f646b9 100644 --- a/src/test/debuginfo/trait-pointers.rs +++ b/src/test/debuginfo/trait-pointers.rs @@ -19,11 +19,11 @@ #![omit_gdb_pretty_printer_section] trait Trait { - fn method(&self) -> int { 0 } + fn method(&self) -> isize { 0 } } struct Struct { - a: int, + a: isize, b: f64 } diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 7c9760c3a5..6ed231726b 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -68,7 +68,7 @@ enum Univariant { fn main() { - // In order to avoid endianess trouble all of the following test values consist of a single + // In order to avoid endianness trouble all of the following test values consist of a single // repeated byte. This way each interpretation of the union should look the same, no matter if // this is a big or little endian machine. diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index bf26fc23d3..e7ee9e2ccf 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -21,10 +21,10 @@ // gdb-check:type = struct Struct1 // gdb-command:whatis generic_struct1 -// gdb-check:type = struct GenericStruct +// gdb-check:type = struct GenericStruct // gdb-command:whatis generic_struct2 -// gdb-check:type = struct GenericStruct usize> +// gdb-check:type = struct GenericStruct usize> // gdb-command:whatis mod_struct // gdb-check:type = struct Struct2 @@ -41,18 +41,18 @@ // gdb-check:type = union Enum2 // gdb-command:whatis generic_enum_1 -// gdb-check:type = union Enum3 +// gdb-check:type = union Enum3 // gdb-command:whatis generic_enum_2 -// gdb-check:type = union Enum3 +// gdb-check:type = union Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdb-check:type = struct (u32, type-names::Struct1, type-names::Mod1::Mod2::Enum3) +// gdb-check:type = struct (u32, type_names::Struct1, type_names::Mod1::Mod2::Enum3) // gdb-command:whatis tuple2 -// gdb-check:type = struct ((type-names::Struct1, type-names::Mod1::Mod2::Struct3), type-names::Mod1::Enum2, char) +// gdb-check:type = struct ((type_names::Struct1, type_names::Mod1::Mod2::Struct3), type_names::Mod1::Enum2, char) // BOX @@ -60,46 +60,46 @@ // gdb-check:type = struct (Box, i32) // gdb-command:whatis box2 -// gdb-check:type = struct (Box>, i32) +// gdb-check:type = struct (Box>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdb-check:type = struct (&type-names::Struct1, i32) +// gdb-check:type = struct (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdb-check:type = struct (&type-names::GenericStruct, i32) +// gdb-check:type = struct (&type_names::GenericStruct, i32) // gdb-command:whatis mut_ref1 -// gdb-check:type = struct (&mut type-names::Struct1, i32) +// gdb-check:type = struct (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdb-check:type = struct (&mut type-names::GenericStruct, i32) +// gdb-check:type = struct (&mut type_names::GenericStruct, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdb-check:type = struct (*mut type-names::Struct1, isize) +// gdb-check:type = struct (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 // gdb-check:type = struct (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdb-check:type = struct (*mut type-names::Mod1::Mod2::Enum3, isize) +// gdb-check:type = struct (*mut type_names::Mod1::Mod2::Enum3, isize) // gdb-command:whatis const_ptr1 -// gdb-check:type = struct (*const type-names::Struct1, isize) +// gdb-check:type = struct (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 // gdb-check:type = struct (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdb-check:type = struct (*const type-names::Mod1::Mod2::Enum3, isize) +// gdb-check:type = struct (*const type_names::Mod1::Mod2::Enum3, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdb-check:type = struct ([type-names::Struct1; 3], i16) +// gdb-check:type = struct ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 // gdb-check:type = struct ([usize; 3], i16) @@ -108,7 +108,7 @@ // gdb-check:type = struct &[usize] // gdb-command:whatis slice2 -// gdb-check:type = struct &[type-names::Mod1::Enum2] +// gdb-check:type = struct &[type_names::Mod1::Enum2] // TRAITS @@ -122,18 +122,18 @@ // gdb-check:type = struct &mut Trait1 // gdb-command:whatis generic_box_trait -// gdb-check:type = struct Box> +// gdb-check:type = struct Box> // gdb-command:whatis generic_ref_trait -// gdb-check:type = struct &Trait2 +// gdb-check:type = struct &Trait2 // gdb-command:whatis generic_mut_ref_trait -// gdb-check:type = struct &mut Trait2> +// gdb-check:type = struct &mut Trait2> // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdb-check:type = struct (fn(core::option::Option, core::option::Option<&type-names::Mod1::Struct2>), usize) +// gdb-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::Mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn // gdb-check:type = struct (extern "C" fn(isize), usize) @@ -148,10 +148,10 @@ // gdb-check:type = struct (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdb-check:type = struct (extern "C" fn() -> type-names::Struct1, usize) +// gdb-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdb-check:type = struct (unsafe fn(type-names::GenericStruct) -> type-names::Mod1::Struct2, usize) +// gdb-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::Mod1::Struct2, usize) // gdb-command:whatis extern_stdcall_fn_with_return_value // gdb-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) @@ -160,7 +160,7 @@ // gdb-check:type = struct (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdb-check:type = struct (fn(type-names::Mod1::Mod2::Struct3) -> type-names::Mod1::Mod2::Struct3, usize) +// gdb-check:type = struct (fn(type_names::Mod1::Mod2::Struct3) -> type_names::Mod1::Mod2::Struct3, usize) // gdb-command:whatis variadic_function // gdb-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) @@ -291,15 +291,15 @@ fn main() { let slice2 = &*vec2; // Trait Objects - let box_trait = (box 0) as Box; - let ref_trait = &0 as &Trait1; - let mut mut_int1 = 0; + let box_trait = (box 0_isize) as Box; + let ref_trait = &0_isize as &Trait1; + let mut mut_int1 = 0_isize; let mut_ref_trait = (&mut mut_int1) as &mut Trait1; - let generic_box_trait = (box 0) as Box>; - let generic_ref_trait = (&0) as &Trait2; + let generic_box_trait = (box 0_isize) as Box>; + let generic_ref_trait = (&0_isize) as &Trait2; - let mut generic_mut_ref_trait_impl = 0; + let mut generic_mut_ref_trait_impl = 0_isize; let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as &mut Trait2>; diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index 69b5797007..e450ead009 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -59,7 +59,7 @@ enum Univariant { fn main() { - // In order to avoid endianess trouble all of the following test values consist of a single + // In order to avoid endianness trouble all of the following test values consist of a single // repeated byte. This way each interpretation of the union should look the same, no matter if // this is a big or little endian machine. @@ -67,15 +67,15 @@ fn main() { // 0b01111100011111000111110001111100 = 2088533116 // 0b0111110001111100 = 31868 // 0b01111100 = 124 - let the_a = box ABC::TheA { x: 0, y: 8970181431921507452 }; + let the_a: Box<_> = box ABC::TheA { x: 0, y: 8970181431921507452 }; // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 // 0b00010001000100010001000100010001 = 286331153 // 0b0001000100010001 = 4369 // 0b00010001 = 17 - let the_b = box ABC::TheB (0, 286331153, 286331153); + let the_b: Box<_> = box ABC::TheB (0, 286331153, 286331153); - let univariant = box Univariant::TheOnlyCase(123234); + let univariant: Box<_> = box Univariant::TheOnlyCase(123234); zzz(); // #break } diff --git a/src/test/debuginfo/unreachable-locals.rs b/src/test/debuginfo/unreachable-locals.rs index 309848d6ce..63536b1383 100644 --- a/src/test/debuginfo/unreachable-locals.rs +++ b/src/test/debuginfo/unreachable-locals.rs @@ -26,6 +26,22 @@ fn after_return() { (a, ref b) => {} } for a in &[111i32] {} + let test = if some_predicate() { 1 } else { 2 }; + while some_predicate() { + let abc = !some_predicate(); + } + loop { + let abc = !some_predicate(); + break; + } + // nested block + { + let abc = !some_predicate(); + + { + let def = !some_predicate(); + } + } } fn after_panic() { @@ -36,6 +52,22 @@ fn after_panic() { (a, ref b) => {} } for a in &[111i32] {} + let test = if some_predicate() { 1 } else { 2 }; + while some_predicate() { + let abc = !some_predicate(); + } + loop { + let abc = !some_predicate(); + break; + } + // nested block + { + let abc = !some_predicate(); + + { + let def = !some_predicate(); + } + } } fn after_diverging_function() { @@ -46,6 +78,22 @@ fn after_diverging_function() { (a, ref b) => {} } for a in &[111i32] {} + let test = if some_predicate() { 1 } else { 2 }; + while some_predicate() { + let abc = !some_predicate(); + } + loop { + let abc = !some_predicate(); + break; + } + // nested block + { + let abc = !some_predicate(); + + { + let def = !some_predicate(); + } + } } fn after_break() { @@ -57,18 +105,50 @@ fn after_break() { (a, ref b) => {} } for a in &[111i32] {} + let test = if some_predicate() { 1 } else { 2 }; + while some_predicate() { + let abc = !some_predicate(); + } + loop { + let abc = !some_predicate(); + break; + } + // nested block + { + let abc = !some_predicate(); + + { + let def = !some_predicate(); + } + } } } fn after_continue() { for _ in 0..10i32 { - break; + continue; let x = "0"; let (ref y,z) = (1i32, 2u32); match (20i32, 'c') { (a, ref b) => {} } for a in &[111i32] {} + let test = if some_predicate() { 1 } else { 2 }; + while some_predicate() { + let abc = !some_predicate(); + } + loop { + let abc = !some_predicate(); + break; + } + // nested block + { + let abc = !some_predicate(); + + { + let def = !some_predicate(); + } + } } } @@ -83,3 +163,6 @@ fn main() { fn diverge() -> ! { panic!(); } + +fn some_predicate() -> bool { true || false } + diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 9c9d82249e..d576aff8b1 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -82,9 +82,9 @@ #![omit_gdb_pretty_printer_section] struct Struct { - a: int, + a: isize, b: f64, - c: uint + c: usize } fn main() { @@ -98,7 +98,7 @@ fn main() { }; let struct_ref = &a_struct; - let owned = box 6; + let owned: Box<_> = box 6; let mut closure = || { let closure_local = 8; diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index 3c442c95e0..2b27f938b3 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -44,9 +44,9 @@ #![omit_gdb_pretty_printer_section] struct Struct { - a: int, + a: isize, b: f64, - c: uint + c: usize } fn main() { @@ -58,7 +58,7 @@ fn main() { c: 4 }; - let owned = box 5; + let owned: Box<_> = box 5; let closure = move || { zzz(); // #break @@ -80,7 +80,7 @@ fn main() { immedate_env(); } -fn do_something(_: &int, _:&int, _:&int) { +fn do_something(_: &isize, _:&isize, _:&isize) { } diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index e3bd1eade7..54ef42b48f 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -74,9 +74,9 @@ #![omit_gdb_pretty_printer_section] struct Struct { - a: int, + a: isize, b: f64, - c: uint + c: usize } fn main() { @@ -90,7 +90,7 @@ fn main() { }; let struct_ref = &a_struct; - let owned = box 6; + let owned: Box<_> = box 6; { let mut first_closure = || { diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index 3ceb3946f3..3759082db2 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -49,9 +49,9 @@ // gdb-command:print padded_struct.data_ptr[1] // gdb-check:$13 = {x = 13, y = 14, z = 15} -// gdb-command:print 'vec-slices::MUT_VECT_SLICE'.length +// gdb-command:print 'vec_slices::MUT_VECT_SLICE'.length // gdb-check:$14 = 2 -// gdb-command:print *((int64_t[2]*)('vec-slices::MUT_VECT_SLICE'.data_ptr)) +// gdb-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) // gdb-check:$15 = {64, 65} diff --git a/src/test/parse-fail/ascii-only-character-escape.rs b/src/test/parse-fail/ascii-only-character-escape.rs index 1ba25a827a..bcfcc43470 100644 --- a/src/test/parse-fail/ascii-only-character-escape.rs +++ b/src/test/parse-fail/ascii-only-character-escape.rs @@ -14,4 +14,3 @@ fn main() { let z = "\xe2"; //~ ERROR may only be used let a = b"\x00e2"; // ok because byte literal } - diff --git a/src/test/parse-fail/bad-lit-suffixes.rs b/src/test/parse-fail/bad-lit-suffixes.rs index d10337e768..f1f1811582 100644 --- a/src/test/parse-fail/bad-lit-suffixes.rs +++ b/src/test/parse-fail/bad-lit-suffixes.rs @@ -9,10 +9,6 @@ // except according to those terms. -extern crate - "foo"suffix //~ ERROR extern crate name with a suffix is illegal - as foo; - extern "C"suffix //~ ERROR ABI spec with a suffix is illegal fn foo() {} diff --git a/src/test/parse-fail/byte-literals.rs b/src/test/parse-fail/byte-literals.rs index 436078fa76..08935a24a1 100644 --- a/src/test/parse-fail/byte-literals.rs +++ b/src/test/parse-fail/byte-literals.rs @@ -21,5 +21,3 @@ pub fn main() { b'é'; //~ ERROR byte constant must be ASCII b'a //~ ERROR unterminated byte constant } - - diff --git a/src/test/parse-fail/byte-string-literals.rs b/src/test/parse-fail/byte-string-literals.rs index ec67cdd77e..ee3d86a663 100644 --- a/src/test/parse-fail/byte-string-literals.rs +++ b/src/test/parse-fail/byte-string-literals.rs @@ -19,5 +19,3 @@ pub fn main() { b"é"; //~ ERROR byte constant must be ASCII b"a //~ ERROR unterminated double quote byte string } - - diff --git a/src/test/parse-fail/circular_modules_main.rs b/src/test/parse-fail/circular_modules_main.rs index ac5ec1236f..3e548981f1 100644 --- a/src/test/parse-fail/circular_modules_main.rs +++ b/src/test/parse-fail/circular_modules_main.rs @@ -9,10 +9,10 @@ // except according to those terms. #[path = "circular_modules_hello.rs"] -mod circular_modules_hello; //~ERROR: circular modules +mod circular_modules_hello; //~ ERROR: circular modules pub fn hi_str() -> String { - "Hi!".to_string() + "Hi!".to_string() } fn main() { diff --git a/src/test/parse-fail/class-implements-bad-trait.rs b/src/test/parse-fail/class-implements-bad-trait.rs index d709ffdc3f..7de51c1ea7 100644 --- a/src/test/parse-fail/class-implements-bad-trait.rs +++ b/src/test/parse-fail/class-implements-bad-trait.rs @@ -15,5 +15,5 @@ class cat : nonexistent { } fn main() { - let nyan = cat(0us); + let nyan = cat(0); } diff --git a/src/test/compile-fail/slice-1.rs b/src/test/parse-fail/closure-return-syntax.rs similarity index 73% rename from src/test/compile-fail/slice-1.rs rename to src/test/parse-fail/closure-return-syntax.rs index 3b992e3bcc..da6245597f 100644 --- a/src/test/compile-fail/slice-1.rs +++ b/src/test/parse-fail/closure-return-syntax.rs @@ -8,13 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test slicing &expr[] is deprecated and gives a helpful error message. - -struct Foo; +// Test that we cannot parse a closure with an explicit return type +// unless it uses braces. fn main() { - let x = Foo; - &x[]; - //~^ WARN obsolete syntax - //~| ERROR cannot index + let x = || -> i32 22; //~ ERROR expected `{`, found `22` } diff --git a/src/test/parse-fail/column-offset-1-based.rs b/src/test/parse-fail/column-offset-1-based.rs index 621b480fe7..a00ded6175 100644 --- a/src/test/parse-fail/column-offset-1-based.rs +++ b/src/test/parse-fail/column-offset-1-based.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -# //~ ERROR 11:1: 11:2 error: expected one of `!` or `[`, found `` +# //~ ERROR 11:1: 11:2 error: expected `[`, found `` diff --git a/src/test/parse-fail/empty-impl-semicolon.rs b/src/test/parse-fail/empty-impl-semicolon.rs index 70c7d42feb..a2e780d49b 100644 --- a/src/test/parse-fail/empty-impl-semicolon.rs +++ b/src/test/parse-fail/empty-impl-semicolon.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -impl Foo; //~ ERROR expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;` +impl Foo; //~ ERROR expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `;` diff --git a/src/test/parse-fail/extern-crate-as-no-string-help.rs b/src/test/parse-fail/extern-crate-as-no-string-help.rs deleted file mode 100644 index 5cc52f6f6d..0000000000 --- a/src/test/parse-fail/extern-crate-as-no-string-help.rs +++ /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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that the proper help is displayed in the error message - -extern crate foo as bar; -//~^ ERROR expected `;`, found `as` -//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string? diff --git a/src/test/parse-fail/extern-foreign-crate.rs b/src/test/parse-fail/extern-foreign-crate.rs index 24b978b0a2..1ff4368dac 100644 --- a/src/test/parse-fail/extern-foreign-crate.rs +++ b/src/test/parse-fail/extern-foreign-crate.rs @@ -11,4 +11,4 @@ // Verifies that the expected token errors for `extern crate` are // raised -extern crate foo {} //~ERROR expected `;`, found `{` +extern crate foo {} //~ERROR expected one of `;` or `as`, found `{` diff --git a/src/test/parse-fail/issue-10392-2.rs b/src/test/parse-fail/issue-10392-2.rs index b077081c5b..2a3dd7fba0 100644 --- a/src/test/parse-fail/issue-10392-2.rs +++ b/src/test/parse-fail/issue-10392-2.rs @@ -15,4 +15,3 @@ fn a() -> A { panic!() } fn main() { let A { .., } = a(); //~ ERROR: expected `}` } - diff --git a/src/test/parse-fail/issue-1655.rs b/src/test/parse-fail/issue-1655.rs index a8704f7545..6bdcf5c5ed 100644 --- a/src/test/parse-fail/issue-1655.rs +++ b/src/test/parse-fail/issue-1655.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected one of `!` or `[`, found `vec` +// error-pattern:expected `[`, found `vec` mod blade_runner { #vec[doc( brief = "Blade Runner is probably the best movie ever", diff --git a/src/test/parse-fail/issue-17718-const-mut.rs b/src/test/parse-fail/issue-17718-const-mut.rs index 5177ebbc18..b7feeecbfd 100644 --- a/src/test/parse-fail/issue-17718-const-mut.rs +++ b/src/test/parse-fail/issue-17718-const-mut.rs @@ -15,4 +15,3 @@ FOO: usize = 3; fn main() { } - diff --git a/src/test/parse-fail/issue-1802-1.rs b/src/test/parse-fail/issue-1802-1.rs index 8ce99f517c..00fb2808fa 100644 --- a/src/test/parse-fail/issue-1802-1.rs +++ b/src/test/parse-fail/issue-1802-1.rs @@ -10,5 +10,5 @@ // error-pattern:no valid digits found for number fn main() { - log(error, 0b42); + log(error, 0b); } diff --git a/src/test/parse-fail/issue-20711-2.rs b/src/test/parse-fail/issue-20711-2.rs index a6c4570c60..a50a757160 100644 --- a/src/test/parse-fail/issue-20711-2.rs +++ b/src/test/parse-fail/issue-20711-2.rs @@ -17,4 +17,3 @@ impl Foo { } //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` fn main() {} - diff --git a/src/test/parse-fail/issue-21153.rs b/src/test/parse-fail/issue-21153.rs index e2b6deb0ad..6496ffebbc 100644 --- a/src/test/parse-fail/issue-21153.rs +++ b/src/test/parse-fail/issue-21153.rs @@ -9,5 +9,5 @@ // except according to those terms. trait MyTrait: Iterator { - Item = T; //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `Item` + Item = T; //~ ERROR expected one of `extern`, `fn`, `type`, or `unsafe`, found `Item` } diff --git a/src/test/parse-fail/issue-22647.rs b/src/test/parse-fail/issue-22647.rs new file mode 100644 index 0000000000..5de8627001 --- /dev/null +++ b/src/test/parse-fail/issue-22647.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let caller = |f: F| //~ ERROR unexpected token: `<` + where F: Fn() -> i32 + { + let x = f(); + println!("Y {}",x); + return x; + }; + + caller(bar_handler); +} + +fn bar_handler() -> i32 { + 5 +} diff --git a/src/test/parse-fail/issue-22712.rs b/src/test/parse-fail/issue-22712.rs new file mode 100644 index 0000000000..abc9e59946 --- /dev/null +++ b/src/test/parse-fail/issue-22712.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + buffer: B +} + +fn bar() { + let Foo> //~ ERROR unexpected token: `<` +} + +fn main() {} diff --git a/src/test/parse-fail/issue-2354-1.rs b/src/test/parse-fail/issue-2354-1.rs index d37837b971..48cdeeb0d7 100644 --- a/src/test/parse-fail/issue-2354-1.rs +++ b/src/test/parse-fail/issue-2354-1.rs @@ -9,4 +9,3 @@ // except according to those terms. static foo: isize = 2; } //~ ERROR incorrect close delimiter: - diff --git a/src/test/parse-fail/issue-23620-invalid-escapes.rs b/src/test/parse-fail/issue-23620-invalid-escapes.rs new file mode 100644 index 0000000000..7930ea75bf --- /dev/null +++ b/src/test/parse-fail/issue-23620-invalid-escapes.rs @@ -0,0 +1,45 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _ = b"\u{a66e}"; + //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string + + let _ = b'\u{a66e}'; + //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string + + let _ = b'\u'; + //~^ ERROR unknown byte escape: u + + let _ = b'\x5'; + //~^ ERROR numeric character escape is too short + + let _ = b'\xxy'; + //~^ ERROR illegal character in numeric character escape: x + //~^^ ERROR illegal character in numeric character escape: y + + let _ = '\x5'; + //~^ ERROR numeric character escape is too short + + let _ = '\xxy'; + //~^ ERROR illegal character in numeric character escape: x + //~^^ ERROR illegal character in numeric character escape: y + + let _ = b"\u{a4a4} \xf \u"; + //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string + //~^^ ERROR illegal character in numeric character escape: + //~^^^ ERROR unknown byte escape: u + + let _ = "\u{ffffff} \xf \u"; + //~^ ERROR illegal unicode character escape + //~^^ ERROR illegal character in numeric character escape: + //~^^^ ERROR form of character escape may only be used with characters in the range [\x00-\x7f] + //~^^^^ ERROR unknown character escape: u +} diff --git a/src/test/parse-fail/issue-5544-b.rs b/src/test/parse-fail/issue-5544-b.rs index afff5984b4..9c35d77baf 100644 --- a/src/test/parse-fail/issue-5544-b.rs +++ b/src/test/parse-fail/issue-5544-b.rs @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - let __isize = 0xff_ffff_ffff_ffff_ffff__isize; + let __isize = 0xff_ffff_ffff_ffff_ffff; //~^ ERROR int literal is too large } diff --git a/src/test/parse-fail/issue-5806.rs b/src/test/parse-fail/issue-5806.rs index 597366a1b3..09de97d71b 100644 --- a/src/test/parse-fail/issue-5806.rs +++ b/src/test/parse-fail/issue-5806.rs @@ -8,15 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +// ignore-windows +// ignore-freebsd +// ignore-openbsd #[path = "../compile-fail"] mod foo; //~ ERROR: a directory diff --git a/src/test/parse-fail/keywords-followed-by-double-colon.rs b/src/test/parse-fail/keywords-followed-by-double-colon.rs index f69b041597..ba04a5ac9a 100644 --- a/src/test/parse-fail/keywords-followed-by-double-colon.rs +++ b/src/test/parse-fail/keywords-followed-by-double-colon.rs @@ -12,4 +12,3 @@ fn main() { struct::foo(); //~ ERROR expected identifier mut::baz(); //~ ERROR expected identifier } - diff --git a/src/test/parse-fail/lex-bad-binary-literal.rs b/src/test/parse-fail/lex-bad-binary-literal.rs new file mode 100644 index 0000000000..e92000c54b --- /dev/null +++ b/src/test/parse-fail/lex-bad-binary-literal.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 0b121; //~ ERROR invalid digit for a base 2 literal + 0b10_10301; //~ ERROR invalid digit for a base 2 literal + 0b30; //~ ERROR invalid digit for a base 2 literal + 0b41; //~ ERROR invalid digit for a base 2 literal + 0b5; //~ ERROR invalid digit for a base 2 literal + 0b6; //~ ERROR invalid digit for a base 2 literal + 0b7; //~ ERROR invalid digit for a base 2 literal + 0b8; //~ ERROR invalid digit for a base 2 literal + 0b9; //~ ERROR invalid digit for a base 2 literal +} diff --git a/src/test/parse-fail/lex-bad-char-literals.rs b/src/test/parse-fail/lex-bad-char-literals.rs index fbe03e355e..4aa01bcde6 100644 --- a/src/test/parse-fail/lex-bad-char-literals.rs +++ b/src/test/parse-fail/lex-bad-char-literals.rs @@ -8,36 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -static c: char = - '\u539_' //~ ERROR: illegal character in numeric character escape - //~^ WARNING: \uABCD escapes are deprecated -; - -static c2: char = - '\Uffffffff' //~ ERROR: illegal numeric character escape - //~^ WARNING: \uABCD escapes are deprecated -; - static c3: char = '\x1' //~ ERROR: numeric character escape is too short ; -static c4: char = - '\u23q' //~ ERROR: illegal character in numeric character escape - //~^ WARNING: \uABCD escapes are deprecated -; -//~^^^ ERROR: numeric character escape is too short - static s: &'static str = "\x1" //~ ERROR: numeric character escape is too short ; -static s2: &'static str = - "\u23q" //~ ERROR: illegal character in numeric character escape - //~^ ERROR: numeric character escape is too short - //~^^ WARNING: \uABCD escapes are deprecated -; - static c: char = '\●' //~ ERROR: unknown character escape ; diff --git a/src/test/parse-fail/lex-bad-numeric-literals.rs b/src/test/parse-fail/lex-bad-numeric-literals.rs index 9a490be6a0..62b87e3f48 100644 --- a/src/test/parse-fail/lex-bad-numeric-literals.rs +++ b/src/test/parse-fail/lex-bad-numeric-literals.rs @@ -22,7 +22,7 @@ fn main() { 1e+; //~ ERROR: expected at least one digit in exponent 0x539.0; //~ ERROR: hexadecimal float literal is not supported 99999999999999999999999999999999; //~ ERROR: int literal is too large - 99999999999999999999999999999999u32; //~ ERROR: int literal is too large + 99999999999999999999999999999999; //~ ERROR: int literal is too large 0x; //~ ERROR: no valid digits 0xu32; //~ ERROR: no valid digits 0ou32; //~ ERROR: no valid digits diff --git a/src/test/parse-fail/lex-bad-octal-literal.rs b/src/test/parse-fail/lex-bad-octal-literal.rs new file mode 100644 index 0000000000..bf9880cb6c --- /dev/null +++ b/src/test/parse-fail/lex-bad-octal-literal.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 0o18; //~ ERROR invalid digit for a base 8 literal + 0o1234_9_5670; //~ ERROR invalid digit for a base 8 literal +} diff --git a/src/test/parse-fail/macro-attribute.rs b/src/test/parse-fail/macro-attribute.rs index 77ea0c9c4f..52f867fe91 100644 --- a/src/test/parse-fail/macro-attribute.rs +++ b/src/test/parse-fail/macro-attribute.rs @@ -10,4 +10,3 @@ #[doc = $not_there] //~ error: unexpected token: `$` fn main() { } - diff --git a/src/test/parse-fail/macros-no-semicolon.rs b/src/test/parse-fail/macros-no-semicolon.rs index 0e85551e21..23b27b49a8 100644 --- a/src/test/parse-fail/macros-no-semicolon.rs +++ b/src/test/parse-fail/macros-no-semicolon.rs @@ -13,4 +13,3 @@ fn main() { assert!(3 == 4) //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `assert` println!("hello"); } - diff --git a/src/test/parse-fail/multitrait.rs b/src/test/parse-fail/multitrait.rs index f182eb8fa5..a8b2fa4e11 100644 --- a/src/test/parse-fail/multitrait.rs +++ b/src/test/parse-fail/multitrait.rs @@ -13,7 +13,7 @@ struct S { } impl Cmp, ToString for S { -//~^ ERROR: expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` +//~^ ERROR: expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `,` fn eq(&&other: S) { false } fn to_string(&self) -> String { "hi".to_string() } } diff --git a/src/test/parse-fail/new-unicode-escapes-4.rs b/src/test/parse-fail/new-unicode-escapes-4.rs index ffc2b11e0c..96b86f1f56 100644 --- a/src/test/parse-fail/new-unicode-escapes-4.rs +++ b/src/test/parse-fail/new-unicode-escapes-4.rs @@ -9,5 +9,8 @@ // except according to those terms. pub fn main() { - let s = "\u{lol}"; //~ ERROR illegal character in unicode escape + let s = "\u{lol}"; + //~^ ERROR illegal character in unicode escape: l + //~^^ ERROR illegal character in unicode escape: o + //~^^^ ERROR illegal character in unicode escape: l } diff --git a/src/test/parse-fail/obsolete-closure-kind.rs b/src/test/parse-fail/obsolete-closure-kind.rs new file mode 100644 index 0000000000..89134e806a --- /dev/null +++ b/src/test/parse-fail/obsolete-closure-kind.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we generate obsolete syntax errors around usages of closure kinds: `|:|`, `|&:|` and +// `|&mut:|`. + +fn main() { + let a = |:| {}; //~ ERROR obsolete syntax: `:`, `&mut:`, or `&:` + let a = |&:| {}; //~ ERROR obsolete syntax: `:`, `&mut:`, or `&:` + let a = |&mut:| {}; //~ ERROR obsolete syntax: `:`, `&mut:`, or `&:` +} diff --git a/src/test/parse-fail/obsolete-proc.rs b/src/test/parse-fail/obsolete-proc.rs index 5208cdb6ad..4767c66c2a 100644 --- a/src/test/parse-fail/obsolete-proc.rs +++ b/src/test/parse-fail/obsolete-proc.rs @@ -10,8 +10,8 @@ // Test that we generate obsolete syntax errors around usages of `proc`. -fn foo(p: proc()) { } //~ ERROR obsolete syntax: the `proc` type +fn foo(p: proc()) { } //~ ERROR `proc` is a reserved keyword -fn bar() { proc() 1; } //~ ERROR obsolete syntax: `proc` expression +fn bar() { proc() 1; } fn main() { } diff --git a/src/test/parse-fail/raw-byte-string-eof.rs b/src/test/parse-fail/raw-byte-string-eof.rs index 83ea9db39b..ccf9e2d868 100644 --- a/src/test/parse-fail/raw-byte-string-eof.rs +++ b/src/test/parse-fail/raw-byte-string-eof.rs @@ -12,5 +12,3 @@ pub fn main() { br##"a"#; //~ unterminated raw string } - - diff --git a/src/test/parse-fail/raw-byte-string-literals.rs b/src/test/parse-fail/raw-byte-string-literals.rs index 7a3d1b2318..d6073a1030 100644 --- a/src/test/parse-fail/raw-byte-string-literals.rs +++ b/src/test/parse-fail/raw-byte-string-literals.rs @@ -13,5 +13,3 @@ pub fn main() { br"é"; //~ raw byte string must be ASCII br##~"a"~##; //~ only `#` is allowed in raw string delimitation } - - diff --git a/src/test/parse-fail/regions-trait-2.rs b/src/test/parse-fail/regions-trait-2.rs index 8b36e87db3..7a7113cd59 100644 --- a/src/test/parse-fail/regions-trait-2.rs +++ b/src/test/parse-fail/regions-trait-2.rs @@ -26,7 +26,7 @@ impl<'a> get_ctxt for has_ctxt<'a> { } fn make_gc() -> @get_ctxt { - let ctxt = ctxt { v: 22us }; + let ctxt = ctxt { v: 22 }; let hc = has_ctxt { c: &ctxt }; return @hc as @get_ctxt; //~^ ERROR source contains reference diff --git a/src/test/parse-fail/struct-literal-in-for.rs b/src/test/parse-fail/struct-literal-in-for.rs index 4bb5d5e6aa..a6d4da526f 100644 --- a/src/test/parse-fail/struct-literal-in-for.rs +++ b/src/test/parse-fail/struct-literal-in-for.rs @@ -25,4 +25,3 @@ fn main() { println!("yo"); } } - diff --git a/src/test/parse-fail/struct-literal-in-if.rs b/src/test/parse-fail/struct-literal-in-if.rs index b2bc8a4901..00ece3fcca 100644 --- a/src/test/parse-fail/struct-literal-in-if.rs +++ b/src/test/parse-fail/struct-literal-in-if.rs @@ -25,4 +25,3 @@ fn main() { println!("yo"); } } - diff --git a/src/test/parse-fail/struct-literal-in-match-discriminant.rs b/src/test/parse-fail/struct-literal-in-match-discriminant.rs index e6948b7c7c..cdcf98a42f 100644 --- a/src/test/parse-fail/struct-literal-in-match-discriminant.rs +++ b/src/test/parse-fail/struct-literal-in-match-discriminant.rs @@ -21,4 +21,3 @@ fn main() { } => {} } } - diff --git a/src/test/parse-fail/struct-literal-in-while.rs b/src/test/parse-fail/struct-literal-in-while.rs index 05fa3a8dd5..c23b5dbb9c 100644 --- a/src/test/parse-fail/struct-literal-in-while.rs +++ b/src/test/parse-fail/struct-literal-in-while.rs @@ -25,4 +25,3 @@ fn main() { println!("yo"); } } - diff --git a/src/test/parse-fail/trailing-plus-in-bounds.rs b/src/test/parse-fail/trailing-plus-in-bounds.rs index e8f9ed4d2c..8febbf8309 100644 --- a/src/test/parse-fail/trailing-plus-in-bounds.rs +++ b/src/test/parse-fail/trailing-plus-in-bounds.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; fn main() { - let x: Box = box 3 as Box; + let x: Box = box 3 as Box; //~^ ERROR at least one type parameter bound must be specified //~^^ ERROR at least one type parameter bound must be specified } - diff --git a/src/test/parse-fail/trait-bounds-not-on-impl.rs b/src/test/parse-fail/trait-bounds-not-on-impl.rs index a034352c4a..51447b2257 100644 --- a/src/test/parse-fail/trait-bounds-not-on-impl.rs +++ b/src/test/parse-fail/trait-bounds-not-on-impl.rs @@ -13,7 +13,9 @@ trait Foo { struct Bar; -impl Foo + Owned for Bar { //~ ERROR not a trait +impl Foo + Owned for Bar { +//~^ ERROR not a trait +//~^^ ERROR expected one of `..`, `where`, or `{`, found `Bar` } fn main() { } diff --git a/src/test/parse-fail/trait-pub-assoc-ty.rs b/src/test/parse-fail/trait-pub-assoc-ty.rs new file mode 100644 index 0000000000..02d76234d4 --- /dev/null +++ b/src/test/parse-fail/trait-pub-assoc-ty.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + pub type Foo; //~ ERROR expected one of `extern`, `fn`, `type`, or `unsafe`, found `pub` +} + +fn main() {} diff --git a/src/test/parse-fail/trait-pub-method.rs b/src/test/parse-fail/trait-pub-method.rs new file mode 100644 index 0000000000..e76802d2ea --- /dev/null +++ b/src/test/parse-fail/trait-pub-method.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + pub fn foo(); //~ ERROR expected one of `extern`, `fn`, `type`, or `unsafe`, found `pub` +} + +fn main() {} diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs index 54ddb3e19f..191bd78212 100644 --- a/src/test/parse-fail/type-parameters-in-field-exprs.rs +++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs @@ -21,4 +21,3 @@ fn main() { f.x::; //~^ ERROR field expressions may not have type parameters } - diff --git a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs index d86f55d536..de6291c7cc 100644 --- a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs +++ b/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs @@ -26,4 +26,3 @@ fn bar() { } fn main() { } - diff --git a/src/test/parse-fail/use-mod-4.rs b/src/test/parse-fail/use-mod-4.rs index a8b551b537..52d0d1a5fb 100644 --- a/src/test/parse-fail/use-mod-4.rs +++ b/src/test/parse-fail/use-mod-4.rs @@ -12,4 +12,3 @@ use foo::self; //~^ ERROR expected identifier, found keyword `self` fn main() {} - diff --git a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs index b96c7c2de6..ebdbdc4b2b 100644 --- a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs +++ b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs @@ -20,4 +20,3 @@ fn equal2(_: &T, _: &T) -> bool where T: { fn main() { } - diff --git a/src/test/pretty/asm-clobbers.rs b/src/test/pretty/asm-clobbers.rs index 20a3ac226b..c72add8d3d 100644 --- a/src/test/pretty/asm-clobbers.rs +++ b/src/test/pretty/asm-clobbers.rs @@ -11,4 +11,3 @@ #![feature(asm)] pub fn main() { unsafe { asm!("" : : : "hello", "world") }; } - diff --git a/src/test/pretty/blank-lines.rs b/src/test/pretty/blank-lines.rs index 1774edd3f7..4d135801da 100644 --- a/src/test/pretty/blank-lines.rs +++ b/src/test/pretty/blank-lines.rs @@ -9,7 +9,7 @@ // except according to those terms. // pp-exact -fn f() -> [int; 3] { +fn f() -> [isize; 3] { let picard = 0; let data = 1; diff --git a/src/test/pretty/block-comment-wchar.pp b/src/test/pretty/block-comment-wchar.pp index 5a55cb4e56..a5d82277d2 100644 --- a/src/test/pretty/block-comment-wchar.pp +++ b/src/test/pretty/block-comment-wchar.pp @@ -105,10 +105,11 @@ fn f() { fn main() { // Taken from http://www.unicode.org/Public/UNIDATA/PropList.txt let chars = - ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u0085', '\u00A0', '\u1680', - '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', - '\u2007', '\u2008', '\u2009', '\u200A', '\u2028', '\u2029', '\u202F', - '\u205F', '\u3000']; + ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}', + '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', + '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', + '\u{2009}', '\u{200A}', '\u{2028}', '\u{2029}', '\u{202F}', + '\u{205F}', '\u{3000}']; for c in &chars { let ws = c.is_whitespace(); println!("{} {}" , c , ws); diff --git a/src/test/pretty/block-comment-wchar.rs b/src/test/pretty/block-comment-wchar.rs index c82bdcd8dc..eb6d2a4a0a 100644 --- a/src/test/pretty/block-comment-wchar.rs +++ b/src/test/pretty/block-comment-wchar.rs @@ -99,10 +99,11 @@ fn f() { fn main() { // Taken from http://www.unicode.org/Public/UNIDATA/PropList.txt let chars = - ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u0085', '\u00A0', '\u1680', - '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', - '\u2007', '\u2008', '\u2009', '\u200A', '\u2028', '\u2029', '\u202F', - '\u205F', '\u3000']; + ['\x0A', '\x0B', '\x0C', '\x0D', '\x20', '\u{85}', '\u{A0}', + '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', + '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', + '\u{2009}', '\u{200A}', '\u{2028}', '\u{2029}', '\u{202F}', + '\u{205F}', '\u{3000}']; for c in &chars { let ws = c.is_whitespace(); println!("{} {}", c , ws); diff --git a/src/test/pretty/block-disambig.rs b/src/test/pretty/block-disambig.rs index c9cb72d8af..3d5e6e78de 100644 --- a/src/test/pretty/block-disambig.rs +++ b/src/test/pretty/block-disambig.rs @@ -17,10 +17,10 @@ use std::cell::Cell; fn test1() { let val = &0; { } *val; } -fn test2() -> int { let val = &0; { } *val } +fn test2() -> isize { let val = &0; { } *val } -#[derive(Copy)] -struct S { eax: int } +#[derive(Copy, Clone)] +struct S { eax: isize } fn test3() { let regs = &Cell::new(S {eax: 0}); @@ -30,17 +30,17 @@ fn test3() { fn test4() -> bool { let regs = &true; if true { } *regs || false } -fn test5() -> (int, int) { { } (0, 1) } +fn test5() -> (isize, isize) { { } (0, 1) } fn test6() -> bool { { } (true || false) && true } -fn test7() -> uint { +fn test7() -> usize { let regs = &0; match true { true => { } _ => { } } - (*regs < 2) as uint + (*regs < 2) as usize } -fn test8() -> int { +fn test8() -> isize { let val = &0; match true { true => { } @@ -58,10 +58,10 @@ fn test9() { match true { true => { } _ => { } } regs.set(regs.get() + 1); } -fn test10() -> int { +fn test10() -> isize { let regs = vec!(0); match true { true => { } _ => { } } regs[0] } -fn test11() -> Vec { if true { } vec!(1, 2) } +fn test11() -> Vec { if true { } vec!(1, 2) } diff --git a/src/test/pretty/closure-reform-pretty.rs b/src/test/pretty/closure-reform-pretty.rs index 094e3ce915..63568dbcd5 100644 --- a/src/test/pretty/closure-reform-pretty.rs +++ b/src/test/pretty/closure-reform-pretty.rs @@ -17,11 +17,10 @@ fn call_it(f: Box String>) { } fn call_this(f: F) where F: Fn(&str) + Send { } -fn call_that(f: F) where F: for<'a>Fn(&'a int, &'a int) -> int { } +fn call_that(f: F) where F: for<'a>Fn(&'a isize, &'a isize) -> isize { } -fn call_extern(f: fn() -> int) { } +fn call_extern(f: fn() -> isize) { } -fn call_abid_extern(f: extern "C" fn() -> int) { } +fn call_abid_extern(f: extern "C" fn() -> isize) { } pub fn main() { } - diff --git a/src/test/run-pass/coherence-local-2.rs b/src/test/pretty/default-trait-impl.rs similarity index 75% rename from src/test/run-pass/coherence-local-2.rs rename to src/test/pretty/default-trait-impl.rs index 07a830cb1a..509bee9def 100644 --- a/src/test/run-pass/coherence-local-2.rs +++ b/src/test/pretty/default-trait-impl.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:coherence-lib.rs +#![feature(optin_builtin_traits, core)] -extern crate "coherence-lib" as lib; -use lib::Remote; +// pp-exact -struct Local(T); +use std::marker::MarkerTrait; -impl Remote for Vec> { } +trait MyTrait: MarkerTrait { } -fn main() { } +impl MyTrait for .. { } + +pub fn main() { } diff --git a/src/test/pretty/disamb-stmt-expr.rs b/src/test/pretty/disamb-stmt-expr.rs index 0c4cd103b8..610d9a7782 100644 --- a/src/test/pretty/disamb-stmt-expr.rs +++ b/src/test/pretty/disamb-stmt-expr.rs @@ -14,7 +14,7 @@ // preserved. They are needed to disambiguate `{return n+1}; - 0` from // `({return n+1}-0)`. -fn id(f: F) -> int where F: Fn() -> int { f() } +fn id(f: F) -> isize where F: Fn() -> isize { f() } -fn wsucc(_n: int) -> int { id(|| { 1 }) - 0 } +fn wsucc(_n: isize) -> isize { id(|| { 1 }) - 0 } fn main() { } diff --git a/src/test/pretty/do1.rs b/src/test/pretty/do1.rs index e0066053f3..a85f85a395 100644 --- a/src/test/pretty/do1.rs +++ b/src/test/pretty/do1.rs @@ -10,6 +10,6 @@ // pp-exact -fn f(f: F) where F: Fn(int) { f(10) } +fn f(f: F) where F: Fn(isize) { f(10) } fn main() { f(|i| { assert!(i == 10) }) } diff --git a/src/test/pretty/empty-impl.rs b/src/test/pretty/empty-impl.rs index f5205de5c1..b30f226435 100644 --- a/src/test/pretty/empty-impl.rs +++ b/src/test/pretty/empty-impl.rs @@ -9,7 +9,7 @@ // except according to those terms. trait X { fn dummy(&self) { } } -impl X for uint { } +impl X for usize { } trait Y { fn dummy(&self) { } } -impl Y for uint { } +impl Y for usize { } diff --git a/src/test/pretty/empty-lines.rs b/src/test/pretty/empty-lines.rs index 58f6ae960b..3104941fb4 100644 --- a/src/test/pretty/empty-lines.rs +++ b/src/test/pretty/empty-lines.rs @@ -11,7 +11,7 @@ // Issue #759 // Whitespace under block opening should not expand forever -fn a() -> uint { +fn a() -> usize { - 1usize + 1 } diff --git a/src/test/pretty/for-comment.rs b/src/test/pretty/for-comment.rs index 0f2a667e11..43c41deaae 100644 --- a/src/test/pretty/for-comment.rs +++ b/src/test/pretty/for-comment.rs @@ -10,7 +10,7 @@ // pp-exact -fn f(v: &[int]) -> int { +fn f(v: &[isize]) -> isize { let mut n = 0; for e in v { n = *e; // This comment once triggered pretty printer bug diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 83ee2bd08f..c2ed10ce6a 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -3,7 +3,7 @@ #[prelude_import] use std::prelude::v1::*; #[macro_use] -extern crate "std" as std; +extern crate std as std; // 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. @@ -26,12 +26,12 @@ pub fn bar() { const FOO: usize = ((5 as usize) - (4 as usize) as usize); let _: [(); (FOO as usize)] = ([(() as ())] as [(); 1]); - let _: [(); (1usize as usize)] = ([(() as ())] as [(); 1]); + let _: [(); (1 as usize)] = ([(() as ())] as [(); 1]); let _ = (((&((([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3]) as &[i32; 3]) as *const _ as *const [i32; 3]) as - *const [i32; (3usize as usize)] as *const [i32; 3]); + *const [i32; (3 as usize)] as *const [i32; 3]); diff --git a/src/test/pretty/issue-4264.rs b/src/test/pretty/issue-4264.rs index 3aa2f4826b..90757c92c4 100644 --- a/src/test/pretty/issue-4264.rs +++ b/src/test/pretty/issue-4264.rs @@ -20,9 +20,9 @@ pub fn bar() { const FOO: usize = 5 - 4; let _: [(); FOO] = [()]; - let _ : [(); 1usize] = [()]; + let _ : [(); 1] = [()]; - let _ = &([1,2,3]) as *const _ as *const [i32; 3usize]; + let _ = &([1,2,3]) as *const _ as *const [i32; 3]; format!("test"); } diff --git a/src/test/pretty/path-type-bounds.rs b/src/test/pretty/path-type-bounds.rs index 9e1f2aa8bf..06d57b261e 100644 --- a/src/test/pretty/path-type-bounds.rs +++ b/src/test/pretty/path-type-bounds.rs @@ -14,13 +14,12 @@ trait Tr { fn dummy(&self) { } } -impl Tr for int { } +impl Tr for isize { } fn foo<'a>(x: Box) -> Box { x } fn main() { let x: Box; - Box::new(1) as Box; + Box::new(1isize) as Box; } - diff --git a/src/test/pretty/raw-str-nonexpr.rs b/src/test/pretty/raw-str-nonexpr.rs index 965b1760f1..bce78e4f4c 100644 --- a/src/test/pretty/raw-str-nonexpr.rs +++ b/src/test/pretty/raw-str-nonexpr.rs @@ -13,6 +13,6 @@ #![feature(asm)] #[cfg(foo = r#"just parse this"#)] -extern crate r##"blah"## as blah; +extern crate blah as blah; fn main() { unsafe { asm!(r###"blah"###); } } diff --git a/src/test/pretty/record-trailing-comma.rs b/src/test/pretty/record-trailing-comma.rs index 1cdf2e6de4..dd7fbf32dd 100644 --- a/src/test/pretty/record-trailing-comma.rs +++ b/src/test/pretty/record-trailing-comma.rs @@ -11,8 +11,8 @@ // ignore-test // pp-exact struct Thing { - x: int, - y: int, + x: isize, + y: isize, } fn main() { diff --git a/src/test/pretty/struct-tuple.rs b/src/test/pretty/struct-tuple.rs index acd534ccbf..82d430b270 100644 --- a/src/test/pretty/struct-tuple.rs +++ b/src/test/pretty/struct-tuple.rs @@ -10,11 +10,11 @@ // pp-exact struct Foo; -struct Bar(int, int); +struct Bar(isize, isize); fn main() { struct Foo2; - struct Bar2(int, int, int); + struct Bar2(isize, isize, isize); let _a = Bar(5, 5); let _b = Foo; } diff --git a/src/test/pretty/trait-safety.rs b/src/test/pretty/trait-safety.rs index b96dbbf3cc..95dfc751ff 100644 --- a/src/test/pretty/trait-safety.rs +++ b/src/test/pretty/trait-safety.rs @@ -14,7 +14,7 @@ unsafe trait UnsafeTrait { fn foo(&self); } -unsafe impl UnsafeTrait for int { +unsafe impl UnsafeTrait for isize { fn foo(&self) { } } diff --git a/src/test/pretty/unary-op-disambig.rs b/src/test/pretty/unary-op-disambig.rs index 1592e010aa..2a9066accd 100644 --- a/src/test/pretty/unary-op-disambig.rs +++ b/src/test/pretty/unary-op-disambig.rs @@ -12,16 +12,16 @@ fn f() { } -fn block_semi() -> int { { f() }; -1 } +fn block_semi() -> isize { { f() }; -1 } -fn block_nosemi() -> int { ({ 0 }) - 1 } +fn block_nosemi() -> isize { ({ 0 }) - 1 } -fn if_semi() -> int { if true { f() } else { f() }; -1 } +fn if_semi() -> isize { if true { f() } else { f() }; -1 } -fn if_nosemi() -> int { (if true { 0 } else { 0 }) - 1 } +fn if_nosemi() -> isize { (if true { 0 } else { 0 }) - 1 } -fn alt_semi() -> int { match true { true => { f() } _ => { } }; -1 } +fn alt_semi() -> isize { match true { true => { f() } _ => { } }; -1 } -fn alt_no_semi() -> int { (match true { true => { 0 } _ => { 1 } }) - 1 } +fn alt_no_semi() -> isize { (match true { true => { 0 } _ => { 1 } }) - 1 } fn stmt() { { f() }; -1; } diff --git a/src/test/pretty/where-clauses.rs b/src/test/pretty/where-clauses.rs index 0f3b914334..cca7707509 100644 --- a/src/test/pretty/where-clauses.rs +++ b/src/test/pretty/where-clauses.rs @@ -10,7 +10,6 @@ // pp-exact -fn f<'a, 'b, T>(t: T) -> int where T: 'a, 'a:'b, T: Eq { 0 } +fn f<'a, 'b, T>(t: T) -> isize where T: 'a, 'a:'b, T: Eq { 0 } fn main() { } - diff --git a/src/test/run-fail/args-panic.rs b/src/test/run-fail/args-panic.rs index eab7475bc8..47831f1af7 100644 --- a/src/test/run-fail/args-panic.rs +++ b/src/test/run-fail/args-panic.rs @@ -14,6 +14,6 @@ #![allow(unknown_features)] #![feature(box_syntax)] -fn f(_a: int, _b: int, _c: Box) { panic!("moop"); } +fn f(_a: isize, _b: isize, _c: Box) { panic!("moop"); } fn main() { f(1, panic!("meep"), box 42); } diff --git a/src/test/run-fail/assert-eq-macro-panic.rs b/src/test/run-fail/assert-eq-macro-panic.rs index fd6d69efb4..0b35062b18 100644 --- a/src/test/run-fail/assert-eq-macro-panic.rs +++ b/src/test/run-fail/assert-eq-macro-panic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`) +// error-pattern:assertion failed: `(left == right)` (left: `14`, right: `15`) fn main() { assert_eq!(14,15); diff --git a/src/test/compile-fail/binop-fail-3.rs b/src/test/run-fail/binop-fail-3.rs similarity index 84% rename from src/test/compile-fail/binop-fail-3.rs rename to src/test/run-fail/binop-fail-3.rs index 097a52b894..8cabd3b326 100644 --- a/src/test/compile-fail/binop-fail-3.rs +++ b/src/test/run-fail/binop-fail-3.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// error-pattern:quux fn foo() -> ! { panic!("quux"); } fn main() { - foo() //~ ERROR the type of this value must be known in this context - == - foo(); + foo() == foo(); // these types wind up being defaulted to () } diff --git a/src/test/run-fail/bounds-check-no-overflow.rs b/src/test/run-fail/bounds-check-no-overflow.rs index be4ad0781f..4d502cb210 100644 --- a/src/test/run-fail/bounds-check-no-overflow.rs +++ b/src/test/run-fail/bounds-check-no-overflow.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:index out of bounds: the len is 3 but the index is +// error-pattern:assertion failed: index < self.len() -use std::uint; +use std::usize; use std::mem::size_of; fn main() { let xs = [1, 2, 3]; - xs[uint::MAX / size_of::() + 1]; + xs[usize::MAX / size_of::() + 1]; } diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs b/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs index 6dd329b729..07fac8e39c 100644 --- a/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs +++ b/src/test/run-fail/bug-2470-bounds-check-overflow-2.rs @@ -11,7 +11,7 @@ // ignore-test // error-pattern:index out of bounds -use std::uint; +use std::usize; fn main() { let x = vec!(1_usize,2_usize,3_usize); @@ -21,7 +21,7 @@ fn main() { // length (in bytes), because the scaling of the index will cause it to // wrap around to a small number. - let idx = uint::MAX & !(uint::MAX >> 1_usize); + let idx = usize::MAX & !(usize::MAX >> 1_usize); println!("ov2 idx = 0x%x", idx); // This should panic. diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs b/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs index ec7fde1710..b7aff8d1be 100644 --- a/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs +++ b/src/test/run-fail/bug-2470-bounds-check-overflow-3.rs @@ -25,8 +25,8 @@ fn main() { let idx = u64::MAX & !(u64::MAX >> 1_usize); println!("ov3 idx = 0x%8.8x%8.8x", - (idx >> 32) as uint, - idx as uint); + (idx >> 32) as usize, + idx as usize); // This should panic. println!("ov3 0x%x", x[idx]); diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow.rs b/src/test/run-fail/bug-2470-bounds-check-overflow.rs index e48d749d94..5e3da8476a 100644 --- a/src/test/run-fail/bug-2470-bounds-check-overflow.rs +++ b/src/test/run-fail/bug-2470-bounds-check-overflow.rs @@ -22,13 +22,13 @@ fn main() { let x = vec!(1_usize,2_usize,3_usize); - let base = x.as_ptr() as uint; - let idx = base / mem::size_of::(); + let base = x.as_ptr() as usize; + let idx = base / mem::size_of::(); println!("ov1 base = 0x{:x}", base); println!("ov1 idx = 0x{:x}", idx); - println!("ov1 sizeof::() = 0x{:x}", mem::size_of::()); - println!("ov1 idx * sizeof::() = 0x{:x}", - idx * mem::size_of::()); + println!("ov1 sizeof::() = 0x{:x}", mem::size_of::()); + println!("ov1 idx * sizeof::() = 0x{:x}", + idx * mem::size_of::()); // This should panic. println!("ov1 0x{:x}", x[idx]); diff --git a/src/test/run-fail/bug-811.rs b/src/test/run-fail/bug-811.rs index 4ad8119728..fc64d7c1ba 100644 --- a/src/test/run-fail/bug-811.rs +++ b/src/test/run-fail/bug-811.rs @@ -12,10 +12,10 @@ use std::marker::PhantomData; -fn test00_start(ch: chan_t, message: int) { send(ch, message); } +fn test00_start(ch: chan_t, message: isize) { send(ch, message); } -type task_id = int; -type port_id = int; +type task_id = isize; +type port_id = isize; struct chan_t { task: task_id, diff --git a/src/test/run-fail/die-macro-expr.rs b/src/test/run-fail/die-macro-expr.rs index f2253b7342..16aa4d48d9 100644 --- a/src/test/run-fail/die-macro-expr.rs +++ b/src/test/run-fail/die-macro-expr.rs @@ -11,5 +11,5 @@ // error-pattern:test fn main() { - let __isize: int = panic!("test"); + let __isize: isize = panic!("test"); } diff --git a/src/test/run-fail/expr-if-panic-fn.rs b/src/test/run-fail/expr-if-panic-fn.rs index 987bee55c6..e9f493c16f 100644 --- a/src/test/run-fail/expr-if-panic-fn.rs +++ b/src/test/run-fail/expr-if-panic-fn.rs @@ -12,6 +12,6 @@ fn f() -> ! { panic!() } -fn g() -> int { let x = if true { f() } else { 10 }; return x; } +fn g() -> isize { let x = if true { f() } else { 10 }; return x; } fn main() { g(); } diff --git a/src/test/run-fail/expr-match-panic-fn.rs b/src/test/run-fail/expr-match-panic-fn.rs index 069c1d5ed3..0269eb0af9 100644 --- a/src/test/run-fail/expr-match-panic-fn.rs +++ b/src/test/run-fail/expr-match-panic-fn.rs @@ -12,6 +12,6 @@ fn f() -> ! { panic!() } -fn g() -> int { let x = match true { true => { f() } false => { 10 } }; return x; } +fn g() -> isize { let x = match true { true => { f() } false => { 10 } }; return x; } fn main() { g(); } diff --git a/src/test/run-fail/extern-panic.rs b/src/test/run-fail/extern-panic.rs index 225ce5a741..f4a3adba76 100644 --- a/src/test/run-fail/extern-panic.rs +++ b/src/test/run-fail/extern-panic.rs @@ -12,6 +12,7 @@ // error-pattern:explicit failure // Testing that runtime failure doesn't cause callbacks to abort abnormally. // Instead the failure will be delivered after the callbacks return. +#![feature(std_misc, libc)] extern crate libc; use std::task; @@ -26,14 +27,14 @@ mod rustrt { } extern fn cb(data: libc::uintptr_t) -> libc::uintptr_t { - if data == 1_usize { + if data == 1 { data } else { - count(data - 1_usize) + count(data - 1_usize) + count(data - 1) + count(data - 1) } } -fn count(n: uint) -> uint { +fn count(n: usize) -> usize { unsafe { task::deschedule(); rustrt::rust_dbg_call(cb, n) @@ -41,9 +42,9 @@ fn count(n: uint) -> uint { } fn main() { - for _ in 0..10_usize { + for _ in 0..10 { task::spawn(move|| { - let result = count(5_usize); + let result = count(5); println!("result = %?", result); panic!(); }); diff --git a/src/test/run-fail/hashmap-capacity-overflow.rs b/src/test/run-fail/hashmap-capacity-overflow.rs index c86f8a38f6..2c7c087522 100644 --- a/src/test/run-fail/hashmap-capacity-overflow.rs +++ b/src/test/run-fail/hashmap-capacity-overflow.rs @@ -11,11 +11,11 @@ // error-pattern:capacity overflow use std::collections::hash_map::HashMap; -use std::uint; +use std::usize; use std::mem::size_of; fn main() { - let threshold = uint::MAX / size_of::<(u64, u64, u64)>(); + let threshold = usize::MAX / size_of::<(u64, u64, u64)>(); let mut h = HashMap::::with_capacity(threshold + 100); h.insert(0, 0); } diff --git a/src/test/run-fail/if-check-panic.rs b/src/test/run-fail/if-check-panic.rs index 19a57db5ec..8c4caccdb6 100644 --- a/src/test/run-fail/if-check-panic.rs +++ b/src/test/run-fail/if-check-panic.rs @@ -9,13 +9,13 @@ // except according to those terms. // error-pattern:Number is odd -fn even(x: uint) -> bool { - if x < 2_usize { +fn even(x: usize) -> bool { + if x < 2 { return false; - } else if x == 2_usize { return true; } else { return even(x - 2_usize); } + } else if x == 2 { return true; } else { return even(x - 2); } } -fn foo(x: uint) { +fn foo(x: usize) { if even(x) { println!("{}", x); } else { @@ -23,4 +23,4 @@ fn foo(x: uint) { } } -fn main() { foo(3_usize); } +fn main() { foo(3); } diff --git a/src/test/run-fail/issue-2061.rs b/src/test/run-fail/issue-2061.rs index 49449be52a..7213d3ef7c 100644 --- a/src/test/run-fail/issue-2061.rs +++ b/src/test/run-fail/issue-2061.rs @@ -12,7 +12,7 @@ // error-pattern: task '