From 54a0048b59ea495a22e43a2e9a5fadf6d5912c15 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sun, 29 May 2016 17:53:46 +0200 Subject: [PATCH] Imported Upstream version 1.9.0+dfsg1 --- CONTRIBUTING.md | 7 +- README.md | 5 +- RELEASES.md | 338 +- configure | 26 +- man/rustc.1 | 4 +- mk/cfg/i586-pc-windows-msvc.mk | 28 + mk/cfg/i586-unknown-linux-gnu.mk | 6 +- mk/cfg/i686-pc-windows-gnu.mk | 2 - mk/cfg/x86_64-pc-windows-gnu.mk | 2 - mk/crates.mk | 69 +- mk/dist.mk | 3 +- mk/main.mk | 34 +- mk/rt.mk | 10 +- mk/target.mk | 1 + mk/tests.mk | 36 +- src/bootstrap/Cargo.lock | 40 +- src/bootstrap/Cargo.toml | 5 + src/bootstrap/bootstrap.py | 3 +- src/bootstrap/build/channel.rs | 15 +- src/bootstrap/build/check.rs | 35 + src/bootstrap/build/compile.rs | 172 +- src/bootstrap/build/dist.rs | 292 ++ src/bootstrap/build/doc.rs | 89 +- src/bootstrap/build/mod.rs | 212 +- src/bootstrap/build/native.rs | 7 +- src/bootstrap/build/sanity.rs | 14 +- src/bootstrap/build/step.rs | 210 +- src/bootstrap/build/util.rs | 12 +- src/bootstrap/main.rs | 1 + src/bootstrap/mk/Makefile.in | 8 + src/bootstrap/rustc.rs | 17 + src/bootstrap/rustdoc.rs | 31 + src/build_helper/lib.rs | 12 +- src/compiler-rt/cmake/config-ix.cmake | 7 +- src/compiler-rt/lib/builtins/CMakeLists.txt | 71 +- src/compiletest/common.rs | 14 +- src/compiletest/compiletest.rs | 104 +- src/compiletest/errors.rs | 123 +- src/compiletest/header.rs | 241 +- src/compiletest/procsrv.rs | 18 +- src/compiletest/runtest.rs | 427 ++- src/doc/book/SUMMARY.md | 2 +- src/doc/book/associated-types.md | 2 +- src/doc/book/casting-between-types.md | 14 +- src/doc/book/choosing-your-guarantees.md | 3 +- src/doc/book/closures.md | 7 +- src/doc/book/compiler-plugins.md | 57 +- src/doc/book/concurrency.md | 147 +- src/doc/book/const-and-static.md | 2 +- src/doc/book/crates-and-modules.md | 22 +- src/doc/book/drop.md | 2 +- src/doc/book/error-handling.md | 10 + src/doc/book/functions.md | 13 + src/doc/book/getting-started.md | 34 +- src/doc/book/guessing-game.md | 4 +- src/doc/book/if.md | 2 +- src/doc/book/inline-assembly.md | 3 +- src/doc/book/iterators.md | 5 + src/doc/book/lifetimes.md | 18 +- src/doc/book/macros.md | 6 +- src/doc/book/match.md | 14 +- src/doc/book/no-stdlib.md | 4 +- src/doc/book/ownership.md | 8 +- src/doc/book/patterns.md | 2 +- src/doc/book/primitive-types.md | 10 +- src/doc/book/references-and-borrowing.md | 14 +- src/doc/book/strings.md | 10 +- src/doc/book/syntax-index.md | 24 +- src/doc/book/testing.md | 4 - src/doc/book/traits.md | 4 +- src/doc/book/unsafe.md | 2 +- src/doc/book/variable-bindings.md | 4 +- src/doc/book/vectors.md | 34 +- src/doc/guide-plugins.md | 2 +- src/doc/nomicon/coercions.md | 2 +- src/doc/nomicon/vec.md | 2 +- src/doc/reference.md | 62 +- src/doc/style/README.md | 2 +- .../features/functions-and-methods/input.md | 2 +- src/doc/style/features/traits/generics.md | 5 +- src/doc/style/style/naming/README.md | 2 +- src/etc/CONFIGS.md | 4 - src/etc/platform-intrinsics/generator.py | 76 +- src/etc/platform-intrinsics/x86/avx.json | 77 + src/etc/platform-intrinsics/x86/fma.json | 47 + src/etc/tidy.py | 1 + src/etc/unicode.py | 4 +- src/jemalloc/COPYING | 4 +- src/jemalloc/ChangeLog | 335 +- src/jemalloc/INSTALL | 114 +- src/jemalloc/Makefile.in | 99 +- src/jemalloc/VERSION | 1 - src/jemalloc/bin/jemalloc-config.in | 79 + src/jemalloc/bin/{pprof => jeprof.in} | 250 +- src/jemalloc/{ => build-aux}/config.guess | 0 src/jemalloc/{ => build-aux}/config.sub | 0 src/jemalloc/{ => build-aux}/install-sh | 0 src/jemalloc/configure | 946 +++++- src/jemalloc/configure.ac | 334 +- src/jemalloc/doc/jemalloc.xml.in | 992 ++++-- .../include/jemalloc/internal/arena.h | 1118 ++++--- .../include/jemalloc/internal/assert.h | 45 + .../include/jemalloc/internal/atomic.h | 486 ++- src/jemalloc/include/jemalloc/internal/base.h | 4 +- .../include/jemalloc/internal/bitmap.h | 76 +- .../include/jemalloc/internal/chunk.h | 65 +- .../include/jemalloc/internal/chunk_dss.h | 3 +- .../include/jemalloc/internal/chunk_mmap.h | 5 +- src/jemalloc/include/jemalloc/internal/ckh.h | 6 +- src/jemalloc/include/jemalloc/internal/ctl.h | 13 +- .../include/jemalloc/internal/extent.h | 218 +- src/jemalloc/include/jemalloc/internal/hash.h | 38 +- src/jemalloc/include/jemalloc/internal/huge.h | 22 +- .../jemalloc/internal/jemalloc_internal.h.in | 744 +++-- .../internal/jemalloc_internal_decls.h | 25 +- .../internal/jemalloc_internal_defs.h.in | 72 +- .../include/jemalloc/internal/mutex.h | 12 + .../include/jemalloc/internal/nstime.h | 48 + .../include/jemalloc/internal/pages.h | 26 + .../jemalloc/internal/private_symbols.txt | 251 +- src/jemalloc/include/jemalloc/internal/prng.h | 67 +- src/jemalloc/include/jemalloc/internal/prof.h | 121 +- src/jemalloc/include/jemalloc/internal/ql.h | 4 +- src/jemalloc/include/jemalloc/internal/qr.h | 6 +- .../include/jemalloc/internal/quarantine.h | 6 +- src/jemalloc/include/jemalloc/internal/rb.h | 212 +- .../include/jemalloc/internal/rtree.h | 366 ++- .../include/jemalloc/internal/size_classes.sh | 41 +- .../include/jemalloc/internal/smoothstep.h | 246 ++ .../include/jemalloc/internal/smoothstep.sh | 115 + .../include/jemalloc/internal/stats.h | 75 +- .../include/jemalloc/internal/tcache.h | 238 +- .../include/jemalloc/internal/ticker.h | 75 + src/jemalloc/include/jemalloc/internal/tsd.h | 243 +- src/jemalloc/include/jemalloc/internal/util.h | 274 +- src/jemalloc/include/jemalloc/jemalloc.sh | 2 +- .../include/jemalloc/jemalloc_defs.h.in | 24 + .../include/jemalloc/jemalloc_macros.h.in | 94 +- .../include/jemalloc/jemalloc_protos.h.in | 76 +- .../include/jemalloc/jemalloc_typedefs.h.in | 59 +- .../include/msvc_compat/C99/inttypes.h | 313 -- src/jemalloc/include/msvc_compat/strings.h | 40 +- .../include/msvc_compat/windows_extra.h | 6 + src/jemalloc/jemalloc.pc.in | 3 +- src/jemalloc/msvc/ReadMe.txt | 24 + src/jemalloc/msvc/jemalloc_vc2015.sln | 63 + .../projects/vc2015/jemalloc/jemalloc.vcxproj | 396 +++ .../vc2015/jemalloc/jemalloc.vcxproj.filters | 257 ++ .../vc2015/test_threads/test_threads.cpp | 89 + .../vc2015/test_threads/test_threads.h | 3 + .../vc2015/test_threads/test_threads.vcxproj | 327 ++ .../test_threads/test_threads.vcxproj.filters | 26 + .../vc2015/test_threads/test_threads_main.cpp | 12 + src/jemalloc/src/arena.c | 2769 ++++++++++++----- src/jemalloc/src/base.c | 171 +- src/jemalloc/src/bitmap.c | 62 +- src/jemalloc/src/chunk.c | 772 +++-- src/jemalloc/src/chunk_dss.c | 31 +- src/jemalloc/src/chunk_mmap.c | 161 +- src/jemalloc/src/ckh.c | 47 +- src/jemalloc/src/ctl.c | 1013 ++++-- src/jemalloc/src/extent.c | 44 +- src/jemalloc/src/huge.c | 524 ++-- src/jemalloc/src/jemalloc.c | 1703 ++++++---- src/jemalloc/src/mutex.c | 10 +- src/jemalloc/src/nstime.c | 148 + src/jemalloc/src/pages.c | 173 + src/jemalloc/src/prng.c | 2 + src/jemalloc/src/prof.c | 392 ++- src/jemalloc/src/quarantine.c | 45 +- src/jemalloc/src/rtree.c | 140 +- src/jemalloc/src/stats.c | 471 +-- src/jemalloc/src/tcache.c | 274 +- src/jemalloc/src/ticker.c | 2 + src/jemalloc/src/tsd.c | 26 +- src/jemalloc/src/util.c | 36 +- src/jemalloc/src/zone.c | 8 +- .../test/include/test/jemalloc_test.h.in | 11 +- .../test/include/test/jemalloc_test_defs.h.in | 5 +- src/jemalloc/test/include/test/math.h | 2 +- src/jemalloc/test/include/test/mq.h | 19 +- src/jemalloc/test/include/test/test.h | 52 +- src/jemalloc/test/include/test/thd.h | 2 +- src/jemalloc/test/include/test/timer.h | 10 +- src/jemalloc/test/integration/chunk.c | 273 +- src/jemalloc/test/integration/mallocx.c | 161 +- src/jemalloc/test/integration/overflow.c | 49 + src/jemalloc/test/integration/rallocx.c | 93 +- src/jemalloc/test/integration/xallocx.c | 436 ++- src/jemalloc/test/src/mq.c | 29 + src/jemalloc/test/src/test.c | 4 +- src/jemalloc/test/src/timer.c | 16 +- src/jemalloc/test/stress/microbench.c | 16 +- src/jemalloc/test/unit/SFMT.c | 8 +- src/jemalloc/test/unit/atomic.c | 85 +- src/jemalloc/test/unit/bitmap.c | 22 +- src/jemalloc/test/unit/ckh.c | 22 +- src/jemalloc/test/unit/decay.c | 360 +++ src/jemalloc/test/unit/hash.c | 36 +- src/jemalloc/test/unit/junk.c | 89 +- src/jemalloc/test/unit/junk_alloc.c | 3 + src/jemalloc/test/unit/junk_free.c | 3 + src/jemalloc/test/unit/lg_chunk.c | 26 + src/jemalloc/test/unit/mallctl.c | 346 +- src/jemalloc/test/unit/mq.c | 1 + src/jemalloc/test/unit/nstime.c | 220 ++ src/jemalloc/test/unit/prng.c | 68 + src/jemalloc/test/unit/prof_active.c | 2 +- src/jemalloc/test/unit/prof_gdump.c | 29 +- src/jemalloc/test/unit/prof_reset.c | 130 +- src/jemalloc/test/unit/prof_thread_name.c | 3 +- src/jemalloc/test/unit/rb.c | 60 +- src/jemalloc/test/unit/rtree.c | 93 +- src/jemalloc/test/unit/run_quantize.c | 149 + src/jemalloc/test/unit/size_classes.c | 112 + src/jemalloc/test/unit/smoothstep.c | 106 + src/jemalloc/test/unit/stats.c | 153 +- src/jemalloc/test/unit/ticker.c | 76 + src/jemalloc/test/unit/tsd.c | 7 + src/jemalloc/test/unit/util.c | 69 +- src/jemalloc/test/unit/zero.c | 4 +- src/liballoc/arc.rs | 91 +- src/liballoc/boxed.rs | 8 +- src/liballoc/lib.rs | 6 +- src/liballoc/rc.rs | 51 +- src/liballoc_jemalloc/build.rs | 4 +- src/liballoc_jemalloc/lib.rs | 19 +- src/libarena/lib.rs | 468 +-- src/libcollections/binary_heap.rs | 152 +- src/libcollections/borrow.rs | 30 +- src/libcollections/btree/map.rs | 184 ++ src/libcollections/btree/set.rs | 40 +- src/libcollections/enum_set.rs | 8 +- src/libcollections/fmt.rs | 14 +- src/libcollections/lib.rs | 17 +- src/libcollections/linked_list.rs | 18 +- src/libcollections/macros.rs | 5 +- src/libcollections/range.rs | 1 + src/libcollections/slice.rs | 8 +- src/libcollections/str.rs | 33 +- src/libcollections/string.rs | 209 +- src/libcollections/vec.rs | 89 +- src/libcollections/vec_deque.rs | 11 +- src/libcollectionstest/btree/map.rs | 51 + src/libcollectionstest/lib.rs | 9 +- src/libcollectionstest/slice.rs | 62 +- src/libcollectionstest/str.rs | 51 +- src/libcollectionstest/vec_deque.rs | 4 - src/libcore/Cargo.toml | 1 + src/libcore/any.rs | 2 +- src/libcore/array.rs | 2 +- src/libcore/build.rs | 14 + src/libcore/cell.rs | 104 +- src/libcore/char.rs | 217 +- src/libcore/clone.rs | 25 +- src/libcore/cmp.rs | 35 + src/libcore/convert.rs | 20 +- src/libcore/fmt/builders.rs | 37 +- src/libcore/fmt/mod.rs | 168 +- src/libcore/fmt/num.rs | 77 - src/libcore/fmt/rt/v1.rs | 1 + src/libcore/hash/mod.rs | 32 +- src/libcore/hash/sip.rs | 21 +- src/libcore/intrinsics.rs | 67 +- src/libcore/iter.rs | 499 ++- src/libcore/lib.rs | 5 + src/libcore/macros.rs | 8 +- src/libcore/mem.rs | 2 +- src/libcore/num/dec2flt/mod.rs | 6 +- src/libcore/num/f32.rs | 2 +- src/libcore/num/f64.rs | 2 +- src/libcore/num/flt2dec/mod.rs | 1 + src/libcore/num/i16.rs | 2 +- src/libcore/num/i32.rs | 2 +- src/libcore/num/i64.rs | 2 +- src/libcore/num/i8.rs | 2 +- src/libcore/num/int_macros.rs | 19 - src/libcore/num/isize.rs | 2 +- src/libcore/num/mod.rs | 13 +- src/libcore/num/u16.rs | 2 +- src/libcore/num/u32.rs | 2 +- src/libcore/num/u64.rs | 2 +- src/libcore/num/u8.rs | 2 +- src/libcore/num/uint_macros.rs | 15 - src/libcore/num/usize.rs | 2 +- src/libcore/num/wrapping.rs | 151 +- src/libcore/ops.rs | 305 +- src/libcore/option.rs | 18 +- src/libcore/ptr.rs | 155 +- src/libcore/raw.rs | 12 + src/libcore/result.rs | 5 +- src/libcore/slice.rs | 414 ++- src/libcore/str/mod.rs | 331 +- src/libcore/str/pattern.rs | 20 +- src/libcore/sync/atomic.rs | 238 +- src/libcoretest/cell.rs | 20 + src/libcoretest/char.rs | 21 +- src/libcoretest/fmt/builders.rs | 20 +- src/libcoretest/fmt/num.rs | 104 - src/libcoretest/iter.rs | 46 +- src/libcoretest/lib.rs | 5 - src/libcoretest/num/int_macros.rs | 8 +- src/libcoretest/num/mod.rs | 4 +- src/libcoretest/option.rs | 6 +- src/libflate/lib.rs | 4 +- src/libgetopts/lib.rs | 22 +- src/libgraphviz/lib.rs | 117 +- src/liblibc/.travis.yml | 7 +- src/liblibc/Cargo.toml | 2 +- src/liblibc/appveyor.yml | 4 - src/liblibc/ci/landing-page-footer.html | 10 +- src/liblibc/ci/landing-page-head.html | 11 +- src/liblibc/ci/run-travis.sh | 32 +- src/liblibc/ci/style.rs | 204 ++ src/liblibc/libc-test/Cargo.lock | 37 +- src/liblibc/libc-test/build.rs | 32 +- .../libc-test/generate-files/Cargo.lock | 10 +- src/liblibc/src/lib.rs | 6 +- src/liblibc/src/macros.rs | 2 +- src/liblibc/src/unix/bsd/apple/b32.rs | 11 +- src/liblibc/src/unix/bsd/apple/b64.rs | 11 +- src/liblibc/src/unix/bsd/apple/mod.rs | 102 +- .../src/unix/bsd/freebsdlike/dragonfly.rs | 11 - .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 120 + .../src/unix/bsd/freebsdlike/freebsd.rs | 13 - .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 108 + .../unix/bsd/freebsdlike/{ => freebsd}/x86.rs | 0 .../bsd/freebsdlike/{ => freebsd}/x86_64.rs | 0 src/liblibc/src/unix/bsd/freebsdlike/mod.rs | 133 +- src/liblibc/src/unix/bsd/mod.rs | 30 +- .../src/unix/bsd/openbsdlike/bitrig.rs | 31 + src/liblibc/src/unix/bsd/openbsdlike/mod.rs | 45 +- .../src/unix/bsd/openbsdlike/netbsd.rs | 33 + .../src/unix/bsd/openbsdlike/openbsd.rs | 31 + src/liblibc/src/unix/mod.rs | 84 +- src/liblibc/src/unix/notbsd/android/b32.rs | 2 + src/liblibc/src/unix/notbsd/android/b64.rs | 2 + src/liblibc/src/unix/notbsd/android/mod.rs | 18 +- src/liblibc/src/unix/notbsd/linux/mips.rs | 17 +- src/liblibc/src/unix/notbsd/linux/mod.rs | 103 +- .../src/unix/notbsd/linux/musl/b32/arm.rs | 161 +- .../src/unix/notbsd/linux/musl/b32/asmjs.rs | 160 +- .../src/unix/notbsd/linux/musl/b32/mips.rs | 3 + .../src/unix/notbsd/linux/musl/b32/mod.rs | 10 +- .../src/unix/notbsd/linux/musl/b32/x86.rs | 162 +- .../src/unix/notbsd/linux/musl/b64/aarch64.rs | 1 + .../src/unix/notbsd/linux/musl/b64/mod.rs | 206 +- .../unix/notbsd/linux/musl/b64/powerpc64.rs | 1 + .../src/unix/notbsd/linux/musl/b64/x86_64.rs | 3 + src/liblibc/src/unix/notbsd/linux/musl/mod.rs | 5 + .../src/unix/notbsd/linux/other/b32/arm.rs | 3 + .../src/unix/notbsd/linux/other/b32/mod.rs | 24 +- .../unix/notbsd/linux/other/b32/powerpc.rs | 3 + .../src/unix/notbsd/linux/other/b32/x86.rs | 29 + .../unix/notbsd/linux/other/b64/aarch64.rs | 45 +- .../src/unix/notbsd/linux/other/b64/mod.rs | 4 +- .../unix/notbsd/linux/other/b64/powerpc64.rs | 45 +- .../src/unix/notbsd/linux/other/b64/x86_64.rs | 83 +- .../src/unix/notbsd/linux/other/mod.rs | 83 +- src/liblibc/src/unix/notbsd/mod.rs | 116 +- src/liblibc/src/unix/solaris/mod.rs | 19 +- src/liblibc/src/windows.rs | 10 +- src/librand/lib.rs | 7 +- src/librand/rand_impls.rs | 7 +- src/librbml/lib.rs | 124 +- src/librbml/opaque.rs | 26 +- src/librustc/Cargo.toml | 4 +- src/librustc/{middle => }/cfg/construct.rs | 45 +- src/librustc/{middle => }/cfg/graphviz.rs | 16 +- src/librustc/{middle => }/cfg/mod.rs | 6 +- src/librustc/dep_graph/README.md | 9 +- src/librustc/dep_graph/dep_node.rs | 205 ++ src/librustc/dep_graph/dep_tracking_map.rs | 3 +- src/librustc/dep_graph/edges.rs | 30 +- src/librustc/dep_graph/graph.rs | 71 + src/librustc/dep_graph/mod.rs | 203 +- src/librustc/dep_graph/query.rs | 40 +- src/librustc/dep_graph/raii.rs | 6 +- src/librustc/dep_graph/thread.rs | 17 +- src/librustc/dep_graph/visit.rs | 56 + src/librustc/diagnostics.rs | 614 +--- src/librustc/{front => hir}/check_attr.rs | 0 src/librustc/{middle => hir}/def.rs | 41 +- src/librustc/{middle => hir}/def_id.rs | 12 +- src/{librustc_front => librustc/hir}/fold.rs | 62 +- .../hir}/intravisit.rs | 291 +- .../hir}/lowering.rs | 228 +- src/librustc/{front => hir}/map/blocks.rs | 71 +- src/librustc/{front => hir}/map/collector.rs | 52 +- .../{front => hir}/map/definitions.rs | 184 +- src/librustc/{front => hir}/map/mod.rs | 333 +- .../hir.rs => librustc/hir/mod.rs} | 340 +- src/librustc/{middle => hir}/pat_util.rs | 31 +- .../print/pprust.rs => librustc/hir/print.rs} | 1531 +++++---- src/librustc/hir/svh.rs | 87 + src/librustc/{middle => }/infer/README.md | 0 src/librustc/{middle => }/infer/bivariate.rs | 18 +- src/librustc/{middle => }/infer/combine.rs | 74 +- src/librustc/{middle => }/infer/equate.rs | 25 +- .../{middle => }/infer/error_reporting.rs | 256 +- src/librustc/{middle => }/infer/freshen.rs | 21 +- src/librustc/{middle => }/infer/glb.rs | 15 +- .../infer/higher_ranked/README.md | 0 .../{middle => }/infer/higher_ranked/mod.rs | 38 +- src/librustc/{middle => }/infer/lattice.rs | 14 +- src/librustc/{middle => }/infer/lub.rs | 15 +- src/librustc/{middle => }/infer/mod.rs | 270 +- .../infer/region_inference/README.md | 0 .../infer/region_inference/graphviz.rs | 26 +- .../infer/region_inference/mod.rs | 97 +- src/librustc/{middle => }/infer/resolve.rs | 12 +- src/librustc/{middle => }/infer/sub.rs | 27 +- .../{middle => }/infer/type_variable.rs | 108 +- src/librustc/{middle => }/infer/unify_key.rs | 15 +- src/librustc/lib.rs | 41 +- src/librustc/lint/builtin.rs | 45 +- src/librustc/lint/context.rs | 138 +- src/librustc/lint/mod.rs | 4 +- src/librustc/macros.rs | 15 + src/librustc/middle/astconv_util.rs | 17 +- src/librustc/middle/const_eval.rs | 1406 --------- src/librustc/middle/const_val.rs | 101 + src/librustc/middle/cstore.rs | 283 +- src/librustc/middle/dataflow.rs | 31 +- src/librustc/middle/dead.rs | 71 +- src/librustc/middle/effect.rs | 23 +- src/librustc/middle/entry.rs | 8 +- src/librustc/middle/expr_use_visitor.rs | 81 +- src/librustc/middle/free_region.rs | 15 +- src/librustc/middle/intrinsicck.rs | 309 +- src/librustc/middle/lang_items.rs | 54 +- src/librustc/middle/liveness.rs | 156 +- src/librustc/middle/mem_categorization.rs | 156 +- src/librustc/middle/privacy.rs | 41 - src/librustc/middle/reachable.rs | 37 +- src/librustc/middle/region.rs | 44 +- src/librustc/middle/resolve_lifetime.rs | 38 +- src/librustc/middle/stability.rs | 66 +- src/librustc/middle/weak_lang_items.rs | 6 +- src/librustc/mir/mir_map.rs | 22 - src/librustc/mir/repr.rs | 210 +- src/librustc/mir/tcx.rs | 57 +- src/librustc/mir/transform.rs | 65 +- src/librustc/mir/visit.rs | 453 ++- src/librustc/session/config.rs | 165 +- src/librustc/session/filesearch.rs | 4 +- src/librustc/session/mod.rs | 87 +- src/librustc/{middle => }/traits/README.md | 40 + src/librustc/{middle => }/traits/coherence.rs | 122 +- .../{middle => }/traits/error_reporting.rs | 217 +- src/librustc/{middle => }/traits/fulfill.rs | 341 +- src/librustc/{middle => }/traits/mod.rs | 26 +- .../{middle => }/traits/object_safety.rs | 30 +- src/librustc/{middle => }/traits/project.rs | 301 +- src/librustc/{middle => }/traits/select.rs | 374 ++- src/librustc/traits/specialize/mod.rs | 219 ++ .../traits/specialize/specialization_graph.rs | 486 +++ .../{middle => }/traits/structural_impls.rs | 11 +- src/librustc/{middle => }/traits/util.rs | 83 +- src/librustc/{middle => }/ty/_match.rs | 14 +- src/librustc/{middle => }/ty/adjustment.rs | 44 +- src/librustc/{middle => }/ty/cast.rs | 4 +- src/librustc/{middle => }/ty/contents.rs | 16 +- src/librustc/{middle => }/ty/context.rs | 196 +- src/librustc/{middle => }/ty/error.rs | 18 +- src/librustc/{middle => }/ty/fast_reject.rs | 8 +- src/librustc/{middle => }/ty/flags.rs | 20 +- src/librustc/{middle => }/ty/fold.rs | 80 +- src/librustc/ty/item_path.rs | 364 +++ src/librustc/{middle => }/ty/ivar.rs | 11 +- src/librustc/ty/layout.rs | 1336 ++++++++ src/librustc/{middle => }/ty/maps.rs | 6 +- src/librustc/{middle => }/ty/mod.rs | 436 +-- src/librustc/{middle => }/ty/outlives.rs | 7 +- src/librustc/{middle => }/ty/relate.rs | 153 +- .../{middle => }/ty/structural_impls.rs | 125 +- src/librustc/{middle => }/ty/sty.rs | 105 +- src/librustc/{middle => ty}/subst.rs | 178 +- src/librustc/{middle => }/ty/trait_def.rs | 119 +- src/librustc/{middle => }/ty/util.rs | 322 +- src/librustc/{middle => }/ty/walk.rs | 8 +- src/librustc/{middle => }/ty/wf.rs | 18 +- src/librustc/util/common.rs | 6 +- src/librustc/util/nodemap.rs | 2 +- src/librustc/util/ppaux.rs | 393 +-- src/librustc_back/Cargo.toml | 2 - src/librustc_back/abi.rs | 24 - src/{libstd => librustc_back}/dynamic_lib.rs | 236 +- src/librustc_back/lib.rs | 9 +- src/librustc_back/target/aarch64_apple_ios.rs | 1 + .../target/aarch64_linux_android.rs | 1 + .../target/aarch64_unknown_linux_gnu.rs | 1 + .../target/arm_linux_androideabi.rs | 1 + .../target/arm_unknown_linux_gnueabi.rs | 1 + .../target/arm_unknown_linux_gnueabihf.rs | 1 + src/librustc_back/target/armv7_apple_ios.rs | 1 + .../target/armv7_unknown_linux_gnueabihf.rs | 1 + src/librustc_back/target/armv7s_apple_ios.rs | 1 + .../target/asmjs_unknown_emscripten.rs | 1 + src/librustc_back/target/i386_apple_ios.rs | 1 + .../target/i586_pc_windows_msvc.rs | 18 + .../target/i586_unknown_linux_gnu.rs | 18 +- src/librustc_back/target/i686_apple_darwin.rs | 1 + .../target/i686_linux_android.rs | 1 + .../target/i686_pc_windows_gnu.rs | 1 + .../target/i686_pc_windows_msvc.rs | 1 + .../target/i686_unknown_dragonfly.rs | 1 + .../target/i686_unknown_freebsd.rs | 1 + .../target/i686_unknown_linux_gnu.rs | 1 + .../target/i686_unknown_linux_musl.rs | 1 + src/librustc_back/target/le32_unknown_nacl.rs | 1 + .../target/mips_unknown_linux_gnu.rs | 1 + .../target/mips_unknown_linux_musl.rs | 1 + .../target/mipsel_unknown_linux_gnu.rs | 1 + .../target/mipsel_unknown_linux_musl.rs | 1 + src/librustc_back/target/mod.rs | 31 +- .../target/powerpc64_unknown_linux_gnu.rs | 1 + .../target/powerpc64le_unknown_linux_gnu.rs | 1 + .../target/powerpc_unknown_linux_gnu.rs | 1 + .../target/x86_64_apple_darwin.rs | 1 + src/librustc_back/target/x86_64_apple_ios.rs | 1 + .../target/x86_64_pc_windows_gnu.rs | 1 + .../target/x86_64_pc_windows_msvc.rs | 1 + .../target/x86_64_rumprun_netbsd.rs | 1 + .../target/x86_64_sun_solaris.rs | 1 + .../target/x86_64_unknown_bitrig.rs | 1 + .../target/x86_64_unknown_dragonfly.rs | 1 + .../target/x86_64_unknown_freebsd.rs | 1 + .../target/x86_64_unknown_linux_gnu.rs | 1 + .../target/x86_64_unknown_linux_musl.rs | 1 + .../target/x86_64_unknown_netbsd.rs | 1 + .../target/x86_64_unknown_openbsd.rs | 1 + src/librustc_back/tempdir.rs | 2 +- src/librustc_borrowck/Cargo.toml | 2 +- src/librustc_borrowck/bitslice.rs | 105 + src/librustc_borrowck/borrowck/check_loans.rs | 14 +- src/librustc_borrowck/borrowck/fragments.rs | 27 +- .../borrowck/gather_loans/gather_moves.rs | 8 +- .../borrowck/gather_loans/lifetime.rs | 2 +- .../borrowck/gather_loans/mod.rs | 31 +- .../borrowck/gather_loans/move_error.rs | 13 +- .../borrowck/gather_loans/restrictions.rs | 2 +- .../borrowck/mir/abs_domain.rs | 62 + .../borrowck/mir/dataflow.rs | 504 +++ .../borrowck/mir/gather_moves.rs | 744 +++++ .../borrowck/mir/graphviz.rs | 232 ++ src/librustc_borrowck/borrowck/mir/mod.rs | 91 + src/librustc_borrowck/borrowck/mod.rs | 107 +- src/librustc_borrowck/borrowck/move_data.rs | 26 +- src/librustc_borrowck/graphviz.rs | 14 +- src/librustc_borrowck/lib.rs | 9 +- src/librustc_const_eval/Cargo.toml | 18 + .../check_match.rs | 208 +- src/librustc_const_eval/diagnostics.rs | 545 ++++ src/librustc_const_eval/eval.rs | 1237 ++++++++ src/librustc_const_eval/lib.rs | 52 + .../Cargo.toml | 7 +- src/librustc_const_math/err.rs | 85 + src/librustc_const_math/int.rs | 569 ++++ src/librustc_const_math/is.rs | 39 + src/librustc_const_math/lib.rs | 43 + src/librustc_const_math/us.rs | 39 + src/librustc_data_structures/bitvec.rs | 64 +- src/librustc_data_structures/fnv.rs | 8 +- src/librustc_data_structures/graph/mod.rs | 136 +- src/librustc_data_structures/graph/tests.rs | 40 +- src/librustc_data_structures/ivar.rs | 15 +- src/librustc_data_structures/lib.rs | 3 +- .../obligation_forest/README.md | 4 +- .../obligation_forest/mod.rs | 152 +- .../obligation_forest/node_index.rs | 7 +- .../obligation_forest/test.rs | 105 +- .../obligation_forest/tree_index.rs | 3 +- src/librustc_data_structures/snapshot_vec.rs | 50 +- .../transitive_relation.rs | 118 +- src/librustc_data_structures/tuple_slice.rs | 14 +- src/librustc_data_structures/unify/mod.rs | 114 +- src/librustc_data_structures/unify/tests.rs | 35 +- src/librustc_data_structures/veccell/mod.rs | 4 +- src/librustc_driver/Cargo.toml | 5 +- src/librustc_driver/driver.rs | 252 +- src/librustc_driver/lib.rs | 190 +- src/librustc_driver/pretty.rs | 157 +- src/librustc_driver/test.rs | 103 +- src/librustc_front/lib.rs | 57 - src/librustc_front/util.rs | 362 --- src/librustc_incremental/Cargo.toml | 18 + .../assert_dep_graph.rs | 148 +- .../calculate_svh.rs} | 159 +- src/librustc_incremental/lib.rs | 41 + src/librustc_incremental/persist/README.md | 13 + src/librustc_incremental/persist/data.rs | 35 + src/librustc_incremental/persist/directory.rs | 118 + .../persist/dirty_clean.rs | 151 + src/librustc_incremental/persist/load.rs | 214 ++ src/librustc_incremental/persist/mod.rs | 23 + src/librustc_incremental/persist/save.rs | 136 + src/librustc_incremental/persist/serialize.rs | 0 src/librustc_incremental/persist/util.rs | 32 + src/librustc_lint/Cargo.toml | 2 +- src/librustc_lint/bad_style.rs | 25 +- src/librustc_lint/builtin.rs | 54 +- src/librustc_lint/lib.rs | 23 +- src/librustc_lint/types.rs | 131 +- src/librustc_lint/unused.rs | 10 +- src/librustc_llvm/build.rs | 20 +- src/librustc_llvm/lib.rs | 198 +- src/librustc_metadata/Cargo.toml | 2 +- src/librustc_metadata/astencode.rs | 199 +- src/librustc_metadata/common.rs | 14 +- src/librustc_metadata/creader.rs | 166 +- src/librustc_metadata/csearch.rs | 194 +- src/librustc_metadata/cstore.rs | 69 +- src/librustc_metadata/decoder.rs | 363 +-- src/librustc_metadata/diagnostics.rs | 2 + src/librustc_metadata/encoder.rs | 311 +- src/librustc_metadata/index.rs | 2 +- src/librustc_metadata/lib.rs | 4 +- src/librustc_metadata/loader.rs | 13 +- src/librustc_metadata/macro_import.rs | 11 +- src/librustc_metadata/tls_context.rs | 12 +- src/librustc_metadata/tydecode.rs | 66 +- src/librustc_metadata/tyencode.rs | 61 +- src/librustc_mir/Cargo.toml | 3 +- src/librustc_mir/build/block.rs | 68 +- src/librustc_mir/build/cfg.rs | 26 +- src/librustc_mir/build/expr/as_constant.rs | 5 +- src/librustc_mir/build/expr/as_lvalue.rs | 11 +- src/librustc_mir/build/expr/as_operand.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 32 +- src/librustc_mir/build/expr/as_temp.rs | 7 +- src/librustc_mir/build/expr/into.rs | 78 +- src/librustc_mir/build/matches/mod.rs | 99 +- src/librustc_mir/build/matches/simplify.rs | 20 +- src/librustc_mir/build/matches/test.rs | 150 +- src/librustc_mir/build/matches/util.rs | 6 +- src/librustc_mir/build/misc.rs | 24 +- src/librustc_mir/build/mod.rs | 220 +- src/librustc_mir/build/scope.rs | 372 ++- src/librustc_mir/build/stmt.rs | 83 - src/librustc_mir/graphviz.rs | 129 +- src/librustc_mir/hair/cx/block.rs | 78 +- src/librustc_mir/hair/cx/expr.rs | 192 +- src/librustc_mir/hair/cx/mod.rs | 69 +- src/librustc_mir/hair/cx/pattern.rs | 95 +- src/librustc_mir/hair/cx/to_ref.rs | 2 +- src/librustc_mir/hair/mod.rs | 27 +- src/librustc_mir/lib.rs | 6 +- src/librustc_mir/mir_map.rs | 133 +- src/librustc_mir/pretty.rs | 213 +- .../transform/break_critical_edges.rs | 117 + src/librustc_mir/transform/erase_regions.rs | 106 +- src/librustc_mir/transform/mod.rs | 3 +- src/librustc_mir/transform/no_landing_pads.rs | 32 +- ...r_dead_blocks.rs => remove_dead_blocks.rs} | 66 +- src/librustc_mir/transform/simplify_cfg.rs | 102 +- src/librustc_mir/transform/type_check.rs | 64 +- src/librustc_mir/traversal.rs | 276 ++ src/librustc_passes/Cargo.toml | 2 +- src/librustc_passes/const_fn.rs | 6 +- src/librustc_passes/consts.rs | 76 +- src/librustc_passes/lib.rs | 4 +- src/librustc_passes/loops.rs | 6 +- src/librustc_passes/rvalues.rs | 18 +- src/librustc_passes/static_recursion.rs | 26 +- src/librustc_platform_intrinsics/Cargo.toml | 4 - src/librustc_platform_intrinsics/aarch64.rs | 2717 ++++++++-------- src/librustc_platform_intrinsics/arm.rs | 1653 +++++----- src/librustc_platform_intrinsics/lib.rs | 99 +- src/librustc_platform_intrinsics/x86.rs | 1063 ++++--- src/librustc_plugin/Cargo.toml | 2 +- src/librustc_plugin/build.rs | 6 +- src/librustc_plugin/lib.rs | 3 +- src/librustc_plugin/load.rs | 14 +- src/librustc_plugin/registry.rs | 6 +- src/librustc_privacy/Cargo.toml | 1 - src/librustc_privacy/lib.rs | 999 +----- src/librustc_resolve/Cargo.toml | 1 - src/librustc_resolve/build_reduced_graph.rs | 426 +-- src/librustc_resolve/check_unused.rs | 71 +- src/librustc_resolve/diagnostics.rs | 45 - src/librustc_resolve/lib.rs | 1196 +++---- src/librustc_resolve/resolve_imports.rs | 777 +++-- src/librustc_save_analysis/Cargo.toml | 14 + src/librustc_save_analysis/csv_dumper.rs | 566 ++++ src/librustc_save_analysis/data.rs | 383 +++ src/librustc_save_analysis/dump.rs | 40 + .../dump_visitor.rs} | 766 +++-- .../mod.rs => librustc_save_analysis/lib.rs} | 347 +-- .../span_utils.rs | 28 +- src/librustc_trans/Cargo.toml | 5 +- src/librustc_trans/{trans => }/_match.rs | 160 +- src/librustc_trans/abi.rs | 546 ++++ src/librustc_trans/{trans => }/adt.rs | 183 +- src/librustc_trans/asm.rs | 120 + src/librustc_trans/attributes.rs | 110 + src/librustc_trans/back/archive.rs | 28 +- src/librustc_trans/back/link.rs | 268 +- src/librustc_trans/back/linker.rs | 17 +- src/librustc_trans/back/symbol_names.rs | 379 +++ src/librustc_trans/back/write.rs | 8 +- src/librustc_trans/{trans => }/base.rs | 1842 +++++------ src/librustc_trans/{trans => }/basic_block.rs | 8 +- src/librustc_trans/{trans => }/build.rs | 102 +- src/librustc_trans/{trans => }/builder.rs | 151 +- .../{trans => }/cabi_aarch64.rs | 79 +- src/librustc_trans/{trans => }/cabi_arm.rs | 69 +- src/librustc_trans/cabi_asmjs.rs | 55 + src/librustc_trans/{trans => }/cabi_mips.rs | 71 +- .../{trans => }/cabi_powerpc.rs | 71 +- .../{trans => }/cabi_powerpc64.rs | 84 +- src/librustc_trans/cabi_x86.rs | 53 + src/librustc_trans/{trans => }/cabi_x86_64.rs | 79 +- src/librustc_trans/cabi_x86_win64.rs | 41 + src/librustc_trans/callee.rs | 1039 +++++++ src/librustc_trans/{trans => }/cleanup.rs | 69 +- src/librustc_trans/closure.rs | 444 +++ src/librustc_trans/{trans => }/collector.rs | 386 +-- src/librustc_trans/{trans => }/common.rs | 348 +-- src/librustc_trans/{trans => }/consts.rs | 594 ++-- src/librustc_trans/{trans => }/context.rs | 188 +- src/librustc_trans/{trans => }/controlflow.rs | 83 +- src/librustc_trans/{trans => }/datum.rs | 77 +- .../{trans => }/debuginfo/create_scope_map.rs | 29 +- .../{trans => }/debuginfo/doc.rs | 0 .../{trans => }/debuginfo/gdb.rs | 13 +- .../{trans => }/debuginfo/metadata.rs | 210 +- .../{trans => }/debuginfo/mod.rs | 82 +- src/librustc_trans/debuginfo/namespace.rs | 127 + .../{trans => }/debuginfo/source_loc.rs | 2 +- .../{trans => }/debuginfo/type_names.rs | 55 +- .../{trans => }/debuginfo/utils.rs | 12 +- src/librustc_trans/declare.rs | 179 ++ src/librustc_trans/diagnostics.rs | 26 - src/librustc_trans/{trans => }/disr.rs | 6 +- src/librustc_trans/{trans => }/expr.rs | 712 ++--- src/librustc_trans/{trans => }/glue.rs | 200 +- src/librustc_trans/{trans => }/inline.rs | 108 +- src/librustc_trans/{trans => }/intrinsic.rs | 601 ++-- src/librustc_trans/lib.rs | 80 +- src/librustc_trans/{trans => }/machine.rs | 4 +- src/librustc_trans/{trans => }/macros.rs | 0 src/librustc_trans/meth.rs | 334 ++ src/librustc_trans/{trans => }/mir/analyze.rs | 5 +- src/librustc_trans/mir/block.rs | 666 ++++ src/librustc_trans/mir/constant.rs | 143 + src/librustc_trans/mir/drop.rs | 27 + src/librustc_trans/{trans => }/mir/lvalue.rs | 135 +- src/librustc_trans/{trans => }/mir/mod.rs | 194 +- src/librustc_trans/{trans => }/mir/operand.rs | 156 +- src/librustc_trans/{trans => }/mir/rvalue.rs | 237 +- .../{trans => }/mir/statement.rs | 8 +- src/librustc_trans/monomorphize.rs | 211 ++ src/librustc_trans/save/recorder.rs | 714 ----- src/librustc_trans/symbol_names_test.rs | 86 + src/librustc_trans/trans/asm.rs | 161 - src/librustc_trans/trans/attributes.rs | 307 -- src/librustc_trans/trans/cabi.rs | 137 - src/librustc_trans/trans/cabi_asmjs.rs | 72 - src/librustc_trans/trans/cabi_x86.rs | 85 - src/librustc_trans/trans/cabi_x86_win64.rs | 64 - src/librustc_trans/trans/callee.rs | 1096 ------- src/librustc_trans/trans/closure.rs | 429 --- .../trans/debuginfo/namespace.rs | 135 - src/librustc_trans/trans/declare.rs | 259 -- src/librustc_trans/trans/foreign.rs | 1070 ------- src/librustc_trans/trans/llrepr.rs | 36 - src/librustc_trans/trans/meth.rs | 658 ---- src/librustc_trans/trans/mir/block.rs | 422 --- src/librustc_trans/trans/mir/constant.rs | 99 - src/librustc_trans/trans/mir/did.rs | 171 - src/librustc_trans/trans/mod.rs | 84 - src/librustc_trans/trans/monomorphize.rs | 317 -- src/librustc_trans/{trans => }/tvec.rs | 94 +- src/librustc_trans/{trans => }/type_.rs | 47 +- src/librustc_trans/{trans => }/type_of.rs | 271 +- src/librustc_trans/{trans => }/value.rs | 17 +- src/librustc_typeck/Cargo.toml | 3 +- src/librustc_typeck/astconv.rs | 105 +- src/librustc_typeck/check/_match.rs | 131 +- src/librustc_typeck/check/assoc.rs | 6 +- src/librustc_typeck/check/callee.rs | 19 +- src/librustc_typeck/check/cast.rs | 52 +- src/librustc_typeck/check/closure.rs | 6 +- src/librustc_typeck/check/coercion.rs | 599 +++- src/librustc_typeck/check/compare_method.rs | 41 +- src/librustc_typeck/check/demand.rs | 64 +- src/librustc_typeck/check/dropck.rs | 67 +- src/librustc_typeck/check/intrinsic.rs | 44 +- src/librustc_typeck/check/method/confirm.rs | 224 +- src/librustc_typeck/check/method/mod.rs | 71 +- src/librustc_typeck/check/method/probe.rs | 71 +- src/librustc_typeck/check/method/suggest.rs | 165 +- src/librustc_typeck/check/mod.rs | 922 +++--- src/librustc_typeck/check/op.rs | 22 +- src/librustc_typeck/check/regionck.rs | 76 +- src/librustc_typeck/check/upvar.rs | 40 +- src/librustc_typeck/check/wfcheck.rs | 32 +- src/librustc_typeck/check/writeback.rs | 31 +- src/librustc_typeck/coherence/mod.rs | 93 +- src/librustc_typeck/coherence/orphan.rs | 14 +- src/librustc_typeck/coherence/overlap.rs | 291 +- src/librustc_typeck/coherence/unsafety.rs | 10 +- src/librustc_typeck/collect.rs | 382 +-- .../constrained_type_params.rs | 13 +- src/librustc_typeck/diagnostics.rs | 145 +- src/librustc_typeck/lib.rs | 90 +- src/librustc_typeck/rscope.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 53 +- src/librustc_typeck/variance/mod.rs | 4 +- src/librustc_typeck/variance/solve.rs | 4 +- src/librustc_typeck/variance/terms.rs | 16 +- src/librustc_typeck/variance/xform.rs | 2 +- src/librustc_unicode/char.rs | 335 +- src/librustc_unicode/lib.rs | 6 + src/librustc_unicode/tables.rs | 9 + src/librustc_unicode/u_str.rs | 10 +- src/librustdoc/Cargo.toml | 4 +- src/librustdoc/clean/inline.rs | 145 +- src/librustdoc/clean/mod.rs | 435 ++- src/librustdoc/clean/simplify.rs | 6 +- src/librustdoc/core.rs | 20 +- src/librustdoc/doctree.rs | 2 +- src/librustdoc/externalfiles.rs | 4 +- src/librustdoc/fold.rs | 89 +- src/librustdoc/html/escape.rs | 6 +- src/librustdoc/html/format.rs | 213 +- src/librustdoc/html/highlight.rs | 78 +- src/librustdoc/html/item_type.rs | 8 +- src/librustdoc/html/layout.rs | 12 +- src/librustdoc/html/markdown.rs | 12 +- src/librustdoc/html/render.rs | 1561 +++++----- src/librustdoc/html/static/main.js | 6 +- src/librustdoc/html/static/rustdoc.css | 10 +- src/librustdoc/html/toc.rs | 12 +- src/librustdoc/lib.rs | 306 +- src/librustdoc/markdown.rs | 2 +- src/librustdoc/passes.rs | 131 +- src/librustdoc/plugins.rs | 17 +- src/librustdoc/test.rs | 71 +- src/librustdoc/visit_ast.rs | 83 +- src/libserialize/collection_impls.rs | 34 +- src/libserialize/hex.rs | 5 +- src/libserialize/json.rs | 187 +- src/libserialize/lib.rs | 2 +- src/libserialize/serialize.rs | 28 +- src/libstd/ascii.rs | 16 +- src/libstd/build.rs | 18 +- src/libstd/collections/hash/map.rs | 568 ++-- src/libstd/collections/hash/mod.rs | 1 - src/libstd/collections/hash/set.rs | 72 +- src/libstd/collections/hash/state.rs | 40 - src/libstd/collections/hash/table.rs | 150 +- src/libstd/collections/mod.rs | 10 - src/libstd/env.rs | 34 +- src/libstd/error.rs | 11 +- src/libstd/ffi/c_str.rs | 4 +- src/libstd/ffi/os_str.rs | 136 +- src/libstd/fs.rs | 162 +- src/libstd/io/buffered.rs | 52 +- src/libstd/io/cursor.rs | 6 +- src/libstd/io/error.rs | 8 - src/libstd/io/impls.rs | 2 +- src/libstd/io/mod.rs | 216 +- src/libstd/io/stdio.rs | 37 +- src/libstd/io/util.rs | 29 +- src/libstd/lib.rs | 12 +- src/libstd/macros.rs | 12 - src/libstd/net/addr.rs | 62 +- src/libstd/net/ip.rs | 161 +- src/libstd/net/mod.rs | 32 +- src/libstd/net/tcp.rs | 177 +- src/libstd/net/udp.rs | 232 +- src/libstd/num/f32.rs | 10 +- src/libstd/num/f64.rs | 10 +- src/libstd/num/mod.rs | 2 +- src/libstd/os/dragonfly/fs.rs | 10 - src/libstd/os/emscripten/fs.rs | 128 + .../os/emscripten/mod.rs} | 6 +- src/libstd/os/emscripten/raw.rs | 80 + src/libstd/os/mod.rs | 8 +- src/libstd/panic.rs | 266 +- src/libstd/panicking.rs | 62 +- src/libstd/path.rs | 71 +- src/libstd/prelude/mod.rs | 2 +- src/libstd/primitive_docs.rs | 44 +- src/libstd/process.rs | 49 +- src/libstd/rt.rs | 2 +- src/libstd/sync/barrier.rs | 9 +- src/libstd/sync/condvar.rs | 53 +- src/libstd/sync/mod.rs | 6 +- src/libstd/sync/mpsc/mod.rs | 6 + src/libstd/sync/mutex.rs | 4 +- src/libstd/sync/once.rs | 419 ++- src/libstd/sync/rwlock.rs | 8 +- src/libstd/sync/semaphore.rs | 226 -- src/libstd/sys/common/backtrace.rs | 20 +- src/libstd/sys/common/gnu/libbacktrace.rs | 55 +- src/libstd/sys/common/io.rs | 43 +- src/libstd/sys/common/libunwind.rs | 10 +- src/libstd/sys/common/net.rs | 283 +- src/libstd/sys/common/remutex.rs | 5 +- src/libstd/sys/common/unwind/gcc.rs | 7 +- src/libstd/sys/common/wtf8.rs | 54 +- .../unix/backtrace/tracing/backtrace_fn.rs | 4 +- .../sys/unix/backtrace/tracing/gcc_s.rs | 2 +- src/libstd/sys/unix/ext/fs.rs | 79 - src/libstd/sys/unix/ext/mod.rs | 5 +- src/libstd/sys/unix/ext/net.rs | 1042 +++++++ src/libstd/sys/unix/ext/process.rs | 4 +- src/libstd/sys/unix/ext/thread.rs | 16 +- src/libstd/sys/unix/fd.rs | 46 +- src/libstd/sys/unix/fs.rs | 118 +- src/libstd/sys/unix/mod.rs | 36 +- src/libstd/sys/unix/net.rs | 71 +- src/libstd/sys/unix/os.rs | 42 +- src/libstd/sys/unix/pipe.rs | 59 + src/libstd/sys/unix/process.rs | 61 +- src/libstd/sys/unix/rand.rs | 2 +- src/libstd/sys/unix/stdio.rs | 9 + src/libstd/sys/unix/thread.rs | 27 +- src/libstd/sys/unix/time.rs | 15 +- src/libstd/sys/unix/weak.rs | 8 +- src/libstd/sys/windows/backtrace.rs | 120 +- src/libstd/sys/windows/c.rs | 85 +- src/libstd/sys/windows/dynamic_lib.rs | 55 + src/libstd/sys/windows/ext/thread.rs | 4 +- src/libstd/sys/windows/fs.rs | 111 +- src/libstd/sys/windows/handle.rs | 97 +- src/libstd/sys/windows/mod.rs | 1 + src/libstd/sys/windows/net.rs | 100 +- src/libstd/sys/windows/os.rs | 8 +- src/libstd/sys/windows/pipe.rs | 275 +- src/libstd/sys/windows/printing/gnu.rs | 15 +- src/libstd/sys/windows/printing/msvc.rs | 82 +- src/libstd/sys/windows/process.rs | 54 +- src/libstd/sys/windows/stdio.rs | 50 +- src/libstd/sys/windows/thread.rs | 3 +- src/libstd/thread/mod.rs | 59 +- src/libstd/time/duration.rs | 51 +- src/libstd/time/mod.rs | 80 +- src/libsyntax/Cargo.toml | 1 - src/libsyntax/ast.rs | 118 +- src/libsyntax/ast_util.rs | 398 --- src/libsyntax/codemap.rs | 203 +- src/libsyntax/config.rs | 6 +- src/libsyntax/diagnostics/metadata.rs | 8 +- src/libsyntax/errors/emitter.rs | 84 +- src/libsyntax/errors/json.rs | 93 +- src/libsyntax/ext/base.rs | 8 + src/libsyntax/ext/build.rs | 8 +- src/libsyntax/ext/expand.rs | 96 +- src/libsyntax/ext/quote.rs | 48 +- src/libsyntax/ext/tt/macro_parser.rs | 4 +- src/libsyntax/ext/tt/macro_rules.rs | 8 +- src/libsyntax/feature_gate.rs | 86 +- src/libsyntax/fold.rs | 53 +- src/libsyntax/lib.rs | 4 +- src/libsyntax/parse/attr.rs | 16 +- src/libsyntax/parse/lexer/comments.rs | 4 +- src/libsyntax/parse/lexer/mod.rs | 20 +- src/libsyntax/parse/mod.rs | 134 +- src/libsyntax/parse/parser.rs | 1358 ++++---- src/libsyntax/parse/token.rs | 105 +- src/libsyntax/print/pp.rs | 14 +- src/libsyntax/print/pprust.rs | 1797 +++++------ src/libsyntax/test.rs | 16 +- src/libsyntax/util/parser.rs | 14 +- src/libsyntax/util/parser_testing.rs | 108 +- src/libsyntax/visit.rs | 31 +- src/libsyntax_ext/Cargo.toml | 1 + src/libsyntax_ext/asm.rs | 11 +- src/libsyntax_ext/deriving/cmp/ord.rs | 54 +- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 13 +- src/libsyntax_ext/deriving/cmp/partial_ord.rs | 78 +- src/libsyntax_ext/deriving/decodable.rs | 12 +- src/libsyntax_ext/deriving/encodable.rs | 12 +- src/libsyntax_ext/deriving/generic/mod.rs | 128 +- src/libsyntax_ext/deriving/hash.rs | 22 +- src/libsyntax_ext/deriving/mod.rs | 103 +- src/libsyntax_ext/lib.rs | 2 +- src/libterm/lib.rs | 1 + src/libterm/terminfo/mod.rs | 2 +- src/libterm/terminfo/parm.rs | 4 +- src/libterm/terminfo/parser/compiled.rs | 24 +- src/libtest/Cargo.toml | 1 - src/libtest/lib.rs | 121 +- src/rt/rust_test_helpers.c | 4 + src/rustbook/Cargo.toml | 13 - src/rustc/Cargo.lock | 108 +- src/rustc/Cargo.toml | 7 +- src/rustc/test_shim/Cargo.lock | 23 + src/rustc/test_shim/Cargo.toml | 25 + src/rustc/test_shim/lib.rs | 11 + src/rustllvm/RustWrapper.cpp | 35 + src/rustllvm/llvm-auto-clean-trigger | 2 +- src/snapshots.txt | 13 + src/test/auxiliary/ambig_impl_2_lib.rs | 2 +- src/test/auxiliary/cgu_test.rs | 16 + src/test/auxiliary/cgu_test_a.rs | 25 + src/test/auxiliary/cgu_test_b.rs | 25 + src/test/auxiliary/derive-no-std.rs | 40 + src/test/auxiliary/dummy_mir_pass.rs | 22 +- src/test/auxiliary/empty.rs | 9 + src/test/auxiliary/foreign_lib.rs | 27 + src/test/auxiliary/go_trait.rs | 6 +- src/test/auxiliary/inline-default-methods.rs | 2 + src/test/auxiliary/issue-13698.rs | 2 + src/test/auxiliary/issue-15318.rs | 2 + src/test/auxiliary/issue-17476.rs | 1 + .../{issue-17718.rs => issue-17718-aux.rs} | 0 src/test/auxiliary/issue-19190-3.rs | 2 + src/test/auxiliary/issue-20646.rs | 2 + src/test/auxiliary/issue-20727.rs | 2 + src/test/auxiliary/issue-21092.rs | 2 + src/test/auxiliary/issue-21801.rs | 2 + src/test/auxiliary/issue-22025.rs | 2 + src/test/auxiliary/issue-27362.rs | 2 + src/test/auxiliary/issue-29584.rs | 2 + src/test/auxiliary/issue13507.rs | 72 +- src/test/auxiliary/linkage-visibility.rs | 6 +- src/test/auxiliary/lint_for_crate.rs | 3 +- src/test/auxiliary/lint_group_plugin_test.rs | 4 +- src/test/auxiliary/reexp_stripped.rs | 21 + .../auxiliary/specialization_cross_crate.rs | 82 + .../specialization_cross_crate_defaults.rs | 49 + src/test/auxiliary/struct_field_privacy.rs | 2 +- ...-intrinsic.rs => typeid-intrinsic-aux1.rs} | 0 ...intrinsic2.rs => typeid-intrinsic-aux2.rs} | 0 src/test/auxiliary/variant-struct.rs | 15 + .../xcrate_associated_type_defaults.rs | 12 +- .../codegen-units/cross-crate-closures.rs | 8 +- .../cross-crate-generic-functions.rs | 8 +- .../codegen-units/cross-crate-trait-method.rs | 20 +- src/test/codegen-units/generic-drop-glue.rs | 10 +- src/test/codegen-units/generic-impl.rs | 24 +- .../impl-in-non-instantiated-generic.rs | 2 +- .../instantiation-through-vtable.rs | 8 +- .../codegen-units/non-generic-drop-glue.rs | 4 +- .../codegen-units/non-generic-functions.rs | 12 +- .../codegen-units/overloaded-operators.rs | 12 +- .../codegen-units/trait-implementations.rs | 20 +- .../codegen-units/trait-method-as-argument.rs | 2 +- .../codegen-units/transitive-drop-glue.rs | 6 +- src/test/codegen-units/tuple-drop-glue.rs | 2 +- src/test/codegen-units/unsizing.rs | 8 +- .../unused-traits-and-generics.rs | 2 +- src/test/codegen/adjustments.rs | 2 + src/test/codegen/coercions.rs | 3 + src/test/codegen/consts.rs | 5 + src/test/codegen/drop.rs | 2 + src/test/codegen/extern-functions.rs | 5 + src/test/codegen/float_math.rs | 60 + src/test/codegen/naked-functions.rs | 69 + src/test/codegen/refs.rs | 2 + src/test/codegen/stores.rs | 26 +- .../derive-no-std-not-supported.rs | 0 .../dropck_tarena_cycle_checked.rs | 0 .../dropck_tarena_unsound_drop.rs | 0 .../macro-crate-doesnt-resolve.rs | 1 - .../compile-fail/allocator-dylib-is-system.rs | 17 +- .../allocator-rust-dylib-is-jemalloc.rs | 18 +- src/test/compile-fail/asm-out-assign-imm.rs | 1 + .../associated-item-duplicate-names-2.rs | 2 +- .../associated-item-duplicate-names-3.rs | 2 +- .../associated-item-duplicate-names.rs | 4 +- ...ed-types-ICE-when-projecting-out-of-err.rs | 2 +- .../associated-types-bound-failure.rs | 2 +- .../associated-types-coherence-failure.rs | 10 +- .../associated-types-for-unimpl-trait.rs | 2 +- ...ted-types-invalid-trait-ref-issue-18865.rs | 2 +- .../associated-types-no-suitable-bound.rs | 2 +- ...sociated-types-no-suitable-supertrait-2.rs | 2 +- ...associated-types-no-suitable-supertrait.rs | 4 +- .../compile-fail/associated-types-path-2.rs | 4 +- .../compile-fail/associated-types-unsized.rs | 2 +- src/test/compile-fail/bad-const-type.rs | 4 +- .../bad-intrinsic-monomorphization.rs | 44 + .../compile-fail/bad-method-typaram-kind.rs | 2 +- src/test/compile-fail/bad-module.rs | 2 +- src/test/compile-fail/bad-sized.rs | 6 +- src/test/compile-fail/bad-type-env-capture.rs | 1 - src/test/compile-fail/binop-bitxor-str.rs | 2 +- .../blind-item-block-item-shadow.rs | 4 +- .../compile-fail/blind-item-block-middle.rs | 2 +- .../compile-fail/blind-item-item-shadow.rs | 4 +- .../borrowck/borrowck-box-insensitivity.rs | 17 + .../borrowck/borrowck-let-suggestion.rs | 1 + .../borrowck-report-with-custom-diagnostic.rs | 3 + .../borrowck/borrowck-vec-pattern-nesting.rs | 4 + .../builtin-superkinds-double-superkind.rs | 4 +- .../builtin-superkinds-in-metadata.rs | 2 +- .../compile-fail/builtin-superkinds-simple.rs | 2 +- .../builtin-superkinds-typaram-not-send.rs | 2 +- src/test/compile-fail/cast-as-bool.rs | 1 + src/test/compile-fail/cast-rfc0401.rs | 14 +- src/test/compile-fail/cfg-empty-codemap.rs | 2 +- ...bounds-cant-promote-superkind-in-struct.rs | 2 +- .../compile-fail/closure-bounds-subtype.rs | 2 +- ...nket-conflicts-with-blanket-implemented.rs | 4 +- ...et-conflicts-with-blanket-unimplemented.rs | 4 +- ...t-conflicts-with-specific-multidispatch.rs | 4 +- ...e-blanket-conflicts-with-specific-trait.rs | 4 +- ...herence-blanket-conflicts-with-specific.rs | 4 +- ...herence-conflicting-negative-trait-impl.rs | 6 +- .../{coherence-cow-2.rs => coherence-cow.rs} | 16 +- .../coherence-cross-crate-conflict.rs | 5 +- .../coherence-default-trait-impl.rs | 2 +- .../coherence-no-direct-lifetime-dispatch.rs | 18 + .../coherence-overlap-all-t-and-tuple.rs | 4 +- .../coherence-overlap-issue-23516.rs | 4 +- .../coherence-overlap-messages.rs | 30 +- .../coherence-projection-conflict-orphan.rs | 4 +- .../coherence-projection-conflict-ty-param.rs | 4 +- .../coherence-projection-conflict.rs | 4 +- .../compile-fail/coherence-tuple-conflict.rs | 4 +- ..._copy_like_err_fundamental_struct_tuple.rs | 4 +- .../coherence_copy_like_err_struct.rs | 4 +- .../coherence_copy_like_err_tuple.rs | 4 +- .../consider-removing-last-semi.rs | 23 + src/test/compile-fail/const-err-early.rs | 22 + src/test/compile-fail/const-err.rs | 15 +- .../compile-fail/const-eval-overflow-2.rs | 3 +- .../compile-fail/const-eval-overflow-3.rs | 1 - .../compile-fail/const-eval-overflow-4b.rs | 5 +- src/test/compile-fail/const-eval-overflow.rs | 34 +- src/test/compile-fail/const-eval-span.rs | 2 +- .../compile-fail/const-integer-bool-ops.rs | 22 +- .../const-len-underflow-separate-spans.rs | 2 +- .../const-len-underflow-subspans.rs | 2 +- .../compile-fail/const-pattern-irrefutable.rs | 4 +- .../const-pattern-not-const-evaluable.rs | 6 +- src/test/compile-fail/const-tup-index-span.rs | 2 +- src/test/compile-fail/cross-fn-cache-hole.rs | 2 +- .../dep-graph-assoc-type-trans.rs | 2 +- .../compile-fail/dep-graph-caller-callee.rs | 2 +- .../dep-graph-struct-signature.rs | 2 +- ...graph-trait-impl-two-traits-same-method.rs | 2 +- .../dep-graph-trait-impl-two-traits.rs | 2 +- src/test/compile-fail/dep-graph-trait-impl.rs | 2 +- src/test/compile-fail/dep-graph-unrelated.rs | 2 +- .../compile-fail/deprecation-in-staged-api.rs | 2 +- src/test/compile-fail/deprecation-lint.rs | 2 - src/test/compile-fail/deprecation-sanity.rs | 2 - .../deriving-no-inner-impl-error-message.rs | 2 +- .../deriving-span-Default-struct.rs | 2 +- .../compile-fail/destructure-trait-ref.rs | 2 +- src/test/compile-fail/discrim-overflow-2.rs | 4 +- src/test/compile-fail/discrim-overflow.rs | 4 +- src/test/compile-fail/double-import.rs | 4 +- .../dropck_no_diverge_on_nonregular_3.rs | 4 +- src/test/compile-fail/dst-bad-assign-2.rs | 2 +- src/test/compile-fail/dst-bad-assign.rs | 2 +- src/test/compile-fail/dst-bad-coerce1.rs | 2 +- src/test/compile-fail/dst-bad-deep.rs | 2 +- .../dst-object-from-unsized-type.rs | 8 +- .../compile-fail/dst-sized-trait-param.rs | 4 +- .../compile-fail/duplicate_entry_error.rs | 5 +- .../enum-and-module-in-same-scope.rs | 4 +- .../compile-fail/enum-discrim-autosizing.rs | 20 + .../compile-fail/enum-discrim-too-small.rs | 36 +- .../compile-fail/enum-discrim-too-small2.rs | 47 + .../error-should-say-copy-not-pod.rs | 2 +- src/test/compile-fail/eval-enum.rs | 3 +- .../compile-fail/export-fully-qualified.rs | 2 +- src/test/compile-fail/export-tag-variant.rs | 2 +- src/test/compile-fail/export2.rs | 2 +- .../compile-fail/extern-crate-visibility.rs | 9 + .../compile-fail/extern-wrong-value-type.rs | 4 +- src/test/compile-fail/fat-ptr-cast.rs | 3 +- .../feature-gate-negate-unsigned.rs | 23 +- .../feature-gate-negate-unsigned0.rs | 31 + .../compile-fail/feature-gate-try-operator.rs | 18 + src/test/compile-fail/fn-item-type.rs | 38 +- src/test/compile-fail/fn-trait-formatting.rs | 10 +- src/test/compile-fail/for-loop-bogosity.rs | 2 +- .../fully-qualified-type-name1.rs | 4 +- .../fully-qualified-type-name4.rs | 4 +- .../compile-fail/gated-naked_functions.rs | 19 + .../generic-type-params-name-repr.rs | 4 +- src/test/compile-fail/glob-cycles.rs | 26 + .../compile-fail/hrtb-conflate-regions.rs | 2 +- ...tb-higher-ranker-supertraits-transitive.rs | 2 +- .../hrtb-higher-ranker-supertraits.rs | 4 +- src/test/compile-fail/hrtb-just-for-static.rs | 2 +- .../compile-fail/hrtb-perfect-forwarding.rs | 2 +- src/test/compile-fail/ifmt-unimpl.rs | 2 +- src/test/compile-fail/impl-bounds-checking.rs | 2 +- .../compile-fail/impl-duplicate-methods.rs | 2 +- src/test/compile-fail/impossible_range.rs | 29 + .../compile-fail/indexing-requires-a-uint.rs | 2 +- .../compile-fail/infinite-instantiation.rs | 2 +- src/test/compile-fail/inherent-overlap.rs | 51 + .../inner-static-type-parameter.rs | 1 - src/test/compile-fail/integral-indexing.rs | 16 +- .../compile-fail/intrinsic-return-address.rs | 13 +- src/test/compile-fail/invalid-intrinsic.rs | 16 + src/test/compile-fail/issue-10291.rs | 3 +- .../issue-10636-2.rs | 7 +- src/test/compile-fail/issue-11680.rs | 4 +- src/test/compile-fail/issue-11714.rs | 1 + src/test/compile-fail/issue-12796.rs | 1 - src/test/compile-fail/issue-13058.rs | 5 +- src/test/compile-fail/issue-13407.rs | 1 + src/test/compile-fail/issue-13428.rs | 2 + src/test/compile-fail/issue-13466.rs | 16 +- src/test/compile-fail/issue-13482-2.rs | 2 +- src/test/compile-fail/issue-13641.rs | 6 +- src/test/compile-fail/issue-14084.rs | 2 +- src/test/compile-fail/issue-14366.rs | 2 +- src/test/compile-fail/issue-14853.rs | 2 +- src/test/compile-fail/issue-15260.rs | 1 + src/test/compile-fail/issue-15524.rs | 6 +- src/test/compile-fail/issue-15756.rs | 2 +- src/test/compile-fail/issue-15783.rs | 4 +- src/test/compile-fail/issue-16338.rs | 4 +- src/test/compile-fail/issue-16401.rs | 4 +- src/test/compile-fail/issue-16538.rs | 8 +- src/test/compile-fail/issue-16747.rs | 1 + src/test/compile-fail/issue-17263.rs | 2 + src/test/compile-fail/issue-17441.rs | 4 +- src/test/compile-fail/issue-17651.rs | 2 +- .../compile-fail/issue-17718-static-sync.rs | 2 +- src/test/compile-fail/issue-17728.rs | 4 +- src/test/compile-fail/issue-17959.rs | 2 +- src/test/compile-fail/issue-18107.rs | 2 +- src/test/compile-fail/issue-18611.rs | 2 +- src/test/compile-fail/issue-18919.rs | 2 +- src/test/compile-fail/issue-1920-1.rs | 2 +- src/test/compile-fail/issue-1920-2.rs | 2 +- src/test/compile-fail/issue-1920-3.rs | 2 +- src/test/compile-fail/issue-19498.rs | 12 +- src/test/compile-fail/issue-19707.rs | 2 + src/test/compile-fail/issue-20005.rs | 2 +- src/test/compile-fail/issue-20162.rs | 2 +- src/test/compile-fail/issue-20605.rs | 2 +- src/test/compile-fail/issue-20616-8.rs | 4 +- src/test/compile-fail/issue-20616-9.rs | 4 +- src/test/compile-fail/issue-21160.rs | 2 +- src/test/compile-fail/issue-21174.rs | 2 +- src/test/compile-fail/issue-21221-1.rs | 7 + src/test/compile-fail/issue-21221-2.rs | 5 +- src/test/compile-fail/issue-21221-3.rs | 3 +- src/test/compile-fail/issue-21221-4.rs | 3 +- src/test/compile-fail/issue-21332.rs | 4 +- src/test/compile-fail/issue-2149.rs | 2 +- src/test/compile-fail/issue-21546.rs | 24 +- src/test/compile-fail/issue-21600.rs | 3 + ...issue-21659-show-relevant-trait-impls-1.rs | 2 +- ...issue-21659-show-relevant-trait-impls-2.rs | 2 +- src/test/compile-fail/issue-21763.rs | 2 +- src/test/compile-fail/issue-21950.rs | 2 +- src/test/compile-fail/issue-22034.rs | 4 +- src/test/compile-fail/issue-22560.rs | 2 +- src/test/compile-fail/issue-22638.rs | 2 +- src/test/compile-fail/issue-22645.rs | 2 +- src/test/compile-fail/issue-22684.rs | 28 + src/test/compile-fail/issue-23024.rs | 2 +- src/test/compile-fail/issue-24036.rs | 5 +- src/test/compile-fail/issue-24081.rs | 20 +- src/test/compile-fail/issue-24446.rs | 4 +- src/test/compile-fail/issue-24883.rs | 28 + src/test/compile-fail/issue-25076.rs | 2 +- src/test/compile-fail/issue-25385.rs | 1 + src/test/compile-fail/issue-25386.rs | 2 - src/test/compile-fail/issue-25396.rs | 2 +- src/test/compile-fail/issue-25793.rs | 1 + src/test/compile-fail/issue-2611-4.rs | 2 +- src/test/compile-fail/issue-26638.rs | 5 + src/test/compile-fail/issue-26930.rs | 20 + src/test/compile-fail/issue-27340.rs | 16 + src/test/compile-fail/issue-28098.rs | 12 +- src/test/compile-fail/issue-28472.rs | 4 +- src/test/compile-fail/issue-28568.rs | 4 +- src/test/compile-fail/issue-29124.rs | 35 + src/test/compile-fail/issue-29147.rs | 2 +- src/test/compile-fail/issue-29161.rs | 3 +- src/test/compile-fail/issue-30079.rs | 55 + src/test/compile-fail/issue-3021-b.rs | 1 - src/test/compile-fail/issue-3021-c.rs | 2 - src/test/compile-fail/issue-3021-d.rs | 2 - src/test/compile-fail/issue-3021.rs | 1 - src/test/compile-fail/issue-30302.rs | 2 + src/test/compile-fail/issue-30560.rs | 18 + src/test/compile-fail/issue-30730.rs | 13 + src/test/compile-fail/issue-3099-a.rs | 2 +- src/test/compile-fail/issue-3099-b.rs | 2 +- src/test/compile-fail/issue-3099.rs | 2 +- src/test/compile-fail/issue-31511.rs | 16 + .../{mut-not-freeze.rs => issue-31804.rs} | 13 +- src/test/compile-fail/issue-32119.rs | 28 + src/test/compile-fail/issue-32128.rs | 25 + src/test/compile-fail/issue-3214.rs | 1 - src/test/compile-fail/issue-32201.rs | 22 + src/test/compile-fail/issue-32222.rs | 34 + src/test/compile-fail/issue-32323.rs | 18 + src/test/compile-fail/issue-32326.rs | 20 + src/test/compile-fail/issue-32377.rs | 27 + src/test/compile-fail/issue-32797.rs | 21 + src/test/compile-fail/issue-3521-2.rs | 1 - src/test/compile-fail/issue-3521.rs | 3 +- src/test/compile-fail/issue-3668-2.rs | 1 - src/test/compile-fail/issue-3668.rs | 1 - src/test/compile-fail/issue-3680.rs | 8 +- src/test/compile-fail/issue-3907.rs | 2 +- src/test/compile-fail/issue-4265.rs | 2 +- src/test/compile-fail/issue-5035-2.rs | 2 +- src/test/compile-fail/issue-5035.rs | 2 +- src/test/compile-fail/issue-5883.rs | 4 +- src/test/compile-fail/issue-5997-enum.rs | 1 - src/test/compile-fail/issue-5997-struct.rs | 3 +- src/test/compile-fail/issue-6642.rs | 1 - src/test/compile-fail/issue-6702.rs | 1 + src/test/compile-fail/issue-6804.rs | 4 + src/test/compile-fail/issue-6936.rs | 8 +- src/test/compile-fail/issue-7013.rs | 2 +- src/test/compile-fail/issue-7044.rs | 2 +- src/test/compile-fail/issue-7092.rs | 4 +- src/test/compile-fail/issue-7364.rs | 2 +- src/test/compile-fail/issue-7573.rs | 4 +- src/test/compile-fail/issue-7575.rs | 7 +- src/test/compile-fail/issue-7867.rs | 12 +- src/test/compile-fail/issue-8153.rs | 2 +- src/test/compile-fail/issue-8460-const.rs | 20 +- src/test/compile-fail/issue-8640.rs | 2 +- src/test/compile-fail/issue-8727.rs | 2 +- src/test/compile-fail/issue-8761.rs | 12 +- src/test/compile-fail/kindck-copy.rs | 22 +- .../compile-fail/kindck-impl-type-params-2.rs | 2 +- .../compile-fail/kindck-impl-type-params.rs | 8 +- src/test/compile-fail/kindck-nonsendable-1.rs | 2 +- src/test/compile-fail/kindck-send-object.rs | 4 +- src/test/compile-fail/kindck-send-object1.rs | 4 +- src/test/compile-fail/kindck-send-object2.rs | 4 +- src/test/compile-fail/kindck-send-owned.rs | 2 +- src/test/compile-fail/kindck-send-unsafe.rs | 2 +- src/test/compile-fail/lexical-scopes.rs | 23 + ...-return-type-requires-explicit-lifetime.rs | 6 + ...me-inference-give-expl-lifetime-param-3.rs | 16 +- ...time-inference-give-expl-lifetime-param.rs | 12 +- src/test/compile-fail/linkage2.rs | 2 +- src/test/compile-fail/lint-group-style.rs | 1 + .../lint-no-drop-on-repr-extern.rs | 2 + src/test/compile-fail/lint-removed-allow.rs | 17 + src/test/compile-fail/lint-removed.rs | 6 +- src/test/compile-fail/lint-renamed-allow.rs | 17 + src/test/compile-fail/lint-type-limits.rs | 13 - src/test/compile-fail/lint-type-limits2.rs | 24 + src/test/compile-fail/lint-type-limits3.rs | 22 + src/test/compile-fail/lint-type-overflow.rs | 6 - src/test/compile-fail/lint-type-overflow2.rs | 22 + .../lint-unconditional-recursion.rs | 14 + .../liveness-return-last-stmt-semi.rs | 4 + src/test/compile-fail/liveness-unused.rs | 46 + src/test/compile-fail/lub-if.rs | 4 +- src/test/compile-fail/lub-match.rs | 6 +- .../compile-fail/macro-backtrace-nested.rs | 2 + .../compile-fail/macro-backtrace-println.rs | 3 +- src/test/compile-fail/macro-expanded-mod.rs | 23 + .../compile-fail/macro-inner-attributes.rs | 1 - .../macro_expanded_mod_helper/foo/bar.rs | 11 + .../macro_expanded_mod_helper/foo/mod.rs | 13 + src/test/compile-fail/map-types.rs | 2 +- .../meta-expected-error-correct-rev.rs} | 20 +- ...-1.rs => meta-expected-error-wrong-rev.rs} | 23 +- .../method-help-unsatisfied-bound.rs | 4 +- .../compile-fail/method-macro-backtrace.rs | 2 +- .../method-suggestion-no-duplication.rs | 2 + src/test/compile-fail/minus-string.rs | 2 +- ...s-based-on-type-cyclic-types-issue-4821.rs | 2 +- .../compile-fail/mutable-enum-indirect.rs | 2 +- src/test/compile-fail/no-link.rs | 1 - .../no-method-suggested-traits.rs | 4 +- src/test/compile-fail/no-send-res-ports.rs | 2 +- src/test/compile-fail/no-std-inject.rs | 2 +- src/test/compile-fail/no_send-enum.rs | 2 +- src/test/compile-fail/no_send-rc.rs | 2 +- src/test/compile-fail/no_send-struct.rs | 2 +- src/test/compile-fail/no_share-enum.rs | 2 +- src/test/compile-fail/no_share-struct.rs | 2 +- src/test/compile-fail/noexporttypeexe.rs | 4 +- .../non-constant-enum-for-vec-repeat.rs | 2 +- src/test/compile-fail/non-interger-atomic.rs | 117 + src/test/compile-fail/not-panic-safe-3.rs | 2 +- src/test/compile-fail/not-panic-safe-5.rs | 2 +- src/test/compile-fail/not-panic-safe.rs | 6 +- src/test/compile-fail/not-sync.rs | 34 + .../object-does-not-impl-trait.rs | 2 +- .../object-lifetime-default-mybox.rs | 3 +- .../compile-fail/object-safety-generics.rs | 1 + src/test/compile-fail/on-unimplemented.rs | 6 +- src/test/compile-fail/phantom-oibit.rs | 4 +- .../compile-fail/placement-expr-unstable.rs | 5 +- src/test/compile-fail/privacy-in-paths.rs | 40 + src/test/compile-fail/privacy-ns2.rs | 7 +- src/test/compile-fail/privacy-sanity.rs | 50 +- src/test/compile-fail/privacy-ufcs.rs | 3 +- src/test/compile-fail/privacy1.rs | 34 +- src/test/compile-fail/privacy2.rs | 2 +- src/test/compile-fail/privacy4.rs | 2 +- src/test/compile-fail/privacy5.rs | 36 +- src/test/compile-fail/private-impl-method.rs | 7 + .../compile-fail/private-in-public-warn.rs | 8 +- src/test/compile-fail/range-1.rs | 6 +- src/test/compile-fail/range-2.rs | 10 +- src/test/compile-fail/range_inclusive_gate.rs | 25 + src/test/compile-fail/recursion_limit.rs | 11 + src/test/compile-fail/ref-suggestion.rs | 3 + src/test/compile-fail/reflect-assoc.rs | 2 +- src/test/compile-fail/reflect-object-param.rs | 6 +- src/test/compile-fail/reflect.rs | 4 +- ...ion-lifetime-bounds-on-fns-where-clause.rs | 2 +- ...ple-lifetime-bounds-on-fns-where-clause.rs | 4 +- .../regions-early-bound-error-method.rs | 3 +- .../compile-fail/regions-early-bound-error.rs | 6 +- .../compile-fail/regions-glb-free-free.rs | 6 +- .../regions-lifetime-bounds-on-fns.rs | 4 +- src/test/compile-fail/regions-nested-fns.rs | 6 +- src/test/compile-fail/regions-static-bound.rs | 2 +- .../reject-specialized-drops-8142.rs | 2 +- .../compile-fail/repeat-to-run-dtor-twice.rs | 2 +- src/test/compile-fail/repeat_count.rs | 12 +- ...e-conflict-extern-crate-vs-extern-crate.rs | 2 +- ...resolve-conflict-import-vs-extern-crate.rs | 2 +- .../resolve-conflict-item-vs-extern-crate.rs | 2 +- .../resolve-conflict-item-vs-import.rs | 3 +- .../resolve-conflict-type-vs-import.rs | 2 +- .../resolve-type-param-in-item-in-trait.rs | 8 +- src/test/compile-fail/rfc1445/feature-gate.rs | 36 + .../rfc1445/match-forbidden-without-eq.rs | 39 + .../match-requires-both-partialeq-and-eq.rs | 35 + ..._share-rc.rs => shadowed-trait-methods.rs} | 18 +- .../simd-intrinsic-generic-arithmetic.rs | 3 +- .../simd-intrinsic-generic-cast.rs | 3 +- .../simd-intrinsic-generic-comparison.rs | 3 +- .../simd-intrinsic-generic-elements.rs | 3 +- src/test/compile-fail/sized-cycle-note.rs | 10 +- .../compile-fail/specialization/README.md | 21 + .../specialization-default-projection.rs | 46 + .../specialization-default-types.rs | 45 + .../specialization-feature-gate-default.rs} | 18 +- .../specialization-feature-gate-overlap.rs | 25 + .../specialization-no-default.rs | 95 + .../specialization-overlap-negative.rs | 21 + .../specialization/specialization-overlap.rs | 29 + .../specialization/specialization-polarity.rs | 30 + src/test/compile-fail/str-idx.rs | 2 +- src/test/compile-fail/str-mut-idx.rs | 8 +- src/test/compile-fail/struct-field-privacy.rs | 11 +- .../compile-fail/struct-variant-privacy-xc.rs | 2 +- .../compile-fail/struct-variant-privacy.rs | 3 +- src/test/compile-fail/substs-ppaux.rs | 61 + .../suggest-path-instead-of-mod-dot-item.rs | 8 + .../compile-fail/suggest-private-fields.rs | 1 + src/test/compile-fail/super-at-top-level.rs | 2 +- .../basic.rs} | 9 +- src/test/compile-fail/symbol-names/impl1.rs | 35 + .../tag-that-dare-not-speak-its-name.rs | 4 +- .../compile-fail/task-rng-isnt-sendable.rs | 4 +- .../compile-fail/token-error-correct-2.rs | 17 + .../compile-fail/token-error-correct-3.rs | 34 + src/test/compile-fail/token-error-correct.rs | 20 + .../trait-bounds-impl-comparison-1.rs | 12 +- .../trait-bounds-impl-comparison-2.rs | 2 +- .../trait-bounds-not-on-bare-trait.rs | 2 +- ...rait-bounds-on-structs-and-enums-in-fns.rs | 4 +- ...it-bounds-on-structs-and-enums-in-impls.rs | 2 +- ...rait-bounds-on-structs-and-enums-locals.rs | 4 +- ...rait-bounds-on-structs-and-enums-static.rs | 2 +- .../trait-bounds-on-structs-and-enums-xc.rs | 4 +- .../trait-bounds-on-structs-and-enums-xc1.rs | 4 +- .../trait-bounds-on-structs-and-enums.rs | 14 +- .../trait-coercion-generic-bad.rs | 2 +- .../compile-fail/trait-duplicate-methods.rs | 4 +- src/test/compile-fail/trait-not-accessible.rs | 2 +- ...ect-reference-without-parens-suggestion.rs | 2 + src/test/compile-fail/trait-privacy.rs | 35 + .../trait-suggest-where-clause.rs | 67 + ...its-inductive-overflow-auto-normal-auto.rs | 32 + .../compile-fail/traits-negative-impls.rs | 14 +- .../traits-repeated-supertrait-ambig.rs | 10 +- .../transmute-from-fn-item-types-error.rs | 23 + .../transmute-from-fn-item-types-lint.rs | 49 + .../compile-fail/transmute-type-parameters.rs | 18 +- src/test/compile-fail/trivial_casts.rs | 2 +- src/test/compile-fail/type-macros-fail.rs | 2 +- .../type-params-in-different-spaces-2.rs | 4 +- .../typeck-default-trait-impl-assoc-type.rs | 2 +- ...-default-trait-impl-constituent-types-2.rs | 2 +- ...ck-default-trait-impl-constituent-types.rs | 2 +- ...typeck-default-trait-impl-negation-send.rs | 2 +- ...typeck-default-trait-impl-negation-sync.rs | 6 +- .../typeck-default-trait-impl-negation.rs | 4 +- .../typeck-default-trait-impl-precedence.rs | 2 +- .../typeck-default-trait-impl-send-param.rs | 2 +- .../typeck-default-trait-impl-supertrait.rs | 4 +- ...default-trait-impl-trait-where-clause-2.rs | 2 +- ...k-default-trait-impl-trait-where-clause.rs | 2 +- .../typeck-unsafe-always-share.rs | 10 +- .../compile-fail/ufcs-qpath-missing-params.rs | 12 +- .../compile-fail/ufcs-qpath-self-mismatch.rs | 2 +- .../unboxed-closure-sugar-default.rs | 2 +- .../unboxed-closure-sugar-equiv.rs | 2 +- .../unboxed-closures-fnmut-as-fn.rs | 2 +- ...nfer-argument-types-two-region-pointers.rs | 2 +- .../unboxed-closures-unsafe-extern-fn.rs | 10 +- .../unboxed-closures-wrong-abi.rs | 10 +- ...boxed-closures-wrong-arg-type-extern-fn.rs | 10 +- src/test/compile-fail/unique-vec-res.rs | 42 - src/test/compile-fail/unnecessary-private.rs | 27 - .../unresolved-extern-mod-suggestion.rs | 2 +- src/test/compile-fail/unsized-bare-typaram.rs | 2 +- src/test/compile-fail/unsized-enum.rs | 4 +- .../unsized-inherent-impl-self-type.rs | 2 +- src/test/compile-fail/unsized-struct.rs | 4 +- .../unsized-trait-impl-self-type.rs | 2 +- .../unsized-trait-impl-trait-arg.rs | 2 +- src/test/compile-fail/unsized3.rs | 12 +- src/test/compile-fail/unsized5.rs | 12 +- src/test/compile-fail/unsized6.rs | 24 +- src/test/compile-fail/unsized7.rs | 2 +- src/test/compile-fail/use-mod-3.rs | 3 +- src/test/compile-fail/use-mod.rs | 1 + .../compile-fail/use-super-global-path.rs | 22 + src/test/compile-fail/useless-pub.rs | 7 + src/test/compile-fail/variadic-ffi-3.rs | 14 +- .../variance-unused-type-param.rs | 3 + src/test/compile-fail/variant-namespacing.rs | 32 +- .../compile-fail/vtable-res-trait-param.rs | 2 +- .../wf-impl-associated-type-trait.rs | 3 +- src/test/compile-fail/wf-static-method.rs | 4 +- ...constraints-are-local-for-inherent-impl.rs | 2 +- ...se-constraints-are-local-for-trait-impl.rs | 2 +- .../where-clause-method-substituion.rs | 2 +- .../where-clauses-method-unsatisfied.rs | 2 +- .../compile-fail/where-clauses-unsatisfied.rs | 2 +- src/test/compile-fail/where-for-self-2.rs | 2 +- .../compile-fail/xcrate-private-by-default.rs | 10 +- .../debuginfo/constant-in-match-pattern.rs | 3 + src/test/incremental/dirty_clean.rs | 53 + src/test/incremental/hello_world.rs | 46 + src/test/incremental/string_constant.rs | 58 + src/test/parse-fail/default.rs | 35 + src/test/parse-fail/issue-19096.rs | 2 +- src/test/parse-fail/issue-20711-2.rs | 2 +- src/test/parse-fail/issue-20711.rs | 2 +- src/test/parse-fail/issue-2354-1.rs | 2 +- src/test/parse-fail/issue-3036.rs | 2 +- src/test/parse-fail/issue-32501.rs | 21 + .../macro-mismatched-delim-paren-brace.rs | 2 +- src/test/parse-fail/macros-no-semicolon.rs | 2 +- src/test/parse-fail/match-refactor-to-expr.rs | 2 +- src/test/parse-fail/paamayim-nekudotayim.rs | 2 +- src/test/parse-fail/pub-method-macro.rs | 4 +- src/test/parse-fail/range-3.rs | 2 +- src/test/parse-fail/range-4.rs | 2 +- .../range_inclusive.rs} | 15 +- src/test/parse-fail/range_inclusive_gate.rs | 74 + src/test/parse-fail/raw-str-unbalanced.rs | 2 +- .../parse-fail/removed-syntax-mut-vec-expr.rs | 2 +- .../parse-fail/removed-syntax-static-fn.rs | 2 +- .../removed-syntax-uniq-mut-expr.rs | 2 +- src/test/parse-fail/removed-syntax-with-1.rs | 2 +- src/test/parse-fail/struct-literal-in-for.rs | 2 +- src/test/parse-fail/struct-literal-in-if.rs | 2 +- .../struct-literal-in-match-discriminant.rs | 2 +- .../parse-fail/struct-literal-in-while.rs | 2 +- .../unboxed-closure-sugar-used-on-struct-3.rs | 2 +- src/test/pretty/issue-4264.pp | 78 +- src/test/pretty/top-level-doc-comments.rs | 20 + src/test/run-fail/divide-by-zero.rs | 5 + src/test/run-fail/meta-revision-bad.rs | 22 + src/test/run-fail/meta-revision-ok.rs | 21 + src/test/run-fail/mir_dynamic_drops_1.rs | 42 + src/test/run-fail/mir_dynamic_drops_2.rs | 40 + src/test/run-fail/mir_dynamic_drops_3.rs | 45 + src/test/run-fail/mod-zero.rs | 5 + src/test/run-fail/overflowing-add.rs | 4 + src/test/run-fail/overflowing-lsh-1.rs | 4 + src/test/run-fail/overflowing-lsh-2.rs | 4 + src/test/run-fail/overflowing-lsh-3.rs | 4 + src/test/run-fail/overflowing-lsh-4.rs | 4 + src/test/run-fail/overflowing-mul.rs | 4 + src/test/run-fail/overflowing-neg.rs | 4 + src/test/run-fail/overflowing-rsh-1.rs | 4 + src/test/run-fail/overflowing-rsh-2.rs | 4 + src/test/run-fail/overflowing-rsh-3.rs | 4 + src/test/run-fail/overflowing-rsh-4.rs | 4 + src/test/run-fail/overflowing-rsh-5.rs | 4 + src/test/run-fail/overflowing-rsh-6.rs | 4 + src/test/run-fail/overflowing-sub.rs | 4 + src/test/run-make/a-b-a-linker-guard/Makefile | 12 + src/test/run-make/a-b-a-linker-guard/a.rs | 20 + .../a-b-a-linker-guard/b.rs} | 12 +- src/test/run-make/debug-assertions/debug.rs | 2 + src/test/run-make/execution-engine/test.rs | 20 +- src/test/run-make/extern-fn-reachable/main.rs | 6 +- .../extern-overrides-distribution/Makefile | 2 +- src/test/run-make/issue-19371/foo.rs | 4 +- src/test/run-make/issue-25581/test.c | 13 +- src/test/run-make/issue-26006/Makefile | 12 +- src/test/run-make/json-errors/Makefile | 8 +- .../pretty-print-path-suffix/foo_method.pp | 2 +- src/test/run-make/relocation-model/Makefile | 4 +- src/test/run-make/reproducible-build/Makefile | 20 + .../reproducible-build-aux.rs | 38 + .../reproducible-build/reproducible-build.rs | 128 + src/test/run-make/rustdoc-json/Makefile | 4 - .../run-make/stable-symbol-names/Makefile | 18 + .../stable-symbol-names1.rs | 22 + .../stable-symbol-names2.rs | 20 + .../target-specs/my-awesome-platform.json | 1 + src/test/run-make/test-harness/Makefile | 2 + .../conditional-debug-macro-off.rs | 0 .../deprecated-derive.rs | 0 .../deriving-encodable-decodable-box.rs | 0 ...riving-encodable-decodable-cell-refcell.rs | 0 .../deriving-global.rs | 0 .../dropck_tarena_sound_drop.rs | 0 .../empty-struct-braces-derive.rs | 0 .../extern-mod-syntax.rs | 0 .../issue-11881.rs | 0 .../issue-14021.rs | 0 .../issue-15924.rs | 0 .../issue-24972.rs | 0 .../issue-2804.rs | 0 .../issue-4016.rs | 0 .../issue-4036.rs | 0 .../linkage-visibility.rs | 0 .../logging-enabled-debug.rs | 0 .../logging-enabled.rs | 0 .../logging-right-crate.rs | 0 .../logging-separate-lines.rs | 0 .../regions-mock-tcx.rs | 0 .../rust-log-filter.rs | 0 .../run-pass-valgrind/cast-enum-with-dtor.rs | 5 +- src/test/run-pass/allocator-default.rs | 6 +- .../associated-const-match-patterns.rs | 1 + src/test/run-pass/atomic-compare_exchange.rs | 36 +- src/test/run-pass/augmented-assignments.rs | 18 + src/test/run-pass/autoderef-privacy.rs | 60 + src/test/run-pass/backtrace-debuginfo-aux.rs | 2 + src/test/run-pass/backtrace-debuginfo.rs | 20 +- src/test/run-pass/backtrace.rs | 40 +- src/test/run-pass/bench/issue-32062.rs | 58 + src/test/run-pass/binary-heap-panic-safe.rs | 2 +- .../run-pass/borrow-by-val-method-receiver.rs | 3 - .../borrowck/borrowck-binding-mutbl.rs | 3 - src/test/run-pass/cabi-int-widening.rs | 22 + src/test/run-pass/cci_nested_exe.rs | 2 - src/test/run-pass/coerce-unify.rs | 77 + .../run-pass/const-bitshift-rhs-inference.rs | 33 + src/test/run-pass/const-fn.rs | 12 +- src/test/run-pass/const-negation.rs | 42 + src/test/run-pass/const-str-ptr.rs | 4 + src/test/run-pass/default-associated-types.rs | 21 +- src/test/run-pass/derive-no-std.rs | 31 +- src/test/run-pass/deriving-hash.rs | 30 + src/test/run-pass/empty-struct-braces.rs | 3 + .../run-pass/empty-type-parameter-list.rs | 33 + src/test/run-pass/enum-clike-ffi-as-int.rs | 13 +- src/test/run-pass/enum-discrim-autosizing.rs | 10 +- .../run-pass/enum-discrim-manual-sizing.rs | 33 +- src/test/run-pass/env-funky-keys.rs | 11 +- src/test/run-pass/float_math.rs | 30 + src/test/run-pass/fn-item-type-zero-sized.rs | 22 + src/test/run-pass/foreign-dupe.rs | 29 +- src/test/run-pass/generic-ivec-leak.rs | 2 - src/test/run-pass/ifmt.rs | 7 +- src/test/run-pass/intrinsic-atomics.rs | 12 +- src/test/run-pass/issue-12860.rs | 2 - src/test/run-pass/issue-13507-2.rs | 34 +- src/test/run-pass/issue-13763.rs | 7 +- src/test/run-pass/issue-17121.rs | 4 +- src/test/run-pass/issue-17718.rs | 4 +- src/test/run-pass/issue-17816.rs | 2 - src/test/run-pass/issue-18514.rs | 1 - .../{compile-fail => run-pass}/issue-20427.rs | 49 +- src/test/run-pass/issue-20797.rs | 4 +- src/test/run-pass/issue-21058.rs | 2 +- src/test/run-pass/issue-21400.rs | 4 +- src/test/run-pass/issue-22577.rs | 3 +- .../issue-23338-ensure-param-drop-order.rs | 3 + src/test/run-pass/issue-23550.rs | 10 +- src/test/run-pass/issue-23833.rs | 25 + src/test/run-pass/issue-2631-b.rs | 2 - src/test/run-pass/issue-26997.rs | 22 + src/test/run-pass/issue-2723-b.rs | 2 - src/test/run-pass/issue-28950.rs | 23 + src/test/run-pass/issue-29663.rs | 64 + src/test/run-pass/issue-30615.rs | 14 + src/test/run-pass/issue-31597.rs | 37 + src/test/run-pass/issue-31776.rs | 64 + .../issue-32292.rs} | 15 +- src/test/run-pass/issue-32324.rs | 33 + .../issue-32389.rs} | 11 +- src/test/run-pass/issue-32518.rs | 22 + src/test/run-pass/issue-33461.rs | 36 + src/test/run-pass/issue-8460.rs | 55 +- src/test/run-pass/ivec-pass-by-value.rs | 3 - src/test/run-pass/ivec-tag.rs | 1 - .../lint-dead-code-associated-type.rs | 27 + .../run-pass/macro-delimiter-significance.rs | 2 - src/test/run-pass/match-arm-statics.rs | 11 +- .../run-pass/minmax-stability-issue-23687.rs | 6 +- src/test/run-pass/mir_fat_ptr_drop.rs | 39 + src/test/run-pass/mir_raw_fat_ptr.rs | 3 + src/test/run-pass/mir_refs_correct.rs | 81 +- src/test/run-pass/mir_trans_critical_edge.rs | 53 + src/test/run-pass/multi-panic.rs | 25 +- .../run-pass/nullable-pointer-ffi-compat.rs | 5 +- .../nullable-pointer-iotareduction.rs | 11 +- src/test/run-pass/num-wrapping.rs | 35 +- src/test/run-pass/panic-handler-chain.rs | 10 +- .../run-pass/panic-handler-flail-wildly.rs | 30 +- src/test/run-pass/panic-handler-set-twice.rs | 4 +- src/test/run-pass/panic-safe.rs | 14 +- .../run-pass/parser-unicode-whitespace.rs | 22 + .../run-pass/process-status-inherits-stdin.rs | 41 + src/test/run-pass/range.rs | 3 +- src/test/run-pass/range_inclusive.rs | 129 + src/test/run-pass/range_inclusive_gate.rs | 23 + .../run-pass/regions-dependent-autoslice.rs | 3 - src/test/run-pass/regions-lub-ref-ref-rc.rs | 36 + .../rfc1445/eq-allows-match-on-ty-in-macro.rs | 32 + .../rfc1445/eq-allows-match.rs} | 17 +- src/test/run-pass/send_str_hashmap.rs | 64 +- src/test/run-pass/send_str_treemap.rs | 73 +- .../simd-intrinsic-generic-elements.rs | 5 +- src/test/run-pass/specialization/README.md | 37 + .../specialization-allowed-cross-crate.rs} | 22 +- .../specialization-assoc-fns.rs | 37 + .../specialization/specialization-basics.rs | 106 + .../specialization-cross-crate-defaults.rs | 49 + .../specialization-cross-crate-no-gate.rs | 29 + .../specialization-cross-crate.rs | 58 + .../specialization-default-methods.rs | 94 + .../specialization-on-projection.rs | 31 + .../specialization-out-of-order.rs | 27 + .../specialization-overlap-projection.rs | 33 + .../specialization-projection-alias.rs | 32 + .../specialization-projection.rs | 49 + .../specialization-super-traits.rs | 25 + ...ation-translate-projections-with-params.rs | 40 + .../specialization-translate-projections.rs | 41 + .../run-pass/std-sync-right-kind-impls.rs | 1 - src/test/run-pass/super-fast-paren-parsing.rs | 1 + .../run-pass/transmute-from-fn-item-types.rs | 27 + src/test/run-pass/try-macro.rs | 57 + src/test/run-pass/try-operator-hygiene.rs | 34 + src/test/run-pass/try-operator.rs | 200 ++ src/test/run-pass/typeid-intrinsic.rs | 8 +- src/test/run-pass/ufcs-polymorphic-paths.rs | 14 +- src/test/run-pass/unique-ffi-symbols.rs | 25 + src/test/run-pass/variadic-ffi.rs | 6 +- src/test/run-pass/vec-concat.rs | 4 +- src/test/run-pass/vec-push.rs | 2 - src/test/run-pass/vector-sort-panic-safe.rs | 3 +- src/test/run-pass/volatile-fat-ptr.rs | 22 + .../xcrate-associated-type-defaults.rs | 22 +- .../run-pass/zero-size-type-destructors.rs | 4 +- src/test/rustdoc/inline_local/issue-28537.rs | 27 + src/test/rustdoc/inline_local/issue-32343.rs | 33 + .../rustdoc/inline_local/please_inline.rs | 29 + src/test/rustdoc/issue-15347.rs | 2 +- src/test/rustdoc/issue-25001.rs | 6 +- src/test/rustdoc/issue-27104.rs | 20 + src/test/rustdoc/issue-27362.rs | 2 +- src/test/rustdoc/issue-28478.rs | 42 + src/test/rustdoc/issue-32395.rs | 23 + src/test/rustdoc/recursion1.rs | 1 - src/test/rustdoc/recursion2.rs | 1 - src/test/rustdoc/recursion3.rs | 2 - src/test/rustdoc/redirect.rs | 48 + src/test/rustdoc/structfields.rs | 44 + src/tools/cargotest/Cargo.lock | 28 + src/tools/cargotest/Cargo.toml | 11 + src/tools/cargotest/lockfiles/iron-Cargo.lock | 364 +++ src/tools/cargotest/main.rs | 102 + src/tools/error_index_generator/Cargo.lock | 4 + src/tools/error_index_generator/Cargo.toml | 8 + src/{ => tools}/error_index_generator/main.rs | 82 +- src/tools/linkchecker/Cargo.lock | 64 + src/tools/linkchecker/Cargo.toml | 11 + src/tools/linkchecker/main.rs | 344 ++ src/tools/rustbook/Cargo.lock | 4 + src/tools/rustbook/Cargo.toml | 8 + src/{ => tools}/rustbook/book.rs | 0 src/{ => tools}/rustbook/build.rs | 84 +- src/{ => tools}/rustbook/error.rs | 0 src/{ => tools}/rustbook/help.rs | 0 src/{ => tools}/rustbook/main.rs | 1 + src/{ => tools}/rustbook/serve.rs | 0 src/{ => tools}/rustbook/static/rustbook.css | 0 src/{ => tools}/rustbook/static/rustbook.js | 0 src/{ => tools}/rustbook/subcommand.rs | 0 src/{ => tools}/rustbook/term.rs | 0 src/{ => tools}/rustbook/test.rs | 2 +- 1798 files changed, 77995 insertions(+), 47018 deletions(-) create mode 100644 mk/cfg/i586-pc-windows-msvc.mk create mode 100644 src/bootstrap/build/check.rs create mode 100644 src/bootstrap/build/dist.rs create mode 100644 src/bootstrap/rustdoc.rs create mode 100644 src/etc/platform-intrinsics/x86/fma.json delete mode 100644 src/jemalloc/VERSION create mode 100644 src/jemalloc/bin/jemalloc-config.in rename src/jemalloc/bin/{pprof => jeprof.in} (96%) mode change 100755 => 100644 rename src/jemalloc/{ => build-aux}/config.guess (100%) rename src/jemalloc/{ => build-aux}/config.sub (100%) rename src/jemalloc/{ => build-aux}/install-sh (100%) create mode 100644 src/jemalloc/include/jemalloc/internal/assert.h create mode 100644 src/jemalloc/include/jemalloc/internal/nstime.h create mode 100644 src/jemalloc/include/jemalloc/internal/pages.h create mode 100644 src/jemalloc/include/jemalloc/internal/smoothstep.h create mode 100755 src/jemalloc/include/jemalloc/internal/smoothstep.sh create mode 100644 src/jemalloc/include/jemalloc/internal/ticker.h delete mode 100644 src/jemalloc/include/msvc_compat/C99/inttypes.h create mode 100644 src/jemalloc/include/msvc_compat/windows_extra.h create mode 100644 src/jemalloc/msvc/ReadMe.txt create mode 100644 src/jemalloc/msvc/jemalloc_vc2015.sln create mode 100644 src/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj create mode 100644 src/jemalloc/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters create mode 100644 src/jemalloc/msvc/projects/vc2015/test_threads/test_threads.cpp create mode 100644 src/jemalloc/msvc/projects/vc2015/test_threads/test_threads.h create mode 100644 src/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj create mode 100644 src/jemalloc/msvc/projects/vc2015/test_threads/test_threads.vcxproj.filters create mode 100644 src/jemalloc/msvc/projects/vc2015/test_threads/test_threads_main.cpp create mode 100644 src/jemalloc/src/nstime.c create mode 100644 src/jemalloc/src/pages.c create mode 100644 src/jemalloc/src/prng.c create mode 100644 src/jemalloc/src/ticker.c create mode 100644 src/jemalloc/test/integration/overflow.c create mode 100644 src/jemalloc/test/src/mq.c create mode 100644 src/jemalloc/test/unit/decay.c create mode 100644 src/jemalloc/test/unit/junk_alloc.c create mode 100644 src/jemalloc/test/unit/junk_free.c create mode 100644 src/jemalloc/test/unit/lg_chunk.c create mode 100644 src/jemalloc/test/unit/nstime.c create mode 100644 src/jemalloc/test/unit/prng.c create mode 100644 src/jemalloc/test/unit/run_quantize.c create mode 100644 src/jemalloc/test/unit/size_classes.c create mode 100644 src/jemalloc/test/unit/smoothstep.c create mode 100644 src/jemalloc/test/unit/ticker.c create mode 100644 src/libcore/build.rs create mode 100644 src/liblibc/ci/style.rs delete mode 100644 src/liblibc/src/unix/bsd/freebsdlike/dragonfly.rs create mode 100644 src/liblibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs delete mode 100644 src/liblibc/src/unix/bsd/freebsdlike/freebsd.rs create mode 100644 src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs rename src/liblibc/src/unix/bsd/freebsdlike/{ => freebsd}/x86.rs (100%) rename src/liblibc/src/unix/bsd/freebsdlike/{ => freebsd}/x86_64.rs (100%) create mode 100644 src/liblibc/src/unix/notbsd/linux/musl/b64/aarch64.rs create mode 100644 src/liblibc/src/unix/notbsd/linux/musl/b64/powerpc64.rs create mode 100644 src/liblibc/src/unix/notbsd/linux/musl/b64/x86_64.rs rename src/librustc/{middle => }/cfg/construct.rs (93%) rename src/librustc/{middle => }/cfg/graphviz.rs (92%) rename src/librustc/{middle => }/cfg/mod.rs (95%) create mode 100644 src/librustc/dep_graph/dep_node.rs create mode 100644 src/librustc/dep_graph/graph.rs create mode 100644 src/librustc/dep_graph/visit.rs rename src/librustc/{front => hir}/check_attr.rs (100%) rename src/librustc/{middle => hir}/def.rs (79%) rename src/librustc/{middle => hir}/def_id.rs (90%) rename src/{librustc_front => librustc/hir}/fold.rs (95%) rename src/{librustc_front => librustc/hir}/intravisit.rs (78%) rename src/{librustc_front => librustc/hir}/lowering.rs (89%) rename src/librustc/{front => hir}/map/blocks.rs (79%) rename src/librustc/{front => hir}/map/collector.rs (88%) rename src/librustc/{front => hir}/map/definitions.rs (58%) rename src/librustc/{front => hir}/map/mod.rs (78%) rename src/{librustc_front/hir.rs => librustc/hir/mod.rs} (85%) rename src/librustc/{middle => hir}/pat_util.rs (92%) rename src/{librustc_front/print/pprust.rs => librustc/hir/print.rs} (57%) create mode 100644 src/librustc/hir/svh.rs rename src/librustc/{middle => }/infer/README.md (100%) rename src/librustc/{middle => }/infer/bivariate.rs (88%) rename src/librustc/{middle => }/infer/combine.rs (88%) rename src/librustc/{middle => }/infer/equate.rs (79%) rename src/librustc/{middle => }/infer/error_reporting.rs (92%) rename src/librustc/{middle => }/infer/freshen.rs (92%) rename src/librustc/{middle => }/infer/glb.rs (88%) rename src/librustc/{middle => }/infer/higher_ranked/README.md (100%) rename src/librustc/{middle => }/infer/higher_ranked/mod.rs (95%) rename src/librustc/{middle => }/infer/lattice.rs (89%) rename src/librustc/{middle => }/infer/lub.rs (88%) rename src/librustc/{middle => }/infer/mod.rs (89%) rename src/librustc/{middle => }/infer/region_inference/README.md (100%) rename src/librustc/{middle => }/infer/region_inference/graphviz.rs (93%) rename src/librustc/{middle => }/infer/region_inference/mod.rs (95%) rename src/librustc/{middle => }/infer/resolve.rs (93%) rename src/librustc/{middle => }/infer/sub.rs (83%) rename src/librustc/{middle => }/infer/type_variable.rs (65%) rename src/librustc/{middle => }/infer/unify_key.rs (83%) delete mode 100644 src/librustc/middle/const_eval.rs create mode 100644 src/librustc/middle/const_val.rs rename src/librustc/{middle => }/traits/README.md (89%) rename src/librustc/{middle => }/traits/coherence.rs (66%) rename src/librustc/{middle => }/traits/error_reporting.rs (84%) rename src/librustc/{middle => }/traits/fulfill.rs (76%) rename src/librustc/{middle => }/traits/mod.rs (97%) rename src/librustc/{middle => }/traits/object_safety.rs (94%) rename src/librustc/{middle => }/traits/project.rs (78%) rename src/librustc/{middle => }/traits/select.rs (91%) create mode 100644 src/librustc/traits/specialize/mod.rs create mode 100644 src/librustc/traits/specialize/specialization_graph.rs rename src/librustc/{middle => }/traits/structural_impls.rs (97%) rename src/librustc/{middle => }/traits/util.rs (85%) rename src/librustc/{middle => }/ty/_match.rs (89%) rename src/librustc/{middle => }/ty/adjustment.rs (86%) rename src/librustc/{middle => }/ty/cast.rs (96%) rename src/librustc/{middle => }/ty/contents.rs (95%) rename src/librustc/{middle => }/ty/context.rs (88%) rename src/librustc/{middle => }/ty/error.rs (97%) rename src/librustc/{middle => }/ty/fast_reject.rs (96%) rename src/librustc/{middle => }/ty/flags.rs (95%) rename src/librustc/{middle => }/ty/fold.rs (92%) create mode 100644 src/librustc/ty/item_path.rs rename src/librustc/{middle => }/ty/ivar.rs (91%) create mode 100644 src/librustc/ty/layout.rs rename src/librustc/{middle => }/ty/maps.rs (94%) rename src/librustc/{middle => }/ty/mod.rs (89%) rename src/librustc/{middle => }/ty/outlives.rs (98%) rename src/librustc/{middle => }/ty/relate.rs (82%) rename src/librustc/{middle => }/ty/structural_impls.rs (89%) rename src/librustc/{middle => }/ty/sty.rs (94%) rename src/librustc/{middle => ty}/subst.rs (81%) rename src/librustc/{middle => }/ty/trait_def.rs (63%) rename src/librustc/{middle => }/ty/util.rs (72%) rename src/librustc/{middle => }/ty/walk.rs (95%) rename src/librustc/{middle => }/ty/wf.rs (98%) delete mode 100644 src/librustc_back/abi.rs rename src/{libstd => librustc_back}/dynamic_lib.rs (56%) create mode 100644 src/librustc_back/target/i586_pc_windows_msvc.rs create mode 100644 src/librustc_borrowck/bitslice.rs create mode 100644 src/librustc_borrowck/borrowck/mir/abs_domain.rs create mode 100644 src/librustc_borrowck/borrowck/mir/dataflow.rs create mode 100644 src/librustc_borrowck/borrowck/mir/gather_moves.rs create mode 100644 src/librustc_borrowck/borrowck/mir/graphviz.rs create mode 100644 src/librustc_borrowck/borrowck/mir/mod.rs create mode 100644 src/librustc_const_eval/Cargo.toml rename src/{librustc/middle => librustc_const_eval}/check_match.rs (89%) create mode 100644 src/librustc_const_eval/diagnostics.rs create mode 100644 src/librustc_const_eval/eval.rs create mode 100644 src/librustc_const_eval/lib.rs rename src/{librustc_front => librustc_const_math}/Cargo.toml (71%) create mode 100644 src/librustc_const_math/err.rs create mode 100644 src/librustc_const_math/int.rs create mode 100644 src/librustc_const_math/is.rs create mode 100644 src/librustc_const_math/lib.rs create mode 100644 src/librustc_const_math/us.rs delete mode 100644 src/librustc_front/lib.rs delete mode 100644 src/librustc_front/util.rs create mode 100644 src/librustc_incremental/Cargo.toml rename src/{librustc_trans/trans => librustc_incremental}/assert_dep_graph.rs (75%) rename src/{librustc_back/svh.rs => librustc_incremental/calculate_svh.rs} (79%) create mode 100644 src/librustc_incremental/lib.rs create mode 100644 src/librustc_incremental/persist/README.md create mode 100644 src/librustc_incremental/persist/data.rs create mode 100644 src/librustc_incremental/persist/directory.rs create mode 100644 src/librustc_incremental/persist/dirty_clean.rs create mode 100644 src/librustc_incremental/persist/load.rs create mode 100644 src/librustc_incremental/persist/mod.rs create mode 100644 src/librustc_incremental/persist/save.rs create mode 100644 src/librustc_incremental/persist/serialize.rs create mode 100644 src/librustc_incremental/persist/util.rs delete mode 100644 src/librustc_mir/build/stmt.rs create mode 100644 src/librustc_mir/transform/break_critical_edges.rs rename src/librustc_mir/transform/{clear_dead_blocks.rs => remove_dead_blocks.rs} (53%) create mode 100644 src/librustc_mir/traversal.rs create mode 100644 src/librustc_save_analysis/Cargo.toml create mode 100644 src/librustc_save_analysis/csv_dumper.rs create mode 100644 src/librustc_save_analysis/data.rs create mode 100644 src/librustc_save_analysis/dump.rs rename src/{librustc_trans/save/dump_csv.rs => librustc_save_analysis/dump_visitor.rs} (61%) rename src/{librustc_trans/save/mod.rs => librustc_save_analysis/lib.rs} (76%) rename src/{librustc_trans/save => librustc_save_analysis}/span_utils.rs (95%) rename src/librustc_trans/{trans => }/_match.rs (95%) create mode 100644 src/librustc_trans/abi.rs rename src/librustc_trans/{trans => }/adt.rs (92%) create mode 100644 src/librustc_trans/asm.rs create mode 100644 src/librustc_trans/attributes.rs create mode 100644 src/librustc_trans/back/symbol_names.rs rename src/librustc_trans/{trans => }/base.rs (63%) rename src/librustc_trans/{trans => }/basic_block.rs (92%) rename src/librustc_trans/{trans => }/build.rs (94%) rename src/librustc_trans/{trans => }/builder.rs (91%) rename src/librustc_trans/{trans => }/cabi_aarch64.rs (78%) rename src/librustc_trans/{trans => }/cabi_arm.rs (73%) create mode 100644 src/librustc_trans/cabi_asmjs.rs rename src/librustc_trans/{trans => }/cabi_mips.rs (69%) rename src/librustc_trans/{trans => }/cabi_powerpc.rs (66%) rename src/librustc_trans/{trans => }/cabi_powerpc64.rs (77%) create mode 100644 src/librustc_trans/cabi_x86.rs rename src/librustc_trans/{trans => }/cabi_x86_64.rs (87%) create mode 100644 src/librustc_trans/cabi_x86_win64.rs create mode 100644 src/librustc_trans/callee.rs rename src/librustc_trans/{trans => }/cleanup.rs (96%) create mode 100644 src/librustc_trans/closure.rs rename src/librustc_trans/{trans => }/collector.rs (83%) rename src/librustc_trans/{trans => }/common.rs (80%) rename src/librustc_trans/{trans => }/consts.rs (67%) rename src/librustc_trans/{trans => }/context.rs (89%) rename src/librustc_trans/{trans => }/controlflow.rs (87%) rename src/librustc_trans/{trans => }/datum.rs (94%) rename src/librustc_trans/{trans => }/debuginfo/create_scope_map.rs (94%) rename src/librustc_trans/{trans => }/debuginfo/doc.rs (100%) rename src/librustc_trans/{trans => }/debuginfo/gdb.rs (92%) rename src/librustc_trans/{trans => }/debuginfo/metadata.rs (92%) rename src/librustc_trans/{trans => }/debuginfo/mod.rs (92%) create mode 100644 src/librustc_trans/debuginfo/namespace.rs rename src/librustc_trans/{trans => }/debuginfo/source_loc.rs (99%) rename src/librustc_trans/{trans => }/debuginfo/type_names.rs (83%) rename src/librustc_trans/{trans => }/debuginfo/utils.rs (93%) create mode 100644 src/librustc_trans/declare.rs rename src/librustc_trans/{trans => }/disr.rs (90%) rename src/librustc_trans/{trans => }/expr.rs (81%) rename src/librustc_trans/{trans => }/glue.rs (81%) rename src/librustc_trans/{trans => }/inline.rs (62%) rename src/librustc_trans/{trans => }/intrinsic.rs (79%) rename src/librustc_trans/{trans => }/machine.rs (98%) rename src/librustc_trans/{trans => }/macros.rs (100%) create mode 100644 src/librustc_trans/meth.rs rename src/librustc_trans/{trans => }/mir/analyze.rs (96%) create mode 100644 src/librustc_trans/mir/block.rs create mode 100644 src/librustc_trans/mir/constant.rs create mode 100644 src/librustc_trans/mir/drop.rs rename src/librustc_trans/{trans => }/mir/lvalue.rs (64%) rename src/librustc_trans/{trans => }/mir/mod.rs (50%) rename src/librustc_trans/{trans => }/mir/operand.rs (56%) rename src/librustc_trans/{trans => }/mir/rvalue.rs (74%) rename src/librustc_trans/{trans => }/mir/statement.rs (89%) create mode 100644 src/librustc_trans/monomorphize.rs delete mode 100644 src/librustc_trans/save/recorder.rs create mode 100644 src/librustc_trans/symbol_names_test.rs delete mode 100644 src/librustc_trans/trans/asm.rs delete mode 100644 src/librustc_trans/trans/attributes.rs delete mode 100644 src/librustc_trans/trans/cabi.rs delete mode 100644 src/librustc_trans/trans/cabi_asmjs.rs delete mode 100644 src/librustc_trans/trans/cabi_x86.rs delete mode 100644 src/librustc_trans/trans/cabi_x86_win64.rs delete mode 100644 src/librustc_trans/trans/callee.rs delete mode 100644 src/librustc_trans/trans/closure.rs delete mode 100644 src/librustc_trans/trans/debuginfo/namespace.rs delete mode 100644 src/librustc_trans/trans/declare.rs delete mode 100644 src/librustc_trans/trans/foreign.rs delete mode 100644 src/librustc_trans/trans/llrepr.rs delete mode 100644 src/librustc_trans/trans/meth.rs delete mode 100644 src/librustc_trans/trans/mir/block.rs delete mode 100644 src/librustc_trans/trans/mir/constant.rs delete mode 100644 src/librustc_trans/trans/mir/did.rs delete mode 100644 src/librustc_trans/trans/mod.rs delete mode 100644 src/librustc_trans/trans/monomorphize.rs rename src/librustc_trans/{trans => }/tvec.rs (86%) rename src/librustc_trans/{trans => }/type_.rs (88%) rename src/librustc_trans/{trans => }/type_of.rs (61%) rename src/librustc_trans/{trans => }/value.rs (92%) delete mode 100644 src/libstd/collections/hash/state.rs create mode 100644 src/libstd/os/emscripten/fs.rs rename src/{rustc/rustbook.rs => libstd/os/emscripten/mod.rs} (81%) create mode 100644 src/libstd/os/emscripten/raw.rs delete mode 100644 src/libstd/sync/semaphore.rs create mode 100644 src/libstd/sys/unix/ext/net.rs create mode 100644 src/libstd/sys/windows/dynamic_lib.rs delete mode 100644 src/libsyntax/ast_util.rs delete mode 100644 src/rustbook/Cargo.toml create mode 100644 src/rustc/test_shim/Cargo.lock create mode 100644 src/rustc/test_shim/Cargo.toml create mode 100644 src/rustc/test_shim/lib.rs create mode 100644 src/test/auxiliary/cgu_test.rs create mode 100644 src/test/auxiliary/cgu_test_a.rs create mode 100644 src/test/auxiliary/cgu_test_b.rs create mode 100644 src/test/auxiliary/derive-no-std.rs create mode 100644 src/test/auxiliary/empty.rs rename src/test/auxiliary/{issue-17718.rs => issue-17718-aux.rs} (100%) create mode 100644 src/test/auxiliary/reexp_stripped.rs create mode 100644 src/test/auxiliary/specialization_cross_crate.rs create mode 100755 src/test/auxiliary/specialization_cross_crate_defaults.rs rename src/test/auxiliary/{typeid-intrinsic.rs => typeid-intrinsic-aux1.rs} (100%) rename src/test/auxiliary/{typeid-intrinsic2.rs => typeid-intrinsic-aux2.rs} (100%) create mode 100644 src/test/auxiliary/variant-struct.rs create mode 100644 src/test/codegen/float_math.rs create mode 100644 src/test/codegen/naked-functions.rs rename src/test/{compile-fail => compile-fail-fulldeps}/derive-no-std-not-supported.rs (100%) rename src/test/{compile-fail => compile-fail-fulldeps}/dropck_tarena_cycle_checked.rs (100%) rename src/test/{compile-fail => compile-fail-fulldeps}/dropck_tarena_unsound_drop.rs (100%) create mode 100644 src/test/compile-fail/bad-intrinsic-monomorphization.rs rename src/test/compile-fail/{coherence-cow-2.rs => coherence-cow.rs} (74%) create mode 100644 src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs create mode 100644 src/test/compile-fail/consider-removing-last-semi.rs create mode 100644 src/test/compile-fail/const-err-early.rs create mode 100644 src/test/compile-fail/enum-discrim-autosizing.rs create mode 100644 src/test/compile-fail/enum-discrim-too-small2.rs create mode 100644 src/test/compile-fail/feature-gate-negate-unsigned0.rs create mode 100644 src/test/compile-fail/feature-gate-try-operator.rs create mode 100644 src/test/compile-fail/gated-naked_functions.rs create mode 100644 src/test/compile-fail/glob-cycles.rs create mode 100644 src/test/compile-fail/impossible_range.rs create mode 100644 src/test/compile-fail/inherent-overlap.rs create mode 100644 src/test/compile-fail/invalid-intrinsic.rs rename src/test/{parse-fail => compile-fail}/issue-10636-2.rs (77%) create mode 100644 src/test/compile-fail/issue-22684.rs create mode 100644 src/test/compile-fail/issue-24883.rs create mode 100644 src/test/compile-fail/issue-26930.rs create mode 100644 src/test/compile-fail/issue-27340.rs create mode 100644 src/test/compile-fail/issue-29124.rs create mode 100644 src/test/compile-fail/issue-30079.rs create mode 100644 src/test/compile-fail/issue-30560.rs create mode 100644 src/test/compile-fail/issue-30730.rs create mode 100644 src/test/compile-fail/issue-31511.rs rename src/test/compile-fail/{mut-not-freeze.rs => issue-31804.rs} (66%) create mode 100644 src/test/compile-fail/issue-32119.rs create mode 100644 src/test/compile-fail/issue-32128.rs create mode 100644 src/test/compile-fail/issue-32201.rs create mode 100644 src/test/compile-fail/issue-32222.rs create mode 100644 src/test/compile-fail/issue-32323.rs create mode 100644 src/test/compile-fail/issue-32326.rs create mode 100644 src/test/compile-fail/issue-32377.rs create mode 100644 src/test/compile-fail/issue-32797.rs create mode 100644 src/test/compile-fail/lexical-scopes.rs create mode 100644 src/test/compile-fail/lint-removed-allow.rs create mode 100644 src/test/compile-fail/lint-renamed-allow.rs create mode 100644 src/test/compile-fail/lint-type-limits2.rs create mode 100644 src/test/compile-fail/lint-type-limits3.rs create mode 100644 src/test/compile-fail/lint-type-overflow2.rs create mode 100644 src/test/compile-fail/macro-expanded-mod.rs create mode 100644 src/test/compile-fail/macro_expanded_mod_helper/foo/bar.rs create mode 100644 src/test/compile-fail/macro_expanded_mod_helper/foo/mod.rs rename src/test/{run-make/rustdoc-json/foo.rs => compile-fail/meta-expected-error-correct-rev.rs} (70%) rename src/test/compile-fail/{coherence-cow-1.rs => meta-expected-error-wrong-rev.rs} (55%) create mode 100644 src/test/compile-fail/non-interger-atomic.rs create mode 100644 src/test/compile-fail/not-sync.rs create mode 100644 src/test/compile-fail/privacy-in-paths.rs create mode 100644 src/test/compile-fail/range_inclusive_gate.rs create mode 100644 src/test/compile-fail/rfc1445/feature-gate.rs create mode 100644 src/test/compile-fail/rfc1445/match-forbidden-without-eq.rs create mode 100644 src/test/compile-fail/rfc1445/match-requires-both-partialeq-and-eq.rs rename src/test/compile-fail/{no_share-rc.rs => shadowed-trait-methods.rs} (59%) create mode 100644 src/test/compile-fail/specialization/README.md create mode 100644 src/test/compile-fail/specialization/specialization-default-projection.rs create mode 100644 src/test/compile-fail/specialization/specialization-default-types.rs rename src/test/{run-pass/allocator-jemalloc.rs => compile-fail/specialization/specialization-feature-gate-default.rs} (61%) create mode 100644 src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs create mode 100644 src/test/compile-fail/specialization/specialization-no-default.rs create mode 100644 src/test/compile-fail/specialization/specialization-overlap-negative.rs create mode 100644 src/test/compile-fail/specialization/specialization-overlap.rs create mode 100755 src/test/compile-fail/specialization/specialization-polarity.rs create mode 100644 src/test/compile-fail/substs-ppaux.rs rename src/test/compile-fail/{comm-not-freeze-receiver.rs => symbol-names/basic.rs} (67%) create mode 100644 src/test/compile-fail/symbol-names/impl1.rs create mode 100644 src/test/compile-fail/token-error-correct-2.rs create mode 100644 src/test/compile-fail/token-error-correct-3.rs create mode 100644 src/test/compile-fail/token-error-correct.rs create mode 100644 src/test/compile-fail/trait-privacy.rs create mode 100644 src/test/compile-fail/trait-suggest-where-clause.rs create mode 100644 src/test/compile-fail/traits-inductive-overflow-auto-normal-auto.rs create mode 100644 src/test/compile-fail/transmute-from-fn-item-types-error.rs create mode 100644 src/test/compile-fail/transmute-from-fn-item-types-lint.rs delete mode 100644 src/test/compile-fail/unique-vec-res.rs delete mode 100644 src/test/compile-fail/unnecessary-private.rs create mode 100644 src/test/compile-fail/use-super-global-path.rs create mode 100644 src/test/incremental/dirty_clean.rs create mode 100644 src/test/incremental/hello_world.rs create mode 100644 src/test/incremental/string_constant.rs create mode 100644 src/test/parse-fail/default.rs create mode 100644 src/test/parse-fail/issue-32501.rs rename src/test/{run-pass/placement-new-arena.rs => parse-fail/range_inclusive.rs} (59%) create mode 100644 src/test/parse-fail/range_inclusive_gate.rs create mode 100644 src/test/pretty/top-level-doc-comments.rs create mode 100644 src/test/run-fail/meta-revision-bad.rs create mode 100644 src/test/run-fail/meta-revision-ok.rs create mode 100644 src/test/run-fail/mir_dynamic_drops_1.rs create mode 100644 src/test/run-fail/mir_dynamic_drops_2.rs create mode 100644 src/test/run-fail/mir_dynamic_drops_3.rs create mode 100644 src/test/run-make/a-b-a-linker-guard/Makefile create mode 100644 src/test/run-make/a-b-a-linker-guard/a.rs rename src/test/{parse-fail/struct-variant-no-pub.rs => run-make/a-b-a-linker-guard/b.rs} (78%) create mode 100644 src/test/run-make/reproducible-build/Makefile create mode 100644 src/test/run-make/reproducible-build/reproducible-build-aux.rs create mode 100644 src/test/run-make/reproducible-build/reproducible-build.rs delete mode 100644 src/test/run-make/rustdoc-json/Makefile create mode 100644 src/test/run-make/stable-symbol-names/Makefile create mode 100644 src/test/run-make/stable-symbol-names/stable-symbol-names1.rs create mode 100644 src/test/run-make/stable-symbol-names/stable-symbol-names2.rs rename src/test/{run-pass => run-pass-fulldeps}/conditional-debug-macro-off.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/deprecated-derive.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/deriving-encodable-decodable-box.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/deriving-encodable-decodable-cell-refcell.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/deriving-global.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/dropck_tarena_sound_drop.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/empty-struct-braces-derive.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/extern-mod-syntax.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-11881.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-14021.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-15924.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-24972.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-2804.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-4016.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/issue-4036.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/linkage-visibility.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/logging-enabled-debug.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/logging-enabled.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/logging-right-crate.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/logging-separate-lines.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/regions-mock-tcx.rs (100%) rename src/test/{run-pass => run-pass-fulldeps}/rust-log-filter.rs (100%) create mode 100644 src/test/run-pass/autoderef-privacy.rs create mode 100644 src/test/run-pass/bench/issue-32062.rs create mode 100644 src/test/run-pass/cabi-int-widening.rs create mode 100644 src/test/run-pass/coerce-unify.rs create mode 100644 src/test/run-pass/const-bitshift-rhs-inference.rs create mode 100644 src/test/run-pass/const-negation.rs create mode 100644 src/test/run-pass/empty-type-parameter-list.rs create mode 100644 src/test/run-pass/float_math.rs create mode 100644 src/test/run-pass/fn-item-type-zero-sized.rs rename src/test/{compile-fail => run-pass}/issue-20427.rs (55%) create mode 100644 src/test/run-pass/issue-23833.rs create mode 100644 src/test/run-pass/issue-26997.rs create mode 100644 src/test/run-pass/issue-28950.rs create mode 100644 src/test/run-pass/issue-29663.rs create mode 100644 src/test/run-pass/issue-30615.rs create mode 100644 src/test/run-pass/issue-31597.rs create mode 100644 src/test/run-pass/issue-31776.rs rename src/test/{compile-fail/dupe-symbols-8.rs => run-pass/issue-32292.rs} (77%) create mode 100644 src/test/run-pass/issue-32324.rs rename src/test/{compile-fail/comm-not-freeze.rs => run-pass/issue-32389.rs} (67%) create mode 100644 src/test/run-pass/issue-32518.rs create mode 100644 src/test/run-pass/issue-33461.rs create mode 100644 src/test/run-pass/lint-dead-code-associated-type.rs create mode 100644 src/test/run-pass/mir_fat_ptr_drop.rs create mode 100644 src/test/run-pass/mir_trans_critical_edge.rs create mode 100644 src/test/run-pass/parser-unicode-whitespace.rs create mode 100644 src/test/run-pass/process-status-inherits-stdin.rs create mode 100644 src/test/run-pass/range_inclusive.rs create mode 100644 src/test/run-pass/range_inclusive_gate.rs create mode 100644 src/test/run-pass/regions-lub-ref-ref-rc.rs create mode 100644 src/test/run-pass/rfc1445/eq-allows-match-on-ty-in-macro.rs rename src/test/{compile-fail/unique-unique-kind.rs => run-pass/rfc1445/eq-allows-match.rs} (68%) create mode 100644 src/test/run-pass/specialization/README.md rename src/test/{compile-fail/coherence-cow-no-cover.rs => run-pass/specialization/specialization-allowed-cross-crate.rs} (62%) create mode 100644 src/test/run-pass/specialization/specialization-assoc-fns.rs create mode 100644 src/test/run-pass/specialization/specialization-basics.rs create mode 100644 src/test/run-pass/specialization/specialization-cross-crate-defaults.rs create mode 100644 src/test/run-pass/specialization/specialization-cross-crate-no-gate.rs create mode 100644 src/test/run-pass/specialization/specialization-cross-crate.rs create mode 100644 src/test/run-pass/specialization/specialization-default-methods.rs create mode 100644 src/test/run-pass/specialization/specialization-on-projection.rs create mode 100644 src/test/run-pass/specialization/specialization-out-of-order.rs create mode 100644 src/test/run-pass/specialization/specialization-overlap-projection.rs create mode 100644 src/test/run-pass/specialization/specialization-projection-alias.rs create mode 100644 src/test/run-pass/specialization/specialization-projection.rs create mode 100644 src/test/run-pass/specialization/specialization-super-traits.rs create mode 100644 src/test/run-pass/specialization/specialization-translate-projections-with-params.rs create mode 100644 src/test/run-pass/specialization/specialization-translate-projections.rs create mode 100644 src/test/run-pass/transmute-from-fn-item-types.rs create mode 100644 src/test/run-pass/try-macro.rs create mode 100644 src/test/run-pass/try-operator-hygiene.rs create mode 100644 src/test/run-pass/try-operator.rs create mode 100644 src/test/run-pass/unique-ffi-symbols.rs create mode 100644 src/test/run-pass/volatile-fat-ptr.rs create mode 100644 src/test/rustdoc/inline_local/issue-28537.rs create mode 100644 src/test/rustdoc/inline_local/issue-32343.rs create mode 100644 src/test/rustdoc/inline_local/please_inline.rs create mode 100644 src/test/rustdoc/issue-27104.rs create mode 100644 src/test/rustdoc/issue-28478.rs create mode 100644 src/test/rustdoc/issue-32395.rs create mode 100644 src/test/rustdoc/redirect.rs create mode 100644 src/test/rustdoc/structfields.rs create mode 100644 src/tools/cargotest/Cargo.lock create mode 100644 src/tools/cargotest/Cargo.toml create mode 100644 src/tools/cargotest/lockfiles/iron-Cargo.lock create mode 100644 src/tools/cargotest/main.rs create mode 100644 src/tools/error_index_generator/Cargo.lock create mode 100644 src/tools/error_index_generator/Cargo.toml rename src/{ => tools}/error_index_generator/main.rs (68%) create mode 100644 src/tools/linkchecker/Cargo.lock create mode 100644 src/tools/linkchecker/Cargo.toml create mode 100644 src/tools/linkchecker/main.rs create mode 100644 src/tools/rustbook/Cargo.lock create mode 100644 src/tools/rustbook/Cargo.toml rename src/{ => tools}/rustbook/book.rs (100%) rename src/{ => tools}/rustbook/build.rs (71%) rename src/{ => tools}/rustbook/error.rs (100%) rename src/{ => tools}/rustbook/help.rs (100%) rename src/{ => tools}/rustbook/main.rs (98%) rename src/{ => tools}/rustbook/serve.rs (100%) rename src/{ => tools}/rustbook/static/rustbook.css (100%) rename src/{ => tools}/rustbook/static/rustbook.js (100%) rename src/{ => tools}/rustbook/subcommand.rs (100%) rename src/{ => tools}/rustbook/term.rs (100%) rename src/{ => tools}/rustbook/test.rs (97%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 609bf03fb6..10598e78ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,7 +71,8 @@ which includes important information about what platform you're on, what version of Rust you're using, etc. Sometimes, a backtrace is helpful, and so including that is nice. To get -a backtrace, set the `RUST_BACKTRACE` environment variable. The easiest way +a backtrace, set the `RUST_BACKTRACE` environment variable to a value +other than `0`. The easiest way to do this is to invoke `rustc` like this: ```bash @@ -132,8 +133,8 @@ Some common make targets are: - `make check-stage1-std NO_REBUILD=1` - test the standard library without rebuilding the entire compiler - `make check TESTNAME=` - Run a matching set of tests. - - `TESTNAME` should be a substring of the tests to match against e.g. it could - be the fully qualified test name, or just a part of it. + - `TESTNAME` should be a substring of the tests to match against e.g. it could + be the fully qualified test name, or just a part of it. `TESTNAME=collections::hash::map::test_map::test_capacity_not_less_than_len` or `TESTNAME=test_capacity_not_less_than_len`. - `make check-stage1-rpass TESTNAME=` - Run a single diff --git a/README.md b/README.md index a83f51e157..1acf5fd1f3 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ build. Download [MinGW from here](http://mingw-w64.org/doku.php/download/mingw-builds), and choose the -`threads=win32,exceptions=dwarf/seh` flavor when installing. After installing, +`version=4.9.x,threads=win32,exceptions=dwarf/seh` flavor when installing. Also, make sure to install to a path without spaces in it. After installing, add its `bin` directory to your `PATH`. This is due to [#28260](https://github.com/rust-lang/rust/issues/28260), in the future, installing from pacman should be just fine. @@ -177,10 +177,11 @@ 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 would be [#rust-beginners]. [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat [#rust]: irc://irc.mozilla.org/rust +[#rust-beginners]: irc://irc.mozilla.org/rust-beginners ## License diff --git a/RELEASES.md b/RELEASES.md index 0871ae3eaf..b19f4b07a3 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,291 @@ +Version 1.9.0 (2016-05-26) +========================== + +Language +-------- + +* The `#[deprecated]` attribute when applied to an API will generate + warnings when used. The warnings may be suppressed with + `#[allow(deprecated)]`. [RFC 1270]. +* [`fn` item types are zero sized, and each `fn` names a unique + type][1.9fn]. This will break code that transmutes `fn`s, so calling + `transmute` on a `fn` type will generate a warning for a few cycles, + then will be converted to an error. +* [Field and method resolution understand visibility, so private + fields and methods cannot prevent the proper use of public fields + and methods][1.9fv]. +* [The parser considers unicode codepoints in the + `PATTERN_WHITE_SPACE` category to be whitespace][1.9ws]. + +Stabilized APIs +--------------- + +* [`std::panic`] +* [`std::panic::catch_unwind`][] (renamed from `recover`) +* [`std::panic::resume_unwind`][] (renamed from `propagate`) +* [`std::panic::AssertUnwindSafe`][] (renamed from `AssertRecoverSafe`) +* [`std::panic::UnwindSafe`][] (renamed from `RecoverSafe`) +* [`str::is_char_boundary`] +* [`<*const T>::as_ref`] +* [`<*mut T>::as_ref`] +* [`<*mut T>::as_mut`] +* [`AsciiExt::make_ascii_uppercase`] +* [`AsciiExt::make_ascii_lowercase`] +* [`char::decode_utf16`] +* [`char::DecodeUtf16`] +* [`char::DecodeUtf16Error`] +* [`char::DecodeUtf16Error::unpaired_surrogate`] +* [`BTreeSet::take`] +* [`BTreeSet::replace`] +* [`BTreeSet::get`] +* [`HashSet::take`] +* [`HashSet::replace`] +* [`HashSet::get`] +* [`OsString::with_capacity`] +* [`OsString::clear`] +* [`OsString::capacity`] +* [`OsString::reserve`] +* [`OsString::reserve_exact`] +* [`OsStr::is_empty`] +* [`OsStr::len`] +* [`std::os::unix::thread`] +* [`RawPthread`] +* [`JoinHandleExt`] +* [`JoinHandleExt::as_pthread_t`] +* [`JoinHandleExt::into_pthread_t`] +* [`HashSet::hasher`] +* [`HashMap::hasher`] +* [`CommandExt::exec`] +* [`File::try_clone`] +* [`SocketAddr::set_ip`] +* [`SocketAddr::set_port`] +* [`SocketAddrV4::set_ip`] +* [`SocketAddrV4::set_port`] +* [`SocketAddrV6::set_ip`] +* [`SocketAddrV6::set_port`] +* [`SocketAddrV6::set_flowinfo`] +* [`SocketAddrV6::set_scope_id`] +* [`slice::copy_from_slice`] +* [`ptr::read_volatile`] +* [`ptr::write_volatile`] +* [`OpenOptions::create_new`] +* [`TcpStream::set_nodelay`] +* [`TcpStream::nodelay`] +* [`TcpStream::set_ttl`] +* [`TcpStream::ttl`] +* [`TcpStream::set_only_v6`] +* [`TcpStream::only_v6`] +* [`TcpStream::take_error`] +* [`TcpStream::set_nonblocking`] +* [`TcpListener::set_ttl`] +* [`TcpListener::ttl`] +* [`TcpListener::set_only_v6`] +* [`TcpListener::only_v6`] +* [`TcpListener::take_error`] +* [`TcpListener::set_nonblocking`] +* [`UdpSocket::set_broadcast`] +* [`UdpSocket::broadcast`] +* [`UdpSocket::set_multicast_loop_v4`] +* [`UdpSocket::multicast_loop_v4`] +* [`UdpSocket::set_multicast_ttl_v4`] +* [`UdpSocket::multicast_ttl_v4`] +* [`UdpSocket::set_multicast_loop_v6`] +* [`UdpSocket::multicast_loop_v6`] +* [`UdpSocket::set_multicast_ttl_v6`] +* [`UdpSocket::multicast_ttl_v6`] +* [`UdpSocket::set_ttl`] +* [`UdpSocket::ttl`] +* [`UdpSocket::set_only_v6`] +* [`UdpSocket::only_v6`] +* [`UdpSocket::join_multicast_v4`] +* [`UdpSocket::join_multicast_v6`] +* [`UdpSocket::leave_multicast_v4`] +* [`UdpSocket::leave_multicast_v6`] +* [`UdpSocket::take_error`] +* [`UdpSocket::connect`] +* [`UdpSocket::send`] +* [`UdpSocket::recv`] +* [`UdpSocket::set_nonblocking`] + +Libraries +--------- + +* [`std::sync::Once` is poisoned if its initialization function + fails][1.9o]. +* [`cell::Ref` and `cell::RefMut` can contain unsized types][1.9cu]. +* [Most types implement `fmt::Debug`][1.9db]. +* [The default buffer size used by `BufReader` and `BufWriter` was + reduced to 8K, from 64K][1.9bf]. This is in line with the buffer size + used by other languages. +* [`Instant`, `SystemTime` and `Duration` implement `+=` and `-=`. + `Duration` additionally implements `*=` and `/=`][1.9ta]. +* [`Skip` is a `DoubleEndedIterator`][1.9sk]. +* [`From<[u8; 4]>` is implemented for `Ipv4Addr`][1.9fi]. +* [`Chain` implements `BufRead`][1.9ch]. +* [`HashMap`, `HashSet` and iterators are covariant][1.9hc]. + +Cargo +----- + +* [Cargo can now run concurrently][1.9cc]. +* [Top-level overrides allow specific revisions of crates to be + overridden through the entire crate graph][1.9ct]. This is intended + to make upgrades easier for large projects, by allowing crates to be + forked temporarily until they've been upgraded and republished. +* [Cargo exports a `CARGO_PKG_AUTHORS` environment variable][1.9cp]. +* [Cargo will pass the contents of the `RUSTFLAGS` variable to `rustc` + on the commandline][1.9cf]. `rustc` arguments can also be specified + in the `build.rustflags` configuration key. + +Performance +----------- + +* [During type unification, the complexity of comparing variables for + equivalance was reduced from `O(n!)` to `O(n)`][1.9tu]. This leads + to major compile-time improvements in some scenarios. +* [`ToString` is specialized for `str`, giving it the same performance + as `to_owned`][1.9ts]. +* [Spawning processes with `Command::output` no longer creates extra + threads][1.9sp]. +* [`#[derive(PartialEq)]` and `#[derive(PartialOrd)]` emit less code + for C-like enums][1.9cl]. + +Misc +---- + +* [Passing the `--quiet` flag to a test runner will produce + much-abbreviated output][1.9q]. +* The Rust Project now publishes std binaries for the + `mips-unknown-linux-musl`, `mipsel-unknown-linux-musl`, and + `i586-pc-windows-msvc` targets. + +Compatibility Notes +------------------- + +* [`std::sync::Once` is poisoned if its initialization function + fails][1.9o]. +* [It is illegal to define methods with the same name in overlapping + inherent `impl` blocks][1.9sn]. +* [`fn` item types are zero sized, and each `fn` names a unique + type][1.9fn]. This will break code that transmutes `fn`s, so calling + `transmute` on a `fn` type will generate a warning for a few cycles, + then will be converted to an error. +* [Improvements to const evaluation may trigger new errors when integer + literals are out of range][1.9ce]. + + +[1.9bf]: https://github.com/rust-lang/rust/pull/32695 +[1.9cc]: https://github.com/rust-lang/cargo/pull/2486 +[1.9ce]: https://github.com/rust-lang/rust/pull/30587 +[1.9cf]: https://github.com/rust-lang/cargo/pull/2241 +[1.9ch]: https://github.com/rust-lang/rust/pull/32541 +[1.9cl]: https://github.com/rust-lang/rust/pull/31977 +[1.9cp]: https://github.com/rust-lang/cargo/pull/2465 +[1.9ct]: https://github.com/rust-lang/cargo/pull/2385 +[1.9cu]: https://github.com/rust-lang/rust/pull/32652 +[1.9db]: https://github.com/rust-lang/rust/pull/32054 +[1.9fi]: https://github.com/rust-lang/rust/pull/32050 +[1.9fn]: https://github.com/rust-lang/rust/pull/31710 +[1.9fv]: https://github.com/rust-lang/rust/pull/31938 +[1.9hc]: https://github.com/rust-lang/rust/pull/32635 +[1.9o]: https://github.com/rust-lang/rust/pull/32325 +[1.9q]: https://github.com/rust-lang/rust/pull/31887 +[1.9sk]: https://github.com/rust-lang/rust/pull/31700 +[1.9sn]: https://github.com/rust-lang/rust/pull/31925 +[1.9sp]: https://github.com/rust-lang/rust/pull/31618 +[1.9ta]: https://github.com/rust-lang/rust/pull/32448 +[1.9ts]: https://github.com/rust-lang/rust/pull/32586 +[1.9tu]: https://github.com/rust-lang/rust/pull/32062 +[1.9ws]: https://github.com/rust-lang/rust/pull/29734 +[RFC 1270]: https://github.com/rust-lang/rfcs/blob/master/text/1270-deprecation.md +[`<*const T>::as_ref`]: http://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.as_ref +[`<*mut T>::as_mut`]: http://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.as_mut +[`<*mut T>::as_ref`]: http://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.as_ref +[`slice::copy_from_slice`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.copy_from_slice +[`AsciiExt::make_ascii_lowercase`]: http://doc.rust-lang.org/nightly/std/ascii/trait.AsciiExt.html#tymethod.make_ascii_lowercase +[`AsciiExt::make_ascii_uppercase`]: http://doc.rust-lang.org/nightly/std/ascii/trait.AsciiExt.html#tymethod.make_ascii_uppercase +[`BTreeSet::get`]: http://doc.rust-lang.org/nightly/collections/btree/set/struct.BTreeSet.html#method.get +[`BTreeSet::replace`]: http://doc.rust-lang.org/nightly/collections/btree/set/struct.BTreeSet.html#method.replace +[`BTreeSet::take`]: http://doc.rust-lang.org/nightly/collections/btree/set/struct.BTreeSet.html#method.take +[`CommandExt::exec`]: http://doc.rust-lang.org/nightly/std/os/unix/process/trait.CommandExt.html#tymethod.exec +[`File::try_clone`]: http://doc.rust-lang.org/nightly/std/fs/struct.File.html#method.try_clone +[`HashMap::hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html#method.hasher +[`HashSet::get`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.get +[`HashSet::hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.hasher +[`HashSet::replace`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.replace +[`HashSet::take`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.take +[`JoinHandleExt::as_pthread_t`]: http://doc.rust-lang.org/nightly/std/os/unix/thread/trait.JoinHandleExt.html#tymethod.as_pthread_t +[`JoinHandleExt::into_pthread_t`]: http://doc.rust-lang.org/nightly/std/os/unix/thread/trait.JoinHandleExt.html#tymethod.into_pthread_t +[`JoinHandleExt`]: http://doc.rust-lang.org/nightly/std/os/unix/thread/trait.JoinHandleExt.html +[`OpenOptions::create_new`]: http://doc.rust-lang.org/nightly/std/fs/struct.OpenOptions.html#method.create_new +[`OsStr::is_empty`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.is_empty +[`OsStr::len`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsStr.html#method.len +[`OsString::capacity`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.capacity +[`OsString::clear`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.clear +[`OsString::reserve_exact`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.reserve_exact +[`OsString::reserve`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.reserve +[`OsString::with_capacity`]: http://doc.rust-lang.org/nightly/std/ffi/struct.OsString.html#method.with_capacity +[`RawPthread`]: http://doc.rust-lang.org/nightly/std/os/unix/thread/type.RawPthread.html +[`SocketAddr::set_ip`]: http://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_ip +[`SocketAddr::set_port`]: http://doc.rust-lang.org/nightly/std/net/enum.SocketAddr.html#method.set_port +[`SocketAddrV4::set_ip`]: http://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_ip +[`SocketAddrV4::set_port`]: http://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV4.html#method.set_port +[`SocketAddrV6::set_flowinfo`]: http://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_flowinfo +[`SocketAddrV6::set_ip`]: http://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_ip +[`SocketAddrV6::set_port`]: http://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_port +[`SocketAddrV6::set_scope_id`]: http://doc.rust-lang.org/nightly/std/net/struct.SocketAddrV6.html#method.set_scope_id +[`TcpListener::only_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.only_v6 +[`TcpListener::set_nonblocking`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_nonblocking +[`TcpListener::set_only_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_only_v6 +[`TcpListener::set_ttl`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_ttl +[`TcpListener::take_error`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.take_error +[`TcpListener::ttl`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.ttl +[`TcpStream::nodelay`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.nodelay +[`TcpStream::only_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.only_v6 +[`TcpStream::set_nodelay`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_nodelay +[`TcpStream::set_nonblocking`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_nonblocking +[`TcpStream::set_only_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_only_v6 +[`TcpStream::set_ttl`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.set_ttl +[`TcpStream::take_error`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.take_error +[`TcpStream::ttl`]: http://doc.rust-lang.org/nightly/std/net/struct.TcpStream.html#method.ttl +[`UdpSocket::broadcast`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.broadcast +[`UdpSocket::connect`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.connect +[`UdpSocket::join_multicast_v4`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.join_multicast_v4 +[`UdpSocket::join_multicast_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.join_multicast_v6 +[`UdpSocket::leave_multicast_v4`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.leave_multicast_v4 +[`UdpSocket::leave_multicast_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.leave_multicast_v6 +[`UdpSocket::multicast_loop_v4`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.multicast_loop_v4 +[`UdpSocket::multicast_loop_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.multicast_loop_v6 +[`UdpSocket::multicast_ttl_v4`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.multicast_ttl_v4 +[`UdpSocket::multicast_ttl_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.multicast_ttl_v6 +[`UdpSocket::only_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.only_v6 +[`UdpSocket::recv`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.recv +[`UdpSocket::send`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.send +[`UdpSocket::set_broadcast`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_broadcast +[`UdpSocket::set_multicast_loop_v4`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_multicast_loop_v4 +[`UdpSocket::set_multicast_loop_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_multicast_loop_v6 +[`UdpSocket::set_multicast_ttl_v4`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_multicast_ttl_v4 +[`UdpSocket::set_multicast_ttl_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_multicast_ttl_v6 +[`UdpSocket::set_nonblocking`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_nonblocking +[`UdpSocket::set_only_v6`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_only_v6 +[`UdpSocket::set_ttl`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.set_ttl +[`UdpSocket::take_error`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.take_error +[`UdpSocket::ttl`]: http://doc.rust-lang.org/nightly/std/net/struct.UdpSocket.html#method.ttl +[`char::DecodeUtf16Error::unpaired_surrogate`]: http://doc.rust-lang.org/nightly/std/char/struct.DecodeUtf16Error.html#method.unpaired_surrogate +[`char::DecodeUtf16Error`]: http://doc.rust-lang.org/nightly/std/char/struct.DecodeUtf16Error.html +[`char::DecodeUtf16`]: http://doc.rust-lang.org/nightly/std/char/struct.DecodeUtf16.html +[`char::decode_utf16`]: http://doc.rust-lang.org/nightly/std/char/fn.decode_utf16.html +[`ptr::read_volatile`]: http://doc.rust-lang.org/nightly/std/ptr/fn.read_volatile.html +[`ptr::write_volatile`]: http://doc.rust-lang.org/nightly/std/ptr/fn.write_volatile.html +[`std::os::unix::thread`]: http://doc.rust-lang.org/nightly/std/os/unix/thread/index.html +[`std::panic::AssertUnwindSafe`]: http://doc.rust-lang.org/nightly/std/panic/struct.AssertUnwindSafe.html +[`std::panic::UnwindSafe`]: http://doc.rust-lang.org/nightly/std/panic/trait.UnwindSafe.html +[`std::panic::catch_unwind`]: http://doc.rust-lang.org/nightly/std/panic/fn.catch_unwind.html +[`std::panic::resume_unwind`]: http://doc.rust-lang.org/nightly/std/panic/fn.resume_unwind.html +[`std::panic`]: http://doc.rust-lang.org/nightly/std/panic/index.html +[`str::is_char_boundary`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.is_char_boundary + + Version 1.8.0 (2016-04-14) ========================== @@ -209,16 +497,6 @@ Compatibility Notes Version 1.7.0 (2016-03-03) ========================== -Language --------- - -* Soundness fixes to the interactions between associated types and - lifetimes, specified in [RFC 1214], [now generate errors][1.7sf] for - code that violates the new rules. This is a significant change that - is known to break existing code, so it has emitted warnings for the - new error cases since 1.4 to give crate authors time to adapt. The - details of what is changing are subtle; read the RFC for more. - Libraries --------- @@ -267,6 +545,17 @@ Libraries * [`IntoStringError::into_cstring`] * [`IntoStringError::utf8_error`] * `Error for IntoStringError` + * Hashing + * [`std::hash::BuildHasher`] + * [`BuildHasher::Hasher`] + * [`BuildHasher::build_hasher`] + * [`std::hash::BuildHasherDefault`] + * [`HashMap::with_hasher`] + * [`HashMap::with_capacity_and_hasher`] + * [`HashSet::with_hasher`] + * [`HashSet::with_capacity_and_hasher`] + * [`std::collections::hash_map::RandomState`] + * [`RandomState::new`] * [Validating UTF-8 is faster by a factor of between 7 and 14x for ASCII input][1.7utf8]. This means that creating `String`s and `str`s from bytes is faster. @@ -288,9 +577,6 @@ Libraries Misc ---- -* [The `--error-format=json` flag to `rustc` causes it to emit errors - in JSON format][1.7j]. This is an unstable flag and so also requires - the `-Z unstable-options` flag. * [When running tests with `--test`, rustdoc will pass `--cfg` arguments to the compiler][1.7dt]. * [The compiler is built with RPATH information by default][1.7rpa]. @@ -312,6 +598,12 @@ Cargo Compatibility Notes ------------------- +* Soundness fixes to the interactions between associated types and + lifetimes, specified in [RFC 1214], [now generate errors][1.7sf] for + code that violates the new rules. This is a significant change that + is known to break existing code, so it has emitted warnings for the + new error cases since 1.4 to give crate authors time to adapt. The + details of what is changing are subtle; read the RFC for more. * [Several bugs in the compiler's visibility calculations were fixed][1.7v]. Since this was found to break significant amounts of code, the new errors will be emitted as warnings for several release @@ -320,8 +612,8 @@ Compatibility Notes that were not intended. In this release, [defaulted type parameters appearing outside of type definitions will generate a warning][1.7d], which will become an error in future releases. -* [Parsing "." as a float results in an error instead of - 0][1.7p]. That is, `".".parse::()` returns `Err`, not `Ok(0)`. +* [Parsing "." as a float results in an error instead of 0][1.7p]. + That is, `".".parse::()` returns `Err`, not `Ok(0.0)`. * [Borrows of closure parameters may not outlive the closure][1.7bc]. [1.7a]: https://github.com/rust-lang/rust/pull/30928 @@ -334,7 +626,6 @@ Compatibility Notes [1.7dta]: https://github.com/rust-lang/rust/pull/30394 [1.7f]: https://github.com/rust-lang/rust/pull/30672 [1.7h]: https://github.com/rust-lang/rust/pull/30818 -[1.7j]: https://github.com/rust-lang/rust/pull/30711 [1.7ll]: https://github.com/rust-lang/rust/pull/30663 [1.7m]: https://github.com/rust-lang/rust/pull/30381 [1.7p]: https://github.com/rust-lang/rust/pull/30681 @@ -345,11 +636,15 @@ Compatibility Notes [1.7utf8]: https://github.com/rust-lang/rust/pull/30740 [1.7v]: https://github.com/rust-lang/rust/pull/29973 [RFC 1214]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md -[`clone_from_slice`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice -[`sort_by_key`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.sort_by_key +[`BuildHasher::Hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.Hasher.html +[`BuildHasher::build_hasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.BuildHasher.html#tymethod.build_hasher [`CString::into_bytes_with_nul`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_bytes_with_nul [`CString::into_bytes`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_bytes [`CString::into_string`]: http://doc.rust-lang.org/nightly/std/ffi/struct.CString.html#method.into_string +[`HashMap::with_capacity_and_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html#method.with_capacity_and_hasher +[`HashMap::with_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashMap.html#method.with_hasher +[`HashSet::with_capacity_and_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.with_capacity_and_hasher +[`HashSet::with_hasher`]: http://doc.rust-lang.org/nightly/std/collections/struct.HashSet.html#method.with_hasher [`IntoStringError::into_cstring`]: http://doc.rust-lang.org/nightly/std/ffi/struct.IntoStringError.html#method.into_cstring [`IntoStringError::utf8_error`]: http://doc.rust-lang.org/nightly/std/ffi/struct.IntoStringError.html#method.utf8_error [`Ipv4Addr::is_broadcast`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv4Addr.html#method.is_broadcast @@ -362,10 +657,12 @@ Compatibility Notes [`Ipv6Addr::is_multicast`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#method.is_multicast [`Ipv6Addr::is_unspecified`]: http://doc.rust-lang.org/nightly/std/net/struct.Ipv6Addr.html#method.is_unspecified [`Path::strip_prefix`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.strip_prefix +[`RandomState::new`]: http://doc.rust-lang.org/nightly/std/collections/hash_map/struct.RandomState.html#method.new [`String::as_mut_str`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_mut_str [`String::as_str`]: http://doc.rust-lang.org/nightly/std/string/struct.String.html#method.as_str [`Vec::as_mut_slice`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_mut_slice [`Vec::as_slice`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.as_slice +[`clone_from_slice`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.clone_from_slice [`ffi::IntoStringError`]: http://doc.rust-lang.org/nightly/std/ffi/struct.IntoStringError.html [`i32::checked_neg`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.checked_neg [`i32::checked_rem`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.checked_rem @@ -381,8 +678,13 @@ Compatibility Notes [`i32::overflowing_sub`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.overflowing_sub [`i32::saturating_mul`]: http://doc.rust-lang.org/nightly/std/primitive.i32.html#method.saturating_mul [`path::StripPrefixError`]: http://doc.rust-lang.org/nightly/std/path/struct.StripPrefixError.html +[`sort_by_key`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.sort_by_key +[`std::collections::hash_map::RandomState`]: http://doc.rust-lang.org/nightly/std/collections/hash_map/struct.RandomState.html +[`std::hash::BuildHasherDefault`]: http://doc.rust-lang.org/nightly/std/hash/struct.BuildHasherDefault.html +[`std::hash::BuildHasher`]: http://doc.rust-lang.org/nightly/std/hash/trait.BuildHasher.html [`u32::checked_neg`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_neg [`u32::checked_rem`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_rem +[`u32::checked_neg`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_neg [`u32::checked_shl`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.checked_shl [`u32::overflowing_add`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.overflowing_add [`u32::overflowing_div`]: http://doc.rust-lang.org/nightly/std/primitive.u32.html#method.overflowing_div diff --git a/configure b/configure index 086dd9f74e..fdef550a64 100755 --- a/configure +++ b/configure @@ -607,6 +607,8 @@ opt dist-host-only 0 "only install bins for the host architecture" opt inject-std-version 1 "inject the current compiler version of libstd into programs" opt llvm-version-check 1 "check if the LLVM version is supported, build anyway" opt rustbuild 0 "use the rust and cargo based build system" +opt orbit 0 "get MIR where it belongs - everywhere; most importantly, in orbit" +opt codegen-tests 1 "run the src/test/codegen tests" # Optimization and debugging options. These may be overridden by the release channel, etc. opt_nosave optimize 1 "build optimized rust code" @@ -713,17 +715,7 @@ if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTION if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi -# A magic value that allows the compiler to use unstable features -# during the bootstrap even when doing so would normally be an error -# because of feature staging or because the build turns on -# warnings-as-errors and unstable features default to warnings. The -# build has to match this key in an env var. Meant to be a mild -# deterrent from users just turning on unstable features on the stable -# channel. -# Basing CFG_BOOTSTRAP_KEY on CFG_BOOTSTRAP_KEY lets it get picked up -# during a Makefile reconfig. -CFG_BOOTSTRAP_KEY="${CFG_BOOTSTRAP_KEY-`date +%H:%M:%S`}" -putvar CFG_BOOTSTRAP_KEY +if [ -n "$CFG_ENABLE_ORBIT" ]; then putvar CFG_ENABLE_ORBIT; fi step_msg "looking for build programs" @@ -966,11 +958,11 @@ then LLVM_VERSION=$($LLVM_CONFIG --version) case $LLVM_VERSION in - (3.[5-8]*) + (3.[6-8]*) msg "found ok version of LLVM: $LLVM_VERSION" ;; (*) - err "bad LLVM version: $LLVM_VERSION, need >=3.5" + err "bad LLVM version: $LLVM_VERSION, need >=3.6" ;; esac fi @@ -1031,7 +1023,7 @@ then if [ -n "$CFG_OSX_CLANG_VERSION" ] then case $CFG_OSX_CLANG_VERSION in - (7.0* | 7.1* | 7.2*) + (7.0* | 7.1* | 7.2* | 7.3*) step_msg "found ok version of APPLE CLANG: $CFG_OSX_CLANG_VERSION" ;; (*) @@ -1249,7 +1241,7 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake bits=x86_64 msvc_part=amd64 ;; - i686-*) + i*86-*) bits=i386 msvc_part= ;; @@ -1494,7 +1486,9 @@ do LLVM_INST_DIR=$CFG_LLVM_ROOT do_reconfigure=0 # Check that LLVm FileCheck is available. Needed for the tests - need_cmd $LLVM_INST_DIR/bin/FileCheck + if [ -z "$CFG_DISABLE_CODEGEN_TESTS" ]; then + need_cmd $LLVM_INST_DIR/bin/FileCheck + fi fi if [ ${do_reconfigure} -ne 0 ] diff --git a/man/rustc.1 b/man/rustc.1 index 0b8b1559d9..a034e471b6 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -268,7 +268,7 @@ the maximum number of threads used for this purpose. .TP \fBRUST_TEST_NOCAPTURE\fR -A synonym for the --nocapture flag. +If set to a value other than "0", a synonym for the --nocapture flag. .TP \fBRUST_MIN_STACK\fR @@ -276,7 +276,7 @@ Sets the minimum stack size for new threads. .TP \fBRUST_BACKTRACE\fR -If set, produces a backtrace in the output of a program which panics. +If set to a value different than "0", 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: diff --git a/mk/cfg/i586-pc-windows-msvc.mk b/mk/cfg/i586-pc-windows-msvc.mk new file mode 100644 index 0000000000..da2680f741 --- /dev/null +++ b/mk/cfg/i586-pc-windows-msvc.mk @@ -0,0 +1,28 @@ +# i586-pc-windows-msvc configuration +CC_i586-pc-windows-msvc="$(CFG_MSVC_CL_i386)" -nologo +LINK_i586-pc-windows-msvc="$(CFG_MSVC_LINK_i386)" -nologo +CXX_i586-pc-windows-msvc="$(CFG_MSVC_CL_i386)" -nologo +CPP_i586-pc-windows-msvc="$(CFG_MSVC_CL_i386)" -nologo +AR_i586-pc-windows-msvc="$(CFG_MSVC_LIB_i386)" -nologo +CFG_LIB_NAME_i586-pc-windows-msvc=$(1).dll +CFG_STATIC_LIB_NAME_i586-pc-windows-msvc=$(1).lib +CFG_LIB_GLOB_i586-pc-windows-msvc=$(1)-*.{dll,lib} +CFG_LIB_DSYM_GLOB_i586-pc-windows-msvc=$(1)-*.dylib.dSYM +CFG_JEMALLOC_CFLAGS_i586-pc-windows-msvc := +CFG_GCCISH_CFLAGS_i586-pc-windows-msvc := -MD -arch:IA32 +CFG_GCCISH_CXXFLAGS_i586-pc-windows-msvc := -MD -arch:IA32 +CFG_GCCISH_LINK_FLAGS_i586-pc-windows-msvc := +CFG_GCCISH_DEF_FLAG_i586-pc-windows-msvc := +CFG_LLC_FLAGS_i586-pc-windows-msvc := +CFG_INSTALL_NAME_i586-pc-windows-msvc = +CFG_EXE_SUFFIX_i586-pc-windows-msvc := .exe +CFG_WINDOWSY_i586-pc-windows-msvc := 1 +CFG_UNIXY_i586-pc-windows-msvc := +CFG_LDPATH_i586-pc-windows-msvc := +CFG_RUN_i586-pc-windows-msvc=$(2) +CFG_RUN_TARG_i586-pc-windows-msvc=$(call CFG_RUN_i586-pc-windows-msvc,,$(2)) +CFG_GNU_TRIPLE_i586-pc-windows-msvc := i586-pc-win32 + +# Currently the build system is not configured to build jemalloc +# with MSVC, so we omit this optional dependency. +CFG_DISABLE_JEMALLOC_i586-pc-windows-msvc := 1 diff --git a/mk/cfg/i586-unknown-linux-gnu.mk b/mk/cfg/i586-unknown-linux-gnu.mk index 0609f365de..2b28550320 100644 --- a/mk/cfg/i586-unknown-linux-gnu.mk +++ b/mk/cfg/i586-unknown-linux-gnu.mk @@ -7,9 +7,9 @@ CFG_LIB_NAME_i586-unknown-linux-gnu=lib$(1).so CFG_STATIC_LIB_NAME_i586-unknown-linux-gnu=lib$(1).a CFG_LIB_GLOB_i586-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM -CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) +CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -march=pentium +CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -march=pentium +CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) -march=pentium CFG_GCCISH_LINK_FLAGS_i586-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32 CFG_GCCISH_DEF_FLAG_i586-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list= CFG_LLC_FLAGS_i586-unknown-linux-gnu := diff --git a/mk/cfg/i686-pc-windows-gnu.mk b/mk/cfg/i686-pc-windows-gnu.mk index 0ed65effbd..3426b30aee 100644 --- a/mk/cfg/i686-pc-windows-gnu.mk +++ b/mk/cfg/i686-pc-windows-gnu.mk @@ -25,5 +25,3 @@ CFG_GNU_TRIPLE_i686-pc-windows-gnu := i686-w64-mingw32 CFG_THIRD_PARTY_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o CFG_INSTALLED_OBJECTS_i686-pc-windows-gnu := crt2.o dllcrt2.o rsbegin.o rsend.o CFG_RUSTRT_HAS_STARTUP_OBJS_i686-pc-windows-gnu := 1 -# FIXME(#31030) - there's not a great reason to disable jemalloc here -CFG_DISABLE_JEMALLOC_i686-pc-windows-gnu := 1 diff --git a/mk/cfg/x86_64-pc-windows-gnu.mk b/mk/cfg/x86_64-pc-windows-gnu.mk index f7fc4a2f26..f0732d08c7 100644 --- a/mk/cfg/x86_64-pc-windows-gnu.mk +++ b/mk/cfg/x86_64-pc-windows-gnu.mk @@ -25,5 +25,3 @@ CFG_GNU_TRIPLE_x86_64-pc-windows-gnu := x86_64-w64-mingw32 CFG_THIRD_PARTY_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o CFG_INSTALLED_OBJECTS_x86_64-pc-windows-gnu := crt2.o dllcrt2.o rsbegin.o rsend.o CFG_RUSTRT_HAS_STARTUP_OBJS_x86_64-pc-windows-gnu := 1 -# FIXME(#31030) - there's not a great reason to disable jemalloc here -CFG_DISABLE_JEMALLOC_x86_64-pc-windows-gnu := 1 diff --git a/mk/crates.mk b/mk/crates.mk index b7bb7c1083..dafda75f5f 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -49,16 +49,18 @@ # automatically generated for all stage/host/target combinations. ################################################################################ -TARGET_CRATES := libc std flate arena term \ - serialize getopts collections test rand \ - log graphviz core rbml alloc \ +TARGET_CRATES := libc std term \ + getopts collections test rand \ + core alloc \ rustc_unicode rustc_bitflags \ alloc_system alloc_jemalloc RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \ rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \ - rustc_data_structures rustc_front rustc_platform_intrinsics \ - rustc_plugin rustc_metadata rustc_passes -HOST_CRATES := syntax syntax_ext $(RUSTC_CRATES) rustdoc fmt_macros + rustc_data_structures rustc_platform_intrinsics \ + rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \ + rustc_const_eval rustc_const_math rustc_incremental +HOST_CRATES := syntax syntax_ext $(RUSTC_CRATES) rustdoc fmt_macros \ + flate arena graphviz rbml log serialize TOOLS := compiletest rustdoc rustc rustbook error_index_generator DEPS_core := @@ -84,40 +86,49 @@ DEPS_log := std DEPS_num := std DEPS_rbml := std log serialize DEPS_serialize := std log -DEPS_term := std log -DEPS_test := std getopts serialize rbml term native:rust_test_helpers +DEPS_term := std +DEPS_test := std getopts term native:rust_test_helpers -DEPS_syntax := std term serialize log arena libc rustc_bitflags +DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode DEPS_syntax_ext := syntax fmt_macros -DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml rustc_front\ - log graphviz rustc_llvm rustc_back rustc_data_structures -DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc -DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax +DEPS_rustc_const_math := std syntax log serialize +DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \ + rustc_back graphviz + +DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml \ + log graphviz rustc_back rustc_data_structures\ + rustc_const_math +DEPS_rustc_back := std syntax flate log libc +DEPS_rustc_borrowck := rustc rustc_mir log graphviz syntax DEPS_rustc_data_structures := std log serialize DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \ rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \ - rustc_trans rustc_privacy rustc_lint rustc_front rustc_plugin \ - rustc_metadata syntax_ext rustc_passes -DEPS_rustc_front := std syntax log serialize -DEPS_rustc_lint := rustc log syntax + rustc_trans rustc_privacy rustc_lint rustc_plugin \ + rustc_metadata syntax_ext rustc_passes rustc_save_analysis rustc_const_eval \ + rustc_incremental +DEPS_rustc_lint := rustc log syntax rustc_const_eval DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags -DEPS_rustc_metadata := rustc rustc_front syntax rbml -DEPS_rustc_passes := syntax rustc core rustc_front -DEPS_rustc_mir := rustc rustc_front syntax -DEPS_rustc_resolve := arena rustc rustc_front log syntax -DEPS_rustc_platform_intrinsics := rustc rustc_llvm +DEPS_rustc_metadata := rustc syntax rbml rustc_const_math +DEPS_rustc_passes := syntax rustc core rustc_const_eval +DEPS_rustc_mir := rustc syntax rustc_const_math rustc_const_eval +DEPS_rustc_resolve := arena rustc log syntax +DEPS_rustc_platform_intrinsics := std DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir -DEPS_rustc_privacy := rustc rustc_front log syntax +DEPS_rustc_privacy := rustc log syntax DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \ - log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics -DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics + log syntax serialize rustc_llvm rustc_platform_intrinsics \ + rustc_const_math rustc_const_eval rustc_incremental +DEPS_rustc_incremental := rbml rustc serialize rustc_data_structures +DEPS_rustc_save_analysis := rustc log syntax +DEPS_rustc_typeck := rustc syntax rustc_platform_intrinsics rustc_const_math \ + rustc_const_eval DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \ - test rustc_lint rustc_front + test rustc_lint rustc_const_eval -TOOL_DEPS_compiletest := test getopts +TOOL_DEPS_compiletest := test getopts log TOOL_DEPS_rustdoc := rustdoc TOOL_DEPS_rustc := rustc_driver TOOL_DEPS_rustbook := std rustdoc @@ -125,8 +136,8 @@ TOOL_DEPS_error_index_generator := rustdoc syntax serialize TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs TOOL_SOURCE_rustc := $(S)src/driver/driver.rs -TOOL_SOURCE_rustbook := $(S)src/rustbook/main.rs -TOOL_SOURCE_error_index_generator := $(S)src/error_index_generator/main.rs +TOOL_SOURCE_rustbook := $(S)src/tools/rustbook/main.rs +TOOL_SOURCE_error_index_generator := $(S)src/tools/error_index_generator/main.rs ONLY_RLIB_core := 1 ONLY_RLIB_libc := 1 diff --git a/mk/dist.mk b/mk/dist.mk index 38e0bcd338..1273900608 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -54,7 +54,6 @@ PKG_FILES := \ doc \ driver \ etc \ - error_index_generator \ $(foreach crate,$(CRATES),lib$(crate)) \ libcollectionstest \ libcoretest \ @@ -65,7 +64,7 @@ PKG_FILES := \ rustc \ snapshots.txt \ rust-installer \ - rustbook \ + tools \ test) \ $(PKG_GITMODULES) \ $(filter-out config.stamp, \ diff --git a/mk/main.mk b/mk/main.mk index a0a44cd345..fc537d3b7d 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -13,17 +13,28 @@ ###################################################################### # The version number -CFG_RELEASE_NUM=1.8.0 +CFG_RELEASE_NUM=1.9.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=.3 # Append a version-dependent hash to each library, so we can install different # versions in the same place CFG_FILENAME_EXTRA=$(shell printf '%s' $(CFG_RELEASE)$(CFG_EXTRA_FILENAME) | $(CFG_HASH_COMMAND)) +# A magic value that allows the compiler to use unstable features during the +# bootstrap even when doing so would normally be an error because of feature +# staging or because the build turns on warnings-as-errors and unstable features +# default to warnings. The build has to match this key in an env var. +# +# This value is keyed off the release to ensure that all compilers for one +# particular release have the same bootstrap key. Note that this is +# intentionally not "secure" by any definition, this is largely just a deterrent +# from users enabling unstable features on the stable compiler. +CFG_BOOTSTRAP_KEY=$(CFG_FILENAME_EXTRA) + ifeq ($(CFG_RELEASE_CHANNEL),stable) # This is the normal semver version string, e.g. "0.12.0", "0.12.0-nightly" CFG_RELEASE=$(CFG_RELEASE_NUM) @@ -134,6 +145,11 @@ ifdef CFG_ENABLE_DEBUGINFO CFG_RUSTC_FLAGS += -g endif +ifdef CFG_ENABLE_ORBIT + $(info cfg: launching MIR (CFG_ENABLE_ORBIT)) + CFG_RUSTC_FLAGS += -Z orbit +endif + ifdef SAVE_TEMPS CFG_RUSTC_FLAGS += --save-temps endif @@ -488,7 +504,7 @@ endif LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3) := \ $$(CURDIR)/$$(HLIB$(1)_H_$(3)):$$(CFG_LLVM_INST_DIR_$(3))/lib LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3) := \ - $$(CURDIR)/$$(TLIB1_T_$(2)_H_$(CFG_BUILD)) + $$(CURDIR)/$$(TLIB$(1)_T_$(2)_H_$(3)) HOST_RPATH_VAR$(1)_T_$(2)_H_$(3) := \ $$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3))=$$(LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3)):$$$$$$(LD_LIBRARY_PATH_ENV_NAME$(1)_T_$(2)_H_$(3)) @@ -501,18 +517,14 @@ RPATH_VAR$(1)_T_$(2)_H_$(3) := $$(HOST_RPATH_VAR$(1)_T_$(2)_H_$(3)) # if you're building a cross config, the host->* parts are # effectively stage1, since it uses the just-built stage0. # -# This logic is similar to how the LD_LIBRARY_PATH variable must -# change be slightly different when doing cross compilations. -# The build doesn't copy over all target libraries into -# a new directory, so we need to point the library path at -# the build directory where all the target libraries came -# from (the stage0 build host). Otherwise the relative rpaths -# inside of the rustc binary won't get resolved correctly. +# Also be sure to use the right rpath because we're loading libraries from the +# CFG_BUILD's stage1 directory for our target, so switch this one instance of +# `RPATH_VAR` to get the bootstrap working. ifeq ($(1),0) ifneq ($(strip $(CFG_BUILD)),$(strip $(3))) CFGFLAG$(1)_T_$(2)_H_$(3) = stage1 -RPATH_VAR$(1)_T_$(2)_H_$(3) := $$(TARGET_RPATH_VAR$(1)_T_$(2)_H_$(3)) +RPATH_VAR$(1)_T_$(2)_H_$(3) := $$(TARGET_RPATH_VAR1_T_$(2)_H_$$(CFG_BUILD)) endif endif diff --git a/mk/rt.mk b/mk/rt.mk index bd17490955..6591812280 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -157,6 +157,8 @@ else ifeq ($(findstring android, $(OSTYPE_$(1))), android) # If the test suite passes, however, without symbol prefixes then we should be # good to go! JEMALLOC_ARGS_$(1) := --disable-tls --with-jemalloc-prefix=je_ +else ifeq ($(findstring dragonfly, $(OSTYPE_$(1))), dragonfly) + JEMALLOC_ARGS_$(1) := --with-jemalloc-prefix=je_ endif ifdef CFG_ENABLE_DEBUG_JEMALLOC @@ -236,11 +238,11 @@ COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1)) COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt ifeq ($$(findstring msvc,$(1)),msvc) -$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1)) +$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD)) @$$(call E, cmake: compiler-rt) $$(Q)cd "$$(COMPRT_BUILD_DIR_$(1))"; $$(CFG_CMAKE) "$(S)src/compiler-rt" \ -DCMAKE_BUILD_TYPE=$$(LLVM_BUILD_CONFIG_MODE) \ - -DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$(1)) \ + -DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$$(CFG_BUILD)) \ -G"$$(CFG_CMAKE_GENERATOR)" $$(Q)$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \ --target lib/builtins/builtins \ @@ -253,7 +255,7 @@ COMPRT_AR_$(1) := $$(AR_$(1)) # We chomp -Werror here because GCC warns about the type signature of # builtins not matching its own and the build fails. It's a bit hacky, # but what can we do, we're building libclang-rt using GCC ...... -COMPRT_CFLAGS_$(1) := $$(filter-out -Werror -Werror=*,$$(CFG_GCCISH_CFLAGS_$(1))) -std=c99 +COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error -std=c99 # FreeBSD Clang's packaging is problematic; it doesn't copy unwind.h to # the standard include directory. This should really be in our changes to @@ -361,7 +363,7 @@ $$(BACKTRACE_BUILD_DIR_$(1))/Makefile: $$(BACKTRACE_DEPS) $$(MKFILE_DEPS) CC="$$(CC_$(1))" \ AR="$$(AR_$(1))" \ RANLIB="$$(AR_$(1)) s" \ - CFLAGS="$$(CFG_GCCISH_CFLAGS_$(1):-Werror=) -fno-stack-protector" \ + CFLAGS="$$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error -fno-stack-protector" \ $(S)src/libbacktrace/configure --build=$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$(CFG_GNU_TRIPLE_$(1))) $$(Q)echo '#undef HAVE_ATOMIC_FUNCTIONS' >> \ $$(BACKTRACE_BUILD_DIR_$(1))/config.h diff --git a/mk/target.mk b/mk/target.mk index cdd8abd7fb..261b9e79aa 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -89,6 +89,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \ $$(RUSTFLAGS$(1)_$(4)_T_$(2)) \ --out-dir $$(@D) \ -C extra-filename=-$$(CFG_FILENAME_EXTRA) \ + -C metadata=$$(CFG_FILENAME_EXTRA) \ $$< @touch -r $$@.start_time $$@ && rm $$@.start_time $$(call LIST_ALL_OLD_GLOB_MATCHES, \ diff --git a/mk/tests.mk b/mk/tests.mk index ea88a7d34f..20736165b7 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -299,24 +299,35 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \ check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \ check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \ check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \ - check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \ - check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \ - check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \ check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \ check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \ check-stage$(1)-T-$(2)-H-$(3)-crates-exec \ check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \ check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \ check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \ - check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \ - check-stage$(1)-T-$(2)-H-$(3)-codegen-units-exec \ + check-stage$(1)-T-$(2)-H-$(3)-incremental-exec \ check-stage$(1)-T-$(2)-H-$(3)-doc-exec \ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec +ifndef CFG_DISABLE_CODEGEN_TESTS +check-stage$(1)-T-$(2)-H-$(3)-exec: \ + check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \ + check-stage$(1)-T-$(2)-H-$(3)-codegen-units-exec +endif + # Only test the compiler-dependent crates when the target is # able to build a compiler (when the target triple is in the set of host triples) ifneq ($$(findstring $(2),$$(CFG_HOST)),) +check-stage$(1)-T-$(2)-H-$(3)-exec: \ + check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \ + check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \ + check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec + +check-stage$(1)-T-$(2)-H-$(3)-pretty-exec: \ + check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-full-exec \ + check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-full-exec + check-stage$(1)-T-$(2)-H-$(3)-crates-exec: \ $$(foreach crate,$$(TEST_CRATES), \ check-stage$(1)-T-$(2)-H-$(3)-$$(crate)-exec) @@ -340,9 +351,7 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-exec: \ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec: \ check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-exec \ check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-valgrind-exec \ - check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-full-exec \ check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-exec \ - check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-full-exec \ check-stage$(1)-T-$(2)-H-$(3)-pretty-pretty-exec endef @@ -379,7 +388,7 @@ $(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): \ @$$(call E, rustc: $$@) $(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(2)) \ $$(subst @,,$$(STAGE$(1)_T_$(2)_H_$(3))) -o $$@ $$< --test \ - -L "$$(RT_OUTPUT_DIR_$(2))" \ + -Cmetadata="test-crate" -L "$$(RT_OUTPUT_DIR_$(2))" \ $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ $$(RUSTFLAGS_$(4)) @@ -473,6 +482,7 @@ DEBUGINFO_LLDB_RS := $(call rwildcard,$(S)src/test/debuginfo/,*.rs) CODEGEN_RS := $(call rwildcard,$(S)src/test/codegen/,*.rs) CODEGEN_CC := $(call rwildcard,$(S)src/test/codegen/,*.cc) CODEGEN_UNITS_RS := $(call rwildcard,$(S)src/test/codegen-units/,*.rs) +INCREMENTAL_RS := $(call rwildcard,$(S)src/test/incremental/,*.rs) RUSTDOCCK_RS := $(call rwildcard,$(S)src/test/rustdoc/,*.rs) RPASS_TESTS := $(RPASS_RS) @@ -488,6 +498,7 @@ DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS) DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS) CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC) CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS) +INCREMENTAL_TESTS := $(INCREMENTAL_RS) RUSTDOCCK_TESTS := $(RUSTDOCCK_RS) CTEST_SRC_BASE_rpass = run-pass @@ -550,6 +561,11 @@ CTEST_BUILD_BASE_codegen-units = codegen-units CTEST_MODE_codegen-units = codegen-units CTEST_RUNTOOL_codegen-units = $(CTEST_RUNTOOL) +CTEST_SRC_BASE_incremental = incremental +CTEST_BUILD_BASE_incremental = incremental +CTEST_MODE_incremental = incremental +CTEST_RUNTOOL_incremental = $(CTEST_RUNTOOL) + CTEST_SRC_BASE_rustdocck = rustdoc CTEST_BUILD_BASE_rustdocck = rustdoc CTEST_MODE_rustdocck = rustdoc @@ -673,6 +689,7 @@ CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \ $(S)src/etc/lldb_rust_formatters.py CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS) CTEST_DEPS_codegen-units_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_UNITS_TESTS) +CTEST_DEPS_incremental_$(1)-T-$(2)-H-$(3) = $$(INCREMENTAL_TESTS) CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \ $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ $(S)src/etc/htmldocck.py @@ -739,7 +756,7 @@ endif endef CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \ - debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck + debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck incremental $(foreach host,$(CFG_HOST), \ $(eval $(foreach target,$(CFG_TARGET), \ @@ -937,6 +954,7 @@ TEST_GROUPS = \ debuginfo-lldb \ codegen \ codegen-units \ + incremental \ doc \ $(foreach docname,$(DOC_NAMES),doc-$(docname)) \ pretty \ diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 05186d48ce..722feab212 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -3,16 +3,17 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -21,10 +22,10 @@ version = "0.1.0" [[package]] name = "cmake" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -32,12 +33,12 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "gcc" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -50,13 +51,18 @@ name = "kernel32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.2.7" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "md5" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -64,25 +70,25 @@ name = "num_cpus" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-serialize" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "toml" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "winapi" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 8321f93c90..88dd19a769 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -15,6 +15,10 @@ path = "main.rs" name = "rustc" path = "rustc.rs" +[[bin]] +name = "rustdoc" +path = "rustdoc.rs" + [dependencies] build_helper = { path = "../build_helper" } cmake = "0.1.10" @@ -27,3 +31,4 @@ winapi = "0.2" kernel32-sys = "0.2" gcc = "0.3.17" libc = "0.2" +md5 = "0.1" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 6659894a17..5de7e6957c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -73,7 +73,8 @@ class RustBuild: if self.rustc().startswith(self.bin_root()) and \ (not os.path.exists(self.rustc()) or self.rustc_out_of_date()): - shutil.rmtree(self.bin_root()) + if os.path.exists(self.bin_root()): + shutil.rmtree(self.bin_root()) filename = "rust-std-nightly-" + self.build + ".tar.gz" url = "https://static.rust-lang.org/dist/" + self.snap_rustc_date() tarball = os.path.join(rustc_cache, filename) diff --git a/src/bootstrap/build/channel.rs b/src/bootstrap/build/channel.rs index 628b1d7643..611e347561 100644 --- a/src/bootstrap/build/channel.rs +++ b/src/bootstrap/build/channel.rs @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::env; use std::fs::{self, File}; use std::io::prelude::*; -use std::path::Path; use std::process::Command; use build_helper::output; +use md5; use build::Build; -use build::util::mtime; pub fn collect(build: &mut Build) { let mut main_mk = String::new(); @@ -36,19 +36,23 @@ pub fn collect(build: &mut Build) { match &build.config.channel[..] { "stable" => { build.release = release_num.to_string(); + build.package_vers = build.release.clone(); build.unstable_features = false; } "beta" => { build.release = format!("{}-beta{}", release_num, prerelease_version); + build.package_vers = "beta".to_string(); build.unstable_features = false; } "nightly" => { build.release = format!("{}-nightly", release_num); + build.package_vers = "nightly".to_string(); build.unstable_features = true; } _ => { build.release = format!("{}-dev", release_num); + build.package_vers = build.release.clone(); build.unstable_features = true; } } @@ -76,7 +80,8 @@ pub fn collect(build: &mut Build) { build.short_ver_hash = Some(short_ver_hash); } - build.bootstrap_key = mtime(Path::new("config.toml")).seconds() - .to_string(); + let key = md5::compute(build.release.as_bytes()); + build.bootstrap_key = format!("{:02x}{:02x}{:02x}{:02x}", + key[0], key[1], key[2], key[3]); + env::set_var("RUSTC_BOOTSTRAP_KEY", &build.bootstrap_key); } - diff --git a/src/bootstrap/build/check.rs b/src/bootstrap/build/check.rs new file mode 100644 index 0000000000..a2445ae498 --- /dev/null +++ b/src/bootstrap/build/check.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, 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 build::{Build, Compiler}; + +pub fn linkcheck(build: &Build, stage: u32, host: &str) { + println!("Linkcheck stage{} ({})", stage, host); + let compiler = Compiler::new(stage, host); + build.run(build.tool_cmd(&compiler, "linkchecker") + .arg(build.out.join(host).join("doc"))); +} + +pub fn cargotest(build: &Build, stage: u32, host: &str) { + + let ref compiler = Compiler::new(stage, host); + + // Configure PATH to find the right rustc. NB. we have to use PATH + // and not RUSTC because the Cargo test suite has tests that will + // fail if rustc is not spelled `rustc`. + let path = build.sysroot(compiler).join("bin"); + let old_path = ::std::env::var("PATH").expect(""); + let sep = if cfg!(windows) { ";" } else {":" }; + let ref newpath = format!("{}{}{}", path.display(), sep, old_path); + + build.run(build.tool_cmd(compiler, "cargotest") + .env("PATH", newpath) + .arg(&build.cargo)); +} diff --git a/src/bootstrap/build/compile.rs b/src/bootstrap/build/compile.rs index 3be4199352..a67f1ba48b 100644 --- a/src/bootstrap/build/compile.rs +++ b/src/bootstrap/build/compile.rs @@ -15,33 +15,31 @@ use std::process::Command; use build_helper::output; -use build::util::{exe, staticlib, libdir, mtime, is_dylib}; -use build::{Build, Compiler}; +use build::util::{exe, staticlib, libdir, mtime, is_dylib, copy}; +use build::{Build, Compiler, Mode}; /// Build the standard library. /// /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn std<'a>(build: &'a Build, stage: u32, target: &str, - compiler: &Compiler<'a>) { - let host = compiler.host; - println!("Building stage{} std artifacts ({} -> {})", stage, - host, target); +pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { + println!("Building stage{} std artifacts ({} -> {})", compiler.stage, + compiler.host, target); // Move compiler-rt into place as it'll be required by the compiler when // building the standard library to link the dylib of libstd - let libdir = build.sysroot_libdir(stage, &host, target); + let libdir = build.sysroot_libdir(compiler, target); let _ = fs::remove_dir_all(&libdir); t!(fs::create_dir_all(&libdir)); - t!(fs::hard_link(&build.compiler_rt_built.borrow()[target], - libdir.join(staticlib("compiler-rt", target)))); + copy(&build.compiler_rt_built.borrow()[target], + &libdir.join(staticlib("compiler-rt", target))); build_startup_objects(build, target, &libdir); - let out_dir = build.cargo_out(stage, &host, true, target); + let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &build.compiler_path(compiler)); - let mut cargo = build.cargo(stage, compiler, true, target, "build"); + let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build"); cargo.arg("--features").arg(build.std_features()) .arg("--manifest-path") .arg(build.src.join("src/rustc/std_shim/Cargo.toml")); @@ -58,7 +56,7 @@ pub fn std<'a>(build: &'a Build, stage: u32, target: &str, } build.run(&mut cargo); - std_link(build, stage, target, compiler, host); + std_link(build, target, compiler, compiler.host); } /// Link all libstd rlibs/dylibs into the sysroot location. @@ -66,12 +64,12 @@ pub fn std<'a>(build: &'a Build, stage: u32, target: &str, /// Links those artifacts generated in the given `stage` for `target` produced /// by `compiler` into `host`'s sysroot. pub fn std_link(build: &Build, - stage: u32, target: &str, compiler: &Compiler, host: &str) { - let libdir = build.sysroot_libdir(stage, host, target); - let out_dir = build.cargo_out(stage, compiler.host, true, target); + let target_compiler = Compiler::new(compiler.stage, host); + let libdir = build.sysroot_libdir(&target_compiler, target); + let out_dir = build.cargo_out(compiler, Mode::Libstd, target); // If we're linking one compiler host's output into another, then we weren't // called from the `std` method above. In that case we clean out what's @@ -79,10 +77,24 @@ pub fn std_link(build: &Build, if host != compiler.host { let _ = fs::remove_dir_all(&libdir); t!(fs::create_dir_all(&libdir)); - t!(fs::hard_link(&build.compiler_rt_built.borrow()[target], - libdir.join(staticlib("compiler-rt", target)))); + copy(&build.compiler_rt_built.borrow()[target], + &libdir.join(staticlib("compiler-rt", target))); } add_to_sysroot(&out_dir, &libdir); + + if target.contains("musl") && + (target.contains("x86_64") || target.contains("i686")) { + copy_third_party_objects(build, target, &libdir); + } +} + +/// Copies the crt(1,i,n).o startup objects +/// +/// Only required for musl targets that statically link to libc +fn copy_third_party_objects(build: &Build, target: &str, into: &Path) { + for &obj in &["crt1.o", "crti.o", "crtn.o"] { + copy(&compiler_file(build.cc(target), obj), &into.join(obj)); + } } /// Build and prepare startup objects like rsbegin.o and rsend.o @@ -107,34 +119,59 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) { } for obj in ["crt2.o", "dllcrt2.o"].iter() { - t!(fs::copy(compiler_file(build.cc(target), obj), into.join(obj))); + copy(&compiler_file(build.cc(target), obj), &into.join(obj)); } } +/// Build libtest. +/// +/// This will build libtest and supporting libraries for a particular stage of +/// the build using the `compiler` targeting the `target` architecture. The +/// artifacts created will also be linked into the sysroot directory. +pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { + println!("Building stage{} test artifacts ({} -> {})", compiler.stage, + compiler.host, target); + let out_dir = build.cargo_out(compiler, Mode::Libtest, target); + build.clear_if_dirty(&out_dir, &libstd_shim(build, compiler, target)); + let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); + build.run(&mut cargo); + test_link(build, target, compiler, compiler.host); +} + +/// Link all libtest rlibs/dylibs into the sysroot location. +/// +/// Links those artifacts generated in the given `stage` for `target` produced +/// by `compiler` into `host`'s sysroot. +pub fn test_link(build: &Build, + target: &str, + compiler: &Compiler, + host: &str) { + let target_compiler = Compiler::new(compiler.stage, host); + let libdir = build.sysroot_libdir(&target_compiler, target); + let out_dir = build.cargo_out(compiler, Mode::Libtest, target); + add_to_sysroot(&out_dir, &libdir); +} + + /// Build the compiler. /// /// This will build the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. -pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str, - compiler: &Compiler<'a>) { - let host = compiler.host; - println!("Building stage{} compiler artifacts ({} -> {})", stage, - host, target); +pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { + println!("Building stage{} compiler artifacts ({} -> {})", + compiler.stage, compiler.host, target); - let out_dir = build.cargo_out(stage, &host, false, target); - build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target)); + let out_dir = build.cargo_out(compiler, Mode::Librustc, target); + build.clear_if_dirty(&out_dir, &libtest_shim(build, compiler, target)); - let mut cargo = build.cargo(stage, compiler, false, target, "build"); - cargo.arg("--features").arg(build.rustc_features(stage)) + let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build"); + cargo.arg("--features").arg(build.rustc_features()) .arg("--manifest-path") .arg(build.src.join("src/rustc/Cargo.toml")); - // In stage0 we may not need to build as many executables - if stage == 0 { - cargo.arg("--bin").arg("rustc"); - } - // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", &build.release) @@ -174,7 +211,7 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str, } build.run(&mut cargo); - rustc_link(build, stage, target, compiler, compiler.host); + rustc_link(build, target, compiler, compiler.host); } /// Link all librustc rlibs/dylibs into the sysroot location. @@ -182,24 +219,31 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str, /// Links those artifacts generated in the given `stage` for `target` produced /// by `compiler` into `host`'s sysroot. pub fn rustc_link(build: &Build, - stage: u32, target: &str, compiler: &Compiler, host: &str) { - let libdir = build.sysroot_libdir(stage, host, target); - let out_dir = build.cargo_out(stage, compiler.host, false, target); + let target_compiler = Compiler::new(compiler.stage, host); + let libdir = build.sysroot_libdir(&target_compiler, target); + let out_dir = build.cargo_out(compiler, Mode::Librustc, target); add_to_sysroot(&out_dir, &libdir); } /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -fn libstd_shim(build: &Build, stage: u32, host: &str, target: &str) -> PathBuf { - build.cargo_out(stage, host, true, target).join("libstd_shim.rlib") +fn libstd_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { + build.cargo_out(compiler, Mode::Libstd, target).join("libstd_shim.rlib") } -fn compiler_file(compiler: &Path, file: &str) -> String { - output(Command::new(compiler) - .arg(format!("-print-file-name={}", file))).trim().to_string() +/// Cargo's output path for libtest in a given stage, compiled by a particular +/// compiler for the specified target. +fn libtest_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf { + build.cargo_out(compiler, Mode::Libtest, target).join("libtest_shim.rlib") +} + +fn compiler_file(compiler: &Path, file: &str) -> PathBuf { + let out = output(Command::new(compiler) + .arg(format!("-print-file-name={}", file))); + PathBuf::from(out.trim()) } /// Prepare a new compiler from the artifacts in `stage` @@ -209,24 +253,29 @@ fn compiler_file(compiler: &Path, file: &str) -> String { /// compiler. pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { assert!(stage > 0, "the stage0 compiler isn't assembled, it's downloaded"); + // The compiler that we're assembling + let target_compiler = Compiler::new(stage, host); + + // The compiler that compiled the compiler we're assembling + let build_compiler = Compiler::new(stage - 1, &build.config.build); // Clear out old files - let sysroot = build.sysroot(stage, host); + let sysroot = build.sysroot(&target_compiler); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); // Link in all dylibs to the libdir let sysroot_libdir = sysroot.join(libdir(host)); t!(fs::create_dir_all(&sysroot_libdir)); - let src_libdir = build.sysroot_libdir(stage - 1, &build.config.build, host); + let src_libdir = build.sysroot_libdir(&build_compiler, host); for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) { let filename = f.file_name().into_string().unwrap(); if is_dylib(&filename) { - t!(fs::hard_link(&f.path(), sysroot_libdir.join(&filename))); + copy(&f.path(), &sysroot_libdir.join(&filename)); } } - let out_dir = build.cargo_out(stage - 1, &build.config.build, false, host); + let out_dir = build.cargo_out(&build_compiler, Mode::Librustc, host); // Link the compiler binary itself into place let rustc = out_dir.join(exe("rustc", host)); @@ -234,7 +283,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { t!(fs::create_dir_all(&bindir)); let compiler = build.compiler_path(&Compiler::new(stage, host)); let _ = fs::remove_file(&compiler); - t!(fs::hard_link(rustc, compiler)); + copy(&rustc, &compiler); // See if rustdoc exists to link it into place let rustdoc = exe("rustdoc", host); @@ -242,7 +291,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { let rustdoc_dst = bindir.join(&rustdoc); if fs::metadata(&rustdoc_src).is_ok() { let _ = fs::remove_file(&rustdoc_dst); - t!(fs::hard_link(&rustdoc_src, &rustdoc_dst)); + copy(&rustdoc_src, &rustdoc_dst); } } @@ -281,7 +330,30 @@ fn add_to_sysroot(out_dir: &Path, sysroot_dst: &Path) { let (_, path) = paths.iter().map(|path| { (mtime(&path).seconds(), path) }).max().unwrap(); - t!(fs::hard_link(&path, - sysroot_dst.join(path.file_name().unwrap()))); + copy(&path, &sysroot_dst.join(path.file_name().unwrap())); } } + +/// Build a tool in `src/tools` +/// +/// This will build the specified tool with the specified `host` compiler in +/// `stage` into the normal cargo output directory. +pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) { + println!("Building stage{} tool {} ({})", stage, tool, host); + + let compiler = Compiler::new(stage, host); + + // FIXME: need to clear out previous tool and ideally deps, may require + // isolating output directories or require a pseudo shim step to + // clear out all the info. + // + // Maybe when libstd is compiled it should clear out the rustc of the + // corresponding stage? + // let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target); + // build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target)); + + let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build"); + cargo.arg("--manifest-path") + .arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool))); + build.run(&mut cargo); +} diff --git a/src/bootstrap/build/dist.rs b/src/bootstrap/build/dist.rs new file mode 100644 index 0000000000..6ae652bd66 --- /dev/null +++ b/src/bootstrap/build/dist.rs @@ -0,0 +1,292 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, 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::fs::{self, File}; +use std::io::Write; +use std::path::{PathBuf, Path}; +use std::process::Command; + +use build::{Build, Compiler}; +use build::util::{cp_r, libdir, is_dylib}; + +fn package_vers(build: &Build) -> &str { + match &build.config.channel[..] { + "stable" => &build.release, + "beta" => "beta", + "nightly" => "nightly", + _ => &build.release, + } +} + +fn distdir(build: &Build) -> PathBuf { + build.out.join("dist") +} + +fn tmpdir(build: &Build) -> PathBuf { + build.out.join("tmp/dist") +} + +pub fn docs(build: &Build, stage: u32, host: &str) { + println!("Dist docs stage{} ({})", stage, host); + let name = format!("rust-docs-{}", package_vers(build)); + let image = tmpdir(build).join(format!("{}-{}-image", name, name)); + let _ = fs::remove_dir_all(&image); + + let dst = image.join("share/doc/rust/html"); + t!(fs::create_dir_all(&dst)); + let src = build.out.join(host).join("doc"); + cp_r(&src, &dst); + + let mut cmd = Command::new("sh"); + cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh"))) + .arg("--product-name=Rust-Documentation") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-documentation-is-installed.") + .arg(format!("--image-dir={}", sanitize_sh(&image))) + .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build)))) + .arg(format!("--output-dir={}", sanitize_sh(&distdir(build)))) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rust-docs") + .arg("--legacy-manifest-dirs=rustlib,cargo") + .arg("--bulk-dirs=share/doc/rust/html"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + + // As part of this step, *also* copy the docs directory to a directory which + // buildbot typically uploads. + if host == build.config.build { + let dst = distdir(build).join("doc").join(&build.package_vers); + t!(fs::create_dir_all(&dst)); + cp_r(&src, &dst); + } +} + +pub fn mingw(build: &Build, host: &str) { + println!("Dist mingw ({})", host); + let name = format!("rust-mingw-{}", package_vers(build)); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); + + // The first argument to the script is a "temporary directory" which is just + // thrown away (this contains the runtime DLLs included in the rustc package + // above) and the second argument is where to place all the MinGW components + // (which is what we want). + // + // FIXME: this script should be rewritten into Rust + let mut cmd = Command::new("python"); + cmd.arg(build.src.join("src/etc/make-win-dist.py")) + .arg(tmpdir(build)) + .arg(&image) + .arg(host); + build.run(&mut cmd); + + let mut cmd = Command::new("sh"); + cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh"))) + .arg("--product-name=Rust-MinGW") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-MinGW-is-installed.") + .arg(format!("--image-dir={}", sanitize_sh(&image))) + .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build)))) + .arg(format!("--output-dir={}", sanitize_sh(&distdir(build)))) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rust-mingw") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); +} + +pub fn rustc(build: &Build, stage: u32, host: &str) { + println!("Dist rustc stage{} ({})", stage, host); + let name = format!("rustc-{}", package_vers(build)); + let image = tmpdir(build).join(format!("{}-{}-image", name, host)); + let _ = fs::remove_dir_all(&image); + let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host)); + let _ = fs::remove_dir_all(&overlay); + + // Prepare the rustc "image", what will actually end up getting installed + prepare_image(build, stage, host, &image); + + // Prepare the overlay which is part of the tarball but won't actually be + // installed + t!(fs::create_dir_all(&overlay)); + let cp = |file: &str| { + install(&build.src.join(file), &overlay, 0o644); + }; + cp("COPYRIGHT"); + cp("LICENSE-APACHE"); + cp("LICENSE-MIT"); + cp("README.md"); + // tiny morsel of metadata is used by rust-packaging + let version = &build.version; + t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes())); + + // On MinGW we've got a few runtime DLL dependencies that we need to + // include. The first argument to this script is where to put these DLLs + // (the image we're creating), and the second argument is a junk directory + // to ignore all other MinGW stuff the script creates. + // + // On 32-bit MinGW we're always including a DLL which needs some extra + // licenses to distribute. On 64-bit MinGW we don't actually distribute + // anything requiring us to distribute a license, but it's likely the + // install will *also* include the rust-mingw package, which also needs + // licenses, so to be safe we just include it here in all MinGW packages. + // + // FIXME: this script should be rewritten into Rust + if host.contains("pc-windows-gnu") { + let mut cmd = Command::new("python"); + cmd.arg(build.src.join("src/etc/make-win-dist.py")) + .arg(&image) + .arg(tmpdir(build)) + .arg(host); + build.run(&mut cmd); + + let dst = image.join("share/doc"); + t!(fs::create_dir_all(&dst)); + cp_r(&build.src.join("src/etc/third-party"), &dst); + } + + // Finally, wrap everything up in a nice tarball! + let mut cmd = Command::new("sh"); + cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh"))) + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-roll.") + .arg(format!("--image-dir={}", sanitize_sh(&image))) + .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build)))) + .arg(format!("--output-dir={}", sanitize_sh(&distdir(build)))) + .arg(format!("--non-installed-overlay={}", sanitize_sh(&overlay))) + .arg(format!("--package-name={}-{}", name, host)) + .arg("--component-name=rustc") + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); + t!(fs::remove_dir_all(&overlay)); + + fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) { + let src = build.sysroot(&Compiler::new(stage, host)); + let libdir = libdir(host); + + // Copy rustc/rustdoc binaries + t!(fs::create_dir_all(image.join("bin"))); + cp_r(&src.join("bin"), &image.join("bin")); + + // Copy runtime DLLs needed by the compiler + if libdir != "bin" { + t!(fs::create_dir_all(image.join(libdir))); + for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) { + let name = entry.file_name(); + if let Some(s) = name.to_str() { + if is_dylib(s) { + install(&entry.path(), &image.join(libdir), 0o644); + } + } + } + } + + // Man pages + t!(fs::create_dir_all(image.join("share/man/man1"))); + cp_r(&build.src.join("man"), &image.join("share/man/man1")); + + // Debugger scripts + let cp_debugger_script = |file: &str| { + let dst = image.join("lib/rustlib/etc"); + t!(fs::create_dir_all(&dst)); + install(&build.src.join("src/etc/").join(file), &dst, 0o644); + }; + if host.contains("windows") { + // no debugger scripts + } else if host.contains("darwin") { + // lldb debugger scripts + install(&build.src.join("src/etc/rust-lldb"), &image.join("bin"), + 0o755); + + cp_debugger_script("lldb_rust_formatters.py"); + cp_debugger_script("debugger_pretty_printers_common.py"); + } else { + // gdb debugger scripts + install(&build.src.join("src/etc/rust-gdb"), &image.join("bin"), + 0o755); + + cp_debugger_script("gdb_load_rust_pretty_printers.py"); + cp_debugger_script("gdb_rust_pretty_printing.py"); + cp_debugger_script("debugger_pretty_printers_common.py"); + } + + // Misc license info + let cp = |file: &str| { + install(&build.src.join(file), &image.join("share/doc/rust"), 0o644); + }; + t!(fs::create_dir_all(&image.join("share/doc/rust"))); + cp("COPYRIGHT"); + cp("LICENSE-APACHE"); + cp("LICENSE-MIT"); + cp("README.md"); + } +} + +pub fn std(build: &Build, compiler: &Compiler, target: &str) { + println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host, + target); + let name = format!("rust-std-{}", package_vers(build)); + let image = tmpdir(build).join(format!("{}-{}-image", name, target)); + let _ = fs::remove_dir_all(&image); + + let dst = image.join("lib/rustlib").join(target); + t!(fs::create_dir_all(&dst)); + let src = build.sysroot(compiler).join("lib/rustlib"); + cp_r(&src.join(target), &dst); + + let mut cmd = Command::new("sh"); + cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh"))) + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=std-is-standing-at-the-ready.") + .arg(format!("--image-dir={}", sanitize_sh(&image))) + .arg(format!("--work-dir={}", sanitize_sh(&tmpdir(build)))) + .arg(format!("--output-dir={}", sanitize_sh(&distdir(build)))) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rust-std-{}", target)) + .arg("--legacy-manifest-dirs=rustlib,cargo"); + build.run(&mut cmd); + t!(fs::remove_dir_all(&image)); +} + +fn install(src: &Path, dstdir: &Path, perms: u32) { + let dst = dstdir.join(src.file_name().unwrap()); + t!(fs::copy(src, &dst)); + chmod(&dst, perms); +} + +#[cfg(unix)] +fn chmod(path: &Path, perms: u32) { + use std::os::unix::fs::*; + t!(fs::set_permissions(path, fs::Permissions::from_mode(perms))); +} +#[cfg(windows)] +fn chmod(_path: &Path, _perms: u32) {} + +// We have to run a few shell scripts, which choke quite a bit on both `\` +// characters and on `C:\` paths, so normalize both of them away. +fn sanitize_sh(path: &Path) -> String { + let path = path.to_str().unwrap().replace("\\", "/"); + return change_drive(&path).unwrap_or(path); + + fn change_drive(s: &str) -> Option { + let mut ch = s.chars(); + let drive = ch.next().unwrap_or('C'); + if ch.next() != Some(':') { + return None + } + if ch.next() != Some('/') { + return None + } + Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..])) + } +} diff --git a/src/bootstrap/build/doc.rs b/src/bootstrap/build/doc.rs index 937a234bec..5782dd5ec2 100644 --- a/src/bootstrap/build/doc.rs +++ b/src/bootstrap/build/doc.rs @@ -8,25 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::path::Path; use std::fs::{self, File}; use std::io::prelude::*; +use std::path::Path; +use std::process::Command; -use build::{Build, Compiler}; -use build::util::up_to_date; +use build::{Build, Compiler, Mode}; +use build::util::{up_to_date, cp_r}; -pub fn rustbook(build: &Build, stage: u32, host: &str, name: &str, out: &Path) { +pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) { t!(fs::create_dir_all(out)); let out = out.join(name); - let compiler = Compiler::new(stage, host); + let compiler = Compiler::new(stage, &build.config.build); let src = build.src.join("src/doc").join(name); let index = out.join("index.html"); let rustbook = build.tool(&compiler, "rustbook"); if up_to_date(&src, &index) && up_to_date(&rustbook, &index) { return } - println!("Rustbook stage{} ({}) - {}", stage, host, name); + println!("Rustbook stage{} ({}) - {}", stage, target, name); let _ = fs::remove_dir_all(&out); build.run(build.tool_cmd(&compiler, "rustbook") .arg("build") @@ -34,11 +35,11 @@ pub fn rustbook(build: &Build, stage: u32, host: &str, name: &str, out: &Path) { .arg(out)); } -pub fn standalone(build: &Build, stage: u32, host: &str, out: &Path) { - println!("Documenting stage{} standalone ({})", stage, host); +pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { + println!("Documenting stage{} standalone ({})", stage, target); t!(fs::create_dir_all(out)); - let compiler = Compiler::new(stage, host); + let compiler = Compiler::new(stage, &build.config.build); let favicon = build.src.join("src/doc/favicon.inc"); let footer = build.src.join("src/doc/footer.inc"); @@ -69,7 +70,7 @@ pub fn standalone(build: &Build, stage: u32, host: &str, out: &Path) { } let html = out.join(filename).with_extension("html"); - let rustdoc = build.tool(&compiler, "rustdoc"); + let rustdoc = build.rustdoc(&compiler); if up_to_date(&path, &html) && up_to_date(&footer, &html) && up_to_date(&favicon, &html) && @@ -79,7 +80,8 @@ pub fn standalone(build: &Build, stage: u32, host: &str, out: &Path) { continue } - let mut cmd = build.tool_cmd(&compiler, "rustdoc"); + let mut cmd = Command::new(&rustdoc); + build.add_rustc_lib_path(&compiler, &mut cmd); cmd.arg("--html-after-content").arg(&footer) .arg("--html-before-content").arg(&version_info) .arg("--html-in-header").arg(&favicon) @@ -102,3 +104,68 @@ pub fn standalone(build: &Build, stage: u32, host: &str, out: &Path) { build.run(&mut cmd); } } + +pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { + println!("Documenting stage{} std ({})", stage, target); + t!(fs::create_dir_all(out)); + let compiler = Compiler::new(stage, &build.config.build); + let out_dir = build.stage_out(&compiler, Mode::Libstd) + .join(target).join("doc"); + let rustdoc = build.rustdoc(&compiler); + + build.clear_if_dirty(&out_dir, &rustdoc); + + let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/rustc/std_shim/Cargo.toml")) + .arg("--features").arg(build.std_features()); + build.run(&mut cargo); + cp_r(&out_dir, out) +} + +pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { + println!("Documenting stage{} test ({})", stage, target); + let compiler = Compiler::new(stage, &build.config.build); + let out_dir = build.stage_out(&compiler, Mode::Libtest) + .join(target).join("doc"); + let rustdoc = build.rustdoc(&compiler); + + build.clear_if_dirty(&out_dir, &rustdoc); + + let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); + build.run(&mut cargo); + cp_r(&out_dir, out) +} + +pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { + println!("Documenting stage{} compiler ({})", stage, target); + let compiler = Compiler::new(stage, &build.config.build); + let out_dir = build.stage_out(&compiler, Mode::Librustc) + .join(target).join("doc"); + let rustdoc = build.rustdoc(&compiler); + if !up_to_date(&rustdoc, &out_dir.join("rustc/index.html")) { + t!(fs::remove_dir_all(&out_dir)); + } + let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc"); + cargo.arg("--manifest-path") + .arg(build.src.join("src/rustc/Cargo.toml")) + .arg("--features").arg(build.rustc_features()); + build.run(&mut cargo); + cp_r(&out_dir, out) +} + +pub fn error_index(build: &Build, stage: u32, target: &str, out: &Path) { + println!("Documenting stage{} error index ({})", stage, target); + t!(fs::create_dir_all(out)); + let compiler = Compiler::new(stage, &build.config.build); + let mut index = build.tool_cmd(&compiler, "error_index_generator"); + index.arg("html"); + index.arg(out.join("error-index.html")); + + // FIXME: shouldn't have to pass this env var + index.env("CFG_BUILD", &build.config.build); + + build.run(&mut index); +} diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs index 98d821b8b9..248bf6cb4e 100644 --- a/src/bootstrap/build/mod.rs +++ b/src/bootstrap/build/mod.rs @@ -30,9 +30,11 @@ macro_rules! t { mod cc; mod channel; +mod check; mod clean; mod compile; mod config; +mod dist; mod doc; mod flags; mod native; @@ -75,6 +77,7 @@ pub struct Build { short_ver_hash: Option, ver_date: Option, version: String, + package_vers: String, bootstrap_key: String, // Runtime state filled in later on @@ -83,6 +86,13 @@ pub struct Build { compiler_rt_built: RefCell>, } +pub enum Mode { + Libstd, + Libtest, + Librustc, + Tool, +} + impl Build { pub fn new(flags: Flags, config: Config) -> Build { let cwd = t!(env::current_dir()); @@ -114,6 +124,7 @@ impl Build { ver_date: None, version: String::new(), bootstrap_key: String::new(), + package_vers: String::new(), cc: HashMap::new(), cxx: HashMap::new(), compiler_rt_built: RefCell::new(HashMap::new()), @@ -131,9 +142,13 @@ impl Build { return clean::clean(self); } + self.verbose("finding compilers"); cc::find(self); + self.verbose("running sanity check"); sanity::check(self); + self.verbose("collecting channel variables"); channel::collect(self); + self.verbose("updating submodules"); self.update_submodules(); for target in step::all(self) { @@ -145,19 +160,23 @@ impl Build { CompilerRt { _dummy } => { native::compiler_rt(self, target.target); } - Libstd { stage, compiler } => { - compile::std(self, stage, target.target, &compiler); + Libstd { compiler } => { + compile::std(self, target.target, &compiler); + } + Libtest { compiler } => { + compile::test(self, target.target, &compiler); + } + Librustc { compiler } => { + compile::rustc(self, target.target, &compiler); } - Librustc { stage, compiler } => { - compile::rustc(self, stage, target.target, &compiler); + LibstdLink { compiler, host } => { + compile::std_link(self, target.target, &compiler, host); } - LibstdLink { stage, compiler, host } => { - compile::std_link(self, stage, target.target, - &compiler, host); + LibtestLink { compiler, host } => { + compile::test_link(self, target.target, &compiler, host); } - LibrustcLink { stage, compiler, host } => { - compile::rustc_link(self, stage, target.target, - &compiler, host); + LibrustcLink { compiler, host } => { + compile::rustc_link(self, target.target, &compiler, host); } Rustc { stage: 0 } => { // nothing to do... @@ -165,6 +184,19 @@ impl Build { Rustc { stage } => { compile::assemble_rustc(self, stage, target.target); } + ToolLinkchecker { stage } => { + compile::tool(self, stage, target.target, "linkchecker"); + } + ToolRustbook { stage } => { + compile::tool(self, stage, target.target, "rustbook"); + } + ToolErrorIndex { stage } => { + compile::tool(self, stage, target.target, + "error_index_generator"); + } + ToolCargoTest { stage } => { + compile::tool(self, stage, target.target, "cargotest"); + } DocBook { stage } => { doc::rustbook(self, stage, target.target, "book", &doc_out); } @@ -179,7 +211,34 @@ impl Build { DocStandalone { stage } => { doc::standalone(self, stage, target.target, &doc_out); } - Doc { .. } => {} // pseudo-step + DocStd { stage } => { + doc::std(self, stage, target.target, &doc_out); + } + DocTest { stage } => { + doc::test(self, stage, target.target, &doc_out); + } + DocRustc { stage } => { + doc::rustc(self, stage, target.target, &doc_out); + } + DocErrorIndex { stage } => { + doc::error_index(self, stage, target.target, &doc_out); + } + + CheckLinkcheck { stage } => { + check::linkcheck(self, stage, target.target); + } + CheckCargoTest { stage } => { + check::cargotest(self, stage, target.target); + } + + DistDocs { stage } => dist::docs(self, stage, target.target), + DistMingw { _dummy } => dist::mingw(self, target.target), + DistRustc { stage } => dist::rustc(self, stage, target.target), + DistStd { compiler } => dist::std(self, &compiler, target.target), + + Dist { .. } | + Doc { .. } | // pseudo-steps + Check { .. } => {} } } } @@ -229,43 +288,51 @@ impl Build { /// This will create a `Command` that represents a pending execution of /// Cargo for the specified stage, whether or not the standard library is /// being built, and using the specified compiler targeting `target`. - // FIXME: aren't stage/compiler duplicated? - fn cargo(&self, stage: u32, compiler: &Compiler, is_std: bool, - target: &str, cmd: &str) -> Command { + fn cargo(&self, + compiler: &Compiler, + mode: Mode, + target: &str, + cmd: &str) -> Command { let mut cargo = Command::new(&self.cargo); - let host = compiler.host; - let out_dir = self.stage_out(stage, host, is_std); + let out_dir = self.stage_out(compiler, mode); cargo.env("CARGO_TARGET_DIR", out_dir) .arg(cmd) - .arg("--target").arg(target) - .arg("-j").arg(self.jobs().to_string()); + .arg("-j").arg(self.jobs().to_string()) + .arg("--target").arg(target); // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure // how the actual compiler itself is called. cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.compiler_path(compiler)) - .env("RUSTC_STAGE", self.stage_arg(stage, compiler).to_string()) + .env("RUSTC_STAGE", compiler.stage.to_string()) .env("RUSTC_DEBUGINFO", self.config.rust_debuginfo.to_string()) .env("RUSTC_CODEGEN_UNITS", self.config.rust_codegen_units.to_string()) .env("RUSTC_DEBUG_ASSERTIONS", self.config.rust_debug_assertions.to_string()) .env("RUSTC_SNAPSHOT", &self.rustc) - .env("RUSTC_SYSROOT", self.sysroot(stage, host)) + .env("RUSTC_SYSROOT", self.sysroot(compiler)) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()) - .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")) .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) - .env("RUSTDOC", self.tool(compiler, "rustdoc")); + .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) + .env("RUSTDOC_REAL", self.rustdoc(compiler)) + .env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); - // Specify some variuos options for build scripts used throughout the - // build. + // Specify some various options for build scripts used throughout + // the build. // // FIXME: the guard against msvc shouldn't need to be here if !target.contains("msvc") { cargo.env(format!("CC_{}", target), self.cc(target)) .env(format!("AR_{}", target), self.ar(target)) - .env(format!("CFLAGS_{}", target), self.cflags(target)); + .env(format!("CFLAGS_{}", target), self.cflags(target).join(" ")); + } + + // If we're building for OSX, inform the compiler and the linker that + // we want to build a compiler runnable on 10.7 + if target.contains("apple-darwin") { + cargo.env("MACOSX_DEPLOYMENT_TARGET", "10.7"); } // Environment variables *required* needed throughout the build @@ -288,43 +355,38 @@ impl Build { if compiler.is_snapshot(self) { self.rustc.clone() } else { - self.sysroot(compiler.stage, compiler.host).join("bin") - .join(exe("rustc", compiler.host)) + self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) } } - /// Get the specified tool next to the specified compiler + /// Get the specified tool built by the specified compiler fn tool(&self, compiler: &Compiler, tool: &str) -> PathBuf { - if compiler.is_snapshot(self) { - assert!(tool == "rustdoc", "no tools other than rustdoc in stage0"); - let mut rustdoc = self.rustc.clone(); - rustdoc.pop(); - rustdoc.push(exe("rustdoc", &self.config.build)); - return rustdoc - } - let (stage, host) = (compiler.stage, compiler.host); - self.cargo_out(stage - 1, host, false, host).join(exe(tool, host)) + self.cargo_out(compiler, Mode::Tool, compiler.host) + .join(exe(tool, compiler.host)) + } + + /// Get the `rustdoc` executable next to the specified compiler + fn rustdoc(&self, compiler: &Compiler) -> PathBuf { + let mut rustdoc = self.compiler_path(compiler); + rustdoc.pop(); + rustdoc.push(exe("rustdoc", compiler.host)); + return rustdoc } /// Get a `Command` which is ready to run `tool` in `stage` built for /// `host`. - #[allow(dead_code)] // this will be used soon fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command { let mut cmd = Command::new(self.tool(&compiler, tool)); let host = compiler.host; - let stage = compiler.stage; let paths = vec![ - self.cargo_out(stage - 1, host, true, host).join("deps"), - self.cargo_out(stage - 1, host, false, host).join("deps"), + self.cargo_out(compiler, Mode::Libstd, host).join("deps"), + self.cargo_out(compiler, Mode::Libtest, host).join("deps"), + self.cargo_out(compiler, Mode::Librustc, host).join("deps"), ]; add_lib_path(paths, &mut cmd); return cmd } - fn stage_arg(&self, stage: u32, compiler: &Compiler) -> u32 { - if stage == 0 && compiler.host != self.config.build {1} else {stage} - } - /// Get the space-separated set of activated features for the standard /// library. fn std_features(&self) -> String { @@ -339,15 +401,11 @@ impl Build { } /// Get the space-separated set of activated features for the compiler. - fn rustc_features(&self, stage: u32) -> String { + fn rustc_features(&self) -> String { let mut features = String::new(); if self.config.use_jemalloc { features.push_str(" jemalloc"); } - if stage > 0 { - features.push_str(" rustdoc"); - features.push_str(" rustbook"); - } return features } @@ -357,35 +415,41 @@ impl Build { if self.config.rust_optimize {"release"} else {"debug"} } - fn sysroot(&self, stage: u32, host: &str) -> PathBuf { - if stage == 0 { - self.stage_out(stage, host, false) + fn sysroot(&self, compiler: &Compiler) -> PathBuf { + if compiler.stage == 0 { + self.out.join(compiler.host).join("stage0-sysroot") } else { - self.out.join(host).join(format!("stage{}", stage)) + self.out.join(compiler.host).join(format!("stage{}", compiler.stage)) } } - fn sysroot_libdir(&self, stage: u32, host: &str, target: &str) -> PathBuf { - self.sysroot(stage, host).join("lib").join("rustlib") + fn sysroot_libdir(&self, compiler: &Compiler, target: &str) -> PathBuf { + self.sysroot(compiler).join("lib").join("rustlib") .join(target).join("lib") } /// Returns the root directory for all output generated in a particular /// stage when running with a particular host compiler. /// - /// The `is_std` flag indicates whether the root directory is for the - /// bootstrap of the standard library or for the compiler. - fn stage_out(&self, stage: u32, host: &str, is_std: bool) -> PathBuf { - self.out.join(host) - .join(format!("stage{}{}", stage, if is_std {"-std"} else {"-rustc"})) + /// The mode indicates what the root directory is for. + fn stage_out(&self, compiler: &Compiler, mode: Mode) -> PathBuf { + let suffix = match mode { + Mode::Libstd => "-std", + Mode::Libtest => "-test", + Mode::Tool | Mode::Librustc => "-rustc", + }; + self.out.join(compiler.host) + .join(format!("stage{}{}", compiler.stage, suffix)) } /// Returns the root output directory for all Cargo output in a given stage, /// running a particular comipler, wehther or not we're building the /// standard library, and targeting the specified architecture. - fn cargo_out(&self, stage: u32, host: &str, is_std: bool, + fn cargo_out(&self, + compiler: &Compiler, + mode: Mode, target: &str) -> PathBuf { - self.stage_out(stage, host, is_std).join(target).join(self.cargo_dir()) + self.stage_out(compiler, mode).join(target).join(self.cargo_dir()) } /// Root output directory for LLVM compiled for `target` @@ -411,8 +475,7 @@ impl Build { if compiler.is_snapshot(self) { self.rustc_snapshot_libdir() } else { - self.sysroot(compiler.stage, compiler.host) - .join(libdir(compiler.host)) + self.sysroot(compiler).join(libdir(compiler.host)) } } @@ -440,11 +503,20 @@ impl Build { self.cc[target].0.path() } - fn cflags(&self, target: &str) -> String { - self.cc[target].0.args().iter() - .map(|s| s.to_string_lossy()) - .collect::>() - .join(" ") + fn cflags(&self, target: &str) -> Vec { + let mut base = self.cc[target].0.args().iter() + .map(|s| s.to_string_lossy().into_owned()) + .collect::>(); + + // If we're compiling on OSX then we add a few unconditional flags + // indicating that we want libc++ (more filled out than libstdc++) and + // we want to compile for 10.7. This way we can ensure that + // LLVM/jemalloc/etc are all properly compiled. + if target.contains("apple-darwin") { + base.push("-stdlib=libc++".into()); + base.push("-mmacosx-version-min=10.7".into()); + } + return base } fn ar(&self, target: &str) -> &Path { diff --git a/src/bootstrap/build/native.rs b/src/bootstrap/build/native.rs index a9d84b60fb..bf0494bcd8 100644 --- a/src/bootstrap/build/native.rs +++ b/src/bootstrap/build/native.rs @@ -86,6 +86,9 @@ pub fn llvm(build: &Build, target: &str) { .define("CMAKE_CXX_COMPILER", build.cxx(target)); } cfg.build_arg("-j").build_arg(build.jobs().to_string()); + + cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); + cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" ")); } // FIXME: we don't actually need to build all LLVM tools and all LLVM @@ -113,7 +116,9 @@ pub fn compiler_rt(build: &Build, target: &str) { let dst = build.compiler_rt_out(target); let arch = target.split('-').next().unwrap(); let mode = if build.config.rust_optimize {"Release"} else {"Debug"}; - let (dir, build_target, libname) = if target.contains("linux") { + let (dir, build_target, libname) = if target.contains("linux") || + target.contains("freebsd") || + target.contains("netbsd") { let os = if target.contains("android") {"-android"} else {""}; let arch = if arch.starts_with("arm") && target.contains("eabihf") { "armhf" diff --git a/src/bootstrap/build/sanity.rs b/src/bootstrap/build/sanity.rs index 40f4c70760..6ce2749638 100644 --- a/src/bootstrap/build/sanity.rs +++ b/src/bootstrap/build/sanity.rs @@ -79,7 +79,7 @@ pub fn check(build: &mut Build) { } // Make sure musl-root is valid if specified - if target.contains("musl") { + if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) { match build.config.musl_root { Some(ref root) => { if fs::metadata(root.join("lib/libc.a")).is_err() { @@ -119,4 +119,16 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake } } } + + for host in build.flags.host.iter() { + if !build.config.host.contains(host) { + panic!("specified host `{}` is not in the ./configure list", host); + } + } + for target in build.flags.target.iter() { + if !build.config.target.contains(target) { + panic!("specified target `{}` is not in the ./configure list", + target); + } + } } diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs index ba0095ce84..80fcc32e53 100644 --- a/src/bootstrap/build/step.rs +++ b/src/bootstrap/build/step.rs @@ -25,26 +25,33 @@ macro_rules! targets { // compiler executable itself, not any of the support libraries (rustc, Rustc { stage: u32 }), - // Steps for the two main cargo builds, one for the standard library - // and one for the compiler itself. These are parameterized over the - // stage output they're going to be placed in along with the - // compiler which is producing the copy of libstd or librustc - (libstd, Libstd { stage: u32, compiler: Compiler<'a> }), - (librustc, Librustc { stage: u32, compiler: Compiler<'a> }), - - // Links the standard library/librustc produced by the compiler - // provided into the host's directory also provided. + // Steps for the two main cargo builds. These are parameterized over + // the compiler which is producing the artifact. + (libstd, Libstd { compiler: Compiler<'a> }), + (libtest, Libtest { compiler: Compiler<'a> }), + (librustc, Librustc { compiler: Compiler<'a> }), + + // Links the target produced by the compiler provided into the + // host's directory also provided. (libstd_link, LibstdLink { - stage: u32, + compiler: Compiler<'a>, + host: &'a str + }), + (libtest_link, LibtestLink { compiler: Compiler<'a>, host: &'a str }), (librustc_link, LibrustcLink { - stage: u32, compiler: Compiler<'a>, host: &'a str }), + // Various tools that we can build as part of the build. + (tool_linkchecker, ToolLinkchecker { stage: u32 }), + (tool_rustbook, ToolRustbook { stage: u32 }), + (tool_error_index, ToolErrorIndex { stage: u32 }), + (tool_cargotest, ToolCargoTest { stage: u32 }), + // Steps for long-running native builds. Ideally these wouldn't // actually exist and would be part of build scripts, but for now // these are here. @@ -53,11 +60,32 @@ macro_rules! targets { // with braces are unstable so we just pick something that works. (llvm, Llvm { _dummy: () }), (compiler_rt, CompilerRt { _dummy: () }), + + // Steps for various pieces of documentation that we can generate, + // the 'doc' step is just a pseudo target to depend on a bunch of + // others. (doc, Doc { stage: u32 }), (doc_book, DocBook { stage: u32 }), (doc_nomicon, DocNomicon { stage: u32 }), (doc_style, DocStyle { stage: u32 }), (doc_standalone, DocStandalone { stage: u32 }), + (doc_std, DocStd { stage: u32 }), + (doc_test, DocTest { stage: u32 }), + (doc_rustc, DocRustc { stage: u32 }), + (doc_error_index, DocErrorIndex { stage: u32 }), + + // Steps for running tests. The 'check' target is just a pseudo + // target to depend on a bunch of others. + (check, Check { stage: u32, compiler: Compiler<'a> }), + (check_linkcheck, CheckLinkcheck { stage: u32 }), + (check_cargotest, CheckCargoTest { stage: u32 }), + + // Distribution targets, creating tarballs + (dist, Dist { stage: u32 }), + (dist_docs, DistDocs { stage: u32 }), + (dist_mingw, DistMingw { _dummy: () }), + (dist_rustc, DistRustc { stage: u32 }), + (dist_std, DistStd { compiler: Compiler<'a> }), } } } @@ -127,10 +155,9 @@ fn top_level(build: &Build) -> Vec { } let host = t.target(host); if host.target == build.config.build { - targets.push(host.librustc(stage, host.compiler(stage))); + targets.push(host.librustc(host.compiler(stage))); } else { - targets.push(host.librustc_link(stage, t.compiler(stage), - host.target)); + targets.push(host.librustc_link(t.compiler(stage), host.target)); } for target in build.config.target.iter() { if !build.flags.target.contains(target) { @@ -139,11 +166,10 @@ fn top_level(build: &Build) -> Vec { if host.target == build.config.build { targets.push(host.target(target) - .libstd(stage, host.compiler(stage))); + .libtest(host.compiler(stage))); } else { targets.push(host.target(target) - .libstd_link(stage, t.compiler(stage), - host.target)); + .libtest_link(t.compiler(stage), host.target)); } } } @@ -158,25 +184,37 @@ fn add_steps<'a>(build: &'a Build, host: &Step<'a>, target: &Step<'a>, targets: &mut Vec>) { + struct Context<'a> { + stage: u32, + compiler: Compiler<'a>, + _dummy: (), + host: &'a str, + } for step in build.flags.step.iter() { - let compiler = host.target(&build.config.build).compiler(stage); - match &step[..] { - "libstd" => targets.push(target.libstd(stage, compiler)), - "librustc" => targets.push(target.librustc(stage, compiler)), - "libstd-link" => targets.push(target.libstd_link(stage, compiler, - host.target)), - "librustc-link" => targets.push(target.librustc_link(stage, compiler, - host.target)), - "rustc" => targets.push(host.rustc(stage)), - "llvm" => targets.push(target.llvm(())), - "compiler-rt" => targets.push(target.compiler_rt(())), - "doc-style" => targets.push(host.doc_style(stage)), - "doc-standalone" => targets.push(host.doc_standalone(stage)), - "doc-nomicon" => targets.push(host.doc_nomicon(stage)), - "doc-book" => targets.push(host.doc_book(stage)), - "doc" => targets.push(host.doc(stage)), - _ => panic!("unknown build target: `{}`", step), + + // The macro below insists on hygienic access to all local variables, so + // we shove them all in a struct and subvert hygiene by accessing struct + // fields instead, + let cx = Context { + stage: stage, + compiler: host.target(&build.config.build).compiler(stage), + _dummy: (), + host: host.target, + }; + macro_rules! add_step { + ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => ({$( + let name = stringify!($short).replace("_", "-"); + if &step[..] == &name[..] { + targets.push(target.$short($(cx.$arg),*)); + continue + } + drop(name); + )*}) } + + targets!(add_step); + + panic!("unknown step: {}", step); } } @@ -209,36 +247,114 @@ impl<'a> Step<'a> { } Source::Rustc { stage } => { let compiler = Compiler::new(stage - 1, &build.config.build); - vec![self.librustc(stage - 1, compiler)] + vec![self.librustc(compiler)] } - Source::Librustc { stage, compiler } => { - vec![self.libstd(stage, compiler), self.llvm(())] + Source::Librustc { compiler } => { + vec![self.libtest(compiler), self.llvm(())] } - Source::Libstd { stage: _, compiler } => { + Source::Libtest { compiler } => { + vec![self.libstd(compiler)] + } + Source::Libstd { compiler } => { vec![self.compiler_rt(()), self.rustc(compiler.stage).target(compiler.host)] } - Source::LibrustcLink { stage, compiler, host } => { - vec![self.librustc(stage, compiler), - self.libstd_link(stage, compiler, host)] + Source::LibrustcLink { compiler, host } => { + vec![self.librustc(compiler), + self.libtest_link(compiler, host)] + } + Source::LibtestLink { compiler, host } => { + vec![self.libtest(compiler), self.libstd_link(compiler, host)] } - Source::LibstdLink { stage, compiler, host } => { - vec![self.libstd(stage, compiler), - self.target(host).rustc(stage)] + Source::LibstdLink { compiler, host } => { + vec![self.libstd(compiler), + self.target(host).rustc(compiler.stage)] } Source::CompilerRt { _dummy } => { vec![self.llvm(()).target(&build.config.build)] } Source::Llvm { _dummy } => Vec::new(), + + // Note that all doc targets depend on artifacts from the build + // architecture, not the target (which is where we're generating + // docs into). + Source::DocStd { stage } => { + let compiler = self.target(&build.config.build).compiler(stage); + vec![self.libstd(compiler)] + } + Source::DocTest { stage } => { + let compiler = self.target(&build.config.build).compiler(stage); + vec![self.libtest(compiler)] + } Source::DocBook { stage } | Source::DocNomicon { stage } | - Source::DocStyle { stage } | + Source::DocStyle { stage } => { + vec![self.target(&build.config.build).tool_rustbook(stage)] + } + Source::DocErrorIndex { stage } => { + vec![self.target(&build.config.build).tool_error_index(stage)] + } Source::DocStandalone { stage } => { - vec![self.rustc(stage)] + vec![self.target(&build.config.build).rustc(stage)] + } + Source::DocRustc { stage } => { + vec![self.doc_test(stage)] } Source::Doc { stage } => { vec![self.doc_book(stage), self.doc_nomicon(stage), - self.doc_style(stage), self.doc_standalone(stage)] + self.doc_style(stage), self.doc_standalone(stage), + self.doc_std(stage), + self.doc_error_index(stage)] + } + Source::Check { stage, compiler: _ } => { + vec![self.check_linkcheck(stage), + self.dist(stage)] + } + Source::CheckLinkcheck { stage } => { + vec![self.tool_linkchecker(stage), self.doc(stage)] + } + Source::CheckCargoTest { stage } => { + vec![self.tool_cargotest(stage)] + } + + Source::ToolLinkchecker { stage } => { + vec![self.libstd(self.compiler(stage))] + } + Source::ToolErrorIndex { stage } | + Source::ToolRustbook { stage } => { + vec![self.librustc(self.compiler(stage))] + } + Source::ToolCargoTest { stage } => { + vec![self.librustc(self.compiler(stage))] + } + + Source::DistDocs { stage } => vec![self.doc(stage)], + Source::DistMingw { _dummy: _ } => Vec::new(), + Source::DistRustc { stage } => { + vec![self.rustc(stage)] + } + Source::DistStd { compiler } => { + vec![self.libtest(compiler)] + } + + Source::Dist { stage } => { + let mut base = Vec::new(); + + for host in build.config.host.iter() { + let host = self.target(host); + base.push(host.dist_rustc(stage)); + if host.target.contains("windows-gnu") { + base.push(host.dist_mingw(())); + } + + let compiler = self.compiler(stage); + for target in build.config.target.iter() { + let target = self.target(target); + base.push(target.dist_docs(stage)); + base.push(target.dist_std(compiler)); + } + } + return base } } } diff --git a/src/bootstrap/build/util.rs b/src/bootstrap/build/util.rs index 6c700671f1..41cf924d44 100644 --- a/src/bootstrap/build/util.rs +++ b/src/bootstrap/build/util.rs @@ -30,7 +30,15 @@ pub fn mtime(path: &Path) -> FileTime { }).unwrap_or(FileTime::zero()) } -#[allow(dead_code)] // this will be used soon +pub fn copy(src: &Path, dst: &Path) { + let res = fs::hard_link(src, dst); + let res = res.or_else(|_| fs::copy(src, dst).map(|_| ())); + if let Err(e) = res { + panic!("failed to copy `{}` to `{}`: {}", src.display(), + dst.display(), e) + } +} + pub fn cp_r(src: &Path, dst: &Path) { for f in t!(fs::read_dir(src)) { let f = t!(f); @@ -43,7 +51,7 @@ pub fn cp_r(src: &Path, dst: &Path) { cp_r(&path, &dst); } else { let _ = fs::remove_file(&dst); - t!(fs::hard_link(&path, dst)); + copy(&path, &dst); } } } diff --git a/src/bootstrap/main.rs b/src/bootstrap/main.rs index 32432132c1..bf29ac107f 100644 --- a/src/bootstrap/main.rs +++ b/src/bootstrap/main.rs @@ -20,6 +20,7 @@ extern crate libc; extern crate num_cpus; extern crate rustc_serialize; extern crate toml; +extern crate md5; use std::env; diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index fa3dee2f35..9199c755f6 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -36,3 +36,11 @@ book: $(Q)$(BOOTSTRAP) --step doc-book standalone-docs: $(Q)$(BOOTSTRAP) --step doc-standalone +check: + $(Q)$(BOOTSTRAP) --step check +check-cargotest: + $(Q)$(BOOTSTRAP) --step check-cargotest +dist: + $(Q)$(BOOTSTRAP) --step dist + +.PHONY: dist diff --git a/src/bootstrap/rustc.rs b/src/bootstrap/rustc.rs index 4e9d6da915..d403d76bb1 100644 --- a/src/bootstrap/rustc.rs +++ b/src/bootstrap/rustc.rs @@ -8,6 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Shim which is passed to Cargo as "rustc" when running the bootstrap. +//! +//! This shim will take care of some various tasks that our build process +//! requires that Cargo can't quite do through normal configuration: +//! +//! 1. When compiling build scripts and build dependencies, we need a guaranteed +//! full standard library available. The only compiler which actually has +//! this is the snapshot, so we detect this situation and always compile with +//! the snapshot compiler. +//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling +//! (and this slightly differs based on a whether we're using a snapshot or +//! not), so we do that all here. +//! +//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of +//! switching compilers for the bootstrap and for build scripts will probably +//! never get replaced. + extern crate bootstrap; use std::env; diff --git a/src/bootstrap/rustdoc.rs b/src/bootstrap/rustdoc.rs new file mode 100644 index 0000000000..8c61819611 --- /dev/null +++ b/src/bootstrap/rustdoc.rs @@ -0,0 +1,31 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Shim which is passed to Cargo as "rustdoc" when running the bootstrap. +//! +//! See comments in `src/bootstrap/rustc.rs` for more information. + +use std::env; +use std::process::Command; + +fn main() { + let args = env::args_os().skip(1).collect::>(); + let rustdoc = env::var_os("RUSTDOC_REAL").unwrap(); + + let mut cmd = Command::new(rustdoc); + cmd.args(&args) + .arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap())) + .arg("--cfg").arg("dox"); + std::process::exit(match cmd.status() { + Ok(s) => s.code().unwrap_or(1), + Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), + }) +} + diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 092a1cabc7..8e1da69cf0 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -43,10 +43,16 @@ pub fn cc2ar(cc: &Path, target: &str) -> PathBuf { if target.contains("musl") || target.contains("msvc") { PathBuf::from("ar") } else { + let parent = cc.parent().unwrap(); let file = cc.file_name().unwrap().to_str().unwrap(); - cc.parent().unwrap().join(file.replace("gcc", "ar") - .replace("cc", "ar") - .replace("clang", "ar")) + for suffix in &["gcc", "cc", "clang"] { + if let Some(idx) = file.rfind(suffix) { + let mut file = file[..idx].to_owned(); + file.push_str("ar"); + return parent.join(&file); + } + } + parent.join(file) } } diff --git a/src/compiler-rt/cmake/config-ix.cmake b/src/compiler-rt/cmake/config-ix.cmake index f137d51c7f..9ede367080 100644 --- a/src/compiler-rt/cmake/config-ix.cmake +++ b/src/compiler-rt/cmake/config-ix.cmake @@ -207,8 +207,11 @@ elseif(NOT APPLE) # Supported archs for Apple platforms are generated later test_target_arch(mips "" "-mips32r2" "--target=mips-linux-gnu") test_target_arch(mips64 "" "-mips64r2" "--target=mips64-linux-gnu" "-mabi=n64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm") - test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft") - test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard") + if("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES "eabihf") + test_target_arch(armhf "" "-march=armv7-a" "-mfloat-abi=hard") + else() + test_target_arch(arm "" "-march=armv7-a" "-mfloat-abi=soft") + endif() elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch32") test_target_arch(aarch32 "" "-march=armv8-a") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "aarch64") diff --git a/src/compiler-rt/lib/builtins/CMakeLists.txt b/src/compiler-rt/lib/builtins/CMakeLists.txt index 97249ea730..9f9f4304d7 100644 --- a/src/compiler-rt/lib/builtins/CMakeLists.txt +++ b/src/compiler-rt/lib/builtins/CMakeLists.txt @@ -220,8 +220,6 @@ else () # MSVC endif () # if (NOT MSVC) set(arm_SOURCES - arm/adddf3vfp.S - arm/addsf3vfp.S arm/aeabi_cdcmp.S arm/aeabi_cdcmpeq_check_nan.c arm/aeabi_cfcmp.S @@ -242,40 +240,11 @@ set(arm_SOURCES arm/bswapdi2.S arm/bswapsi2.S arm/comparesf2.S - arm/divdf3vfp.S arm/divmodsi4.S - arm/divsf3vfp.S arm/divsi3.S - arm/eqdf2vfp.S - arm/eqsf2vfp.S - arm/extendsfdf2vfp.S - arm/fixdfsivfp.S - arm/fixsfsivfp.S - arm/fixunsdfsivfp.S - arm/fixunssfsivfp.S - arm/floatsidfvfp.S - arm/floatsisfvfp.S - arm/floatunssidfvfp.S - arm/floatunssisfvfp.S - arm/gedf2vfp.S - arm/gesf2vfp.S - arm/gtdf2vfp.S - arm/gtsf2vfp.S - arm/ledf2vfp.S - arm/lesf2vfp.S - arm/ltdf2vfp.S - arm/ltsf2vfp.S arm/modsi3.S - arm/muldf3vfp.S - arm/mulsf3vfp.S - arm/nedf2vfp.S arm/negdf2vfp.S arm/negsf2vfp.S - arm/nesf2vfp.S - arm/restore_vfp_d8_d15_regs.S - arm/save_vfp_d8_d15_regs.S - arm/subdf3vfp.S - arm/subsf3vfp.S arm/switch16.S arm/switch32.S arm/switch8.S @@ -301,12 +270,9 @@ set(arm_SOURCES arm/sync_fetch_and_xor_4.S arm/sync_fetch_and_xor_8.S arm/sync_synchronize.S - arm/truncdfsf2vfp.S arm/udivmodsi4.S arm/udivsi3.S arm/umodsi3.S - arm/unorddf2vfp.S - arm/unordsf2vfp.S ${GENERIC_SOURCES}) set(aarch64_SOURCES @@ -328,7 +294,42 @@ set(aarch64_SOURCES trunctfsf2.c ${GENERIC_SOURCES}) -set(armhf_SOURCES ${arm_SOURCES}) +set(armhf_SOURCES + arm/adddf3vfp.S + arm/addsf3vfp.S + arm/divdf3vfp.S + arm/divsf3vfp.S + arm/eqdf2vfp.S + arm/eqsf2vfp.S + arm/extendsfdf2vfp.S + arm/fixdfsivfp.S + arm/fixsfsivfp.S + arm/fixunsdfsivfp.S + arm/fixunssfsivfp.S + arm/floatsidfvfp.S + arm/floatsisfvfp.S + arm/floatunssidfvfp.S + arm/floatunssisfvfp.S + arm/gedf2vfp.S + arm/gesf2vfp.S + arm/gtdf2vfp.S + arm/gtsf2vfp.S + arm/ledf2vfp.S + arm/lesf2vfp.S + arm/ltdf2vfp.S + arm/ltsf2vfp.S + arm/muldf3vfp.S + arm/mulsf3vfp.S + arm/nedf2vfp.S + arm/nesf2vfp.S + arm/restore_vfp_d8_d15_regs.S + arm/save_vfp_d8_d15_regs.S + arm/subdf3vfp.S + arm/subsf3vfp.S + arm/truncdfsf2vfp.S + arm/unorddf2vfp.S + arm/unordsf2vfp.S + ${arm_SOURCES}) set(armv7_SOURCES ${arm_SOURCES}) set(armv7s_SOURCES ${arm_SOURCES}) set(arm64_SOURCES ${aarch64_SOURCES}) diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index e66094dc39..a6960ff178 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -25,7 +25,8 @@ pub enum Mode { DebugInfoLldb, Codegen, Rustdoc, - CodegenUnits + CodegenUnits, + Incremental, } impl FromStr for Mode { @@ -43,6 +44,7 @@ impl FromStr for Mode { "codegen" => Ok(Codegen), "rustdoc" => Ok(Rustdoc), "codegen-units" => Ok(CodegenUnits), + "incremental" => Ok(Incremental), _ => Err(()), } } @@ -62,6 +64,7 @@ impl fmt::Display for Mode { Codegen => "codegen", Rustdoc => "rustdoc", CodegenUnits => "codegen-units", + Incremental => "incremental", }, f) } } @@ -69,10 +72,10 @@ impl fmt::Display for Mode { #[derive(Clone)] pub struct Config { // The library paths required for running the compiler - pub compile_lib_path: String, + pub compile_lib_path: PathBuf, // The library paths required for running compiled programs - pub run_lib_path: String, + pub run_lib_path: PathBuf, // The rustc executable pub rustc_path: PathBuf, @@ -155,5 +158,8 @@ pub struct Config { pub lldb_python_dir: Option, // Explain what's going on - pub verbose: bool + pub verbose: bool, + + // Print one character per test instead of one line + pub quiet: bool, } diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index bbace16f05..8d2558e434 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -11,11 +11,10 @@ #![crate_type = "bin"] #![feature(box_syntax)] -#![feature(dynamic_lib)] #![feature(libc)] #![feature(rustc_private)] -#![feature(str_char)] #![feature(test)] +#![feature(question_mark)] #![deny(warnings)] @@ -71,13 +70,15 @@ pub fn parse_config(args: Vec ) -> Config { reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"), reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"), reqopt("", "mode", "which sort of compile tests to run", - "(compile-fail|parse-fail|run-fail|run-pass|run-pass-valgrind|pretty|debug-info)"), + "(compile-fail|parse-fail|run-fail|run-pass|\ + run-pass-valgrind|pretty|debug-info|incremental)"), optflag("", "ignored", "run tests marked as ignored"), optopt("", "runtool", "supervisor program to run tests under \ (eg. emulator, valgrind)", "PROGRAM"), optopt("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS"), optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS"), optflag("", "verbose", "run tests verbosely, showing all output"), + optflag("", "quiet", "print one character per test instead of one line"), optopt("", "logfile", "file to log test execution to", "FILE"), optopt("", "target", "the target to build for", "TARGET"), optopt("", "host", "the host to build for", "HOST"), @@ -117,15 +118,17 @@ pub fn parse_config(args: Vec ) -> Config { } } - let filter = if !matches.free.is_empty() { - Some(matches.free[0].clone()) - } else { - None - }; + fn make_absolute(path: PathBuf) -> PathBuf { + if path.is_relative() { + env::current_dir().unwrap().join(path) + } else { + path + } + } Config { - compile_lib_path: matches.opt_str("compile-lib-path").unwrap(), - run_lib_path: matches.opt_str("run-lib-path").unwrap(), + compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), + run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), rustc_path: opt_path(matches, "rustc-path"), rustdoc_path: opt_path(matches, "rustdoc-path"), python: matches.opt_str("python").unwrap(), @@ -138,7 +141,7 @@ pub fn parse_config(args: Vec ) -> Config { stage_id: matches.opt_str("stage-id").unwrap(), mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"), run_ignored: matches.opt_present("ignored"), - filter: filter, + filter: matches.free.first().cloned(), logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)), runtool: matches.opt_str("runtool"), host_rustcflags: matches.opt_str("host-rustcflags"), @@ -158,6 +161,7 @@ pub fn parse_config(args: Vec ) -> Config { !opt_str2(matches.opt_str("adb-test-dir")).is_empty(), lldb_python_dir: matches.opt_str("lldb-python-dir"), verbose: matches.opt_present("verbose"), + quiet: matches.opt_present("quiet"), } } @@ -191,6 +195,7 @@ pub fn log_config(config: &Config) { logv(c, format!("adb_device_status: {}", config.adb_device_status)); logv(c, format!("verbose: {}", config.verbose)); + logv(c, format!("quiet: {}", config.quiet)); logv(c, format!("\n")); } @@ -252,15 +257,16 @@ pub fn run_tests(config: &Config) { pub fn test_opts(config: &Config) -> test::TestOpts { test::TestOpts { - filter: match config.filter { - None => None, - Some(ref filter) => Some(filter.clone()), - }, + filter: config.filter.clone(), run_ignored: config.run_ignored, + quiet: config.quiet, logfile: config.logfile.clone(), run_tests: true, bench_benchmarks: true, - nocapture: env::var("RUST_TEST_NOCAPTURE").is_ok(), + nocapture: match env::var("RUST_TEST_NOCAPTURE") { + Ok(val) => &val != "0", + Err(_) => false + }, color: test::AutoColor, } } @@ -286,16 +292,16 @@ fn collect_tests_from_dir(config: &Config, -> io::Result<()> { // Ignore directories that contain a file // `compiletest-ignore-dir`. - for file in try!(fs::read_dir(dir)) { - let file = try!(file); + for file in fs::read_dir(dir)? { + let file = file?; if file.file_name() == *"compiletest-ignore-dir" { return Ok(()); } } - let dirs = try!(fs::read_dir(dir)); + let dirs = fs::read_dir(dir)?; for file in dirs { - let file = try!(file); + let file = file?; let file_path = file.path(); debug!("inspecting file {:?}", file_path.display()); if is_test(config, &file_path) { @@ -316,11 +322,11 @@ fn collect_tests_from_dir(config: &Config, tests.push(make_test(config, &paths)) } else if file_path.is_dir() { let relative_file_path = relative_dir_path.join(file.file_name()); - try!(collect_tests_from_dir(config, - base, - &file_path, - &relative_file_path, - tests)); + collect_tests_from_dir(config, + base, + &file_path, + &relative_file_path, + tests)?; } } Ok(()) @@ -354,11 +360,25 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool { } pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn { + let early_props = header::early_props(config, &testpaths.file); + + // The `should-fail` annotation doesn't apply to pretty tests, + // since we run the pretty printer across all tests by default. + // If desired, we could add a `should-fail-pretty` annotation. + let should_panic = match config.mode { + Pretty => test::ShouldPanic::No, + _ => if early_props.should_fail { + test::ShouldPanic::Yes + } else { + test::ShouldPanic::No + } + }; + test::TestDescAndFn { desc: test::TestDesc { name: make_test_name(config, testpaths), - ignore: header::is_test_ignored(config, &testpaths.file), - should_panic: test::ShouldPanic::No, + ignore: early_props.ignore, + should_panic: should_panic, }, testfn: make_test_closure(config, testpaths), } @@ -391,16 +411,26 @@ fn extract_gdb_version(full_version_line: Option) -> Option { // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)" for (pos, c) in full_version_line.char_indices() { - if !c.is_digit(10) { continue } - if pos + 2 >= full_version_line.len() { continue } - if full_version_line.char_at(pos + 1) != '.' { continue } - if !full_version_line.char_at(pos + 2).is_digit(10) { continue } - if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) { + if !c.is_digit(10) { + continue + } + if pos + 2 >= full_version_line.len() { + continue + } + if full_version_line[pos + 1..].chars().next().unwrap() != '.' { + continue + } + if !full_version_line[pos + 2..].chars().next().unwrap().is_digit(10) { + continue + } + if pos > 0 && full_version_line[..pos].chars().next_back() + .unwrap().is_digit(10) { continue } let mut end = pos + 3; while end < full_version_line.len() && - full_version_line.char_at(end).is_digit(10) { + full_version_line[end..].chars().next() + .unwrap().is_digit(10) { end += 1; } return Some(full_version_line[pos..end].to_owned()); @@ -432,13 +462,13 @@ fn extract_lldb_version(full_version_line: Option) -> Option { for (pos, l) in full_version_line.char_indices() { if l != 'l' && l != 'L' { continue } if pos + 5 >= full_version_line.len() { continue } - let l = full_version_line.char_at(pos + 1); + let l = full_version_line[pos + 1..].chars().next().unwrap(); if l != 'l' && l != 'L' { continue } - let d = full_version_line.char_at(pos + 2); + let d = full_version_line[pos + 2..].chars().next().unwrap(); if d != 'd' && d != 'D' { continue } - let b = full_version_line.char_at(pos + 3); + let b = full_version_line[pos + 3..].chars().next().unwrap(); if b != 'b' && b != 'B' { continue } - let dash = full_version_line.char_at(pos + 4); + let dash = full_version_line[pos + 4..].chars().next().unwrap(); if dash != '-' { continue } let vers = full_version_line[pos + 5..].chars().take_while(|c| { diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index a3ad022ebd..418a0bc712 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -9,14 +9,54 @@ // except according to those terms. use self::WhichLine::*; +use std::fmt; use std::fs::File; use std::io::BufReader; use std::io::prelude::*; use std::path::Path; +use std::str::FromStr; + +#[derive(Clone, Debug, PartialEq)] +pub enum ErrorKind { + Help, + Error, + Note, + Suggestion, + Warning, +} + +impl FromStr for ErrorKind { + type Err = (); + fn from_str(s: &str) -> Result { + match &s.trim_right_matches(':') as &str { + "HELP" => Ok(ErrorKind::Help), + "ERROR" => Ok(ErrorKind::Error), + "NOTE" => Ok(ErrorKind::Note), + "SUGGESTION" => Ok(ErrorKind::Suggestion), + "WARN" => Ok(ErrorKind::Warning), + "WARNING" => Ok(ErrorKind::Warning), + _ => Err(()), + } + } +} + +impl fmt::Display for ErrorKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ErrorKind::Help => write!(f, "help"), + ErrorKind::Error => write!(f, "error"), + ErrorKind::Note => write!(f, "note"), + ErrorKind::Suggestion => write!(f, "suggestion"), + ErrorKind::Warning => write!(f, "warning"), + } + } +} pub struct ExpectedError { - pub line: usize, - pub kind: String, + pub line_num: usize, + /// What kind of message we expect (e.g. warning, error, suggestion). + /// `None` if not specified or unknown message kind. + pub kind: Option, pub msg: String, } @@ -30,8 +70,10 @@ enum WhichLine { ThisLine, FollowPrevious(usize), AdjustBackward(usize) } /// Goal is to enable tests both like: //~^^^ ERROR go up three /// and also //~^ ERROR message one for the preceding line, and /// //~| ERROR message two for that same line. -// Load any test directives embedded in the file -pub fn load_errors(testfile: &Path) -> Vec { +/// +/// If cfg is not None (i.e., in an incremental test), then we look +/// for `//[X]~` instead, where `X` is the current `cfg`. +pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec { let rdr = BufReader::new(File::open(testfile).unwrap()); // `last_nonfollow_error` tracks the most recently seen @@ -44,55 +86,66 @@ pub fn load_errors(testfile: &Path) -> Vec { // updating it in the map callback below.) let mut last_nonfollow_error = None; - rdr.lines().enumerate().filter_map(|(line_no, ln)| { - parse_expected(last_nonfollow_error, - line_no + 1, - &ln.unwrap()) - .map(|(which, error)| { - match which { - FollowPrevious(_) => {} - _ => last_nonfollow_error = Some(error.line), - } - error - }) - }).collect() + let tag = match cfg { + Some(rev) => format!("//[{}]~", rev), + None => format!("//~") + }; + + rdr.lines() + .enumerate() + .filter_map(|(line_num, line)| { + parse_expected(last_nonfollow_error, + line_num + 1, + &line.unwrap(), + &tag) + .map(|(which, error)| { + match which { + FollowPrevious(_) => {} + _ => last_nonfollow_error = Some(error.line_num), + } + error + }) + }) + .collect() } fn parse_expected(last_nonfollow_error: Option, line_num: usize, - line: &str) -> Option<(WhichLine, ExpectedError)> { - let start = match line.find("//~") { Some(i) => i, None => return None }; - let (follow, adjusts) = if line.char_at(start + 3) == '|' { + line: &str, + tag: &str) + -> Option<(WhichLine, ExpectedError)> { + let start = match line.find(tag) { Some(i) => i, None => return None }; + let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' { (true, 0) } else { - (false, line[start + 3..].chars().take_while(|c| *c == '^').count()) + (false, line[start + tag.len()..].chars().take_while(|c| *c == '^').count()) }; - let kind_start = start + 3 + adjusts + (follow as usize); - let letters = line[kind_start..].chars(); - let kind = letters.skip_while(|c| c.is_whitespace()) - .take_while(|c| !c.is_whitespace()) - .flat_map(|c| c.to_lowercase()) - .collect::(); + let kind_start = start + tag.len() + adjusts + (follow as usize); + let kind = line[kind_start..].split_whitespace() + .next() + .expect("Encountered unexpected empty comment") + .parse::() + .ok(); let letters = line[kind_start..].chars(); let msg = letters.skip_while(|c| c.is_whitespace()) .skip_while(|c| !c.is_whitespace()) .collect::().trim().to_owned(); - let (which, line) = if follow { + let (which, line_num) = if follow { assert!(adjusts == 0, "use either //~| or //~^, not both."); - let line = last_nonfollow_error.unwrap_or_else(|| { - panic!("encountered //~| without preceding //~^ line.") - }); - (FollowPrevious(line), line) + let line_num = last_nonfollow_error.expect("encountered //~| without \ + preceding //~^ line."); + (FollowPrevious(line_num), line_num) } else { let which = if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine }; - let line = line_num - adjusts; - (which, line) + let line_num = line_num - adjusts; + (which, line_num) }; - debug!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg); - Some((which, ExpectedError { line: line, + debug!("line={} tag={:?} which={:?} kind={:?} msg={:?}", + line_num, tag, which, kind, msg); + Some((which, ExpectedError { line_num: line_num, kind: kind, msg: msg, })) } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 6efe6e608e..ef93fcfa01 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -18,11 +18,12 @@ use common::Config; use common; use util; +#[derive(Clone, Debug)] pub struct TestProps { // Lines that should be expected, in order, on standard out pub error_patterns: Vec , // Extra flags to pass to the compiler - pub compile_flags: Option, + pub compile_flags: Vec, // Extra flags to pass when the compiled code is run (such as --bench) pub run_flags: Option, // If present, the name of a file that this test should match when @@ -30,6 +31,8 @@ pub struct TestProps { pub pp_exact: Option, // Modules from aux directory that should be compiled pub aux_builds: Vec , + // Environment settings to use for compiling + pub rustc_env: Vec<(String,String)> , // Environment settings to use during execution pub exec_env: Vec<(String,String)> , // Lines to check if they appear in the expected debugger output @@ -50,119 +53,173 @@ pub struct TestProps { pub pretty_compare_only: bool, // Patterns which must not appear in the output of a cfail test. pub forbid_output: Vec, + // Revisions to test for incremental compilation. + pub revisions: Vec, } // Load any test directives embedded in the file pub fn load_props(testfile: &Path) -> TestProps { - let mut error_patterns = Vec::new(); - let mut aux_builds = Vec::new(); - let mut exec_env = Vec::new(); - let mut compile_flags = None; - let mut run_flags = None; - let mut pp_exact = None; - let mut check_lines = Vec::new(); - let mut build_aux_docs = false; - let mut force_host = false; - let mut check_stdout = false; - let mut no_prefer_dynamic = 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, &mut |ln| { + let error_patterns = Vec::new(); + let aux_builds = Vec::new(); + let exec_env = Vec::new(); + let run_flags = None; + let pp_exact = None; + let check_lines = Vec::new(); + let build_aux_docs = false; + let force_host = false; + let check_stdout = false; + let no_prefer_dynamic = false; + let pretty_expanded = false; + let pretty_compare_only = false; + let forbid_output = Vec::new(); + let mut props = TestProps { + error_patterns: error_patterns, + compile_flags: vec![], + run_flags: run_flags, + pp_exact: pp_exact, + aux_builds: aux_builds, + revisions: vec![], + rustc_env: vec![], + exec_env: exec_env, + check_lines: check_lines, + build_aux_docs: build_aux_docs, + force_host: force_host, + check_stdout: check_stdout, + no_prefer_dynamic: no_prefer_dynamic, + pretty_expanded: pretty_expanded, + pretty_mode: format!("normal"), + pretty_compare_only: pretty_compare_only, + forbid_output: forbid_output, + }; + load_props_into(&mut props, testfile, None); + props +} + +/// Load properties from `testfile` into `props`. If a property is +/// tied to a particular revision `foo` (indicated by writing +/// `//[foo]`), then the property is ignored unless `cfg` is +/// `Some("foo")`. +pub fn load_props_into(props: &mut TestProps, testfile: &Path, cfg: Option<&str>) { + iter_header(testfile, cfg, &mut |ln| { if let Some(ep) = parse_error_pattern(ln) { - error_patterns.push(ep); + props.error_patterns.push(ep); } - if compile_flags.is_none() { - compile_flags = parse_compile_flags(ln); + if let Some(flags) = parse_compile_flags(ln) { + props.compile_flags.extend( + flags + .split_whitespace() + .map(|s| s.to_owned())); } - if run_flags.is_none() { - run_flags = parse_run_flags(ln); + if let Some(r) = parse_revisions(ln) { + props.revisions.extend(r); } - if pp_exact.is_none() { - pp_exact = parse_pp_exact(ln, testfile); + if props.run_flags.is_none() { + props.run_flags = parse_run_flags(ln); } - if !build_aux_docs { - build_aux_docs = parse_build_aux_docs(ln); + if props.pp_exact.is_none() { + props.pp_exact = parse_pp_exact(ln, testfile); } - if !force_host { - force_host = parse_force_host(ln); + if !props.build_aux_docs { + props.build_aux_docs = parse_build_aux_docs(ln); } - if !check_stdout { - check_stdout = parse_check_stdout(ln); + if !props.force_host { + props.force_host = parse_force_host(ln); } - if !no_prefer_dynamic { - no_prefer_dynamic = parse_no_prefer_dynamic(ln); + if !props.check_stdout { + props.check_stdout = parse_check_stdout(ln); } - if !pretty_expanded { - pretty_expanded = parse_pretty_expanded(ln); + if !props.no_prefer_dynamic { + props.no_prefer_dynamic = parse_no_prefer_dynamic(ln); } - if pretty_mode.is_none() { - pretty_mode = parse_pretty_mode(ln); + if !props.pretty_expanded { + props.pretty_expanded = parse_pretty_expanded(ln); } - if !pretty_compare_only { - pretty_compare_only = parse_pretty_compare_only(ln); + if let Some(m) = parse_pretty_mode(ln) { + props.pretty_mode = m; + } + + if !props.pretty_compare_only { + props.pretty_compare_only = parse_pretty_compare_only(ln); } if let Some(ab) = parse_aux_build(ln) { - aux_builds.push(ab); + props.aux_builds.push(ab); } - if let Some(ee) = parse_exec_env(ln) { - exec_env.push(ee); + if let Some(ee) = parse_env(ln, "exec-env") { + props.exec_env.push(ee); + } + + if let Some(ee) = parse_env(ln, "rustc-env") { + props.rustc_env.push(ee); } if let Some(cl) = parse_check_line(ln) { - check_lines.push(cl); + props.check_lines.push(cl); } if let Some(of) = parse_forbid_output(ln) { - forbid_output.push(of); + props.forbid_output.push(of); } - - 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).is_none() { - exec_env.push((key.to_owned(), val)) + if props.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() { + props.exec_env.push((key.to_owned(), val)) }, Err(..) => {} } } +} - TestProps { - error_patterns: error_patterns, - compile_flags: compile_flags, - run_flags: run_flags, - pp_exact: pp_exact, - aux_builds: aux_builds, - exec_env: exec_env, - check_lines: check_lines, - build_aux_docs: build_aux_docs, - force_host: force_host, - check_stdout: check_stdout, - no_prefer_dynamic: no_prefer_dynamic, - pretty_expanded: pretty_expanded, - pretty_mode: pretty_mode.unwrap_or("normal".to_owned()), - pretty_compare_only: pretty_compare_only, - forbid_output: forbid_output, - } +pub struct EarlyProps { + pub ignore: bool, + pub should_fail: bool, } -pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { +// scan the file to detect whether the test should be ignored and +// whether it should panic; these are two things the test runner needs +// to know early, before actually running the test +pub fn early_props(config: &Config, testfile: &Path) -> EarlyProps { + let mut props = EarlyProps { + ignore: false, + should_fail: false, + }; + + iter_header(testfile, None, &mut |ln| { + props.ignore = + props.ignore || + 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)) || + parse_name_directive(ln, &ignore_env(config)) || + (config.mode == common::Pretty && + parse_name_directive(ln, "ignore-pretty")) || + (config.target != config.host && + parse_name_directive(ln, "ignore-cross-compile")) || + ignore_gdb(config, ln) || + ignore_lldb(config, ln); + + props.should_fail = + props.should_fail || + parse_name_directive(ln, "should-fail"); + }); + + return props; + fn ignore_target(config: &Config) -> String { format!("ignore-{}", util::get_os(&config.target)) } @@ -229,39 +286,40 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { false } } - - 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)) && - !parse_name_directive(ln, &ignore_env(config)) && - !(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) && - !(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) && - !ignore_gdb(config, ln) && - !ignore_lldb(config, ln) - }); - - !val } -fn iter_header(testfile: &Path, it: &mut FnMut(&str) -> bool) -> bool { +fn iter_header(testfile: &Path, + cfg: Option<&str>, + it: &mut FnMut(&str)) { 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 // with a warm page cache. Maybe with a cold one. let ln = ln.unwrap(); - if ln.starts_with("fn") || - ln.starts_with("mod") { - return true; - } else { - if !(it(ln.trim())) { - return false; + let ln = ln.trim(); + if ln.starts_with("fn") || ln.starts_with("mod") { + return; + } else if ln.starts_with("//[") { + // A comment like `//[foo]` is specific to revision `foo` + if let Some(close_brace) = ln.find("]") { + let lncfg = &ln[3..close_brace]; + let matches = match cfg { + Some(s) => s == &lncfg[..], + None => false, + }; + if matches { + it(&ln[close_brace+1..]); + } + } else { + panic!("malformed condition directive: expected `//[foo]`, found `{}`", + ln) } + } else if ln.starts_with("//") { + it(&ln[2..]); } } - return true; + return; } fn parse_error_pattern(line: &str) -> Option { @@ -280,6 +338,11 @@ fn parse_compile_flags(line: &str) -> Option { parse_name_value_directive(line, "compile-flags") } +fn parse_revisions(line: &str) -> Option> { + parse_name_value_directive(line, "revisions") + .map(|r| r.split_whitespace().map(|t| t.to_string()).collect()) +} + fn parse_run_flags(line: &str) -> Option { parse_name_value_directive(line, "run-flags") } @@ -316,8 +379,8 @@ fn parse_pretty_compare_only(line: &str) -> bool { parse_name_directive(line, "pretty-compare-only") } -fn parse_exec_env(line: &str) -> Option<(String, String)> { - parse_name_value_directive(line, "exec-env").map(|nv| { +fn parse_env(line: &str, name: &str) -> Option<(String, String)> { + parse_name_value_directive(line, name).map(|nv| { // nv is either FOO or FOO=BAR let mut strs: Vec = nv .splitn(2, '=') diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index 7c5397a1af..f418edf668 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(deprecated)] - -use std::dynamic_lib::DynamicLibrary; +use std::env; +use std::ffi::OsString; use std::io::prelude::*; use std::path::PathBuf; use std::process::{ExitStatus, Command, Child, Output, Stdio}; @@ -18,15 +17,22 @@ 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(); + let var = if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + }; + let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new())) + .collect::>(); if let Some(p) = aux_path { path.insert(0, PathBuf::from(p)) } 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 = env::join_paths(&path).unwrap(); cmd.env(var, newpath); } diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 7cad5a4391..6773c34c7d 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -11,7 +11,8 @@ use common::Config; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits}; -use errors; +use common::{Incremental}; +use errors::{self, ErrorKind}; use header::TestProps; use header; use procsrv; @@ -59,6 +60,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { Codegen => run_codegen_test(&config, &props, &testpaths), Rustdoc => run_rustdoc_test(&config, &props, &testpaths), CodegenUnits => run_codegen_units_test(&config, &props, &testpaths), + Incremental => run_incremental_test(&config, &props, &testpaths), } } @@ -70,39 +72,77 @@ fn get_output(props: &TestProps, proc_res: &ProcRes) -> String { } } + +fn for_each_revision(config: &Config, props: &TestProps, testpaths: &TestPaths, + mut op: OP) + where OP: FnMut(&Config, &TestProps, &TestPaths, Option<&str>) +{ + if props.revisions.is_empty() { + op(config, props, testpaths, None) + } else { + for revision in &props.revisions { + let mut revision_props = props.clone(); + header::load_props_into(&mut revision_props, + &testpaths.file, + Some(&revision)); + revision_props.compile_flags.extend(vec![ + format!("--cfg"), + format!("{}", revision), + ]); + op(config, &revision_props, testpaths, Some(revision)); + } + } +} + fn run_cfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + for_each_revision(config, props, testpaths, run_cfail_test_revision); +} + +fn run_cfail_test_revision(config: &Config, + props: &TestProps, + testpaths: &TestPaths, + revision: Option<&str>) { let proc_res = compile_test(config, props, testpaths); if proc_res.status.success() { - fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[..], - &proc_res); + fatal_proc_rec( + revision, + &format!("{} test compiled successfully!", config.mode)[..], + &proc_res); } - check_correct_failure_status(&proc_res); + check_correct_failure_status(revision, &proc_res); if proc_res.status.success() { - fatal("process did not return an error status"); + fatal(revision, "process did not return an error status"); } let output_to_check = get_output(props, &proc_res); - let expected_errors = errors::load_errors(&testpaths.file); + let expected_errors = errors::load_errors(&testpaths.file, revision); if !expected_errors.is_empty() { if !props.error_patterns.is_empty() { - fatal("both error pattern and expected errors specified"); + fatal(revision, "both error pattern and expected errors specified"); } - check_expected_errors(expected_errors, testpaths, &proc_res); + check_expected_errors(revision, expected_errors, testpaths, &proc_res); } else { - check_error_patterns(props, testpaths, &output_to_check, &proc_res); + check_error_patterns(revision, props, testpaths, &output_to_check, &proc_res); } - check_no_compiler_crash(&proc_res); - check_forbid_output(props, &output_to_check, &proc_res); + check_no_compiler_crash(revision, &proc_res); + check_forbid_output(revision, props, &output_to_check, &proc_res); } fn run_rfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + for_each_revision(config, props, testpaths, run_rfail_test_revision); +} + +fn run_rfail_test_revision(config: &Config, + props: &TestProps, + testpaths: &TestPaths, + revision: Option<&str>) { let proc_res = compile_test(config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("compilation failed!", &proc_res); + fatal_proc_rec(revision, "compilation failed!", &proc_res); } let proc_res = exec_compiled_test(config, props, testpaths); @@ -110,19 +150,20 @@ fn run_rfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { // The value our Makefile configures valgrind to return on failure 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); + fatal_proc_rec(revision, "run-fail test isn't valgrind-clean!", &proc_res); } let output_to_check = get_output(props, &proc_res); - check_correct_failure_status(&proc_res); - check_error_patterns(props, testpaths, &output_to_check, &proc_res); + check_correct_failure_status(revision, &proc_res); + check_error_patterns(revision, props, testpaths, &output_to_check, &proc_res); } -fn check_correct_failure_status(proc_res: &ProcRes) { +fn check_correct_failure_status(revision: Option<&str>, proc_res: &ProcRes) { // The value the rust runtime returns on failure const RUST_ERR: i32 = 101; if proc_res.status.code() != Some(RUST_ERR) { fatal_proc_rec( + revision, &format!("failure produced the wrong error: {}", proc_res.status), proc_res); @@ -130,20 +171,29 @@ fn check_correct_failure_status(proc_res: &ProcRes) { } fn run_rpass_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + for_each_revision(config, props, testpaths, run_rpass_test_revision); +} + +fn run_rpass_test_revision(config: &Config, + props: &TestProps, + testpaths: &TestPaths, + revision: Option<&str>) { let proc_res = compile_test(config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("compilation failed!", &proc_res); + fatal_proc_rec(revision, "compilation failed!", &proc_res); } let proc_res = exec_compiled_test(config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("test run failed!", &proc_res); + fatal_proc_rec(revision, "test run failed!", &proc_res); } } fn run_valgrind_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + assert!(props.revisions.is_empty(), "revisions not relevant here"); + if config.valgrind_path.is_none() { assert!(!config.force_valgrind); return run_rpass_test(config, props, testpaths); @@ -152,7 +202,7 @@ fn run_valgrind_test(config: &Config, props: &TestProps, testpaths: &TestPaths) let mut proc_res = compile_test(config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("compilation failed!", &proc_res); + fatal_proc_rec(None, "compilation failed!", &proc_res); } let mut new_config = config.clone(); @@ -160,11 +210,18 @@ fn run_valgrind_test(config: &Config, props: &TestProps, testpaths: &TestPaths) proc_res = exec_compiled_test(&new_config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("test run failed!", &proc_res); + fatal_proc_rec(None, "test run failed!", &proc_res); } } fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + for_each_revision(config, props, testpaths, run_pretty_test_revision); +} + +fn run_pretty_test_revision(config: &Config, + props: &TestProps, + testpaths: &TestPaths, + revision: Option<&str>) { if props.pp_exact.is_some() { logv(config, "testing for exact pretty-printing".to_owned()); } else { @@ -180,7 +237,8 @@ fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { let mut round = 0; while round < rounds { - logv(config, format!("pretty-printing round {}", round)); + logv(config, format!("pretty-printing round {} revision {:?}", + round, revision)); let proc_res = print_source(config, props, testpaths, @@ -188,8 +246,10 @@ fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { &props.pretty_mode); if !proc_res.status.success() { - fatal_proc_rec(&format!("pretty-printing failed in round {}", round), - &proc_res); + fatal_proc_rec(revision, + &format!("pretty-printing failed in round {} revision {:?}", + round, revision), + &proc_res); } let ProcRes{ stdout, .. } = proc_res; @@ -215,30 +275,32 @@ fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { expected = expected.replace(&cr, "").to_owned(); } - compare_source(&expected, &actual); + compare_source(revision, &expected, &actual); // If we're only making sure that the output matches then just stop here if props.pretty_compare_only { return; } // Finally, let's make sure it actually appears to remain valid code let proc_res = typecheck_source(config, props, testpaths, actual); - if !proc_res.status.success() { - fatal_proc_rec("pretty-printed source does not typecheck", &proc_res); + fatal_proc_rec(revision, "pretty-printed source does not typecheck", &proc_res); } + if !props.pretty_expanded { return } // additionally, run `--pretty expanded` and try to build it. let proc_res = print_source(config, props, testpaths, srcs[round].clone(), "expanded"); if !proc_res.status.success() { - fatal_proc_rec("pretty-printing (expanded) failed", &proc_res); + fatal_proc_rec(revision, "pretty-printing (expanded) failed", &proc_res); } let ProcRes{ stdout: expanded_src, .. } = proc_res; let proc_res = typecheck_source(config, props, testpaths, expanded_src); if !proc_res.status.success() { - fatal_proc_rec("pretty-printed source (expanded) does not typecheck", - &proc_res); + fatal_proc_rec( + revision, + "pretty-printed source (expanded) does not typecheck", + &proc_res); } return; @@ -256,7 +318,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { testpaths, pretty_type.to_owned()), props.exec_env.clone(), - &config.compile_lib_path, + config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), Some(src)) } @@ -275,16 +337,16 @@ fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { "-L".to_owned(), aux_dir.to_str().unwrap().to_owned()); args.extend(split_maybe_args(&config.target_rustcflags)); - args.extend(split_maybe_args(&props.compile_flags)); + args.extend(props.compile_flags.iter().cloned()); return ProcArgs { prog: config.rustc_path.to_str().unwrap().to_owned(), args: args, }; } - fn compare_source(expected: &str, actual: &str) { + fn compare_source(revision: Option<&str>, expected: &str, actual: &str) { if expected != actual { - error("pretty-printed source does not match expected source"); + error(revision, "pretty-printed source does not match expected source"); println!("\n\ expected:\n\ ------------------------------------------\n\ @@ -322,7 +384,7 @@ actual:\n\ "-L".to_owned(), aux_dir.to_str().unwrap().to_owned()); args.extend(split_maybe_args(&config.target_rustcflags)); - args.extend(split_maybe_args(&props.compile_flags)); + args.extend(props.compile_flags.iter().cloned()); // FIXME (#9639): This needs to handle non-utf8 paths return ProcArgs { prog: config.rustc_path.to_str().unwrap().to_owned(), @@ -332,6 +394,8 @@ actual:\n\ } fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + assert!(props.revisions.is_empty(), "revisions not relevant here"); + let mut config = Config { target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags), host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags), @@ -349,7 +413,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testpaths: &TestPa // compile test file (it should have 'compile-flags:-g' in the header) let compiler_run_result = compile_test(config, props, testpaths); if !compiler_run_result.status.success() { - fatal_proc_rec("compilation failed!", &compiler_run_result); + fatal_proc_rec(None, "compilation failed!", &compiler_run_result); } let exe_file = make_exe_name(config, testpaths); @@ -441,7 +505,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testpaths: &TestPa let tool_path = match config.android_cross_path.to_str() { Some(x) => x.to_owned(), - None => fatal("cannot find android cross path") + None => fatal(None, "cannot find android cross path") }; let debugger_script = make_out_name(config, testpaths, "debugger.script"); @@ -573,14 +637,14 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testpaths: &TestPa testpaths, proc_args, environment, - &config.run_lib_path, + config.run_lib_path.to_str().unwrap(), None, None); } } if !debugger_run_result.status.success() { - fatal("gdb failed to execute"); + fatal(None, "gdb failed to execute"); } check_debugger_output(&debugger_run_result, &check_lines); @@ -600,8 +664,10 @@ fn find_rust_src_root(config: &Config) -> Option { } fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + assert!(props.revisions.is_empty(), "revisions not relevant here"); + if config.lldb_python_dir.is_none() { - fatal("Can't run LLDB test because LLDB's python path is not set."); + fatal(None, "Can't run LLDB test because LLDB's python path is not set."); } let mut config = Config { @@ -615,7 +681,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testpaths: &TestP // compile test file (it should have 'compile-flags:-g' in the header) let compile_result = compile_test(config, props, testpaths); if !compile_result.status.success() { - fatal_proc_rec("compilation failed!", &compile_result); + fatal_proc_rec(None, "compilation failed!", &compile_result); } let exe_file = make_exe_name(config, testpaths); @@ -663,8 +729,11 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testpaths: &TestP script_str.push_str("type category enable Rust\n"); // Set breakpoints on every line that contains the string "#break" + let source_file_name = testpaths.file.file_name().unwrap().to_string_lossy(); for line in &breakpoint_lines { - script_str.push_str(&format!("breakpoint set --line {}\n", line)); + script_str.push_str(&format!("breakpoint set --file '{}' --line {}\n", + source_file_name, + line)); } // Append the other commands @@ -692,7 +761,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testpaths: &TestP &rust_src_root); if !debugger_run_result.status.success() { - fatal_proc_rec("Error while running LLDB", &debugger_run_result); + fatal_proc_rec(None, "Error while running LLDB", &debugger_run_result); } check_debugger_output(&debugger_run_result, &check_lines); @@ -725,7 +794,7 @@ fn cmd2procres(config: &Config, testpaths: &TestPaths, cmd: &mut Command) String::from_utf8(stderr).unwrap()) }, Err(e) => { - fatal(&format!("Failed to setup Python process for \ + fatal(None, &format!("Failed to setup Python process for \ LLDB script: {}", e)) } }; @@ -775,7 +844,7 @@ fn parse_debugger_commands(testpaths: &TestPaths, debugger_prefix: &str) }); } Err(e) => { - fatal(&format!("Error while parsing debugger commands: {}", e)) + fatal(None, &format!("Error while parsing debugger commands: {}", e)) } } counter += 1; @@ -799,12 +868,28 @@ fn cleanup_debug_info_options(options: &Option) -> Option { "-g".to_owned(), "--debuginfo".to_owned() ]; - let new_options = + let mut new_options = split_maybe_args(options).into_iter() .filter(|x| !options_to_remove.contains(x)) - .collect::>() - .join(" "); - Some(new_options) + .collect::>(); + + let mut i = 0; + while i + 1 < new_options.len() { + if new_options[i] == "-Z" { + // FIXME #31005 MIR missing debuginfo currently. + if new_options[i + 1] == "orbit" { + // Remove "-Z" and "orbit". + new_options.remove(i); + new_options.remove(i); + continue; + } + // Always skip over -Z's argument. + i += 1; + } + i += 1; + } + + Some(new_options.join(" ")) } fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) { @@ -857,19 +942,21 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) } } if i != num_check_lines { - fatal_proc_rec(&format!("line not found in debugger output: {}", + fatal_proc_rec(None, &format!("line not found in debugger output: {}", check_lines.get(i).unwrap()), debugger_run_result); } } } -fn check_error_patterns(props: &TestProps, +fn check_error_patterns(revision: Option<&str>, + props: &TestProps, testpaths: &TestPaths, output_to_check: &str, proc_res: &ProcRes) { if props.error_patterns.is_empty() { - fatal(&format!("no error pattern specified in {:?}", + fatal(revision, + &format!("no error pattern specified in {:?}", testpaths.file.display())); } let mut next_err_idx = 0; @@ -891,75 +978,68 @@ fn check_error_patterns(props: &TestProps, let missing_patterns = &props.error_patterns[next_err_idx..]; if missing_patterns.len() == 1 { - fatal_proc_rec(&format!("error pattern '{}' not found!", missing_patterns[0]), - proc_res); + fatal_proc_rec( + revision, + &format!("error pattern '{}' not found!", missing_patterns[0]), + proc_res); } else { for pattern in missing_patterns { - error(&format!("error pattern '{}' not found!", *pattern)); + error(revision, &format!("error pattern '{}' not found!", *pattern)); } - fatal_proc_rec("multiple error patterns not found", proc_res); + fatal_proc_rec(revision, "multiple error patterns not found", proc_res); } } -fn check_no_compiler_crash(proc_res: &ProcRes) { +fn check_no_compiler_crash(revision: Option<&str>, proc_res: &ProcRes) { for line in proc_res.stderr.lines() { if line.starts_with("error: internal compiler error:") { - fatal_proc_rec("compiler encountered internal error", - proc_res); + fatal_proc_rec(revision, + "compiler encountered internal error", + proc_res); } } } -fn check_forbid_output(props: &TestProps, +fn check_forbid_output(revision: Option<&str>, + props: &TestProps, output_to_check: &str, proc_res: &ProcRes) { for pat in &props.forbid_output { if output_to_check.contains(pat) { - fatal_proc_rec("forbidden pattern found in compiler output", proc_res); + fatal_proc_rec(revision, + "forbidden pattern found in compiler output", + proc_res); } } } -fn check_expected_errors(expected_errors: Vec, +fn check_expected_errors(revision: Option<&str>, + expected_errors: Vec, testpaths: &TestPaths, proc_res: &ProcRes) { - // true if we found the error in question let mut found_flags = vec![false; expected_errors.len()]; if proc_res.status.success() { - fatal("process did not return an error status"); + fatal_proc_rec(revision, "process did not return an error status", proc_res); } let prefixes = expected_errors.iter().map(|ee| { - let expected = format!("{}:{}:", testpaths.file.display(), ee.line); + let expected = format!("{}:{}:", testpaths.file.display(), ee.line_num); // On windows just translate all '\' path separators to '/' expected.replace(r"\", "/") }).collect::>(); + // If the testcase being checked contains at least one expected "help" + // message, then we'll ensure that all "help" messages are expected. + // Otherwise, all "help" messages reported by the compiler will be ignored. + // This logic also applies to "note" messages. let (expect_help, expect_note) = expected_errors.iter() .fold((false, false), |(acc_help, acc_note), ee| - (acc_help || ee.kind == "help:", acc_note || - ee.kind == "note:")); - - 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 start with a space - // or open paren. - fn continuation( line: &str) -> bool { - line.starts_with(" ") || line.starts_with("(") - } + (acc_help || ee.kind == Some(ErrorKind::Help), + acc_note || ee.kind == Some(ErrorKind::Note))); // Scan and extract our error/warning messages, // which look like: @@ -970,20 +1050,22 @@ fn check_expected_errors(expected_errors: Vec, // // This pattern is ambiguous on windows, because filename may contain // a colon, so any path prefix must be detected and removed first. + let mut unexpected = 0; + let mut not_found = 0; for line in proc_res.stderr.lines() { let mut was_expected = false; let mut prev = 0; for (i, ee) in expected_errors.iter().enumerate() { if !found_flags[i] { - debug!("prefix={} ee.kind={} ee.msg={} line={}", + debug!("prefix={} ee.kind={:?} ee.msg={} line={}", prefixes[i], ee.kind, ee.msg, line); // Suggestions have no line number in their output, so take on the line number of // the previous expected error - if ee.kind == "suggestion" { - assert!(expected_errors[prev].kind == "help", + if ee.kind == Some(ErrorKind::Suggestion) { + assert!(expected_errors[prev].kind == Some(ErrorKind::Help), "SUGGESTIONs must be preceded by a HELP"); if line.contains(&ee.msg) { found_flags[i] = true; @@ -991,9 +1073,11 @@ fn check_expected_errors(expected_errors: Vec, break; } } - if (prefix_matches(line, &prefixes[i]) || continuation(line)) && - line.contains(&ee.kind) && - line.contains(&ee.msg) { + if + (prefix_matches(line, &prefixes[i]) || continuation(line)) && + (ee.kind.is_none() || line.contains(&ee.kind.as_ref().unwrap().to_string())) && + line.contains(&ee.msg) + { found_flags[i] = true; was_expected = true; break; @@ -1008,20 +1092,47 @@ fn check_expected_errors(expected_errors: Vec, } if !was_expected && is_unexpected_compiler_message(line, expect_help, expect_note) { - fatal_proc_rec(&format!("unexpected compiler message: '{}'", - line), - proc_res); + error(revision, &format!("unexpected compiler message: '{}'", line)); + unexpected += 1; } } for (i, &flag) in found_flags.iter().enumerate() { if !flag { let ee = &expected_errors[i]; - fatal_proc_rec(&format!("expected {} on line {} not found: {}", - ee.kind, ee.line, ee.msg), - proc_res); + error(revision, &format!("expected {} on line {} not found: {}", + ee.kind.as_ref() + .map_or("message".into(), + |k| k.to_string()), + ee.line_num, ee.msg)); + not_found += 1; } } + + if unexpected > 0 || not_found > 0 { + fatal_proc_rec( + revision, + &format!("{} unexpected errors found, {} expected errors not found", + unexpected, not_found), + proc_res); + } + + 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 start with a space + // or open paren. + fn continuation( line: &str) -> bool { + line.starts_with(" ") || line.starts_with("(") + } } fn is_unexpected_compiler_message(line: &str, expect_help: bool, expect_note: bool) -> bool { @@ -1066,7 +1177,7 @@ fn scan_char(haystack: &str, needle: char, idx: &mut usize) -> bool { if *idx >= haystack.len() { return false; } - let ch = haystack.char_at(*idx); + let ch = haystack[*idx..].chars().next().unwrap(); if ch != needle { return false; } @@ -1077,7 +1188,7 @@ fn scan_char(haystack: &str, needle: char, idx: &mut usize) -> bool { fn scan_integer(haystack: &str, idx: &mut usize) -> bool { let mut i = *idx; while i < haystack.len() { - let ch = haystack.char_at(i); + let ch = haystack[i..].chars().next().unwrap(); if ch < '0' || '9' < ch { break; } @@ -1097,7 +1208,7 @@ fn scan_string(haystack: &str, needle: &str, idx: &mut usize) -> bool { if haystack_i >= haystack.len() { return false; } - let ch = haystack.char_at(haystack_i); + let ch = haystack[haystack_i..].chars().next().unwrap(); haystack_i += ch.len_utf8(); if !scan_char(needle, ch, &mut needle_i) { return false; @@ -1184,7 +1295,7 @@ fn document(config: &Config, "-o".to_owned(), out_dir.to_str().unwrap().to_owned(), testpaths.file.to_str().unwrap().to_owned()]; - args.extend(split_maybe_args(&props.compile_flags)); + args.extend(props.compile_flags.iter().cloned()); let args = ProcArgs { prog: config.rustdoc_path.to_str().unwrap().to_owned(), args: args, @@ -1209,7 +1320,7 @@ fn exec_compiled_test(config: &Config, props: &TestProps, testpaths, make_run_args(config, props, testpaths), env, - &config.run_lib_path, + config.run_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), None) } @@ -1281,11 +1392,12 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps, &aux_testpaths, aux_args, Vec::new(), - &config.compile_lib_path, + config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), None); if !auxres.status.success() { fatal_proc_rec( + None, &format!("auxiliary build of {:?} failed to compile: ", aux_testpaths.file.display()), &auxres); @@ -1302,8 +1414,8 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps, compose_and_run(config, testpaths, args, - Vec::new(), - &config.compile_lib_path, + props.rustc_env.clone(), + config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), input) } @@ -1369,7 +1481,7 @@ fn make_compile_args(config: &Config, } else { args.extend(split_maybe_args(&config.target_rustcflags)); } - args.extend(split_maybe_args(&props.compile_flags)); + args.extend(props.compile_flags.iter().cloned()); return ProcArgs { prog: config.rustc_path.to_str().unwrap().to_owned(), args: args, @@ -1537,13 +1649,20 @@ fn maybe_dump_to_stdout(config: &Config, out: &str, err: &str) { } } -fn error(err: &str) { println!("\nerror: {}", err); } +fn error(revision: Option<&str>, err: &str) { + match revision { + Some(rev) => println!("\nerror in revision `{}`: {}", rev, err), + None => println!("\nerror: {}", err) + } +} -fn fatal(err: &str) -> ! { error(err); panic!(); } +fn fatal(revision: Option<&str>, err: &str) -> ! { + error(revision, err); panic!(); +} -fn fatal_proc_rec(err: &str, proc_res: &ProcRes) -> ! { - print!("\n\ -error: {}\n\ +fn fatal_proc_rec(revision: Option<&str>, err: &str, proc_res: &ProcRes) -> ! { + error(revision, err); + print!("\ status: {}\n\ command: {}\n\ stdout:\n\ @@ -1555,7 +1674,7 @@ stderr:\n\ {}\n\ ------------------------------------------\n\ \n", - err, proc_res.status, proc_res.cmdline, proc_res.stdout, + proc_res.status, proc_res.cmdline, proc_res.stdout, proc_res.stderr); panic!(); } @@ -1753,20 +1872,22 @@ fn check_ir_with_filecheck(config: &Config, testpaths: &TestPaths) -> ProcRes { } fn run_codegen_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + assert!(props.revisions.is_empty(), "revisions not relevant here"); if config.llvm_bin_path.is_none() { - fatal("missing --llvm-bin-path"); + fatal(None, "missing --llvm-bin-path"); } let mut proc_res = compile_test_and_save_ir(config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("compilation failed!", &proc_res); + fatal_proc_rec(None, "compilation failed!", &proc_res); } proc_res = check_ir_with_filecheck(config, testpaths); if !proc_res.status.success() { - fatal_proc_rec("verification with 'FileCheck' failed", - &proc_res); + fatal_proc_rec(None, + "verification with 'FileCheck' failed", + &proc_res); } } @@ -1782,13 +1903,15 @@ fn charset() -> &'static str { } fn run_rustdoc_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + assert!(props.revisions.is_empty(), "revisions not relevant here"); + let out_dir = output_base_name(config, testpaths); let _ = fs::remove_dir_all(&out_dir); ensure_dir(&out_dir); let proc_res = document(config, props, testpaths, &out_dir); if !proc_res.status.success() { - fatal_proc_rec("rustdoc failed!", &proc_res); + fatal_proc_rec(None, "rustdoc failed!", &proc_res); } let root = find_rust_src_root(config).unwrap(); @@ -1799,18 +1922,20 @@ fn run_rustdoc_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { .arg(out_dir) .arg(&testpaths.file)); if !res.status.success() { - fatal_proc_rec("htmldocck failed!", &res); + fatal_proc_rec(None, "htmldocck failed!", &res); } } fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + assert!(props.revisions.is_empty(), "revisions not relevant here"); + let proc_res = compile_test(config, props, testpaths); if !proc_res.status.success() { - fatal_proc_rec("compilation failed!", &proc_res); + fatal_proc_rec(None, "compilation failed!", &proc_res); } - check_no_compiler_crash(&proc_res); + check_no_compiler_crash(None, &proc_res); let prefix = "TRANS_ITEM "; @@ -1821,7 +1946,7 @@ fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPa .map(|s| (&s[prefix.len()..]).to_string()) .collect(); - let expected: HashSet = errors::load_errors(&testpaths.file) + let expected: HashSet = errors::load_errors(&testpaths.file, None) .iter() .map(|e| e.msg.trim().to_string()) .collect(); @@ -1843,3 +1968,67 @@ fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPa panic!(); } } + +fn run_incremental_test(config: &Config, props: &TestProps, testpaths: &TestPaths) { + // Basic plan for a test incremental/foo/bar.rs: + // - load list of revisions pass1, fail2, pass3 + // - each should begin with `rpass`, `rfail`, or `cfail` + // - if `rpass`, expect compile and execution to succeed + // - if `cfail`, expect compilation to fail + // - if `rfail`, expect execution to fail + // - create a directory build/foo/bar.incremental + // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C pass1 + // - because name of revision starts with "pass", expect success + // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C fail2 + // - because name of revision starts with "fail", expect an error + // - load expected errors as usual, but filter for those that end in `[fail2]` + // - compile foo/bar.rs with -Z incremental=.../foo/bar.incremental and -C pass3 + // - because name of revision starts with "pass", expect success + // - execute build/foo/bar.exe and save output + // + // FIXME -- use non-incremental mode as an oracle? That doesn't apply + // to #[rustc_dirty] and clean tests I guess + + assert!(!props.revisions.is_empty(), "incremental tests require a list of revisions"); + + let output_base_name = output_base_name(config, testpaths); + + // Create the incremental workproduct directory. + let incremental_dir = output_base_name.with_extension("incremental"); + if incremental_dir.exists() { + fs::remove_dir_all(&incremental_dir).unwrap(); + } + fs::create_dir_all(&incremental_dir).unwrap(); + + if config.verbose { + print!("incremental_dir={}", incremental_dir.display()); + } + + for revision in &props.revisions { + let mut revision_props = props.clone(); + header::load_props_into(&mut revision_props, &testpaths.file, Some(&revision)); + + revision_props.compile_flags.extend(vec![ + format!("-Z"), + format!("incremental={}", incremental_dir.display()), + format!("--cfg"), + format!("{}", revision), + ]); + + if config.verbose { + print!("revision={:?} revision_props={:#?}", revision, revision_props); + } + + if revision.starts_with("rpass") { + run_rpass_test_revision(config, &revision_props, testpaths, Some(&revision)); + } else if revision.starts_with("rfail") { + run_rfail_test_revision(config, &revision_props, testpaths, Some(&revision)); + } else if revision.starts_with("cfail") { + run_cfail_test_revision(config, &revision_props, testpaths, Some(&revision)); + } else { + fatal( + Some(revision), + "revision name must begin with rpass, rfail, or cfail"); + } + } +} diff --git a/src/doc/book/SUMMARY.md b/src/doc/book/SUMMARY.md index fe5e1c3990..18aa9f2458 100644 --- a/src/doc/book/SUMMARY.md +++ b/src/doc/book/SUMMARY.md @@ -9,6 +9,7 @@ * [Comments](comments.md) * [if](if.md) * [Loops](loops.md) + * [Vectors](vectors.md) * [Ownership](ownership.md) * [References and Borrowing](references-and-borrowing.md) * [Lifetimes](lifetimes.md) @@ -18,7 +19,6 @@ * [Match](match.md) * [Patterns](patterns.md) * [Method Syntax](method-syntax.md) - * [Vectors](vectors.md) * [Strings](strings.md) * [Generics](generics.md) * [Traits](traits.md) diff --git a/src/doc/book/associated-types.md b/src/doc/book/associated-types.md index a0676a3399..cb54ac2419 100644 --- a/src/doc/book/associated-types.md +++ b/src/doc/book/associated-types.md @@ -131,7 +131,7 @@ 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: +try to create a trait object from a trait with an associated type, like this: ```rust,ignore # trait Graph { diff --git a/src/doc/book/casting-between-types.md b/src/doc/book/casting-between-types.md index 5cafe16936..7d03d2991a 100644 --- a/src/doc/book/casting-between-types.md +++ b/src/doc/book/casting-between-types.md @@ -17,12 +17,12 @@ function result. The most common case of coercion is removing mutability from a reference: * `&mut T` to `&T` - + An analogous conversion is to remove mutability from a [raw pointer](raw-pointers.md): * `*mut T` to `*const T` - + References can also be coerced to raw pointers: * `&T` to `*const T` @@ -32,7 +32,7 @@ References can also be coerced to raw pointers: Custom coercions may be defined using [`Deref`](deref-coercions.md). Coercion is transitive. - + # `as` The `as` keyword does safe casting: @@ -64,7 +64,7 @@ A cast `e as U` is also valid in any of the following cases: and `U` is an integer type; *enum-cast* * `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast* * `e` has type `u8` and `U` is `char`; *u8-char-cast* - + For example ```rust @@ -98,9 +98,9 @@ The semantics of numeric casts are: [float-int]: https://github.com/rust-lang/rust/issues/10184 [float-float]: https://github.com/rust-lang/rust/issues/15536 - + ## Pointer casts - + Perhaps surprisingly, it is safe to cast [raw pointers](raw-pointers.md) to and from integers, and to cast between pointers to different types subject to some constraints. It is only unsafe to dereference the pointer: @@ -114,7 +114,7 @@ let b = a as u32; * `e` has type `*T`, `U` has type `*U_0`, and either `U_0: Sized` or `unsize_kind(T) == unsize_kind(U_0)`; a *ptr-ptr-cast* - + * `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast* * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast* diff --git a/src/doc/book/choosing-your-guarantees.md b/src/doc/book/choosing-your-guarantees.md index f2b92e6dec..5035021307 100644 --- a/src/doc/book/choosing-your-guarantees.md +++ b/src/doc/book/choosing-your-guarantees.md @@ -204,7 +204,7 @@ borrow checker. Generally we know that such mutations won't happen in a nested f to check. For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things -simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the Rust compiler internals +simpler. For example, a lot of the maps in the `ctxt` struct in the Rust compiler internals are inside this wrapper. These are only modified once (during creation, which is not right after initialization) or a couple of times in well-separated places. However, since this struct is pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps @@ -235,7 +235,6 @@ At runtime each borrow causes a modification/check of the refcount. [cell-mod]: ../std/cell/ [cell]: ../std/cell/struct.Cell.html [refcell]: ../std/cell/struct.RefCell.html -[ctxt]: ../rustc/middle/ty/struct.ctxt.html # Synchronous types diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index 237545edc0..a8135ad384 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -371,14 +371,13 @@ assert_eq!(6, answer); This gives us these long, related errors: ```text -error: the trait `core::marker::Sized` is not implemented for the type -`core::ops::Fn(i32) -> i32` [E0277] +error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277] fn factory() -> (Fn(i32) -> i32) { ^~~~~~~~~~~~~~~~ note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time fn factory() -> (Fn(i32) -> i32) { ^~~~~~~~~~~~~~~~ -error: the trait `core::marker::Sized` is not implemented for the type `core::ops::Fn(i32) -> i32` [E0277] +error: the trait bound `core::ops::Fn(i32) -> i32 : core::marker::Sized` is not satisfied [E0277] let f = factory(); ^ note: `core::ops::Fn(i32) -> i32` does not have a constant size known at compile-time @@ -502,5 +501,5 @@ assert_eq!(6, answer); ``` 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 +closure. By `Box`ing it up, we’ve given it a known size, allowing it to escape our stack frame. diff --git a/src/doc/book/compiler-plugins.md b/src/doc/book/compiler-plugins.md index 800be13a24..1af05bfea1 100644 --- a/src/doc/book/compiler-plugins.md +++ b/src/doc/book/compiler-plugins.md @@ -8,12 +8,12 @@ extend the compiler's behavior with new syntax extensions, lint checks, etc. A plugin is a dynamic library crate with a designated *registrar* function that registers extensions with `rustc`. Other crates can load these extensions using the crate attribute `#![plugin(...)]`. See the -[`rustc_plugin`](../rustc_plugin/index.html) documentation for more about the +`rustc_plugin` documentation for more about the mechanics of defining and loading a plugin. If present, arguments passed as `#![plugin(foo(... args ...))]` are not interpreted by rustc itself. They are provided to the plugin through the -`Registry`'s [`args` method](../rustc_plugin/registry/struct.Registry.html#method.args). +`Registry`'s `args` method. In the vast majority of cases, a plugin should *only* be used through `#![plugin]` and not through an `extern crate` item. Linking a plugin would @@ -30,7 +30,7 @@ of a library. Plugins can extend Rust's syntax in various ways. One kind of syntax extension is the procedural macro. These are invoked the same way as [ordinary macros](macros.html), but the expansion is performed by arbitrary Rust -code that manipulates [syntax trees](../syntax/ast/index.html) at +code that manipulates syntax trees at compile time. Let's write a plugin @@ -120,11 +120,8 @@ The advantages over a simple `fn(&str) -> u32` are: In addition to procedural macros, you can define new [`derive`](../reference.html#derive)-like attributes and other kinds of -extensions. See -[`Registry::register_syntax_extension`](../rustc_plugin/registry/struct.Registry.html#method.register_syntax_extension) -and the [`SyntaxExtension` -enum](https://doc.rust-lang.org/syntax/ext/base/enum.SyntaxExtension.html). For -a more involved macro example, see +extensions. See `Registry::register_syntax_extension` and the `SyntaxExtension` +enum. For a more involved macro example, see [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). @@ -132,7 +129,7 @@ a more involved macro example, see 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 +You can use `syntax::parse` to turn token trees into higher-level syntax elements like expressions: ```ignore @@ -148,30 +145,21 @@ Looking through [`libsyntax` parser code](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs) will give you a feel for how the parsing infrastructure works. -Keep the [`Span`s](../syntax/codemap/struct.Span.html) of -everything you parse, for better error reporting. You can wrap -[`Spanned`](../syntax/codemap/struct.Spanned.html) around -your custom data structures. - -Calling -[`ExtCtxt::span_fatal`](../syntax/ext/base/struct.ExtCtxt.html#method.span_fatal) -will immediately abort compilation. It's better to instead call -[`ExtCtxt::span_err`](../syntax/ext/base/struct.ExtCtxt.html#method.span_err) -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`](https://doc.rust-lang.org/syntax/print/pprust/index.html#functions). - -The example above produced an integer literal using -[`AstBuilder::expr_usize`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_usize). +Keep the `Span`s of everything you parse, for better error reporting. You can +wrap `Spanned` around your custom data structures. + +Calling `ExtCtxt::span_fatal` will immediately abort compilation. It's better to +instead call `ExtCtxt::span_err` and return `DummyResult` so that the compiler +can continue and find further errors. + +To print syntax fragments for debugging, you can use `span_note` together with +`syntax::print::pprust::*_to_string`. + +The example above produced an integer literal using `AstBuilder::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 -starting point for an improved quasiquote as an ordinary plugin library. +quasiquote macros. They are undocumented and very rough around the edges. +However, the implementation may be a good starting point for an improved +quasiquote as an ordinary plugin library. # Lint plugins @@ -239,12 +227,11 @@ foo.rs:4 fn lintme() { } The components of a lint plugin are: -* one or more `declare_lint!` invocations, which define static - [`Lint`](../rustc/lint/struct.Lint.html) structs; +* one or more `declare_lint!` invocations, which define static `Lint` structs; * a struct holding any state needed by the lint pass (here, none); -* a [`LintPass`](../rustc/lint/trait.LintPass.html) +* a `LintPass` implementation defining how to check each syntax element. A single `LintPass` may call `span_lint` for several different `Lint`s, but should register them all through the `get_lints` method. diff --git a/src/doc/book/concurrency.md b/src/doc/book/concurrency.md index 30e4ad7ba5..ba4496b93f 100644 --- a/src/doc/book/concurrency.md +++ b/src/doc/book/concurrency.md @@ -94,6 +94,52 @@ fn main() { } ``` +As closures can capture variables from their environment, we can also try to +bring some data into the other thread: + +```rust,ignore +use std::thread; + +fn main() { + let x = 1; + thread::spawn(|| { + println!("x is {}", x); + }); +} +``` + +However, this gives us an error: + +```text +5:19: 7:6 error: closure may outlive the current function, but it + borrows `x`, which is owned by the current function +... +5:19: 7:6 help: to force the closure to take ownership of `x` (and any other referenced variables), + use the `move` keyword, as shown: + thread::spawn(move || { + println!("x is {}", x); + }); +``` + +This is because by default closures capture variables by reference, and thus the +closure only captures a _reference to `x`_. This is a problem, because the +thread may outlive the scope of `x`, leading to a dangling pointer. + +To fix this, we use a `move` closure as mentioned in the error message. `move` +closures are explained in depth [here](closures.html#move-closures); basically +they move variables from their environment into themselves. + +```rust +use std::thread; + +fn main() { + let x = 1; + thread::spawn(move || { + println!("x is {}", x); + }); +} +``` + Many languages have the ability to execute threads, but it's wildly unsafe. There are entire books about how to prevent errors that occur from shared mutable state. Rust helps out with its type system here as well, by preventing @@ -116,7 +162,7 @@ The same [ownership system](ownership.html) that helps prevent using pointers incorrectly also helps rule out data races, one of the worst kinds of concurrency bugs. -As an example, here is a Rust program that would have a data race in many +As an example, here is a Rust program that could have a data race in many languages. It will not compile: ```ignore @@ -145,23 +191,69 @@ This gives us an error: ``` Rust knows this wouldn't be safe! If we had a reference to `data` in each -thread, and the thread takes ownership of the reference, we'd have three -owners! +thread, and the thread takes ownership of the reference, we'd have three owners! +`data` gets moved out of `main` in the first call to `spawn()`, so subsequent +calls in the loop cannot use this variable. -So, we need some type that lets us have more than one reference to a value and -that we can share between threads, that is it must implement `Sync`. +Note that this specific example will not cause a data race since different array +indices are being accessed. But this can't be determined at compile time, and in +a similar situation where `i` is a constant or is random, you would have a data +race. -We'll use `Arc`, Rust's standard atomic reference count type, which -wraps a value up with some extra runtime bookkeeping which allows us to -share the ownership of the value between multiple references at the same time. +So, we need some type that lets us have more than one owning reference to a +value. Usually, we'd use `Rc` for this, which is a reference counted type +that provides shared ownership. It has some runtime bookkeeping that keeps track +of the number of references to it, hence the "reference count" part of its name. -The bookkeeping consists of a count of how many of these references exist to -the value, hence the reference count part of the name. +Calling `clone()` on an `Rc` will return a new owned reference and bump the +internal reference count. We create one of these for each thread: + + +```ignore +use std::thread; +use std::time::Duration; +use std::rc::Rc; + +fn main() { + let mut data = Rc::new(vec![1, 2, 3]); + + for i in 0..3 { + // create a new owned reference + let data_ref = data.clone(); + + // use it in a thread + thread::spawn(move || { + data_ref[i] += 1; + }); + } + + thread::sleep(Duration::from_millis(50)); +} +``` + +This won't work, however, and will give us the error: + +```text +13:9: 13:22 error: the trait bound `alloc::rc::Rc> : core::marker::Send` + is not satisfied +... +13:9: 13:22 note: `alloc::rc::Rc>` + cannot be sent between threads safely +``` + +As the error message mentions, `Rc` cannot be sent between threads safely. This +is because the internal reference count is not maintained in a thread safe +matter and can have a data race. + +To solve this, we'll use `Arc`, Rust's standard atomic reference count type. The Atomic part means `Arc` can safely be accessed from multiple threads. To do this the compiler guarantees that mutations of the internal count use indivisible operations which can't have data races. +In essence, `Arc` is a type that lets us share ownership of data _across +threads_. + ```ignore use std::thread; @@ -182,7 +274,7 @@ fn main() { } ``` -We now call `clone()` on our `Arc`, which increases the internal count. +Similarly to last time, we use `clone()` to create a new owned handle. This handle is then moved into the new thread. And... still gives us an error. @@ -193,14 +285,21 @@ And... still gives us an error. ^~~~ ``` -`Arc` assumes one more property about its contents to ensure that it is safe -to share across threads: it assumes its contents are `Sync`. This is true for -our value if it's immutable, but we want to be able to mutate it, so we need -something else to persuade the borrow checker we know what we're doing. +`Arc` by default has immutable contents. It allows the _sharing_ of data +between threads, but shared mutable data is unsafe and when threads are +involved can cause data races! + -It looks like we need some type that allows us to safely mutate a shared value, -for example a type that can ensure only one thread at a time is able to -mutate the value inside it at any one time. +Usually when we wish to make something in an immutable position mutable, we use +`Cell` or `RefCell` which allow safe mutation via runtime checks or +otherwise (see also: [Choosing Your Guarantees](choosing-your-guarantees.html)). +However, similar to `Rc`, these are not thread safe. If we try using these, we +will get an error about these types not being `Sync`, and the code will fail to +compile. + +It looks like we need some type that allows us to safely mutate a shared value +across threads, for example a type that can ensure only one thread at a time is +able to mutate the value inside it at any one time. For that, we can use the `Mutex` type! @@ -229,7 +328,17 @@ fn main() { Note that the value of `i` is bound (copied) to the closure and not shared among the threads. -Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of +We're "locking" the mutex here. A mutex (short for "mutual exclusion"), as +mentioned, only allows one thread at a time to access a value. When we wish to +access the value, we use `lock()` on it. This will "lock" the mutex, and no +other thread will be able to lock it (and hence, do anything with the value) +until we're done with it. If a thread attempts to lock a mutex which is already +locked, it will wait until the other thread releases the lock. + +The lock "release" here is implicit; when the result of the lock (in this case, +`data`) goes out of scope, the lock is automatically released. + +Note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of [`Mutex`](../std/sync/struct.Mutex.html) has this signature: ```ignore diff --git a/src/doc/book/const-and-static.md b/src/doc/book/const-and-static.md index b7042854bd..08ff3894c9 100644 --- a/src/doc/book/const-and-static.md +++ b/src/doc/book/const-and-static.md @@ -72,7 +72,7 @@ a [`Drop`][drop] implementation. # Initializing Both `const` and `static` have requirements for giving them a value. They must -be given a value that’s a constant expression. In other words, you cannot use +be given a value that’s a constant expression. In other words, you cannot use the result of a function call or anything similarly complex or at runtime. # Which construct should I use? diff --git a/src/doc/book/crates-and-modules.md b/src/doc/book/crates-and-modules.md index 0c9ed0bf12..b3ccefe0a6 100644 --- a/src/doc/book/crates-and-modules.md +++ b/src/doc/book/crates-and-modules.md @@ -118,7 +118,7 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native `libphrases-hash.rlib` is the compiled crate. Before we see how to use this crate from another crate, let’s break it up into multiple files. -# Multiple file crates +# Multiple File Crates If each crate were just one file, these files would get very large. It’s often easier to split up crates into multiple files, and Rust supports this in two @@ -190,13 +190,19 @@ mod farewells; ``` Again, these declarations tell Rust to look for either -`src/english/greetings.rs` and `src/japanese/greetings.rs` or -`src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because -these sub-modules don’t have their own sub-modules, we’ve chosen to make them -`src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew! - -The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are -both empty at the moment. Let’s add some functions. +`src/english/greetings.rs`, `src/english/farewells.rs`, +`src/japanese/greetings.rs` and `src/japanese/farewells.rs` or +`src/english/greetings/mod.rs`, `src/english/farewells/mod.rs`, +`src/japanese/greetings/mod.rs` and +`src/japanese/farewells/mod.rs`. Because these sub-modules don’t have +their own sub-modules, we’ve chosen to make them +`src/english/greetings.rs`, `src/english/farewells.rs`, +`src/japanese/greetings.rs` and `src/japanese/farewells.rs`. Whew! + +The contents of `src/english/greetings.rs`, +`src/english/farewells.rs`, `src/japanese/greetings.rs` and +`src/japanese/farewells.rs` are all empty at the moment. Let’s add +some functions. Put this in `src/english/greetings.rs`: diff --git a/src/doc/book/drop.md b/src/doc/book/drop.md index 8bc25ef90d..5513523e56 100644 --- a/src/doc/book/drop.md +++ b/src/doc/book/drop.md @@ -55,7 +55,7 @@ BOOM times 100!!! BOOM times 1!!! ``` -The TNT goes off before the firecracker does, because it was declared +The `tnt` goes off before the `firecracker` does, because it was declared afterwards. Last in, first out. So what is `Drop` good for? Generally, `Drop` is used to clean up any resources diff --git a/src/doc/book/error-handling.md b/src/doc/book/error-handling.md index 11086af10b..12cb71973a 100644 --- a/src/doc/book/error-handling.md +++ b/src/doc/book/error-handling.md @@ -2019,6 +2019,16 @@ impl Error for CliError { CliError::NotFound => "not found", } } + + fn cause(&self) -> Option<&error::Error> { + match *self { + CliError::Io(ref err) => Some(err), + CliError::Parse(ref err) => Some(err), + // Our custom error doesn't have an underlying cause, but we could + // modify it so that it does. + CliError::NotFound() => None, + } + } } ``` diff --git a/src/doc/book/functions.md b/src/doc/book/functions.md index 31c9da3fad..8a2444323f 100644 --- a/src/doc/book/functions.md +++ b/src/doc/book/functions.md @@ -246,6 +246,19 @@ stack backtrace: 13: 0x0 - ``` +If you need to override an already set `RUST_BACKTRACE`, +in cases when you cannot just unset the variable, +then set it to `0` to avoid getting a backtrace. +Any other value(even no value at all) turns on backtrace. + +```text +$ export RUST_BACKTRACE=1 +... +$ RUST_BACKTRACE=0 ./diverges +thread '
' panicked at 'This function never returns!', hello.rs:2 +note: Run with `RUST_BACKTRACE=1` for a backtrace. +``` + `RUST_BACKTRACE` also works with Cargo’s `run` command: ```text diff --git a/src/doc/book/getting-started.md b/src/doc/book/getting-started.md index 31ee385a92..16141d936e 100644 --- a/src/doc/book/getting-started.md +++ b/src/doc/book/getting-started.md @@ -93,8 +93,8 @@ unofficial locations. | `armv7-apple-ios` | ✓ | | | ARM iOS | | `armv7s-apple-ios` | ✓ | | | ARM iOS | | `aarch64-apple-ios` | ✓ | | | ARM64 iOS | -| `i686-unknown-freebsd` | ✓ | ✓ | | 32-bit FreeBSD | -| `x86_64-unknown-freebsd` | ✓ | ✓ | | 64-bit FreeBSD | +| `i686-unknown-freebsd` | ✓ | ✓ | ✓ | 32-bit FreeBSD | +| `x86_64-unknown-freebsd` | ✓ | ✓ | ✓ | 64-bit FreeBSD | | `x86_64-unknown-openbsd` | ✓ | ✓ | | 64-bit OpenBSD | | `x86_64-unknown-netbsd` | ✓ | ✓ | | 64-bit NetBSD | | `x86_64-unknown-bitrig` | ✓ | ✓ | | 64-bit Bitrig | @@ -119,19 +119,7 @@ This will download a script, and start the installation. If it all goes well, you’ll see this appear: ```text -Welcome to Rust. - -This script will download the Rust compiler and its package manager, Cargo, and -install them to /usr/local. You may install elsewhere by running this script -with the --prefix= option. - -The installer will run under ‘sudo’ and may ask you for your password. If you do -not want the script to run ‘sudo’ then pass it the --disable-sudo flag. - -You may uninstall later by running /usr/local/lib/rustlib/uninstall.sh, -or by running this script again with the --uninstall flag. - -Continue? (y/N) +Rust is ready to roll. ``` From here, press `y` for ‘yes’, and then follow the rest of the prompts. @@ -176,13 +164,15 @@ installed. Doing so will depend on your specific system, consult its documentation for more details. If not, there are a number of places where we can get help. The easiest is -[the #rust IRC channel on irc.mozilla.org][irc], which we can access through -[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans -(a silly nickname we call ourselves) who can help us out. Other great resources -include [the user’s forum][users], and [Stack Overflow][stackoverflow]. +[the #rust-beginners IRC channel on irc.mozilla.org][irc-beginners] and for +general discussion [the #rust IRC channel on irc.mozilla.org][irc], which we +can access through [Mibbit][mibbit]. Then we'll be chatting with other +Rustaceans (a silly nickname we call ourselves) who can help us out. Other great +resources include [the user’s forum][users] and [Stack Overflow][stackoverflow]. +[irc-beginners]: irc://irc.mozilla.org/#rust-beginners [irc]: irc://irc.mozilla.org/#rust -[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust +[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners,%23rust [users]: https://users.rust-lang.org/ [stackoverflow]: http://stackoverflow.com/questions/tagged/rust @@ -429,7 +419,7 @@ first. This leaves the top-level project directory (in this case, to your code. In this way, using Cargo helps you keep your projects nice and tidy. There's a place for everything, and everything is in its place. -Now, copy *main.rs* to the *src* directory, and delete the compiled file you +Now, move *main.rs* into the *src* directory, and delete the compiled file you created with `rustc`. As usual, replace `main` with `main.exe` if you're on Windows. @@ -513,7 +503,7 @@ Cargo checks to see if any of your project’s files have been modified, and onl rebuilds your project if they’ve changed since the last time you built it. With simple projects, Cargo doesn't bring a whole lot over just using `rustc`, -but it will become useful in future. This is especially true when you start +but it will become useful in the future. This is especially true when you start using crates; these are synonymous with a ‘library’ or ‘package’ in other programming languages. For complex projects composed of multiple crates, it’s much easier to let Cargo coordinate the build. Using Cargo, you can run `cargo diff --git a/src/doc/book/guessing-game.md b/src/doc/book/guessing-game.md index b9b6e9a4c9..590c7e8481 100644 --- a/src/doc/book/guessing-game.md +++ b/src/doc/book/guessing-game.md @@ -295,7 +295,7 @@ Rust warns us that we haven’t used the `Result` value. This warning comes from a special annotation that `io::Result` has. Rust is trying to tell you that you haven’t handled a possible error. The right way to suppress the error is to actually write error handling. Luckily, if we want to crash if there’s -a problem, we can use these two little methods. If we can recover from the +a problem, we can use `expect()`. If we can recover from the error somehow, we’d do something else, but we’ll save that for a future project. @@ -912,7 +912,7 @@ returned by `parse()`, this is an `enum` like `Ordering`, but in this case, each variant has some data associated with it: `Ok` is a success, and `Err` is a failure. Each contains more information: the successfully parsed integer, or an error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to -the unwrapped `Ok` value (ythe integer), and then we return it on the +the unwrapped `Ok` value (the integer), and then we return it on the right-hand side. In the `Err` case, we don’t care what kind of error it is, so we just use the catch all `_` instead of a name. This catches everything that isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in diff --git a/src/doc/book/if.md b/src/doc/book/if.md index a532dabf8d..52d0dd888e 100644 --- a/src/doc/book/if.md +++ b/src/doc/book/if.md @@ -4,7 +4,7 @@ Rust’s take on `if` is not particularly complex, but it’s much more like the `if` you’ll find in a dynamically typed language than in a more traditional systems language. So let’s talk about it, to make sure you grasp the nuances. -`if` is a specific form of a more general concept, the ‘branch’. The name comes +`if` is a specific form of a more general concept, the ‘branch’, whose name comes from a branch in a tree: a decision point, where depending on a choice, multiple paths can be taken. diff --git a/src/doc/book/inline-assembly.md b/src/doc/book/inline-assembly.md index 7659c4ff88..a5a2d7ce74 100644 --- a/src/doc/book/inline-assembly.md +++ b/src/doc/book/inline-assembly.md @@ -2,8 +2,7 @@ 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: +assembly to do this via the `asm!` macro. ```ignore asm!(assembly template diff --git a/src/doc/book/iterators.md b/src/doc/book/iterators.md index 0c4f804126..c174d2d6ba 100644 --- a/src/doc/book/iterators.md +++ b/src/doc/book/iterators.md @@ -14,6 +14,11 @@ Now that you know more Rust, we can talk in detail about how this works. Ranges (the `0..10`) are 'iterators'. An iterator is something that we can call the `.next()` method on repeatedly, and it gives us a sequence of things. +(By the way, a range with two dots like `0..10` is inclusive on the left (so it +starts at 0) and exclusive on the right (so it ends at 9). A mathematician +would write "[0, 10)". To get a range that goes all the way up to 10 you can +write `0...10`.) + Like this: ```rust diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 4193c93c89..695b1614fb 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -56,8 +56,8 @@ To fix this, we have to make sure that step four never happens after step three. The ownership system in Rust does this through a concept called lifetimes, which describe the scope that a reference is valid for. -When we have a function that takes a reference by argument, we can be implicit -or explicit about the lifetime of the reference: +When we have a function that takes an argument by reference, we can be +implicit or explicit about the lifetime of the reference: ```rust // implicit @@ -282,14 +282,12 @@ to it. ## Lifetime Elision -Rust supports powerful local type inference in function bodies, but it’s -forbidden in item signatures to allow reasoning about the types based on -the item signature alone. However, for ergonomic reasons a very restricted -secondary inference algorithm called “lifetime elision” applies in function -signatures. It infers only based on the signature components themselves and not -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 +Rust supports powerful local type inference in the bodies of functions but not in their item signatures. +It's forbidden to allow reasoning about types based on the item signature alone. +However, for ergonomic reasons, a very restricted secondary inference algorithm called +“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely to infer +lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision +acts as 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 diff --git a/src/doc/book/macros.md b/src/doc/book/macros.md index 188abb316a..c16e2ea453 100644 --- a/src/doc/book/macros.md +++ b/src/doc/book/macros.md @@ -337,8 +337,8 @@ fn main() { } ``` -Instead you need to pass the variable name into the invocation, so it’s tagged -with the right syntax context. +Instead you need to pass the variable name into the invocation, so that it’s +tagged with the right syntax context. ```rust macro_rules! foo { @@ -470,7 +470,7 @@ which syntactic form it matches. * `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`. * `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`. * `stmt`: a single statement. Example: `let x = 3`. -* `block`: a brace-delimited sequence of statements. Example: +* `block`: a brace-delimited sequence of statements and optionally an expression. Example: `{ log(error, "hi"); return 12; }`. * `item`: an [item][item]. Examples: `fn foo() { }`; `struct Bar;`. * `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`. diff --git a/src/doc/book/match.md b/src/doc/book/match.md index acffaf4544..d01a20083e 100644 --- a/src/doc/book/match.md +++ b/src/doc/book/match.md @@ -28,18 +28,18 @@ patterns][patterns] that covers all the patterns that are possible here. [patterns]: patterns.html -One of the many advantages of `match` is it enforces ‘exhaustiveness checking’. -For example if we remove the last arm with the underscore `_`, the compiler will +One of the many advantages of `match` is it enforces ‘exhaustiveness checking’. +For example if we remove the last arm with the underscore `_`, the compiler will give us an error: ```text error: non-exhaustive patterns: `_` not covered ``` -Rust is telling us that we forgot a value. The compiler infers from `x` that it -can have any positive 32bit value; for example 1 to 2,147,483,647. The `_` acts +Rust is telling us that we forgot some value. The compiler infers from `x` that it +can have any 32bit integer value; for example -2,147,483,648 to 2,147,483,647. The `_` acts as a 'catch-all', and will catch all possible values that *aren't* specified in -an arm of `match`. As you can see with the previous example, we provide `match` +an arm of `match`. As you can see in the previous example, we provide `match` arms for integers 1-5, if `x` is 6 or any other value, then it is caught by `_`. `match` is also an expression, which means we can use it on the right-hand @@ -58,7 +58,7 @@ let number = match x { }; ``` -Sometimes it’s a nice way of converting something from one type to another; in +Sometimes it’s a nice way of converting something from one type to another; in this example the integers are converted to `String`. # Matching on enums @@ -90,7 +90,7 @@ fn process_message(msg: Message) { Again, the Rust compiler checks exhaustiveness, so it demands that you have a match arm for every variant of the enum. If you leave one off, it -will give you a compile-time error unless you use `_` or provide all possible +will give you a compile-time error unless you use `_` or provide all possible arms. Unlike the previous uses of `match`, you can’t use the normal `if` diff --git a/src/doc/book/no-stdlib.md b/src/doc/book/no-stdlib.md index 610940cde9..43bd0507eb 100644 --- a/src/doc/book/no-stdlib.md +++ b/src/doc/book/no-stdlib.md @@ -38,7 +38,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { // for a bare-bones hello world. These are normally // provided by libstd. #[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } +#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { loop {} } # #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} # #[no_mangle] pub extern fn rust_eh_register_frames () {} # #[no_mangle] pub extern fn rust_eh_unregister_frames () {} @@ -65,7 +65,7 @@ pub extern fn main(argc: i32, argv: *const *const u8) -> i32 { } #[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } +#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { loop {} } # #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} # #[no_mangle] pub extern fn rust_eh_register_frames () {} # #[no_mangle] pub extern fn rust_eh_unregister_frames () {} diff --git a/src/doc/book/ownership.md b/src/doc/book/ownership.md index 70d71c14dd..f8938be30e 100644 --- a/src/doc/book/ownership.md +++ b/src/doc/book/ownership.md @@ -51,7 +51,7 @@ fn foo() { } ``` -When `v` comes into scope, a new [vector] is created on [the stack][stack], +When `v` comes into scope, a new [vector][vectors] is created on [the stack][stack], and it allocates space on [the heap][heap] for its elements. When `v` goes out of scope at the end of `foo()`, Rust will clean up everything related to the vector, even the heap-allocated memory. This happens deterministically, at the @@ -124,7 +124,7 @@ special annotation here, it’s the default thing that Rust does. ## The details The reason that we cannot use a binding after we’ve moved it is subtle, but -important. +important. When we write code like this: @@ -148,7 +148,7 @@ The first line allocates memory for the vector object `v` on the stack like it does for `x` above. But in addition to that it also allocates some memory on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address of this heap allocation to an internal pointer, which is part of the vector -object placed on the stack (let's call it the data pointer). +object placed on the stack (let's call it the data pointer). It is worth pointing out (even at the risk of stating the obvious) that the vector object and its data live in separate memory regions instead of being a @@ -163,7 +163,7 @@ does not create a copy of the heap allocation containing the actual data. Which means that there would be two pointers to the contents of the vector both pointing to the same memory allocation on the heap. It would violate Rust’s safety guarantees by introducing a data race if one could access both -`v` and `v2` at the same time. +`v` and `v2` at the same time. For example if we truncated the vector to just two elements through `v2`: diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md index 7325d44896..7ecfdcfcc1 100644 --- a/src/doc/book/patterns.md +++ b/src/doc/book/patterns.md @@ -1,7 +1,7 @@ % Patterns Patterns are quite common in Rust. We use them in [variable -bindings][bindings], [match statements][match], and other places, too. Let’s go +bindings][bindings], [match expressions][match], and other places, too. Let’s go on a whirlwind tour of all of the things patterns can do! [bindings]: variable-bindings.html diff --git a/src/doc/book/primitive-types.md b/src/doc/book/primitive-types.md index 840609d1dd..69040931de 100644 --- a/src/doc/book/primitive-types.md +++ b/src/doc/book/primitive-types.md @@ -7,7 +7,7 @@ of these ones, as well, but these are the most primitive. # Booleans -Rust has a built in boolean type, named `bool`. It has two values, `true` and `false`: +Rust has a built-in boolean type, named `bool`. It has two values, `true` and `false`: ```rust let x = true; @@ -89,13 +89,13 @@ Unsigned types use a `u` for their category, and signed types use `i`. The `i` is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an eight-bit signed number. -## Fixed size types +## Fixed-size types -Fixed size types have a specific number of bits in their representation. Valid +Fixed-size types have a specific number of bits in their representation. Valid bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer, and `i64` is a signed, 64-bit integer. -## Variable sized types +## Variable-size types Rust also provides types whose size depends on the size of a pointer of the underlying machine. These types have ‘size’ as the category, and come in signed @@ -164,7 +164,7 @@ copying. For example, you might want to reference only one line of a file read into memory. By nature, a slice is not created directly, but from an existing variable binding. Slices have a defined length, can be mutable or immutable. -Internally, slices are represented as a pointer to the beginning of the data +Internally, slices are represented as a pointer to the beginning of the data and a length. ## Slicing syntax diff --git a/src/doc/book/references-and-borrowing.md b/src/doc/book/references-and-borrowing.md index e7faf17460..a08d53f958 100644 --- a/src/doc/book/references-and-borrowing.md +++ b/src/doc/book/references-and-borrowing.md @@ -23,7 +23,7 @@ Before we get to the details, two important notes about the ownership system. Rust has a focus on safety and speed. It accomplishes these goals through many ‘zero-cost abstractions’, which means that in Rust, abstractions cost as little as possible in order to make them work. The ownership system is a prime example -of a zero cost abstraction. All of the analysis we’ll talk about in this guide +of a zero-cost abstraction. All of the analysis we’ll talk about in this guide is _done at compile time_. You do not pay any run-time cost for any of these features. @@ -163,8 +163,8 @@ both at the same time: * exactly one mutable reference (`&mut T`). -You may notice that this is very similar, though not exactly the same as, -to the definition of a data race: +You may notice that this is very similar to, though not exactly the same as, +the definition of a data race: > There is a ‘data race’ when two or more pointers access the same memory > location at the same time, where at least one of them is writing, and the @@ -211,9 +211,10 @@ fn main() { ``` In other words, the mutable borrow is held through the rest of our example. What -we want is for the mutable borrow to end _before_ we try to call `println!` and -make an immutable borrow. In Rust, borrowing is tied to the scope that the -borrow is valid for. And our scopes look like this: +we want is for the mutable borrow by `y` to end so that the resource can be +returned to the owner, `x`. `x` can then provide a immutable borrow to `println!`. +In Rust, borrowing is tied to the scope that the borrow is valid for. And our +scopes look like this: ```rust,ignore let mut x = 5; @@ -378,4 +379,3 @@ statement 1 at 3:14 In the above example, `y` is declared before `x`, meaning that `y` lives longer than `x`, which is not allowed. - diff --git a/src/doc/book/strings.md b/src/doc/book/strings.md index 68c7235975..f5ebceedd3 100644 --- a/src/doc/book/strings.md +++ b/src/doc/book/strings.md @@ -44,7 +44,12 @@ let s = "foo\ assert_eq!("foobar", s); ``` -Rust has more than only `&str`s though. A `String`, is a heap-allocated string. +Note that you normally cannot access a `str` directly, but only through a `&str` +reference. This is because `str` is an unsized type which requires additional +runtime information to be usable. For more information see the chapter on +[unsized types][ut]. + +Rust has more than only `&str`s though. 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. @@ -89,7 +94,7 @@ Viewing a `String` as a `&str` is cheap, but converting the `&str` to a ## Indexing -Because strings are valid UTF-8, strings do not support indexing: +Because strings are valid UTF-8, they do not support indexing: ```rust,ignore let s = "hello"; @@ -185,5 +190,6 @@ let hello_world = hello + &world; This is because `&String` can automatically coerce to a `&str`. This is a feature called ‘[`Deref` coercions][dc]’. +[ut]: unsized-types.html [dc]: deref-coercions.html [connect]: ../std/net/struct.TcpStream.html#method.connect diff --git a/src/doc/book/syntax-index.md b/src/doc/book/syntax-index.md index 6782bdb498..3e889f51f5 100644 --- a/src/doc/book/syntax-index.md +++ b/src/doc/book/syntax-index.md @@ -43,39 +43,40 @@ * `!` (`!expr`): bitwise or logical complement. Overloadable (`Not`). * `!=` (`var != expr`): nonequality comparison. Overloadable (`PartialEq`). * `%` (`expr % expr`): arithmetic remainder. Overloadable (`Rem`). -* `%=` (`var %= expr`): arithmetic remainder & assignment. +* `%=` (`var %= expr`): arithmetic remainder & assignment. Overloadable (`RemAssign`). * `&` (`expr & expr`): bitwise and. Overloadable (`BitAnd`). * `&` (`&expr`): borrow. See [References and Borrowing]. * `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type. See [References and Borrowing]. -* `&=` (`var &= expr`): bitwise and & assignment. +* `&=` (`var &= expr`): bitwise and & assignment. Overloadable (`BitAndAssign`). * `&&` (`expr && expr`): logical and. * `*` (`expr * expr`): arithmetic multiplication. Overloadable (`Mul`). * `*` (`*expr`): dereference. * `*` (`*const type`, `*mut type`): raw pointer. See [Raw Pointers]. -* `*=` (`var *= expr`): arithmetic multiplication & assignment. +* `*=` (`var *= expr`): arithmetic multiplication & assignment. Overloadable (`MulAssign`). * `+` (`expr + expr`): arithmetic addition. Overloadable (`Add`). * `+` (`trait + trait`, `'a + trait`): compound type constraint. See [Traits (Multiple Trait Bounds)]. -* `+=` (`var += expr`): arithmetic addition & assignment. +* `+=` (`var += expr`): arithmetic addition & assignment. Overloadable (`AddAssign`). * `,`: argument and element separator. See [Attributes], [Functions], [Structs], [Generics], [Match], [Closures], [Crates and Modules (Importing Modules with `use`)]. * `-` (`expr - expr`): arithmetic subtraction. Overloadable (`Sub`). * `-` (`- expr`): arithmetic negation. Overloadable (`Neg`). -* `-=` (`var -= expr`): arithmetic subtraction & assignment. +* `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`). * `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures]. * `-> !` (`fn(…) -> !`, `|…| -> !`): diverging function or closure. See [Diverging Functions]. * `.` (`expr.ident`): member access. See [Structs], [Method Syntax]. * `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal. * `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)]. * `..` (`variant(x, ..)`, `struct_type { x, .. }`): "and the rest" pattern binding. See [Patterns (Ignoring bindings)]. -* `...` (`expr ... expr`): inclusive range pattern. See [Patterns (Ranges)]. +* `...` (`...expr`, `expr...expr`) *in an expression*: inclusive range expression. See [Iterators]. +* `...` (`expr...expr`) *in a pattern*: inclusive range pattern. See [Patterns (Ranges)]. * `/` (`expr / expr`): arithmetic division. Overloadable (`Div`). -* `/=` (`var /= expr`): arithmetic division & assignment. +* `/=` (`var /= expr`): arithmetic division & assignment. Overloadable (`DivAssign`). * `:` (`pat: type`, `ident: type`): constraints. See [Variable Bindings], [Functions], [Structs], [Traits]. * `:` (`ident: expr`): struct field initializer. See [Structs]. * `:` (`'a: loop {…}`): loop label. See [Loops (Loops Labels)]. * `;`: statement and item terminator. * `;` (`[…; len]`): part of fixed-size array syntax. See [Primitive Types (Arrays)]. * `<<` (`expr << expr`): left-shift. Overloadable (`Shl`). -* `<<=` (`var <<= expr`): left-shift & assignment. +* `<<=` (`var <<= expr`): left-shift & assignment. Overloadable (`ShlAssign`). * `<` (`expr < expr`): less-than comparison. Overloadable (`PartialOrd`). * `<=` (`var <= expr`): less-than or equal-to comparison. Overloadable (`PartialOrd`). * `=` (`var = expr`, `ident = type`): assignment/equivalence. See [Variable Bindings], [`type` Aliases], generic parameter defaults. @@ -84,14 +85,14 @@ * `>` (`expr > expr`): greater-than comparison. Overloadable (`PartialOrd`). * `>=` (`var >= expr`): greater-than or equal-to comparison. Overloadable (`PartialOrd`). * `>>` (`expr >> expr`): right-shift. Overloadable (`Shr`). -* `>>=` (`var >>= expr`): right-shift & assignment. +* `>>=` (`var >>= expr`): right-shift & assignment. Overloadable (`ShrAssign`). * `@` (`ident @ pat`): pattern binding. See [Patterns (Bindings)]. * `^` (`expr ^ expr`): bitwise exclusive or. Overloadable (`BitXor`). -* `^=` (`var ^= expr`): bitwise exclusive or & assignment. +* `^=` (`var ^= expr`): bitwise exclusive or & assignment. Overloadable (`BitXorAssign`). * `|` (`expr | expr`): bitwise or. Overloadable (`BitOr`). * `|` (`pat | pat`): pattern alternatives. See [Patterns (Multiple patterns)]. * `|` (`|…| expr`): closures. See [Closures]. -* `|=` (`var |= expr`): bitwise or & assignment. +* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`). * `||` (`expr || expr`): logical or. * `_`: "ignored" pattern binding. See [Patterns (Ignoring bindings)]. @@ -205,6 +206,7 @@ [Functions (Early Returns)]: functions.html#early-returns [Functions]: functions.html [Generics]: generics.html +[Iterators]: iterators.html [Lifetimes]: lifetimes.html [Loops (`for`)]: loops.html#for [Loops (`loop`)]: loops.html#loop diff --git a/src/doc/book/testing.md b/src/doc/book/testing.md index d57664bf07..59d07e4f81 100644 --- a/src/doc/book/testing.md +++ b/src/doc/book/testing.md @@ -515,7 +515,3 @@ you add more examples. We haven’t covered all of the details with writing documentation tests. For more, please see the [Documentation chapter](documentation.html). - -One final note: documentation tests *cannot* be run on binary crates. -To see more on file arrangement see the [Crates and -Modules](crates-and-modules.html) section. diff --git a/src/doc/book/traits.md b/src/doc/book/traits.md index 2a16407768..b3b4197924 100644 --- a/src/doc/book/traits.md +++ b/src/doc/book/traits.md @@ -154,7 +154,7 @@ print_area(5); We get a compile-time error: ```text -error: the trait `HasArea` is not implemented for the type `_` [E0277] +error: the trait bound `_ : HasArea` is not satisfied [E0277] ``` ## Trait bounds on generic structs @@ -496,7 +496,7 @@ impl FooBar for Baz { If we forget to implement `Foo`, Rust will tell us: ```text -error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277] +error: the trait bound `main::Baz : main::Foo` is not satisfied [E0277] ``` # Deriving diff --git a/src/doc/book/unsafe.md b/src/doc/book/unsafe.md index ecd196a9f0..af4e351569 100644 --- a/src/doc/book/unsafe.md +++ b/src/doc/book/unsafe.md @@ -4,7 +4,7 @@ Rust’s main draw is its powerful static guarantees about behavior. But safety checks are conservative by nature: there are some programs that are actually safe, but the compiler is not able to verify this is true. To write these kinds of programs, we need to tell the compiler to relax its restrictions a bit. For -this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions +this, Rust has a keyword, `unsafe`. Code using `unsafe` has fewer restrictions than normal code does. Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in diff --git a/src/doc/book/variable-bindings.md b/src/doc/book/variable-bindings.md index 29b59937a6..1c8c03cf67 100644 --- a/src/doc/book/variable-bindings.md +++ b/src/doc/book/variable-bindings.md @@ -18,14 +18,14 @@ function, rather than leaving it off. Otherwise, you’ll get an error. In many languages, a variable binding would be called a *variable*, but Rust’s variable bindings have a few tricks up their sleeves. For example the -left-hand side of a `let` expression is a ‘[pattern][pattern]’, not a +left-hand side of a `let` statement is a ‘[pattern][pattern]’, not a variable name. This means we can do things like: ```rust let (x, y) = (1, 2); ``` -After this expression is evaluated, `x` will be one, and `y` will be two. +After this statement is evaluated, `x` will be one, and `y` will be two. Patterns are really powerful, and have [their own section][pattern] in the book. We don’t need those features for now, so we’ll keep this in the back of our minds as we go forward. diff --git a/src/doc/book/vectors.md b/src/doc/book/vectors.md index f5a543d75b..75e961e4c4 100644 --- a/src/doc/book/vectors.md +++ b/src/doc/book/vectors.md @@ -56,8 +56,8 @@ v[j]; Indexing with a non-`usize` type gives an error that looks like this: ```text -error: the trait `core::ops::Index` is not implemented for the type -`collections::vec::Vec<_>` [E0277] +error: the trait bound `collections::vec::Vec<_> : core::ops::Index` +is not satisfied [E0277] v[j]; ^~~~ note: the type `collections::vec::Vec<_>` cannot be indexed by `i32` @@ -115,6 +115,36 @@ for i in v { } ``` +Note: You cannot use the vector again once you have iterated by taking ownership of the vector. +You can iterate the vector multiple times by taking a reference to the vector whilst iterating. +For example, the following code does not compile. + +```rust,ignore +let v = vec![1, 2, 3, 4, 5]; + +for i in v { + println!("Take ownership of the vector and its element {}", i); +} + +for i in v { + println!("Take ownership of the vector and its element {}", i); +} +``` + +Whereas the following works perfectly, + +```rust +let v = vec![1, 2, 3, 4, 5]; + +for i in &v { + println!("This is a reference to {}", i); +} + +for i in &v { + println!("This is a reference to {}", i); +} +``` + Vectors have many more useful methods, which you can read about in [their API documentation][vec]. diff --git a/src/doc/guide-plugins.md b/src/doc/guide-plugins.md index d6495d02e1..742433b99a 100644 --- a/src/doc/guide-plugins.md +++ b/src/doc/guide-plugins.md @@ -1,4 +1,4 @@ % The (old) Rust Compiler Plugins Guide This content has moved into -[the Rust Programming Language book](book/plugins.html). +[the Rust Programming Language book](book/compiler-plugins.html). diff --git a/src/doc/nomicon/coercions.md b/src/doc/nomicon/coercions.md index 1d2897ce3b..6a9ebd6edf 100644 --- a/src/doc/nomicon/coercions.md +++ b/src/doc/nomicon/coercions.md @@ -64,7 +64,7 @@ fn main() { ``` ```text -:10:5: 10:8 error: the trait `Trait` is not implemented for the type `&mut i32` [E0277] +:10:5: 10:8 error: the trait bound `&mut i32 : Trait` is not satisfied [E0277] :10 foo(t); ^~~ ``` diff --git a/src/doc/nomicon/vec.md b/src/doc/nomicon/vec.md index 63f83788c4..691301946d 100644 --- a/src/doc/nomicon/vec.md +++ b/src/doc/nomicon/vec.md @@ -2,7 +2,7 @@ To bring everything together, we're going to write `std::Vec` from scratch. Because all the best tools for writing unsafe code are unstable, this -project will only work on nightly (as of Rust 1.2.0). With the exception of the +project will only work on nightly (as of Rust 1.9.0). With the exception of the allocator API, much of the unstable code we'll use is expected to be stabilized in a similar form as it is today. diff --git a/src/doc/reference.md b/src/doc/reference.md index 6fb8de7809..fcf9aefaba 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -379,6 +379,10 @@ Examples of integer literals of various forms: 0usize; // type usize ``` +Note that the Rust syntax considers `-1i8` as an application of the [unary minus +operator](#unary-operator-expressions) to an integer literal `1i8`, rather than +a single integer literal. + ##### Floating-point literals A _floating-point literal_ has one of two forms: @@ -1114,6 +1118,16 @@ type Point = (u8, u8); let p: Point = (41, 68); ``` +Currently a type alias to an enum type cannot be used to qualify the +constructors: + +``` +enum E { A } +type F = E; +let _: F = E::A; // OK +// let _: F = F::A; // Doesn't work +``` + ### Structs A _struct_ is a nominal [struct type](#struct-types) defined with the @@ -1191,7 +1205,8 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply called an enum variant. -Enums have a discriminant. You can assign them explicitly: +Each enum value has a _discriminant_ which is an integer associated to it. You +can specify it explicitly: ``` enum Foo { @@ -1199,10 +1214,15 @@ enum Foo { } ``` -If a discriminant isn't assigned, they start at zero, and add one for each +The right hand side of the specification is interpreted as an `isize` value, +but the compiler is allowed to use a smaller type in the actual memory layout. +The [`repr` attribute](#ffi-attributes) can be added in order to change +the type of the right hand side and specify the memory layout. + +If a discriminant isn't specified, they start at zero, and add one for each variant, in order. -You can cast an enum to get this value: +You can cast an enum to get its discriminant: ``` # enum Foo { Bar = 123 } @@ -1885,6 +1905,8 @@ type int8_t = i8; - `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. +- `naked` - The function utilizes a custom ABI or custom inline ASM that requires + epilogue and prologue to be skipped. ### Static-only attributes @@ -2277,6 +2299,10 @@ The currently implemented features of the reference compiler are: `#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax extensions. +* `inclusive_range_syntax` - Allows use of the `a...b` and `...b` syntax for inclusive ranges. + +* `inclusive_range` - Allows use of the types that represent desugared inclusive ranges. + * `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics are inherently unstable and no promise about them is made. @@ -2747,13 +2773,34 @@ let y = 0..10; assert_eq!(x, y); ``` +Similarly, the `...` operator will construct an object of one of the +`std::ops::RangeInclusive` variants. + +``` +# #![feature(inclusive_range_syntax)] +1...2; // std::ops::RangeInclusive +...4; // std::ops::RangeToInclusive +``` + +The following expressions are equivalent. + +``` +# #![feature(inclusive_range_syntax, inclusive_range)] +let x = std::ops::RangeInclusive::NonEmpty {start: 0, end: 10}; +let y = 0...10; + +assert_eq!(x, y); +``` + ### Unary operator expressions Rust defines the following unary operators. They are all written as prefix operators, before the expression they apply to. * `-` - : Negation. May only be applied to numeric types. + : Negation. Signed integer types and floating-point types support negation. It + is an error to apply negation to unsigned types; for example, the compiler + rejects `-1u32`. * `*` : Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location. For pointers to mutable locations, the resulting @@ -3283,6 +3330,10 @@ The primitive types are the following: * The boolean type `bool` with values `true` and `false`. * The machine types (integer and floating-point). * The machine-dependent integer types. +* Arrays +* Tuples +* Slices +* Function pointers #### Machine types @@ -3860,6 +3911,9 @@ 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 in the heap, heap allocations may outlive the frame they are allocated within. +An allocation in the heap is guaranteed to reside at a single location in the +heap for the whole lifetime of the allocation - it will never be relocated as +a result of moving a box value. ### Memory ownership diff --git a/src/doc/style/README.md b/src/doc/style/README.md index 5ab1a1d9c1..8d837d1a1a 100644 --- a/src/doc/style/README.md +++ b/src/doc/style/README.md @@ -53,7 +53,7 @@ This document is broken into four parts: cross-cutting topic, starting with [Ownership and resources](ownership/README.md). -* **[APIs for a changing Rust](changing/README.md)** +* **APIs for a changing Rust** discusses the forward-compatibility hazards, especially those that interact with the pre-1.0 library stabilization process. diff --git a/src/doc/style/features/functions-and-methods/input.md b/src/doc/style/features/functions-and-methods/input.md index 9ea1d21816..9b243bc72e 100644 --- a/src/doc/style/features/functions-and-methods/input.md +++ b/src/doc/style/features/functions-and-methods/input.md @@ -76,7 +76,7 @@ needs to make about its arguments. On the other hand, generics can make it more difficult to read and understand a function's signature. Aim for "natural" parameter types that a neither overly concrete nor overly abstract. See the discussion on -[traits](../../traits/README.md) for more guidance. +[traits](../traits/README.md) for more guidance. #### Minimizing ownership assumptions: diff --git a/src/doc/style/features/traits/generics.md b/src/doc/style/features/traits/generics.md index 26ffda50ac..a09640c305 100644 --- a/src/doc/style/features/traits/generics.md +++ b/src/doc/style/features/traits/generics.md @@ -27,8 +27,7 @@ explicitly implement to be used by this generic function. * _Inference_. Since the type parameters to generic functions can usually be inferred, generic functions can help cut down on verbosity in code where explicit conversions or other method calls would usually be necessary. See the - [overloading/implicits use case](#use-case-limited-overloading-andor-implicit-conversions) - below. + overloading/implicits use case below. * _Precise types_. Because generics give a _name_ to the specific type implementing a trait, it is possible to be precise about places where that exact type is required or produced. For example, a function @@ -51,7 +50,7 @@ explicitly implement to be used by this generic function. a `Vec` contains elements of a single concrete type (and, indeed, the vector representation is specialized to lay these out in line). Sometimes heterogeneous collections are useful; see - [trait objects](#use-case-trait-objects) below. + trait objects below. * _Signature verbosity_. Heavy use of generics can bloat function signatures. **[Ed. note]** This problem may be mitigated by some language improvements; stay tuned. diff --git a/src/doc/style/style/naming/README.md b/src/doc/style/style/naming/README.md index 9d78721ad3..2106f32faf 100644 --- a/src/doc/style/style/naming/README.md +++ b/src/doc/style/style/naming/README.md @@ -101,7 +101,7 @@ The convention for a field `foo: T` is: here may take `&T` or some other type, depending on the context.) Note that this convention is about getters/setters on ordinary data types, *not* -on [builder objects](../ownership/builders.html). +on [builder objects](../../ownership/builders.html). ### Escape hatches [FIXME] diff --git a/src/etc/CONFIGS.md b/src/etc/CONFIGS.md index 74837a06fa..cde7094cec 100644 --- a/src/etc/CONFIGS.md +++ b/src/etc/CONFIGS.md @@ -10,7 +10,3 @@ These are some links to repos with configs which ease the use of rust. * [kate-config](https://github.com/rust-lang/kate-config) * [nano-config](https://github.com/rust-lang/nano-config) * [zsh-config](https://github.com/rust-lang/zsh-config) - -## Community-maintained Configs - -* [.editorconfig](https://gist.github.com/derhuerst/c9d1b9309e308d9851fa) ([what is this?](http://editorconfig.org/)) diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py index e3aa4e688d..a21194962f 100644 --- a/src/etc/platform-intrinsics/generator.py +++ b/src/etc/platform-intrinsics/generator.py @@ -117,7 +117,10 @@ class Void(Type): Type.__init__(self, 0) def compiler_ctor(self): - return 'void()' + return '::VOID' + + def compiler_ctor_ref(self): + return '&' + self.compiler_ctor() def rust_name(self): return '()' @@ -163,10 +166,12 @@ class Signed(Number): def compiler_ctor(self): if self._llvm_bitwidth is None: - return 'i({})'.format(self.bitwidth()) + return '::I{}'.format(self.bitwidth()) else: - return 'i_({}, {})'.format(self.bitwidth(), - self._llvm_bitwidth) + return '::I{}_{}'.format(self.bitwidth(), self._llvm_bitwidth) + + def compiler_ctor_ref(self): + return '&' + self.compiler_ctor() def llvm_name(self): bw = self._llvm_bitwidth or self.bitwidth() @@ -182,10 +187,12 @@ class Unsigned(Number): def compiler_ctor(self): if self._llvm_bitwidth is None: - return 'u({})'.format(self.bitwidth()) + return '::U{}'.format(self.bitwidth()) else: - return 'u_({}, {})'.format(self.bitwidth(), - self._llvm_bitwidth) + return '::U{}_{}'.format(self.bitwidth(), self._llvm_bitwidth) + + def compiler_ctor_ref(self): + return '&' + self.compiler_ctor() def llvm_name(self): bw = self._llvm_bitwidth or self.bitwidth() @@ -200,7 +207,10 @@ class Float(Number): Number.__init__(self, bitwidth) def compiler_ctor(self): - return 'f({})'.format(self.bitwidth()) + return '::F{}'.format(self.bitwidth()) + + def compiler_ctor_ref(self): + return '&' + self.compiler_ctor() def llvm_name(self): return 'f{}'.format(self.bitwidth()) @@ -244,12 +254,16 @@ class Vector(Type): def compiler_ctor(self): if self._bitcast is None: - return 'v({}, {})'.format(self._elem.compiler_ctor(), - self._length) + return '{}x{}'.format(self._elem.compiler_ctor(), + self._length) else: - return 'v_({}, {}, {})'.format(self._elem.compiler_ctor(), - self._bitcast.compiler_ctor(), - self._length) + return '{}x{}_{}'.format(self._elem.compiler_ctor(), + self._length, + self._bitcast.compiler_ctor() + .replace('::', '')) + + def compiler_ctor_ref(self): + return '&' + self.compiler_ctor() def rust_name(self): return '{}x{}'.format(self._elem.rust_name(), self._length) @@ -284,10 +298,14 @@ class Pointer(Type): if self._llvm_elem is None: llvm_elem = 'None' else: - llvm_elem = 'Some({})'.format(self._llvm_elem.compiler_ctor()) - return 'p({}, {}, {})'.format('true' if self._const else 'false', - self._elem.compiler_ctor(), - llvm_elem) + llvm_elem = 'Some({})'.format(self._llvm_elem.compiler_ctor_ref()) + return 'Type::Pointer({}, {}, {})'.format(self._elem.compiler_ctor_ref(), + llvm_elem, + 'true' if self._const else 'false') + + def compiler_ctor_ref(self): + return "{{ static PTR: Type = {}; &PTR }}".format(self.compiler_ctor()) + def rust_name(self): return '*{} {}'.format('const' if self._const else 'mut', @@ -322,8 +340,14 @@ class Aggregate(Type): raise NotImplementedError() def compiler_ctor(self): - return 'agg({}, vec![{}])'.format('true' if self._flatten else 'false', - ', '.join(elem.compiler_ctor() for elem in self._elems)) + parts = "{{ static PARTS: [&'static Type; {}] = [{}]; &PARTS }}" + elems = ', '.join(elem.compiler_ctor_ref() for elem in self._elems) + parts = parts.format(len(self._elems), elems) + return 'Type::Aggregate({}, {})'.format('true' if self._flatten else 'false', + parts) + + def compiler_ctor_ref(self): + return "{{ static AGG: Type = {}; &AGG }}".format(self.compiler_ctor()) def rust_name(self): return '({})'.format(', '.join(elem.rust_name() for elem in self._elems)) @@ -518,10 +542,10 @@ class MonomorphicIntrinsic(object): return self._platform.platform().intrinsic_prefix() + self.intrinsic_suffix() def compiler_args(self): - return ', '.join(arg.compiler_ctor() for arg in self._args_raw) + return ', '.join(arg.compiler_ctor_ref() for arg in self._args_raw) def compiler_ret(self): - return self._ret_raw.compiler_ctor() + return self._ret_raw.compiler_ctor_ref() def compiler_signature(self): return '({}) -> {}'.format(self.compiler_args(), self.compiler_ret()) @@ -691,7 +715,7 @@ def parse_args(): parser.add_argument('-o', '--out', type=argparse.FileType('w'), default=sys.stdout, help = 'File to output to (default stdout).') parser.add_argument('-i', '--info', type=argparse.FileType('r'), - help = 'File containing platform specific information to merge into' + help = 'File containing platform specific information to merge into ' 'the input files\' header.') parser.add_argument('in_', metavar="FILE", type=argparse.FileType('r'), nargs='+', help = 'JSON files to load') @@ -733,24 +757,24 @@ class CompilerDefs(object): #![allow(unused_imports)] -use {{Intrinsic, i, i_, u, u_, f, v, v_, agg, p, void}}; +use {{Intrinsic, Type}}; use IntrinsicDef::Named; -use rustc::middle::ty; // The default inlining settings trigger a pathological behaviour in // LLVM, which causes makes compilation very slow. See #28273. #[inline(never)] -pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option {{ +pub fn find(name: &str) -> Option {{ if !name.starts_with("{0}") {{ return None }} Some(match &name["{0}".len()..] {{'''.format(platform.intrinsic_prefix()) def render(self, mono): return '''\ "{}" => Intrinsic {{ - inputs: vec![{}], + inputs: {{ static INPUTS: [&'static Type; {}] = [{}]; &INPUTS }}, output: {}, definition: Named("{}") }},'''.format(mono.intrinsic_suffix(), + len(mono._args_raw), mono.compiler_args(), mono.compiler_ret(), mono.llvm_name()) diff --git a/src/etc/platform-intrinsics/x86/avx.json b/src/etc/platform-intrinsics/x86/avx.json index 2c1492c295..05a4721aed 100644 --- a/src/etc/platform-intrinsics/x86/avx.json +++ b/src/etc/platform-intrinsics/x86/avx.json @@ -8,6 +8,83 @@ "ret": "f(32-64)", "args": ["0", "0"] }, + { + "intrinsic": "256_blendv_{0.data_type}", + "width": [256], + "llvm": "blendv.{0.data_type}.256", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "256_broadcast_{0.data_type}", + "width": [256], + "llvm": "vbroadcastf128.{0.data_type}.256", + "ret": "f(32-64)", + "args": ["s8SPc"] + }, + { + "intrinsic": "256_cmp_{0.data_type}", + "width": [256], + "llvm": "cmp.{1.data_type}.256", + "ret": "f(32-64)", + "args": ["0", "0", "s8S"] + }, + { + "intrinsic": "256_cvtepi32_pd", + "width": [256], + "llvm": "cvtdq2.pd.256", + "ret": "f64", + "args": ["s32h"] + }, + { + "intrinsic": "256_cvtepi32_ps", + "width": [256], + "llvm": "cvtdq2.ps.256", + "ret": "f32", + "args": ["s32"] + }, + { + "intrinsic": "256_cvtpd_epi32", + "width": [256], + "llvm": "cvt.pd2dq.256", + "ret": "s32h", + "args": ["f64"] + }, + { + "intrinsic": "256_cvtpd_ps", + "width": [256], + "llvm": "cvt.pd2.ps.256", + "ret": "f32h", + "args": ["f64"] + }, + { + "intrinsic": "256_cvtps_epi32", + "width": [256], + "llvm": "cvt.ps2dq.256", + "ret": "s32", + "args": ["f32"] + }, + { + "intrinsic": "256_cvtps_pd", + "width": [256], + "llvm": "cvt.ps2.pd.256", + "ret": "f64", + "args": ["f32h"] + }, + { + "intrinsic": "256_cvttpd_epi32", + "width": [256], + "llvm": "cvtt.pd2dq.256", + "ret": "s32h", + "args": ["f64"] + }, + { + "intrinsic": "256_cvttps_epi32", + "width": [256], + "llvm": "cvtt.ps2dq.256", + "ret": "s32", + "args": ["f32"] + }, { "intrinsic": "256_dp_ps", "width": [256], diff --git a/src/etc/platform-intrinsics/x86/fma.json b/src/etc/platform-intrinsics/x86/fma.json new file mode 100644 index 0000000000..c922d166c8 --- /dev/null +++ b/src/etc/platform-intrinsics/x86/fma.json @@ -0,0 +1,47 @@ +{ + "llvm_prefix": "llvm.x86.fma.", + "intrinsics": [ + { + "intrinsic": "{0.width_mm}_fmadd_{0.data_type}", + "width": [128, 256], + "llvm": "vfmadd.{0.data_type_short}{0.width_suffix}", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "{0.width_mm}_fmaddsub_{0.data_type}", + "width": [128, 256], + "llvm": "vfmaddsub.{0.data_type_short}{0.width_suffix}", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "{0.width_mm}_fmsub_{0.data_type}", + "width": [128, 256], + "llvm": "vfmsub.{0.data_type_short}{0.width_suffix}", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "{0.width_mm}_fmsubadd_{0.data_type}", + "width": [128, 256], + "llvm": "vfmsubadd.{0.data_type_short}{0.width_suffix}", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "{0.width_mm}_fnmadd_{0.data_type}", + "width": [128, 256], + "llvm": "vfnmadd.{0.data_type_short}{0.width_suffix}", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + }, + { + "intrinsic": "{0.width_mm}_fnmsub_{0.data_type}", + "width": [128, 256], + "llvm": "vfnmsub.{0.data_type_short}{0.width_suffix}", + "ret": "f(32-64)", + "args": ["0", "0", "0"] + } + ] +} diff --git a/src/etc/tidy.py b/src/etc/tidy.py index ce774d31b0..9264646673 100644 --- a/src/etc/tidy.py +++ b/src/etc/tidy.py @@ -31,6 +31,7 @@ stable_whitelist = { 'src/libcore', 'src/libstd', 'src/rustc/std_shim', + 'src/rustc/test_shim', 'src/test' } diff --git a/src/etc/unicode.py b/src/etc/unicode.py index 10b864a902..5a7632868e 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -398,7 +398,7 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s); derived = load_properties("DerivedCoreProperties.txt", want_derived) scripts = load_properties("Scripts.txt", []) props = load_properties("PropList.txt", - ["White_Space", "Join_Control", "Noncharacter_Code_Point"]) + ["White_Space", "Join_Control", "Noncharacter_Code_Point", "Pattern_White_Space"]) norm_props = load_properties("DerivedNormalizationProps.txt", ["Full_Composition_Exclusion"]) @@ -408,7 +408,7 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s); # category tables for (name, cat, pfuns) in ("general_category", gencats, ["N", "Cc"]), \ ("derived_property", derived, want_derived), \ - ("property", props, ["White_Space"]): + ("property", props, ["White_Space", "Pattern_White_Space"]): emit_property_module(rf, name, cat, pfuns) # normalizations and conversions module diff --git a/src/jemalloc/COPYING b/src/jemalloc/COPYING index bdda0feb9e..104b1f8b01 100644 --- a/src/jemalloc/COPYING +++ b/src/jemalloc/COPYING @@ -1,10 +1,10 @@ Unless otherwise specified, files in the jemalloc source distribution are subject to the following license: -------------------------------------------------------------------------------- -Copyright (C) 2002-2014 Jason Evans . +Copyright (C) 2002-2016 Jason Evans . All rights reserved. Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. -Copyright (C) 2009-2014 Facebook, Inc. All rights reserved. +Copyright (C) 2009-2016 Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/src/jemalloc/ChangeLog b/src/jemalloc/ChangeLog index d56ee999e6..9cbfbf9636 100644 --- a/src/jemalloc/ChangeLog +++ b/src/jemalloc/ChangeLog @@ -1,10 +1,335 @@ Following are change highlights associated with official releases. Important -bug fixes are all mentioned, but internal enhancements are omitted here for -brevity (even though they are more fun to write about). Much more detail can be -found in the git revision history: +bug fixes are all mentioned, but some internal enhancements are omitted here for +brevity. Much more detail can be found in the git revision history: https://github.com/jemalloc/jemalloc +* 4.1.0 (February 28, 2016) + + This release is primarily about optimizations, but it also incorporates a lot + of portability-motivated refactoring and enhancements. Many people worked on + this release, to an extent that even with the omission here of minor changes + (see git revision history), and of the people who reported and diagnosed + issues, so much of the work was contributed that starting with this release, + changes are annotated with author credits to help reflect the collaborative + effort involved. + + New features: + - Implement decay-based unused dirty page purging, a major optimization with + mallctl API impact. This is an alternative to the existing ratio-based + unused dirty page purging, and is intended to eventually become the sole + purging mechanism. New mallctls: + + opt.purge + + opt.decay_time + + arena..decay + + arena..decay_time + + arenas.decay_time + + stats.arenas..decay_time + (@jasone, @cevans87) + - Add --with-malloc-conf, which makes it possible to embed a default + options string during configuration. This was motivated by the desire to + specify --with-malloc-conf=purge:decay , since the default must remain + purge:ratio until the 5.0.0 release. (@jasone) + - Add MS Visual Studio 2015 support. (@rustyx, @yuslepukhin) + - Make *allocx() size class overflow behavior defined. The maximum + size class is now less than PTRDIFF_MAX to protect applications against + numerical overflow, and all allocation functions are guaranteed to indicate + errors rather than potentially crashing if the request size exceeds the + maximum size class. (@jasone) + - jeprof: + + Add raw heap profile support. (@jasone) + + Add --retain and --exclude for backtrace symbol filtering. (@jasone) + + Optimizations: + - Optimize the fast path to combine various bootstrapping and configuration + checks and execute more streamlined code in the common case. (@interwq) + - Use linear scan for small bitmaps (used for small object tracking). In + addition to speeding up bitmap operations on 64-bit systems, this reduces + allocator metadata overhead by approximately 0.2%. (@djwatson) + - Separate arena_avail trees, which substantially speeds up run tree + operations. (@djwatson) + - Use memoization (boot-time-computed table) for run quantization. Separate + arena_avail trees reduced the importance of this optimization. (@jasone) + - Attempt mmap-based in-place huge reallocation. This can dramatically speed + up incremental huge reallocation. (@jasone) + + Incompatible changes: + - Make opt.narenas unsigned rather than size_t. (@jasone) + + Bug fixes: + - Fix stats.cactive accounting regression. (@rustyx, @jasone) + - Handle unaligned keys in hash(). This caused problems for some ARM systems. + (@jasone, Christopher Ferris) + - Refactor arenas array. In addition to fixing a fork-related deadlock, this + makes arena lookups faster and simpler. (@jasone) + - Move retained memory allocation out of the default chunk allocation + function, to a location that gets executed even if the application installs + a custom chunk allocation function. This resolves a virtual memory leak. + (@buchgr) + - Fix a potential tsd cleanup leak. (Christopher Ferris, @jasone) + - Fix run quantization. In practice this bug had no impact unless + applications requested memory with alignment exceeding one page. + (@jasone, @djwatson) + - Fix LinuxThreads-specific bootstrapping deadlock. (Cosmin Paraschiv) + - jeprof: + + Don't discard curl options if timeout is not defined. (@djwatson) + + Detect failed profile fetches. (@djwatson) + - Fix stats.arenas..{dss,lg_dirty_mult,decay_time,pactive,pdirty} for + --disable-stats case. (@jasone) + +* 4.0.4 (October 24, 2015) + + This bugfix release fixes another xallocx() regression. No other regressions + have come to light in over a month, so this is likely a good starting point + for people who prefer to wait for "dot one" releases with all the major issues + shaken out. + + Bug fixes: + - Fix xallocx(..., MALLOCX_ZERO to zero the last full trailing page of large + allocations that have been randomly assigned an offset of 0 when + --enable-cache-oblivious configure option is enabled. + +* 4.0.3 (September 24, 2015) + + This bugfix release continues the trend of xallocx() and heap profiling fixes. + + Bug fixes: + - Fix xallocx(..., MALLOCX_ZERO) to zero all trailing bytes of large + allocations when --enable-cache-oblivious configure option is enabled. + - Fix xallocx(..., MALLOCX_ZERO) to zero trailing bytes of huge allocations + when resizing from/to a size class that is not a multiple of the chunk size. + - Fix prof_tctx_dump_iter() to filter out nodes that were created after heap + profile dumping started. + - Work around a potentially bad thread-specific data initialization + interaction with NPTL (glibc's pthreads implementation). + +* 4.0.2 (September 21, 2015) + + This bugfix release addresses a few bugs specific to heap profiling. + + Bug fixes: + - Fix ixallocx_prof_sample() to never modify nor create sampled small + allocations. xallocx() is in general incapable of moving small allocations, + so this fix removes buggy code without loss of generality. + - Fix irallocx_prof_sample() to always allocate large regions, even when + alignment is non-zero. + - Fix prof_alloc_rollback() to read tdata from thread-specific data rather + than dereferencing a potentially invalid tctx. + +* 4.0.1 (September 15, 2015) + + This is a bugfix release that is somewhat high risk due to the amount of + refactoring required to address deep xallocx() problems. As a side effect of + these fixes, xallocx() now tries harder to partially fulfill requests for + optional extra space. Note that a couple of minor heap profiling + optimizations are included, but these are better thought of as performance + fixes that were integral to disovering most of the other bugs. + + Optimizations: + - Avoid a chunk metadata read in arena_prof_tctx_set(), since it is in the + fast path when heap profiling is enabled. Additionally, split a special + case out into arena_prof_tctx_reset(), which also avoids chunk metadata + reads. + - Optimize irallocx_prof() to optimistically update the sampler state. The + prior implementation appears to have been a holdover from when + rallocx()/xallocx() functionality was combined as rallocm(). + + Bug fixes: + - Fix TLS configuration such that it is enabled by default for platforms on + which it works correctly. + - Fix arenas_cache_cleanup() and arena_get_hard() to handle + allocation/deallocation within the application's thread-specific data + cleanup functions even after arenas_cache is torn down. + - Fix xallocx() bugs related to size+extra exceeding HUGE_MAXCLASS. + - Fix chunk purge hook calls for in-place huge shrinking reallocation to + specify the old chunk size rather than the new chunk size. This bug caused + no correctness issues for the default chunk purge function, but was + visible to custom functions set via the "arena..chunk_hooks" mallctl. + - Fix heap profiling bugs: + + Fix heap profiling to distinguish among otherwise identical sample sites + with interposed resets (triggered via the "prof.reset" mallctl). This bug + could cause data structure corruption that would most likely result in a + segfault. + + Fix irealloc_prof() to prof_alloc_rollback() on OOM. + + Make one call to prof_active_get_unlocked() per allocation event, and use + the result throughout the relevant functions that handle an allocation + event. Also add a missing check in prof_realloc(). These fixes protect + allocation events against concurrent prof_active changes. + + Fix ixallocx_prof() to pass usize_max and zero to ixallocx_prof_sample() + in the correct order. + + Fix prof_realloc() to call prof_free_sampled_object() after calling + prof_malloc_sample_object(). Prior to this fix, if tctx and old_tctx were + the same, the tctx could have been prematurely destroyed. + - Fix portability bugs: + + Don't bitshift by negative amounts when encoding/decoding run sizes in + chunk header maps. This affected systems with page sizes greater than 8 + KiB. + + Rename index_t to szind_t to avoid an existing type on Solaris. + + Add JEMALLOC_CXX_THROW to the memalign() function prototype, in order to + match glibc and avoid compilation errors when including both + jemalloc/jemalloc.h and malloc.h in C++ code. + + Don't assume that /bin/sh is appropriate when running size_classes.sh + during configuration. + + Consider __sparcv9 a synonym for __sparc64__ when defining LG_QUANTUM. + + Link tests to librt if it contains clock_gettime(2). + +* 4.0.0 (August 17, 2015) + + This version contains many speed and space optimizations, both minor and + major. The major themes are generalization, unification, and simplification. + Although many of these optimizations cause no visible behavior change, their + cumulative effect is substantial. + + New features: + - Normalize size class spacing to be consistent across the complete size + range. By default there are four size classes per size doubling, but this + is now configurable via the --with-lg-size-class-group option. Also add the + --with-lg-page, --with-lg-page-sizes, --with-lg-quantum, and + --with-lg-tiny-min options, which can be used to tweak page and size class + settings. Impacts: + + Worst case performance for incrementally growing/shrinking reallocation + is improved because there are far fewer size classes, and therefore + copying happens less often. + + Internal fragmentation is limited to 20% for all but the smallest size + classes (those less than four times the quantum). (1B + 4 KiB) + and (1B + 4 MiB) previously suffered nearly 50% internal fragmentation. + + Chunk fragmentation tends to be lower because there are fewer distinct run + sizes to pack. + - Add support for explicit tcaches. The "tcache.create", "tcache.flush", and + "tcache.destroy" mallctls control tcache lifetime and flushing, and the + MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to the *allocx() API + control which tcache is used for each operation. + - Implement per thread heap profiling, as well as the ability to + enable/disable heap profiling on a per thread basis. Add the "prof.reset", + "prof.lg_sample", "thread.prof.name", "thread.prof.active", + "opt.prof_thread_active_init", "prof.thread_active_init", and + "thread.prof.active" mallctls. + - Add support for per arena application-specified chunk allocators, configured + via the "arena..chunk_hooks" mallctl. + - Refactor huge allocation to be managed by arenas, so that arenas now + function as general purpose independent allocators. This is important in + the context of user-specified chunk allocators, aside from the scalability + benefits. Related new statistics: + + The "stats.arenas..huge.allocated", "stats.arenas..huge.nmalloc", + "stats.arenas..huge.ndalloc", and "stats.arenas..huge.nrequests" + mallctls provide high level per arena huge allocation statistics. + + The "arenas.nhchunks", "arenas.hchunk..size", + "stats.arenas..hchunks..nmalloc", + "stats.arenas..hchunks..ndalloc", + "stats.arenas..hchunks..nrequests", and + "stats.arenas..hchunks..curhchunks" mallctls provide per size class + statistics. + - Add the 'util' column to malloc_stats_print() output, which reports the + proportion of available regions that are currently in use for each small + size class. + - Add "alloc" and "free" modes for for junk filling (see the "opt.junk" + mallctl), so that it is possible to separately enable junk filling for + allocation versus deallocation. + - Add the jemalloc-config script, which provides information about how + jemalloc was configured, and how to integrate it into application builds. + - Add metadata statistics, which are accessible via the "stats.metadata", + "stats.arenas..metadata.mapped", and + "stats.arenas..metadata.allocated" mallctls. + - Add the "stats.resident" mallctl, which reports the upper limit of + physically resident memory mapped by the allocator. + - Add per arena control over unused dirty page purging, via the + "arenas.lg_dirty_mult", "arena..lg_dirty_mult", and + "stats.arenas..lg_dirty_mult" mallctls. + - Add the "prof.gdump" mallctl, which makes it possible to toggle the gdump + feature on/off during program execution. + - Add sdallocx(), which implements sized deallocation. The primary + optimization over dallocx() is the removal of a metadata read, which often + suffers an L1 cache miss. + - Add missing header includes in jemalloc/jemalloc.h, so that applications + only have to #include . + - Add support for additional platforms: + + Bitrig + + Cygwin + + DragonFlyBSD + + iOS + + OpenBSD + + OpenRISC/or1k + + Optimizations: + - Maintain dirty runs in per arena LRUs rather than in per arena trees of + dirty-run-containing chunks. In practice this change significantly reduces + dirty page purging volume. + - Integrate whole chunks into the unused dirty page purging machinery. This + reduces the cost of repeated huge allocation/deallocation, because it + effectively introduces a cache of chunks. + - Split the arena chunk map into two separate arrays, in order to increase + cache locality for the frequently accessed bits. + - Move small run metadata out of runs, into arena chunk headers. This reduces + run fragmentation, smaller runs reduce external fragmentation for small size + classes, and packed (less uniformly aligned) metadata layout improves CPU + cache set distribution. + - Randomly distribute large allocation base pointer alignment relative to page + boundaries in order to more uniformly utilize CPU cache sets. This can be + disabled via the --disable-cache-oblivious configure option, and queried via + the "config.cache_oblivious" mallctl. + - Micro-optimize the fast paths for the public API functions. + - Refactor thread-specific data to reside in a single structure. This assures + that only a single TLS read is necessary per call into the public API. + - Implement in-place huge allocation growing and shrinking. + - Refactor rtree (radix tree for chunk lookups) to be lock-free, and make + additional optimizations that reduce maximum lookup depth to one or two + levels. This resolves what was a concurrency bottleneck for per arena huge + allocation, because a global data structure is critical for determining + which arenas own which huge allocations. + + Incompatible changes: + - Replace --enable-cc-silence with --disable-cc-silence to suppress spurious + warnings by default. + - Assure that the constness of malloc_usable_size()'s return type matches that + of the system implementation. + - Change the heap profile dump format to support per thread heap profiling, + rename pprof to jeprof, and enhance it with the --thread= option. As a + result, the bundled jeprof must now be used rather than the upstream + (gperftools) pprof. + - Disable "opt.prof_final" by default, in order to avoid atexit(3), which can + internally deadlock on some platforms. + - Change the "arenas.nlruns" mallctl type from size_t to unsigned. + - Replace the "stats.arenas..bins..allocated" mallctl with + "stats.arenas..bins..curregs". + - Ignore MALLOC_CONF in set{uid,gid,cap} binaries. + - Ignore MALLOCX_ARENA(a) in dallocx(), in favor of using the + MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to control tcache usage. + + Removed features: + - Remove the *allocm() API, which is superseded by the *allocx() API. + - Remove the --enable-dss options, and make dss non-optional on all platforms + which support sbrk(2). + - Remove the "arenas.purge" mallctl, which was obsoleted by the + "arena..purge" mallctl in 3.1.0. + - Remove the unnecessary "opt.valgrind" mallctl; jemalloc automatically + detects whether it is running inside Valgrind. + - Remove the "stats.huge.allocated", "stats.huge.nmalloc", and + "stats.huge.ndalloc" mallctls. + - Remove the --enable-mremap option. + - Remove the "stats.chunks.current", "stats.chunks.total", and + "stats.chunks.high" mallctls. + + Bug fixes: + - Fix the cactive statistic to decrease (rather than increase) when active + memory decreases. This regression was first released in 3.5.0. + - Fix OOM handling in memalign() and valloc(). A variant of this bug existed + in all releases since 2.0.0, which introduced these functions. + - Fix an OOM-related regression in arena_tcache_fill_small(), which could + cause cache corruption on OOM. This regression was present in all releases + from 2.2.0 through 3.6.0. + - Fix size class overflow handling for malloc(), posix_memalign(), memalign(), + calloc(), and realloc() when profiling is enabled. + - Fix the "arena..dss" mallctl to return an error if "primary" or + "secondary" precedence is specified, but sbrk(2) is not supported. + - Fix fallback lg_floor() implementations to handle extremely large inputs. + - Ensure the default purgeable zone is after the default zone on OS X. + - Fix latent bugs in atomic_*(). + - Fix the "arena..dss" mallctl to handle read-only calls. + - Fix tls_model configuration to enable the initial-exec model when possible. + - Mark malloc_conf as a weak symbol so that the application can override it. + - Correctly detect glibc's adaptive pthread mutexes. + - Fix the --without-export configure option. + * 3.6.0 (March 31, 2014) This version contains a critical bug fix for a regression present in 3.5.0 and @@ -21,7 +346,7 @@ found in the git revision history: backtracing to be reliable. - Use dss allocation precedence for huge allocations as well as small/large allocations. - - Fix test assertion failure message formatting. This bug did not manifect on + - Fix test assertion failure message formatting. This bug did not manifest on x86_64 systems because of implementation subtleties in va_list. - Fix inconsequential test failures for hash and SFMT code. @@ -516,7 +841,7 @@ found in the git revision history: - Make it possible for the application to manually flush a thread's cache, via the "tcache.flush" mallctl. - Base maximum dirty page count on proportion of active memory. - - Compute various addtional run-time statistics, including per size class + - Compute various additional run-time statistics, including per size class statistics for large objects. - Expose malloc_stats_print(), which can be called repeatedly by the application. diff --git a/src/jemalloc/INSTALL b/src/jemalloc/INSTALL index 9af233693b..5c25054a88 100644 --- a/src/jemalloc/INSTALL +++ b/src/jemalloc/INSTALL @@ -84,6 +84,14 @@ any of the following arguments (not a definitive list) to 'configure': versions of jemalloc can coexist in the same installation directory. For example, libjemalloc.so.0 becomes libjemalloc.so.0. +--with-malloc-conf= + Embed as a run-time options string that is processed prior to + the malloc_conf global variable, the /etc/malloc.conf symlink, and the + MALLOC_CONF environment variable. For example, to change the default chunk + size to 256 KiB: + + --with-malloc-conf=lg_chunk:18 + --disable-cc-silence Disable code that silences non-useful compiler warnings. This is mainly useful during development when auditing the set of warnings that are being @@ -107,15 +115,15 @@ any of the following arguments (not a definitive list) to 'configure': there are interactions between the various coverage targets, so it is usually advisable to run 'make clean' between repeated code coverage runs. ---enable-ivsalloc - Enable validation code, which verifies that pointers reside within - jemalloc-owned chunks before dereferencing them. This incurs a substantial - performance hit. - --disable-stats Disable statistics gathering functionality. See the "opt.stats_print" option documentation for usage details. +--enable-ivsalloc + Enable validation code, which verifies that pointers reside within + jemalloc-owned chunks before dereferencing them. This incurs a minor + performance hit. + --enable-prof Enable heap profiling and leak detection functionality. See the "opt.prof" option documentation for usage details. When enabled, there are several @@ -185,10 +193,106 @@ any of the following arguments (not a definitive list) to 'configure': thread-local variables via the __thread keyword. If TLS is available, jemalloc uses it for several purposes. +--disable-cache-oblivious + Disable cache-oblivious large allocation alignment for large allocation + requests with no alignment constraints. If this feature is disabled, all + large allocations are page-aligned as an implementation artifact, which can + severely harm CPU cache utilization. However, the cache-oblivious layout + comes at the cost of one extra page per large allocation, which in the + most extreme case increases physical memory usage for the 16 KiB size class + to 20 KiB. + --with-xslroot= Specify where to find DocBook XSL stylesheets when building the documentation. +--with-lg-page= + Specify the base 2 log of the system page size. This option is only useful + when cross compiling, since the configure script automatically determines + the host's page size by default. + +--with-lg-page-sizes= + Specify the comma-separated base 2 logs of the page sizes to support. This + option may be useful when cross-compiling in combination with + --with-lg-page, but its primary use case is for integration with FreeBSD's + libc, wherein jemalloc is embedded. + +--with-lg-size-class-group= + Specify the base 2 log of how many size classes to use for each doubling in + size. By default jemalloc uses =2, which results in + e.g. the following size classes: + + [...], 64, + 80, 96, 112, 128, + 160, [...] + + =3 results in e.g. the following size classes: + + [...], 64, + 72, 80, 88, 96, 104, 112, 120, 128, + 144, [...] + + The minimal =0 causes jemalloc to only provide size + classes that are powers of 2: + + [...], + 64, + 128, + 256, + [...] + + An implementation detail currently limits the total number of small size + classes to 255, and a compilation error will result if the + you specify cannot be supported. The limit is + roughly =4, depending on page size. + +--with-lg-quantum= + Specify the base 2 log of the minimum allocation alignment. jemalloc needs + to know the minimum alignment that meets the following C standard + requirement (quoted from the April 12, 2011 draft of the C11 standard): + + The pointer returned if the allocation succeeds is suitably aligned so + that it may be assigned to a pointer to any type of object with a + fundamental alignment requirement and then used to access such an object + or an array of such objects in the space allocated [...] + + This setting is architecture-specific, and although jemalloc includes known + safe values for the most commonly used modern architectures, there is a + wrinkle related to GNU libc (glibc) that may impact your choice of + . On most modern architectures, this mandates 16-byte alignment + (=4), but the glibc developers chose not to meet this + requirement for performance reasons. An old discussion can be found at + https://sourceware.org/bugzilla/show_bug.cgi?id=206 . Unlike glibc, + jemalloc does follow the C standard by default (caveat: jemalloc + technically cheats if --with-lg-tiny-min is smaller than + --with-lg-quantum), but the fact that Linux systems already work around + this allocator noncompliance means that it is generally safe in practice to + let jemalloc's minimum alignment follow glibc's lead. If you specify + --with-lg-quantum=3 during configuration, jemalloc will provide additional + size classes that are not 16-byte-aligned (24, 40, and 56, assuming + --with-lg-size-class-group=2). + +--with-lg-tiny-min= + Specify the base 2 log of the minimum tiny size class to support. Tiny + size classes are powers of 2 less than the quantum, and are only + incorporated if is less than (see + --with-lg-quantum). Tiny size classes technically violate the C standard + requirement for minimum alignment, and crashes could conceivably result if + the compiler were to generate instructions that made alignment assumptions, + both because illegal instruction traps could result, and because accesses + could straddle page boundaries and cause segmentation faults due to + accessing unmapped addresses. + + The default of =3 works well in practice even on architectures + that technically require 16-byte alignment, probably for the same reason + --with-lg-quantum=3 works. Smaller tiny size classes can, and will, cause + crashes (see https://bugzilla.mozilla.org/show_bug.cgi?id=691003 for an + example). + + This option is rarely useful, and is mainly provided as documentation of a + subtle implementation detail. If you do use this option, specify a + value in [3, ..., ]. + The following environment variables (not a definitive list) impact configure's behavior: diff --git a/src/jemalloc/Makefile.in b/src/jemalloc/Makefile.in index 50f6596a6c..f60823f596 100644 --- a/src/jemalloc/Makefile.in +++ b/src/jemalloc/Makefile.in @@ -28,6 +28,7 @@ CFLAGS := @CFLAGS@ LDFLAGS := @LDFLAGS@ EXTRA_LDFLAGS := @EXTRA_LDFLAGS@ LIBS := @LIBS@ +TESTLIBS := @TESTLIBS@ RPATH_EXTRA := @RPATH_EXTRA@ SO := @so@ IMPORTLIB := @importlib@ @@ -48,8 +49,10 @@ cfgoutputs_in := $(addprefix $(srcroot),@cfgoutputs_in@) cfgoutputs_out := @cfgoutputs_out@ enable_autogen := @enable_autogen@ enable_code_coverage := @enable_code_coverage@ +enable_prof := @enable_prof@ enable_valgrind := @enable_valgrind@ enable_zone_allocator := @enable_zone_allocator@ +MALLOC_CONF := @JEMALLOC_CPREFIX@MALLOC_CONF DSO_LDFLAGS = @DSO_LDFLAGS@ SOREV = @SOREV@ PIC_CFLAGS = @PIC_CFLAGS@ @@ -73,16 +76,34 @@ endif LIBJEMALLOC := $(LIBPREFIX)jemalloc$(install_suffix) # Lists of files. -BINS := $(srcroot)bin/pprof $(objroot)bin/jemalloc.sh +BINS := $(objroot)bin/jemalloc-config $(objroot)bin/jemalloc.sh $(objroot)bin/jeprof C_HDRS := $(objroot)include/jemalloc/jemalloc$(install_suffix).h -C_SRCS := $(srcroot)src/jemalloc.c $(srcroot)src/arena.c \ - $(srcroot)src/atomic.c $(srcroot)src/base.c $(srcroot)src/bitmap.c \ - $(srcroot)src/chunk.c $(srcroot)src/chunk_dss.c \ - $(srcroot)src/chunk_mmap.c $(srcroot)src/ckh.c $(srcroot)src/ctl.c \ - $(srcroot)src/extent.c $(srcroot)src/hash.c $(srcroot)src/huge.c \ - $(srcroot)src/mb.c $(srcroot)src/mutex.c $(srcroot)src/prof.c \ - $(srcroot)src/quarantine.c $(srcroot)src/rtree.c $(srcroot)src/stats.c \ - $(srcroot)src/tcache.c $(srcroot)src/util.c $(srcroot)src/tsd.c +C_SRCS := $(srcroot)src/jemalloc.c \ + $(srcroot)src/arena.c \ + $(srcroot)src/atomic.c \ + $(srcroot)src/base.c \ + $(srcroot)src/bitmap.c \ + $(srcroot)src/chunk.c \ + $(srcroot)src/chunk_dss.c \ + $(srcroot)src/chunk_mmap.c \ + $(srcroot)src/ckh.c \ + $(srcroot)src/ctl.c \ + $(srcroot)src/extent.c \ + $(srcroot)src/hash.c \ + $(srcroot)src/huge.c \ + $(srcroot)src/mb.c \ + $(srcroot)src/mutex.c \ + $(srcroot)src/nstime.c \ + $(srcroot)src/pages.c \ + $(srcroot)src/prng.c \ + $(srcroot)src/prof.c \ + $(srcroot)src/quarantine.c \ + $(srcroot)src/rtree.c \ + $(srcroot)src/stats.c \ + $(srcroot)src/tcache.c \ + $(srcroot)src/ticker.c \ + $(srcroot)src/tsd.c \ + $(srcroot)src/util.c ifeq ($(enable_valgrind), 1) C_SRCS += $(srcroot)src/valgrind.c endif @@ -104,24 +125,29 @@ endif PC := $(objroot)jemalloc.pc MAN3 := $(objroot)doc/jemalloc$(install_suffix).3 DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml -DOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.html) -DOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.3) +DOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.html) +DOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(objroot)%.3) DOCS := $(DOCS_HTML) $(DOCS_MAN3) C_TESTLIB_SRCS := $(srcroot)test/src/btalloc.c $(srcroot)test/src/btalloc_0.c \ $(srcroot)test/src/btalloc_1.c $(srcroot)test/src/math.c \ - $(srcroot)test/src/mtx.c $(srcroot)test/src/SFMT.c \ - $(srcroot)test/src/test.c $(srcroot)test/src/thd.c \ - $(srcroot)test/src/timer.c -C_UTIL_INTEGRATION_SRCS := $(srcroot)src/util.c + $(srcroot)test/src/mtx.c $(srcroot)test/src/mq.c \ + $(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \ + $(srcroot)test/src/thd.c $(srcroot)test/src/timer.c +C_UTIL_INTEGRATION_SRCS := $(srcroot)src/nstime.c $(srcroot)src/util.c TESTS_UNIT := $(srcroot)test/unit/atomic.c \ $(srcroot)test/unit/bitmap.c \ $(srcroot)test/unit/ckh.c \ + $(srcroot)test/unit/decay.c \ $(srcroot)test/unit/hash.c \ $(srcroot)test/unit/junk.c \ + $(srcroot)test/unit/junk_alloc.c \ + $(srcroot)test/unit/junk_free.c \ + $(srcroot)test/unit/lg_chunk.c \ $(srcroot)test/unit/mallctl.c \ $(srcroot)test/unit/math.c \ $(srcroot)test/unit/mq.c \ $(srcroot)test/unit/mtx.c \ + $(srcroot)test/unit/prng.c \ $(srcroot)test/unit/prof_accum.c \ $(srcroot)test/unit/prof_active.c \ $(srcroot)test/unit/prof_gdump.c \ @@ -133,8 +159,13 @@ TESTS_UNIT := $(srcroot)test/unit/atomic.c \ $(srcroot)test/unit/quarantine.c \ $(srcroot)test/unit/rb.c \ $(srcroot)test/unit/rtree.c \ + $(srcroot)test/unit/run_quantize.c \ $(srcroot)test/unit/SFMT.c \ + $(srcroot)test/unit/size_classes.c \ + $(srcroot)test/unit/smoothstep.c \ $(srcroot)test/unit/stats.c \ + $(srcroot)test/unit/ticker.c \ + $(srcroot)test/unit/nstime.c \ $(srcroot)test/unit/tsd.c \ $(srcroot)test/unit/util.c \ $(srcroot)test/unit/zero.c @@ -143,6 +174,7 @@ TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \ $(srcroot)test/integration/sdallocx.c \ $(srcroot)test/integration/mallocx.c \ $(srcroot)test/integration/MALLOCX_ARENA.c \ + $(srcroot)test/integration/overflow.c \ $(srcroot)test/integration/posix_memalign.c \ $(srcroot)test/integration/rallocx.c \ $(srcroot)test/integration/thread_arena.c \ @@ -178,10 +210,10 @@ all: build_lib dist: build_doc -$(srcroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl +$(objroot)doc/%.html : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/html.xsl $(XSLTPROC) -o $@ $(objroot)doc/html.xsl $< -$(srcroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl +$(objroot)doc/%.3 : $(objroot)doc/%.xml $(srcroot)doc/stylesheet.xsl $(objroot)doc/manpages.xsl $(XSLTPROC) -o $@ $(objroot)doc/manpages.xsl $< build_doc_html: $(DOCS_HTML) @@ -257,15 +289,15 @@ $(STATIC_LIBS): $(objroot)test/unit/%$(EXE): $(objroot)test/unit/%.$(O) $(TESTS_UNIT_LINK_OBJS) $(C_JET_OBJS) $(C_TESTLIB_UNIT_OBJS) @mkdir -p $(@D) - $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS) + $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(TESTLIBS) $(EXTRA_LDFLAGS) $(objroot)test/integration/%$(EXE): $(objroot)test/integration/%.$(O) $(C_TESTLIB_INTEGRATION_OBJS) $(C_UTIL_INTEGRATION_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) @mkdir -p $(@D) - $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(EXTRA_LDFLAGS) + $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(filter -lpthread,$(LIBS))) -lm $(TESTLIBS) $(EXTRA_LDFLAGS) $(objroot)test/stress/%$(EXE): $(objroot)test/stress/%.$(O) $(C_JET_OBJS) $(C_TESTLIB_STRESS_OBJS) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) @mkdir -p $(@D) - $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(EXTRA_LDFLAGS) + $(CC) $(LDTARGET) $(filter %.$(O),$^) $(call RPATH,$(objroot)lib) $(objroot)lib/$(LIBJEMALLOC).$(IMPORTLIB) $(LDFLAGS) $(filter-out -lm,$(LIBS)) -lm $(TESTLIBS) $(EXTRA_LDFLAGS) build_lib_shared: $(DSOS) build_lib_static: $(STATIC_LIBS) @@ -335,18 +367,27 @@ check_unit_dir: @mkdir -p $(objroot)test/unit check_integration_dir: @mkdir -p $(objroot)test/integration -check_stress_dir: +stress_dir: @mkdir -p $(objroot)test/stress -check_dir: check_unit_dir check_integration_dir check_stress_dir +check_dir: check_unit_dir check_integration_dir check_unit: tests_unit check_unit_dir - $(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%) + $(MALLOC_CONF)="purge:ratio" $(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%) + $(MALLOC_CONF)="purge:decay" $(SHELL) $(objroot)test/test.sh $(TESTS_UNIT:$(srcroot)%.c=$(objroot)%) +check_integration_prof: tests_integration check_integration_dir +ifeq ($(enable_prof), 1) + $(MALLOC_CONF)="prof:true" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) + $(MALLOC_CONF)="prof:true,prof_active:false" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) +endif +check_integration_decay: tests_integration check_integration_dir + $(MALLOC_CONF)="purge:decay,decay_time:-1" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) + $(MALLOC_CONF)="purge:decay,decay_time:0" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) + $(MALLOC_CONF)="purge:decay" $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) check_integration: tests_integration check_integration_dir $(SHELL) $(objroot)test/test.sh $(TESTS_INTEGRATION:$(srcroot)%.c=$(objroot)%) -check_stress: tests_stress check_stress_dir +stress: tests_stress stress_dir $(SHELL) $(objroot)test/test.sh $(TESTS_STRESS:$(srcroot)%.c=$(objroot)%) -check: tests check_dir - $(SHELL) $(objroot)test/test.sh $(TESTS:$(srcroot)%.c=$(objroot)%) +check: check_unit check_integration check_integration_decay check_integration_prof ifeq ($(enable_code_coverage), 1) coverage_unit: check_unit @@ -360,7 +401,7 @@ coverage_integration: check_integration $(SHELL) $(srcroot)coverage.sh $(srcroot)test/src integration $(C_TESTLIB_INTEGRATION_OBJS) $(SHELL) $(srcroot)coverage.sh $(srcroot)test/integration integration $(TESTS_INTEGRATION_OBJS) -coverage_stress: check_stress +coverage_stress: stress $(SHELL) $(srcroot)coverage.sh $(srcroot)src pic $(C_PIC_OBJS) $(SHELL) $(srcroot)coverage.sh $(srcroot)src jet $(C_JET_OBJS) $(SHELL) $(srcroot)coverage.sh $(srcroot)test/src stress $(C_TESTLIB_STRESS_OBJS) @@ -405,7 +446,9 @@ clean: rm -f $(objroot)*.gcov.* distclean: clean + rm -f $(objroot)bin/jemalloc-config rm -f $(objroot)bin/jemalloc.sh + rm -f $(objroot)bin/jeprof rm -f $(objroot)config.log rm -f $(objroot)config.status rm -f $(objroot)config.stamp @@ -414,7 +457,7 @@ distclean: clean relclean: distclean rm -f $(objroot)configure - rm -f $(srcroot)VERSION + rm -f $(objroot)VERSION rm -f $(DOCS_HTML) rm -f $(DOCS_MAN3) diff --git a/src/jemalloc/VERSION b/src/jemalloc/VERSION deleted file mode 100644 index f1e1510d67..0000000000 --- a/src/jemalloc/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.12.0-17867-gdb2939409db26ab4904372c82492cd3488e4c44e diff --git a/src/jemalloc/bin/jemalloc-config.in b/src/jemalloc/bin/jemalloc-config.in new file mode 100644 index 0000000000..b016c8d331 --- /dev/null +++ b/src/jemalloc/bin/jemalloc-config.in @@ -0,0 +1,79 @@ +#!/bin/sh + +usage() { + cat < +Options: + --help | -h : Print usage. + --version : Print jemalloc version. + --revision : Print shared library revision number. + --config : Print configure options used to build jemalloc. + --prefix : Print installation directory prefix. + --bindir : Print binary installation directory. + --datadir : Print data installation directory. + --includedir : Print include installation directory. + --libdir : Print library installation directory. + --mandir : Print manual page installation directory. + --cc : Print compiler used to build jemalloc. + --cflags : Print compiler flags used to build jemalloc. + --cppflags : Print preprocessor flags used to build jemalloc. + --ldflags : Print library flags used to build jemalloc. + --libs : Print libraries jemalloc was linked against. +EOF +} + +prefix="@prefix@" +exec_prefix="@exec_prefix@" + +case "$1" in +--help | -h) + usage + exit 0 + ;; +--version) + echo "@jemalloc_version@" + ;; +--revision) + echo "@rev@" + ;; +--config) + echo "@CONFIG@" + ;; +--prefix) + echo "@PREFIX@" + ;; +--bindir) + echo "@BINDIR@" + ;; +--datadir) + echo "@DATADIR@" + ;; +--includedir) + echo "@INCLUDEDIR@" + ;; +--libdir) + echo "@LIBDIR@" + ;; +--mandir) + echo "@MANDIR@" + ;; +--cc) + echo "@CC@" + ;; +--cflags) + echo "@CFLAGS@" + ;; +--cppflags) + echo "@CPPFLAGS@" + ;; +--ldflags) + echo "@LDFLAGS@ @EXTRA_LDFLAGS@" + ;; +--libs) + echo "@LIBS@" + ;; +*) + usage + exit 1 +esac diff --git a/src/jemalloc/bin/pprof b/src/jemalloc/bin/jeprof.in old mode 100755 new mode 100644 similarity index 96% rename from src/jemalloc/bin/pprof rename to src/jemalloc/bin/jeprof.in index 5a4c6cd71a..42087fcec2 --- a/src/jemalloc/bin/pprof +++ b/src/jemalloc/bin/jeprof.in @@ -40,28 +40,28 @@ # # Examples: # -# % tools/pprof "program" "profile" +# % tools/jeprof "program" "profile" # Enters "interactive" mode # -# % tools/pprof --text "program" "profile" +# % tools/jeprof --text "program" "profile" # Generates one line per procedure # -# % tools/pprof --gv "program" "profile" +# % tools/jeprof --gv "program" "profile" # Generates annotated call-graph and displays via "gv" # -# % tools/pprof --gv --focus=Mutex "program" "profile" +# % tools/jeprof --gv --focus=Mutex "program" "profile" # Restrict to code paths that involve an entry that matches "Mutex" # -# % tools/pprof --gv --focus=Mutex --ignore=string "program" "profile" +# % tools/jeprof --gv --focus=Mutex --ignore=string "program" "profile" # Restrict to code paths that involve an entry that matches "Mutex" # and does not match "string" # -# % tools/pprof --list=IBF_CheckDocid "program" "profile" +# % tools/jeprof --list=IBF_CheckDocid "program" "profile" # Generates disassembly listing of all routines with at least one # sample that match the --list= pattern. The listing is # annotated with the flat and cumulative sample counts at each line. # -# % tools/pprof --disasm=IBF_CheckDocid "program" "profile" +# % tools/jeprof --disasm=IBF_CheckDocid "program" "profile" # Generates disassembly listing of all routines with at least one # sample that match the --disasm= pattern. The listing is # annotated with the flat and cumulative sample counts at each PC value. @@ -72,10 +72,11 @@ use strict; use warnings; use Getopt::Long; +my $JEPROF_VERSION = "@jemalloc_version@"; my $PPROF_VERSION = "2.0"; # These are the object tools we use which can come from a -# user-specified location using --tools, from the PPROF_TOOLS +# user-specified location using --tools, from the JEPROF_TOOLS # environment variable, or from the environment. my %obj_tool_map = ( "objdump" => "objdump", @@ -94,7 +95,7 @@ my @EVINCE = ("evince"); # could also be xpdf or perhaps acroread my @KCACHEGRIND = ("kcachegrind"); my @PS2PDF = ("ps2pdf"); # These are used for dynamic profiles -my @URL_FETCHER = ("curl", "-s"); +my @URL_FETCHER = ("curl", "-s", "--fail"); # These are the web pages that servers need to support for dynamic profiles my $HEAP_PAGE = "/pprof/heap"; @@ -144,13 +145,13 @@ my $sep_address = undef; sub usage_string { return < +jeprof [options] is a space separated list of profile names. -pprof [options] +jeprof [options] is a list of profile files where each file contains the necessary symbol mappings as well as profile data (likely generated with --raw). -pprof [options] +jeprof [options] is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE Each name can be: @@ -161,9 +162,9 @@ pprof [options] $GROWTH_PAGE, $CONTENTION_PAGE, /pprof/wall, $CENSUSPROFILE_PAGE, or /pprof/filteredprofile. For instance: - pprof http://myserver.com:80$HEAP_PAGE + jeprof http://myserver.com:80$HEAP_PAGE If / is omitted, the service defaults to $PROFILE_PAGE (cpu profiling). -pprof --symbols +jeprof --symbols Maps addresses to symbol names. In this mode, stdin should be a list of library mappings, in the same format as is found in the heap- and cpu-profile files (this loosely matches that of /proc/self/maps @@ -202,7 +203,7 @@ Output type: --pdf Generate PDF to stdout --svg Generate SVG to stdout --gif Generate GIF to stdout - --raw Generate symbolized pprof data (useful with remote fetch) + --raw Generate symbolized jeprof data (useful with remote fetch) Heap-Profile Options: --inuse_space Display in-use (mega)bytes [default] @@ -222,12 +223,14 @@ Call-graph Options: --nodefraction= Hide nodes below *total [default=.005] --edgefraction= Hide edges below *total [default=.001] --maxdegree= Max incoming/outgoing edges per node [default=8] - --focus= Focus on nodes matching + --focus= Focus on backtraces with nodes matching --thread= Show profile for thread - --ignore= Ignore nodes matching + --ignore= Ignore backtraces with nodes matching --scale= Set GV scaling [default=0] --heapcheck Make nodes with non-0 object counts (i.e. direct leak generators) more visible + --retain= Retain only nodes that match + --exclude= Exclude all nodes that match Miscellaneous: --tools=[,...] \$PATH for object tool pathnames @@ -236,34 +239,34 @@ Miscellaneous: --version Version information Environment Variables: - PPROF_TMPDIR Profiles directory. Defaults to \$HOME/pprof - PPROF_TOOLS Prefix for object tools pathnames + JEPROF_TMPDIR Profiles directory. Defaults to \$HOME/jeprof + JEPROF_TOOLS Prefix for object tools pathnames Examples: -pprof /bin/ls ls.prof +jeprof /bin/ls ls.prof Enters "interactive" mode -pprof --text /bin/ls ls.prof +jeprof --text /bin/ls ls.prof Outputs one line per procedure -pprof --web /bin/ls ls.prof +jeprof --web /bin/ls ls.prof Displays annotated call-graph in web browser -pprof --gv /bin/ls ls.prof +jeprof --gv /bin/ls ls.prof Displays annotated call-graph via 'gv' -pprof --gv --focus=Mutex /bin/ls ls.prof +jeprof --gv --focus=Mutex /bin/ls ls.prof Restricts to code paths including a .*Mutex.* entry -pprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof +jeprof --gv --focus=Mutex --ignore=string /bin/ls ls.prof Code paths including Mutex but not string -pprof --list=getdir /bin/ls ls.prof +jeprof --list=getdir /bin/ls ls.prof (Per-line) annotated source listing for getdir() -pprof --disasm=getdir /bin/ls ls.prof +jeprof --disasm=getdir /bin/ls ls.prof (Per-PC) annotated disassembly for getdir() -pprof http://localhost:1234/ +jeprof http://localhost:1234/ Enters "interactive" mode -pprof --text localhost:1234 +jeprof --text localhost:1234 Outputs one line per procedure for localhost:1234 -pprof --raw localhost:1234 > ./local.raw -pprof --text ./local.raw +jeprof --raw localhost:1234 > ./local.raw +jeprof --text ./local.raw Fetches a remote profile for later analysis and then analyzes it in text mode. EOF @@ -271,7 +274,8 @@ EOF sub version_string { return < \$main::opt_edgefraction, "maxdegree=i" => \$main::opt_maxdegree, "focus=s" => \$main::opt_focus, - "thread=i" => \$main::opt_thread, + "thread=s" => \$main::opt_thread, "ignore=s" => \$main::opt_ignore, "scale=i" => \$main::opt_scale, "heapcheck" => \$main::opt_heapcheck, + "retain=s" => \$main::opt_retain, + "exclude=s" => \$main::opt_exclude, "inuse_space!" => \$main::opt_inuse_space, "inuse_objects!" => \$main::opt_inuse_objects, "alloc_space!" => \$main::opt_alloc_space, @@ -707,7 +715,8 @@ sub Main() { } if (defined($data->{threads})) { foreach my $thread (sort { $a <=> $b } keys(%{$data->{threads}})) { - if (!defined($main::opt_thread) || $main::opt_thread == $thread) { + if (defined($main::opt_thread) && + ($main::opt_thread eq '*' || $main::opt_thread == $thread)) { my $thread_profile = $data->{threads}{$thread}; FilterAndPrint($thread_profile, $symbols, $libs, $thread); } @@ -801,14 +810,14 @@ sub InteractiveMode { $| = 1; # Make output unbuffered for interactive mode my ($orig_profile, $symbols, $libs, $total) = @_; - print STDERR "Welcome to pprof! For help, type 'help'.\n"; + print STDERR "Welcome to jeprof! For help, type 'help'.\n"; # Use ReadLine if it's installed and input comes from a console. if ( -t STDIN && !ReadlineMightFail() && defined(eval {require Term::ReadLine}) ) { - my $term = new Term::ReadLine 'pprof'; - while ( defined ($_ = $term->readline('(pprof) '))) { + my $term = new Term::ReadLine 'jeprof'; + while ( defined ($_ = $term->readline('(jeprof) '))) { $term->addhistory($_) if /\S/; if (!InteractiveCommand($orig_profile, $symbols, $libs, $total, $_)) { last; # exit when we get an interactive command to quit @@ -816,7 +825,7 @@ sub InteractiveMode { } } else { # don't have readline while (1) { - print STDERR "(pprof) "; + print STDERR "(jeprof) "; $_ = ; last if ! defined $_ ; s/\r//g; # turn windows-looking lines into unix-looking lines @@ -1009,7 +1018,7 @@ sub ProcessProfile { sub InteractiveHelpMessage { print STDERR < "##, + css_extension = if css_file_extension { + format!("", + root_path = page.root_path) + } else { + "".to_owned() + }, content = *t, root_path = page.root_path, ty = page.ty, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 9fd476bfba..3baf22b38e 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -262,9 +262,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { &Default::default()); s.push_str(&format!("{}", Escape(&test))); }); - s.push_str(&highlight::highlight(&text, - Some("rust-example-rendered"), - None)); + s.push_str(&highlight::render_with_highlighting(&text, + Some("rust-example-rendered"), + None)); let output = CString::new(s).unwrap(); hoedown_buffer_puts(ob, output.as_ptr()); }) @@ -607,7 +607,7 @@ mod tests { fn issue_17736() { let markdown = "# title"; format!("{}", Markdown(markdown)); - reset_ids(); + reset_ids(true); } #[test] @@ -615,7 +615,7 @@ mod tests { fn t(input: &str, expect: &str) { let output = format!("{}", Markdown(input)); assert_eq!(output, expect); - reset_ids(); + reset_ids(true); } t("# Foo bar", "\n

\ @@ -654,7 +654,7 @@ mod tests { Panics

"); }; test(); - reset_ids(); + reset_ids(true); test(); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index af6dec8dc8..c585008957 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -56,13 +56,13 @@ use serialize::json::{ToJson, Json, as_json}; use syntax::{abi, ast}; use syntax::feature_gate::UnstableFeatures; use rustc::middle::cstore::LOCAL_CRATE; -use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; use rustc::session::config::get_unstable_features_setting; -use rustc_front::hir; +use rustc::hir; -use clean::{self, SelfTy}; +use clean::{self, SelfTy, Attributes, GetDefId}; use doctree; use fold::DocFolder; use html::escape::Escape; @@ -91,12 +91,20 @@ pub struct Context { /// String representation of how to get back to the root path of the 'doc/' /// folder in terms of a relative URL. pub root_path: String, - /// The path to the crate root source minus the file name. - /// Used for simplifying paths to the highlighted source code files. - pub src_root: PathBuf, /// The current destination folder of where HTML artifacts should be placed. /// This changes as the context descends into the module hierarchy. pub dst: PathBuf, + /// A flag, which when `true`, will render pages which redirect to the + /// real location of an item. This is used to allow external links to + /// publicly reused items to redirect to the right location. + pub render_redirect_pages: bool, + pub shared: Arc, +} + +pub struct SharedContext { + /// The path to the crate root source minus the file name. + /// Used for simplifying paths to the highlighted source code files. + pub src_root: PathBuf, /// This describes the layout of each page, and is not modified after /// creation of the context (contains info like the favicon and added html). pub layout: layout::Layout, @@ -104,15 +112,16 @@ pub struct Context { /// the source files are present in the html rendering, then this will be /// `true`. pub include_sources: bool, - /// A flag, which when turned off, will render pages which redirect to the - /// real location of an item. This is used to allow external links to - /// publicly reused items to redirect to the right location. - pub render_redirect_pages: bool, + /// The local file sources we've emitted and their respective url-paths. + pub local_sources: HashMap, /// All the passes that were run on this crate. pub passes: HashSet, /// The base-URL of the issue tracker for when an item has been tagged with /// an issue number. pub issue_tracker_base_url: Option, + /// The given user css file which allow to customize the generated + /// documentation theme. + pub css_file_extension: Option, } /// Indicates where an external crate can be found. @@ -142,9 +151,7 @@ pub struct Impl { impl Impl { fn trait_did(&self) -> Option { - self.impl_.trait_.as_ref().and_then(|tr| { - if let clean::ResolvedPath { did, .. } = *tr {Some(did)} else {None} - }) + self.impl_.trait_.def_id() } } @@ -245,8 +252,7 @@ pub struct Cache { parent_stack: Vec, parent_is_trait_impl: bool, search_index: Vec, - privmod: bool, - remove_priv: bool, + stripped_mod: bool, access_levels: AccessLevels, deref_trait_did: Option, @@ -260,10 +266,8 @@ pub struct Cache { /// Helper struct to render all source code to HTML pages struct SourceCollector<'a> { - cx: &'a mut Context, + scx: &'a mut SharedContext, - /// Processed source-file paths - seen: HashSet, /// Root destination to place all HTML output into dst: PathBuf, } @@ -374,14 +378,20 @@ fn init_ids() -> HashMap { "deref-methods", "implementations", "derived_implementations" - ].into_iter().map(|id| (String::from(*id), 1)).collect::>() + ].into_iter().map(|id| (String::from(*id), 1)).collect() } /// This method resets the local table of used ID attributes. This is typically /// used at the beginning of rendering an entire HTML page to reset from the /// previous state (if any). -pub fn reset_ids() { - USED_ID_MAP.with(|s| *s.borrow_mut() = init_ids()); +pub fn reset_ids(embedded: bool) { + USED_ID_MAP.with(|s| { + *s.borrow_mut() = if embedded { + init_ids() + } else { + HashMap::new() + }; + }); } pub fn derive_id(candidate: String) -> String { @@ -404,17 +414,18 @@ pub fn derive_id(candidate: String) -> String { pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: PathBuf, - passes: HashSet) -> Result<(), Error> { + passes: HashSet, + css_file_extension: Option) -> Result<(), Error> { let src_root = match krate.src.parent() { Some(p) => p.to_path_buf(), None => PathBuf::new(), }; - let mut cx = Context { - dst: dst, + let mut scx = SharedContext { src_root: src_root, passes: passes, - current: Vec::new(), - root_path: String::new(), + include_sources: true, + local_sources: HashMap::new(), + issue_tracker_base_url: None, layout: layout::Layout { logo: "".to_string(), favicon: "".to_string(), @@ -422,52 +433,53 @@ pub fn run(mut krate: clean::Crate, krate: krate.name.clone(), playground_url: "".to_string(), }, - include_sources: true, - render_redirect_pages: false, - issue_tracker_base_url: None, + css_file_extension: css_file_extension.clone(), }; - try_err!(mkdir(&cx.dst), &cx.dst); - // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML - let default: &[_] = &[]; - match krate.module.as_ref().map(|m| m.doc_list().unwrap_or(default)) { - Some(attrs) => { - for attr in attrs { - match *attr { - clean::NameValue(ref x, ref s) - if "html_favicon_url" == *x => { - cx.layout.favicon = s.to_string(); - } - clean::NameValue(ref x, ref s) - if "html_logo_url" == *x => { - cx.layout.logo = s.to_string(); - } - clean::NameValue(ref x, ref s) - if "html_playground_url" == *x => { - cx.layout.playground_url = s.to_string(); - markdown::PLAYGROUND_KRATE.with(|slot| { - if slot.borrow().is_none() { - let name = krate.name.clone(); - *slot.borrow_mut() = Some(Some(name)); - } - }); - } - clean::NameValue(ref x, ref s) - if "issue_tracker_base_url" == *x => { - cx.issue_tracker_base_url = Some(s.to_string()); - } - clean::Word(ref x) - if "html_no_source" == *x => { - cx.include_sources = false; - } - _ => {} + if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list("doc")) { + for attr in attrs { + match *attr { + clean::NameValue(ref x, ref s) + if "html_favicon_url" == *x => { + scx.layout.favicon = s.to_string(); + } + clean::NameValue(ref x, ref s) + if "html_logo_url" == *x => { + scx.layout.logo = s.to_string(); + } + clean::NameValue(ref x, ref s) + if "html_playground_url" == *x => { + scx.layout.playground_url = s.to_string(); + markdown::PLAYGROUND_KRATE.with(|slot| { + if slot.borrow().is_none() { + let name = krate.name.clone(); + *slot.borrow_mut() = Some(Some(name)); + } + }); } + clean::NameValue(ref x, ref s) + if "issue_tracker_base_url" == *x => { + scx.issue_tracker_base_url = Some(s.to_string()); + } + clean::Word(ref x) + if "html_no_source" == *x => { + scx.include_sources = false; + } + _ => {} } } - None => {} } + try_err!(mkdir(&dst), &dst); + krate = render_sources(&dst, &mut scx, krate)?; + let cx = Context { + current: Vec::new(), + root_path: String::new(), + dst: dst, + render_redirect_pages: false, + shared: Arc::new(scx), + }; // Crawl the crate to build various caches used for the output let analysis = ::ANALYSISKEY.with(|a| a.clone()); @@ -491,8 +503,7 @@ pub fn run(mut krate: clean::Crate, parent_is_trait_impl: false, extern_locations: HashMap::new(), primitive_locations: HashMap::new(), - remove_priv: cx.passes.contains("strip-private"), - privmod: false, + stripped_mod: false, access_levels: access_levels, orphan_methods: Vec::new(), traits: mem::replace(&mut krate.external_traits, HashMap::new()), @@ -538,8 +549,7 @@ pub fn run(mut krate: clean::Crate, CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone()); CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear()); - try!(write_shared(&cx, &krate, &*cache, index)); - let krate = try!(render_sources(&mut cx, krate)); + write_shared(&cx, &krate, &*cache, index)?; // And finally render the whole crate's documentation cx.krate(krate) @@ -632,53 +642,65 @@ fn write_shared(cx: &Context, // Add all the static files. These may already exist, but we just // overwrite them anyway to make sure that they're fresh and up-to-date. - try!(write(cx.dst.join("jquery.js"), - include_bytes!("static/jquery-2.1.4.min.js"))); - try!(write(cx.dst.join("main.js"), - include_bytes!("static/main.js"))); - try!(write(cx.dst.join("playpen.js"), - include_bytes!("static/playpen.js"))); - try!(write(cx.dst.join("rustdoc.css"), - include_bytes!("static/rustdoc.css"))); - try!(write(cx.dst.join("main.css"), - include_bytes!("static/styles/main.css"))); - try!(write(cx.dst.join("normalize.css"), - include_bytes!("static/normalize.css"))); - try!(write(cx.dst.join("FiraSans-Regular.woff"), - include_bytes!("static/FiraSans-Regular.woff"))); - try!(write(cx.dst.join("FiraSans-Medium.woff"), - include_bytes!("static/FiraSans-Medium.woff"))); - try!(write(cx.dst.join("FiraSans-LICENSE.txt"), - include_bytes!("static/FiraSans-LICENSE.txt"))); - try!(write(cx.dst.join("Heuristica-Italic.woff"), - include_bytes!("static/Heuristica-Italic.woff"))); - try!(write(cx.dst.join("Heuristica-LICENSE.txt"), - include_bytes!("static/Heuristica-LICENSE.txt"))); - try!(write(cx.dst.join("SourceSerifPro-Regular.woff"), - include_bytes!("static/SourceSerifPro-Regular.woff"))); - try!(write(cx.dst.join("SourceSerifPro-Bold.woff"), - include_bytes!("static/SourceSerifPro-Bold.woff"))); - try!(write(cx.dst.join("SourceSerifPro-LICENSE.txt"), - include_bytes!("static/SourceSerifPro-LICENSE.txt"))); - try!(write(cx.dst.join("SourceCodePro-Regular.woff"), - include_bytes!("static/SourceCodePro-Regular.woff"))); - try!(write(cx.dst.join("SourceCodePro-Semibold.woff"), - include_bytes!("static/SourceCodePro-Semibold.woff"))); - try!(write(cx.dst.join("SourceCodePro-LICENSE.txt"), - include_bytes!("static/SourceCodePro-LICENSE.txt"))); - try!(write(cx.dst.join("LICENSE-MIT.txt"), - include_bytes!("static/LICENSE-MIT.txt"))); - try!(write(cx.dst.join("LICENSE-APACHE.txt"), - include_bytes!("static/LICENSE-APACHE.txt"))); - try!(write(cx.dst.join("COPYRIGHT.txt"), - include_bytes!("static/COPYRIGHT.txt"))); + + write(cx.dst.join("jquery.js"), + include_bytes!("static/jquery-2.1.4.min.js"))?; + write(cx.dst.join("main.js"), + include_bytes!("static/main.js"))?; + write(cx.dst.join("playpen.js"), + include_bytes!("static/playpen.js"))?; + write(cx.dst.join("rustdoc.css"), + include_bytes!("static/rustdoc.css"))?; + write(cx.dst.join("main.css"), + include_bytes!("static/styles/main.css"))?; + if let Some(ref css) = cx.shared.css_file_extension { + let mut content = String::new(); + let css = css.as_path(); + let mut f = try_err!(File::open(css), css); + + try_err!(f.read_to_string(&mut content), css); + let css = cx.dst.join("theme.css"); + let css = css.as_path(); + let mut f = try_err!(File::create(css), css); + try_err!(write!(f, "{}", &content), css); + } + write(cx.dst.join("normalize.css"), + include_bytes!("static/normalize.css"))?; + write(cx.dst.join("FiraSans-Regular.woff"), + include_bytes!("static/FiraSans-Regular.woff"))?; + write(cx.dst.join("FiraSans-Medium.woff"), + include_bytes!("static/FiraSans-Medium.woff"))?; + write(cx.dst.join("FiraSans-LICENSE.txt"), + include_bytes!("static/FiraSans-LICENSE.txt"))?; + write(cx.dst.join("Heuristica-Italic.woff"), + include_bytes!("static/Heuristica-Italic.woff"))?; + write(cx.dst.join("Heuristica-LICENSE.txt"), + include_bytes!("static/Heuristica-LICENSE.txt"))?; + write(cx.dst.join("SourceSerifPro-Regular.woff"), + include_bytes!("static/SourceSerifPro-Regular.woff"))?; + write(cx.dst.join("SourceSerifPro-Bold.woff"), + include_bytes!("static/SourceSerifPro-Bold.woff"))?; + write(cx.dst.join("SourceSerifPro-LICENSE.txt"), + include_bytes!("static/SourceSerifPro-LICENSE.txt"))?; + write(cx.dst.join("SourceCodePro-Regular.woff"), + include_bytes!("static/SourceCodePro-Regular.woff"))?; + write(cx.dst.join("SourceCodePro-Semibold.woff"), + include_bytes!("static/SourceCodePro-Semibold.woff"))?; + write(cx.dst.join("SourceCodePro-LICENSE.txt"), + include_bytes!("static/SourceCodePro-LICENSE.txt"))?; + write(cx.dst.join("LICENSE-MIT.txt"), + include_bytes!("static/LICENSE-MIT.txt"))?; + write(cx.dst.join("LICENSE-APACHE.txt"), + include_bytes!("static/LICENSE-APACHE.txt"))?; + write(cx.dst.join("COPYRIGHT.txt"), + include_bytes!("static/COPYRIGHT.txt"))?; fn collect(path: &Path, krate: &str, key: &str) -> io::Result> { let mut ret = Vec::new(); if path.exists() { - for line in BufReader::new(try!(File::open(path))).lines() { - let line = try!(line); + for line in BufReader::new(File::open(path)?).lines() { + let line = line?; if !line.starts_with(key) { continue } @@ -761,20 +783,17 @@ fn write_shared(cx: &Context, Ok(()) } -fn render_sources(cx: &mut Context, +fn render_sources(dst: &Path, scx: &mut SharedContext, krate: clean::Crate) -> Result { info!("emitting source files"); - let dst = cx.dst.join("src"); + let dst = dst.join("src"); try_err!(mkdir(&dst), &dst); let dst = dst.join(&krate.name); try_err!(mkdir(&dst), &dst); let mut folder = SourceCollector { dst: dst, - seen: HashSet::new(), - cx: cx, + scx: scx, }; - // skip all invalid spans - folder.seen.insert("".to_string()); Ok(folder.fold_crate(krate)) } @@ -838,42 +857,33 @@ fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation { // Failing that, see if there's an attribute specifying where to find this // external crate - for attr in &e.attrs { - match *attr { - clean::List(ref x, ref list) if "doc" == *x => { - for attr in list { - match *attr { - clean::NameValue(ref x, ref s) - if "html_root_url" == *x => { - if s.ends_with("/") { - return Remote(s.to_string()); - } - return Remote(format!("{}/", s)); - } - _ => {} - } - } - } - _ => {} + e.attrs.list("doc").value("html_root_url").map(|url| { + let mut url = url.to_owned(); + if !url.ends_with("/") { + url.push('/') } - } - - // Well, at least we tried. - return Unknown; + Remote(url) + }).unwrap_or(Unknown) // Well, at least we tried. } impl<'a> DocFolder for SourceCollector<'a> { fn fold_item(&mut self, item: clean::Item) -> Option { // If we're including source files, and we haven't seen this file yet, // then we need to render it out to the filesystem - if self.cx.include_sources && !self.seen.contains(&item.source.filename) { + if self.scx.include_sources + // skip all invalid spans + && item.source.filename != "" + // macros from other libraries get special filenames which we can + // safely ignore + && !(item.source.filename.starts_with("<") + && item.source.filename.ends_with("macros>")) { // If it turns out that we couldn't read this file, then we probably // can't read any of the files (generating html output from json or // something like that), so just don't include sources for the // entire crate. The other option is maintaining this mapping on a // per-file basis, but that's probably not worth it... - self.cx + self.scx .include_sources = match self.emit_source(&item.source.filename) { Ok(()) => true, Err(e) => { @@ -884,9 +894,7 @@ impl<'a> DocFolder for SourceCollector<'a> { false } }; - self.seen.insert(item.source.filename.clone()); } - self.fold_item_recur(item) } } @@ -895,19 +903,14 @@ impl<'a> SourceCollector<'a> { /// Renders the given filename into its corresponding HTML source file. fn emit_source(&mut self, filename: &str) -> io::Result<()> { let p = PathBuf::from(filename); + if self.scx.local_sources.contains_key(&p) { + // We've already emitted this source + return Ok(()); + } - // If we couldn't open this file, then just returns because it - // probably means that it's some standard library macro thing and we - // can't have the source to it anyway. let mut contents = Vec::new(); - match File::open(&p).and_then(|mut f| f.read_to_end(&mut contents)) { - Ok(r) => r, - // macros from other libraries get special filenames which we can - // safely ignore - Err(..) if filename.starts_with("<") && - filename.ends_with("macros>") => return Ok(()), - Err(e) => return Err(e) - }; + File::open(&p).and_then(|mut f| f.read_to_end(&mut contents))?; + let contents = str::from_utf8(&contents).unwrap(); // Remove the utf-8 BOM if any @@ -920,17 +923,21 @@ impl<'a> SourceCollector<'a> { // Create the intermediate directories let mut cur = self.dst.clone(); let mut root_path = String::from("../../"); - clean_srcpath(&self.cx.src_root, &p, false, |component| { + let mut href = String::new(); + clean_srcpath(&self.scx.src_root, &p, false, |component| { cur.push(component); mkdir(&cur).unwrap(); root_path.push_str("../"); + href.push_str(component); + href.push('/'); }); - let mut fname = p.file_name().expect("source has no filename") .to_os_string(); fname.push(".html"); cur.push(&fname[..]); - let mut w = BufWriter::new(try!(File::create(&cur))); + href.push_str(&fname.to_string_lossy()); + + let mut w = BufWriter::new(File::create(&cur)?); let title = format!("{} -- source", cur.file_name().unwrap() .to_string_lossy()); let desc = format!("Source to the Rust file `{}`.", filename); @@ -939,25 +946,28 @@ impl<'a> SourceCollector<'a> { ty: "source", root_path: &root_path, description: &desc, - keywords: get_basic_keywords(), + keywords: BASIC_KEYWORDS, }; - try!(layout::render(&mut w, &self.cx.layout, - &page, &(""), &Source(contents))); - try!(w.flush()); - return Ok(()); + layout::render(&mut w, &self.scx.layout, + &page, &(""), &Source(contents), + self.scx.css_file_extension.is_some())?; + w.flush()?; + self.scx.local_sources.insert(p, href); + Ok(()) } } impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option { - // If this is a private module, we don't want it in the search index. - let orig_privmod = match item.inner { - clean::ModuleItem(..) => { - let prev = self.privmod; - self.privmod = prev || (self.remove_priv && item.visibility != Some(hir::Public)); + // If this is a stripped module, + // we don't want it or its children in the search index. + let orig_stripped_mod = match item.inner { + clean::StrippedItem(box clean::ModuleItem(..)) => { + let prev = self.stripped_mod; + self.stripped_mod = true; prev } - _ => self.privmod, + _ => self.stripped_mod, }; // Register any generics to their corresponding string. This is used @@ -983,21 +993,19 @@ impl DocFolder for Cache { // Collect all the implementors of traits. if let clean::ImplItem(ref i) = item.inner { - match i.trait_ { - Some(clean::ResolvedPath{ did, .. }) => { - self.implementors.entry(did).or_insert(vec![]).push(Implementor { - def_id: item.def_id, - stability: item.stability.clone(), - impl_: i.clone(), - }); - } - Some(..) | None => {} + if let Some(did) = i.trait_.def_id() { + self.implementors.entry(did).or_insert(vec![]).push(Implementor { + def_id: item.def_id, + stability: item.stability.clone(), + impl_: i.clone(), + }); } } // Index this method for searching later on if let Some(ref s) = item.name { let (parent, is_method) = match item.inner { + clean::StrippedItem(..) => ((None, None), false), clean::AssociatedConstItem(..) | clean::TypedefItem(_, true) if self.parent_is_trait_impl => { // skip associated items in trait impls @@ -1036,13 +1044,9 @@ impl DocFolder for Cache { } _ => ((None, Some(&*self.stack)), false) }; - let hidden_field = match item.inner { - clean::StructFieldItem(clean::HiddenStructField) => true, - _ => false - }; match parent { - (parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => { + (parent, Some(path)) if is_method || (!self.stripped_mod) => { // Needed to determine `self` type. let parent_basename = self.parent_stack.first().and_then(|parent| { match self.paths.get(parent) { @@ -1050,7 +1054,11 @@ impl DocFolder for Cache { _ => None } }); + debug_assert!(!item.is_stripped()); + // A crate has a module at its root, containing all items, + // which should not be indexed. The crate-item itself is + // inserted later on when serializing the search-index. if item.def_id.index != CRATE_DEF_INDEX { self.search_index.push(IndexItem { ty: shortty(&item), @@ -1063,7 +1071,7 @@ impl DocFolder for Cache { }); } } - (Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> { + (Some(parent), None) if is_method || (!self.stripped_mod)=> { if parent.is_local() { // We have a parent, but we don't know where they're // defined yet. Wait for later to index this item. @@ -1075,18 +1083,19 @@ impl DocFolder for Cache { } // Keep track of the fully qualified path for this item. - let pushed = if item.name.is_some() { - let n = item.name.as_ref().unwrap(); - if !n.is_empty() { + let pushed = match item.name { + Some(ref n) if !n.is_empty() => { self.stack.push(n.to_string()); true - } else { false } - } else { false }; + } + _ => false, + }; + match item.inner { clean::StructItem(..) | clean::EnumItem(..) | clean::TypedefItem(..) | clean::TraitItem(..) | clean::FunctionItem(..) | clean::ModuleItem(..) | - clean::ForeignFunctionItem(..) if !self.privmod => { + clean::ForeignFunctionItem(..) if !self.stripped_mod => { // Reexported items mean that the same id can show up twice // in the rustdoc ast that we're looking at. We know, // however, that a reexported item doesn't show up in the @@ -1104,7 +1113,7 @@ impl DocFolder for Cache { } // link variants to their parent enum because pages aren't emitted // for each variant - clean::VariantItem(..) if !self.privmod => { + clean::VariantItem(..) if !self.stripped_mod => { let mut stack = self.stack.clone(); stack.pop(); self.paths.insert(item.def_id, (stack, ItemType::Enum)); @@ -1150,64 +1159,44 @@ impl DocFolder for Cache { // Once we've recursively found all the generics, then hoard off all the // implementations elsewhere - let ret = match self.fold_item_recur(item) { - Some(item) => { - match item { - clean::Item{ attrs, inner: clean::ImplItem(i), .. } => { - // extract relevant documentation for this impl - let dox = match attrs.into_iter().find(|a| { - match *a { - clean::NameValue(ref x, _) - if "doc" == *x => { - true - } - _ => false - } - }) { - Some(clean::NameValue(_, dox)) => Some(dox), - Some(..) | None => None, - }; - - // Figure out the id of this impl. This may map to a - // primitive rather than always to a struct/enum. - let did = match i.for_ { - clean::ResolvedPath { did, .. } | - clean::BorrowedRef { - type_: box clean::ResolvedPath { did, .. }, .. - } => { - Some(did) - } - - ref t => { - t.primitive_type().and_then(|t| { - self.primitive_locations.get(&t).map(|n| { - let id = t.to_def_index(); - DefId { krate: *n, index: id } - }) - }) - } - }; - - if let Some(did) = did { - self.impls.entry(did).or_insert(vec![]).push(Impl { - impl_: i, - dox: dox, - stability: item.stability.clone(), - }); - } + let ret = self.fold_item_recur(item).and_then(|item| { + if let clean::Item { attrs, inner: clean::ImplItem(i), .. } = item { + // Figure out the id of this impl. This may map to a + // primitive rather than always to a struct/enum. + let did = match i.for_ { + clean::ResolvedPath { did, .. } | + clean::BorrowedRef { + type_: box clean::ResolvedPath { did, .. }, .. + } => { + Some(did) + } - None + ref t => { + t.primitive_type().and_then(|t| { + self.primitive_locations.get(&t).map(|n| { + let id = t.to_def_index(); + DefId { krate: *n, index: id } + }) + }) } + }; - i => Some(i), + if let Some(did) = did { + self.impls.entry(did).or_insert(vec![]).push(Impl { + impl_: i, + dox: attrs.value("doc").map(|s|s.to_owned()), + stability: item.stability.clone(), + }); } + None + } else { + Some(item) } - i => i, - }; + }); if pushed { self.stack.pop().unwrap(); } if parent_pushed { self.parent_stack.pop().unwrap(); } - self.privmod = orig_privmod; + self.stripped_mod = orig_stripped_mod; self.parent_is_trait_impl = orig_parent_is_trait_impl; return ret; } @@ -1264,15 +1253,12 @@ impl Context { // render the crate documentation let mut work = vec!((self, item)); - loop { - match work.pop() { - Some((mut cx, item)) => try!(cx.item(item, |cx, item| { - work.push((cx.clone(), item)); - })), - None => break, - } - } + while let Some((mut cx, item)) = work.pop() { + cx.item(item, |cx, item| { + work.push((cx.clone(), item)) + })? + } Ok(()) } @@ -1301,16 +1287,12 @@ impl Context { } title.push_str(" - Rust"); let tyname = shortty(it).to_static_str(); - let is_crate = match it.inner { - clean::ModuleItem(clean::Module { items: _, is_crate: true }) => true, - _ => false - }; - let desc = if is_crate { + let desc = if it.is_crate() { format!("API documentation for the Rust `{}` crate.", - cx.layout.krate) + cx.shared.layout.krate) } else { format!("API documentation for the Rust `{}` {} in crate `{}`.", - it.name.as_ref().unwrap(), tyname, cx.layout.krate) + it.name.as_ref().unwrap(), tyname, cx.shared.layout.krate) }; let keywords = make_item_keywords(it); let page = layout::Page { @@ -1321,89 +1303,82 @@ impl Context { keywords: &keywords, }; - reset_ids(); + reset_ids(true); // We have a huge number of calls to write, so try to alleviate some // of the pain by using a buffered writer instead of invoking the // write syscall all the time. let mut writer = BufWriter::new(w); if !cx.render_redirect_pages { - try!(layout::render(&mut writer, &cx.layout, &page, - &Sidebar{ cx: cx, item: it }, - &Item{ cx: cx, item: it })); + layout::render(&mut writer, &cx.shared.layout, &page, + &Sidebar{ cx: cx, item: it }, + &Item{ cx: cx, item: it }, + cx.shared.css_file_extension.is_some())?; } else { let mut url = repeat("../").take(cx.current.len()) .collect::(); - match cache().paths.get(&it.def_id) { - Some(&(ref names, _)) => { - for name in &names[..names.len() - 1] { - url.push_str(name); - url.push_str("/"); - } - url.push_str(&item_path(it)); - try!(layout::redirect(&mut writer, &url)); + if let Some(&(ref names, _)) = cache().paths.get(&it.def_id) { + for name in &names[..names.len() - 1] { + url.push_str(name); + url.push_str("/"); } - None => {} + url.push_str(&item_path(it)); + layout::redirect(&mut writer, &url)?; } } writer.flush() } - // Private modules may survive the strip-private pass if they - // contain impls for public types. These modules can also + // Stripped modules survive the rustdoc passes (i.e. `strip-private`) + // if they contain impls for public types. These modules can also // contain items such as publicly reexported structures. // // External crates will provide links to these structures, so - // these modules are recursed into, but not rendered normally (a - // flag on the context). + // these modules are recursed into, but not rendered normally + // (a flag on the context). if !self.render_redirect_pages { - self.render_redirect_pages = self.ignore_private_item(&item); + self.render_redirect_pages = self.maybe_ignore_item(&item); } - match item.inner { + if item.is_mod() { // modules are special because they add a namespace. We also need to // recurse into the items of the module as well. - clean::ModuleItem(..) => { - let name = item.name.as_ref().unwrap().to_string(); - let mut item = Some(item); - self.recurse(name, |this| { - let item = item.take().unwrap(); - let joint_dst = this.dst.join("index.html"); - let dst = try_err!(File::create(&joint_dst), &joint_dst); - try_err!(render(dst, this, &item, false), &joint_dst); - - let m = match item.inner { - clean::ModuleItem(m) => m, - _ => unreachable!() - }; - - // render sidebar-items.js used throughout this module - { - let items = this.build_sidebar_items(&m); - let js_dst = this.dst.join("sidebar-items.js"); - let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst)); - try_err!(write!(&mut js_out, "initSidebarItems({});", - as_json(&items)), &js_dst); - } + let name = item.name.as_ref().unwrap().to_string(); + let mut item = Some(item); + self.recurse(name, |this| { + let item = item.take().unwrap(); + let joint_dst = this.dst.join("index.html"); + let dst = try_err!(File::create(&joint_dst), &joint_dst); + try_err!(render(dst, this, &item, false), &joint_dst); - for item in m.items { - f(this,item); - } - Ok(()) - }) - } + let m = match item.inner { + clean::StrippedItem(box clean::ModuleItem(m)) | + clean::ModuleItem(m) => m, + _ => unreachable!() + }; - // Things which don't have names (like impls) don't get special - // pages dedicated to them. - _ if item.name.is_some() => { - let joint_dst = self.dst.join(&item_path(&item)); + // render sidebar-items.js used throughout this module + { + let items = this.build_sidebar_items(&m); + let js_dst = this.dst.join("sidebar-items.js"); + let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst)); + try_err!(write!(&mut js_out, "initSidebarItems({});", + as_json(&items)), &js_dst); + } - let dst = try_err!(File::create(&joint_dst), &joint_dst); - try_err!(render(dst, self, &item, true), &joint_dst); + for item in m.items { + f(this,item); + } Ok(()) - } + }) + } else if item.name.is_some() { + let joint_dst = self.dst.join(&item_path(&item)); - _ => Ok(()) + let dst = try_err!(File::create(&joint_dst), &joint_dst); + try_err!(render(dst, self, &item, true), &joint_dst); + Ok(()) + } else { + Ok(()) } } @@ -1411,7 +1386,7 @@ impl Context { // BTreeMap instead of HashMap to get a sorted output let mut map = BTreeMap::new(); for item in &m.items { - if self.ignore_private_item(item) { continue } + if self.maybe_ignore_item(item) { continue } let short = shortty(item).to_static_str(); let myname = match item.name { @@ -1429,27 +1404,18 @@ impl Context { return map; } - fn ignore_private_item(&self, it: &clean::Item) -> bool { + fn maybe_ignore_item(&self, it: &clean::Item) -> bool { match it.inner { + clean::StrippedItem(..) => true, clean::ModuleItem(ref m) => { - (m.items.is_empty() && - it.doc_value().is_none() && - it.visibility != Some(hir::Public)) || - (self.passes.contains("strip-private") && it.visibility != Some(hir::Public)) - } - clean::PrimitiveItem(..) => it.visibility != Some(hir::Public), + it.doc_value().is_none() && m.items.is_empty() && it.visibility != Some(hir::Public) + }, _ => false, } } } impl<'a> Item<'a> { - fn ismodule(&self) -> bool { - match self.item.inner { - clean::ModuleItem(..) => true, _ => false - } - } - /// Generate a url appropriate for an `href` attribute back to the source of /// this item. /// @@ -1459,7 +1425,7 @@ impl<'a> Item<'a> { /// If `None` is returned, then a source link couldn't be generated. This /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. - fn href(&self, cx: &Context) -> Option { + fn href(&self) -> Option { let href = if self.item.source.loline == self.item.source.hiline { format!("{}", self.item.source.loline) } else { @@ -1492,25 +1458,14 @@ impl<'a> Item<'a> { // know the span, so we plow forward and generate a proper url. The url // has anchors for the line numbers that we're linking to. } else if self.item.def_id.is_local() { - let mut path = Vec::new(); - clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename), - true, |component| { - path.push(component.to_string()); - }); - - // If the span points into an external macro the - // source-file will be bogus, i.e `` - let filename = &self.item.source.filename; - if !(filename.starts_with("<") && filename.ends_with("macros>")) { - Some(format!("{root}src/{krate}/{path}.html#{href}", - root = self.cx.root_path, - krate = self.cx.layout.krate, - path = path.join("/"), - href = href)) - } else { - None - } - + let path = PathBuf::from(&self.item.source.filename); + self.cx.shared.local_sources.get(&path).map(|path| { + format!("{root}src/{krate}/{path}#{href}", + root = self.cx.root_path, + krate = self.cx.shared.layout.krate, + path = path, + href = href) + }) // If this item is not part of the local crate, then things get a little // trickier. We don't actually know the span of the external item, but // we know that the documentation on the other end knows the span! @@ -1542,19 +1497,20 @@ impl<'a> Item<'a> { impl<'a> fmt::Display for Item<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + debug_assert!(!self.item.is_stripped()); // Write the breadcrumb trail header for the top - try!(write!(fmt, "\n

")); + write!(fmt, "\n

")?; match self.item.inner { clean::ModuleItem(ref m) => if m.is_crate { - try!(write!(fmt, "Crate ")); + write!(fmt, "Crate ")?; } else { - try!(write!(fmt, "Module ")); + write!(fmt, "Module ")?; }, - clean::FunctionItem(..) => try!(write!(fmt, "Function ")), - clean::TraitItem(..) => try!(write!(fmt, "Trait ")), - clean::StructItem(..) => try!(write!(fmt, "Struct ")), - clean::EnumItem(..) => try!(write!(fmt, "Enum ")), - clean::PrimitiveItem(..) => try!(write!(fmt, "Primitive Type ")), + clean::FunctionItem(..) => write!(fmt, "Function ")?, + clean::TraitItem(..) => write!(fmt, "Trait ")?, + clean::StructItem(..) => write!(fmt, "Struct ")?, + clean::EnumItem(..) => write!(fmt, "Enum ")?, + clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?, _ => {} } let is_primitive = match self.item.inner { @@ -1563,25 +1519,25 @@ impl<'a> fmt::Display for Item<'a> { }; if !is_primitive { let cur = &self.cx.current; - let amt = if self.ismodule() { cur.len() - 1 } else { cur.len() }; + let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() }; for (i, component) in cur.iter().enumerate().take(amt) { - try!(write!(fmt, "{}::", - repeat("../").take(cur.len() - i - 1) - .collect::(), - component)); + write!(fmt, "{}::", + repeat("../").take(cur.len() - i - 1) + .collect::(), + component)?; } } - try!(write!(fmt, "{}", - shortty(self.item), self.item.name.as_ref().unwrap())); + write!(fmt, "{}", + shortty(self.item), self.item.name.as_ref().unwrap())?; - try!(write!(fmt, "")); // in-band - try!(write!(fmt, "")); - try!(write!(fmt, - r##" - - [] - - "##)); + write!(fmt, "")?; // in-band + write!(fmt, "")?; + write!(fmt, + r##" + + [] + + "##)?; // Write `src` tag // @@ -1589,20 +1545,17 @@ impl<'a> fmt::Display for Item<'a> { // [src] link in the downstream documentation will actually come back to // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. - if self.cx.include_sources && !is_primitive { - match self.href(self.cx) { - Some(l) => { - try!(write!(fmt, "[src]", - self.item.def_id.index.as_usize(), l, "goto source code")); - } - None => {} + if self.cx.shared.include_sources && !is_primitive { + if let Some(l) = self.href() { + write!(fmt, "[src]", + self.item.def_id.index.as_usize(), l, "goto source code")?; } } - try!(write!(fmt, "")); // out-of-band + write!(fmt, "")?; // out-of-band - try!(write!(fmt, "

\n")); + write!(fmt, "

\n")?; match self.item.inner { clean::ModuleItem(ref m) => { @@ -1625,15 +1578,12 @@ impl<'a> fmt::Display for Item<'a> { } fn item_path(item: &clean::Item) -> String { - match item.inner { - clean::ModuleItem(..) => { - format!("{}/index.html", item.name.as_ref().unwrap()) - } - _ => { - format!("{}.{}.html", - shortty(item).to_static_str(), - *item.name.as_ref().unwrap()) - } + if item.is_mod() { + format!("{}/index.html", item.name.as_ref().unwrap()) + } else { + format!("{}.{}.html", + shortty(item).to_static_str(), + *item.name.as_ref().unwrap()) } } @@ -1663,20 +1613,20 @@ fn plain_summary_line(s: Option<&str>) -> String { fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result { if let Some(s) = short_stability(item, cx, true) { - try!(write!(w, "
{}
", s)); + write!(w, "
{}
", s)?; } if let Some(s) = item.doc_value() { - try!(write!(w, "
{}
", Markdown(s))); + write!(w, "
{}
", Markdown(s))?; } Ok(()) } fn item_module(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, items: &[clean::Item]) -> fmt::Result { - try!(document(w, cx, item)); + document(w, cx, item)?; let mut indices = (0..items.len()).filter(|i| { - !cx.ignore_private_item(&items[*i]) + !cx.maybe_ignore_item(&items[*i]) }).collect::>(); // the order of item types in the listing @@ -1720,6 +1670,9 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, let mut curty = None; for &idx in &indices { let myitem = &items[idx]; + if myitem.is_stripped() { + continue; + } let myty = Some(shortty(myitem)); if curty == Some(ItemType::ExternCrate) && myty == Some(ItemType::Import) { @@ -1727,7 +1680,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, curty = myty; } else if myty != curty { if curty.is_some() { - try!(write!(w, "")); + write!(w, "")?; } curty = myty; let (short, name) = match myty.unwrap() { @@ -1751,31 +1704,31 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, ItemType::AssociatedType => ("associated-types", "Associated Types"), ItemType::AssociatedConst => ("associated-consts", "Associated Constants"), }; - try!(write!(w, "

\ - {name}

\n", - id = derive_id(short.to_owned()), name = name)); + write!(w, "

\ + {name}

\n
", + id = derive_id(short.to_owned()), name = name)?; } match myitem.inner { clean::ExternCrateItem(ref name, ref src) => { match *src { Some(ref src) => { - try!(write!(w, "")); + write!(w, "")?; } clean::ImportItem(ref import) => { - try!(write!(w, "", - VisSpace(myitem.visibility), *import)); + write!(w, "", + VisSpace(&myitem.visibility), *import)?; } _ => { @@ -1786,22 +1739,21 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, String::new() }; let doc_value = myitem.doc_value().unwrap_or(""); - try!(write!(w, " - - - - - ", - name = *myitem.name.as_ref().unwrap(), - stab_docs = stab_docs, - docs = shorter(Some(&Markdown(doc_value).to_string())), - class = shortty(myitem), - stab = myitem.stability_class(), - href = item_path(myitem), - title = full_path(cx, myitem))); + write!(w, " + + + + ", + name = *myitem.name.as_ref().unwrap(), + stab_docs = stab_docs, + docs = shorter(Some(&Markdown(doc_value).to_string())), + class = shortty(myitem), + stab = myitem.stability_class(), + href = item_path(myitem), + title = full_path(cx, myitem))?; } } } @@ -1810,7 +1762,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Option { - let mut result = item.stability.as_ref().and_then(|stab| { + item.stability.as_ref().and_then(|stab| { let reason = if show_reason && !stab.reason.is_empty() { format!(": {}", stab.reason) } else { @@ -1825,7 +1777,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio format!("Deprecated{}{}", since, Markdown(&reason)) } else if stab.level == stability::Unstable { let unstable_extra = if show_reason { - match (!stab.feature.is_empty(), &cx.issue_tracker_base_url, stab.issue) { + match (!stab.feature.is_empty(), &cx.shared.issue_tracker_base_url, stab.issue) { (true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 => format!(" ({} #{})", Escape(&stab.feature), tracker_url, issue_no, issue_no), @@ -1845,10 +1797,8 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio }; Some(format!("{}", item.stability_class(), text)) - }); - - if result.is_none() { - result = item.deprecation.as_ref().and_then(|depr| { + }).or_else(|| { + item.deprecation.as_ref().and_then(|depr| { let note = if show_reason && !depr.note.is_empty() { format!(": {}", depr.note) } else { @@ -1862,10 +1812,8 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio let text = format!("Deprecated{}{}", since, Markdown(¬e)); Some(format!("{}", text)) - }); - } - - result + }) + }) } struct Initializer<'a>(&'a str); @@ -1874,51 +1822,52 @@ impl<'a> fmt::Display for Initializer<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let Initializer(s) = *self; if s.is_empty() { return Ok(()); } - try!(write!(f, " = ")); + write!(f, " = ")?; write!(f, "{}", s) } } fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, c: &clean::Constant) -> fmt::Result { - try!(write!(w, "
{vis}const \
-                    {name}: {typ}{init}
", - vis = VisSpace(it.visibility), + write!(w, "
{vis}const \
+               {name}: {typ}{init}
", + vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), typ = c.type_, - init = Initializer(&c.expr))); + init = Initializer(&c.expr))?; document(w, cx, it) } fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Static) -> fmt::Result { - try!(write!(w, "
{vis}static {mutability}\
-                    {name}: {typ}{init}
", - vis = VisSpace(it.visibility), + write!(w, "
{vis}static {mutability}\
+               {name}: {typ}{init}
", + vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), typ = s.type_, - init = Initializer(&s.expr))); + init = Initializer(&s.expr))?; document(w, cx, it) } fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, f: &clean::Function) -> fmt::Result { + // FIXME(#24111): remove when `const_fn` is stabilized let vis_constness = match get_unstable_features_setting() { UnstableFeatures::Allow => f.constness, _ => hir::Constness::NotConst }; - try!(write!(w, "
{vis}{constness}{unsafety}{abi}fn \
-                    {name}{generics}{decl}{where_clause}
", - vis = VisSpace(it.visibility), + write!(w, "
{vis}{constness}{unsafety}{abi}fn \
+               {name}{generics}{decl}{where_clause}
", + vis = VisSpace(&it.visibility), constness = ConstnessSpace(vis_constness), unsafety = UnsafetySpace(f.unsafety), abi = AbiSpace(f.abi), name = it.name.as_ref().unwrap(), generics = f.generics, where_clause = WhereClause(&f.generics), - decl = f.decl)); - try!(render_stability_since_raw(w, it.stable_since(), None)); + decl = f.decl)?; + render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it) } @@ -1937,179 +1886,196 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } // Output the trait definition - try!(write!(w, "
{}{}trait {}{}{}{} ",
-                  VisSpace(it.visibility),
-                  UnsafetySpace(t.unsafety),
-                  it.name.as_ref().unwrap(),
-                  t.generics,
-                  bounds,
-                  WhereClause(&t.generics)));
-
-    let types = t.items.iter().filter(|m| {
-        match m.inner { clean::AssociatedTypeItem(..) => true, _ => false }
-    }).collect::>();
-    let consts = t.items.iter().filter(|m| {
-        match m.inner { clean::AssociatedConstItem(..) => true, _ => false }
-    }).collect::>();
-    let required = t.items.iter().filter(|m| {
-        match m.inner { clean::TyMethodItem(_) => true, _ => false }
-    }).collect::>();
-    let provided = t.items.iter().filter(|m| {
-        match m.inner { clean::MethodItem(_) => true, _ => false }
-    }).collect::>();
+    write!(w, "
{}{}trait {}{}{}{} ",
+           VisSpace(&it.visibility),
+           UnsafetySpace(t.unsafety),
+           it.name.as_ref().unwrap(),
+           t.generics,
+           bounds,
+           WhereClause(&t.generics))?;
+
+    let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>();
+    let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>();
+    let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>();
+    let provided = t.items.iter().filter(|m| m.is_method()).collect::>();
 
     if t.items.is_empty() {
-        try!(write!(w, "{{ }}"));
+        write!(w, "{{ }}")?;
     } else {
-        try!(write!(w, "{{\n"));
+        write!(w, "{{\n")?;
         for t in &types {
-            try!(write!(w, "    "));
-            try!(render_assoc_item(w, t, AssocItemLink::Anchor));
-            try!(write!(w, ";\n"));
+            write!(w, "    ")?;
+            render_assoc_item(w, t, AssocItemLink::Anchor)?;
+            write!(w, ";\n")?;
         }
         if !types.is_empty() && !consts.is_empty() {
-            try!(w.write_str("\n"));
+            w.write_str("\n")?;
         }
         for t in &consts {
-            try!(write!(w, "    "));
-            try!(render_assoc_item(w, t, AssocItemLink::Anchor));
-            try!(write!(w, ";\n"));
+            write!(w, "    ")?;
+            render_assoc_item(w, t, AssocItemLink::Anchor)?;
+            write!(w, ";\n")?;
         }
         if !consts.is_empty() && !required.is_empty() {
-            try!(w.write_str("\n"));
+            w.write_str("\n")?;
         }
         for m in &required {
-            try!(write!(w, "    "));
-            try!(render_assoc_item(w, m, AssocItemLink::Anchor));
-            try!(write!(w, ";\n"));
+            write!(w, "    ")?;
+            render_assoc_item(w, m, AssocItemLink::Anchor)?;
+            write!(w, ";\n")?;
         }
         if !required.is_empty() && !provided.is_empty() {
-            try!(w.write_str("\n"));
+            w.write_str("\n")?;
         }
         for m in &provided {
-            try!(write!(w, "    "));
-            try!(render_assoc_item(w, m, AssocItemLink::Anchor));
-            try!(write!(w, " {{ ... }}\n"));
+            write!(w, "    ")?;
+            render_assoc_item(w, m, AssocItemLink::Anchor)?;
+            write!(w, " {{ ... }}\n")?;
         }
-        try!(write!(w, "}}"));
+        write!(w, "}}")?;
     }
-    try!(write!(w, "
")); + write!(w, "
")?; // Trait documentation - try!(document(w, cx, it)); + document(w, cx, it)?; fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item) -> fmt::Result { let name = m.name.as_ref().unwrap(); let id = derive_id(format!("{}.{}", shortty(m), name)); - try!(write!(w, "

", - id = id, - stab = m.stability_class())); - try!(render_assoc_item(w, m, AssocItemLink::Anchor)); - try!(write!(w, "")); - try!(render_stability_since(w, m, t)); - try!(write!(w, "

")); - try!(document(w, cx, m)); + write!(w, "

", + id = id, + stab = m.stability_class())?; + render_assoc_item(w, m, AssocItemLink::Anchor)?; + write!(w, "")?; + render_stability_since(w, m, t)?; + write!(w, "

")?; + document(w, cx, m)?; Ok(()) } if !types.is_empty() { - try!(write!(w, " + write!(w, "

Associated Types

- ")); + ")?; for t in &types { - try!(trait_item(w, cx, *t, it)); + trait_item(w, cx, *t, it)?; } - try!(write!(w, "
")); + write!(w, "")?; } if !consts.is_empty() { - try!(write!(w, " + write!(w, "

Associated Constants

- ")); + ")?; for t in &consts { - try!(trait_item(w, cx, *t, it)); + trait_item(w, cx, *t, it)?; } - try!(write!(w, "
")); + write!(w, "")?; } // Output the documentation for each function individually if !required.is_empty() { - try!(write!(w, " + write!(w, "

Required Methods

- ")); + ")?; for m in &required { - try!(trait_item(w, cx, *m, it)); + trait_item(w, cx, *m, it)?; } - try!(write!(w, "
")); + write!(w, "")?; } if !provided.is_empty() { - try!(write!(w, " + write!(w, "

Provided Methods

- ")); + ")?; for m in &provided { - try!(trait_item(w, cx, *m, it)); + trait_item(w, cx, *m, it)?; } - try!(write!(w, "
")); + write!(w, "")?; } // If there are methods directly on this trait object, render them here. - try!(render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)); + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?; let cache = cache(); - try!(write!(w, " + write!(w, "

Implementors

    - ")); + ")?; match cache.implementors.get(&it.def_id) { Some(implementors) => { for i in implementors { - try!(writeln!(w, "
  • {}
  • ", i.impl_)); + writeln!(w, "
  • {}
  • ", i.impl_)?; } } None => {} } - try!(write!(w, "
")); - try!(write!(w, r#""#, - root_path = vec![".."; cx.current.len()].join("/"), - path = if it.def_id.is_local() { - cx.current.join("/") - } else { - let path = &cache.external_paths[&it.def_id]; - path[..path.len() - 1].join("/") - }, - ty = shortty(it).to_static_str(), - name = *it.name.as_ref().unwrap())); + write!(w, "")?; + write!(w, r#""#, + root_path = vec![".."; cx.current.len()].join("/"), + path = if it.def_id.is_local() { + cx.current.join("/") + } else { + let path = &cache.external_paths[&it.def_id]; + path[..path.len() - 1].join("/") + }, + ty = shortty(it).to_static_str(), + name = *it.name.as_ref().unwrap())?; Ok(()) } -fn assoc_const(w: &mut fmt::Formatter, it: &clean::Item, - ty: &clean::Type, default: Option<&String>) - -> fmt::Result { - try!(write!(w, "const {}", it.name.as_ref().unwrap())); - try!(write!(w, ": {}", ty)); +fn naive_assoc_href(it: &clean::Item, link: AssocItemLink) -> String { + use html::item_type::ItemType::*; + + let name = it.name.as_ref().unwrap(); + let ty = match shortty(it) { + Typedef | AssociatedType => AssociatedType, + s@_ => s, + }; + + let anchor = format!("#{}.{}", ty, name); + match link { + AssocItemLink::Anchor => anchor, + AssocItemLink::GotoSource(did, _) => { + href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) + } + } +} + +fn assoc_const(w: &mut fmt::Formatter, + it: &clean::Item, + ty: &clean::Type, + default: Option<&String>, + link: AssocItemLink) -> fmt::Result { + write!(w, "const {}", + naive_assoc_href(it, link), + it.name.as_ref().unwrap())?; + + write!(w, ": {}", ty)?; if let Some(default) = default { - try!(write!(w, " = {}", default)); + write!(w, " = {}", default)?; } Ok(()) } fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, bounds: &Vec, - default: &Option) - -> fmt::Result { - try!(write!(w, "type {}", it.name.as_ref().unwrap())); + default: Option<&clean::Type>, + link: AssocItemLink) -> fmt::Result { + write!(w, "type {}", + naive_assoc_href(it, link), + it.name.as_ref().unwrap())?; if !bounds.is_empty() { - try!(write!(w, ": {}", TyParamBounds(bounds))) + write!(w, ": {}", TyParamBounds(bounds))? } - if let Some(ref default) = *default { - try!(write!(w, " = {}", default)); + if let Some(default) = default { + write!(w, " = {}", default)?; } Ok(()) } @@ -2117,17 +2083,12 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, fn render_stability_since_raw<'a>(w: &mut fmt::Formatter, ver: Option<&'a str>, containing_ver: Option<&'a str>) -> fmt::Result { - if containing_ver != ver { - match ver { - Some(v) => - if v.len() > 0 { - try!(write!(w, "{}", - v)) - }, - None => {} + if let Some(v) = ver { + if containing_ver != ver && v.len() > 0 { + write!(w, "{}", + v)? } } - Ok(()) } @@ -2137,10 +2098,11 @@ fn render_stability_since(w: &mut fmt::Formatter, render_stability_since_raw(w, item.stable_since(), containing_item.stable_since()) } -fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, +fn render_assoc_item(w: &mut fmt::Formatter, + item: &clean::Item, link: AssocItemLink) -> fmt::Result { fn method(w: &mut fmt::Formatter, - it: &clean::Item, + meth: &clean::Item, unsafety: hir::Unsafety, constness: hir::Constness, abi: abi::Abi, @@ -2151,14 +2113,23 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, -> fmt::Result { use syntax::abi::Abi; - let name = it.name.as_ref().unwrap(); - let anchor = format!("#{}.{}", shortty(it), name); + let name = meth.name.as_ref().unwrap(); + let anchor = format!("#{}.{}", shortty(meth), name); let href = match link { AssocItemLink::Anchor => anchor, - AssocItemLink::GotoSource(did) => { - href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) + AssocItemLink::GotoSource(did, provided_methods) => { + // We're creating a link from an impl-item to the corresponding + // trait-item and need to map the anchored type accordingly. + let ty = if provided_methods.contains(name) { + ItemType::Method + } else { + ItemType::TyMethod + }; + + href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) } }; + // FIXME(#24111): remove when `const_fn` is stabilized let vis_constness = match get_unstable_features_setting() { UnstableFeatures::Allow => constness, _ => hir::Constness::NotConst @@ -2177,21 +2148,22 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, decl = Method(selfty, d), where_clause = WhereClause(g)) } - match meth.inner { + match item.inner { + clean::StrippedItem(..) => Ok(()), clean::TyMethodItem(ref m) => { - method(w, meth, m.unsafety, hir::Constness::NotConst, + method(w, item, m.unsafety, hir::Constness::NotConst, m.abi, &m.generics, &m.self_, &m.decl, link) } clean::MethodItem(ref m) => { - method(w, meth, m.unsafety, m.constness, + method(w, item, m.unsafety, m.constness, m.abi, &m.generics, &m.self_, &m.decl, link) } clean::AssociatedConstItem(ref ty, ref default) => { - assoc_const(w, meth, ty, default.as_ref()) + assoc_const(w, item, ty, default.as_ref(), link) } clean::AssociatedTypeItem(ref bounds, ref default) => { - assoc_type(w, meth, bounds, default) + assoc_type(w, item, bounds, default.as_ref(), link) } _ => panic!("render_assoc_item called on non-associated-item") } @@ -2199,39 +2171,39 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item, fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Struct) -> fmt::Result { - try!(write!(w, "
"));
-    try!(render_attributes(w, it));
-    try!(render_struct(w,
-                       it,
-                       Some(&s.generics),
-                       s.struct_type,
-                       &s.fields,
-                       "",
-                       true));
-    try!(write!(w, "
")); - try!(render_stability_since_raw(w, it.stable_since(), None)); - - try!(document(w, cx, it)); + write!(w, "
")?;
+    render_attributes(w, it)?;
+    render_struct(w,
+                  it,
+                  Some(&s.generics),
+                  s.struct_type,
+                  &s.fields,
+                  "",
+                  true)?;
+    write!(w, "
")?; + render_stability_since_raw(w, it.stable_since(), None)?; + + document(w, cx, it)?; let mut fields = s.fields.iter().filter(|f| { match f.inner { - clean::StructFieldItem(clean::HiddenStructField) => false, - clean::StructFieldItem(clean::TypedStructField(..)) => true, + clean::StructFieldItem(..) => true, _ => false, } }).peekable(); if let doctree::Plain = s.struct_type { if fields.peek().is_some() { - try!(write!(w, "

Fields

\n
{}extern crate {} as {};", - VisSpace(myitem.visibility), - src, - name)) + write!(w, "
{}extern crate {} as {};", + VisSpace(&myitem.visibility), + src, + name)? } None => { - try!(write!(w, "
{}extern crate {};", - VisSpace(myitem.visibility), name)) + write!(w, "
{}extern crate {};", + VisSpace(&myitem.visibility), name)? } } - try!(write!(w, "
{}{}
{}{}
{name} - {stab_docs} {docs} -
{name} + {stab_docs} {docs} +
")); + write!(w, "

Fields

\n
")?; for field in fields { - try!(write!(w, " - ")); + write!(w, " + ")?; } - try!(write!(w, "
\ - {name}", - stab = field.stability_class(), - name = field.name.as_ref().unwrap())); - try!(document(w, cx, field)); - try!(write!(w, "
\ + {name}", + shortty = ItemType::StructField, + stab = field.stability_class(), + name = field.name.as_ref().unwrap())?; + document(w, cx, field)?; + write!(w, "
")); + write!(w, "")?; } } render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) @@ -2239,104 +2211,96 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, e: &clean::Enum) -> fmt::Result { - try!(write!(w, "
"));
-    try!(render_attributes(w, it));
-    try!(write!(w, "{}enum {}{}{}",
-                  VisSpace(it.visibility),
-                  it.name.as_ref().unwrap(),
-                  e.generics,
-                  WhereClause(&e.generics)));
+    write!(w, "
")?;
+    render_attributes(w, it)?;
+    write!(w, "{}enum {}{}{}",
+           VisSpace(&it.visibility),
+           it.name.as_ref().unwrap(),
+           e.generics,
+           WhereClause(&e.generics))?;
     if e.variants.is_empty() && !e.variants_stripped {
-        try!(write!(w, " {{}}"));
+        write!(w, " {{}}")?;
     } else {
-        try!(write!(w, " {{\n"));
+        write!(w, " {{\n")?;
         for v in &e.variants {
-            try!(write!(w, "    "));
+            write!(w, "    ")?;
             let name = v.name.as_ref().unwrap();
             match v.inner {
                 clean::VariantItem(ref var) => {
                     match var.kind {
-                        clean::CLikeVariant => try!(write!(w, "{}", name)),
+                        clean::CLikeVariant => write!(w, "{}", name)?,
                         clean::TupleVariant(ref tys) => {
-                            try!(write!(w, "{}(", name));
+                            write!(w, "{}(", name)?;
                             for (i, ty) in tys.iter().enumerate() {
                                 if i > 0 {
-                                    try!(write!(w, ", "))
+                                    write!(w, ", ")?
                                 }
-                                try!(write!(w, "{}", *ty));
+                                write!(w, "{}", *ty)?;
                             }
-                            try!(write!(w, ")"));
+                            write!(w, ")")?;
                         }
                         clean::StructVariant(ref s) => {
-                            try!(render_struct(w,
-                                               v,
-                                               None,
-                                               s.struct_type,
-                                               &s.fields,
-                                               "    ",
-                                               false));
+                            render_struct(w,
+                                          v,
+                                          None,
+                                          s.struct_type,
+                                          &s.fields,
+                                          "    ",
+                                          false)?;
                         }
                     }
                 }
                 _ => unreachable!()
             }
-            try!(write!(w, ",\n"));
+            write!(w, ",\n")?;
         }
 
         if e.variants_stripped {
-            try!(write!(w, "    // some variants omitted\n"));
+            write!(w, "    // some variants omitted\n")?;
         }
-        try!(write!(w, "}}"));
+        write!(w, "}}")?;
     }
-    try!(write!(w, "
")); - try!(render_stability_since_raw(w, it.stable_since(), None)); + write!(w, "
")?; + render_stability_since_raw(w, it.stable_since(), None)?; - try!(document(w, cx, it)); + document(w, cx, it)?; if !e.variants.is_empty() { - try!(write!(w, "

Variants

\n")); + write!(w, "

Variants

\n
")?; for variant in &e.variants { - try!(write!(w, "")); + write!(w, "")?; } - try!(write!(w, "
{name}", - name = variant.name.as_ref().unwrap())); - try!(document(w, cx, variant)); - match variant.inner { - clean::VariantItem(ref var) => { - match var.kind { - clean::StructVariant(ref s) => { - let fields = s.fields.iter().filter(|f| { - match f.inner { - clean::StructFieldItem(ref t) => match *t { - clean::HiddenStructField => false, - clean::TypedStructField(..) => true, - }, - _ => false, - } - }); - try!(write!(w, "

Fields

\n - ")); - for field in fields { - try!(write!(w, "")); - } - try!(write!(w, "
\ - {f}", - v = variant.name.as_ref().unwrap(), - f = field.name.as_ref().unwrap())); - try!(document(w, cx, field)); - try!(write!(w, "
")); - } - _ => () + write!(w, "
{name}", + shortty = ItemType::Variant, + name = variant.name.as_ref().unwrap())?; + document(w, cx, variant)?; + + use clean::{Variant, StructVariant}; + if let clean::VariantItem( Variant { kind: StructVariant(ref s) } ) = variant.inner { + let fields = s.fields.iter().filter(|f| { + match f.inner { + clean::StructFieldItem(..) => true, + _ => false, } + }); + write!(w, "

Fields

\n + ")?; + for field in fields { + write!(w, "")?; } - _ => () + write!(w, "
\ + {f}", + shortty = ItemType::Variant, + v = variant.name.as_ref().unwrap(), + f = field.name.as_ref().unwrap())?; + document(w, cx, field)?; + write!(w, "
")?; } - try!(write!(w, "
")); - try!(render_stability_since(w, variant, it)); - try!(write!(w, "
")?; + render_stability_since(w, variant, it)?; + write!(w, "
")); - + write!(w, "")?; } - try!(render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)); + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?; Ok(()) } @@ -2344,10 +2308,10 @@ fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { for attr in &it.attrs { match *attr { clean::Word(ref s) if *s == "must_use" => { - try!(write!(w, "#[{}]\n", s)); + write!(w, "#[{}]\n", s)?; } clean::NameValue(ref k, ref v) if *k == "must_use" => { - try!(write!(w, "#[{} = \"{}\"]\n", k, v)); + write!(w, "#[{} = \"{}\"]\n", k, v)?; } _ => () } @@ -2361,68 +2325,60 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item, fields: &[clean::Item], tab: &str, structhead: bool) -> fmt::Result { - try!(write!(w, "{}{}{}", - VisSpace(it.visibility), - if structhead {"struct "} else {""}, - it.name.as_ref().unwrap())); - match g { - Some(g) => try!(write!(w, "{}{}", *g, WhereClause(g))), - None => {} + write!(w, "{}{}{}", + VisSpace(&it.visibility), + if structhead {"struct "} else {""}, + it.name.as_ref().unwrap())?; + if let Some(g) = g { + write!(w, "{}{}", *g, WhereClause(g))? } match ty { doctree::Plain => { - try!(write!(w, " {{\n{}", tab)); - let mut fields_stripped = false; + write!(w, " {{\n{}", tab)?; for field in fields { - match field.inner { - clean::StructFieldItem(clean::HiddenStructField) => { - fields_stripped = true; - } - clean::StructFieldItem(clean::TypedStructField(ref ty)) => { - try!(write!(w, " {}{}: {},\n{}", - VisSpace(field.visibility), - field.name.as_ref().unwrap(), - *ty, - tab)); - } - _ => unreachable!(), - }; + if let clean::StructFieldItem(ref ty) = field.inner { + write!(w, " {}{}: {},\n{}", + VisSpace(&field.visibility), + field.name.as_ref().unwrap(), + *ty, + tab)?; + } } - if fields_stripped { - try!(write!(w, " // some fields omitted\n{}", tab)); + if it.has_stripped_fields().unwrap() { + write!(w, " // some fields omitted\n{}", tab)?; } - try!(write!(w, "}}")); + write!(w, "}}")?; } doctree::Tuple | doctree::Newtype => { - try!(write!(w, "(")); + write!(w, "(")?; for (i, field) in fields.iter().enumerate() { if i > 0 { - try!(write!(w, ", ")); + write!(w, ", ")?; } match field.inner { - clean::StructFieldItem(clean::HiddenStructField) => { - try!(write!(w, "_")) + clean::StrippedItem(box clean::StructFieldItem(..)) => { + write!(w, "_")? } - clean::StructFieldItem(clean::TypedStructField(ref ty)) => { - try!(write!(w, "{}{}", VisSpace(field.visibility), *ty)) + clean::StructFieldItem(ref ty) => { + write!(w, "{}{}", VisSpace(&field.visibility), *ty)? } _ => unreachable!() } } - try!(write!(w, ");")); + write!(w, ");")?; } doctree::Unit => { - try!(write!(w, ";")); + write!(w, ";")?; } } Ok(()) } #[derive(Copy, Clone)] -enum AssocItemLink { +enum AssocItemLink<'a> { Anchor, - GotoSource(DefId), + GotoSource(DefId, &'a HashSet), } enum AssocItemRender<'a> { @@ -2446,53 +2402,48 @@ fn render_assoc_items(w: &mut fmt::Formatter, if !non_trait.is_empty() { let render_header = match what { AssocItemRender::All => { - try!(write!(w, "

Methods

")); + write!(w, "

Methods

")?; true } AssocItemRender::DerefFor { trait_, type_ } => { - try!(write!(w, "

Methods from \ - {}<Target={}>

", trait_, type_)); + write!(w, "

Methods from \ + {}<Target={}>

", trait_, type_)?; false } }; for i in &non_trait { - try!(render_impl(w, cx, i, AssocItemLink::Anchor, render_header, - containing_item.stable_since())); + render_impl(w, cx, i, AssocItemLink::Anchor, render_header, + containing_item.stable_since())?; } } if let AssocItemRender::DerefFor { .. } = what { - return Ok(()) + return Ok(()); } if !traits.is_empty() { let deref_impl = traits.iter().find(|t| { - match *t.impl_.trait_.as_ref().unwrap() { - clean::ResolvedPath { did, .. } => { - Some(did) == c.deref_trait_did - } - _ => false - } + t.impl_.trait_.def_id() == c.deref_trait_did }); if let Some(impl_) = deref_impl { - try!(render_deref_methods(w, cx, impl_, containing_item)); + render_deref_methods(w, cx, impl_, containing_item)?; } - try!(write!(w, "

Trait \ - Implementations

")); + write!(w, "

Trait \ + Implementations

")?; let (derived, manual): (Vec<_>, Vec<&Impl>) = traits.iter().partition(|i| { i.impl_.derived }); for i in &manual { let did = i.trait_did().unwrap(); - try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true, - containing_item.stable_since())); + let assoc_link = AssocItemLink::GotoSource(did, &i.impl_.provided_trait_methods); + render_impl(w, cx, i, assoc_link, true, containing_item.stable_since())?; } if !derived.is_empty() { - try!(write!(w, "

\ - Derived Implementations \ -

")); + write!(w, "

\ + Derived Implementations \ +

")?; for i in &derived { let did = i.trait_did().unwrap(); - try!(render_impl(w, cx, i, AssocItemLink::GotoSource(did), true, - containing_item.stable_since())); + let assoc_link = AssocItemLink::GotoSource(did, &i.impl_.provided_trait_methods); + render_impl(w, cx, i, assoc_link, true, containing_item.stable_since())?; } } } @@ -2509,17 +2460,16 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl, } }).next().expect("Expected associated type binding"); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target }; - match *target { - clean::ResolvedPath { did, .. } => render_assoc_items(w, cx, container_item, did, what), - _ => { - if let Some(prim) = target.primitive_type() { - if let Some(c) = cache().primitive_locations.get(&prim) { - let did = DefId { krate: *c, index: prim.to_def_index() }; - try!(render_assoc_items(w, cx, container_item, did, what)); - } + if let Some(did) = target.def_id() { + render_assoc_items(w, cx, container_item, did, what) + } else { + if let Some(prim) = target.primitive_type() { + if let Some(c) = cache().primitive_locations.get(&prim) { + let did = DefId { krate: *c, index: prim.to_def_index() }; + render_assoc_items(w, cx, container_item, did, what)?; } - Ok(()) } + Ok(()) } } @@ -2529,123 +2479,118 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl, fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink, render_header: bool, outer_version: Option<&str>) -> fmt::Result { if render_header { - try!(write!(w, "

{}", i.impl_)); + write!(w, "

{}", i.impl_)?; let since = i.stability.as_ref().map(|s| &s.since[..]); - try!(render_stability_since_raw(w, since, outer_version)); - try!(write!(w, "

")); + render_stability_since_raw(w, since, outer_version)?; + write!(w, "")?; if let Some(ref dox) = i.dox { - try!(write!(w, "
{}
", Markdown(dox))); + write!(w, "
{}
", Markdown(dox))?; } } fn doctraititem(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink, render_static: bool, outer_version: Option<&str>) -> fmt::Result { + let shortty = shortty(item); let name = item.name.as_ref().unwrap(); + + let is_static = match item.inner { + clean::MethodItem(ref method) => method.self_ == SelfTy::SelfStatic, + clean::TyMethodItem(ref method) => method.self_ == SelfTy::SelfStatic, + _ => false + }; + match item.inner { clean::MethodItem(..) | clean::TyMethodItem(..) => { // Only render when the method is not static or we allow static methods - if !is_static_method(item) || render_static { - let id = derive_id(format!("method.{}", name)); - try!(write!(w, "

", id, shortty(item))); - try!(render_stability_since_raw(w, item.stable_since(), outer_version)); - try!(write!(w, "")); - try!(render_assoc_item(w, item, link)); - try!(write!(w, "

\n")); + if !is_static || render_static { + let id = derive_id(format!("{}.{}", shortty, name)); + write!(w, "

", id, shortty)?; + render_stability_since_raw(w, item.stable_since(), outer_version)?; + write!(w, "")?; + render_assoc_item(w, item, link)?; + write!(w, "

\n")?; } } clean::TypedefItem(ref tydef, _) => { - let id = derive_id(format!("associatedtype.{}", name)); - try!(write!(w, "

", id, shortty(item))); - try!(write!(w, "type {} = {}", name, tydef.type_)); - try!(write!(w, "

\n")); + let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name)); + write!(w, "

", id, shortty)?; + assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link)?; + write!(w, "

\n")?; } clean::AssociatedConstItem(ref ty, ref default) => { - let id = derive_id(format!("associatedconstant.{}", name)); - try!(write!(w, "

", id, shortty(item))); - try!(assoc_const(w, item, ty, default.as_ref())); - try!(write!(w, "

\n")); + let id = derive_id(format!("{}.{}", shortty, name)); + write!(w, "

", id, shortty)?; + assoc_const(w, item, ty, default.as_ref(), link)?; + write!(w, "

\n")?; } clean::ConstantItem(ref c) => { - let id = derive_id(format!("associatedconstant.{}", name)); - try!(write!(w, "

", id, shortty(item))); - try!(assoc_const(w, item, &c.type_, Some(&c.expr))); - try!(write!(w, "

\n")); + let id = derive_id(format!("{}.{}", shortty, name)); + write!(w, "

", id, shortty)?; + assoc_const(w, item, &c.type_, Some(&c.expr), link)?; + write!(w, "

\n")?; } clean::AssociatedTypeItem(ref bounds, ref default) => { - let id = derive_id(format!("associatedtype.{}", name)); - try!(write!(w, "

", id, shortty(item))); - try!(assoc_type(w, item, bounds, default)); - try!(write!(w, "

\n")); + let id = derive_id(format!("{}.{}", shortty, name)); + write!(w, "

", id, shortty)?; + assoc_type(w, item, bounds, default.as_ref(), link)?; + write!(w, "

\n")?; } + clean::StrippedItem(..) => return Ok(()), _ => panic!("can't make docs for trait item with name {:?}", item.name) } - return if let AssocItemLink::Anchor = link { - if is_static_method(item) && !render_static { - Ok(()) - } else { + match link { + AssocItemLink::Anchor if !is_static || render_static => { document(w, cx, item) - } - } else { - Ok(()) - }; - - fn is_static_method(item: &clean::Item) -> bool { - match item.inner { - clean::MethodItem(ref method) => method.self_ == SelfTy::SelfStatic, - clean::TyMethodItem(ref method) => method.self_ == SelfTy::SelfStatic, - _ => false - } + }, + _ => Ok(()), } } - try!(write!(w, "
")); + write!(w, "
")?; for trait_item in &i.impl_.items { - try!(doctraititem(w, cx, trait_item, link, render_header, outer_version)); + doctraititem(w, cx, trait_item, link, render_header, outer_version)?; } fn render_default_items(w: &mut fmt::Formatter, cx: &Context, - did: DefId, t: &clean::Trait, - i: &clean::Impl, - render_static: bool, - outer_version: Option<&str>) -> fmt::Result { + i: &clean::Impl, + render_static: bool, + outer_version: Option<&str>) -> fmt::Result { for trait_item in &t.items { let n = trait_item.name.clone(); - match i.items.iter().find(|m| { m.name == n }) { - Some(..) => continue, - None => {} + if i.items.iter().find(|m| m.name == n).is_some() { + continue; } + let did = i.trait_.as_ref().unwrap().def_id().unwrap(); + let assoc_link = AssocItemLink::GotoSource(did, &i.provided_trait_methods); - try!(doctraititem(w, cx, trait_item, AssocItemLink::GotoSource(did), render_static, - outer_version)); + doctraititem(w, cx, trait_item, assoc_link, render_static, + outer_version)?; } Ok(()) } // If we've implemented a trait, then also emit documentation for all - // default methods which weren't overridden in the implementation block. - // FIXME: this also needs to be done for associated types, whenever defaults - // for them work. - if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ { + // default items which weren't overridden in the implementation block. + if let Some(did) = i.trait_did() { if let Some(t) = cache().traits.get(&did) { - try!(render_default_items(w, cx, did, t, &i.impl_, render_header, outer_version)); - + render_default_items(w, cx, t, &i.impl_, render_header, outer_version)?; } } - try!(write!(w, "
")); + write!(w, "
")?; Ok(()) } fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Typedef) -> fmt::Result { - try!(write!(w, "
type {}{}{where_clause} = {type_};
", - it.name.as_ref().unwrap(), - t.generics, - where_clause = WhereClause(&t.generics), - type_ = t.type_)); + write!(w, "
type {}{}{where_clause} = {type_};
", + it.name.as_ref().unwrap(), + t.generics, + where_clause = WhereClause(&t.generics), + type_ = t.type_)?; document(w, cx, it) } @@ -2664,34 +2609,34 @@ impl<'a> fmt::Display for Sidebar<'a> { // as much HTML as possible in order to allow non-JS-enabled browsers // to navigate the documentation (though slightly inefficiently). - try!(write!(fmt, "

")); + write!(fmt, "

")?; for (i, name) in cx.current.iter().take(parentlen).enumerate() { if i > 0 { - try!(write!(fmt, "::")); + write!(fmt, "::")?; } - try!(write!(fmt, "{}", - &cx.root_path[..(cx.current.len() - i - 1) * 3], - *name)); + write!(fmt, "{}", + &cx.root_path[..(cx.current.len() - i - 1) * 3], + *name)?; } - try!(write!(fmt, "

")); + write!(fmt, "

")?; // sidebar refers to the enclosing module, not this module - let relpath = if shortty(it) == ItemType::Module { "../" } else { "" }; - try!(write!(fmt, - "", - name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = shortty(it).to_static_str(), - path = relpath)); + let relpath = if it.is_mod() { "../" } else { "" }; + write!(fmt, + "", + 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)); + write!(fmt, "", + path = relpath)?; } Ok(()) @@ -2708,38 +2653,36 @@ impl<'a> fmt::Display for Source<'a> { cols += 1; tmp /= 10; } - try!(write!(fmt, "
"));
+        write!(fmt, "
")?;
         for i in 1..lines + 1 {
-            try!(write!(fmt, "{0:1$}\n", i, cols));
+            write!(fmt, "{0:1$}\n", i, cols)?;
         }
-        try!(write!(fmt, "
")); - try!(write!(fmt, "{}", highlight::highlight(s, None, None))); + write!(fmt, "
")?; + write!(fmt, "{}", highlight::render_with_highlighting(s, None, None))?; Ok(()) } } fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Macro) -> fmt::Result { - try!(w.write_str(&highlight::highlight(&t.source, - Some("macro"), - None))); - try!(render_stability_since_raw(w, it.stable_since(), None)); + w.write_str(&highlight::render_with_highlighting(&t.source, + Some("macro"), + None))?; + render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it) } fn item_primitive(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, _p: &clean::PrimitiveType) -> fmt::Result { - try!(document(w, cx, it)); + document(w, cx, it)?; render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn get_basic_keywords() -> &'static str { - "rust, rustlang, rust-lang" -} +const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; fn make_item_keywords(it: &clean::Item) -> String { - format!("{}, {}", get_basic_keywords(), it.name.as_ref().unwrap()) + format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) } fn get_index_search_type(item: &clean::Item, @@ -2808,6 +2751,6 @@ fn test_unique_id() { assert_eq!(&actual[..], expected); }; test(); - reset_ids(); + reset_ids(true); test(); } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index f3efbcb1db..1d1e78926f 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -740,7 +740,9 @@ $(".search-input").on("keyup input",function() { clearTimeout(searchTimeout); if ($(this).val().length === 0) { - window.history.replaceState("", "std - Rust", "?search="); + if (browserSupportsHistoryApi()) { + history.replaceState("", "std - Rust", "?search="); + } $('#main.content').removeClass('hidden'); $('#search.content').addClass('hidden'); } else { @@ -996,7 +998,7 @@ var prev_id = 0; function set_fragment(name) { - if (history.replaceState) { + if (browserSupportsHistoryApi()) { history.replaceState(null, null, '#' + name); $(window).trigger('hashchange'); } else { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 1cadc4e476..c07871a402 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -616,15 +616,19 @@ a.test-arrow { } .sidebar .location { - float: left; + float: right; margin: 0px; - padding: 5px; - width: 60%; + padding: 3px 10px 1px 10px; + min-height: 39px; background: inherit; text-align: left; font-size: 24px; } + .sidebar .location:empty { + padding: 0; + } + .sidebar img { width: 35px; margin-top: 5px; diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 53be8b5bc0..305e6258ba 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -183,15 +183,15 @@ impl fmt::Debug for Toc { impl fmt::Display for Toc { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(write!(fmt, "